diff --git a/CMakeLists.txt b/CMakeLists.txt index 2e14f7fe10..4d76434190 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1474,6 +1474,7 @@ set (MAC_SRC set (MAC_NR_SRC ${NR_PHY_INTERFACE_DIR}/NR_IF_Module.c + ${NR_PHY_INTERFACE_DIR}/nr_sched_response.c ${NR_GNB_MAC_DIR}/main.c ${NR_GNB_MAC_DIR}/config.c ${NR_GNB_MAC_DIR}/gNB_scheduler.c @@ -1895,6 +1896,7 @@ set(libnrnas_emm_msg_OBJS ${NAS_SRC}COMMON/EMM/MSG/FGSUplinkNasTransport.c ${NAS_SRC}COMMON/ESM/MSG/PduSessionEstablishRequest.c ${NAS_SRC}COMMON/ESM/MSG/PduSessionEstablishmentAccept.c + ${NAS_SRC}COMMON/EMM/MSG/FGSDeregistrationRequestUEOriginating.c ) set(libnrnas_ies_OBJS @@ -2015,7 +2017,9 @@ add_boolean_option(ENABLE_NRQTSCOPE OFF "Build the Qt-Scope" OFF) if (ENABLE_NRQTSCOPE) find_package(Qt5 REQUIRED COMPONENTS Widgets Charts) message ("Qt5 Widgets and Charts found for nrqtscope") - set(QTSCOPE_SOURCE_NR ${OPENAIR1_DIR}/PHY/TOOLS/nr_phy_qt_scope.cpp) + set(QTSCOPE_SOURCE_NR + ${OPENAIR1_DIR}/PHY/TOOLS/nr_phy_qt_scope.cpp + ${OPENAIR1_DIR}/PHY/TOOLS/phy_scope_interface.c) # Creates rules for calling the Meta-Object Compiler (moc) on the given source files qt5_wrap_cpp(QTSCOPE_SOURCE_NR ${OPENAIR1_DIR}/PHY/TOOLS/nr_phy_qt_scope.h) add_library(nrqtscope MODULE ${QTSCOPE_SOURCE_NR}) diff --git a/README.md b/README.md index c82eff8f36..70614fd72d 100644 --- a/README.md +++ b/README.md @@ -4,8 +4,12 @@

License - Supported OS - Supported OS + Supported OS Ubuntu 18 + Supported OS Ubuntu 20 + Supported OS Ubuntu 22 + Supported OS RHEL8 + Supported OS RELH9 + Supported OS Fedora 37

@@ -13,10 +17,10 @@

- Docker Pulls - Docker Pulls - Docker Pulls - Docker Pulls + Docker Pulls + Docker Pulls + Docker Pulls + Docker Pulls

# OpenAirInterface License # @@ -32,12 +36,12 @@ Please see [NOTICE](NOTICE.md) file for third party software that is included in # Where to Start # + * [General overview of documentation](./doc/README.md) * [The implemented features](./doc/FEATURE_SET.md) * [How to build](./doc/BUILD.md) * [How to run the modems](./doc/RUNMODEM.md) -More information and documentation can be found in the [doc folder](./doc). -Unfortunately, not all information is available there, and information for +Not all information is available in a central place, and information for specific sub-systems might be available in the corresponding sub-directories. To find all READMEs, this command might be handy: @@ -51,52 +55,20 @@ The OpenAirInterface (OAI) software is composed of the following parts: ``` openairinterface5g +├── charts ├── ci-scripts : Meta-scripts used by the OSA CI process. Contains also configuration files used day-to-day by CI. +├── CMakeLists.txt : Top-level CMakeLists.txt for building ├── cmake_targets : Build utilities to compile (simulation, emulation and real-time platforms), and generated build files. -├── common : Some common OAI utilities, other tools can be found at openair2/UTILS. -├── doc : Contains an up-to-date feature set list and starting tutorials. -├── executables : Top-level executable source files. -├── LICENSE : License file. +├── common : Some common OAI utilities, some other tools can be found at openair2/UTILS. +├── doc : Documentation +├── docker : Dockerfiles to build for Ubuntu and RHEL +├── executables : Top-level executable source files (gNB, eNB, ...) ├── maketags : Script to generate emacs tags. -├── nfapi : Contains the NFAPI code. A local Readme file provides more details. +├── nfapi : (n)FAPI code for MAC-PHY interface ├── openair1 : 3GPP LTE Rel-10/12 PHY layer / 3GPP NR Rel-15 layer. A local Readme file provides more details. -│   ├── PHY -│   ├── SCHED -│   ├── SCHED_NBIOT -│   ├── SCHED_NR -│   ├── SCHED_NR_UE -│   ├── SCHED_UE -│   └── SIMULATION : PHY RF simulation. ├── openair2 : 3GPP LTE Rel-10 RLC/MAC/PDCP/RRC/X2AP + LTE Rel-14 M2AP implementation. Also 3GPP NR Rel-15 RLC/MAC/PDCP/RRC/X2AP. -│   ├── COMMON -│   ├── DOCS -│   ├── ENB_APP -│   ├── F1AP -│   ├── GNB_APP -│   ├── LAYER2/RLC/ : with the following subdirectories: UM_v9.3.0, TM_v9.3.0, and AM_v9.3.0. -│   ├── LAYER2/PDCP/PDCP_v10.1.0 -│   ├── M2AP -│   ├── MCE_APP -│   ├── NETWORK_DRIVER -│   ├── NR_PHY_INTERFACE -│   ├── NR_UE_PHY_INTERFACE -│   ├── PHY_INTERFACE -│   ├── RRC -│   ├── UTIL -│   └── X2AP ├── openair3 : 3GPP LTE Rel10 for S1AP, NAS GTPV1-U for both ENB and UE. -│   ├── COMMON -│   ├── DOCS -│   ├── GTPV1-U -│   ├── M3AP -│   ├── MME_APP -│   ├── NAS -│   ├── S1AP -│   ├── SCTP -│   ├── SECU -│   ├── TEST -│   ├── UDP -│   └── UTILS -├── radio : drivers for various radios such as USRP, AW2S, RFsim, ... -└── targets : Top-level wrappers for unitary simulation for PHY channels, system-level emulation (eNB-UE with and without S1), and realtime eNB and UE and RRH GW. +├── openshift : OpenShift helm charts for some deployment options of OAI +├── radio : Drivers for various radios such as USRP, AW2S, RFsim, ... +└── targets : Some configuration files; only historical relevance, and might be deleted in the future ``` diff --git a/ci-scripts/Jenkinsfile-GitLab-Container b/ci-scripts/Jenkinsfile-GitLab-Container index 31ea662e3c..0a033cf760 100644 --- a/ci-scripts/Jenkinsfile-GitLab-Container +++ b/ci-scripts/Jenkinsfile-GitLab-Container @@ -385,6 +385,27 @@ pipeline { } } } + stage ("LTE-TDD-2x2-Container") { + when { expression {do4Gtest} } + steps { + script { + triggerSlaveJob ('RAN-LTE-TDD-2x2-Container', 'LTE-TDD-2x2-Container') + } + } + post { + always { + script { + finalizeSlaveJob('RAN-LTE-TDD-2x2-Container') + } + } + failure { + script { + currentBuild.result = 'FAILURE' + } + } + } + } + //avra is offline, re-enable once it is available //stage ("T1-Offload-Test") { // when { expression {do5Gtest} } diff --git a/ci-scripts/cls_containerize.py b/ci-scripts/cls_containerize.py index 9a00ec3dfe..492a48805a 100644 --- a/ci-scripts/cls_containerize.py +++ b/ci-scripts/cls_containerize.py @@ -844,7 +844,7 @@ class Containerize(): CreateWorkspace(mySSH, lSourcePath, self.ranRepository, self.ranCommitID, self.ranTargetBranch, self.ranAllowMerge) mySSH.command('cd ' + lSourcePath + '/' + self.yamlPath[self.eNB_instance], '\$', 5) - mySSH.command('cp docker-compose.yml ci-docker-compose.yml', '\$', 5) + mySSH.command('cp docker-compose.y*ml ci-docker-compose.yml', '\$', 5) imagesList = ['oai-enb', 'oai-gnb', 'oai-nr-cuup'] for image in imagesList: imageToUse = self.ImageTagToUse(image) @@ -1559,17 +1559,6 @@ class Containerize(): mySSH.close() if svrName == 'nepes': mySSH.open(ipAddr, userName, password) - # Check if route to porcepix epc exists: not necessary, is on same host - #mySSH.command('ip route | grep --colour=never "192.168.61.192/26"', '\$', 10) - #result = re.search('172.21.16.136', mySSH.getBefore()) - #if result is None: - # mySSH.command('echo ' + password + ' | sudo -S ip route add 192.168.61.192/26 via 172.21.16.136 dev enp0s31f6', '\$', 10) - # Check if X2 route to obelix enb exists: not necessary, gnb is on ofqot - #mySSH.command('ip route | grep --colour=never "192.168.68.128/26"', '\$', 10) - #result = re.search('172.21.16.128', mySSH.getBefore()) - #if result is None: - # mySSH.command('echo ' + password + ' | sudo -S ip route add 192.168.68.128/26 via 172.21.16.128 dev enp0s31f6', '\$', 10) - # Check if forwarding is enabled # Check if route to ofqot gnb exists mySSH.command('ip route | grep --colour=never "192.168.68.192/26"', '\$', 10) result = re.search('172.21.16.109', mySSH.getBefore()) diff --git a/ci-scripts/cls_oaicitest.py b/ci-scripts/cls_oaicitest.py index 9fa1dcbb71..2bd8ba4263 100644 --- a/ci-scripts/cls_oaicitest.py +++ b/ci-scripts/cls_oaicitest.py @@ -1227,7 +1227,7 @@ class OaiCiTest(): raise Exception("could not corver prod-trf-gen IP address") cn_target_ip = result.group('trf_ip_addr') SSH.close() - cn_iperf_prefix = "docker exec -it prod-trf-gen" # -w /iperf-2.0.13 necessary? + cn_iperf_prefix = "docker exec prod-trf-gen" # -w /iperf-2.0.13 necessary? else: # ltebox, sabox cn_target_ip = "192.172.0.1" cn_iperf_prefix = "" diff --git a/ci-scripts/conf_files/enb.band38.lte_2x2.100PRB.usrpn310.conf b/ci-scripts/conf_files/enb.band38.lte_2x2.100PRB.usrpn310.conf index f1d30c4b42..2042768933 100644 --- a/ci-scripts/conf_files/enb.band38.lte_2x2.100PRB.usrpn310.conf +++ b/ci-scripts/conf_files/enb.band38.lte_2x2.100PRB.usrpn310.conf @@ -172,7 +172,7 @@ eNBs = ////////// MME parameters: - mme_ip_address = ( { ipv4 = "CI_MME_IP_ADDR"; + mme_ip_address = ( { ipv4 = "192.168.61.195"; ipv6 = "192:168:30::17"; active = "yes"; preference = "ipv4"; @@ -191,11 +191,11 @@ eNBs = NETWORK_INTERFACES : { ENB_INTERFACE_NAME_FOR_S1_MME = "eno1"; - ENB_IPV4_ADDRESS_FOR_S1_MME = "CI_ENB_IP_ADDR"; + ENB_IPV4_ADDRESS_FOR_S1_MME = "172.21.16.128"; ENB_INTERFACE_NAME_FOR_S1U = "eno1"; - ENB_IPV4_ADDRESS_FOR_S1U = "CI_ENB_IP_ADDR"; + ENB_IPV4_ADDRESS_FOR_S1U = "172.21.16.128"; ENB_PORT_FOR_S1U = 2152; # Spec 2152 - ENB_IPV4_ADDRESS_FOR_X2C = "CI_ENB_IP_ADDR"; + ENB_IPV4_ADDRESS_FOR_X2C = "172.21.16.128"; ENB_PORT_FOR_X2C = 36422; # Spec 36422 }; } diff --git a/ci-scripts/conf_files/enb.band38.lte_2x2_tm2.100PRB.usrpn310.conf b/ci-scripts/conf_files/enb.band38.lte_2x2_tm2.100PRB.usrpn310.conf index c3d9b7c893..e50c1acfe8 100644 --- a/ci-scripts/conf_files/enb.band38.lte_2x2_tm2.100PRB.usrpn310.conf +++ b/ci-scripts/conf_files/enb.band38.lte_2x2_tm2.100PRB.usrpn310.conf @@ -172,7 +172,7 @@ eNBs = ////////// MME parameters: - mme_ip_address = ( { ipv4 = "CI_MME_IP_ADDR"; + mme_ip_address = ( { ipv4 = "192.168.61.195"; ipv6 = "192:168:30::17"; active = "yes"; preference = "ipv4"; @@ -191,11 +191,11 @@ eNBs = NETWORK_INTERFACES : { ENB_INTERFACE_NAME_FOR_S1_MME = "eno1"; - ENB_IPV4_ADDRESS_FOR_S1_MME = "CI_ENB_IP_ADDR"; + ENB_IPV4_ADDRESS_FOR_S1_MME = "172.21.16.128"; ENB_INTERFACE_NAME_FOR_S1U = "eno1"; - ENB_IPV4_ADDRESS_FOR_S1U = "CI_ENB_IP_ADDR"; + ENB_IPV4_ADDRESS_FOR_S1U = "172.21.16.128"; ENB_PORT_FOR_S1U = 2152; # Spec 2152 - ENB_IPV4_ADDRESS_FOR_X2C = "CI_ENB_IP_ADDR"; + ENB_IPV4_ADDRESS_FOR_X2C = "172.21.16.128"; ENB_PORT_FOR_X2C = 36422; # Spec 36422 }; } diff --git a/ci-scripts/datalog_rt_stats.1x1.60.yaml b/ci-scripts/datalog_rt_stats.1x1.60.yaml index bf22c6f432..c65c4614d2 100644 --- a/ci-scripts/datalog_rt_stats.1x1.60.yaml +++ b/ci-scripts/datalog_rt_stats.1x1.60.yaml @@ -14,8 +14,8 @@ Ref : L1 Tx processing : 210.0 DLSCH encoding : 137.0 L1 Rx processing : 345.0 - PUSCH inner-receiver : 184.0 - PUSCH decoding : 276.0 + PUSCH inner-receiver : 210.0 + PUSCH decoding : 210.0 Schedule Response : 48.0 DL & UL scheduling timing : 13.0 UL Indication : 60.0 diff --git a/ci-scripts/datalog_rt_stats.60.2x2.yaml b/ci-scripts/datalog_rt_stats.60.2x2.yaml index b0d861d758..50444cc6b0 100644 --- a/ci-scripts/datalog_rt_stats.60.2x2.yaml +++ b/ci-scripts/datalog_rt_stats.60.2x2.yaml @@ -14,10 +14,10 @@ Ref : L1 Tx processing : 400.0 DLSCH encoding : 177.0 L1 Rx processing : 345.0 - PUSCH inner-receiver : 184.0 - PUSCH decoding : 276.0 + PUSCH inner-receiver : 210.0 + PUSCH decoding : 210.0 Schedule Response : 111.0 - DL & UL scheduling timing : 37.0 + DL & UL scheduling timing : 20.0 UL Indication : 127.0 Threshold : feprx : 1.25 diff --git a/ci-scripts/datalog_rt_stats.default.yaml b/ci-scripts/datalog_rt_stats.default.yaml index 971e72944a..8f7f0f015c 100644 --- a/ci-scripts/datalog_rt_stats.default.yaml +++ b/ci-scripts/datalog_rt_stats.default.yaml @@ -14,11 +14,11 @@ Ref : L1 Tx processing : 170.0 DLSCH encoding : 118.0 L1 Rx processing : 305.0 - PUSCH inner-receiver : 117.0 - PUSCH decoding : 303.0 - Schedule Response : 25.0 + PUSCH inner-receiver : 150.0 + PUSCH decoding : 210.0 + Schedule Response : 20.0 DL & UL scheduling timing : 10.0 - UL Indication : 34.0 + UL Indication : 30.0 Threshold : feprx : 1.25 feptx_prec : 1.25 diff --git a/ci-scripts/xml_files/container_lte_b200_tdd_05Mhz_tm1.xml b/ci-scripts/xml_files/container_lte_b200_tdd_05Mhz_tm1.xml index 3f12ed8330..eb11412ef5 100644 --- a/ci-scripts/xml_files/container_lte_b200_tdd_05Mhz_tm1.xml +++ b/ci-scripts/xml_files/container_lte_b200_tdd_05Mhz_tm1.xml @@ -27,6 +27,7 @@ Replaces xml_files/enb_usrp210_band40_test_05mhz_tm1.xml Test-TDD-05MHz-TM1 tasks +300000 100000 111110 040101 @@ -57,6 +58,13 @@ Replaces xml_files/enb_usrp210_band40_test_05mhz_tm1.xml sudo cpupower idle-set -E + + Custom_Command + Reset USRP + starsky + sudo -S b2xx_fx3_utils --reset-device + + Deploy_Object Deploy eNB (TDD/Band40/5MHz/B200) in a container diff --git a/ci-scripts/xml_files/container_lte_n3xx_tdd_2x2_tm1.xml b/ci-scripts/xml_files/container_lte_n3xx_tdd_2x2_tm1.xml new file mode 100644 index 0000000000..480825bede --- /dev/null +++ b/ci-scripts/xml_files/container_lte_n3xx_tdd_2x2_tm1.xml @@ -0,0 +1,160 @@ + + + + TEST-LTE-2x2-N3XX-TM1 + 2.6 Ghz TDD LTE 2x2 TM1 + tasks + 1 + + +111111 +100000 +010000 +030101 +010001 +000001 +050000 +050001 +070000 +070001 +010010 +010002 +030201 + + + + + + Pull_Local_Registry + Pull Images from Local Registry + 0 + oai-enb + + + + Custom_Command + Disable Sleep States + obelix + sudo cpupower idle-set -D 0 + + + + Custom_Command + Enable Sleep States + obelix + sudo cpupower idle-set -E + + + + Deploy_Object + Deploy eNB (TDD/Band38/2.6Ghz/N3XX) in a container + ci-scripts/yaml_files/lte_n3xx_tdd_2x2_tm1 + 0 + 0 + + + + IdleSleep + Sleep + 5 + + + + Initialize_UE + Initialize Quectel + nrmodule2_quectel + + + + Terminate_UE + Terminate Quectel + nrmodule2_quectel + + + + Attach_UE + Attach UE + nrmodule2_quectel + + + + Ping + Ping: 20 pings + nrmodule2_quectel + -c 20 + 1 + 60 + + + + Ping + Ping: 100 pings, size 1024 + nrmodule2_quectel + -c 100 -s 1024 -i 0,2 + 1 + 60 + + + + Iperf + iperf (DL/26Mbps/UDP)(60 sec)(single-ue profile) + -u -b 26M -t 60 + DL + nrmodule2_quectel + 5 + 95 + single-ue + + + + Iperf + iperf (UL/7Mbps/UDP)(60 sec)(single-ue profile) + -u -b 7M -t 60 + UL + nrmodule2_quectel + 5 + 95 + single-ue + + + + Detach_UE + Detach UE + nrmodule2_quectel + + + + Undeploy_Object + Undeploy gNB + ci-scripts/yaml_files/lte_n3xx_tdd_2x2_tm1 + 0 + 0 + + + + + diff --git a/ci-scripts/xml_files/container_lte_n3xx_tdd_2x2_tm2.xml b/ci-scripts/xml_files/container_lte_n3xx_tdd_2x2_tm2.xml new file mode 100644 index 0000000000..b3dc7efab7 --- /dev/null +++ b/ci-scripts/xml_files/container_lte_n3xx_tdd_2x2_tm2.xml @@ -0,0 +1,160 @@ + + + + TEST-LTE-2x2-N3XXi-TM2 + 2.6 Ghz TDD LTE 2x2 TM2 + tasks + 1 + + +111111 +100000 +010000 +030101 +010001 +000001 +050000 +050001 +070000 +070001 +010010 +010002 +030201 + + + + + + Pull_Local_Registry + Pull Images from Local Registry + 0 + oai-enb + + + + Custom_Command + Disable Sleep States + obelix + sudo cpupower idle-set -D 0 + + + + Custom_Command + Enable Sleep States + obelix + sudo cpupower idle-set -E + + + + Deploy_Object + Deploy eNB (TDD/Band38/2.6Ghz/N3XX) in a container + ci-scripts/yaml_files/lte_n3xx_tdd_2x2_tm2 + 0 + 0 + + + + IdleSleep + Sleep + 5 + + + + Initialize_UE + Initialize Quectel + nrmodule2_quectel + + + + Terminate_UE + Terminate Quectel + nrmodule2_quectel + + + + Attach_UE + Attach UE + nrmodule2_quectel + + + + Ping + Ping: 20 pings + nrmodule2_quectel + -c 20 + 1 + 60 + + + + Ping + Ping: 100 pings, size 1024 + nrmodule2_quectel + -c 100 -s 1024 -i 0,2 + 1 + 60 + + + + Iperf + iperf (DL/26Mbps/UDP)(60 sec)(single-ue profile) + -u -b 1M -t 60 + DL + nrmodule2_quectel + 5 + 95 + single-ue + + + + Iperf + iperf (UL/7Mbps/UDP)(60 sec)(single-ue profile) + -u -b 7M -t 60 + UL + nrmodule2_quectel + 5 + 95 + single-ue + + + + Detach_UE + Detach UE + nrmodule2_quectel + + + + Undeploy_Object + Undeploy gNB + ci-scripts/yaml_files/lte_n3xx_tdd_2x2_tm2 + 0 + 0 + + + + + diff --git a/ci-scripts/xml_files/lte_2x2_tm1_quectel.xml b/ci-scripts/xml_files/lte_2x2_tm1_quectel.xml deleted file mode 100644 index 4270510842..0000000000 --- a/ci-scripts/xml_files/lte_2x2_tm1_quectel.xml +++ /dev/null @@ -1,164 +0,0 @@ - - - TEST-LTE-TM1-Tab1 - LTE 2x2 TM1 Ping DL UL with QUECTEL - tasks - 1 - - 100000 - 010000 - 030000 - 010001 - 050000 - 050001 - 070000 - 070001 - 010011 - 010002 - 080000 - 200000 - - - - - Custom_Command - Disable Sleep States - obelix - sudo cpupower idle-set -D 0 - - - Custom_Command - Enable Sleep States - obelix - sudo cpupower idle-set -E - - - - Initialize_UE - Initialize Quectel - nrmodule2_quectel - - - Terminate_UE - Terminate Quectel - nrmodule2_quectel - - - Attach_UE - Attach Quectel - nrmodule2_quectel - - - Detach_UE - Detach Quectel - nrmodule2_quectel - - - - Initialize_eNB - Initialize eNB - -O ci-scripts/conf_files/enb.band38.lte_2x2.100PRB.usrpn310.conf --usrp-tx-thread-config 1 --thread-pool 0,2,4,6 --log_config.global_log_options level,nocolor,time - 0 - 0 - lte - yes - yes - 172.21.19.13 - - - - - IdleSleep - Sleep - 5 - - - - IdleSleep - Sleep - 20 - - - - - Ping - Ping: 20 pings - nrmodule2_quectel - -c 20 - 1 - 60 - - - Ping - Ping: 100 pings, size 1024 - nrmodule2_quectel - -c 100 -s 1024 -i 0,2 - 1 - 60 - - - - - Iperf - iperf (DL/26Mbps/UDP)(60 sec)(single-ue profile) - -u -b 26M -t 60 - DL - nrmodule2_quectel - 5 - 95 - single-ue - - - - Iperf - iperf (UL/7Mbps/UDP)(60 sec)(single-ue profile) - -u -b 7M -t 60 - UL - nrmodule2_quectel - 5 - 95 - single-ue - - - - - - - Terminate_eNB - Terminate eNB - 0 - 0 - lte - - - - Terminate_eNB - Terminate gNB - 1 - 1 - nr - - - - diff --git a/ci-scripts/xml_files/lte_2x2_tm2_quectel.xml b/ci-scripts/xml_files/lte_2x2_tm2_quectel.xml deleted file mode 100644 index d02749700d..0000000000 --- a/ci-scripts/xml_files/lte_2x2_tm2_quectel.xml +++ /dev/null @@ -1,164 +0,0 @@ - - - TEST-LTE-TM2-Tab2 - LTE 2x2 TM2 Ping DL UL with QUECTEL - tasks - 1 - - 100000 - 010000 - 030001 - 010001 - 050002 - 050003 - 070002 - 070003 - 010011 - 010002 - 080000 - 200000 - - - - - Custom_Command - Disable Sleep States - obelix - sudo cpupower idle-set -D 0 - - - Custom_Command - Enable Sleep States - obelix - sudo cpupower idle-set -E - - - - Initialize_UE - Initialize Quectel - nrmodule2_quectel - - - Terminate_UE - Terminate Quectel - nrmodule2_quectel - - - Attach_UE - Attach Quectel - nrmodule2_quectel - - - Detach_UE - Detach Quectel - nrmodule2_quectel - - - - Initialize_eNB - Initialize eNB - -O ci-scripts/conf_files/enb.band38.lte_2x2_tm2.100PRB.usrpn310.conf --usrp-tx-thread-config 1 --thread-pool 0,2,4,6 --log_config.global_log_options level,nocolor,time - 0 - 0 - lte - yes - yes - 172.21.19.13 - - - - - IdleSleep - Sleep - 5 - - - - IdleSleep - Sleep - 20 - - - - - Ping - Ping: 20 pings - nrmodule2_quectel - -c 20 - 1 - 60 - - - Ping - Ping: 100 pings, size 1024 - nrmodule2_quectel - -c 100 -s 1024 -i 0,2 - 1 - 60 - - - - - Iperf - iperf (DL/1Mbps/UDP)(60 sec)(single-ue profile) - -u -b 1M -t 60 - DL - nrmodule2_quectel - 5 - 95 - single-ue - - - - Iperf - iperf (UL/7Mbps/UDP)(60 sec)(single-ue profile) - -u -b 7M -t 60 - UL - nrmodule2_quectel - 5 - 95 - single-ue - - - - - - - Terminate_eNB - Terminate eNB - 0 - 0 - lte - - - - Terminate_eNB - Terminate gNB - 1 - 1 - nr - - - - diff --git a/ci-scripts/yaml_files/5g_f1_rfsimulator/docker-compose.yaml b/ci-scripts/yaml_files/5g_f1_rfsimulator/docker-compose.yaml index 4a2195f37d..b940794425 100644 --- a/ci-scripts/yaml_files/5g_f1_rfsimulator/docker-compose.yaml +++ b/ci-scripts/yaml_files/5g_f1_rfsimulator/docker-compose.yaml @@ -219,7 +219,7 @@ services: F1_DU_IP_ADDRESS: 192.168.71.142 F1_CU_D_PORT: 2153 F1_DU_D_PORT: 2153 - USE_ADDITIONAL_OPTIONS: --sa --rfsim --rfsimulator.wait_timeout 20 --log_config.global_log_options level,nocolor,time + USE_ADDITIONAL_OPTIONS: --sa --rfsim --log_config.global_log_options level,nocolor,time depends_on: - oai-cu networks: diff --git a/ci-scripts/yaml_files/5g_fdd_rfsimulator/docker-compose.yaml b/ci-scripts/yaml_files/5g_fdd_rfsimulator/docker-compose.yaml index 38a21e4dd0..404860d390 100644 --- a/ci-scripts/yaml_files/5g_fdd_rfsimulator/docker-compose.yaml +++ b/ci-scripts/yaml_files/5g_fdd_rfsimulator/docker-compose.yaml @@ -180,7 +180,7 @@ services: GNB_NGA_IP_ADDRESS: 192.168.71.140 GNB_NGU_IF_NAME: eth0 GNB_NGU_IP_ADDRESS: 192.168.71.140 - USE_ADDITIONAL_OPTIONS: --sa -E --rfsim --rfsimulator.wait_timeout 20 --log_config.global_log_options level,nocolor,time + USE_ADDITIONAL_OPTIONS: --sa -E --rfsim --log_config.global_log_options level,nocolor,time depends_on: - oai-ext-dn networks: diff --git a/ci-scripts/yaml_files/5g_rfsimulator/docker-compose.yaml b/ci-scripts/yaml_files/5g_rfsimulator/docker-compose.yaml index 98bf516ae0..f1bf2e0b54 100644 --- a/ci-scripts/yaml_files/5g_rfsimulator/docker-compose.yaml +++ b/ci-scripts/yaml_files/5g_rfsimulator/docker-compose.yaml @@ -181,7 +181,7 @@ services: GNB_NGU_IF_NAME: eth0 GNB_NGU_IP_ADDRESS: 192.168.71.140 SDR_ADDRS: serial=XXXXXXX - USE_ADDITIONAL_OPTIONS: --sa -E --rfsim --rfsimulator.wait_timeout 20 --log_config.global_log_options level,nocolor,time + USE_ADDITIONAL_OPTIONS: --sa -E --rfsim --log_config.global_log_options level,nocolor,time depends_on: - oai-ext-dn networks: diff --git a/ci-scripts/yaml_files/5g_rfsimulator_24prb/docker-compose.yaml b/ci-scripts/yaml_files/5g_rfsimulator_24prb/docker-compose.yaml index 0009277e01..32f769ec3a 100644 --- a/ci-scripts/yaml_files/5g_rfsimulator_24prb/docker-compose.yaml +++ b/ci-scripts/yaml_files/5g_rfsimulator_24prb/docker-compose.yaml @@ -169,7 +169,7 @@ services: environment: RFSIMULATOR: server USE_VOLUMED_CONF: 'yes' - USE_ADDITIONAL_OPTIONS: --sa --rfsim --rfsimulator.wait_timeout 20 --log_config.global_log_options level,nocolor,time + USE_ADDITIONAL_OPTIONS: --sa --rfsim --log_config.global_log_options level,nocolor,time depends_on: - oai-ext-dn networks: diff --git a/ci-scripts/yaml_files/5g_rfsimulator_2x2/docker-compose.yaml b/ci-scripts/yaml_files/5g_rfsimulator_2x2/docker-compose.yaml index 5f55ae8877..5a62f8ba5c 100644 --- a/ci-scripts/yaml_files/5g_rfsimulator_2x2/docker-compose.yaml +++ b/ci-scripts/yaml_files/5g_rfsimulator_2x2/docker-compose.yaml @@ -169,7 +169,7 @@ services: environment: RFSIMULATOR: server USE_VOLUMED_CONF: 'yes' - USE_ADDITIONAL_OPTIONS: --sa --rfsim --rfsimulator.wait_timeout 20 --log_config.global_log_options level,nocolor,time + USE_ADDITIONAL_OPTIONS: --sa --rfsim --log_config.global_log_options level,nocolor,time depends_on: - oai-ext-dn networks: diff --git a/ci-scripts/yaml_files/5g_rfsimulator_e1/docker-compose.yaml b/ci-scripts/yaml_files/5g_rfsimulator_e1/docker-compose.yaml index 26e01febb7..f29f9e1ac6 100644 --- a/ci-scripts/yaml_files/5g_rfsimulator_e1/docker-compose.yaml +++ b/ci-scripts/yaml_files/5g_rfsimulator_e1/docker-compose.yaml @@ -216,7 +216,7 @@ services: environment: RFSIMULATOR: server USE_VOLUMED_CONF: 'yes' - USE_ADDITIONAL_OPTIONS: --sa --rfsim --rfsimulator.wait_timeout 20 --log_config.global_log_options level,nocolor,time + USE_ADDITIONAL_OPTIONS: --sa --rfsim --log_config.global_log_options level,nocolor,time networks: ran_net: ipv4_address: 192.168.72.142 diff --git a/ci-scripts/yaml_files/5g_rfsimulator_u0_25prb/docker-compose.yaml b/ci-scripts/yaml_files/5g_rfsimulator_u0_25prb/docker-compose.yaml index 93c18cdfd9..1282edc470 100644 --- a/ci-scripts/yaml_files/5g_rfsimulator_u0_25prb/docker-compose.yaml +++ b/ci-scripts/yaml_files/5g_rfsimulator_u0_25prb/docker-compose.yaml @@ -169,7 +169,7 @@ services: environment: RFSIMULATOR: server USE_VOLUMED_CONF: 'yes' - USE_ADDITIONAL_OPTIONS: --sa --rfsim --rfsimulator.wait_timeout 20 --log_config.global_log_options level,nocolor,time + USE_ADDITIONAL_OPTIONS: --sa --rfsim --log_config.global_log_options level,nocolor,time depends_on: - oai-ext-dn networks: diff --git a/ci-scripts/yaml_files/lte_n3xx_tdd_2x2_tm1/docker-compose.yml b/ci-scripts/yaml_files/lte_n3xx_tdd_2x2_tm1/docker-compose.yml new file mode 100644 index 0000000000..abd2c7d40e --- /dev/null +++ b/ci-scripts/yaml_files/lte_n3xx_tdd_2x2_tm1/docker-compose.yml @@ -0,0 +1,18 @@ +version: '3.8' +services: + oai-enb: + image: oai-enb:latest + privileged: true + container_name: oai-enb + environment: + TZ: Europe/Paris + USE_VOLUMED_CONF: 'yes' + USE_ADDITIONAL_OPTIONS: --usrp-tx-thread-config 1 --thread-pool 0,2,4,6 + volumes: + - ../../conf_files/enb.band38.lte_2x2.100PRB.usrpn310.conf:/opt/oai-enb/etc/mounted.conf + network_mode: "host" + healthcheck: + test: /bin/bash -c "pgrep lte-softmodem" + interval: 10s + timeout: 5s + retries: 5 diff --git a/ci-scripts/yaml_files/lte_n3xx_tdd_2x2_tm2/docker-compose.yml b/ci-scripts/yaml_files/lte_n3xx_tdd_2x2_tm2/docker-compose.yml new file mode 100644 index 0000000000..1679b632b6 --- /dev/null +++ b/ci-scripts/yaml_files/lte_n3xx_tdd_2x2_tm2/docker-compose.yml @@ -0,0 +1,18 @@ +version: '3.8' +services: + oai-enb: + image: oai-enb:latest + privileged: true + container_name: oai-enb + environment: + TZ: Europe/Paris + USE_VOLUMED_CONF: 'yes' + USE_ADDITIONAL_OPTIONS: --usrp-tx-thread-config 1 --thread-pool 0,2,4,6 + volumes: + - ../../conf_files/enb.band38.lte_2x2_tm2.100PRB.usrpn310.conf:/opt/oai-enb/etc/mounted.conf + network_mode: "host" + healthcheck: + test: /bin/bash -c "pgrep lte-softmodem" + interval: 10s + timeout: 5s + retries: 5 diff --git a/common/openairinterface5g_limits.h b/common/openairinterface5g_limits.h index b86f01df6a..d9e49e26a7 100644 --- a/common/openairinterface5g_limits.h +++ b/common/openairinterface5g_limits.h @@ -10,10 +10,9 @@ # define NUMBER_OF_ULSCH_MAX 8 # define NUMBER_OF_DLSCH_MAX 8 # define NUMBER_OF_SRS_MAX 16 -# define NUMBER_OF_NR_ULSCH_MAX MAX_MOBILES_PER_GNB -# define NUMBER_OF_NR_DLSCH_MAX MAX_MOBILES_PER_GNB # define NUMBER_OF_SCH_STATS_MAX 16 -# define NUMBER_OF_NR_SCH_STATS_MAX MAX_MOBILES_PER_GNB + +#define NUMBER_FRAMES_PHY_UE_INACTIVE 10 #define MAX_MANAGED_ENB_PER_MOBILE 2 #define MAX_MANAGED_GNB_PER_MOBILE 2 diff --git a/common/utils/ocp_itti/intertask_interface.cpp b/common/utils/ocp_itti/intertask_interface.cpp index fe43dde319..897e6757af 100644 --- a/common/utils/ocp_itti/intertask_interface.cpp +++ b/common/utils/ocp_itti/intertask_interface.cpp @@ -24,6 +24,7 @@ #include #include #include +#include extern "C" { @@ -434,24 +435,32 @@ extern "C" { void itti_send_terminate_message(task_id_t task_id) { } - pthread_mutex_t signal_mutex; + sem_t itti_sem_block; + void itti_wait_tasks_unblock() + { + int rc = sem_post(&itti_sem_block); + AssertFatal(rc == 0, "error in sem_post(): %d %s\n", errno, strerror(errno)); + } static void catch_sigterm(int) { static const char msg[] = "\n** Caught SIGTERM, shutting down\n"; __attribute__((unused)) int unused = write(STDOUT_FILENO, msg, sizeof(msg) - 1); - pthread_mutex_unlock(&signal_mutex); + itti_wait_tasks_unblock(); } - void itti_wait_tasks_end(void) { + void itti_wait_tasks_end(void (*handler)(int)) + { + int rc = sem_init(&itti_sem_block, 0, 0); + AssertFatal(rc == 0, "error in sem_init(): %d %s\n", errno, strerror(errno)); - pthread_mutex_init(&signal_mutex, NULL); - pthread_mutex_lock(&signal_mutex); + if (handler == NULL) /* no handler given: install default */ + handler = catch_sigterm; + signal(SIGTERM, handler); + signal(SIGINT, handler); - signal(SIGTERM, catch_sigterm); - signal(SIGINT, catch_sigterm); - - pthread_mutex_lock(&signal_mutex); + rc = sem_wait(&itti_sem_block); + AssertFatal(rc == 0, "error in sem_wait(): %d %s\n", errno, strerror(errno)); } void itti_update_lte_time(uint32_t frame, uint8_t slot) {} diff --git a/common/utils/ocp_itti/intertask_interface.h b/common/utils/ocp_itti/intertask_interface.h index 3874d52829..19b0ba32a9 100644 --- a/common/utils/ocp_itti/intertask_interface.h +++ b/common/utils/ocp_itti/intertask_interface.h @@ -550,10 +550,13 @@ MessageDef *itti_alloc_new_message_sized( MessagesIds message_id, MessageHeaderSize size); -/** \brief handle signals and wait for all threads to join when the process complete. - This function should be called from the main thread after having created all ITTI tasks. +/** \brief Wait for SIGINT/SIGTERM signals to unblock ITTI. + This function should be called from the main thread after having created all ITTI tasks. If handler is NULL, a default handler is installed. + \param handler a custom signal handler. To unblock, it should call itti_wait_tasks_unblock() **/ -void itti_wait_tasks_end(void); +void itti_wait_tasks_end(void (*handler)(int)); +/** \brif unblocks ITTI waiting in itti_wait_tasks_end(). **/ +void itti_wait_tasks_unblock(void); void itti_set_task_real_time(task_id_t task_id); /** \brief Send a termination message to all tasks. diff --git a/common/utils/threadPool/thread-pool.c b/common/utils/threadPool/thread-pool.c index b351a667b5..f0f4769faf 100644 --- a/common/utils/threadPool/thread-pool.c +++ b/common/utils/threadPool/thread-pool.c @@ -98,6 +98,8 @@ void *one_thread(void *arg) { myThread->runningOnKey=-1; mutexunlock(tp->incomingFifo.lockF); } + else + delNotifiedFIFO_elt(elt); } while (!myThread->terminate); return NULL; } diff --git a/common/utils/threadPool/thread-pool.h b/common/utils/threadPool/thread-pool.h index 0c544e5b0f..b06671c728 100644 --- a/common/utils/threadPool/thread-pool.h +++ b/common/utils/threadPool/thread-pool.h @@ -279,6 +279,8 @@ static inline void pushTpool(tpool_t *t, notifiedFIFO_elt_t *msg) { if (msg->reponseFifo) pushNotifiedFIFO(msg->reponseFifo, msg); + else + delNotifiedFIFO_elt(msg); } } diff --git a/doc/BUILD.md b/doc/BUILD.md index fd2af4703b..a2c9d0d5a4 100644 --- a/doc/BUILD.md +++ b/doc/BUILD.md @@ -14,13 +14,13 @@ This page is valid on tags starting from **`2019.w09`**. -# Soft Modem Build Script +# Overview -The OAI EPC is developed in a distinct project with it's own [documentation](https://github.com/OPENAIRINTERFACE/openair-epc-fed/wiki) , it is not described here. +The [OAI EPC](https://github.com/OPENAIRINTERFACE/openair-epc-fed/blob/master/docs/DEPLOY_HOME_MAGMA_MME.md) and [OAI 5GC](https://gitlab.eurecom.fr/oai/cn5g/oai-cn5g-fed/-/blob/master/docs/DEPLOY_HOME.md) are developed in distinct projects with their own documentation and are not further described here. OAI softmodem sources, which aim to implement 3GPP compliant UEs, eNodeB and gNodeB can be downloaded from the Eurecom [gitlab repository](./GET_SOURCES.md). -Sources come with a build script [build_oai](../cmake_targets/build_oai) located at the root of the `openairinterface5g/cmake_targets` directory. This script is developed to build the oai binaries (executables,shared libraries) for different hardware platforms, and use cases. +Sources come with a build script [build_oai](../cmake_targets/build_oai) located at the root of the `openairinterface5g/cmake_targets` directory. This script is developed to build the oai binaries (executables,shared libraries) for different hardware platforms, and use cases. The main oai binaries, which are tested by the Continuous Integration process are: @@ -28,36 +28,57 @@ The main oai binaries, which are tested by the Continuous Integration process ar - The 5G UE: `nr-uesoftmodem` - The LTE eNodeB: `lte-softmodem` - The 5G gNodeB: `nr-softmodem` +- The 5G CU-UP: `nr-cuup` - The LTE PHY simulators: `dlsim` and `ulsim` -- The 5G PHY simulators: `nr_dlschsim` `nr_dlsim` `nr_pbchsim` `nr_pucchsim` `nr_ulschsim` `nr_ulsim` `polartest` `smallblocktest` - `ulsim` `ldpctest` +- The 5G PHY simulators: `nr_dlschsim`, `nr_dlsim`, `nr_pbchsim`, `nr_pucchsim`, `nr_ulschsim`, `nr_ulsim`, `polartest`, `smallblocktest`, `nr _ulsim`, `ldpctest` Running the [build_oai](../cmake_targets/build_oai) script also generates some utilities required to build and/or run the oai softmodem binaries: -- `conf2uedata`: a binary used to build the UE data from a configuration file. The created file emulates the sim card of a 3GPP compliant phone. -- `nvram`: a binary used to build UE (IMEI...) and EMM (IMSI, registered PLMN) non volatile data. -- `rb_tool`: radio bearer utility -- `genids` T Tracer utility, used at build time to generate T_IDs.h include file. This binary is located in the [T Tracer source file directory](../common/utils/T) . +- `conf2uedata`: a binary used to build the (4G) UE data from a configuration file. The created file emulates the sim card of a 3GPP compliant phone. +- `nvram`: a binary used to build (4G) UE (IMEI...) and EMM (IMSI, registered PLMN) non volatile data. +- `rb_tool`: radio bearer utility for (4G) UE +- `genids` T Tracer utility, used at build time to generate `T_IDs.h` include file. This binary is located in the [T Tracer source file directory](../common/utils/T) . -The build system for OAI uses [cmake](https://cmake.org/) which is a tool to generate makefiles. The `build_oai` script is a wrapper using cmake, make and standard linux shell commands to ease the oai build and use . The file describing how to build the executables from source files is the [CMakeLists.txt](../CMakeLists.txt), it is used as input by cmake to generate the makefiles. +The build system for OAI uses [cmake](https://cmake.org/) which is a tool to generate makefiles. The `build_oai` script is a wrapper using `cmake` and `make`/`ninja` to ease the oai build and use. It logs the `cmake` and `ninja`/`make` commands it executes. The file describing how to build the executables from source files is the [CMakeLists.txt](../CMakeLists.txt), it is used as input by cmake to generate the makefiles. The oai softmodem supports many use cases, and new ones are regularly added. Most of them are accessible using the configuration file or the command line options and continuous effort is done to avoid introducing build options as it makes tests and usage more complicated than run-time options. The following functionalities, originally requiring a specific build are now accessible by configuration or command line options: - s1, noS1 - all simulators as the rfsimulator, the L2 simulator, with exception of PHY simulators, which are distinct executables. +# Running `build_oai` -Calling the `build_oai` script with the -h option gives the list of all available options, but a process to simplify and check the requirements of all these options is on-going. Check the [table](BUILD.md "# `build_oai` options") At the end of this page to know the status of `buid_oai` options which are not described hereafter. +## List of options -# Building PHY Simulators +Calling the `build_oai` script with the `-h` option gives the list of all available options. A number of important ones: + +- The `-I` option is to install pre-requisites, you only need it the first time you build the softmodem or when some oai dependencies have changed. +- The `-w` option is to select the radio head support you want to include in your build. Radio head support is provided via a shared library, which is called the "oai device" The build script creates a soft link from `liboai_device.so` to the true device which will be used at run-time (here the USRP one, `liboai_usrpdevif.so`). The RF simulator[RF simulator](../radio/rfsimulator/README.md) is implemented as a specific device replacing RF hardware, it can be specifically built using `-w SIMU` option, but is also built during any softmodem build. +- `--eNB` is to build the `lte-softmodem` executable and all required shared libraries +- `--gNB` is to build the `nr-softmodem` and `nr-cuup` executables and all required shared libraries +- `--UE` is to build the `lte-uesoftmodem` executable and all required shared libraries +- `--nrUE` is to build the `nr-uesoftmodem` executable and all required shared libraries +- `--ninja` is to use the `ninja` build tool, which speeds up compilation. +- `-c` is to clean the workspace and force a complete rebuild. + +## Installing dependencies + +Install all dependencies by issuing the `-I` option. To install furthermore libraries for optional libraries, use the `--install-optional-packages` option. The `-I` option will also install dependencies for an SDR when paired with `-w`. For instance, in order to install all dependencies and the ones for USRP, run: + +```bash +cd openairinterface5g/cmake_targets/ +./build_oai -I --install-optional-packages -w USRP +``` + +Note the section on installing UHD further down for more information. + +## Building PHY Simulators The PHY layer simulators (LTE and NR) can be built as follows: -``` -cd /openairinterface5g/ -source oaienv -cd cmake_targets/ -./build_oai -I --phy_simulators +```bash +cd openairinterface5g/cmake_targets/ +./build_oai --phy_simulators ``` After completing the build, the binaries are available in the `cmake_targets/ran_build/build` directory. @@ -68,19 +89,10 @@ Detailed information about these simulators can be found [in this dedicated page After downloading the source files, a single build command can be used to get the binaries supporting all the oai softmodem use cases (UE and [eg]NodeB): +```bash +cd openairinterface5g/cmake_targets/ +./build_oai -w USRP --eNB --UE --nrUE --gNB ``` -cd /openairinterface5g/ -source oaienv -cd cmake_targets/ -./build_oai -I -w USRP --eNB --UE --nrUE --gNB -``` - -- The `-I` option is to install pre-requisites, you only need it the first time you build the softmodem or when some oai dependencies have changed. -- The `-w` option is to select the radio head support you want to include in your build. Radio head support is provided via a shared library, which is called the "oai device" The build script creates a soft link from `liboai_device.so` to the true device which will be used at run-time (here the USRP one,`liboai_usrpdevif.so` . USRP is the only hardware tested today in the Continuous Integration process. The RF simulator[RF simulator](../radio/rfsimulator/README.md) is implemented as a specific device replacing RF hardware, it can be specifically built using `-w SIMU` option, but is also built during any softmodem build. -- `--eNB` is to build the `lte-softmodem` executable and all required shared libraries -- `--gNB` is to build the `nr-softmodem` executable and all required shared libraries -- `--UE` is to build the `lte-uesoftmodem` executable and all required shared libraries -- `--nrUE` is to build the `nr-uesoftmodem` executable and all required shared libraries You can build any oai softmodem executable separately, you may not need all of them depending on your oai usage. @@ -118,35 +130,56 @@ See: * `cmake_targets/tools/uhd-4.x-tdd-patch.diff` * `cmake_targets/tools/build_helper` --> function `install_usrp_uhd_driver_from_source` -# Building Optional Binaries +## Building Optional Binaries -## Telnet Server +There are a number of optional libraries that can be built in support of the +RAN, such as telnet, scopes, offloading libraries, etc. -The telnet server can be built with the `--build-lib telnetsrv` option, after building the softmodem or while building it. +Using the help option of the build script you can get the list of available optional libraries. -`./build_oai -I -w USRP --eNB --UE --build-lib telnetsrv` +```bash +./build_oai --build-lib all # build all +./build_oai --build-lib telnet # build only telnet +./build_oai --build-lib "telnet enbscope uescope nrscope nrqtscope" +./build_oai --build-lib telnet --build-lib nrqtscope +``` -or +The following libraries are build in CI and should always work: `telnet`, +`enbscope`, `uescope`, `nrscope`, `nrqtscope`. -`./build_oai --build-lib telnetsrv` +Some libraries have further dependencies and might not build on every system: +- `enbscope`, `uescope`, `nrscope`: libforms/X +- `nrqtscope`: Qt5 +- `ldpc_cuda`: CUDA +- `ldpc_t1`: DPDK and VVDN T1 +- `websrv`: npm and others -You can get documentation about the telnet server [here](common/utils/telnetsrv/DOC/telnetsrv.md) +# Running `cmake` directly +`build_oai` is a wrapper on top of `cmake`. It is therefore possible to run `cmake` directly. An example using `ninja`: to build all "main targets" for 5G, excluding additional libraries: +``` +cd openairinterface5g +mkdir build && cd build +cmake .. -GNinja && ninja nr-softmodem nr-uesoftmodem nr-cuup params_libconfig coding rfsimulator ldpc +``` +To build additional libraries, e.g., telnet, do the following: +```bash +cmake .. -GNinja -DENABLE_TELNETSRV=ON && ninja telnetsrv +``` -## Other optional libraries +A list of all libraries can be seen using `ccmake ..` or `cmake-gui ..`. -Using the help option of the build script you can get the list of available optional libraries. Those which haven't been mentioned above are known to need more tests and documentation. - -`./build_oai --build-lib all` will build all available optional libraries. - -# `build_oai` options - -Please run `./build_oai -h` to get a list of available options. - -[oai wiki home](https://gitlab.eurecom.fr/oai/openairinterface5g/wikis/home) - -[oai softmodem features](FEATURE_SET.md) - -[running the oai softmodem ](RUNMODEM.md) +It is currently not possible to build all targets in the form of `cmake .. +-GNinja && ninja`: currently, SDRs are always exposed, even if you don't have +the dependencies, and some targets are simply broken. Again, `build_oai` list +all targets that it builds, and you can use them with `ninja` +The default target directory of `build_oai` is the following, for historical reasons: +```bash +cd openairinterface5g/cmake_targets/ran_build/build +cmake ../../.. -GNinja +ccmake ../../.. +cmake-gui ../../.. +``` +You can of course use all standard cmake/ninja/make commands in this directory. diff --git a/doc/Doxyfile b/doc/Doxyfile index 6a4dd850a3..afb89b43ef 100644 --- a/doc/Doxyfile +++ b/doc/Doxyfile @@ -1340,6 +1340,7 @@ INPUT = \ @CMAKE_CURRENT_SOURCE_DIR@/../openair2/LAYER2/NR_MAC_UE/nr_ue_dci_configuration.c \ @CMAKE_CURRENT_SOURCE_DIR@/../openair2/LAYER2/NR_MAC_UE/mac_extern.h \ @CMAKE_CURRENT_SOURCE_DIR@/../openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.c \ +@CMAKE_CURRENT_SOURCE_DIR@/../openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.h \ @CMAKE_CURRENT_SOURCE_DIR@/../openair2/LAYER2/nr_pdcp/nr_pdcp_entity.h \ @CMAKE_CURRENT_SOURCE_DIR@/../openair2/LAYER2/nr_pdcp/nr_pdcp_timer_thread.h \ @CMAKE_CURRENT_SOURCE_DIR@/../openair2/LAYER2/nr_pdcp/nr_pdcp_integrity_nia2.h \ diff --git a/doc/GET_SOURCES.md b/doc/GET_SOURCES.md index f594ba1747..98fd933882 100644 --- a/doc/GET_SOURCES.md +++ b/doc/GET_SOURCES.md @@ -25,7 +25,7 @@ git config --global user.email "Your email address" ## In order to clone the Git repository (for OAI Users without login to gitlab server) -Cloning RAN repository (eNB RAN + UE RAN): +Cloning RAN repository: ```shell git clone https://gitlab.eurecom.fr/oai/openairinterface5g.git @@ -35,22 +35,18 @@ git clone https://gitlab.eurecom.fr/oai/openairinterface5g.git Please send email to [contact@openairinterface.org](mailto:contact@openairinterface.org) to be added to the repository as a developer (only important for users who want to commit code to the repository). If -you do not have account on gitlab.eurecom.fr, please register yourself to gitlab.eurecom.fr and provide the identifiant in the email. +you do not have account on gitlab.eurecom.fr, please register yourself to gitlab.eurecom.fr and provide the login name in the email. + +More information can be found in [a separate page](../CONTRIBUTING.md). # Which branch to checkout? -On the RAN side: +`develop`: contains recent commits that are tested on our CI test bench. The update frequency is about once a week. 5G is only in this branch. It is the recommended and default branch. +`master`: contains a stable version of 4G, and will be updated in the future with 5G. -* **master**: This branch is targeted for the user community. Since January 2019, it is also subject to a Continuous Integration process. The update frequency is about once every 2-3 months. We are also performing bug fixes on this branch. -* **develop**: This branch contains recent commits that are tested on our CI test bench. The update frequency is about once a week. +Please see the work flow and policies page: https://gitlab.eurecom.fr/oai/openairinterface5g/wikis/oai-policies-home -Please see the work flow and policies page: - -https://gitlab.eurecom.fr/oai/openairinterface5g/wikis/oai-policies-home - -you can find the latest stable tag release here: - -https://gitlab.eurecom.fr/oai/openairinterface5g/tags +You can find the latest stable tag release here: https://gitlab.eurecom.fr/oai/openairinterface5g/tags The tag naming conventions are: @@ -60,4 +56,3 @@ The tag naming conventions are: - On `develop` branch **`yyyy`.w`xx`** * `yyyy` is the calendar year * `xx` the week number within the year - diff --git a/doc/README.md b/doc/README.md new file mode 100644 index 0000000000..8612665a7c --- /dev/null +++ b/doc/README.md @@ -0,0 +1,102 @@ + + + + + +
+ + + + + + OpenAirInterface documentation overview +
+ +[[_TOC_]] + +# General + +- [FEATURE_SET.md](./FEATURE_SET.md): lists supported features +- [GET_SOURCES.md](./GET_SOURCES.md): how to download the sources +- [BUILD.md](./BUILD.md): how to build the sources +- [clang-format.md](./clang-format.md): how to format the code + +There is some general information in the [OpenAirInterface Gitlab Wiki](https://gitlab.eurecom.fr/oai/openairinterface5g/-/wikis/home) + +# Tutorials + +- Step-by-step tutorials to set up 5G: + * [OAI 5GC](./NR_SA_Tutorial_OAI_CN5G.md) + * [OAI gNB with COTS UE](./NR_SA_Tutorial_COTS_UE.md) + * [OAI NR-UE](./NR_SA_Tutorial_OAI_nrUE.md) +- [RUNMODEM.md](./RUNMODEM.md): Generic information on how to + * Run simulators + * Run with hardware + * Specific OAI modes (phy-test, do-ra, noS1) + * (5G) Using SDAP and custom DRBs + * IF setups and arbitrary frequencies + * MIMO +- [How to run a 5G-SA setup](./TESTING_5GSA_setup.md) +- [How to run a 5G-NSA setup](./TESTING_GNB_W_COTS_UE.md) +- [How to run a 4G setup using L1 simulator](./L1SIM.md) _Note: we recommend the RFsimulator_ +- [How to use the L2 simulator](./L2NFAPI.md) +- [How to use multiple BWPs](./RUN_NR_multiple_BWPs.md) +- [How to run OAI-VNF and OAI-PNF](./RUN_NR_NFAPI.md) _Note: does not work currently_ +- [How to use the positioning reference signal (PRS)](./RUN_NR_PRS.md) +- [How to use device-to-device communication (D2D, 4G)](./d2d_emulator_setup.txt) + +Legacy unmaintained files: +- `L2NFAPI_NOS1.md`, `L2NFAPI_S1.md`: old L2simulator, not valid anymore +- `SystemX-tutorial-design.md` +- `UL_MIMO.txt` + +# Designs + +- General software architecture notes: [SW_archi.md](./SW_archi.md) +- [Information on E1](./E1-design.md) +- [Information on F1](./F1-design.md) +- [Information on how NR nFAPI works](./NR_NFAPI_archi.md) +- [Flow graph of the L1 in gNB](SW-archi-graph.md) +- [L1 threads in NR-UE](./nr-ue-design.md) + +Legacy unmaintained files: +- 5Gnas.md + +# Building and running from images + +- [How to build images](../docker/README.md) +- [How to run 5G with the RFsimulator from images](../ci-scripts/yaml_files/5g_rfsimulator/README.md) +- [How to run 4G with the RFsimulator from images](../ci-scripts/yaml_files/4g_rfsimulator_fdd_05MHz/README.md) +- [How to run 5G with the L2simulator from images](../ci-scripts/yaml_files/5g_l2sim_tdd/README.md) +- [How to run images in OpenShift](../openshift/README.md) + +# Libraries + +## General + +- The [T tracer](https://gitlab.eurecom.fr/oai/openairinterface5g/-/wikis/T/): a generic tracing tool (VCD, Wireshark, GUI, to save for later, ...) +- [OPT](../openair2/UTIL/OPT/README.txt): how to trace to wireshark +- The [configuration module](../common/config/DOC/config.md) +- The [logging module](../common/utils/LOG/DOC/log.md) +- The [shared object loader](../common/utils/DOC/loader.md) +- The [threadpool](../common/utils/threadPool/thread-pool.md) used in L1 + +## SDRs + +Some directories under `radio` contain READMEs: + +- [RFsimulator](../radio/rfsimulator/README.md) +- [USRP](../radio/USRP/README.md) +- [BladeRF](../radio/BLADERF/README) +- [IQPlayer](../radio/iqplayer/DOC/iqrecordplayer_usage.md) + +The other SDRs (AW2S, LimeSDR, ...) have no READMEs. + +## Special-purpose libraries + +- OAI comes with an integrated [telnet server](../common/utils/telnetsrv/DOC/telnethelp.md) to monitor and control +- OAI comes with an integrated [web server](../common/utils/websrv/DOC/websrv.md) + +# CI + +- [TESTBenches.md](./TESTBenches.md) lists the CI setup and links to pipelines diff --git a/doc/RUNMODEM.md b/doc/RUNMODEM.md index 988f3364be..d32758b1a2 100644 --- a/doc/RUNMODEM.md +++ b/doc/RUNMODEM.md @@ -7,68 +7,123 @@ - Running OAI Softmodem + Running OAI Softmodems After you have [built the softmodem executables](BUILD.md) you can set your default directory to the build directory `cmake_targets/ran_build/build/` and start testing some use cases. Below, the description of the different oai functionalities should help you choose the oai configuration that suits your need. -# RF Simulator +[[_TOC_]] -The rf simulator is a oai device replacing the radio heads (for example the USRP device). It allows connecting the oai UE (LTE or 5G) and respectively the oai eNodeB or gNodeB through a network interface carrying the time-domain samples, getting rid of over the air unpredictable perturbations. This is the ideal tool to check signal processing algorithms and protocols implementation. The rf simulator has some preliminary support for channel modeling. +# Simulators + +## RFsimulator + +The RF simulator is an OAI device replacing the radio heads (for example the USRP device). It allows connecting the oai UE (LTE or 5G) and respectively the oai eNodeB or gNodeB through a network interface carrying the time-domain samples, getting rid of over the air unpredictable perturbations. This is the ideal tool to check signal processing algorithms and protocols implementation. The rf simulator has some preliminary support for channel modeling. It is planned to enhance this simulator with the following functionalities: -- Support for multiple UE connections,each UE being a `lte-uesoftmodem` or `nr_uesoftmodem` instance. - Support for multiple eNodeB's or gNodeB's for hand-over tests - This is an easy use-case to setup and test, as no specific hardware is required. The [rfsimulator page](../radio/rfsimulator/README.md ) contains the detailed documentation. +This is an easy use-case to setup and test, as no specific hardware is required. The [rfsimulator page](../radio/rfsimulator/README.md ) contains the detailed documentation. -# L2 nFAPI Simulator +## L2 nFAPI Simulator This simulator connects a eNodeB and UEs through a nfapi interface, short-cutting the L1 layer. The objective of this simulator is to allow multi UEs simulation, with a large number of UEs (ideally up to 255 ) .Here to ease the platform setup, UEs are simulated via a single `lte-uesoftmodem` instance. Today the CI tests just with one UE and architecture has to be reviewed to allow a number of UE above about 16. This work is on-going. As for the rf simulator, no specific hardware is required. The [L2 nfapi simulator page](L2NFAPI.md) contains the detailed documentation. -# L1 Simulator +## L1 Simulator + +**This information might be outdated. We recommend to use the RFsimulator as +shown above.** The L1 simulator is using the ethernet fronthaul protocol, as used to connect a RRU and a RAU to connect UEs and a eNodeB. UEs are simulated in a single `lte-uesoftmodem` process, as for the nfapi simulator. The [L1 simulator page](L1SIM.md) contains the detailed documentation. -## noS1 mode - -The noS1 mode is now available via the `--noS1`command line option. It can be used with simulators, described above, or when using oai with true RF boards. Only the oai UE can be connected to the oai eNodeB in noS1 mode. - -By default the noS1 mode is using linux tun interfaces to send or receive ip packets to/from the linux ip stack. using the `--nokrnmod 0`option you can enforce kernel modules instead of tun. - -noS1 code has been revisited, it has been tested with the rf simulator, and tun interfaces. More tests are on going and CI will soon include noS1 tests. - # Running with a true radio head -oai supports [number of deployment](FEATURE_SET.md) model, the following are tested in the CI: +OAI supports different radio heads, the following are tested in the CI: + +1. [Monolithic eNodeB](https://gitlab.eurecom.fr/oai/openairinterface5g/wikis/HowToConnectCOTSUEwithOAIeNBNew) where the whole signal processing is performed in a single process +2. IF4P5 mode, where frequency domain samples are carried over ethernet, from the RRU which implement part of L1(FFT,IFFT,part of PRACH), to a RAU +3. Monolithic gNodeB: see next section, or the [standalone tutorial](NR_SA_Tutorial_COTS_UE.md) -1. [Monolithic eNodeB](https://gitlab.eurecom.fr/oai/openairinterface5g/wikis/HowToConnectCOTSUEwithOAIeNBNew) where the whole signal processing is performed in a single process -2. if4p5 mode, where frequency domain samples are carried over ethernet, from the RRU which implement part of L1(FFT,IFFT,part of PRACH), to a RAU # 5G NR -As of February 2020, all 5G NR development is part of the develop branch (the branch develop-nr is no longer maintained). This also means that all new development will be merged into there once it passes all the CI. - ## NSA setup with COTS UE This setup requires an EPC, an OAI eNB and gNB, and a COTS Phone. A dedicated page describe the setup can be found [here](https://gitlab.eurecom.fr/oai/openairinterface5g/wikis/home/gNB-COTS-UE-testing). -### Launch gNB - -```bash sudo ./nr-softmodem -O ../../../targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.usrpn300.conf``` - ### Launch eNB -```bash sudo ./lte-softmodem -O ../../../targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.usrpb210.conf``` +```bash +sudo ./lte-softmodem -O ../../../targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.usrpb210.conf +``` + +### Launch gNB + +```bash +sudo ./nr-softmodem -O ../../../targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.usrpn300.conf +``` + +You should see the X2 messages in Wireshark and at the eNB. + +## SA setup with OAI NR-UE + +The sa flag is used to run gNB in standalone mode. + +In order to run gNB and UE in standalone mode, the `--sa` flag is needed. + +At the gNB the `--sa` flag does the following: +- The RRC encodes SIB1 according to the configuration file and transmits it through NR-BCCH-DL-SCH. + +At the UE the --sa flag will: +- Decode SIB1 and starts the 5G NR Initial Access Procedure for SA: + 1) 5G-NR RRC Connection Setup + 2) NAS Authentication and Security + 3) 5G-NR AS Security Procedure + 4) 5G-NR RRC Reconfiguration + 5) Start Downlink and Uplink Data Transfer + +Command line parameters for UE in --sa mode: +- `-C` : downlink carrier frequency in Hz (default value 0) +- `--CO` : uplink frequency offset for FDD in Hz (default value 0) +- `--numerology` : numerology index (default value 1) +- `-r` : bandwidth in terms of RBs (default value 106) +- `--band` : NR band number (default value 78) +- `--ssb` : SSB start subcarrier (default value 512) + +You can run this, using USRPs, on two separate machines: + +``` +sudo ./nr-softmodem -O ../../../targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.usrpb210.conf --gNBs.[0].min_rxtxtime 6 --sa +sudo ./nr-uesoftmodem -r 106 --numerology 1 --band 78 -C 3619200000 --ssb 516 --sa +``` + +With the RF simulator (on the same machine): + +```bash +sudo ./nr-softmodem -O ../../../targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.usrpb210.conf --gNBs.[0].min_rxtxtime 6 --rfsim --sa +sudo ./nr-uesoftmodem -r 106 --numerology 1 --band 78 -C 3619200000 --ssb 516 --rfsim --sa +``` + +Additionally, at UE side `--uecap_file` option can be used to pass the UE Capabilities input file (path location + filename), e.g. `--uecap_file ../../../targets/PROJECTS/GENERIC-NR-5GC/CONF/uecap_ports1.xml` + +## Some useful NR-UE parameters + +Some other useful paramters of the UE are + + - --ue-fo-compensation: enables the frequency offset compenstation at the UE. This is useful when running over the air and/or without an external clock/time source + - --usrp-args: this is the equivalend paramter of sdr_addrs field in the gNB config file and can be used to identify the USRP and set some basic paramters (like the clock source) + - --clock-source: sets the clock-source (internal or external). + - --time-source: sets the time-source (internal or external). +# Specific OAI modes ## phy-test setup with OAI UE @@ -81,22 +136,18 @@ At the UE the --phy-test flag will - read the binary files rbconfig.raw and reconfig.raw from the current directory (a different directory can be specified with the flag --rrc_config_path) and process them. -### Launch gNB +```bash +sudo ./nr-softmodem -O ../../../targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.usrpn300.conf --phy-test +``` -```bash sudo ./nr-softmodem -O ../../../targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.usrpn300.conf --phy-test``` +In phy-test mode it is possible to mimic the reception of UE Capabilities at gNB by passing through the command line parameter `--uecap_file` the location and file name of the input UE Capability file, e.g. `--uecap_file ../../../targets/PROJECTS/GENERIC-NR-5GC/CONF/uecap_ports1.xml` (1 layer) or `--uecap_file ../../../targets/PROJECTS/GENERIC-NR-5GC/CONF/uecap_ports2.xml` (2 layers). -In phy-test mode it is possible to mimic the reception of UE Capabilities at gNB by passing through the command line parameter `--uecap_file` the location and file name of the input UE Capability file, e.g. `--uecap_file ../../../targets/PROJECTS/GENERIC-NR-5GC/CONF/uecap_ports1.xml` +```bash +sudo ./nr-uesoftmodem --phy-test [--rrc_config_path ../../../ci-scripts/rrc-files] +``` -### Launch UE in another window - -```bash sudo ./nr-uesoftmodem --phy-test [--rrc_config_path ../../../ci-scripts/rrc-files]``` - -Some other useful paramters of the UE are - - - --ue-fo-compensation: enables the frequency offset compenstation at the UE. This is useful when running over the air and/or without an external clock/time source - - --usrp-args: this is the equivalend paramter of sdr_addrs field in the gNB config file and can be used to identify the USRP and set some basic paramters (like the clock source) - - --clock-source: sets the clock-source (internal or external). - - --time-source: sets the time-source (internal or external). +You need to provide `--rrc_config_path` if you don't start the UE after the gNB +in the same directory. ## noS1 setup with OAI UE @@ -108,78 +159,29 @@ This setup is described in the [rfsimulator page](../radio/rfsimulator/README.md The do-ra flag is used to ran the NR Random Access procedures in contention-free mode. Currently OAI implements the RACH process from Msg1 to Msg3. -In order to run the RA, the following flag is needed for both the gNB and the UE: - -`--do-ra` - -### Run OAI in do-ra mode - -From the `cmake_targets/ran_build/build` folder: - -gNB on machine 1: - -`sudo ./nr-softmodem -O ../../../targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.usrpn300.conf --do-ra` +In order to run the RA, the `--do-ra` flag is needed for both the gNB and the UE. In do-ra mode it is possible to mimic the reception of UE Capabilities at gNB by passing through the command line parameter `--uecap_file` the location and file name of the input UE Capability file, e.g. `--uecap_file ../../../targets/PROJECTS/GENERIC-NR-5GC/CONF/uecap_ports1.xml` -UE on machine 2: +To run using the RFsimulator: -`sudo ./nr-uesoftmodem --do-ra` +```bash +sudo RFSIMULATOR=gnb ./nr-softmodem -O ../../../targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.usrpn300.conf --do-ra --rfsim --parallel-config PARALLEL_SINGLE_THREAD +sudo RFSIMULATOR=127.0.0.1 ./nr-uesoftmodem --do-ra --rfsim --parallel-config PARALLEL_SINGLE_THREAD +``` -With the RF simulator (on the same machine): +Using USRPs: -`sudo RFSIMULATOR=gnb ./nr-softmodem -O ../../../targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.usrpn300.conf --do-ra --rfsim --parallel-config PARALLEL_SINGLE_THREAD` +```bash +sudo ./nr-softmodem -O ../../../targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.usrpn300.conf --do-ra +``` -`sudo RFSIMULATOR=127.0.0.1 ./nr-uesoftmodem --do-ra --rfsim --parallel-config PARALLEL_SINGLE_THREAD` +On a separate machine: -## SA setup with OAI +```bash +sudo ./nr-uesoftmodem --do-ra +``` -The sa flag is used to run gNB in standalone mode. - -In order to run gNB and UE in standalone mode, the following flag is needed: - -`--sa` - -At the gNB the --sa flag does the following: -- The RRC encodes SIB1 according to the configuration file and transmits it through NR-BCCH-DL-SCH. - -At the UE the --sa flag will: -- Decode SIB1 and starts the 5G NR Initial Access Procedure for SA: - 1) 5G-NR RRC Connection Setup - 2) NAS Authentication and Security - 3) 5G-NR AS Security Procedure - 4) 5G-NR RRC Reconfiguration - 5) Start Downlink and Uplink Data Transfer - -Command line parameters for UE in --sa mode: -- `C` : downlink carrier frequency in Hz (default value 0) -- `CO` : uplink frequency offset for FDD in Hz (default value 0) -- `numerology` : numerology index (default value 1) -- `r` : bandwidth in terms of RBs (default value 106) -- `band` : NR band number (default value 78) -- `s` : SSB start subcarrier (default value 512) - -### Run OAI in SA mode - -From the `cmake_targets/ran_build/build` folder: - -gNB on machine 1: - -`sudo ./nr-softmodem -O ../../../targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.usrpb210.conf --gNBs.[0].min_rxtxtime 6 --sa` - -UE on machine 2: - -`sudo ./nr-uesoftmodem -r 106 --numerology 1 --band 78 -C 3619200000 --ssb 516 --sa` - -With the RF simulator (on the same machine): - -`sudo ./nr-softmodem -O ../../../targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.usrpb210.conf --gNBs.[0].min_rxtxtime 6 --rfsim --sa` - -`sudo ./nr-uesoftmodem -r 106 --numerology 1 --band 78 -C 3619200000 --ssb 516 --rfsim --sa` - -where `-r` sets the transmission bandwidth configuration in terms of RBs, `-C` sets the downlink carrier frequency and `--ssb` sets the SSB start subcarrier. - -Additionally, at UE side `--uecap_file` option can be used to pass the UE Capabilities input file (path location + filename), e.g. `--uecap_file ../../../targets/PROJECTS/GENERIC-NR-5GC/CONF/uecap_ports1.xml` ### Run OAI with SDAP & Custom DRBs @@ -208,17 +210,14 @@ Accordingly, the following parameters must be configured in the RUs section of t The following example uses DL frequency 2169.080 MHz and UL frequency offset -400 MHz, with a configuration file for band 66 (FDD) at gNB side. -From the `cmake_targets/ran_build/build` folder: +On two separate machines with USRPs, run: -gNB on machine 1: +``` +sudo ./nr-softmodem -O ../../../targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band66.tm1.106PRB.usrpx300.conf +sudo ./nr-uesoftmodem --if_freq 2169080000 --if_freq_off -400000000 +``` -`sudo ./nr-softmodem -O ../../../targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band66.tm1.106PRB.usrpx300.conf` - -UE on machine 2: - -`sudo ./nr-uesoftmodem --if_freq 2169080000 --if_freq_off -400000000` - -# MIMO configuration +# 5G gNB MIMO configuration In order to enable DL-MIMO in OAI 5G softmodem, the prerequisite is to have `do_CSIRS = 1` in the configuration file. This allows the gNB to schedule CSI reference signal and to acquire from the UE CSI measurements to be able to schedule DLSCH with MIMO. @@ -246,10 +245,3 @@ Finally the number of TX physical antenna in the RU part of the configuration fi # Additional links [Selecting an alternative ldpc implementation at run time](../openair1/PHY/CODING/DOC/LDPCImplementation.md) - -[oai wiki home](https://gitlab.eurecom.fr/oai/openairinterface5g/wikis/home) - -[oai softmodem features](FEATURE_SET.md) - -[oai softmodem build procedure](BUILD.md) - diff --git a/doc/SW_archi.md b/doc/SW_archi.md index 7f16edab11..6b509cc627 100644 --- a/doc/SW_archi.md +++ b/doc/SW_archi.md @@ -327,25 +327,23 @@ successful_delivery() and max_retx_reached(): in ??? trigger, the RLC sends a it The PDCP implementation is also protected through a general mutex. The design is very similar to rlc layer. The pdcp data is isolated and encapsulated. -pdcp_layer_init(): same as rlc init +nr_pdcp_layer_init(): same as rlc init we have to call a second init function: pdcp_module_init() -At Tx side (DL in gNB), pdcp_data_req() is the entry function that the upper layer calls. +At Tx side (DL in gNB), `pdcp_data_req_drb()` and `pdcp_data_req_srb()` are the entry functions that the upper layer calls. The upper layer can be GTP or a PDCP internal thread enb_tun_read_thread() that read directly from Linux socket in case we skip 3GPP core implementation. -PDCP internals for pdcp_data_req() is thread safe: inside pdcp_data_req_drb(), the pdcp manager protects with the mutex the access to the SDU receiving function of PDCP (recv_sdu() callback, corresponding to nr_pdcp_entity_drb_am_recv_sdu() for DRBs). When it needs, the pdcp layer push this data to rlc by calling : rlc_data_req() - -Also, incoming downlink sdu can comme from internal RRC: in this case, pdcp_run() reads a itti queue, for message RRC_DCCH_DATA_REQ, to0 only call 'pdcp_data_req()' +PDCP internals for nr_pdcp_data_req_srb()/nr_pdcp_data_req_drb() are thread safe: inside them, the pdcp manager protects with the mutex the access to the SDU receiving function of PDCP (recv_sdu() callback, corresponding to nr_pdcp_entity_drb_am_recv_sdu() for DRBs). When it needs, the pdcp layer push this data to rlc by calling : rlc_data_req() At Rx side, pdcp_data_ind() is the entry point that receives the data from RLC. - Inside pdcp_data_ind(), the pdcp manager mutex protects the access to the PDU receiving function of PDCP (recv_pdu() callback corresponding to nr_pdcp_entity_drb_am_recv_pdu() for DRBs) - Then deliver_sdu_drb() function sends the received data to GTP thread through an ITTI message (GTPV1U_TUNNEL_DATA_REQ). -pdcp_config_set_security(): not yet developped +nr_pdcp_config_set_security(): sets the keys for AS security of a UE -nr_DRB_preconfiguration(): the mac layer calls this for ??? +nr_DRB_preconfiguration(): the mac layer calls this for configuration in phy-test/do-ra mode -nr_pdcp_add_srbs() adds UE SRBs in pdcp, pdcp_remove_UE() removes it -nr_pdcp_add_drbs() adds UE DRBs in pdcp, pdcp_remove_UE() removes it +nr_pdcp_add_srbs() adds UE SRBs in pdcp, nr_pdcp_remove_UE() removes it +nr_pdcp_add_drbs() adds UE DRBs in pdcp, nr_pdcp_remove_UE() removes it # GTP Gtp + UDP are two twin threads performing the data plane interface to the core network @@ -357,7 +355,7 @@ PDCP layer push to the GTP queue (outside UDP thread that do almost nothing and ## GTP thread running code from other layers -gtp thread calls directly pdcp_data_req(), so it runs inside it's context internal pdcp structures updates +gtp thread calls directly nr_pdcp_data_req_drb(), so it runs inside it's context internal pdcp structures updates ## inside other threads gtpv1u_create_s1u_tunnel(), delete tunnel, ... functions are called inside the other threads, without mutex. diff --git a/doc/TESTBenches.md b/doc/TESTBenches.md index 20d8f79ff0..596097c3d3 100644 --- a/doc/TESTBenches.md +++ b/doc/TESTBenches.md @@ -6,25 +6,25 @@ | Machine | IP address | Lockable Resource | Function | Connected devices | | ------------- | --------------- | --------------------- | ------------------ | ----------------------------------------------------- | -| asterix | 172.21.16.127 | CI-Asterix-Usage | gNB (n78) | 173.21.19.14 | -| obelix | 172.21.16.128 | CI-Obelix-Usage | eNB (n40, n78), nrUE | 172.21.19.13, X300 (192.168.60.2), B200mini (30C51EB) | -| porcepix | 172.21.16.136 | CI-NSA-MiniBench | Executor, EPC, 5GC | -- | -| nrmodule2 | 172.21.16.139 | CI-NSA-MiniBench | Quectel | Quectel module | -| nepes | 172.21.16.137 | CI-NSA-MiniBench | gNB (n78) | B200mini (30C51D4) | +| asterix | 172.21.16.127 | CI-Asterix-Usage | gNB (n78) | 172.21.19.14 | +| obelix | 172.21.16.128 | CI-Obelix-Usage | eNB (n40, n78), nrUE | 172.21.19.13, X300 (192.168.60.2) | +| porcepix | 172.21.16.136 | CI-Porcepix | Executor, EPC, 5GC | -- | +| nrmodule2 | 172.21.16.139 | CI-NrModule2 | Quectel | Quectel module | +| nepes | 172.21.16.137 | CI-Nepes | gNB (n78), EPC/5GC | B200mini (30C51EB) | +| ofqot | 172.21.16.109 | CI-Ofqot | gNB (n78) | B200mini (30C51D4) | +| idefix | 172.21.16.135 | CI-Idefix | Quectel | Quectel module | | caracal | 172.21.16.132 | CI-Caracal | gNB/phytest | N300 (192.168.10.2) | -| idefix | 172.21.16.135 | CI-NSA-MiniBench | Quectel | Quectel module | | amariue | 172.21.16.144 | CI-Amarisoft-UE-Usage | nrUE | Amarisoft UE simulator | -| bellatrix | 192.168.117.115 | CI-RAN-VM-Deployment | Executor | -- | -| nano | 172.21.18.48 | CI-Bench-1-Phones | EPC, adb | 2x COTS (adb) | -| hutch | 172.21.18.46 | CI-Bench-1-Phones | eNB (B7) | B200mini (30C5239) | -| starsky | 172.21.18.45 | CI-Bench-1-Phones | eNB (B40) | b200mini (30A3E3C) | -| carabe | 172.21.18.47 | CI-Bench-2-OAI-Phone | UE (B7UE) | B200mini (30AE8C9) | +| manarola | 172.21.8.116 | _None_ | gNB | AW2S | +| nano | 172.21.18.48 | CI-Nano-Legacy-EPC | Executor, EPC, adb | 2x COTS (adb) | +| hutch | 172.21.18.46 | CI-Hutch-Legacy-FDD-eNB | eNB (B7) | B200mini (30C5239) | +| starsky | 172.21.18.45 | CI-Starsky-Legacy-TDD-eNB | eNB (B40) | b200mini (30A3E3C) | +| carabe | 172.21.18.47 | CI-Carabe-Legacy-FDD-OAI-LTE-UE | UE (B7UE) | B200mini (30AE8C9) | +| nokiabox | 172.21.19.39 | _None_ | gNB (Nokia), 5GC | _Nokia RF integrated_ | Note: The available resources, and their current usage, is indicated here: - [Lockable resources of jenkins-oai](https://jenkins-oai.eurecom.fr/lockable-resources/): "New" Jenkins, i.e., with RAN-Container-Parent -- [Lockable resources of open5glab jenkins](https://open5glab.eurecom.fr:8083/jenkins/lockable-resources/): - "Old" Jenkins, i.e., with RAN-CI-Develop ## Networked devices @@ -35,37 +35,39 @@ Note: The available resources, and their current usage, is indicated here: ## Testbenches -### OTA Testbench +### 5G OTA Testbench -**Purpose**: Over-the-air 4G/5G (NSA/SA) tests - -Note: obelix and porcepix are both used in the OTA testbench and the 5G -NSA/Faraday Cage testbench! +**Purpose**: Over-the-air 4G/5G (NSA/SA) tests, performance tests ![5G OTA Testbench](testbenches_doc_resources/5g-ota-bench.png) [PDF version](testbenches_doc_resources/5g-ota-bench.pdf) | [LaTeX/TikZ version](testbenches_doc_resources/5g-ota-bench.tex) if you want to modify to reflect your setup + ### 5G NSA/Faraday Cage Testbench -**Purpose**: Faraday cage 5G tests - -Note: obelix and porcepix are both used in the OTA testbench and the 5G -NSA/Faraday Cage testbench! +**Purpose**: Faraday cage 5G tests, functional tests ![5G NSA/Faraday Cage Testbench](testbenches_doc_resources/5g-nsa-faraday-bench.png) [PDF version](testbenches_doc_resources/5g-nsa-faraday-bench.pdf) | [LaTeX/TikZ version](testbenches_doc_resources/5g-nsa-faraday-bench.tex) if you want to modify to reflect your setup +### 5G AW2S Testbench + +**Purpose**: AW2S tests with Amarisoft + +Picture: TBD + + ### 4G Testbench(es) **Purpose**: 4G/LTE testbenches - ![4G Faraday Cage Testbench](testbenches_doc_resources/4g-faraday-bench.png) [PDF version](testbenches_doc_resources/4g-faraday-bench.pdf) | [LaTeX/TikZ version](testbenches_doc_resources/4g-faraday-bench.tex) if you want to modify to reflect your setup + ## Pipelines ### [RAN-Container-Parent](https://jenkins-oai.eurecom.fr/job/RAN-Container-Parent/) @@ -76,50 +78,48 @@ Webhook - [RAN-cppcheck](https://jenkins-oai.eurecom.fr/job/RAN-cppcheck/1664/) - obelix - performs static code analysis, currently not actively enforced -- [RAN-gNB-nrUE-MONO-TDD-Band78-N300](https://jenkins-oai.eurecom.fr/job/RAN-gNB-nrUE-MONO-TDD-Band78-N300/) +- [RAN-gNB-N300-Timing-Phytest-LDPC](https://jenkins-oai.eurecom.fr/view/RAN/job/RAN-gNB-N300-Timing-Phytest-LDPC/) - caracal + N310 - - pure performance test through phy-test scheduler, see command line for more - details + - pure performance test through phy-test scheduler, see command line for more details - [RAN-L2-Sim-Test-5G](https://jenkins-oai.eurecom.fr/job/RAN-L2-Sim-Test-4G/) - obelix (eNB, 1x UE, OAI EPC) - L2simulator: skips physical layer and uses proxy between eNB and UE - [RAN-L2-Sim-Test-5G](https://jenkins-oai.eurecom.fr/job/RAN-L2-Sim-Test-5G/) - obelix (gNB, 1x UE, OAI 5GC) - - L2simulator: skips physical layer and uses proxy between gNB and UE, - currently only ping + - L2simulator: skips physical layer and uses proxy between gNB and UE, currently only ping +- [RAN-LTE-FDD-LTEBOX-Container](https://jenkins-oai.eurecom.fr/job/RAN-LTE-FDD-LTEBOX-Container/) + - hutch + B210, nano w/ ltebox + 2x UE + - tests RRC inactivity timers, different bandwidths +- [RAN-LTE-TDD-2x2-Container](https://jenkins-oai.eurecom.fr/view/RAN/job/RAN-LTE-TDD-2x2-Container/) + - obelix + N310, porcepix, quectel + - TM1 and TM2 test +- [RAN-LTE-TDD-LTEBOX-Container](https://jenkins-oai.eurecom.fr/job/RAN-LTE-TDD-LTEBOX-Container/) + - starsky + B210, nano w/ ltebox + 2x UE + - TM1 over bandwidths 5, 10, 20 MHz in Band 40, default scheduler for 20 MHz - [RAN-NSA-B200-Module-LTEBOX-Container](https://jenkins-oai.eurecom.fr/job/RAN-NSA-B200-Module-LTEBOX-Container/) - - obelix + B200, nepes + B200, idefix + Quectel, porcepix w/ ltebox + - nepes + B200 (eNB), ofqot + B200 (gNB), idefix + Quectel, nepes w/ ltebox - basic NSA test -- [RAN-SA-B200-Module-SABOX-Container](https://jenkins-oai.eurecom.fr/job/RAN-SA-B200-Module-SABOX-Container/) - - obelix + B200, nepes + B200, idefix + Quectel, porcepix w/ sabox - - basic SA test (40 MHz TDD) - [RAN-PhySim-Cluster](https://jenkins-oai.eurecom.fr/job/RAN-PhySim-Cluster/) - - poseidon (jumphost, `Asterix-OC-oaicicd-session` resource), tests in - OpenShift Cluster + - cluster (`Asterix-OC-oaicicd-session` resource), tests in OpenShift Cluster - unitary simulators (`nr_dlsim`, etc.) - [RAN-RF-Sim-Test-4G](https://jenkins-oai.eurecom.fr/job/RAN-RF-Sim-Test-4G/) - - obelix (eNB, 1x UE, OAI EPC) + - obelix (eNB, lteUE, OAI EPC) - uses RFsimulator, for FDD 5, 10, 20MHz with core, 5MHz noS1 - [RAN-RF-Sim-Test-5G](https://jenkins-oai.eurecom.fr/job/RAN-RF-Sim-Test-5G/) - - obelix (gNB, 2x UE, OAI 5GC) + - obelix (gNB, nrUE, OAI 5GC) - uses RFsimulator, TDD 40MHz, FDD 40MHz, F1 split - [RAN-RHEL8-Cluster-Image-Builder](https://jenkins-oai.eurecom.fr/job/RAN-RHEL8-Cluster-Image-Builder/) - - poseidon (jumphost, `Asterix-OC-oaicicd-session` resource): RHEL 8 image - build using the OpenShift Cluster -- [RAN-Ubuntu18-Image-Builder](https://jenkins-oai.eurecom.fr/job/RAN-Ubuntu18-Image-Builder/) - - obelix: Ubuntu 18 image build using docker + - cluster (`Asterix-OC-oaicicd-session` resource): RHEL 8 image build using the OpenShift Cluster +- [RAN-SA-B200-Module-SABOX-Container](https://jenkins-oai.eurecom.fr/job/RAN-SA-B200-Module-SABOX-Container/) + - ofqot + B200, idefix + Quectel, nepes w/ sabox + - basic SA test (20 MHz TDD), F1, reestablishment, ... +- [RAN-Ubuntu20-Image-Builder](https://jenkins-oai.eurecom.fr/job/RAN-Ubuntu18-Image-Builder/) + - obelix: Ubuntu 20 image build using docker (Note: builds U20 images while pipeline is named U18!) -### [RAN-CI-NSA-Trigger](https://jenkins-oai.eurecom.fr/view/RAN/job/RAN-CI-NSA-Trigger/) +### RAN-CI-NSA-Trigger -**Purpose**: longer-running over-the-air LTE, NSA, and SA tests, triggered -through cron job at midnight +***DEFUNCT***: longer-running over-the-air LTE, NSA, and SA tests. To be integrated into RAN-Container-Parent. -- [RAN-LTE-2x2-Module-OAIEPC](https://jenkins-oai.eurecom.fr/job/RAN-LTE-2x2-Module-OAIEPC/) - - obelix + N310, nrmodule2 + Quectel, porcepix w/ Magma EPC - - LTE 2x2 test with TM1 and TM2 -- [RAN-NSA-B200-Module-LTEBOX](https://jenkins-oai.eurecom.fr/job/RAN-NSA-B200-Module-LTEBOX/) - - obelix + B200 (eNB), nepes + B200 (gNB), idefix + Quectel, porcepix w/ ltebox - - Note: like [RAN-NSA-B200-Module-LTEBOX-Container](https://jenkins-oai.eurecom.fr/job/RAN-NSA-B200-Module-LTEBOX-Container/) above, but compiled/run from source - [RAN-NSA-2x2-Module-OAIEPC](https://jenkins-oai.eurecom.fr/job/RAN-NSA-2x2-Module-OAIEPC/) - obelix + N310 (eNB), asterix + N310 (gNB), nrmodule2 + Quectel, porcepix w/ Magma EPC - LTE 2x2 and NR 2x2 (non-standalone) @@ -133,32 +133,22 @@ through cron job at midnight - asterix + N310, amariue (1x UE), porcepix w/ OAI 5GC - Amarisoft UE simulator: expected to be increased to more UEs -### [RAN-CI-develop](https://open5glab.eurecom.fr:8083/jenkins/job/RAN-CI-develop/) +### RAN-CI-develop -**Purpose**: automatically triggered tests, mostly 4G, to be phased out and +***DEFUNCT***: automatically triggered tests, mostly 4G, to be phased out and integrated into RAN-Container-Parent -runs tests: -- bellatrix: runs 4G/5G simulators directly (eNB + 1x UE + (opt.) OAI EPC, gNB + 1x UE in "noS1") - -triggers pipelines: -- [eNB-CI-FDD-Band7-B210](https://open5glab.eurecom.fr:8083/jenkins/job/eNB-CI-FDD-Band7-B210/) - - hutch + B210, nano w/ ltebox + 2x UE - - tests T tracer, RRC inactivity timers, different bandwidths -- [eNB-CI-IF4p5-FDD-Band7-B210](https://open5glab.eurecom.fr:8083/jenkins/job/eNB-CI-IF4p5-FDD-Band7-B210/) +The following defunct pipelines remain to be integrated into RAN-Container-Parent: +- eNB-CI-IF4p5-FDD-Band7-B210 - hutch + B210, nano w/ ltebox + 2x UE - tests IF4.5 split over bandwidths 5, 10, 20 MHz in Band 7 -- [eNB-CI-IF4p5-TDD-Band40-B210](https://open5glab.eurecom.fr:8083/jenkins/job/eNB-CI-IF4p5-TDD-Band40-B210/) +- eNB-CI-IF4p5-TDD-Band40-B210 - starsky + B210, nano w/ ltebox + 2x UE - tests IF4.5 split over bandwidths 5, 10, 20 MHz in Band 40 -- [eNB-CI-TDD-Band40-B210](https://open5glab.eurecom.fr:8083/jenkins/job/eNB-CI-TDD-Band40-B210/) - - starsky + B210, nano w/ ltebox + 2x UE - - T tracer, TM1 over bandwidths 5, 10, 20 MHz in Band 40, default scheduler - for 20 MHz -- [eNB-UE-CI-MONO-FDD-Band7-B200](https://open5glab.eurecom.fr:8083/jenkins/job/eNB-UE-CI-MONO-FDD-Band7-B200/) +- eNB-UE-CI-MONO-FDD-Band7-B200 - hutch + B210 (eNB), carabe + B210 (4G UE), nano w/ ltebox - tests OAI 4G for 5 MHz/TM1 with both CN and in noS1 model, MBMS; known to be unstable -- [UE-CI-FDD-Band20-B200](https://open5glab.eurecom.fr:8083/jenkins/job/UE-CI-FDD-Band20-B200/) +- UE-CI-FDD-Band20-B200 - starsky + B210 (sniffer) - Sniff MIB + SIB1 of Orange, SFR diff --git a/doc/TESTING_GNB_W_COTS_UE.md b/doc/TESTING_GNB_W_COTS_UE.md index fa24d74d5d..a152d54075 100644 --- a/doc/TESTING_GNB_W_COTS_UE.md +++ b/doc/TESTING_GNB_W_COTS_UE.md @@ -395,18 +395,3 @@ The following parts have been validated with FR1 COTS UE: DL traffic : 3Mbps UL traffic : 1Mbps some packet losses might still occur even in ideal channel conditions - - -## CI integration -The automation scripts are available on ILIADE. -The end-to-end test is integrated in the CI flow in a semi-automated manner, comprising 3 steps: -- update a YAML file comprising the IT resources definition, branch and commit number the test has to run on -- run the python script that generates the test from the YAML file -``` -python3 obj_build_from_yaml.py py_params_template.yaml fr1.sh -``` -- run the test (fr1.sh) - -At the date of writing, the test comprises the deployment of the components (epc, eNB, gNB, cots ue) and the execution of 2 pings procedures (20 pings in 20sec, then 5 pings in 1sec) - -This automation is run for every integration branch to be merged into develop. diff --git a/doc/nr-ue-design.md b/doc/nr-ue-design.md index 32abe6bd80..7ee42335d6 100644 --- a/doc/nr-ue-design.md +++ b/doc/nr-ue-design.md @@ -16,19 +16,20 @@ The UE exits when at any point in operation it gets out of synchronization. When ## Initial Synchronization Block ```mermaid graph TD - A(Start) -->|UE_thread| B["readFrame
--Reads samples worth 2 frames"] - B --> |Tpool thread| C["UE_synch
--PSS & SSS detection
--PBCH decode"] - B --> |UE_thread| D["readFrame
--trash samples to unblock radio"] - C --> |Tpool thread| E[syncInFrame
--shift first sample to start of frame] - D --> |UE_thread| E + start(Start) -->|UE_thread| rxRu["RU read
(Reads two frames)"] + rxRu --> |Tpool thread| sync["SSB detection
(PSS & SSS detection
PBCH decoding
SIB decoding)"] + rxRu --> |UE_thread| rxRuDummy["RU read
(Dummy read till sync detection to avoid buffer overflow at radio)"] + sync --> |Tpool thread| frameSync["Frame synchronization
(Shift received samples to align with frame)"] + rxRuDummy --> |UE_thread| frameSync ``` ## Regular Slot Processing ```mermaid graph TD - E[syncInFrame
--shift first sample to start of frame] -->|UE_thread| F["trx_read_func (slot n)"] - F --> |Tpool thread| G["processSlotTX (slot n+4)
--PUSCH encode
--PUCCH encode
--trx_write_func"] - F --> |UE_thread| H["UE_processing (slot n)
--PDCCH decode
--PDSCH decode"] - G --> |Tpool thread| I(Merge) - H --> |UE_thread| I(Merge) - I --> |Go to next slot
UE_thread| F + sync["Frame synchronization
(Shift received samples to align with frame)"] -->|UE_thread| hw_read["RU read (slot n)"] + hw_read --> |UE_thread| rxPreProc["PBCH & PDCCH decoding (slot n)"] + hw_read --> |Tpool thread| txProc["Tx processing (slot n+3)
PUSCH encode
PUCCH encode (wait for DLSCH in slot n+3-k1 to finish)
RU write"] + rxPreProc --> |Tpool thread| rxProc["PDSCH decoding (slot n)"] + rxPreProc --> |UE_thread| join(Merge) + txProc --> |Tpool thread| join + join --> |Go to next slot
UE_thread| hw_read ``` diff --git a/doc/testbenches_doc_resources/4g-faraday-bench.pdf b/doc/testbenches_doc_resources/4g-faraday-bench.pdf index f6f7b078e6..ad92b8410a 100644 Binary files a/doc/testbenches_doc_resources/4g-faraday-bench.pdf and b/doc/testbenches_doc_resources/4g-faraday-bench.pdf differ diff --git a/doc/testbenches_doc_resources/4g-faraday-bench.png b/doc/testbenches_doc_resources/4g-faraday-bench.png index 598715a193..094f8786dc 100644 Binary files a/doc/testbenches_doc_resources/4g-faraday-bench.png and b/doc/testbenches_doc_resources/4g-faraday-bench.png differ diff --git a/doc/testbenches_doc_resources/5g-nsa-faraday-bench.pdf b/doc/testbenches_doc_resources/5g-nsa-faraday-bench.pdf index 1b921e6437..dfa35a3dfe 100644 Binary files a/doc/testbenches_doc_resources/5g-nsa-faraday-bench.pdf and b/doc/testbenches_doc_resources/5g-nsa-faraday-bench.pdf differ diff --git a/doc/testbenches_doc_resources/5g-nsa-faraday-bench.png b/doc/testbenches_doc_resources/5g-nsa-faraday-bench.png index 006e6ab347..8df8cb9227 100644 Binary files a/doc/testbenches_doc_resources/5g-nsa-faraday-bench.png and b/doc/testbenches_doc_resources/5g-nsa-faraday-bench.png differ diff --git a/doc/testbenches_doc_resources/5g-nsa-faraday-bench.tex b/doc/testbenches_doc_resources/5g-nsa-faraday-bench.tex index a9f12fe3df..07b382222e 100644 --- a/doc/testbenches_doc_resources/5g-nsa-faraday-bench.tex +++ b/doc/testbenches_doc_resources/5g-nsa-faraday-bench.tex @@ -15,27 +15,24 @@ \node[faraday, label={[anchor=south east]above right:Faraday cage}] (faraday) {}; - \node[above left=0cm and 2.8cm of faraday, label=above:obelix] (obelix) + \node[above left=-0.50cm and 2.8cm of faraday, label=above:nepes] (nepes) {\includegraphics[width=1.2cm]{server}}; - \node[right=0.3cm of obelix, label=above:B200-mini] (b210o) - {\includegraphics[width=1.2cm]{b200-mini}} edge (obelix); + \node[right=0.3cm of nepes, label=above:B200-mini] (b210o) + {\includegraphics[width=1.2cm]{b200-mini}} edge (nepes); \node[below right=0.35cm of faraday.north west] (anto) {\includegraphics[width=0.3cm]{antenna}}; \draw (b210o) -| node [pos=0.2, duplexer] {B7} (anto); - \node[below left=0cm and 2.8cm of faraday, label=above:nepes] (nepes) + \node[below left=-0.50cm and 2.8cm of faraday, label=below:ofqot] (ofqot) {\includegraphics[width=1.2cm]{server}}; - \node[right=0.3cm of nepes, label=above:B200-mini] (b210n) - {\includegraphics[width=1.2cm]{b200-mini}} edge (nepes); - \draw (obelix) -- (b210o); + \node[right=0.3cm of ofqot, label=above:B200-mini] (b210n) + {\includegraphics[width=1.2cm]{b200-mini}} edge (ofqot); + \draw (nepes) -- (b210o); \node[above right=0.35cm of faraday.south west] (antn) {\includegraphics[width=0.3cm]{antenna}}; \draw (b210n) -| node [pos=0.2, duplexer] {n78} (antn); - \node[left=5cm of faraday, label=above:porcepix] (porcepix) - {\includegraphics[width=1.2cm]{server}}; - \draw (obelix) -- (porcepix); - \draw (nepes) -- (porcepix); + \draw (nepes) -- (ofqot); \node[right=1.5cm of faraday, label=above:RM500Q-GL] (quectel) {\includegraphics[height=1.2cm]{quectel}}; diff --git a/doc/testbenches_doc_resources/5g-ota-bench.pdf b/doc/testbenches_doc_resources/5g-ota-bench.pdf index 121969030e..4199a44166 100644 Binary files a/doc/testbenches_doc_resources/5g-ota-bench.pdf and b/doc/testbenches_doc_resources/5g-ota-bench.pdf differ diff --git a/doc/testbenches_doc_resources/5g-ota-bench.png b/doc/testbenches_doc_resources/5g-ota-bench.png index 86ae6b2b64..30309bf9f4 100644 Binary files a/doc/testbenches_doc_resources/5g-ota-bench.png and b/doc/testbenches_doc_resources/5g-ota-bench.png differ diff --git a/doc/testbenches_doc_resources/5g-ota-bench.tex b/doc/testbenches_doc_resources/5g-ota-bench.tex index c3a524fb0a..b7413af7db 100644 --- a/doc/testbenches_doc_resources/5g-ota-bench.tex +++ b/doc/testbenches_doc_resources/5g-ota-bench.tex @@ -16,7 +16,7 @@ \node[label=above:porcepix] (porcepix) {\includegraphics[width=1.2cm]{server}}; - \node[above right=1cm and 2cm of porcepix, label=above:asterix] (asterix) + \node[above right=-0.4cm and 2cm of porcepix, label=above:asterix] (asterix) {\includegraphics[width=1.2cm]{server}} edge (porcepix); \node[right=0.3cm of asterix, label=above:N310] (n310a) @@ -27,7 +27,7 @@ \node[above right=-0.1cm and 0.35cm of b78o.east] (anto2) {\includegraphics[width=0.3cm]{antenna}} edge (b78o); - \node[right=2cm of porcepix, label=above:obelix] (obelix) + \node[below right=-0.4cm and 2cm of porcepix, label=above:obelix] (obelix) {\includegraphics[width=1.2cm]{server}} edge (porcepix); \node[above right=-0.5cm and 0.3cm of obelix, label=above:N310] (n310o) @@ -45,7 +45,7 @@ \node[above right=-0.1cm and 0.35cm of b78o.east] (anto2) {\includegraphics[width=0.3cm]{antenna}} edge (b78o); - \node[above right=-1.3cm and 5.0cm of n310a.east, label=above:RM500Q-GL] (quectel) + \node[above right=-0.5cm and 5.0cm of n310o.east, label=above:RM500Q-GL] (quectel) {\includegraphics[height=1.2cm]{quectel}}; \node[above left=-0.1cm and 0.8cm of quectel.west] (aq2) {\includegraphics[width=0.3cm]{antenna}} edge (quectel); @@ -59,10 +59,5 @@ {\includegraphics[width=1.2cm]{server}} edge (quectel); - \node[above right=-0.3cm and 5.0cm of x310o.east, label=above:amariue] (amariue) - {\includegraphics[height=1.2cm]{server}}; - \node[left=0.8cm of amariue.west] (aa1) - {\includegraphics[width=0.3cm]{antenna}} edge (amariue); - \end{tikzpicture} \end{document} diff --git a/executables/lte-softmodem.c b/executables/lte-softmodem.c index 6d75f0acbd..371735110c 100644 --- a/executables/lte-softmodem.c +++ b/executables/lte-softmodem.c @@ -181,6 +181,21 @@ bool sdap_data_req(protocol_ctxt_t *ctxt_p, abort(); } +/* hack: gtp_itf.cpp requires this empty function to be defined here */ +bool nr_pdcp_data_req_drb(protocol_ctxt_t *ctxt_pP, + const srb_flag_t srb_flagP, + const rb_id_t rb_id, + const mui_t muiP, + const confirm_t confirmP, + const sdu_size_t sdu_buffer_size, + unsigned char *const sdu_buffer, + const pdcp_transmission_mode_t mode, + const uint32_t *const sourceL2Id, + const uint32_t *const destinationL2Id) +{ + abort(); +} + /* forward declarations */ void set_default_frame_parms(LTE_DL_FRAME_PARMS *frame_parms[MAX_NUM_CCs]); @@ -614,7 +629,7 @@ int main ( int argc, char **argv ) //getchar(); if(IS_SOFTMODEM_DOSCOPE) load_softscope("enb",NULL); - itti_wait_tasks_end(); + itti_wait_tasks_end(NULL); #if USING_GPROF // Save the gprof data now (rather than via atexit) in case we crash while shutting down diff --git a/executables/lte-uesoftmodem.c b/executables/lte-uesoftmodem.c index 4fe94f0b80..8e0161c1b6 100644 --- a/executables/lte-uesoftmodem.c +++ b/executables/lte-uesoftmodem.c @@ -699,7 +699,7 @@ int main( int argc, char **argv ) { printf("TYPE TO TERMINATE\n"); //getchar(); printf("Entering ITTI signals handler\n"); - itti_wait_tasks_end(); + itti_wait_tasks_end(NULL); printf("Returned from ITTI signal handler\n"); oai_exit=1; printf("oai_exit=%d\n",oai_exit); diff --git a/executables/nr-cuup.c b/executables/nr-cuup.c index 25ebe6df13..352eed9f4a 100644 --- a/executables/nr-cuup.c +++ b/executables/nr-cuup.c @@ -28,7 +28,7 @@ #include "nfapi/oai_integration/vendor_ext.h" #include "openair2/F1AP/f1ap_common.h" #include "openair2/GNB_APP/gnb_config.h" -#include "pdcp.h" +#include "nr_pdcp/nr_pdcp_oai_api.h" RAN_CONTEXT_t RC; THREAD_STRUCT thread_struct; @@ -147,13 +147,13 @@ int main(int argc, char **argv) AssertFatal(rc >= 0, "Create task for GTPV1U failed\n"); rc = itti_create_task(TASK_CUUP_E1, E1AP_CUUP_task, NULL); AssertFatal(rc >= 0, "Create task for CUUP E1 failed\n"); - pdcp_layer_init(); + nr_pdcp_layer_init(); MessageDef *msg = RCconfig_NR_CU_E1(true); AssertFatal(msg != NULL, "Send init to task for E1AP UP failed\n"); itti_send_msg_to_task(TASK_CUUP_E1, 0, msg); printf("TYPE TO TERMINATE\n"); - itti_wait_tasks_end(); + itti_wait_tasks_end(NULL); logClean(); printf("Bye.\n"); diff --git a/executables/nr-gnb.c b/executables/nr-gnb.c index 830e3d193b..d2cd85be59 100644 --- a/executables/nr-gnb.c +++ b/executables/nr-gnb.c @@ -51,6 +51,7 @@ #include "PHY/NR_TRANSPORT/nr_transport_proto.h" #include "PHY/MODULATION/nr_modulation.h" #include "PHY/NR_TRANSPORT/nr_dlsch.h" +#include "openair2/NR_PHY_INTERFACE/nr_sched_response.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 @@ -110,7 +111,8 @@ time_stats_t softmodem_stats_rx_sf; // total rx time #define L1STATSSTRLEN 16384 -void tx_func(void *param) { +void tx_func(void *param) +{ processingData_L1tx_t *info = (processingData_L1tx_t *) param; int frame_tx = info->frame; @@ -138,11 +140,14 @@ void tx_func(void *param) { LOG_D(PHY,"gNB: %d.%d : calling RU TX function\n",syncMsgRU.frame_tx,syncMsgRU.slot_tx); ru_tx_func((void*)&syncMsgRU); } + /* this thread is done with the sched_info, decrease the reference counter */ + deref_sched_response(info->sched_response_id); stop_meas(&info->gNB->phy_proc_tx); } -void *L1_rx_thread(void *arg) { +void *L1_rx_thread(void *arg) +{ PHY_VARS_gNB *gNB = (PHY_VARS_gNB*)arg; while (oai_exit == 0) { @@ -166,7 +171,8 @@ void *L1_tx_thread(void *arg) { return NULL; } */ -void rx_func(void *param) { +void rx_func(void *param) +{ processingData_L1_t *info = (processingData_L1_t *) param; PHY_VARS_gNB *gNB = info->gNB; int frame_rx = info->frame_rx; @@ -211,46 +217,11 @@ void rx_func(void *param) { T(T_GNB_PHY_DL_TICK, T_INT(gNB->Mod_id), T_INT(frame_tx), T_INT(slot_tx)); - /* hack to remove UEs */ - extern int rnti_to_remove[10]; - extern volatile int rnti_to_remove_count; - extern pthread_mutex_t rnti_to_remove_mutex; - if (pthread_mutex_lock(&rnti_to_remove_mutex)) exit(1); - int up_removed = 0; - int down_removed = 0; - int pucch_removed = 0; - for (int i = 0; i < rnti_to_remove_count; i++) { - LOG_W(NR_PHY, "to remove rnti 0x%04x\n", rnti_to_remove[i]); - void clean_gNB_ulsch(NR_gNB_ULSCH_t *ulsch); - void clean_gNB_dlsch(NR_gNB_DLSCH_t *dlsch); - int j; - for (j = 0; j < NUMBER_OF_NR_ULSCH_MAX; j++) - if (gNB->ulsch[j]->rnti == rnti_to_remove[i]) { - gNB->ulsch[j]->rnti = 0; - gNB->ulsch[j]->harq_mask = 0; - int h; - for (h = 0; h < NR_MAX_ULSCH_HARQ_PROCESSES; h++) { - gNB->ulsch[j]->harq_processes[h]->status = NR_SCH_IDLE; - gNB->ulsch[j]->harq_processes[h]->round = 0; - gNB->ulsch[j]->harq_processes[h]->handled = 0; - } - up_removed++; - } - - for (j = 0; j < gNB->max_nb_pucch; j++) - if (gNB->pucch[j]->active > 0 && - gNB->pucch[j]->pucch_pdu.rnti == rnti_to_remove[i]) { - gNB->pucch[j]->active = 0; - gNB->pucch[j]->pucch_pdu.rnti = 0; - pucch_removed++; - } - } - if (rnti_to_remove_count) LOG_W(NR_PHY, "to remove rnti_to_remove_count=%d, up_removed=%d down_removed=%d pucch_removed=%d\n", rnti_to_remove_count, up_removed, down_removed, pucch_removed); - rnti_to_remove_count = 0; - if (pthread_mutex_unlock(&rnti_to_remove_mutex)) exit(1); + reset_active_stats(gNB, frame_tx); + reset_active_ulsch(gNB, frame_tx); // RX processing - int rx_slot_type = nr_slot_select(cfg,frame_rx,slot_rx); + int rx_slot_type = nr_slot_select(cfg, frame_rx, slot_rx); if (rx_slot_type == NR_UPLINK_SLOT || rx_slot_type == NR_MIXED_SLOT) { // UE-specific RX processing for subframe n // TODO: check if this is correct for PARALLEL_RU_L1_TRX_SPLIT diff --git a/executables/nr-ru.c b/executables/nr-ru.c index 33c58cc973..4017c8e9ac 100644 --- a/executables/nr-ru.c +++ b/executables/nr-ru.c @@ -332,7 +332,9 @@ void fh_if5_south_in(RU_t *ru, if (proc->first_rx == 0) { if (proc->tti_rx != *tti) { LOG_E(PHY,"Received Timestamp doesn't correspond to the time we think it is (proc->tti_rx %d, subframe %d)\n",proc->tti_rx,*tti); - exit_fun("Exiting"); + if (!oai_exit) + exit_fun("Exiting"); + return; } if (proc->frame_rx != *frame) { diff --git a/executables/nr-softmodem.c b/executables/nr-softmodem.c index 120a7c0e65..13ea4b94ee 100644 --- a/executables/nr-softmodem.c +++ b/executables/nr-softmodem.c @@ -59,7 +59,7 @@ unsigned short config_frames[4] = {2,9,11,13}; #include "common/utils/LOG/log.h" #include "common/utils/LOG/vcd_signal_dumper.h" #include "UTIL/OPT/opt.h" -#include "pdcp.h" +#include "LAYER2/nr_pdcp/nr_pdcp_oai_api.h" #include "intertask_interface.h" @@ -176,6 +176,12 @@ openair0_config_t openair0_cfg[MAX_CARDS]; double cpuf; +/* hack: pdcp_run() is required by 4G scheduler which is compiled into + * nr-softmodem because of linker issues */ +void pdcp_run(const protocol_ctxt_t *const ctxt_pP) +{ + abort(); +} /* see file openair2/LAYER2/MAC/main.c for why abstraction_flag is needed * this is very hackish - find a proper solution @@ -556,13 +562,8 @@ void init_pdcp(void) { PDCP_USE_NETLINK_BIT | LINK_ENB_PDCP_TO_IP_DRIVER_BIT | ENB_NAS_USE_TUN_BIT | SOFTMODEM_NOKRNMOD_BIT: LINK_ENB_PDCP_TO_GTPV1U_BIT; - if (!get_softmodem_params()->nsa) { - if (!NODE_IS_DU(get_node_type())) { - pdcp_layer_init(); - nr_pdcp_module_init(pdcp_initmask, 0); - } - } else { - pdcp_layer_init(); + if (!NODE_IS_DU(get_node_type())) { + nr_pdcp_layer_init(); nr_pdcp_module_init(pdcp_initmask, 0); } } @@ -733,7 +734,7 @@ int main( int argc, char **argv ) { // wait for end of program printf("Entering ITTI signals handler\n"); printf("TYPE TO TERMINATE\n"); - itti_wait_tasks_end(); + itti_wait_tasks_end(NULL); printf("Returned from ITTI signal handler\n"); oai_exit=1; printf("oai_exit=%d\n",oai_exit); diff --git a/executables/nr-ue.c b/executables/nr-ue.c index 075789e12b..4024075651 100644 --- a/executables/nr-ue.c +++ b/executables/nr-ue.c @@ -33,7 +33,7 @@ #include "executables/softmodem-common.h" #include "PHY/NR_REFSIG/refsig_defs_ue.h" #include "radio/COMMON/common_lib.h" -#include "pdcp.h" +#include "LAYER2/nr_pdcp/nr_pdcp_oai_api.h" /* * NR SLOT PROCESSING SEQUENCE @@ -157,6 +157,7 @@ void init_nr_ue_vars(PHY_VARS_NR_UE *ue, ue->mac_enabled = 1; ue->if_inst = nr_ue_if_module_init(0); ue->dci_thres = 0; + ue->target_Nid_cell = -1; // initialize all signal buffers init_nr_ue_signal(ue, nb_connected_gNB); @@ -202,6 +203,7 @@ static void process_queued_nr_nfapi_msgs(NR_UE_MAC_INST_t *mac, int sfn_slot) nfapi_nr_ul_tti_request_t *ul_tti_request_crc = unqueue_matching(&nr_ul_tti_req_queue, MAX_QUEUE_SIZE, sfn_slot_matcher, &mac->nr_ue_emul_l1.harq[i].active_ul_harq_sfn_slot); if (ul_tti_request_crc && ul_tti_request_crc->n_pdus > 0) { check_and_process_dci(NULL, NULL, NULL, ul_tti_request_crc); + free_and_zero(ul_tti_request_crc); } } @@ -231,6 +233,8 @@ static void process_queued_nr_nfapi_msgs(NR_UE_MAC_INST_t *mac, int sfn_slot) if (get_softmodem_params()->nsa) save_nr_measurement_info(dl_tti_request); check_and_process_dci(dl_tti_request, tx_data_request, NULL, NULL); + free_and_zero(dl_tti_request); + free_and_zero(tx_data_request); } else { AssertFatal(false, "We dont have PDUs in either dl_tti %d or tx_req %d\n", @@ -239,6 +243,7 @@ static void process_queued_nr_nfapi_msgs(NR_UE_MAC_INST_t *mac, int sfn_slot) } if (ul_dci_request && ul_dci_request->numPdus > 0) { check_and_process_dci(NULL, NULL, ul_dci_request, NULL); + free_and_zero(ul_dci_request); } } @@ -323,14 +328,6 @@ static void *NRUE_phy_stub_standalone_pnf_task(void *arg) if (pthread_mutex_lock(&mac->mutex_dl_info)) abort(); - memset(&mac->dl_info, 0, sizeof(mac->dl_info)); - mac->dl_info.cc_id = CC_id; - mac->dl_info.gNB_index = gNB_id; - mac->dl_info.module_id = mod_id; - mac->dl_info.frame = frame; - mac->dl_info.slot = slot; - mac->dl_info.dci_ind = NULL; - mac->dl_info.rx_ind = NULL; if (ch_info) { mac->nr_ue_emul_l1.pmi = ch_info->csi[0].pmi; mac->nr_ue_emul_l1.ri = ch_info->csi[0].ri; @@ -342,6 +339,14 @@ static void *NRUE_phy_stub_standalone_pnf_task(void *arg) mac->scc->tdd_UL_DL_ConfigurationCommon : mac->scc_SIB->tdd_UL_DL_ConfigurationCommon, ul_info.slot_rx)) { + memset(&mac->dl_info, 0, sizeof(mac->dl_info)); + mac->dl_info.cc_id = CC_id; + mac->dl_info.gNB_index = gNB_id; + mac->dl_info.module_id = mod_id; + mac->dl_info.frame = frame; + mac->dl_info.slot = slot; + mac->dl_info.dci_ind = NULL; + mac->dl_info.rx_ind = NULL; nr_ue_dl_indication(&mac->dl_info, &ul_time_alignment); } @@ -355,12 +360,6 @@ static void *NRUE_phy_stub_standalone_pnf_task(void *arg) nr_ue_ul_scheduler(&ul_info); nr_ue_pucch_scheduler(mod_id, ul_info.frame_tx, ul_info.slot_tx, NULL); } - if (!IS_SOFTMODEM_NOS1 && get_softmodem_params()->sa) { - NR_UE_MAC_INST_t *mac = get_mac_inst(0); - protocol_ctxt_t ctxt; - PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, 0, ENB_FLAG_NO, mac->crnti, frame, slot, 0); - pdcp_run(&ctxt); - } process_queued_nr_nfapi_msgs(mac, sfn_slot); } return NULL; @@ -413,7 +412,11 @@ static void UE_synch(void *arg) { */ } - LOG_W(PHY, "Starting sync detection\n"); + if (UE->target_Nid_cell != -1) { + LOG_W(NR_PHY, "Starting re-sync detection for target Nid_cell %i\n", UE->target_Nid_cell); + } else { + LOG_W(NR_PHY, "Starting sync detection\n"); + } switch (sync_mode) { /* @@ -447,7 +450,7 @@ static void UE_synch(void *arg) { break; */ case pbch: - LOG_I(PHY, "[UE thread Synch] Running Initial Synch (mode %d)\n",UE->mode); + LOG_I(PHY, "[UE thread Synch] Running Initial Synch \n"); uint64_t dl_carrier, ul_carrier; nr_get_carrier_frequencies(UE, &dl_carrier, &ul_carrier); @@ -564,6 +567,12 @@ void processSlotTX(void *arg) { LOG_D(PHY,"%d.%d => slot type %d\n", proc->frame_tx, proc->nr_slot_tx, proc->tx_slot_type); if (proc->tx_slot_type == NR_UPLINK_SLOT || proc->tx_slot_type == NR_MIXED_SLOT){ + // wait for rx slots to send indication (if any) that DLSCH decoding is finished + for(int i=0; i < rxtxD->tx_wait_for_dlsch; i++) { + notifiedFIFO_elt_t *res = pullNotifiedFIFO(UE->tx_resume_ind_fifo[proc->nr_slot_tx]); + delNotifiedFIFO_elt(res); + } + // 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) { @@ -590,13 +599,22 @@ void processSlotTX(void *arg) { RU_write(rxtxD); } -void UE_processing(nr_rxtx_thread_data_t *rxtxD) { +nr_phy_data_t UE_dl_preprocessing(PHY_VARS_NR_UE *UE, UE_nr_rxtx_proc_t *proc) { - UE_nr_rxtx_proc_t *proc = &rxtxD->proc; - PHY_VARS_NR_UE *UE = rxtxD->UE; nr_phy_data_t phy_data = {0}; if (IS_SOFTMODEM_NOS1 || get_softmodem_params()->sa) { + + // Start synchronization with a target gNB + if (UE->synch_request.received_synch_request == 1 && UE->target_Nid_cell == -1) { + UE->is_synchronized = 0; + UE->target_Nid_cell = UE->synch_request.synch_req.target_Nid_cell; + clean_UE_ulsch(UE, proc->gNB_id); + } else if (UE->synch_request.received_synch_request == 1 && UE->target_Nid_cell != -1) { + UE->synch_request.received_synch_request = 0; + UE->target_Nid_cell = -1; + } + /* send tick to RLC and PDCP every ms */ if (proc->nr_slot_rx % UE->frame_parms.slots_per_subframe == 0) { void nr_rlc_tick(int frame, int subframe); @@ -614,24 +632,28 @@ void UE_processing(nr_rxtx_thread_data_t *rxtxD) { 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, no_relay, NULL ); -#else uint64_t a=rdtsc_oai(); - phy_procedures_nrUE_RX(UE, proc, &phy_data); - LOG_D(PHY, "In %s: slot %d, time %llu\n", __FUNCTION__, proc->nr_slot_rx, (rdtsc_oai()-a)/3500); -#endif - - if(IS_SOFTMODEM_NOS1 || get_softmodem_params()->sa){ - NR_UE_MAC_INST_t *mac = get_mac_inst(0); - protocol_ctxt_t ctxt; - PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, UE->Mod_id, ENB_FLAG_NO, mac->crnti, proc->frame_rx, proc->nr_slot_rx, 0); - pdcp_run(&ctxt); + pbch_pdcch_processing(UE, proc, &phy_data); + if (phy_data.dlsch[0].active) { + // indicate to tx thread to wait for DLSCH decoding + const int ack_nack_slot = (proc->nr_slot_rx + phy_data.dlsch[0].dlsch_config.k1_feedback) % UE->frame_parms.slots_per_frame; + UE->tx_wait_for_dlsch[ack_nack_slot]++; } + + LOG_D(PHY, "In %s: slot %d, time %llu\n", __FUNCTION__, proc->nr_slot_rx, (rdtsc_oai()-a)/3500); } ue_ta_procedures(UE, proc->nr_slot_tx, proc->frame_tx); + return phy_data; +} + +void UE_dl_processing(void *arg) { + nr_rxtx_thread_data_t *rxtxD = (nr_rxtx_thread_data_t *) arg; + UE_nr_rxtx_proc_t *proc = &rxtxD->proc; + PHY_VARS_NR_UE *UE = rxtxD->UE; + nr_phy_data_t *phy_data = &rxtxD->phy_data; + + pdsch_processing(UE, proc, phy_data); } void dummyWrite(PHY_VARS_NR_UE *UE,openair0_timestamp timestamp, int writeBlockSize) { @@ -685,7 +707,7 @@ void readFrame(PHY_VARS_NR_UE *UE, openair0_timestamp *timestamp, bool toTrash) void syncInFrame(PHY_VARS_NR_UE *UE, openair0_timestamp *timestamp) { - LOG_I(PHY,"Resynchronizing RX by %d samples (mode = %d)\n",UE->rx_offset,UE->mode); + LOG_I(PHY,"Resynchronizing RX by %d samples\n",UE->rx_offset); if (IS_SOFTMODEM_IQPLAYER || IS_SOFTMODEM_IQRECORDER) { // Resynchonize by slot (will work with numerology 1 only) @@ -752,7 +774,6 @@ void *UE_thread(void *arg) { fapi_nr_config_request_t *cfg = &UE->nrUE_config; AssertFatal(0== openair0_device_load(&(UE->rfdevice), &openair0_cfg[0]), ""); UE->rfdevice.host_type = RAU_HOST; - UE->lost_sync = 0; UE->is_synchronized = 0; AssertFatal(UE->rfdevice.trx_start_func(&UE->rfdevice) == 0, "Could not start the device\n"); @@ -771,12 +792,16 @@ void *UE_thread(void *arg) { bool syncRunning=false; const int nb_slot_frame = UE->frame_parms.slots_per_frame; int absolute_slot=0, decoded_frame_rx=INT_MAX, trashed_frames=0; + initNotifiedFIFO(&UE->phy_config_ind); + + int num_ind_fifo = nb_slot_frame; + for(int i=0; i < num_ind_fifo; i++) { + UE->tx_wait_for_dlsch[num_ind_fifo] = 0; + UE->tx_resume_ind_fifo[i] = malloc(sizeof(*UE->tx_resume_ind_fifo[i])); + initNotifiedFIFO(UE->tx_resume_ind_fifo[i]); + } while (!oai_exit) { - if (UE->lost_sync) { - UE->is_synchronized = 0; - UE->lost_sync = 0; - } if (syncRunning) { notifiedFIFO_elt_t *res=tryPullTpool(&nf,&(get_nrUE_params()->Tpool)); @@ -793,6 +818,11 @@ void *UE_thread(void *arg) { decoded_frame_rx=(((mac->mib->systemFrameNumber.buf[0] >> mac->mib->systemFrameNumber.bits_unused)<<4) | tmp->proc.decoded_frame_rx); // shift the frame index with all the frames we trashed meanwhile we perform the synch search decoded_frame_rx=(decoded_frame_rx + UE->init_sync_frame + trashed_frames) % MAX_FRAME_NUMBER; + // wait for RRC to configure PHY parameters from SIB + if (get_softmodem_params()->sa) { + notifiedFIFO_elt_t *phy_config_res = pullNotifiedFIFO(&UE->phy_config_ind); + delNotifiedFIFO_elt(phy_config_res); + } } delNotifiedFIFO_elt(res); start_rx_stream=0; @@ -815,13 +845,13 @@ void *UE_thread(void *arg) { if (!UE->is_synchronized) { readFrame(UE, ×tamp, false); - notifiedFIFO_elt_t *Msg=newNotifiedFIFO_elt(sizeof(syncData_t),0,&nf,UE_synch); - syncData_t *syncMsg=(syncData_t *)NotifiedFifoData(Msg); - syncMsg->UE=UE; + notifiedFIFO_elt_t *Msg = newNotifiedFIFO_elt(sizeof(syncData_t), 0, &nf, UE_synch); + syncData_t *syncMsg = (syncData_t *)NotifiedFifoData(Msg); + syncMsg->UE = UE; memset(&syncMsg->proc, 0, sizeof(syncMsg->proc)); pushTpool(&(get_nrUE_params()->Tpool), Msg); - trashed_frames=0; - syncRunning=true; + trashed_frames = 0; + syncRunning = true; continue; } @@ -930,15 +960,22 @@ void *UE_thread(void *arg) { curMsgTx->writeBlockSize = writeBlockSize; curMsgTx->proc.timestamp_tx = writeTimestamp; curMsgTx->UE = UE; + curMsgTx->tx_wait_for_dlsch = UE->tx_wait_for_dlsch[curMsgTx->proc.nr_slot_tx]; + UE->tx_wait_for_dlsch[curMsgTx->proc.nr_slot_tx] = 0; pushTpool(&(get_nrUE_params()->Tpool), newElt); - // RX slot processing - UE_processing(&curMsg); + // RX slot processing. We launch and forget. + newElt = newNotifiedFIFO_elt(sizeof(nr_rxtx_thread_data_t), curMsg.proc.nr_slot_rx, NULL, UE_dl_processing); + nr_rxtx_thread_data_t *curMsgRx = (nr_rxtx_thread_data_t *) NotifiedFifoData(newElt); + curMsgRx->proc = curMsg.proc; + curMsgRx->UE = UE; + curMsgRx->phy_data = UE_dl_preprocessing(UE, &curMsg.proc); + pushTpool(&(get_nrUE_params()->Tpool), newElt); if (curMsg.proc.decoded_frame_rx != -1) decoded_frame_rx=(((mac->mib->systemFrameNumber.buf[0] >> mac->mib->systemFrameNumber.bits_unused)<<4) | curMsg.proc.decoded_frame_rx); else - decoded_frame_rx=-1; + decoded_frame_rx=-1; if (decoded_frame_rx>0 && decoded_frame_rx != curMsg.proc.frame_rx) LOG_E(PHY,"Decoded frame index (%d) is not compatible with current context (%d), UE should go back to synch mode\n", diff --git a/executables/nr-uesoftmodem.c b/executables/nr-uesoftmodem.c index eb6e160ec3..8bf0f6efec 100644 --- a/executables/nr-uesoftmodem.c +++ b/executables/nr-uesoftmodem.c @@ -22,6 +22,8 @@ #define _GNU_SOURCE /* See feature_test_macros(7) */ #include +#include +#include #include "T.h" #include "assertions.h" @@ -59,7 +61,7 @@ unsigned short config_frames[4] = {2,9,11,13}; #include "UTIL/OPT/opt.h" #include "enb_config.h" -#include "pdcp.h" +#include "LAYER2/nr_pdcp/nr_pdcp_oai_api.h" #include "intertask_interface.h" @@ -211,6 +213,11 @@ int create_tasks_nrue(uint32_t ue_nb) { } itti_wait_ready(0); + + // Thread to update the RRC timers (in msec) at UE + pthread_t timers_update; + threadCreate(&timers_update, nr_rrc_timers_update, NULL, "nr_rrc_timer_update", -1, OAI_PRIORITY_RT_LOW); + return 0; } @@ -257,7 +264,6 @@ static void get_options(void) { paramdef_t cmdline_params[] =CMDLINE_NRUEPARAMS_DESC ; int numparams = sizeof(cmdline_params)/sizeof(paramdef_t); config_get(cmdline_params,numparams,NULL); - config_process_cmdline( cmdline_params,numparams,NULL); if (vcdflag > 0) ouput_vcd = 1; @@ -265,38 +271,7 @@ static void get_options(void) { // set PHY vars from command line void set_options(int CC_id, PHY_VARS_NR_UE *UE){ - NR_DL_FRAME_PARMS *fp = &UE->frame_parms; - paramdef_t cmdline_params[] = CMDLINE_NRUE_PHYPARAMS_DESC ; - int numparams = sizeof(cmdline_params)/sizeof(paramdef_t); - - UE->mode = normal_txrx; - - config_get(cmdline_params,numparams,NULL); - - int pindex = config_paramidx_fromname(cmdline_params,numparams, CALIBRX_OPT); - if ( (cmdline_params[pindex].paramflags & PARAMFLAG_PARAMSET) != 0) UE->mode = rx_calib_ue; - - pindex = config_paramidx_fromname(cmdline_params,numparams, CALIBRXMED_OPT); - if ( (cmdline_params[pindex].paramflags & PARAMFLAG_PARAMSET) != 0) UE->mode = rx_calib_ue_med; - - pindex = config_paramidx_fromname(cmdline_params,numparams, CALIBRXBYP_OPT); - if ( (cmdline_params[pindex].paramflags & PARAMFLAG_PARAMSET) != 0) UE->mode = rx_calib_ue_byp; - - pindex = config_paramidx_fromname(cmdline_params,numparams, DBGPRACH_OPT); - if (cmdline_params[pindex].uptr) - if ( *(cmdline_params[pindex].uptr) > 0) UE->mode = debug_prach; - - pindex = config_paramidx_fromname(cmdline_params,numparams,NOL2CONNECT_OPT ); - if (cmdline_params[pindex].uptr) - if ( *(cmdline_params[pindex].uptr) > 0) UE->mode = no_L2_connect; - - pindex = config_paramidx_fromname(cmdline_params,numparams,CALIBPRACH_OPT ); - if (cmdline_params[pindex].uptr) - if ( *(cmdline_params[pindex].uptr) > 0) UE->mode = calib_prach_tx; - - pindex = config_paramidx_fromname(cmdline_params,numparams,DUMPFRAME_OPT ); - if ((cmdline_params[pindex].paramflags & PARAMFLAG_PARAMSET) != 0) - UE->mode = rx_dump_frame; + NR_DL_FRAME_PARMS *fp = &UE->frame_parms; // Init power variables tx_max_power[CC_id] = tx_max_power[0]; @@ -309,9 +284,18 @@ void set_options(int CC_id, PHY_VARS_NR_UE *UE){ UE->tx_power_max_dBm = tx_max_power[CC_id]; UE->rf_map.card = card_offset; UE->rf_map.chain = CC_id + chain_offset; + UE->max_ldpc_iterations = nrUE_params.max_ldpc_iterations; + UE->UE_scan_carrier = nrUE_params.UE_scan_carrier; + UE->UE_fo_compensation = nrUE_params.UE_fo_compensation; + UE->if_freq = nrUE_params.if_freq; + UE->if_freq_off = nrUE_params.if_freq_off; + UE->chest_freq = nrUE_params.chest_freq; + UE->chest_time = nrUE_params.chest_time; + UE->no_timing_correction = nrUE_params.no_timing_correction; + UE->timing_advance = nrUE_params.timing_advance; - LOG_I(PHY,"Set UE mode %d, UE_fo_compensation %d, UE_scan_carrier %d, UE_no_timing_correction %d \n, chest-freq %d\n", - UE->mode, UE->UE_fo_compensation, UE->UE_scan_carrier, UE->no_timing_correction, UE->chest_freq); + LOG_I(PHY,"Set UE_fo_compensation %d, UE_scan_carrier %d, UE_no_timing_correction %d \n, chest-freq %d, chest-time %d\n", + UE->UE_fo_compensation, UE->UE_scan_carrier, UE->no_timing_correction, UE->chest_freq, UE->chest_time); // Set FP variables @@ -320,10 +304,14 @@ void set_options(int CC_id, PHY_VARS_NR_UE *UE){ LOG_I(PHY, "Set UE frame_type %d\n", fp->frame_type); } - LOG_I(PHY, "Set UE nb_rx_antenna %d, nb_tx_antenna %d, threequarter_fs %d, ssb_start_subcarrier %d\n", fp->nb_antennas_rx, fp->nb_antennas_tx, fp->threequarter_fs, fp->ssb_start_subcarrier); + fp->nb_antennas_rx = nrUE_params.nb_antennas_rx; + fp->nb_antennas_tx = nrUE_params.nb_antennas_tx; + fp->threequarter_fs = nrUE_params.threequarter_fs; + fp->N_RB_DL = nrUE_params.N_RB_DL; + fp->ssb_start_subcarrier = nrUE_params.ssb_start_subcarrier; + fp->ofdm_offset_divisor = nrUE_params.ofdm_offset_divisor; - fp->ofdm_offset_divisor = nrUE_params.ofdm_offset_divisor; - UE->max_ldpc_iterations = nrUE_params.max_ldpc_iterations; + LOG_I(PHY, "Set UE nb_rx_antenna %d, nb_tx_antenna %d, threequarter_fs %d, ssb_start_subcarrier %d\n", fp->nb_antennas_rx, fp->nb_antennas_tx, fp->threequarter_fs, fp->ssb_start_subcarrier); } @@ -386,7 +374,7 @@ static void init_pdcp(int ue_id) { if (get_softmodem_params()->nsa && rlc_module_init(0) != 0) { LOG_I(RLC, "Problem at RLC initiation \n"); } - pdcp_layer_init(); + nr_pdcp_layer_init(); nr_pdcp_module_init(pdcp_initmask, ue_id); pdcp_set_rlc_data_req_func((send_rlc_data_req_func_t) rlc_data_req); pdcp_set_pdcp_data_ind_func((pdcp_data_ind_func_t) pdcp_data_ind); @@ -397,6 +385,27 @@ void *rrc_enb_process_msg(void *notUsed) { return NULL; } +static bool stop_immediately = false; +static void trigger_stop(int sig) +{ + if (!oai_exit) + itti_wait_tasks_unblock(); +} +static void trigger_deregistration(int sig) +{ + if (!stop_immediately) { + MessageDef *msg = itti_alloc_new_message(TASK_RRC_UE_SIM, 0, NAS_DEREGISTRATION_REQ); + itti_send_msg_to_task(TASK_NAS_NRUE, 0, msg); + stop_immediately = true; + static const char m[] = "Press ^C again to trigger immediate shutdown\n"; + __attribute__((unused)) int unused = write(STDOUT_FILENO, m, sizeof(m) - 1); + signal(SIGALRM, trigger_stop); + alarm(5); + } else { + itti_wait_tasks_unblock(); + } +} + static void get_channel_model_mode() { paramdef_t GNBParams[] = GNBPARAMS_DESC; config_get(GNBParams, sizeof(GNBParams)/sizeof(paramdef_t), NULL); @@ -426,7 +435,7 @@ int main( int argc, char **argv ) { if ( load_configmodule(argc,argv,CONFIG_ENABLECMDLINEONLY) == NULL) { exit_fun("[SOFTMODEM] Error, configuration module init failed\n"); } - set_softmodem_sighandler(); + //set_softmodem_sighandler(); CONFIG_SETRTFLAG(CONFIG_NOEXITONHELP); memset(openair0_cfg,0,sizeof(openair0_config_t)*MAX_CARDS); memset(tx_max_power,0,sizeof(int)*MAX_NUM_CCs); @@ -550,15 +559,28 @@ int main( int argc, char **argv ) { // Sleep a while before checking all parameters have been used // Some are used directly in external threads, asynchronously - sleep(20); + sleep(2); config_check_unknown_cmdlineopt(CONFIG_CHECKALLSECTIONS); - while(true) - sleep(3600); + // wait for end of program + printf("Entering ITTI signals handler\n"); + printf("TYPE TO TERMINATE\n"); + itti_wait_tasks_end(trigger_deregistration); + printf("Returned from ITTI signal handler\n"); + oai_exit=1; + printf("oai_exit=%d\n",oai_exit); if (ouput_vcd) vcd_signal_dumper_close(); + if (PHY_vars_UE_g && PHY_vars_UE_g[0]) { + for (int CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) { + PHY_VARS_NR_UE *phy_vars = PHY_vars_UE_g[0][CC_id]; + if (phy_vars && phy_vars->rfdevice.trx_end_func) + phy_vars->rfdevice.trx_end_func(&phy_vars->rfdevice); + } + } + return 0; } diff --git a/executables/nr-uesoftmodem.h b/executables/nr-uesoftmodem.h index 60b9d91f72..99c97eae28 100644 --- a/executables/nr-uesoftmodem.h +++ b/executables/nr-uesoftmodem.h @@ -36,54 +36,51 @@ {"single-thread-disable", CONFIG_HLP_NOSNGLT, PARAMFLAG_BOOL, .iptr=&single_thread_flag, .defintval=1, TYPE_INT, 0}, \ {"dlsch-parallel", CONFIG_HLP_DLSCH_PARA, 0, .u8ptr=NULL, .defintval=0, TYPE_UINT8, 0}, \ {"offset-divisor", CONFIG_HLP_OFFSET_DIV, 0, .uptr=&nrUE_params.ofdm_offset_divisor, .defuintval=8, TYPE_UINT32, 0}, \ - {"max-ldpc-iterations", CONFIG_HLP_MAX_LDPC_ITERATIONS, 0, .u8ptr=&nrUE_params.max_ldpc_iterations, .defuintval=5, TYPE_UINT8, 0}, \ + {"max-ldpc-iterations", CONFIG_HLP_MAX_LDPC_ITERATIONS, 0, .iptr=&nrUE_params.max_ldpc_iterations, .defuintval=5, TYPE_UINT8, 0}, \ {"nr-dlsch-demod-shift", CONFIG_HLP_DLSHIFT, 0, .iptr=(int32_t *)&nr_dlsch_demod_shift, .defintval=0, TYPE_INT, 0}, \ {"V" , CONFIG_HLP_VCD, PARAMFLAG_BOOL, .iptr=&vcdflag, .defintval=0, TYPE_INT, 0}, \ {"uecap_file", CONFIG_HLP_UECAP_FILE, 0, .strptr=&uecap_file, .defstrval="./uecap_ports1.xml", TYPE_STRING, 0}, \ {"rrc_config_path", CONFIG_HLP_RRC_CFG_PATH, 0, .strptr=&rrc_config_path, .defstrval="./", TYPE_STRING, 0}, \ - {"ue-idx-standalone", NULL, 0, .u16ptr=&ue_idx_standalone, .defuintval=0xFFFF, TYPE_UINT16, 0} \ -} -// clang-format on - -/*------------------------------------------------------------------------------------------------------------------------------------------*/ -/* command line parameters defining UE running mode */ -/* optname helpstr paramflags XXXptr defXXXval type numelt */ -/*------------------------------------------------------------------------------------------------------------------------------------------*/ -// clang-format off -#define CMDLINE_NRUE_PHYPARAMS_DESC { \ - { CALIBRX_OPT, CONFIG_HLP_CALUER, 0, .iptr=&rx_input_level_dBm, .defintval=0, TYPE_INT, 0}, \ - { CALIBRXMED_OPT, CONFIG_HLP_CALUERM, 0, .iptr=&rx_input_level_dBm, .defintval=0, TYPE_INT, 0}, \ - { CALIBRXBYP_OPT, CONFIG_HLP_CALUERB, 0, .iptr=&rx_input_level_dBm, .defintval=0, TYPE_INT, 0}, \ - { DBGPRACH_OPT, CONFIG_HLP_DBGUEPR, PARAMFLAG_BOOL, .uptr=NULL, .defuintval=1, TYPE_INT, 0}, \ - { NOL2CONNECT_OPT, CONFIG_HLP_NOL2CN, PARAMFLAG_BOOL, .uptr=NULL, .defuintval=1, TYPE_INT, 0}, \ - { CALIBPRACH_OPT, CONFIG_HLP_CALPRACH, PARAMFLAG_BOOL, .uptr=NULL, .defuintval=1, TYPE_INT, 0}, \ - { DUMPFRAME_OPT, CONFIG_HLP_DUMPFRAME, PARAMFLAG_BOOL, .iptr=&dumpframe, .defintval=0, TYPE_INT, 0}, \ + {"ue-idx-standalone", NULL, 0, .u16ptr=&ue_idx_standalone, .defuintval=0xFFFF, TYPE_UINT16, 0}, \ {"ue-rxgain", CONFIG_HLP_UERXG, 0, .dblptr=&(rx_gain[0][0]), .defdblval=110, 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-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-nb-ant-rx", CONFIG_HLP_UENANTR, 0, .iptr=&(nrUE_params.nb_antennas_rx), .defuintval=1, TYPE_UINT8, 0}, \ + {"ue-nb-ant-tx", CONFIG_HLP_UENANTT, 0, .iptr=&(nrUE_params.nb_antennas_tx), .defuintval=1, TYPE_UINT8, 0}, \ + {"ue-scan-carrier", CONFIG_HLP_UESCAN, PARAMFLAG_BOOL, .iptr=&(nrUE_params.UE_scan_carrier), .defintval=0, TYPE_INT, 0}, \ + {"ue-fo-compensation", CONFIG_HLP_UEFO, PARAMFLAG_BOOL, .iptr=&(nrUE_params.UE_fo_compensation), .defintval=0, TYPE_INT, 0}, \ {"ue-max-power", NULL, 0, .iptr=&(tx_max_power[0]), .defintval=90, 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}, \ - {"r" , CONFIG_HLP_PRB_SA, 0, .iptr=&(fp->N_RB_DL), .defintval=106, TYPE_UINT, 0}, \ - {"ssb", CONFIG_HLP_SSC, 0, .u16ptr=&(fp->ssb_start_subcarrier), .defintval=516, TYPE_UINT16, 0}, \ + {"A" , CONFIG_HLP_TADV, 0, .iptr=&(nrUE_params.timing_advance), .defintval=0, TYPE_INT, 0}, \ + {"E" , CONFIG_HLP_TQFS, PARAMFLAG_BOOL, .iptr=&(nrUE_params.threequarter_fs), .defintval=0, TYPE_UINT8, 0}, \ + {"r" , CONFIG_HLP_PRB_SA, 0, .iptr=&(nrUE_params.N_RB_DL), .defintval=106, TYPE_UINT, 0}, \ + {"ssb", CONFIG_HLP_SSC, 0, .iptr=&(nrUE_params.ssb_start_subcarrier), .defintval=516, TYPE_UINT16, 0}, \ {"T" , CONFIG_HLP_TDD, PARAMFLAG_BOOL, .iptr=&tddflag, .defintval=0, TYPE_INT, 0}, \ - {"if_freq" , CONFIG_HLP_IF_FREQ, 0, .u64ptr=&(UE->if_freq), .defuintval=0, TYPE_UINT64, 0}, \ - {"if_freq_off" , CONFIG_HLP_IF_FREQ_OFF, 0, .iptr=&(UE->if_freq_off), .defuintval=0, TYPE_INT, 0}, \ - {"chest-freq", CONFIG_HLP_CHESTFREQ, 0, .iptr=&(UE->chest_freq), .defintval=0, TYPE_INT, 0}, \ - {"chest-time", CONFIG_HLP_CHESTTIME, 0, .iptr=&(UE->chest_time), .defintval=0, TYPE_INT, 0}, \ - {"ue-timing-correction-disable", CONFIG_HLP_DISABLETIMECORR, PARAMFLAG_BOOL, .iptr=&(UE->no_timing_correction), .defintval=0, TYPE_INT, 0}, \ + {"if_freq" , CONFIG_HLP_IF_FREQ, 0, .u64ptr=&(nrUE_params.if_freq), .defuintval=0, TYPE_UINT64, 0}, \ + {"if_freq_off" , CONFIG_HLP_IF_FREQ_OFF, 0, .iptr=&(nrUE_params.if_freq_off), .defuintval=0, TYPE_INT, 0}, \ + {"chest-freq", CONFIG_HLP_CHESTFREQ, 0, .iptr=&(nrUE_params.chest_freq), .defintval=0, TYPE_INT, 0}, \ + {"chest-time", CONFIG_HLP_CHESTTIME, 0, .iptr=&(nrUE_params.chest_time), .defintval=0, TYPE_INT, 0}, \ + {"ue-timing-correction-disable", CONFIG_HLP_DISABLETIMECORR, PARAMFLAG_BOOL, .iptr=&(nrUE_params.no_timing_correction), .defintval=0, TYPE_INT, 0}, \ } // clang-format on typedef struct { uint64_t optmask; //mask to store boolean config options uint32_t ofdm_offset_divisor; // Divisor for sample offset computation for each OFDM symbol - uint8_t max_ldpc_iterations; // number of maximum LDPC iterations + int max_ldpc_iterations; // number of maximum LDPC iterations tpool_t Tpool; // thread pool + int UE_scan_carrier; + int UE_fo_compensation; + int timing_advance; + uint64_t if_freq; + int if_freq_off; + int chest_freq; + int chest_time; + int no_timing_correction; + int nb_antennas_rx; + int nb_antennas_tx; + int threequarter_fs; + int N_RB_DL; + int ssb_start_subcarrier; } nrUE_params_t; extern uint64_t get_nrUE_optmask(void); extern uint64_t set_nrUE_optmask(uint64_t bitmask); diff --git a/executables/softmodem-common.h b/executables/softmodem-common.h index 2499a31ac1..b8f7e6ff62 100644 --- a/executables/softmodem-common.h +++ b/executables/softmodem-common.h @@ -38,11 +38,12 @@ extern "C" #endif /* help strings definition for command line options, used in CMDLINE_XXX_DESC macros and printed when -h option is used */ #define CONFIG_HLP_RFCFGF "Configuration file for front-end (e.g. LMS7002M)\n" -#define CONFIG_HLP_SPLIT73 "Split 7.3 (below rate matching) option: ::" +#define CONFIG_HLP_SPLIT73 "Split 7.3 (below rate matching) option: ::\n" #define CONFIG_HLP_TPOOL "Thread pool configuration: \n\ - default no pool (runs in calling thread),\n\ list of cores, comma separated (negative value is no core affinity)\n\ - example: -1,3 launches two working threads one floating, the second set on core 3" + example: -1,3 launches two working threads one floating, the second set on core 3\n\ + default 8 floating threads\n\ + use N for no pool (runs in calling thread) recommended with rfsim.\n" #define CONFIG_HLP_REORDER "Disable reorder thread\n" #define CONFIG_HLP_ULMAXE "set the eNodeB max ULSCH erros\n" #define CONFIG_HLP_CALUER "set UE RX calibration\n" diff --git a/nfapi/oai_integration/nfapi_pnf.c b/nfapi/oai_integration/nfapi_pnf.c index 0ba6df03b9..b431c9b37a 100644 --- a/nfapi/oai_integration/nfapi_pnf.c +++ b/nfapi/oai_integration/nfapi_pnf.c @@ -1220,8 +1220,10 @@ int pnf_phy_dl_tti_req(gNB_L1_rxtx_proc_t *proc, nfapi_pnf_p7_config_t *pnf_p7, if (tx_data != NULL) { uint8_t *dlsch_sdu = (uint8_t *)tx_data->TLVs[0].value.direct; //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); - AssertFatal(msgTx->num_pdsch_slot < NUMBER_OF_NR_DLSCH_MAX,"Number of PDSCH PDUs %d exceeded the limit %d\n", - msgTx->num_pdsch_slot, NUMBER_OF_NR_DLSCH_MAX); + AssertFatal(msgTx->num_pdsch_slot < gNB->max_nb_pdsch, + "Number of PDSCH PDUs %d exceeded the limit %d\n", + msgTx->num_pdsch_slot, + gNB->max_nb_pdsch); handle_nr_nfapi_pdsch_pdu(msgTx, pdsch_pdu, dlsch_sdu); } else { 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 94bf1b02dc..87fe5b82bc 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 @@ -21,6 +21,7 @@ #include "stddef.h" #include "platform_types.h" #include "fapi_nr_ue_constants.h" +#include "PHY/impl_defs_top.h" #include "PHY/impl_defs_nr.h" #include "common/utils/nr/nr_common.h" @@ -116,7 +117,8 @@ typedef struct { } fapi_nr_pdsch_pdu_t; typedef struct { - uint8_t* pdu; // 3bytes + bool decoded_pdu; + uint8_t pdu[3]; uint8_t additional_bits; uint8_t ssb_index; uint8_t ssb_length; @@ -390,8 +392,6 @@ typedef struct { } fapi_nr_ul_config_request_pdu_t; typedef struct { - //uint16_t sfn; - //uint16_t slot; uint16_t sfn; uint16_t slot; uint8_t number_pdus; @@ -423,9 +423,6 @@ typedef struct { typedef struct { fapi_nr_dl_config_dci_dl_pdu_rel15_t dci_config_rel15; } fapi_nr_dl_config_dci_pdu; -typedef struct{ - uint8_t aperiodicSRS_ResourceTrigger; -} fapi_nr_dl_srs_config_t; typedef enum{vrb_to_prb_mapping_non_interleaved = 0, vrb_to_prb_mapping_interleaved = 1} vrb_to_prb_mapping_t; @@ -462,7 +459,6 @@ typedef struct { uint16_t dmrs_ports; uint8_t n_front_load_symb; uint8_t tci_state; - fapi_nr_dl_srs_config_t srs_config; uint8_t cbgti; uint8_t codeBlockGroupFlushIndicator; // to be check the fields needed to L1 with NR_DL_UE_HARQ_t and NR_UE_DLSCH_t @@ -483,6 +479,7 @@ typedef struct { uint8_t nscid; uint16_t dlDmrsScramblingId; uint16_t pduBitmap; + uint32_t k1_feedback; } fapi_nr_dl_config_dlsch_pdu_rel15_t; typedef struct { @@ -654,6 +651,10 @@ typedef struct } fapi_nr_prach_config_t; +typedef struct { + uint16_t target_Nid_cell; +} fapi_nr_synch_request_t; + typedef struct { uint32_t config_mask; diff --git a/openair1/PHY/INIT/nr_init.c b/openair1/PHY/INIT/nr_init.c index b02c2e0397..36561b110c 100644 --- a/openair1/PHY/INIT/nr_init.c +++ b/openair1/PHY/INIT/nr_init.c @@ -77,6 +77,38 @@ void init_ul_delay_table(NR_DL_FRAME_PARMS *fp) } } +NR_gNB_PHY_STATS_t *get_phy_stats(PHY_VARS_gNB *gNB, uint16_t rnti) +{ + NR_gNB_PHY_STATS_t *stats; + int first_free = -1; + for (int i = 0; i < MAX_MOBILES_PER_GNB; i++) { + stats = &gNB->phy_stats[i]; + if (stats->active && stats->rnti == rnti) + return stats; + else if (!stats->active && first_free == -1) + first_free = i; + } + // new stats + AssertFatal(first_free >= 0, "PHY statistics list is full\n"); + stats = &gNB->phy_stats[first_free]; + stats->active = true; + stats->rnti = rnti; + memset(&stats->dlsch_stats, 0, sizeof(stats->dlsch_stats)); + memset(&stats->ulsch_stats, 0, sizeof(stats->ulsch_stats)); + memset(&stats->uci_stats, 0, sizeof(stats->uci_stats)); + return stats; +} + +void reset_active_stats(PHY_VARS_gNB *gNB, int frame) +{ + // disactivate PHY stats if UE is inactive for a given number of frames + for (int i = 0; i < MAX_MOBILES_PER_GNB; i++) { + NR_gNB_PHY_STATS_t *stats = &gNB->phy_stats[i]; + if (stats->active && (((frame - stats->frame + 1024) % 1024) > NUMBER_FRAMES_PHY_UE_INACTIVE)) + stats->active = false; + } +} + int init_codebook_gNB(PHY_VARS_gNB *gNB) { if(gNB->frame_parms.nb_antennas_tx>1){ @@ -486,7 +518,6 @@ int phy_init_nr_gNB(PHY_VARS_gNB *gNB) nfapi_nr_config_request_scf_t *cfg = &gNB->gNB_config; 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; int i; int Ptx=cfg->carrier_config.num_tx_ant.value; @@ -508,7 +539,9 @@ int phy_init_nr_gNB(PHY_VARS_gNB *gNB) load_nrLDPClib(NULL); if (gNB->ldpc_offload_flag) - load_nrLDPClib_offload(); + load_nrLDPClib_offload(); + + gNB->max_nb_pdsch = MAX_MOBILES_PER_GNB; init_codebook_gNB(gNB); init_ul_delay_table(fp); @@ -662,53 +695,54 @@ int phy_init_nr_gNB(PHY_VARS_gNB *gNB) int nb_re_pusch = N_RB_UL * NR_NB_SC_PER_RB; int nb_re_pusch2 = nb_re_pusch + (nb_re_pusch&7); - for (int ULSCH_id = 0; ULSCH_id < NUMBER_OF_NR_ULSCH_MAX; ULSCH_id++) { - 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]->ul_ch_estimates = (int32_t **)malloc16(n_buf*sizeof(int32_t *) ); - pusch_vars[ULSCH_id]->ul_ch_estimates_ext = (int32_t **)malloc16(n_buf*sizeof(int32_t *) ); - pusch_vars[ULSCH_id]->ptrs_phase_per_slot = (int32_t **)malloc16(n_buf*sizeof(int32_t *) ); - pusch_vars[ULSCH_id]->ul_ch_estimates_time = (int32_t **)malloc16(n_buf*sizeof(int32_t *) ); - pusch_vars[ULSCH_id]->rxdataF_comp = (int32_t **)malloc16(n_buf*sizeof(int32_t *) ); - pusch_vars[ULSCH_id]->ul_ch_mag0 = (int32_t **)malloc16(n_buf*sizeof(int32_t *) ); - pusch_vars[ULSCH_id]->ul_ch_magb0 = (int32_t **)malloc16(n_buf*sizeof(int32_t *) ); - pusch_vars[ULSCH_id]->ul_ch_mag = (int32_t **)malloc16(n_buf*sizeof(int32_t *) ); - pusch_vars[ULSCH_id]->ul_ch_magb = (int32_t **)malloc16(n_buf*sizeof(int32_t *) ); - pusch_vars[ULSCH_id]->rho = (int32_t ***)malloc16(Prx*sizeof(int32_t **) ); - pusch_vars[ULSCH_id]->llr_layers = (int16_t **)malloc16(max_ul_mimo_layers*sizeof(int32_t *) ); + gNB->pusch_vars = (NR_gNB_PUSCH *)malloc16_clear(gNB->max_nb_pusch * sizeof(NR_gNB_PUSCH)); + for (int ULSCH_id = 0; ULSCH_id < gNB->max_nb_pusch; ULSCH_id++) { + NR_gNB_PUSCH *pusch = &gNB->pusch_vars[ULSCH_id]; + pusch->rxdataF_ext = (int32_t **)malloc16(Prx * sizeof(int32_t *)); + pusch->ul_ch_estimates = (int32_t **)malloc16(n_buf * sizeof(int32_t *)); + pusch->ul_ch_estimates_ext = (int32_t **)malloc16(n_buf * sizeof(int32_t *)); + pusch->ptrs_phase_per_slot = (int32_t **)malloc16(n_buf * sizeof(int32_t *)); + pusch->ul_ch_estimates_time = (int32_t **)malloc16(n_buf * sizeof(int32_t *)); + pusch->rxdataF_comp = (int32_t **)malloc16(n_buf * sizeof(int32_t *)); + pusch->ul_ch_mag0 = (int32_t **)malloc16(n_buf * sizeof(int32_t *)); + pusch->ul_ch_magb0 = (int32_t **)malloc16(n_buf * sizeof(int32_t *)); + pusch->ul_ch_mag = (int32_t **)malloc16(n_buf * sizeof(int32_t *)); + pusch->ul_ch_magb = (int32_t **)malloc16(n_buf * sizeof(int32_t *)); + pusch->rho = (int32_t ***)malloc16(Prx * sizeof(int32_t **)); + pusch->llr_layers = (int16_t **)malloc16(max_ul_mimo_layers * sizeof(int32_t *)); for (i=0; irxdataF_ext[i] = (int32_t *)malloc16_clear( sizeof(int32_t)*nb_re_pusch2*fp->symbols_per_slot ); - pusch_vars[ULSCH_id]->rho[i] = (int32_t **)malloc16_clear(NR_MAX_NB_LAYERS*NR_MAX_NB_LAYERS*sizeof(int32_t*)); + pusch->rxdataF_ext[i] = (int32_t *)malloc16_clear(sizeof(int32_t) * nb_re_pusch2 * fp->symbols_per_slot); + pusch->rho[i] = (int32_t **)malloc16_clear(NR_MAX_NB_LAYERS * NR_MAX_NB_LAYERS * sizeof(int32_t *)); for (int j=0; j< max_ul_mimo_layers; j++) { for (int k=0; krho[i][j*max_ul_mimo_layers+k]=(int32_t *)malloc16_clear( sizeof(int32_t)*nb_re_pusch2*fp->symbols_per_slot ); + pusch->rho[i][j * max_ul_mimo_layers + k] = + (int32_t *)malloc16_clear(sizeof(int32_t) * nb_re_pusch2 * fp->symbols_per_slot); } } } for (i=0; iul_ch_estimates[i] = (int32_t *)malloc16_clear( sizeof(int32_t)*fp->ofdm_symbol_size*fp->symbols_per_slot ); - pusch_vars[ULSCH_id]->ul_ch_estimates_ext[i] = (int32_t *)malloc16_clear( sizeof(int32_t)*nb_re_pusch2*fp->symbols_per_slot ); - pusch_vars[ULSCH_id]->ul_ch_estimates_time[i] = (int32_t *)malloc16_clear( sizeof(int32_t)*fp->ofdm_symbol_size ); - pusch_vars[ULSCH_id]->ptrs_phase_per_slot[i] = (int32_t *)malloc16_clear( sizeof(int32_t)*fp->symbols_per_slot); // symbols per slot - pusch_vars[ULSCH_id]->rxdataF_comp[i] = (int32_t *)malloc16_clear( sizeof(int32_t)*nb_re_pusch2*fp->symbols_per_slot ); - pusch_vars[ULSCH_id]->ul_ch_mag0[i] = (int32_t *)malloc16_clear( sizeof(int32_t)*nb_re_pusch2*fp->symbols_per_slot ); - pusch_vars[ULSCH_id]->ul_ch_magb0[i] = (int32_t *)malloc16_clear( sizeof(int32_t)*nb_re_pusch2*fp->symbols_per_slot ); - pusch_vars[ULSCH_id]->ul_ch_mag[i] = (int32_t *)malloc16_clear( sizeof(int32_t)*nb_re_pusch2*fp->symbols_per_slot ); - pusch_vars[ULSCH_id]->ul_ch_magb[i] = (int32_t *)malloc16_clear( sizeof(int32_t)*nb_re_pusch2*fp->symbols_per_slot ); + pusch->ul_ch_estimates[i] = (int32_t *)malloc16_clear(sizeof(int32_t) * fp->ofdm_symbol_size * fp->symbols_per_slot); + pusch->ul_ch_estimates_ext[i] = (int32_t *)malloc16_clear(sizeof(int32_t) * nb_re_pusch2 * fp->symbols_per_slot); + pusch->ul_ch_estimates_time[i] = (int32_t *)malloc16_clear(sizeof(int32_t) * fp->ofdm_symbol_size); + pusch->ptrs_phase_per_slot[i] = (int32_t *)malloc16_clear(sizeof(int32_t) * fp->symbols_per_slot); // symbols per slot + pusch->rxdataF_comp[i] = (int32_t *)malloc16_clear(sizeof(int32_t) * nb_re_pusch2 * fp->symbols_per_slot); + pusch->ul_ch_mag0[i] = (int32_t *)malloc16_clear(sizeof(int32_t) * nb_re_pusch2 * fp->symbols_per_slot); + pusch->ul_ch_magb0[i] = (int32_t *)malloc16_clear(sizeof(int32_t) * nb_re_pusch2 * fp->symbols_per_slot); + pusch->ul_ch_mag[i] = (int32_t *)malloc16_clear(sizeof(int32_t) * nb_re_pusch2 * fp->symbols_per_slot); + pusch->ul_ch_magb[i] = (int32_t *)malloc16_clear(sizeof(int32_t) * nb_re_pusch2 * fp->symbols_per_slot); } for (i=0; i< max_ul_mimo_layers; i++) { - pusch_vars[ULSCH_id]->llr_layers[i] = (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 + pusch->llr_layers[i] = (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 } - 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 - 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]; -*/ + pusch->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 + pusch->ul_valid_re_per_slot = (int16_t *)malloc16_clear(sizeof(int16_t) * fp->symbols_per_slot); + } // ulsch_id + return (0); } @@ -813,46 +847,46 @@ void phy_free_nr_gNB(PHY_VARS_gNB *gNB) free_and_zero(prach_vars->rxsigF); free_and_zero(prach_vars->prach_ifft); - NR_gNB_PUSCH** pusch_vars = gNB->pusch_vars; - for (int ULSCH_id = 0; ULSCH_id < NUMBER_OF_NR_ULSCH_MAX; ULSCH_id++) { + for (int ULSCH_id = 0; ULSCH_id < gNB->max_nb_pusch; ULSCH_id++) { + NR_gNB_PUSCH *pusch_vars = &gNB->pusch_vars[ULSCH_id]; for (int i=0; i< max_ul_mimo_layers; i++) - free_and_zero(pusch_vars[ULSCH_id]->llr_layers[i]); + free_and_zero(pusch_vars->llr_layers[i]); for (int i = 0; i < Prx; i++) { - free_and_zero(pusch_vars[ULSCH_id]->rxdataF_ext[i]); + free_and_zero(pusch_vars->rxdataF_ext[i]); for (int j=0; j< max_ul_mimo_layers; j++) { for (int k=0; krho[i][j*max_ul_mimo_layers+k]); + free_and_zero(pusch_vars->rho[i][j * max_ul_mimo_layers + k]); } - free_and_zero(pusch_vars[ULSCH_id]->rho[i]); + free_and_zero(pusch_vars->rho[i]); } for (int i = 0; i < n_buf; i++) { - free_and_zero(pusch_vars[ULSCH_id]->ul_ch_estimates[i]); - free_and_zero(pusch_vars[ULSCH_id]->ul_ch_estimates_ext[i]); - free_and_zero(pusch_vars[ULSCH_id]->ul_ch_estimates_time[i]); - free_and_zero(pusch_vars[ULSCH_id]->ptrs_phase_per_slot[i]); - free_and_zero(pusch_vars[ULSCH_id]->rxdataF_comp[i]); - free_and_zero(pusch_vars[ULSCH_id]->ul_ch_mag0[i]); - free_and_zero(pusch_vars[ULSCH_id]->ul_ch_magb0[i]); - free_and_zero(pusch_vars[ULSCH_id]->ul_ch_mag[i]); - free_and_zero(pusch_vars[ULSCH_id]->ul_ch_magb[i]); + free_and_zero(pusch_vars->ul_ch_estimates[i]); + free_and_zero(pusch_vars->ul_ch_estimates_ext[i]); + free_and_zero(pusch_vars->ul_ch_estimates_time[i]); + free_and_zero(pusch_vars->ptrs_phase_per_slot[i]); + free_and_zero(pusch_vars->rxdataF_comp[i]); + free_and_zero(pusch_vars->ul_ch_mag0[i]); + free_and_zero(pusch_vars->ul_ch_magb0[i]); + free_and_zero(pusch_vars->ul_ch_mag[i]); + free_and_zero(pusch_vars->ul_ch_magb[i]); } - free_and_zero(pusch_vars[ULSCH_id]->llr_layers); - free_and_zero(pusch_vars[ULSCH_id]->rxdataF_ext); - free_and_zero(pusch_vars[ULSCH_id]->ul_ch_estimates); - free_and_zero(pusch_vars[ULSCH_id]->ul_ch_estimates_ext); - free_and_zero(pusch_vars[ULSCH_id]->ptrs_phase_per_slot); - free_and_zero(pusch_vars[ULSCH_id]->ul_ch_estimates_time); - free_and_zero(pusch_vars[ULSCH_id]->ul_valid_re_per_slot); - free_and_zero(pusch_vars[ULSCH_id]->rxdataF_comp); - free_and_zero(pusch_vars[ULSCH_id]->ul_ch_mag0); - free_and_zero(pusch_vars[ULSCH_id]->ul_ch_magb0); - free_and_zero(pusch_vars[ULSCH_id]->ul_ch_mag); - free_and_zero(pusch_vars[ULSCH_id]->ul_ch_magb); - free_and_zero(pusch_vars[ULSCH_id]->rho); + free_and_zero(pusch_vars->llr_layers); + free_and_zero(pusch_vars->rxdataF_ext); + free_and_zero(pusch_vars->ul_ch_estimates); + free_and_zero(pusch_vars->ul_ch_estimates_ext); + free_and_zero(pusch_vars->ptrs_phase_per_slot); + free_and_zero(pusch_vars->ul_ch_estimates_time); + free_and_zero(pusch_vars->ul_valid_re_per_slot); + free_and_zero(pusch_vars->rxdataF_comp); + free_and_zero(pusch_vars->ul_ch_mag0); + free_and_zero(pusch_vars->ul_ch_magb0); + free_and_zero(pusch_vars->ul_ch_mag); + free_and_zero(pusch_vars->ul_ch_magb); + free_and_zero(pusch_vars->rho); - free_and_zero(pusch_vars[ULSCH_id]->llr); - free_and_zero(pusch_vars[ULSCH_id]); - } //ULSCH_id + free_and_zero(pusch_vars->llr); + } // ULSCH_id + free(gNB->pusch_vars); } //Adding nr_schedule_handler @@ -932,8 +966,8 @@ void nr_phy_config_request_sim(PHY_VARS_gNB *gNB, LOG_I(PHY,"gNB configured\n"); } - -void nr_phy_config_request(NR_PHY_Config_t *phy_config) { +void nr_phy_config_request(NR_PHY_Config_t *phy_config) +{ uint8_t Mod_id = phy_config->Mod_id; uint8_t short_sequence, num_sequences, rootSequenceIndex, fd_occasion; NR_DL_FRAME_PARMS *fp = &RC.gNB[Mod_id]->frame_parms; @@ -985,18 +1019,20 @@ void nr_phy_config_request(NR_PHY_Config_t *phy_config) { LOG_I(PHY,"gNB %d configured\n",Mod_id); } -void init_DLSCH_struct(PHY_VARS_gNB *gNB, processingData_L1tx_t *msg) { +void init_DLSCH_struct(PHY_VARS_gNB *gNB, processingData_L1tx_t *msg) +{ NR_DL_FRAME_PARMS *fp = &gNB->frame_parms; nfapi_nr_config_request_scf_t *cfg = &gNB->gNB_config; uint16_t grid_size = cfg->carrier_config.dl_grid_size[fp->numerology_index].value; msg->num_pdsch_slot = 0; + msg->dlsch = malloc16(gNB->max_nb_pdsch * sizeof(NR_gNB_DLSCH_t *)); int num_cw = NR_MAX_NB_LAYERS > 4? 2:1; - for (int i = 0; i < NUMBER_OF_NR_DLSCH_MAX; i++) { - LOG_D(PHY,"Allocating Transport Channel Buffers for DLSCH %d/%d\n", i, NUMBER_OF_NR_DLSCH_MAX); - for (int j=0; jmax_nb_pdsch; i++) { + LOG_D(PHY, "Allocating Transport Channel Buffers for DLSCH %d/%d\n", i, gNB->max_nb_pdsch); + msg->dlsch[i] = (NR_gNB_DLSCH_t *)malloc16(num_cw * sizeof(NR_gNB_DLSCH_t)); + for (int j = 0; j < num_cw; j++) { msg->dlsch[i][j] = new_gNB_dlsch(fp, grid_size); - AssertFatal(msg->dlsch[i][j]!=NULL,"Can't initialize dlsch %d \n", i); } } } @@ -1007,9 +1043,13 @@ void reset_DLSCH_struct(const PHY_VARS_gNB *gNB, processingData_L1tx_t *msg) const nfapi_nr_config_request_scf_t *cfg = &gNB->gNB_config; const uint16_t grid_size = cfg->carrier_config.dl_grid_size[fp->numerology_index].value; int num_cw = NR_MAX_NB_LAYERS > 4? 2:1; - for (int i = 0; i < NUMBER_OF_NR_DLSCH_MAX; i++) - for (int j=0; jmax_nb_pdsch; i++) { + for (int j = 0; j < num_cw; j++) { free_gNB_dlsch(&msg->dlsch[i][j], grid_size, fp); + } + free(msg->dlsch[i]); + } + free(msg->dlsch); } void init_nr_transport(PHY_VARS_gNB *gNB) @@ -1043,33 +1083,23 @@ void init_nr_transport(PHY_VARS_gNB *gNB) else buffer_ul_slots = (nb_ul_slots_period < slot_ahead) ? nb_ul_slots_period : slot_ahead; - gNB->max_nb_pucch = MAX_MOBILES_PER_GNB * buffer_ul_slots; + gNB->max_nb_pucch = buffer_ul_slots ? MAX_MOBILES_PER_GNB * buffer_ul_slots : 1; + gNB->max_nb_pusch = buffer_ul_slots ? MAX_MOBILES_PER_GNB * buffer_ul_slots : 1; gNB->max_nb_srs = buffer_ul_slots << 1; // assuming at most 2 SRS per slot - gNB->pucch = (NR_gNB_PUCCH_t **) malloc16(gNB->max_nb_pucch * sizeof(NR_gNB_PUCCH_t*)); + gNB->pucch = (NR_gNB_PUCCH_t *)malloc16(gNB->max_nb_pucch * sizeof(NR_gNB_PUCCH_t)); for (int i = 0; i < gNB->max_nb_pucch; i++) { - LOG_D(PHY,"Allocating Transport Channel Buffers for PUCCH %d/%d\n", i, gNB->max_nb_pucch); - gNB->pucch[i] = new_gNB_pucch(); - AssertFatal(gNB->pucch[i] != NULL,"Can't initialize pucch %d \n", i); + memset(&gNB->pucch[i], 0, sizeof(gNB->pucch[i])); } - gNB->srs = (NR_gNB_SRS_t **) malloc16(gNB->max_nb_srs * sizeof(NR_gNB_SRS_t*)); - for (int i = 0; i < gNB->max_nb_srs; i++) { - LOG_D(PHY,"Allocating Transport Channel Buffers for SRS %d/%d\n", i, gNB->max_nb_srs); - gNB->srs[i] = new_gNB_srs(); - AssertFatal(gNB->srs[i]!=NULL,"Can't initialize srs %d \n", i); - } - - for (int i = 0; i < NUMBER_OF_NR_ULSCH_MAX; i++) { - - LOG_D(PHY,"Allocating Transport Channel Buffers for ULSCH %d/%d\n", i, NUMBER_OF_NR_ULSCH_MAX); + gNB->srs = (NR_gNB_SRS_t *)malloc16(gNB->max_nb_srs * sizeof(NR_gNB_SRS_t)); + for (int i = 0; i < gNB->max_nb_srs; i++) + gNB->srs[i].active = 0; + gNB->ulsch = (NR_gNB_ULSCH_t *)malloc16(gNB->max_nb_pusch * sizeof(NR_gNB_ULSCH_t)); + for (int i = 0; i < gNB->max_nb_pusch; i++) { + LOG_D(PHY, "Allocating Transport Channel Buffers for ULSCH %d/%d\n", i, gNB->max_nb_pusch); gNB->ulsch[i] = new_gNB_ulsch(gNB->max_ldpc_iterations, fp->N_RB_UL); - - if (!gNB->ulsch[i]) { - LOG_E(PHY,"Can't get gNB ulsch structures\n"); - exit(-1); - } } gNB->rx_total_gain_dB=130; @@ -1081,14 +1111,10 @@ void reset_nr_transport(PHY_VARS_gNB *gNB) { const NR_DL_FRAME_PARMS *fp = &gNB->frame_parms; - for (int i = 0; i < gNB->max_nb_pucch; i++) - free_gNB_pucch(gNB->pucch[i]); free(gNB->pucch); - - for (int i = 0; i < gNB->max_nb_srs; i++) - free_gNB_srs(gNB->srs[i]); free(gNB->srs); - for (int i = 0; i < NUMBER_OF_NR_ULSCH_MAX; i++) + for (int i = 0; i < gNB->max_nb_pusch; i++) free_gNB_ulsch(&gNB->ulsch[i], fp->N_RB_UL); + free(gNB->ulsch); } diff --git a/openair1/PHY/INIT/nr_init_ue.c b/openair1/PHY/INIT/nr_init_ue.c index 32e5647b69..65d3f86f7a 100644 --- a/openair1/PHY/INIT/nr_init_ue.c +++ b/openair1/PHY/INIT/nr_init_ue.c @@ -202,7 +202,6 @@ int init_nr_ue_signal(PHY_VARS_NR_UE *ue, int nb_connected_gNB) // create shortcuts NR_DL_FRAME_PARMS *const fp = &ue->frame_parms; NR_UE_COMMON *const common_vars = &ue->common_vars; - NR_UE_PBCH **const pbch_vars = ue->pbch_vars; NR_UE_PRACH **const prach_vars = ue->prach_vars; NR_UE_CSI_IM **const csiim_vars = ue->csiim_vars; NR_UE_CSI_RS **const csirs_vars = ue->csirs_vars; @@ -357,7 +356,6 @@ int init_nr_ue_signal(PHY_VARS_NR_UE *ue, int nb_connected_gNB) // DLSCH for (gNB_id = 0; gNB_id < ue->n_connected_gNB; gNB_id++) { 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)); csiim_vars[gNB_id] = (NR_UE_CSI_IM *)malloc16_clear(sizeof(NR_UE_CSI_IM)); csirs_vars[gNB_id] = (NR_UE_CSI_RS *)malloc16_clear(sizeof(NR_UE_CSI_RS)); srs_vars[gNB_id] = (NR_UE_SRS *)malloc16_clear(sizeof(NR_UE_SRS)); @@ -476,7 +474,6 @@ void term_nr_ue_signal(PHY_VARS_NR_UE *ue, int nb_connected_gNB) free_and_zero(ue->csirs_vars[gNB_id]); free_and_zero(ue->srs_vars[gNB_id]); - free_and_zero(ue->pbch_vars[gNB_id]); free_and_zero(ue->prach_vars[gNB_id]); } @@ -523,7 +520,6 @@ void free_nr_ue_dl_harq(NR_DL_UE_HARQ_t harq_list[2][NR_MAX_DLSCH_HARQ_PROCESSES for (int j=0; j < 2; j++) { for (int i=0; ipusch_delay_max_pos; int max_val = delay->pusch_delay_max_val; @@ -208,57 +208,60 @@ void gNB_I0_measurements(PHY_VARS_gNB *gNB,int slot, int first_symb,int num_symb // // Todo: // - averaging IIR filter for RX power and noise -void nr_gnb_measurements(PHY_VARS_gNB *gNB, uint8_t ulsch_id, unsigned char harq_pid, unsigned char symbol, uint8_t nrOfLayers){ +void nr_gnb_measurements(PHY_VARS_gNB *gNB, + NR_gNB_ULSCH_t *ulsch, + NR_gNB_PUSCH *pusch_vars, + unsigned char symbol, + uint8_t nrOfLayers) +{ + int rx_power_tot = 0; + unsigned short rx_power_avg_dB; + unsigned short rx_power_tot_dB; - int rx_power_tot[NUMBER_OF_NR_ULSCH_MAX]; - int rx_power[NUMBER_OF_NR_ULSCH_MAX][NB_ANTENNAS_RX]; - unsigned short rx_power_avg_dB[NUMBER_OF_NR_ULSCH_MAX]; - unsigned short rx_power_tot_dB[NUMBER_OF_NR_ULSCH_MAX]; - - double rx_gain = openair0_cfg[0].rx_gain[0]; - double rx_gain_offset = openair0_cfg[0].rx_gain_offset[0]; + double rx_gain = openair0_cfg[0].rx_gain[0]; + double rx_gain_offset = openair0_cfg[0].rx_gain_offset[0]; PHY_MEASUREMENTS_gNB *meas = &gNB->measurements; - NR_DL_FRAME_PARMS *fp = &gNB->frame_parms; - int ch_offset = fp->ofdm_symbol_size * symbol; - int N_RB_UL = gNB->ulsch[ulsch_id]->harq_processes[harq_pid]->ulsch_pdu.rb_size; - - rx_power_tot[ulsch_id] = 0; + NR_DL_FRAME_PARMS *fp = &gNB->frame_parms; + int ch_offset = fp->ofdm_symbol_size * symbol; + int N_RB_UL = ulsch->harq_process->ulsch_pdu.rb_size; + ulsch_measurements_gNB *ulsch_measurements = &ulsch->ulsch_measurements; + int rx_power[fp->nb_antennas_rx]; for (int aarx = 0; aarx < fp->nb_antennas_rx; aarx++){ - - rx_power[ulsch_id][aarx] = 0; + rx_power[aarx] = 0; for (int aatx = 0; aatx < nrOfLayers; aatx++){ + ulsch_measurements->rx_spatial_power[aatx][aarx] = + (signal_energy_nodc(&pusch_vars->ul_ch_estimates[aatx * fp->nb_antennas_rx + aarx][ch_offset], + N_RB_UL * NR_NB_SC_PER_RB)); - meas->rx_spatial_power[ulsch_id][aatx][aarx] = (signal_energy_nodc(&gNB->pusch_vars[ulsch_id]->ul_ch_estimates[aatx*fp->nb_antennas_rx+aarx][ch_offset], N_RB_UL * NR_NB_SC_PER_RB)); - - if (meas->rx_spatial_power[ulsch_id][aatx][aarx] < 0) { - meas->rx_spatial_power[ulsch_id][aatx][aarx] = 0; + if (ulsch_measurements->rx_spatial_power[aatx][aarx] < 0) { + ulsch_measurements->rx_spatial_power[aatx][aarx] = 0; } - meas->rx_spatial_power_dB[ulsch_id][aatx][aarx] = (unsigned short) dB_fixed(meas->rx_spatial_power[ulsch_id][aatx][aarx]); - rx_power[ulsch_id][aarx] += meas->rx_spatial_power[ulsch_id][aatx][aarx]; - + ulsch_measurements->rx_spatial_power_dB[aatx][aarx] = + (unsigned short)dB_fixed(ulsch_measurements->rx_spatial_power[aatx][aarx]); + rx_power[aarx] += ulsch_measurements->rx_spatial_power[aatx][aarx]; } - LOG_D(PHY, "[ULSCH ID %d] RX power in antenna %d = %d\n", ulsch_id, aarx, rx_power[ulsch_id][aarx]); - - rx_power_tot[ulsch_id] += rx_power[ulsch_id][aarx]; + LOG_D(PHY, "[RNTI %04x] RX power in antenna %d = %d\n", ulsch->rnti, aarx, rx_power[aarx]); + rx_power_tot += rx_power[aarx]; } - rx_power_tot_dB[ulsch_id] = (unsigned short) dB_fixed(rx_power_tot[ulsch_id]); - rx_power_avg_dB[ulsch_id] = rx_power_tot_dB[ulsch_id]; + rx_power_tot_dB = (unsigned short)dB_fixed(rx_power_tot); + rx_power_avg_dB = rx_power_tot_dB; - meas->wideband_cqi_tot[ulsch_id] = dB_fixed2(rx_power_tot[ulsch_id], meas->n0_power_tot); - meas->rx_rssi_dBm[ulsch_id] = rx_power_avg_dB[ulsch_id] + 30 - 10 * log10(pow(2, 30)) - (rx_gain - rx_gain_offset) - dB_fixed(fp->ofdm_symbol_size); - - LOG_D(PHY, "[ULSCH %d] RSSI %d dBm/RE, RSSI (digital) %d dB (N_RB_UL %d), WBand CQI tot %d dB, N0 Power tot %d, RX Power tot %d\n", - ulsch_id, - meas->rx_rssi_dBm[ulsch_id], - rx_power_avg_dB[ulsch_id], - N_RB_UL, - meas->wideband_cqi_tot[ulsch_id], - meas->n0_power_tot, - rx_power_tot[ulsch_id]); + ulsch_measurements->wideband_cqi_tot = dB_fixed2(rx_power_tot, meas->n0_power_tot); + ulsch_measurements->rx_rssi_dBm = + rx_power_avg_dB + 30 - 10 * log10(pow(2, 30)) - (rx_gain - rx_gain_offset) - dB_fixed(fp->ofdm_symbol_size); + LOG_D(PHY, + "[RNTI %04x] RSSI %d dBm/RE, RSSI (digital) %d dB (N_RB_UL %d), WBand CQI tot %d dB, N0 Power tot %d, RX Power tot %d\n", + ulsch->rnti, + ulsch_measurements->rx_rssi_dBm, + rx_power_avg_dB, + N_RB_UL, + ulsch_measurements->wideband_cqi_tot, + meas->n0_power_tot, + rx_power_tot); } diff --git a/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c b/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c index fd2ed4f675..e953d8a4a0 100644 --- a/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c +++ b/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c @@ -130,7 +130,8 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB, debug_ch_est = fopen("debug_ch_est.txt","w"); #endif //uint16_t Nid_cell = (eNB_offset == 0) ? gNB->frame_parms.Nid_cell : gNB->measurements.adj_cell_id[eNB_offset-1]; - c16_t **ul_ch_estimates = (c16_t **) gNB->pusch_vars[ul_id]->ul_ch_estimates; + NR_gNB_PUSCH *pusch_vars = &gNB->pusch_vars[ul_id]; + c16_t **ul_ch_estimates = (c16_t **)pusch_vars->ul_ch_estimates; const int symbolSize = gNB->frame_parms.ofdm_symbol_size; const int soffset = (Ns&3)*gNB->frame_parms.symbols_per_slot*symbolSize; const int nushift = (p>>1)&1; @@ -187,7 +188,8 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB, c16_t ul_ls_est[symbolSize] __attribute__((aligned(32))); memset(ul_ls_est, 0, sizeof(c16_t) * symbolSize); - memset(&gNB->measurements.delay[ul_id], 0, sizeof(gNB->measurements.delay[ul_id])); + NR_ULSCH_delay_t *delay = &gNB->ulsch[ul_id].delay; + memset(delay, 0, sizeof(*delay)); for (int aarx=0; aarxframe_parms.nb_antennas_rx; aarx++) { c16_t *rxdataF = (c16_t *)&gNB->common_vars.rxdataF[aarx][symbol_offset]; @@ -228,17 +230,15 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB, pilot_cnt += 2; } - freq2time(symbolSize, - (int16_t *) ul_ls_est, - (int16_t *) gNB->pusch_vars[ul_id]->ul_ch_estimates_time[aarx]); + freq2time(symbolSize, (int16_t *)ul_ls_est, (int16_t *)pusch_vars->ul_ch_estimates_time[aarx]); - nr_est_timing_advance_pusch(&gNB->frame_parms, gNB->pusch_vars[ul_id]->ul_ch_estimates_time[aarx], &gNB->measurements.delay[ul_id]); - int delay = gNB->measurements.delay[ul_id].pusch_est_delay; - int delay_idx = get_delay_idx(delay); + nr_est_timing_advance_pusch(&gNB->frame_parms, pusch_vars->ul_ch_estimates_time[aarx], delay); + int pusch_delay = delay->pusch_est_delay; + int delay_idx = get_delay_idx(pusch_delay); c16_t *ul_delay_table = gNB->frame_parms.ul_delay_table[delay_idx]; #ifdef DEBUG_PUSCH - printf("Estimated delay = %i\n", delay >> 1); + printf("Estimated delay = %i\n", pusch_delay >> 1); #endif pilot_cnt = 0; @@ -277,7 +277,7 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB, // Revert delay pilot_cnt = 0; ul_ch = &ul_ch_estimates[p * gNB->frame_parms.nb_antennas_rx + aarx][ch_offset]; - int inv_delay_idx = get_delay_idx(-delay); + int inv_delay_idx = get_delay_idx(-pusch_delay); c16_t *ul_inv_delay_table = gNB->frame_parms.ul_delay_table[inv_delay_idx]; for (int n = 0; n < 3 * nb_rb_pusch; n++) { for (int k_line = 0; k_line <= 1; k_line++) { @@ -310,10 +310,10 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB, } // Delay compensation - freq2time(symbolSize, (int16_t *)ul_ls_est, (int16_t *)gNB->pusch_vars[ul_id]->ul_ch_estimates_time[aarx]); - nr_est_timing_advance_pusch(&gNB->frame_parms, gNB->pusch_vars[ul_id]->ul_ch_estimates_time[aarx], &gNB->measurements.delay[ul_id]); - int delay = gNB->measurements.delay[ul_id].pusch_est_delay; - int delay_idx = get_delay_idx(-delay); + freq2time(symbolSize, (int16_t *)ul_ls_est, (int16_t *)pusch_vars->ul_ch_estimates_time[aarx]); + nr_est_timing_advance_pusch(&gNB->frame_parms, pusch_vars->ul_ch_estimates_time[aarx], delay); + int pusch_delay = delay->pusch_est_delay; + int delay_idx = get_delay_idx(-pusch_delay); c16_t *ul_delay_table = gNB->frame_parms.ul_delay_table[delay_idx]; for (int n = 0; n < nb_rb_pusch * NR_NB_SC_PER_RB; n++) { ul_ch[n] = c16mulShift(ul_ls_est[n], ul_delay_table[n % 6], 8); @@ -532,7 +532,9 @@ void nr_pusch_ptrs_processing(PHY_VARS_gNB *gNB, uint8_t ulsch_id, uint8_t nr_tti_rx, unsigned char symbol, - uint32_t nb_re_pusch) { + uint32_t nb_re_pusch) +{ + NR_gNB_PUSCH *pusch_vars = &gNB->pusch_vars[ulsch_id]; //#define DEBUG_UL_PTRS 1 int32_t *ptrs_re_symbol = NULL; int8_t ret = 0; @@ -542,16 +544,16 @@ void nr_pusch_ptrs_processing(PHY_VARS_gNB *gNB, uint8_t *L_ptrs = &rel15_ul->pusch_ptrs.ptrs_time_density; uint8_t *K_ptrs = &rel15_ul->pusch_ptrs.ptrs_freq_density; uint16_t *dmrsSymbPos = &rel15_ul->ul_dmrs_symb_pos; - uint16_t *ptrsSymbPos = &gNB->pusch_vars[ulsch_id]->ptrs_symbols; - uint8_t *ptrsSymbIdx = &gNB->pusch_vars[ulsch_id]->ptrs_symbol_index; + uint16_t *ptrsSymbPos = &pusch_vars->ptrs_symbols; + uint8_t *ptrsSymbIdx = &pusch_vars->ptrs_symbol_index; uint8_t *dmrsConfigType = &rel15_ul->dmrs_config_type; uint16_t *nb_rb = &rel15_ul->rb_size; uint8_t *ptrsReOffset = &rel15_ul->pusch_ptrs.ptrs_ports_list[0].ptrs_re_offset; /* loop over antennas */ for (int aarx=0; aarxnb_antennas_rx; aarx++) { - c16_t *phase_per_symbol = (c16_t*)gNB->pusch_vars[ulsch_id]->ptrs_phase_per_slot[aarx]; - ptrs_re_symbol = &gNB->pusch_vars[ulsch_id]->ptrs_re_per_slot; + c16_t *phase_per_symbol = (c16_t *)pusch_vars->ptrs_phase_per_slot[aarx]; + ptrs_re_symbol = &pusch_vars->ptrs_re_per_slot; *ptrs_re_symbol = 0; phase_per_symbol[symbol].i = 0; /* set DMRS estimates to 0 angle with magnitude 1 */ @@ -584,13 +586,17 @@ void nr_pusch_ptrs_processing(PHY_VARS_gNB *gNB, /*------------------------------------------------------------------------------------------------------- */ /* 1) Estimate common phase error per PTRS symbol */ /*------------------------------------------------------------------------------------------------------- */ - nr_ptrs_cpe_estimation(*K_ptrs,*ptrsReOffset,*dmrsConfigType,*nb_rb, + nr_ptrs_cpe_estimation(*K_ptrs, + *ptrsReOffset, + *dmrsConfigType, + *nb_rb, rel15_ul->rnti, nr_tti_rx, - symbol,frame_parms->ofdm_symbol_size, - (int16_t *)&gNB->pusch_vars[ulsch_id]->rxdataF_comp[aarx][(symbol * nb_re_pusch)], + symbol, + frame_parms->ofdm_symbol_size, + (int16_t *)&pusch_vars->rxdataF_comp[aarx][(symbol * nb_re_pusch)], gNB->nr_gold_pusch_dmrs[rel15_ul->scid][nr_tti_rx][symbol], - (int16_t*)&phase_per_symbol[symbol], + (int16_t *)&phase_per_symbol[symbol], ptrs_re_symbol); } @@ -608,7 +614,7 @@ void nr_pusch_ptrs_processing(PHY_VARS_gNB *gNB, } #ifdef DEBUG_UL_PTRS - LOG_M("ptrsEstUl.m","est",gNB->pusch_vars[ulsch_id]->ptrs_phase_per_slot[aarx],frame_parms->symbols_per_slot,1,1 ); + LOG_M("ptrsEstUl.m", "est", pusch_vars->ptrs_phase_per_slot[aarx], frame_parms->symbols_per_slot, 1, 1); LOG_M("rxdataF_bf_ptrs_comp_ul.m","bf_ptrs_cmp", &gNB->pusch_vars[0]->rxdataF_comp[aarx][rel15_ul->start_symbol_index * NR_NB_SC_PER_RB * rel15_ul->rb_size], rel15_ul->nr_of_symbols * NR_NB_SC_PER_RB * rel15_ul->rb_size,1,1); @@ -624,10 +630,11 @@ void nr_pusch_ptrs_processing(PHY_VARS_gNB *gNB, #ifdef DEBUG_UL_PTRS printf("[PHY][UL][PTRS]: Rotate Symbol %2d with %d + j* %d\n", i, phase_per_symbol[i].r,phase_per_symbol[i].i); #endif - rotate_cpx_vector((c16_t*)&gNB->pusch_vars[ulsch_id]->rxdataF_comp[aarx][(i * rel15_ul->rb_size * NR_NB_SC_PER_RB)], + rotate_cpx_vector((c16_t *)&pusch_vars->rxdataF_comp[aarx][(i * rel15_ul->rb_size * NR_NB_SC_PER_RB)], &phase_per_symbol[i], - (c16_t*)&gNB->pusch_vars[ulsch_id]->rxdataF_comp[aarx][(i * rel15_ul->rb_size * NR_NB_SC_PER_RB)], - ((*nb_rb) * NR_NB_SC_PER_RB), 15); + (c16_t *)&pusch_vars->rxdataF_comp[aarx][(i * rel15_ul->rb_size * NR_NB_SC_PER_RB)], + ((*nb_rb) * NR_NB_SC_PER_RB), + 15); }// if not DMRS Symbol }// symbol loop }// last symbol check diff --git a/openair1/PHY/NR_ESTIMATION/nr_ul_estimation.h b/openair1/PHY/NR_ESTIMATION/nr_ul_estimation.h index fb43e83827..41f841a975 100644 --- a/openair1/PHY/NR_ESTIMATION/nr_ul_estimation.h +++ b/openair1/PHY/NR_ESTIMATION/nr_ul_estimation.h @@ -53,9 +53,15 @@ void dump_nr_I0_stats(FILE *fd,PHY_VARS_gNB *gNB); void gNB_I0_measurements(PHY_VARS_gNB *gNB,int slot,int first_symb,int num_symb); -void nr_gnb_measurements(PHY_VARS_gNB *gNB, uint8_t ulsch_id, unsigned char harq_pid, unsigned char symbol, uint8_t nrOfLayers); +void nr_gnb_measurements(PHY_VARS_gNB *gNB, + NR_gNB_ULSCH_t *ulsch, + NR_gNB_PUSCH *pusch_vars, + unsigned char symbol, + uint8_t nrOfLayers); -void nr_est_timing_advance_pusch(const NR_DL_FRAME_PARMS *frame_parms, const int32_t *ul_ch_estimates_time, struct delay_s *delay); +void nr_est_timing_advance_pusch(const NR_DL_FRAME_PARMS *frame_parms, + const int32_t *ul_ch_estimates_time, + NR_ULSCH_delay_t *delay); int nr_est_timing_advance_srs(const NR_DL_FRAME_PARMS *frame_parms, const int32_t srs_estimated_channel_time[][frame_parms->ofdm_symbol_size]); diff --git a/openair1/PHY/NR_REFSIG/pss_nr.h b/openair1/PHY/NR_REFSIG/pss_nr.h index 3b0e87109e..c5bc4f880e 100644 --- a/openair1/PHY/NR_REFSIG/pss_nr.h +++ b/openair1/PHY/NR_REFSIG/pss_nr.h @@ -126,12 +126,7 @@ void init_context_pss_nr(NR_DL_FRAME_PARMS *frame_parms_ue); void free_context_pss_nr(void); int set_pss_nr(int ofdm_symbol_size); int pss_synchro_nr(PHY_VARS_NR_UE *PHY_vars_UE, int is, int rate_change); -int pss_search_time_nr(c16_t **rxdata, ///rx data in time domain - NR_DL_FRAME_PARMS *frame_parms, - int fo_flag, - int is, - int *eNB_id, - int *f_off); +int pss_search_time_nr(c16_t **rxdata, PHY_VARS_NR_UE *ue, int fo_flag, int is); #endif #undef EXTERN diff --git a/openair1/PHY/NR_TRANSPORT/nr_dlsch.c b/openair1/PHY/NR_TRANSPORT/nr_dlsch.c index c361c61f27..165489ee6a 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_dlsch.c +++ b/openair1/PHY/NR_TRANSPORT/nr_dlsch.c @@ -75,7 +75,7 @@ void nr_generate_pdsch(processingData_L1tx_t *msgTx, time_stats_t *dlsch_segmentation_stats=&gNB->dlsch_segmentation_stats; for (int dlsch_id=0; dlsch_idnum_pdsch_slot; dlsch_id++) { - dlsch = msgTx->dlsch[dlsch_id][0]; + dlsch = &msgTx->dlsch[dlsch_id][0]; NR_DL_gNB_HARQ_t *harq = &dlsch->harq_process; nfapi_nr_dl_tti_pdsch_pdu_rel15_t *rel15 = &harq->pdsch_pdu.pdsch_pdu_rel15; @@ -567,21 +567,16 @@ void nr_generate_pdsch(processingData_L1tx_t *msgTx, } void dump_pdsch_stats(FILE *fd,PHY_VARS_gNB *gNB) { - - for (int i=0;idlsch_stats[i].rnti > 0 && gNB->dlsch_stats[i].frame != gNB->dlsch_stats[i].dump_frame) { - gNB->dlsch_stats[i].dump_frame = gNB->dlsch_stats[i].frame; - fprintf(fd,"DLSCH RNTI %x: current_Qm %d, current_RI %d, total_bytes TX %d\n", - gNB->dlsch_stats[i].rnti, - gNB->dlsch_stats[i].current_Qm, - gNB->dlsch_stats[i].current_RI, - gNB->dlsch_stats[i].total_bytes_tx); + for (int i = 0; i < MAX_MOBILES_PER_GNB; i++) { + NR_gNB_PHY_STATS_t *stats = &gNB->phy_stats[i]; + if (stats->active && stats->frame != stats->dlsch_stats.dump_frame) { + stats->dlsch_stats.dump_frame = stats->frame; + fprintf(fd, + "DLSCH RNTI %x: current_Qm %d, current_RI %d, total_bytes TX %d\n", + stats->rnti, + stats->dlsch_stats.current_Qm, + stats->dlsch_stats.current_RI, + stats->dlsch_stats.total_bytes_tx); } - -} - -void clear_pdsch_stats(PHY_VARS_gNB *gNB) { - - for (int i = 0;i < NUMBER_OF_NR_SCH_STATS_MAX; i++) - memset((void*)&gNB->dlsch_stats[i],0,sizeof(gNB->dlsch_stats[i])); + } } diff --git a/openair1/PHY/NR_TRANSPORT/nr_dlsch.h b/openair1/PHY/NR_TRANSPORT/nr_dlsch.h index 974e74f30e..8ee2e1171f 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_dlsch.h +++ b/openair1/PHY/NR_TRANSPORT/nr_dlsch.h @@ -52,8 +52,6 @@ void nr_generate_pdsch(processingData_L1tx_t *msgTx, void clean_gNB_dlsch(NR_gNB_DLSCH_t *dlsch); -void clean_gNB_ulsch(NR_gNB_ULSCH_t *ulsch); - int16_t find_nr_dlsch(uint16_t rnti, PHY_VARS_gNB *gNB,find_type_t type); NR_gNB_SCH_STATS_t *find_nr_dlsch_stats(uint16_t rnti, PHY_VARS_gNB *gNB,find_type_t type); @@ -77,6 +75,4 @@ void nr_emulate_dlsch_payload(uint8_t* payload, uint16_t size); void dump_pdsch_stats(FILE *fd,PHY_VARS_gNB *gNB); -void clear_pdsch_stats(PHY_VARS_gNB *gNB); - #endif diff --git a/openair1/PHY/NR_TRANSPORT/nr_dlsch_coding.c b/openair1/PHY/NR_TRANSPORT/nr_dlsch_coding.c index 63fbf20d0d..d244881c32 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_dlsch_coding.c +++ b/openair1/PHY/NR_TRANSPORT/nr_dlsch_coding.c @@ -48,13 +48,8 @@ //#define DEBUG_DLSCH_CODING //#define DEBUG_DLSCH_FREE 1 - -void free_gNB_dlsch(NR_gNB_DLSCH_t **dlschptr, - uint16_t N_RB, - const NR_DL_FRAME_PARMS* frame_parms) { - - NR_gNB_DLSCH_t *dlsch = *dlschptr; - +void free_gNB_dlsch(NR_gNB_DLSCH_t *dlsch, uint16_t N_RB, const NR_DL_FRAME_PARMS *frame_parms) +{ int max_layers = (frame_parms->nb_antennas_txnb_antennas_tx : NR_MAX_NB_LAYERS; uint16_t a_segments = MAX_NUM_NR_DLSCH_SEGMENTS_PER_LAYER*max_layers; @@ -92,14 +87,10 @@ void free_gNB_dlsch(NR_gNB_DLSCH_t **dlschptr, } free(dlsch->txdataF); free(dlsch->ue_spec_bf_weights); - - free(dlsch); - *dlschptr = NULL; } -NR_gNB_DLSCH_t *new_gNB_dlsch(NR_DL_FRAME_PARMS *frame_parms, - uint16_t N_RB) { - +NR_gNB_DLSCH_t new_gNB_dlsch(NR_DL_FRAME_PARMS *frame_parms, uint16_t N_RB) +{ int max_layers = (frame_parms->nb_antennas_txnb_antennas_tx : NR_MAX_NB_LAYERS; uint16_t a_segments = MAX_NUM_NR_DLSCH_SEGMENTS_PER_LAYER*max_layers; //number of segments to be allocated @@ -110,34 +101,32 @@ NR_gNB_DLSCH_t *new_gNB_dlsch(NR_DL_FRAME_PARMS *frame_parms, LOG_D(PHY,"Allocating %d segments (MAX %d, N_PRB %d)\n",a_segments,MAX_NUM_NR_DLSCH_SEGMENTS_PER_LAYER,N_RB); uint32_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)); + NR_gNB_DLSCH_t dlsch; int txdataf_size = frame_parms->N_RB_DL*NR_SYMBOLS_PER_SLOT*NR_NB_SC_PER_RB*8; // max pdsch encoded length for each layer - dlsch->txdataF = (int32_t **)malloc16(max_layers*sizeof(int32_t *)); + dlsch.txdataF = (int32_t **)malloc16(max_layers * sizeof(int32_t *)); - dlsch->ue_spec_bf_weights = (int32_t ***)malloc16(max_layers*sizeof(int32_t **)); + dlsch.ue_spec_bf_weights = (int32_t ***)malloc16(max_layers * sizeof(int32_t **)); for (int layer=0; layerue_spec_bf_weights[layer] = (int32_t **)malloc16(64*sizeof(int32_t *)); + dlsch.ue_spec_bf_weights[layer] = (int32_t **)malloc16(64 * sizeof(int32_t *)); for (int aa=0; aa<64; aa++) { - dlsch->ue_spec_bf_weights[layer][aa] = (int32_t *)malloc16(OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES*sizeof(int32_t)); + dlsch.ue_spec_bf_weights[layer][aa] = (int32_t *)malloc16(OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES * sizeof(int32_t)); for (int re=0; reue_spec_bf_weights[layer][aa][re] = 0x00007fff; + dlsch.ue_spec_bf_weights[layer][aa][re] = 0x00007fff; } } - dlsch->txdataF[layer] = (int32_t *)malloc16((txdataf_size)*sizeof(int32_t)); + dlsch.txdataF[layer] = (int32_t *)malloc16((txdataf_size) * sizeof(int32_t)); } int nb_codewords = NR_MAX_NB_LAYERS > 4 ? 2 : 1; - dlsch->mod_symbs = (int32_t **)malloc16(nb_codewords*sizeof(int32_t *)); + dlsch.mod_symbs = (int32_t **)malloc16(nb_codewords * sizeof(int32_t *)); for (int q=0; qmod_symbs[q] = (int32_t *)malloc16(txdataf_size*max_layers*sizeof(int32_t)); + dlsch.mod_symbs[q] = (int32_t *)malloc16(txdataf_size * max_layers * sizeof(int32_t)); - NR_DL_gNB_HARQ_t *harq = &dlsch->harq_process; + 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"); @@ -167,7 +156,6 @@ NR_gNB_DLSCH_t *new_gNB_dlsch(NR_DL_FRAME_PARMS *frame_parms, void clean_gNB_dlsch(NR_gNB_DLSCH_t *dlsch) { AssertFatal(dlsch!=NULL,"dlsch is null\n"); - dlsch->rnti = 0; dlsch->active = 0; } @@ -277,10 +265,15 @@ int nr_dlsch_encoding(PHY_VARS_gNB *gNB, uint8_t slot, NR_DL_gNB_HARQ_t *harq, NR_DL_FRAME_PARMS *frame_parms, - unsigned char * output, - time_stats_t *tinput,time_stats_t *tprep,time_stats_t *tparity,time_stats_t *toutput, - time_stats_t *dlsch_rate_matching_stats,time_stats_t *dlsch_interleaving_stats, - time_stats_t *dlsch_segmentation_stats) { + unsigned char *output, + time_stats_t *tinput, + time_stats_t *tprep, + time_stats_t *tparity, + time_stats_t *toutput, + time_stats_t *dlsch_rate_matching_stats, + time_stats_t *dlsch_interleaving_stats, + time_stats_t *dlsch_segmentation_stats) +{ encoder_implemparams_t impp; impp.output=output; unsigned int crc=1; @@ -289,29 +282,18 @@ int nr_dlsch_encoding(PHY_VARS_gNB *gNB, VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_gNB_DLSCH_ENCODING, VCD_FUNCTION_IN); uint32_t A = rel15->TBSize[0]<<3; unsigned char *a=harq->pdu; - if ( rel15->rnti != SI_RNTI) + if (rel15->rnti != SI_RNTI) trace_NRpdu(DIRECTION_DOWNLINK, a, rel15->TBSize[0], WS_C_RNTI, rel15->rnti, frame, slot,0, 0); - NR_gNB_SCH_STATS_t *stats=NULL; - int first_free=-1; + NR_gNB_PHY_STATS_t *phy_stats = NULL; + if (rel15->rnti != 0xFFFF) + phy_stats = get_phy_stats(gNB, rel15->rnti); - for (int i=0; idlsch_stats[i].rnti == 0 && first_free == -1) { - first_free = i; - stats=&gNB->dlsch_stats[i]; - } - - if (gNB->dlsch_stats[i].rnti == rel15->rnti) { - stats=&gNB->dlsch_stats[i]; - break; - } - } - - if (stats) { - stats->rnti = rel15->rnti; - stats->total_bytes_tx += rel15->TBSize[0]; - stats->current_RI = rel15->nrOfLayers; - stats->current_Qm = rel15->qamModOrder[0]; + if (phy_stats) { + phy_stats->frame = frame; + phy_stats->dlsch_stats.total_bytes_tx += rel15->TBSize[0]; + phy_stats->dlsch_stats.current_RI = rel15->nrOfLayers; + phy_stats->dlsch_stats.current_Qm = rel15->qamModOrder[0]; } int max_bytes = MAX_NUM_NR_DLSCH_SEGMENTS_PER_LAYER*rel15->nrOfLayers*1056; diff --git a/openair1/PHY/NR_TRANSPORT/nr_dlsch_tools.c b/openair1/PHY/NR_TRANSPORT/nr_dlsch_tools.c index 2f8087ea0e..c868334a3c 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_dlsch_tools.c +++ b/openair1/PHY/NR_TRANSPORT/nr_dlsch_tools.c @@ -44,16 +44,13 @@ void nr_emulate_dlsch_payload(uint8_t* pdu, uint16_t size) { *(pdu+i) = (uint8_t)rand(); } -void nr_fill_dlsch(processingData_L1tx_t *msgTx, - nfapi_nr_dl_tti_pdsch_pdu *pdsch_pdu, - uint8_t *sdu) { - - NR_gNB_DLSCH_t *dlsch = msgTx->dlsch[msgTx->num_pdsch_slot][0]; - NR_DL_gNB_HARQ_t *harq = &dlsch->harq_process; +void nr_fill_dlsch(processingData_L1tx_t *msgTx, nfapi_nr_dl_tti_pdsch_pdu *pdsch_pdu, uint8_t *sdu) +{ + NR_gNB_DLSCH_t *dlsch = &msgTx->dlsch[msgTx->num_pdsch_slot][0]; + NR_DL_gNB_HARQ_t *harq = &dlsch->harq_process; /// DLSCH struct memcpy((void*)&harq->pdsch_pdu, (void*)pdsch_pdu, sizeof(nfapi_nr_dl_tti_pdsch_pdu)); msgTx->num_pdsch_slot++; - AssertFatal(sdu!=NULL,"sdu is null\n"); + AssertFatal(sdu != NULL, "sdu is null\n"); harq->pdu = sdu; } - diff --git a/openair1/PHY/NR_TRANSPORT/nr_transport_common_proto.h b/openair1/PHY/NR_TRANSPORT/nr_transport_common_proto.h index 74d19bf6f6..f45c23980b 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_transport_common_proto.h +++ b/openair1/PHY/NR_TRANSPORT/nr_transport_common_proto.h @@ -40,7 +40,6 @@ #include "PHY/defs_nr_common.h" - void nr_group_sequence_hopping(pucch_GroupHopping_t PUCCH_GroupHopping, uint32_t n_id, uint8_t n_hop, diff --git a/openair1/PHY/NR_TRANSPORT/nr_transport_proto.h b/openair1/PHY/NR_TRANSPORT/nr_transport_proto.h index 2f0e46a13f..cb7cd35516 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_transport_proto.h +++ b/openair1/PHY/NR_TRANSPORT/nr_transport_proto.h @@ -38,6 +38,7 @@ #define NR_PBCH_PDU_BITS 24 +NR_gNB_PHY_STATS_t *get_phy_stats(PHY_VARS_gNB *gNB, uint16_t rnti); int nr_generate_prs(uint32_t **nr_gold_prs, c16_t *txdataF, @@ -107,10 +108,9 @@ int nr_generate_pbch(nfapi_nr_dl_tti_ssb_pdu *ssb_pdu, */ void nr_init_pbch_interleaver(uint8_t *interleaver); -NR_gNB_DLSCH_t *new_gNB_dlsch(NR_DL_FRAME_PARMS *frame_parms, - uint16_t N_RB); +NR_gNB_DLSCH_t new_gNB_dlsch(NR_DL_FRAME_PARMS *frame_parms, uint16_t N_RB); -void free_gNB_dlsch(NR_gNB_DLSCH_t **dlschptr, uint16_t N_RB, const NR_DL_FRAME_PARMS* frame_parms); +void free_gNB_dlsch(NR_gNB_DLSCH_t *dlsch, uint16_t N_RB, const NR_DL_FRAME_PARMS *frame_parms); /** \brief This function is the top-level entry point to PUSCH demodulation, after frequency-domain transformation and channel estimation. It performs - RB extraction (signal and channel estimates) @@ -269,6 +269,9 @@ void nr_ulsch_compute_llr(int32_t *rxdataF_comp, uint8_t symbol, uint8_t mod_order); +void reset_active_stats(PHY_VARS_gNB *gNB, int frame); +void reset_active_ulsch(PHY_VARS_gNB *gNB, int frame); + void nr_fill_ulsch(PHY_VARS_gNB *gNB, int frame, int slot, @@ -304,27 +307,11 @@ void nr_fill_prach_ru(RU_t *ru, int16_t find_nr_prach(PHY_VARS_gNB *gNB,int frame,int slot, find_type_t type); int16_t find_nr_prach_ru(RU_t *ru,int frame,int slot, find_type_t type); -NR_gNB_PUCCH_t *new_gNB_pucch(void); -void free_gNB_pucch(NR_gNB_PUCCH_t *pucch); - void nr_fill_pucch(PHY_VARS_gNB *gNB, int frame, int slot, nfapi_nr_pucch_pdu_t *pucch_pdu); -int nr_find_pucch(uint16_t rnti, - int frame, - int slot, - PHY_VARS_gNB *gNB); - -NR_gNB_SRS_t *new_gNB_srs(void); -void free_gNB_srs(NR_gNB_SRS_t *srs); - -int nr_find_srs(rnti_t rnti, - frame_t frame, - slot_t slot, - PHY_VARS_gNB *gNB); - void nr_fill_srs(PHY_VARS_gNB *gNB, frame_t frame, slot_t slot, diff --git a/openair1/PHY/NR_TRANSPORT/nr_ulsch.c b/openair1/PHY/NR_TRANSPORT/nr_ulsch.c index 9fb95ac273..e7863d3820 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_ulsch.c +++ b/openair1/PHY/NR_TRANSPORT/nr_ulsch.c @@ -34,57 +34,74 @@ #include "PHY/NR_TRANSPORT/nr_transport_common_proto.h" #include "PHY/NR_TRANSPORT/nr_ulsch.h" -int16_t find_nr_ulsch(uint16_t rnti, PHY_VARS_gNB *gNB,find_type_t type) { +NR_gNB_ULSCH_t *find_nr_ulsch(PHY_VARS_gNB *gNB, uint16_t rnti, int pid) +{ + int16_t first_free_index = -1; + AssertFatal(gNB != NULL, "gNB is null\n"); + NR_gNB_ULSCH_t *ulsch = NULL; - uint16_t i; - int16_t first_free_index=-1; - - AssertFatal(gNB!=NULL,"gNB is null\n"); - for (i = 0; i < NUMBER_OF_NR_ULSCH_MAX; i++) { - AssertFatal(gNB->ulsch[i]!=NULL,"gNB->ulsch[%d] is null\n",i); - LOG_D(PHY,"searching for rnti %x : ulsch_index %d=> harq_mask %x, rnti %x, first_free_index %d\n", rnti,i,gNB->ulsch[i]->harq_mask,gNB->ulsch[i]->rnti,first_free_index); - if ((gNB->ulsch[i]->harq_mask >0) && - (gNB->ulsch[i]->rnti==rnti)) return i; - else if ((gNB->ulsch[i]->harq_mask == 0) && (first_free_index==-1)) first_free_index=i; + for (int i = 0; i < gNB->max_nb_pusch; i++) { + ulsch = &gNB->ulsch[i]; + AssertFatal(ulsch != NULL, "gNB->ulsch[%d] is null\n", i); + if (!ulsch->active) { + if (first_free_index == -1) + first_free_index = i; + } else { + // if there is already an active ULSCH for this RNTI and HARQ_PID + if ((ulsch->harq_pid == pid) && (ulsch->rnti == rnti)) + return ulsch; + } } - if (type == SEARCH_EXIST) return -1; if (first_free_index != -1) - gNB->ulsch[first_free_index]->rnti = 0; - return first_free_index; + ulsch = &gNB->ulsch[first_free_index]; + + return ulsch; } -void nr_fill_ulsch(PHY_VARS_gNB *gNB, - int frame, - int slot, - nfapi_nr_pusch_pdu_t *ulsch_pdu) { - - - int ulsch_id = find_nr_ulsch(ulsch_pdu->rnti,gNB,SEARCH_EXIST_OR_FREE); - AssertFatal((ulsch_id >= 0) && (ulsch_id < NUMBER_OF_NR_ULSCH_MAX), - "illegal or no ulsch_id found!!! rnti %04x ulsch_id %d\n",ulsch_pdu->rnti,ulsch_id); - - NR_gNB_ULSCH_t *ulsch = gNB->ulsch[ulsch_id]; +void nr_fill_ulsch(PHY_VARS_gNB *gNB, int frame, int slot, nfapi_nr_pusch_pdu_t *ulsch_pdu) +{ int harq_pid = ulsch_pdu->pusch_data.harq_process_id; - ulsch->rnti = ulsch_pdu->rnti; - //ulsch->rnti_type; - ulsch->harq_mask |= 1<rnti, harq_pid); + AssertFatal(ulsch, "No ulsch_id found for rnti %04x\n", ulsch_pdu->rnti); - NR_UL_gNB_HARQ_t *harq = ulsch->harq_processes[harq_pid]; - harq->frame=frame; - harq->slot=slot; - harq->handled = 0; - harq->status= NR_ACTIVE; - harq->new_rx = ulsch_pdu->pusch_data.new_data_indicator; - LOG_D(PHY,"ULSCH ID %d RNTI %x HARQ PID %d new data indicator %d\n",ulsch_id, ulsch_pdu->rnti, harq_pid, ulsch_pdu->pusch_data.new_data_indicator); - if (harq->new_rx) + ulsch->rnti = ulsch_pdu->rnti; + ulsch->harq_pid = harq_pid; + ulsch->handled = 0; + ulsch->active = true; + ulsch->frame = frame; + ulsch->slot = slot; + + NR_UL_gNB_HARQ_t *harq = ulsch->harq_process; + if (ulsch_pdu->pusch_data.new_data_indicator) + harq->harq_to_be_cleared = true; + LOG_D(PHY, + "%d.%d RNTI %x HARQ PID %d new data indicator %d\n", + frame, + slot, + ulsch_pdu->rnti, + harq_pid, + ulsch_pdu->pusch_data.new_data_indicator); + + if (ulsch_pdu->pusch_data.new_data_indicator) harq->round = 0; else harq->round++; - memcpy((void*)&ulsch->harq_processes[harq_pid]->ulsch_pdu, (void*)ulsch_pdu, sizeof(nfapi_nr_pusch_pdu_t)); + memcpy(&ulsch->harq_process->ulsch_pdu, ulsch_pdu, sizeof(ulsch->harq_process->ulsch_pdu)); - LOG_D(PHY,"Initializing nFAPI for ULSCH, UE %d, harq_pid %d\n",ulsch_id,harq_pid); + LOG_D(PHY, "Initializing nFAPI for ULSCH, harq_pid %d\n", harq_pid); +} +void reset_active_ulsch(PHY_VARS_gNB *gNB, int frame) +{ + // deactivate ULSCH structure after a given number of frames + // no activity on this structure for NUMBER_FRAMES_PHY_UE_INACTIVE + // assuming UE disconnected or some other error occurred + for (int i = 0; i < gNB->max_nb_pusch; i++) { + NR_gNB_ULSCH_t *ulsch = &gNB->ulsch[i]; + if (ulsch->active && (((frame - ulsch->frame + 1024) % 1024) > NUMBER_FRAMES_PHY_UE_INACTIVE)) + ulsch->active = false; + } } void nr_ulsch_unscrambling(int16_t* llr, uint32_t size, uint32_t Nid, uint32_t n_RNTI) @@ -92,11 +109,7 @@ void nr_ulsch_unscrambling(int16_t* llr, uint32_t size, uint32_t Nid, uint32_t n nr_codeword_unscrambling(llr, size, 0, Nid, n_RNTI); } -void nr_ulsch_layer_demapping(int16_t *llr_cw, - uint8_t Nl, - uint8_t mod_order, - uint32_t length, - int16_t **llr_layers) +void nr_ulsch_layer_demapping(int16_t *llr_cw, uint8_t Nl, uint8_t mod_order, uint32_t length, int16_t **llr_layers) { switch (Nl) { @@ -115,63 +128,55 @@ void nr_ulsch_layer_demapping(int16_t *llr_cw, } break; default: - AssertFatal(0, "Not supported number of layers %d\n", Nl); + AssertFatal(0, "Not supported number of layers %d\n", Nl); } } -void dump_pusch_stats(FILE *fd,PHY_VARS_gNB *gNB) { +void dump_pusch_stats(FILE *fd, PHY_VARS_gNB *gNB) +{ + for (int i = 0; i < MAX_MOBILES_PER_GNB; i++) { + NR_gNB_PHY_STATS_t *stats = &gNB->phy_stats[i]; + if (stats->active && stats->frame != stats->ulsch_stats.dump_frame) { + stats->ulsch_stats.dump_frame = stats->frame; + for (int aa = 0; aa < gNB->frame_parms.nb_antennas_rx; aa++) + if (aa == 0) + fprintf(fd, + "ULSCH RNTI %4x, %d: ulsch_power[%d] %d,%d ulsch_noise_power[%d] %d.%d, sync_pos %d\n", + stats->rnti, + stats->frame, + aa, + stats->ulsch_stats.power[aa] / 10, + stats->ulsch_stats.power[aa] % 10, + aa, + stats->ulsch_stats.noise_power[aa] / 10, + stats->ulsch_stats.noise_power[aa] % 10, + stats->ulsch_stats.sync_pos); + else + fprintf(fd, + " ulsch_power[%d] %d.%d, ulsch_noise_power[%d] %d.%d\n", + aa, + stats->ulsch_stats.power[aa] / 10, + stats->ulsch_stats.power[aa] % 10, + aa, + stats->ulsch_stats.noise_power[aa] / 10, + stats->ulsch_stats.noise_power[aa] % 10); - for (int i = 0;i < NUMBER_OF_NR_SCH_STATS_MAX;i++) { - - if (gNB->ulsch_stats[i].rnti>0 && gNB->ulsch_stats[i].frame != gNB->ulsch_stats[i].dump_frame) { - gNB->ulsch_stats[i].dump_frame = gNB->ulsch_stats[i].frame; - for (int aa=0;aaframe_parms.nb_antennas_rx;aa++) - if (aa==0) fprintf(fd,"ULSCH RNTI %4x, %d.%d: ulsch_power[%d] %d,%d ulsch_noise_power[%d] %d.%d, sync_pos %d\n", - gNB->ulsch_stats[i].rnti,gNB->ulsch_stats[i].frame,gNB->ulsch_stats[i].dump_frame, - aa,gNB->ulsch_stats[i].power[aa]/10,gNB->ulsch_stats[i].power[aa]%10, - aa,gNB->ulsch_stats[i].noise_power[aa]/10,gNB->ulsch_stats[i].noise_power[aa]%10, - gNB->ulsch_stats[i].sync_pos); - else fprintf(fd," ulsch_power[%d] %d.%d, ulsch_noise_power[%d] %d.%d\n", - aa,gNB->ulsch_stats[i].power[aa]/10,gNB->ulsch_stats[i].power[aa]%10, - aa,gNB->ulsch_stats[i].noise_power[aa]/10,gNB->ulsch_stats[i].noise_power[aa]%10); - - - fprintf(fd," round_trials %d(%1.1e):%d(%1.1e):%d(%1.1e):%d, DTX %d, current_Qm %d, current_RI %d, total_bytes RX/SCHED %d/%d\n", - gNB->ulsch_stats[i].round_trials[0], - (double)gNB->ulsch_stats[i].round_trials[1]/gNB->ulsch_stats[i].round_trials[0], - gNB->ulsch_stats[i].round_trials[1], - (double)gNB->ulsch_stats[i].round_trials[2]/gNB->ulsch_stats[i].round_trials[0], - gNB->ulsch_stats[i].round_trials[2], - (double)gNB->ulsch_stats[i].round_trials[3]/gNB->ulsch_stats[i].round_trials[0], - gNB->ulsch_stats[i].round_trials[3], - gNB->ulsch_stats[i].DTX, - gNB->ulsch_stats[i].current_Qm, - gNB->ulsch_stats[i].current_RI, - gNB->ulsch_stats[i].total_bytes_rx, - gNB->ulsch_stats[i].total_bytes_tx); + int *rt = stats->ulsch_stats.round_trials; + fprintf(fd, + " round_trials %d(%1.1e):%d(%1.1e):%d(%1.1e):%d, DTX %d, current_Qm %d, current_RI %d, total_bytes " + "RX/SCHED %d/%d\n", + rt[0], + (double)rt[1] / rt[0], + rt[1], + (double)rt[2] / rt[0], + rt[2], + (double)rt[3] / rt[0], + rt[3], + stats->ulsch_stats.DTX, + stats->ulsch_stats.current_Qm, + stats->ulsch_stats.current_RI, + stats->ulsch_stats.total_bytes_rx, + stats->ulsch_stats.total_bytes_tx); } - } + } } - -void clear_pusch_stats(PHY_VARS_gNB *gNB) { - - for (int i = 0; i < NUMBER_OF_NR_ULSCH_MAX; i++) - memset((void*)&gNB->ulsch_stats[i],0,sizeof(gNB->ulsch_stats[i])); -} - -NR_gNB_SCH_STATS_t *get_ulsch_stats(PHY_VARS_gNB *gNB,NR_gNB_ULSCH_t *ulsch) { - NR_gNB_SCH_STATS_t *stats=NULL; - int first_free=-1; - for (int i = 0; i < NUMBER_OF_NR_ULSCH_MAX; i++) { - if (gNB->ulsch_stats[i].rnti == 0 && first_free == -1) { - first_free = i; - stats=&gNB->ulsch_stats[i]; - } - if (gNB->ulsch_stats[i].rnti == ulsch->rnti) { - stats=&gNB->ulsch_stats[i]; - break; - } - } - return(stats); -} - diff --git a/openair1/PHY/NR_TRANSPORT/nr_ulsch.h b/openair1/PHY/NR_TRANSPORT/nr_ulsch.h index c7229bc5d0..f2028e6591 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_ulsch.h +++ b/openair1/PHY/NR_TRANSPORT/nr_ulsch.h @@ -33,10 +33,9 @@ #include "PHY/defs_gNB.h" #include "common/utils/threadPool/thread-pool.h" -void free_gNB_ulsch(NR_gNB_ULSCH_t **ulsch, uint16_t N_RB_UL); - -NR_gNB_ULSCH_t *new_gNB_ulsch(uint8_t max_ldpc_iterations, uint16_t N_RB_UL); +void free_gNB_ulsch(NR_gNB_ULSCH_t *ulsch, uint16_t N_RB_UL); +NR_gNB_ULSCH_t new_gNB_ulsch(uint8_t max_ldpc_iterations, uint16_t N_RB_UL); /*! \brief Perform PUSCH decoding. TS 38.212 V15.4.0 subclause 6.2 @param phy_vars_gNB, Pointer to PHY data structure for gNB @@ -82,11 +81,11 @@ void nr_ulsch_procedures(PHY_VARS_gNB *gNB, int slot_rx, int UE_id, uint8_t harq_pid); -int16_t find_nr_ulsch(uint16_t rnti, PHY_VARS_gNB *gNB,find_type_t type); + +NR_gNB_ULSCH_t *find_nr_ulsch(PHY_VARS_gNB *gNB, uint16_t rnti, int pid); void dump_pusch_stats(FILE *fd,PHY_VARS_gNB *gNB); void dump_nr_I0_stats(FILE *fd,PHY_VARS_gNB *gNB); -void clear_pusch_stats(PHY_VARS_gNB *gNB); NR_gNB_SCH_STATS_t *get_ulsch_stats(PHY_VARS_gNB *gNB,NR_gNB_ULSCH_t *ulsch); diff --git a/openair1/PHY/NR_TRANSPORT/nr_ulsch_decoding.c b/openair1/PHY/NR_TRANSPORT/nr_ulsch_decoding.c index 0bb872852b..410ffc89d5 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_ulsch_decoding.c +++ b/openair1/PHY/NR_TRANSPORT/nr_ulsch_decoding.c @@ -38,6 +38,7 @@ #include "PHY/CODING/lte_interleaver_inline.h" #include "PHY/CODING/nrLDPC_extern.h" #include "PHY/NR_TRANSPORT/nr_transport_common_proto.h" +#include "PHY/NR_TRANSPORT/nr_transport_proto.h" #include "PHY/NR_TRANSPORT/nr_ulsch.h" #include "PHY/NR_TRANSPORT/nr_dlsch.h" #include "SCHED_NR/sched_nr.h" @@ -54,42 +55,36 @@ //extern double cpuf; -void free_gNB_ulsch(NR_gNB_ULSCH_t **ulschptr, uint16_t N_RB_UL) +void free_gNB_ulsch(NR_gNB_ULSCH_t *ulsch, uint16_t N_RB_UL) { uint16_t a_segments = MAX_NUM_NR_ULSCH_SEGMENTS_PER_LAYER*NR_MAX_NB_LAYERS; //number of segments to be allocated - NR_gNB_ULSCH_t *ulsch = *ulschptr; if (N_RB_UL != 273) { a_segments = a_segments*N_RB_UL; a_segments = a_segments/273 +1; } - for (int i=0; iharq_processes[i]) { - if (ulsch->harq_processes[i]->b) { - free_and_zero(ulsch->harq_processes[i]->b); - ulsch->harq_processes[i]->b = NULL; - } - for (int r=0; rharq_processes[i]->c[r]); - free_and_zero(ulsch->harq_processes[i]->d[r]); - } - free_and_zero(ulsch->harq_processes[i]->c); - free_and_zero(ulsch->harq_processes[i]->d); - free_and_zero(ulsch->harq_processes[i]); - ulsch->harq_processes[i] = NULL; + if (ulsch->harq_process) { + if (ulsch->harq_process->b) { + free_and_zero(ulsch->harq_process->b); + ulsch->harq_process->b = NULL; } + for (int r = 0; r < a_segments; r++) { + free_and_zero(ulsch->harq_process->c[r]); + free_and_zero(ulsch->harq_process->d[r]); + } + free_and_zero(ulsch->harq_process->c); + free_and_zero(ulsch->harq_process->d); + free_and_zero(ulsch->harq_process->d_to_be_cleared); + free_and_zero(ulsch->harq_process); + ulsch->harq_process = NULL; } - free_and_zero(*ulschptr); } - -NR_gNB_ULSCH_t *new_gNB_ulsch(uint8_t max_ldpc_iterations, uint16_t N_RB_UL) +NR_gNB_ULSCH_t new_gNB_ulsch(uint8_t max_ldpc_iterations, uint16_t N_RB_UL) { - NR_gNB_ULSCH_t *ulsch; - uint8_t i,r; uint16_t a_segments = MAX_NUM_NR_ULSCH_SEGMENTS_PER_LAYER*NR_MAX_NB_LAYERS; //number of segments to be allocated if (N_RB_UL != 273) { @@ -97,205 +92,159 @@ NR_gNB_ULSCH_t *new_gNB_ulsch(uint8_t max_ldpc_iterations, uint16_t N_RB_UL) a_segments = a_segments/273 +1; } - uint32_t ulsch_bytes = a_segments*1056; // allocated bytes per segment - ulsch = (NR_gNB_ULSCH_t *)malloc16_clear(sizeof(NR_gNB_ULSCH_t)); + uint32_t ulsch_bytes = a_segments * 1056; // allocated bytes per segment + NR_gNB_ULSCH_t ulsch; - ulsch->max_ldpc_iterations = max_ldpc_iterations; + ulsch.max_ldpc_iterations = max_ldpc_iterations; + ulsch.harq_pid = -1; + ulsch.active = false; - for (i=0; iharq_processes[i] = (NR_UL_gNB_HARQ_t *)malloc16_clear(sizeof(NR_UL_gNB_HARQ_t)); - ulsch->harq_processes[i]->b = (uint8_t*)malloc16_clear(ulsch_bytes); - ulsch->harq_processes[i]->c = (uint8_t**)malloc16_clear(a_segments*sizeof(uint8_t *)); - ulsch->harq_processes[i]->d = (int16_t**)malloc16_clear(a_segments*sizeof(int16_t *)); - for (r=0; rharq_processes[i]->c[r] = (uint8_t*)malloc16_clear(8448*sizeof(uint8_t)); - ulsch->harq_processes[i]->d[r] = (int16_t*)malloc16_clear((68*384)*sizeof(int16_t)); - } + NR_UL_gNB_HARQ_t *harq = malloc16_clear(sizeof(*harq)); + ulsch.harq_process = harq; + harq->b = malloc16_clear(ulsch_bytes * sizeof(*harq->b)); + harq->c = malloc16_clear(a_segments * sizeof(*harq->c)); + harq->d = malloc16_clear(a_segments * sizeof(*harq->d)); + for (int r = 0; r < a_segments; r++) { + harq->c[r] = malloc16_clear(8448 * sizeof(*harq->c[r])); + harq->d[r] = malloc16_clear(68 * 384 * sizeof(*harq->d[r])); } - + harq->d_to_be_cleared = calloc(a_segments, sizeof(bool)); + AssertFatal(harq->d_to_be_cleared != NULL, "out of memory\n"); return(ulsch); } -void clean_gNB_ulsch(NR_gNB_ULSCH_t *ulsch) -{ - - - if (ulsch) { - ulsch->harq_mask = 0; - ulsch->rnti = 0; - ulsch->rnti_type = 0; - ulsch->max_ldpc_iterations = 0; - ulsch->last_iteration_cnt = 0; - - for (int i=0; iharq_processes[i]){ - /// Nfapi ULSCH PDU - //nfapi_nr_ul_config_ulsch_pdu ulsch_pdu; - ulsch->harq_processes[i]->frame=0; - ulsch->harq_processes[i]->slot=0; - ulsch->harq_processes[i]->round=0; - ulsch->harq_processes[i]->status=NR_SCH_IDLE; - ulsch->harq_processes[i]->handled=0; - ulsch->harq_processes[i]->TBS=0; - /// Pointer to the payload (38.212 V15.4.0 section 5.1) - //uint8_t *b; - ulsch->harq_processes[i]->B=0; - /// Pointers to code blocks after code block segmentation and CRC attachment (38.212 V15.4.0 section 5.2.2) - //uint8_t *c[MAX_NUM_NR_ULSCH_SEGMENTS]; - ulsch->harq_processes[i]->K=0; - ulsch->harq_processes[i]->F=0; - ulsch->harq_processes[i]->C=0; - /// Pointers to code blocks after LDPC coding (38.212 V15.4.0 section 5.3.2) - //int16_t *d[MAX_NUM_NR_ULSCH_SEGMENTS]; - ulsch->harq_processes[i]->Z=0; - /// code blocks after bit selection in rate matching for LDPC code (38.212 V15.4.0 section 5.4.2.1) - //int16_t e[MAX_NUM_NR_ULSCH_SEGMENTS][3*8448]; - ulsch->harq_processes[i]->E=0; - } - } - } -} - #ifdef PRINT_CRC_CHECK static uint32_t prnt_crc_cnt = 0; #endif -void nr_processULSegment(void* arg) { - ldpcDecode_t *rdata = (ldpcDecode_t*) arg; - PHY_VARS_gNB *phy_vars_gNB = rdata->gNB; - NR_UL_gNB_HARQ_t *ulsch_harq = rdata->ulsch_harq; - t_nrLDPC_dec_params *p_decoderParms = &rdata->decoderParms; - int length_dec; - int no_iteration_ldpc; - int Kr; - int Kr_bytes; - int K_bits_F; - uint8_t crc_type; - int i; - int j; - int r = rdata->segment_r; - int A = rdata->A; - int E = rdata->E; - int Qm = rdata->Qm; - int rv_index = rdata->rv_index; - int r_offset = rdata->r_offset; - uint8_t kc = rdata->Kc; - short* ulsch_llr = rdata->ulsch_llr; - int max_ldpc_iterations = p_decoderParms->numMaxIter; - int8_t llrProcBuf[OAI_UL_LDPC_MAX_NUM_LLR] __attribute__((aligned(32))); - - int16_t z [68*384 + 16] __attribute__ ((aligned(16))); - int8_t l [68*384 + 16] __attribute__ ((aligned(16))); - - __m128i *pv = (__m128i*)&z; - __m128i *pl = (__m128i*)&l; - - Kr = ulsch_harq->K; - Kr_bytes = Kr>>3; - K_bits_F = Kr-ulsch_harq->F; - - t_nrLDPC_time_stats procTime = {0}; - t_nrLDPC_time_stats* p_procTime = &procTime ; - - //start_meas(&phy_vars_gNB->ulsch_deinterleaving_stats); - - //////////////////////////////////////////////////////////////////////////////////////////// - ///////////////////////////////// nr_deinterleaving_ldpc /////////////////////////////////// - ////////////////////////////////////////////////////////////////////////////////////////// - - //////////////////////////// ulsch_llr =====> ulsch_harq->e ////////////////////////////// - - /// code blocks after bit selection in rate matching for LDPC code (38.212 V15.4.0 section 5.4.2.1) - int16_t harq_e[E]; - - nr_deinterleaving_ldpc(E, - Qm, - harq_e, - ulsch_llr+r_offset); - - //for (int i =0; i<16; i++) - // printf("rx output deinterleaving w[%d]= %d r_offset %d\n", i,ulsch_harq->w[r][i], r_offset); - - stop_meas(&phy_vars_gNB->ulsch_deinterleaving_stats); - - - ////////////////////////////////////////////////////////////////////////////////////////// - - - ////////////////////////////////////////////////////////////////////////////////////////// - //////////////////////////////// nr_rate_matching_ldpc_rx //////////////////////////////// - ////////////////////////////////////////////////////////////////////////////////////////// - - ///////////////////////// ulsch_harq->e =====> ulsch_harq->d ///////////////////////// - - //start_meas(&phy_vars_gNB->ulsch_rate_unmatching_stats); - - if (nr_rate_matching_ldpc_rx(rdata->tbslbrm, - p_decoderParms->BG, - p_decoderParms->Z, - ulsch_harq->d[r], - harq_e, - ulsch_harq->C, - rv_index, - ulsch_harq->new_rx, - E, - ulsch_harq->F, - Kr-ulsch_harq->F-2*(p_decoderParms->Z))==-1) { - - stop_meas(&phy_vars_gNB->ulsch_rate_unmatching_stats); - - LOG_E(PHY,"ulsch_decoding.c: Problem in rate_matching\n"); - rdata->decodeIterations = max_ldpc_iterations + 1; - return; - } else { - stop_meas(&phy_vars_gNB->ulsch_rate_unmatching_stats); - } - - memset(ulsch_harq->c[r],0,Kr_bytes); - - if (ulsch_harq->C == 1) { - if (A > 3824) - crc_type = CRC24_A; - else - crc_type = CRC16; - - length_dec = ulsch_harq->B; - } - else { - crc_type = CRC24_B; - length_dec = (ulsch_harq->B+24*ulsch_harq->C)/ulsch_harq->C; - } - - //start_meas(&phy_vars_gNB->ulsch_ldpc_decoding_stats); - - //set first 2*Z_c bits to zeros - memset(&z[0],0,2*ulsch_harq->Z*sizeof(int16_t)); - //set Filler bits - memset((&z[0]+K_bits_F),127,ulsch_harq->F*sizeof(int16_t)); - //Move coded bits before filler bits - memcpy((&z[0]+2*ulsch_harq->Z),ulsch_harq->d[r],(K_bits_F-2*ulsch_harq->Z)*sizeof(int16_t)); - //skip filler bits - memcpy((&z[0]+Kr),ulsch_harq->d[r]+(Kr-2*ulsch_harq->Z),(kc*ulsch_harq->Z-Kr)*sizeof(int16_t)); - //Saturate coded bits before decoding into 8 bits values - for (i=0, j=0; j < ((kc*ulsch_harq->Z)>>4)+1; i+=2, j++) + void nr_processULSegment(void *arg) { - pl[j] = _mm_packs_epi16(pv[i],pv[i+1]); - } - ////////////////////////////////////////////////////////////////////////////////////////// + ldpcDecode_t *rdata = (ldpcDecode_t *)arg; + PHY_VARS_gNB *phy_vars_gNB = rdata->gNB; + NR_UL_gNB_HARQ_t *ulsch_harq = rdata->ulsch_harq; + t_nrLDPC_dec_params *p_decoderParms = &rdata->decoderParms; + int length_dec; + int no_iteration_ldpc; + int Kr; + int Kr_bytes; + int K_bits_F; + uint8_t crc_type; + int i; + int j; + int r = rdata->segment_r; + int A = rdata->A; + int E = rdata->E; + int Qm = rdata->Qm; + int rv_index = rdata->rv_index; + int r_offset = rdata->r_offset; + uint8_t kc = rdata->Kc; + short *ulsch_llr = rdata->ulsch_llr; + int max_ldpc_iterations = p_decoderParms->numMaxIter; + int8_t llrProcBuf[OAI_UL_LDPC_MAX_NUM_LLR] __attribute__((aligned(32))); + int16_t z[68 * 384 + 16] __attribute__((aligned(16))); + int8_t l[68 * 384 + 16] __attribute__((aligned(16))); - ////////////////////////////////////////////////////////////////////////////////////////// - ///////////////////////////////////// nrLDPC_decoder ///////////////////////////////////// - ////////////////////////////////////////////////////////////////////////////////////////// + __m128i *pv = (__m128i *)&z; + __m128i *pl = (__m128i *)&l; - ////////////////////////////////// pl =====> llrProcBuf ////////////////////////////////// - p_decoderParms->block_length = length_dec; - no_iteration_ldpc = nrLDPC_decoder(p_decoderParms, - (int8_t*)&pl[0], - llrProcBuf, - p_procTime); + Kr = ulsch_harq->K; + Kr_bytes = Kr >> 3; + K_bits_F = Kr - ulsch_harq->F; - if (check_crc((uint8_t*)llrProcBuf,length_dec,ulsch_harq->F,crc_type)) { + t_nrLDPC_time_stats procTime = {0}; + t_nrLDPC_time_stats *p_procTime = &procTime; + + // start_meas(&phy_vars_gNB->ulsch_deinterleaving_stats); + + //////////////////////////////////////////////////////////////////////////////////////////// + ///////////////////////////////// nr_deinterleaving_ldpc /////////////////////////////////// + ////////////////////////////////////////////////////////////////////////////////////////// + + //////////////////////////// ulsch_llr =====> ulsch_harq->e ////////////////////////////// + + /// code blocks after bit selection in rate matching for LDPC code (38.212 V15.4.0 section 5.4.2.1) + int16_t harq_e[E]; + + nr_deinterleaving_ldpc(E, Qm, harq_e, ulsch_llr + r_offset); + + // for (int i =0; i<16; i++) + // printf("rx output deinterleaving w[%d]= %d r_offset %d\n", i,ulsch_harq->w[r][i], r_offset); + + stop_meas(&phy_vars_gNB->ulsch_deinterleaving_stats); + + ////////////////////////////////////////////////////////////////////////////////////////// + + ////////////////////////////////////////////////////////////////////////////////////////// + //////////////////////////////// nr_rate_matching_ldpc_rx //////////////////////////////// + ////////////////////////////////////////////////////////////////////////////////////////// + + ///////////////////////// ulsch_harq->e =====> ulsch_harq->d ///////////////////////// + + // start_meas(&phy_vars_gNB->ulsch_rate_unmatching_stats); + + if (nr_rate_matching_ldpc_rx(rdata->tbslbrm, + p_decoderParms->BG, + p_decoderParms->Z, + ulsch_harq->d[r], + harq_e, + ulsch_harq->C, + rv_index, + ulsch_harq->d_to_be_cleared[r], + E, + ulsch_harq->F, + Kr - ulsch_harq->F - 2 * (p_decoderParms->Z)) + == -1) { + stop_meas(&phy_vars_gNB->ulsch_rate_unmatching_stats); + + LOG_E(PHY, "ulsch_decoding.c: Problem in rate_matching\n"); + rdata->decodeIterations = max_ldpc_iterations + 1; + return; + } else { + stop_meas(&phy_vars_gNB->ulsch_rate_unmatching_stats); + } + + ulsch_harq->d_to_be_cleared[r] = false; + + memset(ulsch_harq->c[r], 0, Kr_bytes); + + if (ulsch_harq->C == 1) { + if (A > 3824) + crc_type = CRC24_A; + else + crc_type = CRC16; + + length_dec = ulsch_harq->B; + } else { + crc_type = CRC24_B; + length_dec = (ulsch_harq->B + 24 * ulsch_harq->C) / ulsch_harq->C; + } + + // start_meas(&phy_vars_gNB->ulsch_ldpc_decoding_stats); + + // set first 2*Z_c bits to zeros + memset(&z[0], 0, 2 * ulsch_harq->Z * sizeof(int16_t)); + // set Filler bits + memset((&z[0] + K_bits_F), 127, ulsch_harq->F * sizeof(int16_t)); + // Move coded bits before filler bits + memcpy((&z[0] + 2 * ulsch_harq->Z), ulsch_harq->d[r], (K_bits_F - 2 * ulsch_harq->Z) * sizeof(int16_t)); + // skip filler bits + memcpy((&z[0] + Kr), ulsch_harq->d[r] + (Kr - 2 * ulsch_harq->Z), (kc * ulsch_harq->Z - Kr) * sizeof(int16_t)); + // Saturate coded bits before decoding into 8 bits values + for (i = 0, j = 0; j < ((kc * ulsch_harq->Z) >> 4) + 1; i += 2, j++) { + pl[j] = _mm_packs_epi16(pv[i], pv[i + 1]); + } + ////////////////////////////////////////////////////////////////////////////////////////// + + ////////////////////////////////////////////////////////////////////////////////////////// + ///////////////////////////////////// nrLDPC_decoder ///////////////////////////////////// + ////////////////////////////////////////////////////////////////////////////////////////// + + ////////////////////////////////// pl =====> llrProcBuf ////////////////////////////////// + p_decoderParms->block_length = length_dec; + no_iteration_ldpc = nrLDPC_decoder(p_decoderParms, (int8_t *)&pl[0], llrProcBuf, p_procTime); + + if (check_crc((uint8_t *)llrProcBuf, length_dec, ulsch_harq->F, crc_type)) { #ifdef PRINT_CRC_CHECK LOG_I(PHY,"Segment %d CRC OK, iterations %d/%d\n",r,no_iteration_ldpc,max_ldpc_iterations); #endif @@ -313,7 +262,7 @@ void nr_processULSegment(void* arg) { } //stop_meas(&phy_vars_gNB->ulsch_ldpc_decoding_stats); -} + } uint32_t nr_ulsch_decoding(PHY_VARS_gNB *phy_vars_gNB, uint8_t ULSCH_id, @@ -328,11 +277,10 @@ uint32_t nr_ulsch_decoding(PHY_VARS_gNB *phy_vars_gNB, #ifdef PRINT_CRC_CHECK prnt_crc_cnt++; #endif - - NR_gNB_ULSCH_t *ulsch = phy_vars_gNB->ulsch[ULSCH_id]; - NR_gNB_PUSCH *pusch = phy_vars_gNB->pusch_vars[ULSCH_id]; - NR_UL_gNB_HARQ_t *harq_process = ulsch->harq_processes[harq_pid]; + NR_gNB_ULSCH_t *ulsch = &phy_vars_gNB->ulsch[ULSCH_id]; + NR_gNB_PUSCH *pusch = &phy_vars_gNB->pusch_vars[ULSCH_id]; + NR_UL_gNB_HARQ_t *harq_process = ulsch->harq_process; if (!harq_process) { LOG_E(PHY,"ulsch_decoding.c: NULL harq_process pointer\n"); @@ -369,7 +317,7 @@ uint32_t nr_ulsch_decoding(PHY_VARS_gNB *phy_vars_gNB, float Coderate = (float) pusch_pdu->target_code_rate / 10240.0f; LOG_D(PHY,"ULSCH Decoding, harq_pid %d rnti %x TBS %d G %d mcs %d Nl %d nb_rb %d, Qm %d, Coderate %f RV %d round %d new RX %d\n", - harq_pid, ulsch->rnti, A, G, mcs, n_layers, nb_rb, Qm, Coderate, pusch_pdu->pusch_data.rv_index, harq_process->round, harq_process->new_rx); + harq_pid, ulsch->rnti, A, G, mcs, n_layers, nb_rb, Qm, Coderate, pusch_pdu->pusch_data.rv_index, harq_process->round, harq_process->harq_to_be_cleared); t_nrLDPC_dec_params decParams = {0}; decParams.BG = pusch_pdu->maintenance_parms_v3.ldpcBaseGraph; int kc; @@ -379,30 +327,18 @@ uint32_t nr_ulsch_decoding(PHY_VARS_gNB *phy_vars_gNB, kc = 68; } - NR_gNB_SCH_STATS_t *stats=NULL; - int first_free=-1; - for (int i=0;iulsch_stats[i].rnti == 0 && first_free == -1) { - first_free = i; - stats=&phy_vars_gNB->ulsch_stats[i]; - } - if (phy_vars_gNB->ulsch_stats[i].rnti == ulsch->rnti) { - stats=&phy_vars_gNB->ulsch_stats[i]; - break; - } - } + NR_gNB_PHY_STATS_t *stats = get_phy_stats(phy_vars_gNB, ulsch->rnti); if (stats) { stats->frame = frame; - stats->rnti = ulsch->rnti; - stats->round_trials[harq_process->round]++; - for (int aarx=0;aarxnb_antennas_rx;aarx++) { - stats->power[aarx] = dB_fixed_x10(pusch->ulsch_power[aarx]); - stats->noise_power[aarx] = dB_fixed_x10(pusch->ulsch_noise_power[aarx]); + stats->ulsch_stats.round_trials[harq_process->round]++; + for (int aarx = 0; aarx < frame_parms->nb_antennas_rx; aarx++) { + stats->ulsch_stats.power[aarx] = dB_fixed_x10(pusch->ulsch_power[aarx]); + stats->ulsch_stats.noise_power[aarx] = dB_fixed_x10(pusch->ulsch_noise_power[aarx]); } - if (harq_process->new_rx == 0) { - stats->current_Qm = Qm; - stats->current_RI = n_layers; - stats->total_bytes_tx += harq_process->TBS; + if (!harq_process->harq_to_be_cleared) { + stats->ulsch_stats.current_Qm = Qm; + stats->ulsch_stats.current_RI = n_layers; + stats->ulsch_stats.total_bytes_tx += harq_process->TBS; } } if (A > 3824) @@ -452,6 +388,13 @@ uint32_t nr_ulsch_decoding(PHY_VARS_gNB *phy_vars_gNB, #ifdef DEBUG_ULSCH_DECODING printf("Segmentation: C %d, K %d\n",harq_process->C,harq_process->K); #endif + + if (harq_process->harq_to_be_cleared) { + for (int r = 0; r < harq_process->C; r++) + harq_process->d_to_be_cleared[r] = true; + harq_process->harq_to_be_cleared = false; + } + Kr = harq_process->K; Kr_bytes = Kr >> 3; @@ -523,7 +466,7 @@ uint32_t nr_ulsch_decoding(PHY_VARS_gNB *phy_vars_gNB, harq_e, harq_process->C, pusch_pdu->pusch_data.rv_index, - harq_process->new_rx, + harq_process->d_to_be_cleared[r], E, harq_process->F, Kr - harq_process->F - 2 * (decParams.Z)) @@ -533,6 +476,8 @@ uint32_t nr_ulsch_decoding(PHY_VARS_gNB *phy_vars_gNB, return 1; } + harq_process->d_to_be_cleared[r] = false; + // set first 2*Z_c bits to zeros memset(&z[0], 0, 2 * harq_process->Z * sizeof(int16_t)); // set Filler bits @@ -592,29 +537,28 @@ uint32_t nr_ulsch_decoding(PHY_VARS_gNB *phy_vars_gNB, VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_gNB_ULSCH_DECODING, 0); - if (harq_process->processedSegments == (harq_process->C)) { - LOG_D(PHY, "[gNB %d] ULSCH: Setting ACK for slot %d TBS %d\n", phy_vars_gNB->Mod_id, harq_process->slot, harq_process->TBS); - harq_process->status = NR_SCH_IDLE; + if (harq_process->processedSegments == harq_process->C) { + LOG_D(PHY, "[gNB %d] ULSCH: Setting ACK for slot %d TBS %d\n", phy_vars_gNB->Mod_id, ulsch->slot, harq_process->TBS); + ulsch->active = false; harq_process->round = 0; - ulsch->harq_mask &= ~(1 << harq_pid); LOG_D(PHY, "ULSCH received ok \n"); - nr_fill_indication(phy_vars_gNB, harq_process->frame, harq_process->slot, ULSCH_id, harq_pid, 0, 0); + nr_fill_indication(phy_vars_gNB, ulsch->frame, ulsch->slot, ULSCH_id, harq_pid, 0, 0); } else { LOG_D(PHY, "[gNB %d] ULSCH: Setting NAK for SFN/SF %d/%d (pid %d, status %d, round %d, TBS %d)\n", phy_vars_gNB->Mod_id, - harq_process->frame, - harq_process->slot, + ulsch->frame, + ulsch->slot, harq_pid, - harq_process->status, + ulsch->active, harq_process->round, harq_process->TBS); - harq_process->handled = 1; + ulsch->handled = 1; no_iteration_ldpc = ulsch->max_ldpc_iterations + 1; LOG_D(PHY, "ULSCH %d in error\n", ULSCH_id); - nr_fill_indication(phy_vars_gNB, harq_process->frame, harq_process->slot, ULSCH_id, harq_pid, 1, 0); + nr_fill_indication(phy_vars_gNB, ulsch->frame, ulsch->slot, ULSCH_id, harq_pid, 1, 0); } ulsch->last_iteration_cnt = no_iteration_ldpc; } diff --git a/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c b/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c index 47d778903e..f0a52b9c8e 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c +++ b/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c @@ -1847,11 +1847,13 @@ void nr_rx_pusch(PHY_VARS_gNB *gNB, int avgs = 0; NR_DL_FRAME_PARMS *frame_parms = &gNB->frame_parms; - nfapi_nr_pusch_pdu_t *rel15_ul = &gNB->ulsch[ulsch_id]->harq_processes[harq_pid]->ulsch_pdu; + NR_gNB_ULSCH_t *ulsch = &gNB->ulsch[ulsch_id]; + nfapi_nr_pusch_pdu_t *rel15_ul = &ulsch->harq_process->ulsch_pdu; int avg[frame_parms->nb_antennas_rx*rel15_ul->nrOfLayers]; - gNB->pusch_vars[ulsch_id]->dmrs_symbol = INVALID_VALUE; - gNB->pusch_vars[ulsch_id]->cl_done = 0; + NR_gNB_PUSCH *pusch_vars = &gNB->pusch_vars[ulsch_id]; + pusch_vars->dmrs_symbol = INVALID_VALUE; + pusch_vars->cl_done = 0; bwp_start_subcarrier = ((rel15_ul->rb_start + rel15_ul->bwp_start)*NR_NB_SC_PER_RB + frame_parms->first_carrier_offset) % frame_parms->ofdm_symbol_size; LOG_D(PHY,"pusch %d.%d : bwp_start_subcarrier %d, rb_start %d, first_carrier_offset %d\n", frame,slot,bwp_start_subcarrier, rel15_ul->rb_start, frame_parms->first_carrier_offset); @@ -1870,8 +1872,8 @@ void nr_rx_pusch(PHY_VARS_gNB *gNB, LOG_D(PHY, "symbol %d, dmrs_symbol_flag :%d\n", symbol, dmrs_symbol_flag); if (dmrs_symbol_flag == 1) { - if (gNB->pusch_vars[ulsch_id]->dmrs_symbol == INVALID_VALUE) - gNB->pusch_vars[ulsch_id]->dmrs_symbol = symbol; + if (pusch_vars->dmrs_symbol == INVALID_VALUE) + pusch_vars->dmrs_symbol = symbol; for (int nl=0; nlnrOfLayers; nl++) { @@ -1885,40 +1887,44 @@ void nr_rx_pusch(PHY_VARS_gNB *gNB, &max_ch); } - nr_gnb_measurements(gNB, ulsch_id, harq_pid, symbol,rel15_ul->nrOfLayers); + nr_gnb_measurements(gNB, ulsch, pusch_vars, symbol, rel15_ul->nrOfLayers); for (aarx = 0; aarx < frame_parms->nb_antennas_rx; aarx++) { if (symbol == rel15_ul->start_symbol_index) { - gNB->pusch_vars[ulsch_id]->ulsch_power[aarx] = 0; - gNB->pusch_vars[ulsch_id]->ulsch_noise_power[aarx] = 0; + pusch_vars->ulsch_power[aarx] = 0; + pusch_vars->ulsch_noise_power[aarx] = 0; } for (aatx = 0; aatx < rel15_ul->nrOfLayers; aatx++) { - gNB->pusch_vars[ulsch_id]->ulsch_power[aarx] += signal_energy_nodc( - &gNB->pusch_vars[ulsch_id]->ul_ch_estimates[aatx*gNB->frame_parms.nb_antennas_rx+aarx][symbol * frame_parms->ofdm_symbol_size], - rel15_ul->rb_size * 12); + pusch_vars->ulsch_power[aarx] += signal_energy_nodc( + &pusch_vars->ul_ch_estimates[aatx * gNB->frame_parms.nb_antennas_rx + aarx][symbol * frame_parms->ofdm_symbol_size], + rel15_ul->rb_size * 12); } for (int rb = 0; rb < rel15_ul->rb_size; rb++) { - gNB->pusch_vars[ulsch_id]->ulsch_noise_power[aarx] += - gNB->measurements.n0_subband_power[aarx][rel15_ul->bwp_start + rel15_ul->rb_start + rb] / - rel15_ul->rb_size; + pusch_vars->ulsch_noise_power[aarx] += + gNB->measurements.n0_subband_power[aarx][rel15_ul->bwp_start + rel15_ul->rb_start + rb] / rel15_ul->rb_size; } - LOG_D(PHY,"aa %d, bwp_start%d, rb_start %d, rb_size %d: ulsch_power %d, ulsch_noise_power %d\n",aarx, - rel15_ul->bwp_start,rel15_ul->rb_start,rel15_ul->rb_size, - gNB->pusch_vars[ulsch_id]->ulsch_power[aarx], - gNB->pusch_vars[ulsch_id]->ulsch_noise_power[aarx]); + LOG_D(PHY, + "aa %d, bwp_start%d, rb_start %d, rb_size %d: ulsch_power %d, ulsch_noise_power %d\n", + aarx, + rel15_ul->bwp_start, + rel15_ul->rb_start, + rel15_ul->rb_size, + pusch_vars->ulsch_power[aarx], + pusch_vars->ulsch_noise_power[aarx]); } } } if (gNB->chest_time == 1) { // averaging time domain channel estimates nr_chest_time_domain_avg(frame_parms, - gNB->pusch_vars[ulsch_id]->ul_ch_estimates, + pusch_vars->ul_ch_estimates, rel15_ul->nr_of_symbols, rel15_ul->start_symbol_index, rel15_ul->ul_dmrs_symb_pos, rel15_ul->rb_size); - gNB->pusch_vars[ulsch_id]->dmrs_symbol = get_next_dmrs_symbol_in_slot(rel15_ul->ul_dmrs_symb_pos, rel15_ul->start_symbol_index, rel15_ul->nr_of_symbols); + pusch_vars->dmrs_symbol = + get_next_dmrs_symbol_in_slot(rel15_ul->ul_dmrs_symb_pos, rel15_ul->start_symbol_index, rel15_ul->nr_of_symbols); } stop_meas(&gNB->ulsch_channel_estimation_stats); @@ -1940,7 +1946,7 @@ void nr_rx_pusch(PHY_VARS_gNB *gNB, AssertFatal(1==0,"Double DMRS configuration is not yet supported\n"); if (gNB->chest_time == 0) // Non averaging time domain channel estimates - gNB->pusch_vars[ulsch_id]->dmrs_symbol = symbol; + pusch_vars->dmrs_symbol = symbol; if (rel15_ul->dmrs_config_type == 0) { // if no data in dmrs cdm group is 1 only even REs have no data @@ -1955,29 +1961,23 @@ void nr_rx_pusch(PHY_VARS_gNB *gNB, nb_re_pusch = rel15_ul->rb_size * NR_NB_SC_PER_RB; } - gNB->pusch_vars[ulsch_id]->ul_valid_re_per_slot[symbol] = nb_re_pusch; - LOG_D(PHY,"symbol %d: nb_re_pusch %d, DMRS symbl used for Chest :%d \n", symbol, nb_re_pusch, gNB->pusch_vars[ulsch_id]->dmrs_symbol); + pusch_vars->ul_valid_re_per_slot[symbol] = nb_re_pusch; + LOG_D(PHY, "symbol %d: nb_re_pusch %d, DMRS symbl used for Chest :%d \n", symbol, nb_re_pusch, pusch_vars->dmrs_symbol); //---------------------------------------------------------- //--------------------- RBs extraction --------------------- //---------------------------------------------------------- if (nb_re_pusch > 0) { start_meas(&gNB->ulsch_rbs_extraction_stats); - nr_ulsch_extract_rbs(gNB->common_vars.rxdataF, - gNB->pusch_vars[ulsch_id], - slot, - symbol, - dmrs_symbol_flag, - rel15_ul, - frame_parms); + nr_ulsch_extract_rbs(gNB->common_vars.rxdataF, pusch_vars, slot, symbol, dmrs_symbol_flag, rel15_ul, frame_parms); stop_meas(&gNB->ulsch_rbs_extraction_stats); //---------------------------------------------------------- //--------------------- Channel Scaling -------------------- //---------------------------------------------------------- - nr_ulsch_scale_channel(gNB->pusch_vars[ulsch_id]->ul_ch_estimates_ext, + nr_ulsch_scale_channel(pusch_vars->ul_ch_estimates_ext, frame_parms, - gNB->ulsch[ulsch_id], + ulsch, symbol, dmrs_symbol_flag, nb_re_pusch, @@ -1985,14 +1985,14 @@ void nr_rx_pusch(PHY_VARS_gNB *gNB, rel15_ul->rb_size, shift_ch_ext); - if (gNB->pusch_vars[ulsch_id]->cl_done==0) { - nr_ulsch_channel_level(gNB->pusch_vars[ulsch_id]->ul_ch_estimates_ext, - frame_parms, - avg, - symbol, - nb_re_pusch, - rel15_ul->nrOfLayers, - rel15_ul->rb_size); + if (pusch_vars->cl_done == 0) { + nr_ulsch_channel_level(pusch_vars->ul_ch_estimates_ext, + frame_parms, + avg, + symbol, + nb_re_pusch, + rel15_ul->nrOfLayers, + rel15_ul->rb_size); avgs = 0; @@ -2000,24 +2000,24 @@ void nr_rx_pusch(PHY_VARS_gNB *gNB, for (aarx=0;aarxnb_antennas_rx;aarx++) avgs = cmax(avgs,avg[aatx*frame_parms->nb_antennas_rx+aarx]); - gNB->pusch_vars[ulsch_id]->log2_maxh = (log2_approx(avgs) >> 1) + ad_shift; - if (gNB->pusch_vars[ulsch_id]->log2_maxh < 0) { - gNB->pusch_vars[ulsch_id]->log2_maxh = 0; + pusch_vars->log2_maxh = (log2_approx(avgs) >> 1) + ad_shift; + if (pusch_vars->log2_maxh < 0) { + pusch_vars->log2_maxh = 0; } - gNB->pusch_vars[ulsch_id]->cl_done = 1; + pusch_vars->cl_done = 1; } //---------------------------------------------------------- //--------------------- Channel Compensation --------------- //---------------------------------------------------------- start_meas(&gNB->ulsch_channel_compensation_stats); - LOG_D(PHY,"Doing channel compensations log2_maxh %d, avgs %d (%d,%d)\n",gNB->pusch_vars[ulsch_id]->log2_maxh,avgs,avg[0],avg[1]); - nr_ulsch_channel_compensation(gNB->pusch_vars[ulsch_id]->rxdataF_ext, - gNB->pusch_vars[ulsch_id]->ul_ch_estimates_ext, - gNB->pusch_vars[ulsch_id]->ul_ch_mag0, - gNB->pusch_vars[ulsch_id]->ul_ch_magb0, - gNB->pusch_vars[ulsch_id]->rxdataF_comp, - (rel15_ul->nrOfLayers>1) ? gNB->pusch_vars[ulsch_id]->rho : NULL, + LOG_D(PHY, "Doing channel compensations log2_maxh %d, avgs %d (%d,%d)\n", pusch_vars->log2_maxh, avgs, avg[0], avg[1]); + nr_ulsch_channel_compensation(pusch_vars->rxdataF_ext, + pusch_vars->ul_ch_estimates_ext, + pusch_vars->ul_ch_mag0, + pusch_vars->ul_ch_magb0, + pusch_vars->rxdataF_comp, + (rel15_ul->nrOfLayers > 1) ? pusch_vars->rho : NULL, frame_parms, symbol, nb_re_pusch, @@ -2025,15 +2025,15 @@ void nr_rx_pusch(PHY_VARS_gNB *gNB, rel15_ul->qam_mod_order, rel15_ul->nrOfLayers, rel15_ul->rb_size, - gNB->pusch_vars[ulsch_id]->log2_maxh); + pusch_vars->log2_maxh); stop_meas(&gNB->ulsch_channel_compensation_stats); start_meas(&gNB->ulsch_mrc_stats); nr_ulsch_detection_mrc(frame_parms, - gNB->pusch_vars[ulsch_id]->rxdataF_comp, - gNB->pusch_vars[ulsch_id]->ul_ch_mag0, - gNB->pusch_vars[ulsch_id]->ul_ch_magb0, - (rel15_ul->nrOfLayers>1) ? gNB->pusch_vars[ulsch_id]->rho : NULL, + pusch_vars->rxdataF_comp, + pusch_vars->ul_ch_mag0, + pusch_vars->ul_ch_magb0, + (rel15_ul->nrOfLayers > 1) ? pusch_vars->rho : NULL, rel15_ul->nrOfLayers, symbol, rel15_ul->rb_size, @@ -2042,14 +2042,14 @@ void nr_rx_pusch(PHY_VARS_gNB *gNB, //Apply zero forcing for 2 Tx layers if (rel15_ul->nrOfLayers == 2) { nr_ulsch_zero_forcing_rx_2layers(frame_parms, - gNB->pusch_vars[ulsch_id]->rxdataF_comp, - gNB->pusch_vars[ulsch_id]->ul_ch_mag0, - gNB->pusch_vars[ulsch_id]->ul_ch_magb0, - gNB->pusch_vars[ulsch_id]->ul_ch_estimates_ext, + pusch_vars->rxdataF_comp, + pusch_vars->ul_ch_mag0, + pusch_vars->ul_ch_magb0, + pusch_vars->ul_ch_estimates_ext, rel15_ul->rb_size, frame_parms->nb_antennas_rx, rel15_ul->qam_mod_order, - gNB->pusch_vars[ulsch_id]->log2_maxh, + pusch_vars->log2_maxh, symbol, nb_re_pusch); } @@ -2061,7 +2061,7 @@ void nr_rx_pusch(PHY_VARS_gNB *gNB, int nb_re_pusch2 = nb_re_pusch + (nb_re_pusch&7); // perform IDFT operation on the compensated rxdata if transform precoding is enabled - nr_idft(&gNB->pusch_vars[ulsch_id]->rxdataF_comp[0][symbol * nb_re_pusch2], nb_re_pusch); + nr_idft(&pusch_vars->rxdataF_comp[0][symbol * nb_re_pusch2], nb_re_pusch); LOG_D(PHY,"Transform precoding being done on data- symbol: %d, nb_re_pusch: %d\n", symbol, nb_re_pusch); } @@ -2082,7 +2082,7 @@ void nr_rx_pusch(PHY_VARS_gNB *gNB, stop_meas(&gNB->ulsch_ptrs_processing_stats); /* Subtract total PTRS RE's in the symbol from PUSCH RE's */ - gNB->pusch_vars[ulsch_id]->ul_valid_re_per_slot[symbol] -= gNB->pusch_vars[ulsch_id]->ptrs_re_per_slot; + pusch_vars->ul_valid_re_per_slot[symbol] -= pusch_vars->ptrs_re_per_slot; } /*---------------------------------------------------------------------------------------------------- */ @@ -2090,17 +2090,18 @@ void nr_rx_pusch(PHY_VARS_gNB *gNB, /*-----------------------------------------------------------------------------------------------------*/ start_meas(&gNB->ulsch_llr_stats); for (aatx=0; aatx < rel15_ul->nrOfLayers; aatx++) { - nr_ulsch_compute_llr(&gNB->pusch_vars[ulsch_id]->rxdataF_comp[aatx*frame_parms->nb_antennas_rx][symbol * (off + rel15_ul->rb_size * NR_NB_SC_PER_RB)], - gNB->pusch_vars[ulsch_id]->ul_ch_mag0[aatx*frame_parms->nb_antennas_rx], - gNB->pusch_vars[ulsch_id]->ul_ch_magb0[aatx*frame_parms->nb_antennas_rx], - &gNB->pusch_vars[ulsch_id]->llr_layers[aatx][rxdataF_ext_offset * rel15_ul->qam_mod_order], - rel15_ul->rb_size, - gNB->pusch_vars[ulsch_id]->ul_valid_re_per_slot[symbol], - symbol, - rel15_ul->qam_mod_order); + nr_ulsch_compute_llr( + &pusch_vars->rxdataF_comp[aatx * frame_parms->nb_antennas_rx][symbol * (off + rel15_ul->rb_size * NR_NB_SC_PER_RB)], + pusch_vars->ul_ch_mag0[aatx * frame_parms->nb_antennas_rx], + pusch_vars->ul_ch_magb0[aatx * frame_parms->nb_antennas_rx], + &pusch_vars->llr_layers[aatx][rxdataF_ext_offset * rel15_ul->qam_mod_order], + rel15_ul->rb_size, + pusch_vars->ul_valid_re_per_slot[symbol], + symbol, + rel15_ul->qam_mod_order); } stop_meas(&gNB->ulsch_llr_stats); - rxdataF_ext_offset += gNB->pusch_vars[ulsch_id]->ul_valid_re_per_slot[symbol]; + rxdataF_ext_offset += pusch_vars->ul_valid_re_per_slot[symbol]; } } // symbol loop } diff --git a/openair1/PHY/NR_TRANSPORT/pucch_rx.c b/openair1/PHY/NR_TRANSPORT/pucch_rx.c index 99a3439420..71db65a14e 100644 --- a/openair1/PHY/NR_TRANSPORT/pucch_rx.c +++ b/openair1/PHY/NR_TRANSPORT/pucch_rx.c @@ -44,55 +44,17 @@ #include "PHY/NR_UE_TRANSPORT/pucch_nr.h" #include #include "PHY/NR_TRANSPORT/nr_transport_common_proto.h" +#include "PHY/NR_TRANSPORT/nr_transport_proto.h" #include "PHY/NR_REFSIG/nr_refsig.h" #include "common/utils/LOG/log.h" #include "common/utils/LOG/vcd_signal_dumper.h" #include "nfapi/oai_integration/vendor_ext.h" - #include "nfapi/oai_integration/vendor_ext.h" #include "T.h" //#define DEBUG_NR_PUCCH_RX 1 -NR_gNB_PUCCH_t *new_gNB_pucch(void){ - NR_gNB_PUCCH_t *pucch; - pucch = (NR_gNB_PUCCH_t *)malloc16(sizeof(NR_gNB_PUCCH_t)); - pucch->active = 0; - return (pucch); -} - -void free_gNB_pucch(NR_gNB_PUCCH_t *pucch) -{ - free_and_zero(pucch); -} - -int nr_find_pucch(uint16_t rnti, - int frame, - int slot, - PHY_VARS_gNB *gNB) -{ - - AssertFatal(gNB!=NULL,"gNB is null\n"); - int index = -1; - - for (int i = 0; i < gNB->max_nb_pucch; i++) { - AssertFatal(gNB->pucch[i] != NULL,"gNB->pucch[%d] is null\n",i); - if ((gNB->pucch[i]->active > 0) && - (gNB->pucch[i]->pucch_pdu.rnti == rnti) && - (gNB->pucch[i]->frame == frame) && - (gNB->pucch[i]->slot == slot)) - return i; - else if ((gNB->pucch[i]->active == 0) && (index == -1)) - index = i; - } - - if (index==-1) - LOG_E(MAC,"PUCCH list is full\n"); - - return(index); -} - void nr_fill_pucch(PHY_VARS_gNB *gNB, int frame, int slot, @@ -100,19 +62,30 @@ void nr_fill_pucch(PHY_VARS_gNB *gNB, { if (NFAPI_MODE == NFAPI_MODE_PNF) - gNB->pucch[0]->active = 0; //check if ture in monolithic mode - int id = nr_find_pucch(pucch_pdu->rnti,frame,slot,gNB); - AssertFatal((id >= 0) && (id < gNB->max_nb_pucch), - "invalid id found for pucch !!! rnti %04x id %d\n",pucch_pdu->rnti,id); + gNB->pucch[0].active = 0; // check if ture in monolithic mode - NR_gNB_PUCCH_t *pucch = gNB->pucch[id]; - pucch->frame = frame; - pucch->slot = slot; - pucch->active = 1; - if (pucch->pucch_pdu.format_type > 0) - LOG_D(PHY,"Programming PUCCH[%d] for %d.%d, format %d, nb_harq %d, nb_sr %d, nb_csi %d\n",id, - pucch->frame,pucch->slot,pucch->pucch_pdu.format_type,pucch->pucch_pdu.bit_len_harq,pucch->pucch_pdu.sr_flag,pucch->pucch_pdu.bit_len_csi_part1); - memcpy((void*)&pucch->pucch_pdu, (void*)pucch_pdu, sizeof(nfapi_nr_pucch_pdu_t)); + bool found = false; + for (int i = 0; i < gNB->max_nb_pucch; i++) { + NR_gNB_PUCCH_t *pucch = &gNB->pucch[i]; + if (pucch->active == 0) { + pucch->frame = frame; + pucch->slot = slot; + pucch->active = 1; + memcpy((void *)&pucch->pucch_pdu, (void *)pucch_pdu, sizeof(nfapi_nr_pucch_pdu_t)); + LOG_D(PHY, + "Programming PUCCH[%d] for %d.%d, format %d, nb_harq %d, nb_sr %d, nb_csi %d\n", + i, + pucch->frame, + pucch->slot, + pucch->pucch_pdu.format_type, + pucch->pucch_pdu.bit_len_harq, + pucch->pucch_pdu.sr_flag, + pucch->pucch_pdu.bit_len_csi_part1); + found = true; + break; + } + } + AssertFatal(found, "PUCCH list is full\n"); } @@ -176,38 +149,27 @@ int16_t idft12_im[12][12] = { {0,-11585,-20066,-23170,-20066,-11585,0,11585,20066,23170,20066,11585} }; - void nr_decode_pucch0(PHY_VARS_gNB *gNB, int frame, int slot, - nfapi_nr_uci_pucch_pdu_format_0_1_t* uci_pdu, - nfapi_nr_pucch_pdu_t* pucch_pdu) { - + nfapi_nr_uci_pucch_pdu_format_0_1_t *uci_pdu, + nfapi_nr_pucch_pdu_t *pucch_pdu) +{ c16_t **rxdataF = gNB->common_vars.rxdataF; NR_DL_FRAME_PARMS *frame_parms = &gNB->frame_parms; - int soffset=(slot&3)*frame_parms->symbols_per_slot*frame_parms->ofdm_symbol_size; - int nr_sequences; - const uint8_t *mcs; - - pucch_GroupHopping_t pucch_GroupHopping = pucch_pdu->group_hop_flag + (pucch_pdu->sequence_hop_flag<<1); + int soffset = (slot & 3) * frame_parms->symbols_per_slot * frame_parms->ofdm_symbol_size; AssertFatal(pucch_pdu->bit_len_harq > 0 || pucch_pdu->sr_flag > 0, "Either bit_len_harq (%d) or sr_flag (%d) must be > 0\n", pucch_pdu->bit_len_harq,pucch_pdu->sr_flag); - NR_gNB_UCI_STATS_t *uci_stats=NULL; - NR_gNB_UCI_STATS_t *first_uci_stats = gNB->uci_stats; - for (int i=0;iuci_stats[i].rnti == pucch_pdu->rnti) { - uci_stats = &gNB->uci_stats[i]; - break; - } else if (first_uci_stats == NULL && gNB->uci_stats[i].rnti == 0) first_uci_stats = &gNB->uci_stats[i]; - - if (uci_stats == NULL) { uci_stats=first_uci_stats; uci_stats->rnti = pucch_pdu->rnti;} - - AssertFatal(uci_stats!=NULL,"No stat index found\n"); - uci_stats->frame = frame; + NR_gNB_PHY_STATS_t *phy_stats = get_phy_stats(gNB, pucch_pdu->rnti); + AssertFatal(phy_stats != NULL, "phy_stats shouldn't be NULL\n"); + phy_stats->frame = frame; + NR_gNB_UCI_STATS_t *uci_stats = &phy_stats->uci_stats; + int nr_sequences; + const uint8_t *mcs; if(pucch_pdu->bit_len_harq==0){ mcs=table1_mcs; nr_sequences=1; @@ -258,20 +220,28 @@ void nr_decode_pucch0(PHY_VARS_gNB *gNB, int n,i; int prb_offset[2] = {pucch_pdu->bwp_start+pucch_pdu->prb_start, pucch_pdu->bwp_start+pucch_pdu->prb_start}; - nr_group_sequence_hopping(pucch_GroupHopping,pucch_pdu->hopping_id,0,slot,&u[0],&v[0]); // calculating u and v value first hop + pucch_GroupHopping_t pucch_GroupHopping = pucch_pdu->group_hop_flag + (pucch_pdu->sequence_hop_flag << 1); + nr_group_sequence_hopping(pucch_GroupHopping, + pucch_pdu->hopping_id, + 0, + slot, + &u[0], + &v[0]); // calculating u and v value first hop LOG_D(PHY,"pucch0: u %d, v %d\n",u[0],v[0]); - if (pucch_pdu->freq_hop_flag == 1) { - nr_group_sequence_hopping(pucch_GroupHopping,pucch_pdu->hopping_id,1,slot,&u[1],&v[1]); // calculating u and v value second hop + nr_group_sequence_hopping(pucch_GroupHopping, + pucch_pdu->hopping_id, + 1, + slot, + &u[1], + &v[1]); // calculating u and v value second hop LOG_D(PHY,"pucch0 second hop: u %d, v %d\n",u[1],v[1]); - prb_offset[1] = pucch_pdu->bwp_start+pucch_pdu->second_hop_prb; + prb_offset[1] = pucch_pdu->bwp_start + pucch_pdu->second_hop_prb; } - AssertFatal(pucch_pdu->nr_of_symbols < 3,"nr_of_symbols %d not allowed\n",pucch_pdu->nr_of_symbols); - uint32_t re_offset[2]={0}; - uint8_t l2; + uint32_t re_offset[2] = {0}; const int16_t *x_re[2],*x_im[2]; x_re[0] = table_5_2_2_2_2_Re[u[0]]; @@ -288,7 +258,7 @@ void nr_decode_pucch0(PHY_VARS_gNB *gNB, int32_t rp[frame_parms->nb_antennas_rx][pucch_pdu->nr_of_symbols][nb_re_pucch],*tmp_rp; for (int l=0; lnr_of_symbols; l++) { - l2 = l+pucch_pdu->start_symbol_index; + uint8_t l2 = l + pucch_pdu->start_symbol_index; re_offset[l] = (12*prb_offset[l]) + frame_parms->first_carrier_offset; if (re_offset[l]>= frame_parms->ofdm_symbol_size) @@ -454,10 +424,22 @@ void nr_decode_pucch0(PHY_VARS_gNB *gNB, uci_pdu->harq->harq_confidence_level = no_conf; uci_pdu->harq->harq_list = (nfapi_nr_harq_t*)malloc(sizeof *uci_pdu->harq->harq_list); uci_pdu->harq->harq_list[0].harq_value = !(index&0x01); - LOG_D(PHY, "[DLSCH/PDSCH/PUCCH] %d.%d HARQ %s with confidence level %s xrt_mag %d xrt_mag_next %d n0 %d (%d,%d) pucch0_thres %d, cqi %d, SNRtimes10 %d, energy %f, sync_pos %d\n", - frame,slot,uci_pdu->harq->harq_list[0].harq_value==0?"ACK":"NACK", - uci_pdu->harq->harq_confidence_level==0?"good":"bad", - xrtmag_dBtimes10,xrtmag_next_dBtimes10,max_n0,uci_stats->pucch0_n00,uci_stats->pucch0_n01,uci_stats->pucch0_thres,cqi,SNRtimes10,10*log10((double)sigenergy),gNB->ulsch_stats[0].sync_pos); + LOG_D(PHY, + "[DLSCH/PDSCH/PUCCH] %d.%d HARQ %s with confidence level %s xrt_mag %d xrt_mag_next %d n0 %d (%d,%d) pucch0_thres %d, " + "cqi %d, SNRtimes10 %d, energy %f\n", + frame, + slot, + uci_pdu->harq->harq_list[0].harq_value == 0 ? "ACK" : "NACK", + uci_pdu->harq->harq_confidence_level == 0 ? "good" : "bad", + xrtmag_dBtimes10, + xrtmag_next_dBtimes10, + max_n0, + uci_stats->pucch0_n00, + uci_stats->pucch0_n01, + uci_stats->pucch0_thres, + cqi, + SNRtimes10, + 10 * log10((double)sigenergy)); if (pucch_pdu->sr_flag == 1) { uci_pdu->sr = calloc(1,sizeof(*uci_pdu->sr)); @@ -478,14 +460,22 @@ void nr_decode_pucch0(PHY_VARS_gNB *gNB, uci_pdu->harq->harq_list[1].harq_value = !(index&0x01); uci_pdu->harq->harq_list[0].harq_value = !((index>>1)&0x01); - LOG_D(PHY, "[DLSCH/PDSCH/PUCCH] %d.%d HARQ values (%s, %s) with confidence level %s, xrt_mag %d xrt_mag_next %d n0 %d (%d,%d) pucch0_thres %d, cqi %d, SNRtimes10 %d,sync_pos %d\n", - frame,slot, + LOG_D(PHY, + "[DLSCH/PDSCH/PUCCH] %d.%d HARQ values (%s, %s) with confidence level %s, xrt_mag %d xrt_mag_next %d n0 %d (%d,%d) " + "pucch0_thres %d, cqi %d, SNRtimes10 %d\n", + frame, + slot, uci_pdu->harq->harq_list[1].harq_value == 0 ? "ACK" : "NACK", uci_pdu->harq->harq_list[0].harq_value == 0 ? "ACK" : "NACK", uci_pdu->harq->harq_confidence_level == 0 ? "good" : "bad", - xrtmag_dBtimes10,xrtmag_next_dBtimes10,max_n0, - uci_stats->pucch0_n00,uci_stats->pucch0_n01,uci_stats->pucch0_thres,cqi, - SNRtimes10,gNB->ulsch_stats[0].sync_pos); + xrtmag_dBtimes10, + xrtmag_next_dBtimes10, + max_n0, + uci_stats->pucch0_n00, + uci_stats->pucch0_n01, + uci_stats->pucch0_thres, + cqi, + SNRtimes10); if (pucch_pdu->sr_flag == 1) { uci_pdu->sr = calloc(1,sizeof(*uci_pdu->sr)); uci_pdu->sr->sr_indication = (index>3) ? 1 : 0; @@ -498,24 +488,21 @@ void nr_decode_pucch0(PHY_VARS_gNB *gNB, } } - - - - -void nr_decode_pucch1( c16_t **rxdataF, - pucch_GroupHopping_t pucch_GroupHopping, - uint32_t n_id, // hoppingID higher layer parameter - uint64_t *payload, - NR_DL_FRAME_PARMS *frame_parms, - int16_t amp, - int nr_tti_tx, - uint8_t m0, - uint8_t nrofSymbols, - uint8_t startingSymbolIndex, - uint16_t startingPRB, - uint16_t startingPRB_intraSlotHopping, - uint8_t timeDomainOCC, - uint8_t nr_bit) { +void nr_decode_pucch1(c16_t **rxdataF, + pucch_GroupHopping_t pucch_GroupHopping, + uint32_t n_id, // hoppingID higher layer parameter + uint64_t *payload, + NR_DL_FRAME_PARMS *frame_parms, + int16_t amp, + int nr_tti_tx, + uint8_t m0, + uint8_t nrofSymbols, + uint8_t startingSymbolIndex, + uint16_t startingPRB, + uint16_t startingPRB_intraSlotHopping, + uint8_t timeDomainOCC, + uint8_t nr_bit) +{ #ifdef DEBUG_NR_PUCCH_RX printf("\t [nr_generate_pucch1] start function at slot(nr_tti_tx)=%d payload=%lp m0=%d nrofSymbols=%d startingSymbolIndex=%d startingPRB=%d startingPRB_intraSlotHopping=%d timeDomainOCC=%d nr_bit=%d\n", nr_tti_tx,payload,m0,nrofSymbols,startingSymbolIndex,startingPRB,startingPRB_intraSlotHopping,timeDomainOCC,nr_bit); @@ -1209,9 +1196,16 @@ void nr_decode_pucch2(PHY_VARS_gNB *gNB, } } } - LOG_D(PHY,"Decoding pucch2 for %d symbols, %d PRB, nb_harq %d, nb_sr %d, nb_csi %d/%d\n", - pucch_pdu->nr_of_symbols,pucch_pdu->prb_size, - pucch_pdu->bit_len_harq,pucch_pdu->sr_flag,pucch_pdu->bit_len_csi_part1,pucch_pdu->bit_len_csi_part2); + LOG_D(PHY, + "%d.%d Decoding pucch2 for %d symbols, %d PRB, nb_harq %d, nb_sr %d, nb_csi %d/%d\n", + frame, + slot, + pucch_pdu->nr_of_symbols, + pucch_pdu->prb_size, + pucch_pdu->bit_len_harq, + pucch_pdu->sr_flag, + pucch_pdu->bit_len_csi_part1, + pucch_pdu->bit_len_csi_part2); int nc_group_size=1; // 2 PRB int ngroup = prb_size_ext/nc_group_size/2; @@ -1789,31 +1783,65 @@ void nr_decode_pucch2(PHY_VARS_gNB *gNB, } void nr_dump_uci_stats(FILE *fd,PHY_VARS_gNB *gNB,int frame) { + int strpos = 0; + char output[16384]; - int strpos=0; - char output[16384]; + for (int i = 0; i < MAX_MOBILES_PER_GNB; i++) { + NR_gNB_PHY_STATS_t *stats = &gNB->phy_stats[i]; + if (!stats->active) + return; + NR_gNB_UCI_STATS_t *uci_stats = &stats->uci_stats; + if (uci_stats->pucch0_sr_trials > 0) + strpos += sprintf(output + strpos, + "UCI %d RNTI %x: pucch0_sr_trials %d, pucch0_n00 %d dB, pucch0_n01 %d dB, pucch0_sr_thres %d dB, current " + "pucch1_stat0 %d dB, current pucch1_stat1 %d dB, positive SR count %d\n", + i, + stats->rnti, + uci_stats->pucch0_sr_trials, + uci_stats->pucch0_n00, + uci_stats->pucch0_n01, + uci_stats->pucch0_sr_thres, + dB_fixed(uci_stats->current_pucch0_sr_stat0), + dB_fixed(uci_stats->current_pucch0_sr_stat1), + uci_stats->pucch0_positive_SR); + if (uci_stats->pucch01_trials > 0) + strpos += sprintf(output + strpos, + "UCI %d RNTI %x: pucch01_trials %d, pucch0_n00 %d dB, pucch0_n01 %d dB, pucch0_thres %d dB, current " + "pucch0_stat0 %d dB, current pucch1_stat1 %d dB, pucch01_DTX %d\n", + i, + stats->rnti, + uci_stats->pucch01_trials, + uci_stats->pucch0_n01, + uci_stats->pucch0_n01, + uci_stats->pucch0_thres, + dB_fixed(uci_stats->current_pucch0_stat0), + dB_fixed(uci_stats->current_pucch0_stat1), + uci_stats->pucch01_DTX); - for (int i=0;iuci_stats[i].rnti>0) { - NR_gNB_UCI_STATS_t *uci_stats = &gNB->uci_stats[i]; - if (uci_stats->pucch0_sr_trials > 0) - strpos+=sprintf(output+strpos,"UCI %d RNTI %x: pucch0_sr_trials %d, pucch0_n00 %d dB, pucch0_n01 %d dB, pucch0_sr_thres %d dB, current pucch1_stat0 %d dB, current pucch1_stat1 %d dB, positive SR count %d\n", - i,uci_stats->rnti,uci_stats->pucch0_sr_trials,uci_stats->pucch0_n00,uci_stats->pucch0_n01,uci_stats->pucch0_sr_thres,dB_fixed(uci_stats->current_pucch0_sr_stat0),dB_fixed(uci_stats->current_pucch0_sr_stat1),uci_stats->pucch0_positive_SR); - if (uci_stats->pucch01_trials > 0) - strpos+=sprintf(output+strpos,"UCI %d RNTI %x: pucch01_trials %d, pucch0_n00 %d dB, pucch0_n01 %d dB, pucch0_thres %d dB, current pucch0_stat0 %d dB, current pucch1_stat1 %d dB, pucch01_DTX %d\n", - i,uci_stats->rnti,uci_stats->pucch01_trials,uci_stats->pucch0_n01,uci_stats->pucch0_n01,uci_stats->pucch0_thres,dB_fixed(uci_stats->current_pucch0_stat0),dB_fixed(uci_stats->current_pucch0_stat1),uci_stats->pucch01_DTX); + if (uci_stats->pucch02_trials > 0) + strpos += sprintf(output + strpos, + "UCI %d RNTI %x: pucch01_trials %d, pucch0_n00 %d dB, pucch0_n01 %d dB, pucch0_thres %d dB, current " + "pucch0_stat0 %d dB, current pucch0_stat1 %d dB, pucch01_DTX %d\n", + i, + stats->rnti, + uci_stats->pucch02_trials, + uci_stats->pucch0_n00, + uci_stats->pucch0_n01, + uci_stats->pucch0_thres, + dB_fixed(uci_stats->current_pucch0_stat0), + dB_fixed(uci_stats->current_pucch0_stat1), + uci_stats->pucch02_DTX); - if (uci_stats->pucch02_trials > 0) - strpos+=sprintf(output+strpos,"UCI %d RNTI %x: pucch01_trials %d, pucch0_n00 %d dB, pucch0_n01 %d dB, pucch0_thres %d dB, current pucch0_stat0 %d dB, current pucch0_stat1 %d dB, pucch01_DTX %d\n", - i,uci_stats->rnti,uci_stats->pucch02_trials,uci_stats->pucch0_n00,uci_stats->pucch0_n01,uci_stats->pucch0_thres,dB_fixed(uci_stats->current_pucch0_stat0),dB_fixed(uci_stats->current_pucch0_stat1),uci_stats->pucch02_DTX); - - if (uci_stats->pucch2_trials > 0) - strpos+=sprintf(output+strpos,"UCI %d RNTI %x: pucch2_trials %d, pucch2_DTX %d\n", - i,uci_stats->rnti, - uci_stats->pucch2_trials, - uci_stats->pucch2_DTX); - } - } - if (fd) fprintf(fd,"%s",output); - else printf("%s",output); + if (uci_stats->pucch2_trials > 0) + strpos += sprintf(output + strpos, + "UCI %d RNTI %x: pucch2_trials %d, pucch2_DTX %d\n", + i, + stats->rnti, + uci_stats->pucch2_trials, + uci_stats->pucch2_DTX); + } + if (fd) + fprintf(fd, "%s", output); + else + printf("%s", output); } diff --git a/openair1/PHY/NR_TRANSPORT/srs_rx.c b/openair1/PHY/NR_TRANSPORT/srs_rx.c index 5521619a8f..989c5cf044 100644 --- a/openair1/PHY/NR_TRANSPORT/srs_rx.c +++ b/openair1/PHY/NR_TRANSPORT/srs_rx.c @@ -44,55 +44,21 @@ //#define SRS_DEBUG -NR_gNB_SRS_t *new_gNB_srs(void){ - NR_gNB_SRS_t *srs; - srs = (NR_gNB_SRS_t *)malloc16(sizeof(NR_gNB_SRS_t)); - srs->active = 0; - return (srs); -} - -void free_gNB_srs(NR_gNB_SRS_t *srs) +void nr_fill_srs(PHY_VARS_gNB *gNB, frame_t frame, slot_t slot, nfapi_nr_srs_pdu_t *srs_pdu) { - free_and_zero(srs); -} - -int nr_find_srs(rnti_t rnti, - frame_t frame, - slot_t slot, - PHY_VARS_gNB *gNB) { - - AssertFatal(gNB!=NULL,"gNB is null\n"); - int index = -1; - + bool found = false; for (int i = 0; i < gNB->max_nb_srs; i++) { - AssertFatal(gNB->srs[i]!=NULL,"gNB->srs[%d] is null\n",i); - if ((gNB->srs[i]->active>0) && - (gNB->srs[i]->srs_pdu.rnti==rnti) && - (gNB->srs[i]->frame==frame) && - (gNB->srs[i]->slot==slot)) return(i); - else if ((gNB->srs[i]->active == 0) && (index==-1)) index=i; + NR_gNB_SRS_t *srs = &gNB->srs[i]; + if (srs->active == 0) { + found = true; + srs->frame = frame; + srs->slot = slot; + srs->active = 1; + memcpy((void *)&srs->srs_pdu, (void *)srs_pdu, sizeof(nfapi_nr_srs_pdu_t)); + break; + } } - - if (index==-1) - LOG_E(PHY,"SRS list is full\n"); - - return(index); -} - -void nr_fill_srs(PHY_VARS_gNB *gNB, - frame_t frame, - slot_t slot, - nfapi_nr_srs_pdu_t *srs_pdu) { - - int id = nr_find_srs(srs_pdu->rnti,frame,slot,gNB); - AssertFatal((id >= 0) && (id < gNB->max_nb_srs), - "invalid id found for srs !!! rnti %04x id %d\n",srs_pdu->rnti,id); - - NR_gNB_SRS_t *srs = gNB->srs[id]; - srs->frame = frame; - srs->slot = slot; - srs->active = 1; - memcpy((void*)&srs->srs_pdu, (void*)srs_pdu, sizeof(nfapi_nr_srs_pdu_t)); + AssertFatal(found, "SRS list is full\n"); } int nr_get_srs_signal(PHY_VARS_gNB *gNB, diff --git a/openair1/PHY/NR_UE_TRANSPORT/csi_rx.c b/openair1/PHY/NR_UE_TRANSPORT/csi_rx.c index 4eaa36f1bc..0e5ba62da7 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/csi_rx.c +++ b/openair1/PHY/NR_UE_TRANSPORT/csi_rx.c @@ -977,13 +977,11 @@ int nr_ue_csi_rs_procedures(PHY_VARS_NR_UE *ue, UE_nr_rxtx_proc_t *proc, c16_t r csirs_measurements.i2 = *i2; csirs_measurements.cqi = cqi; nr_downlink_indication_t dl_indication; - fapi_nr_rx_indication_t *rx_ind = calloc(sizeof(*rx_ind),1); - nr_fill_dl_indication(&dl_indication, NULL, rx_ind, proc, ue, NULL); - nr_fill_rx_indication(rx_ind, FAPI_NR_CSIRS_IND, ue, NULL, NULL, 1, proc, (void *)&csirs_measurements); + fapi_nr_rx_indication_t rx_ind = {0}; + nr_fill_dl_indication(&dl_indication, NULL, &rx_ind, proc, ue, NULL); + nr_fill_rx_indication(&rx_ind, FAPI_NR_CSIRS_IND, ue, NULL, NULL, 1, proc, (void *)&csirs_measurements, NULL); if (ue->if_inst && ue->if_inst->dl_indication) { ue->if_inst->dl_indication(&dl_indication, NULL); - } else { - free(rx_ind); } return 0; diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_decoding.c b/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_decoding.c index db6a15213c..470164817b 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_decoding.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_decoding.c @@ -51,15 +51,8 @@ #define OAI_UL_LDPC_MAX_NUM_LLR 27000//26112 // NR_LDPC_NCOL_BG1*NR_LDPC_ZMAX = 68*384 //#define OAI_LDPC_MAX_NUM_LLR 27000//26112 // NR_LDPC_NCOL_BG1*NR_LDPC_ZMAX -static uint64_t nb_total_decod =0; -static uint64_t nb_error_decod =0; - static extended_kpi_ue kpiStructure = {0}; -notifiedFIFO_t freeBlocks_dl; -notifiedFIFO_elt_t *msgToPush_dl; -int nbDlProcessing =0; - extended_kpi_ue* getKPIUE(void) { return &kpiStructure; } @@ -77,7 +70,7 @@ void nr_dlsch_unscrambling(int16_t *llr, uint32_t size, uint8_t q, uint32_t Nid, nr_codeword_unscrambling(llr, size, q, Nid, n_RNTI); } -bool nr_ue_postDecode(PHY_VARS_NR_UE *phy_vars_ue, notifiedFIFO_elt_t *req, bool last, notifiedFIFO_t *nf_p) { +bool nr_ue_postDecode(PHY_VARS_NR_UE *phy_vars_ue, notifiedFIFO_elt_t *req, bool last, notifiedFIFO_t *nf_p, int b_size, uint8_t b[b_size], int *num_seg_ok, UE_nr_rxtx_proc_t *proc) { ldpcDecode_ue_t *rdata = (ldpcDecode_ue_t*) NotifiedFifoData(req); NR_DL_UE_HARQ_t *harq_process = rdata->harq_process; NR_UE_DLSCH_t *dlsch = (NR_UE_DLSCH_t *) rdata->dlsch; @@ -90,10 +83,11 @@ bool nr_ue_postDecode(PHY_VARS_NR_UE *phy_vars_ue, notifiedFIFO_elt_t *req, bool bool decodeSuccess = (rdata->decodeIterations < (1+dlsch->max_ldpc_iterations)); if (decodeSuccess) { - memcpy(harq_process->b+rdata->offset, + memcpy(b+rdata->offset, harq_process->c[r], rdata->Kr_bytes - (harq_process->F>>3) -((harq_process->C>1)?3:0)); + (*num_seg_ok)++; } else { if ( !last ) { int nb=abortTpoolJob(&get_nrUE_params()->Tpool, req->key); @@ -111,7 +105,20 @@ bool nr_ue_postDecode(PHY_VARS_NR_UE *phy_vars_ue, notifiedFIFO_elt_t *req, bool kpiStructure.dl_mcs = dlsch->dlsch_config.mcs; kpiStructure.nofRBs = dlsch->dlsch_config.number_rbs; - if (decodeSuccess) { + if (*num_seg_ok == harq_process->C) { + if (harq_process->C > 1) { + /* check global CRC */ + int A = dlsch->dlsch_config.TBS; + int crc_length = A > 3824 ? 3 : 2; + int crc_type = A > 3824 ? CRC24_A : CRC16; + if (!check_crc(b, A + crc_length*8, 0 /* F - unused */, crc_type)) { + harq_process->ack = 0; + dlsch->last_iteration_cnt = dlsch->max_ldpc_iterations + 1; + LOG_E(PHY, " Frame %d.%d LDPC global CRC fails, but individual LDPC CRC succeeded. %d segs\n", proc->frame_rx, proc->nr_slot_rx, harq_process->C); + LOG_D(PHY, "DLSCH received nok \n"); + return true; //stop + } + } //LOG_D(PHY,"[UE %d] DLSCH: Setting ACK for nr_slot_rx %d TBS %d mcs %d nb_rb %d harq_process->round %d\n", // phy_vars_ue->Mod_id,nr_slot_rx,harq_process->TBS,harq_process->mcs,harq_process->nb_rb, harq_process->round); harq_process->status = SCH_IDLE; @@ -277,7 +284,7 @@ void nr_processDLSegment(void* arg) { if (no_iteration_ldpc > dlsch->max_ldpc_iterations) no_iteration_ldpc = dlsch->max_ldpc_iterations; } else { - LOG_D(PHY,"CRC NOT OK\n"); + LOG_I(PHY,"%d.%d CRC NOT OK\n",rdata->proc->frame_rx,rdata->proc->nr_slot_rx); no_iteration_ldpc = dlsch->max_ldpc_iterations + 1; } @@ -287,12 +294,6 @@ void nr_processDLSegment(void* arg) { rdata->decodeIterations = no_iteration_ldpc; - nb_total_decod++; - - if (no_iteration_ldpc > dlsch->max_ldpc_iterations) { - nb_error_decod++; - } - for (int m=0; m < Kr>>3; m ++) { harq_process->c[r][m]= (uint8_t) llrProcBuf[m]; } @@ -311,7 +312,9 @@ uint32_t nr_dlsch_decoding(PHY_VARS_NR_UE *phy_vars_ue, uint32_t frame, uint16_t nb_symb_sch, uint8_t nr_slot_rx, - uint8_t harq_pid) { + uint8_t harq_pid, + int b_size, + uint8_t b[b_size]) { uint32_t A,E; uint32_t G; uint32_t ret,offset; @@ -476,6 +479,7 @@ uint32_t nr_dlsch_decoding(PHY_VARS_NR_UE *phy_vars_ue, rdata->offset = offset; rdata->dlsch = dlsch; rdata->dlsch_id = 0; + rdata->proc = proc; reset_meas(&rdata->ts_deinterleave); reset_meas(&rdata->ts_rate_unmatch); reset_meas(&rdata->ts_ldpc_decode); @@ -486,6 +490,7 @@ uint32_t nr_dlsch_decoding(PHY_VARS_NR_UE *phy_vars_ue, offset += (Kr_bytes - (harq_process->F>>3) - ((harq_process->C>1)?3:0)); ////////////////////////////////////////////////////////////////////////////////////////// } + int num_seg_ok = 0; for (r=0; rTpool); if (req == NULL) @@ -493,7 +498,7 @@ uint32_t nr_dlsch_decoding(PHY_VARS_NR_UE *phy_vars_ue, bool last = false; if (r == nbDecode - 1) last = true; - bool stop = nr_ue_postDecode(phy_vars_ue, req, last, &nf); + bool stop = nr_ue_postDecode(phy_vars_ue, req, last, &nf, b_size, b, &num_seg_ok, proc); delNotifiedFIFO_elt(req); if (stop) break; diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync.c b/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync.c index 1904bed457..da99ba7405 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync.c @@ -155,12 +155,11 @@ int nr_pbch_detection(UE_nr_rxtx_proc_t * proc, PHY_VARS_NR_UE *ue, int pbch_ini proc,i,i-pbch_initial_symbol,temp_ptr->i_ssb,temp_ptr->n_hf,rxdataF); stop_meas(&ue->dlsch_channel_estimation_stats); - fapiPbch_t result; + fapiPbch_t result = {0}; ret = nr_rx_pbch(ue, proc, estimateSz, dl_ch_estimates, - ue->pbch_vars[0], frame_parms, temp_ptr->i_ssb, SISO, @@ -188,11 +187,6 @@ int nr_pbch_detection(UE_nr_rxtx_proc_t * proc, PHY_VARS_NR_UE *ue, int pbch_ini // openair_daq_vars.dlsch_transmission_mode = (pbch_tx_ant>1) ? 2 : 1; - // flip byte endian on 24-bits for MIB - // dummy = ue->pbch_vars[0]->decoded_output[0]; - // ue->pbch_vars[0]->decoded_output[0] = ue->pbch_vars[0]->decoded_output[2]; - // ue->pbch_vars[0]->decoded_output[2] = dummy; - #ifdef DEBUG_INITIAL_SYNCH LOG_I(PHY,"[UE%d] Initial sync: pbch decoded sucessfully\n",ue->Mod_id); #endif @@ -300,11 +294,11 @@ int nr_initial_sync(UE_nr_rxtx_proc_t *proc, /* time samples in buffer rxdata are used as input of FFT -> FFT results are stored in the frequency buffer rxdataF */ /* rxdataF stores SS/PBCH from beginning of buffers in the same symbol order as in time domain */ - for(int i=0; i<4;i++) + for (int i = 0; i < NR_N_SYMBOLS_SSB; i++) nr_slot_fep_init_sync(ue, proc, i, - is*fp->samples_per_frame+ue->ssb_offset, + is * fp->samples_per_frame + ue->ssb_offset, false, rxdataF); @@ -447,8 +441,6 @@ int nr_initial_sync(UE_nr_rxtx_proc_t *proc, // send sync status to higher layers later when timing offset converge to target timing - ue->pbch_vars[0]->pdu_errors_conseq=0; - } @@ -466,10 +458,6 @@ int nr_initial_sync(UE_nr_rxtx_proc_t *proc, frame_parms->Nid_cell,frame_parms->frame_type); #endif - ue->pbch_vars[0]->pdu_errors_last=ue->pbch_vars[0]->pdu_errors; - ue->pbch_vars[0]->pdu_errors++; - ue->pbch_vars[0]->pdu_errors_conseq++; - } // gain control @@ -522,6 +510,10 @@ int nr_initial_sync(UE_nr_rxtx_proc_t *proc, } + if (ue->target_Nid_cell != -1) { + return ret; + } + // if stand alone and sync on ssb do sib1 detection as part of initial sync if (sa==1 && ret==0) { nr_ue_dlsch_init(phy_data.dlsch, 1, ue->max_ldpc_iterations); diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_pbch.c b/openair1/PHY/NR_UE_TRANSPORT/nr_pbch.c index 0c2149e997..2fa9ca37ef 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_pbch.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_pbch.c @@ -302,8 +302,7 @@ void nr_pbch_detection_mrc(NR_DL_FRAME_PARMS *frame_parms, #endif } -static void nr_pbch_unscrambling(NR_UE_PBCH *pbch, - int16_t *demod_pbch_e, +static void nr_pbch_unscrambling(int16_t *demod_pbch_e, uint16_t Nid, uint8_t nushift, uint16_t M, @@ -311,7 +310,8 @@ static void nr_pbch_unscrambling(NR_UE_PBCH *pbch, uint8_t bitwise, uint32_t unscrambling_mask, uint32_t pbch_a_prime, - uint32_t *pbch_a_interleaved) { + uint32_t *pbch_a_interleaved) +{ uint8_t reset, offset; uint32_t x1 = 0, x2 = 0, s = 0; uint8_t k=0; @@ -384,17 +384,17 @@ unsigned char sign(int8_t x) { uint8_t pbch_deinterleaving_pattern[32] = {28,0,31,30,7,29,25,27,5,8,24,9,10,11,12,13,1,4,3,14,15,16,17,2,26,18,19,20,21,22,6,23}; -int nr_rx_pbch( PHY_VARS_NR_UE *ue, - UE_nr_rxtx_proc_t *proc, - int estimateSz, struct complex16 dl_ch_estimates [][estimateSz], - NR_UE_PBCH *nr_ue_pbch_vars, - NR_DL_FRAME_PARMS *frame_parms, - uint8_t i_ssb, - MIMO_mode_t mimo_mode, - nr_phy_data_t *phy_data, - fapiPbch_t *result, - c16_t rxdataF[][ue->frame_parms.samples_per_slot_wCP]) { - +int nr_rx_pbch(PHY_VARS_NR_UE *ue, + UE_nr_rxtx_proc_t *proc, + int estimateSz, + struct complex16 dl_ch_estimates [][estimateSz], + NR_DL_FRAME_PARMS *frame_parms, + uint8_t i_ssb, + MIMO_mode_t mimo_mode, + nr_phy_data_t *phy_data, + fapiPbch_t *result, + c16_t rxdataF[][ue->frame_parms.samples_per_slot_wCP]) +{ int max_h=0; int symbol; //uint8_t pbch_a[64]; @@ -456,7 +456,7 @@ int nr_rx_pbch( PHY_VARS_NR_UE *ue, } #ifdef DEBUG_PBCH - LOG_I(PHY,"[PHY] PBCH log2_maxh = %d (%d)\n",nr_ue_pbch_vars->log2_maxh,max_h); + LOG_I(PHY,"[PHY] PBCH log2_maxh = %d (%d)\n", log2_maxh, max_h); #endif __attribute__ ((aligned(32))) struct complex16 rxdataF_comp[frame_parms->nb_antennas_rx][PBCH_MAX_RE_PER_SYMBOL]; nr_pbch_channel_compensation(rxdataF_ext, @@ -464,7 +464,7 @@ int nr_rx_pbch( PHY_VARS_NR_UE *ue, nb_re, rxdataF_comp, frame_parms, - log2_maxh); // log2_maxh+I0_shift + log2_maxh); // log2_maxh+I0_shift /*if (frame_parms->nb_antennas_rx > 1) pbch_detection_mrc(frame_parms, @@ -504,16 +504,25 @@ int nr_rx_pbch( PHY_VARS_NR_UE *ue, uint32_t unscrambling_mask = (Lmax==64)?0x100006D:0x1000041; uint32_t pbch_a_interleaved=0; uint32_t pbch_a_prime=0; - nr_pbch_unscrambling(nr_ue_pbch_vars, pbch_e_rx, frame_parms->Nid_cell, nushift, M, NR_POLAR_PBCH_E, + nr_pbch_unscrambling(pbch_e_rx, frame_parms->Nid_cell, nushift, M, NR_POLAR_PBCH_E, 0, 0, pbch_a_prime, &pbch_a_interleaved); //polar decoding de-rate matching uint64_t tmp=0; decoderState = polar_decoder_int16(pbch_e_rx,(uint64_t *)&tmp,0, NR_POLAR_PBCH_MESSAGE_TYPE, NR_POLAR_PBCH_PAYLOAD_BITS, NR_POLAR_PBCH_AGGREGATION_LEVEL); - pbch_a_prime=tmp; - if(decoderState) - return(decoderState); + pbch_a_prime = tmp; + nr_downlink_indication_t dl_indication; + fapi_nr_rx_indication_t rx_ind = {0}; + uint16_t number_pdus = 1; + + if(decoderState) { + nr_fill_dl_indication(&dl_indication, NULL, &rx_ind, proc, ue, phy_data); + nr_fill_rx_indication(&rx_ind, FAPI_NR_RX_PDU_TYPE_SSB, ue, NULL, NULL, number_pdus, proc, NULL, NULL); + if (ue->if_inst && ue->if_inst->dl_indication) + ue->if_inst->dl_indication(&dl_indication, NULL); + return(decoderState); + } // printf("polar decoder output 0x%08x\n",pbch_a_prime); // Decoder reversal uint32_t a_reversed=0; @@ -526,7 +535,7 @@ int nr_rx_pbch( PHY_VARS_NR_UE *ue, M = (Lmax == 64)? (NR_POLAR_PBCH_PAYLOAD_BITS - 6) : (NR_POLAR_PBCH_PAYLOAD_BITS - 3); nushift = ((pbch_a_prime>>24)&1) ^ (((pbch_a_prime>>6)&1)<<1); pbch_a_interleaved=0; - nr_pbch_unscrambling(nr_ue_pbch_vars, pbch_e_rx, frame_parms->Nid_cell, nushift, M, NR_POLAR_PBCH_PAYLOAD_BITS, + nr_pbch_unscrambling(pbch_e_rx, frame_parms->Nid_cell, nushift, M, NR_POLAR_PBCH_PAYLOAD_BITS, 1, unscrambling_mask, pbch_a_prime, &pbch_a_interleaved); //printf("nushift %d sfn 3rd %d 2nd %d", nushift,((pbch_a_prime>>6)&1), ((pbch_a_prime>>24)&1) ); //payload deinterleaving @@ -577,17 +586,12 @@ int nr_rx_pbch( PHY_VARS_NR_UE *ue, } #endif - nr_downlink_indication_t dl_indication; - fapi_nr_rx_indication_t *rx_ind=calloc(sizeof(*rx_ind),1); - uint16_t number_pdus = 1; - nr_fill_dl_indication(&dl_indication, NULL, rx_ind, proc, ue, phy_data); - nr_fill_rx_indication(rx_ind, FAPI_NR_RX_PDU_TYPE_SSB, ue, NULL, NULL, number_pdus, proc,(void *)result); + nr_fill_dl_indication(&dl_indication, NULL, &rx_ind, proc, ue, phy_data); + nr_fill_rx_indication(&rx_ind, FAPI_NR_RX_PDU_TYPE_SSB, ue, NULL, NULL, number_pdus, proc, (void *)result, NULL); if (ue->if_inst && ue->if_inst->dl_indication) ue->if_inst->dl_indication(&dl_indication, NULL); - else - free(rx_ind); // dl_indication would free(), so free() here if not called return 0; } 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 7432c82aac..b20dbf8483 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h @@ -205,7 +205,9 @@ uint32_t nr_dlsch_decoding(PHY_VARS_NR_UE *phy_vars_ue, uint32_t frame, uint16_t nb_symb_sch, uint8_t nr_slot_rx, - uint8_t harq_pid); + uint8_t harq_pid, + int b_size, + uint8_t b[b_size]); int nr_ulsch_encoding(PHY_VARS_NR_UE *ue, NR_UE_ULSCH_t *ulsch, @@ -251,6 +253,8 @@ uint8_t nr_ue_pusch_common_procedures(PHY_VARS_NR_UE *UE, NR_DL_FRAME_PARMS *frame_parms, uint8_t Nl); +int8_t clean_UE_ulsch(PHY_VARS_NR_UE *UE, uint8_t gNB_id); + void nr_dlsch_unscrambling(int16_t* llr, uint32_t size, uint8_t q, @@ -283,7 +287,6 @@ int nr_rx_pbch(PHY_VARS_NR_UE *ue, UE_nr_rxtx_proc_t *proc, const int estimateSz, struct complex16 dl_ch_estimates[][estimateSz], - NR_UE_PBCH *nr_ue_pbch_vars, NR_DL_FRAME_PARMS *frame_parms, uint8_t i_ssb, MIMO_mode_t mimo_mode, @@ -313,7 +316,7 @@ int dump_ue_stats(PHY_VARS_NR_UE *phy_vars_ue, UE_nr_rxtx_proc_t *proc, char* bu @param mode current running mode */ int nr_initial_sync(UE_nr_rxtx_proc_t *proc, - PHY_VARS_NR_UE *phy_vars_ue, + PHY_VARS_NR_UE *phy_vars_ue, int n_frames, int sa); diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_transport_ue.h b/openair1/PHY/NR_UE_TRANSPORT/nr_transport_ue.h index dc09714da9..811fa7711b 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_transport_ue.h +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_transport_ue.h @@ -119,8 +119,6 @@ typedef struct { uint32_t TBS; /// The payload + CRC size in bits uint32_t B; - /// Pointer to the payload - uint8_t *b; /// Pointers to transport block segments uint8_t **c; /// soft bits for each received segment ("d"-sequence)(for definition see 36-212 V8.6 2009-03, p.15) diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c b/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c index 9d0982689b..fc22a954fe 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c @@ -662,3 +662,15 @@ uint8_t nr_ue_pusch_common_procedures(PHY_VARS_NR_UE *UE, //////////////////////////////////////////////////// return 0; } + +int8_t clean_UE_ulsch(PHY_VARS_NR_UE *UE, uint8_t gNB_id) +{ + for (int harq_pid = 0; harq_pid < NR_MAX_ULSCH_HARQ_PROCESSES; harq_pid++) { + NR_UL_UE_HARQ_t *ul_harq_process = &UE->ul_harq_processes[harq_pid]; + ul_harq_process->tx_status = NEW_TRANSMISSION_HARQ; + ul_harq_process->status = SCH_IDLE; + ul_harq_process->round = 0; + ul_harq_process->first_tx = 1; + } + return 0; +} diff --git a/openair1/PHY/NR_UE_TRANSPORT/pss_nr.c b/openair1/PHY/NR_UE_TRANSPORT/pss_nr.c index fbb4a8a625..50f6fa2f34 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/pss_nr.c +++ b/openair1/PHY/NR_UE_TRANSPORT/pss_nr.c @@ -555,12 +555,8 @@ int pss_synchro_nr(PHY_VARS_NR_UE *PHY_vars_UE, int is, int rate_change) #endif VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PSS_SEARCH_TIME_NR, VCD_FUNCTION_IN); - synchro_position = pss_search_time_nr(rxdata, - frame_parms, - fo_flag, - is, - (int *)&PHY_vars_UE->common_vars.eNb_id, - (int *)&PHY_vars_UE->common_vars.freq_offset); + + synchro_position = pss_search_time_nr(rxdata, PHY_vars_UE, fo_flag, is); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PSS_SEARCH_TIME_NR, VCD_FUNCTION_OUT); @@ -605,7 +601,7 @@ int pss_synchro_nr(PHY_VARS_NR_UE *PHY_vars_UE, int is, int rate_change) * * NAME : pss_search_time_nr * -* PARAMETERS : received buffer +* PARAMETERS : received buffer in time domain * frame parameters * * RETURN : position of detected pss @@ -651,17 +647,15 @@ int pss_synchro_nr(PHY_VARS_NR_UE *PHY_vars_UE, int is, int rate_change) * *********************************************************************/ -int pss_search_time_nr(c16_t **rxdata, ///rx data in time domain - NR_DL_FRAME_PARMS *frame_parms, - int fo_flag, - int is, - int *eNB_id, - int *f_off) +int pss_search_time_nr(c16_t **rxdata, PHY_VARS_NR_UE *ue, int fo_flag, int is) { + NR_DL_FRAME_PARMS *frame_parms = &ue->frame_parms; + int *eNB_id = (int *)&ue->common_vars.eNb_id; + int *f_off = (int *)&ue->common_vars.freq_offset; unsigned int n, ar, peak_position, pss_source; int64_t peak_value; - int64_t avg[NUMBER_PSS_SEQUENCE]={0}; - double ffo_est=0; + int64_t avg[NUMBER_PSS_SEQUENCE] = {0}; + double ffo_est = 0; // performing the correlation on a frame length plus one symbol for the first of the two frame // to take into account the possibility of PSS in between the two frames @@ -692,7 +686,14 @@ int pss_search_time_nr(c16_t **rxdata, ///rx data in time domain /* This is required by SIMD (single instruction Multiple Data) Extensions of Intel processors. */ /* Correlation computation is based on a a dot product which is realized thank to SIMS extensions */ - for (int pss_index = 0; pss_index < NUMBER_PSS_SEQUENCE; pss_index++) { + uint16_t pss_index_start = 0; + uint16_t pss_index_end = NUMBER_PSS_SEQUENCE; + if (ue->target_Nid_cell != -1) { + pss_index_start = GET_NID2(ue->target_Nid_cell); + pss_index_end = pss_index_start + 1; + } + + for (int pss_index = pss_index_start; pss_index < pss_index_end; pss_index++) { for (n = 0; n < length; n += 8) { // int64_t pss_corr_ue=0; @@ -748,10 +749,10 @@ int pss_search_time_nr(c16_t **rxdata, ///rx data in time domain } // computing absolute value of frequency offset - *f_off = ffo_est*frame_parms->subcarrier_spacing; + *f_off = ffo_est*frame_parms->subcarrier_spacing; - for (int pss_index = 0; pss_index < NUMBER_PSS_SEQUENCE; pss_index++) - avg[pss_index]/=(length/4); + for (int pss_index = pss_index_start; pss_index < pss_index_end; pss_index++) + avg[pss_index] /= (length / 4); *eNB_id = pss_source; @@ -776,6 +777,6 @@ int pss_search_time_nr(c16_t **rxdata, ///rx data in time domain #endif - return(peak_position); + return peak_position; } diff --git a/openair1/PHY/NR_UE_TRANSPORT/sss_nr.c b/openair1/PHY/NR_UE_TRANSPORT/sss_nr.c index 3056315999..cdb45fc9c1 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/sss_nr.c +++ b/openair1/PHY/NR_UE_TRANSPORT/sss_nr.c @@ -511,9 +511,15 @@ int rx_sss_nr(PHY_VARS_NR_UE *ue, UE_nr_rxtx_proc_t *proc, int32_t *tot_metric, /* cosinus cos(x + y) = cos(x)cos(y) - sin(x)sin(y) */ /* sinus sin(x + y) = sin(x)cos(y) + cos(x)sin(y) */ - for (Nid1 = 0 ; Nid1 < N_ID_1_NUMBER; Nid1++) { // all possible Nid1 values - for (phase=0; phase < PHASE_HYPOTHESIS_NUMBER; phase++) { // phase offset between PSS and SSS + uint16_t Nid1_start = 0; + uint16_t Nid1_end = N_ID_1_NUMBER; + if (ue->target_Nid_cell != -1) { + Nid1_start = GET_NID1(ue->target_Nid_cell); + Nid1_end = Nid1_start + 1; + } + for (Nid1 = Nid1_start; Nid1 < Nid1_end; Nid1++) { // all possible Nid1 values + for (phase = 0; phase < PHASE_HYPOTHESIS_NUMBER; phase++) { // phase offset between PSS and SSS metric = 0; metric_re = 0; @@ -523,7 +529,6 @@ int rx_sss_nr(PHY_VARS_NR_UE *ue, UE_nr_rxtx_proc_t *proc, int32_t *tot_metric, // This is the inner product using one particular value of each unknown parameter for (i=0; i < LENGTH_SSS_NR; i++) { - metric_re += d[i]*(((phase_re_nr[phase]*sss[2*i])>>SCALING_METRIC_SSS_NR) - ((phase_im_nr[phase]*sss[2*i+1])>>SCALING_METRIC_SSS_NR)); #if 0 diff --git a/openair1/PHY/TOOLS/nr_phy_qt_scope.cpp b/openair1/PHY/TOOLS/nr_phy_qt_scope.cpp index 04e42873ea..5aecc3906b 100644 --- a/openair1/PHY/TOOLS/nr_phy_qt_scope.cpp +++ b/openair1/PHY/TOOLS/nr_phy_qt_scope.cpp @@ -317,6 +317,34 @@ void CIRPlot::timerEvent(QTimerEvent *event) this->series->replace(points); } +void CIRPlotUE::timerEvent(QTimerEvent *event) +{ + if (!this->isVisible()) + return; + + scopeGraphData_t *data = this->valueProvider->getPlotValue(); + if (data) { + this->data = (complex16 *)(data + 1); + this->len = data->lineSz; + QVector points(this->len); + float maxY = this->axisY->max(); + + for (int i = 0; i < this->len / 2; i++) { + float value = SquaredNorm(this->data[i + this->len / 2]); + points[i] = QPointF(i - this->len / 2, value); + maxY = std::max(maxY, value); + } + for (int i = 0; i < this->len / 2; i++) { + float value = SquaredNorm(this->data[i]); + points[i + this->len / 2] = QPointF(i, value); + maxY = std::max(maxY, value); + } + + this->axisY->setMax(maxY); + this->series->replace(points); + } +} + LLRPlot::LLRPlot(int16_t *data, int len) : data(data), len(len) { this->legend()->hide(); @@ -361,6 +389,28 @@ void LLRPlot::timerEvent(QTimerEvent *event) this->series->replace(points); } +void LLRPlotUE::timerEvent(QTimerEvent *event) +{ + if (!this->isVisible()) + return; + + scopeGraphData_t *data = this->valueProvider->getPlotValue(); + if (data) { + this->data = (int16_t *)(data + 1); + this->len = data->lineSz; + QVector points(this->len); + int maxY = this->axisY->max(); + + for (int i = 0; i < this->len; i++) { + points[i] = QPointF(i, this->data[i]); + maxY = std::max(maxY, abs(this->data[i])); + } + + this->axisY->setRange(-maxY, maxY); + this->series->replace(points); + } +} + IQPlot::IQPlot(complex16 *data, int len) : data(data), len(len) { this->legend()->hide(); @@ -407,6 +457,32 @@ void IQPlot::timerEvent(QTimerEvent *event) this->series->replace(points); } +void IQPlotUE::timerEvent(QTimerEvent *event) +{ + if (!this->isVisible()) + return; + + scopeGraphData_t *data = this->valueProvider->getPlotValue(); + if (data) { + this->data = (complex16 *)(data + 1); + this->len = data->lineSz; + QVector points(this->len); + int maxX = this->axisX->max(); + int maxY = this->axisY->max(); + + for (int i = 0; i < this->len; i++) { + points[i] = QPointF(this->data[i].r, this->data[i].i); + + maxX = std::max(maxX, abs(this->data[i].r)); + maxY = std::max(maxY, abs(this->data[i].i)); + } + + this->axisX->setRange(-maxX, maxX); + this->axisY->setRange(-maxY, maxY); + this->series->replace(points); + } +} + KPIPlot::KPIPlot(ValueProvider *valueProvider, float *limits) : valueProvider(valueProvider), limits(limits) { this->series = new QLineSeries(); @@ -697,7 +773,7 @@ void PainterWidgetGnb::makeConnections(int type) break; } case PlotTypeGnb::CIR: { - newChart = new CIRPlot((complex16 *)p->gNB->pusch_vars[0]->ul_ch_estimates_time[0], frame_parms->ofdm_symbol_size); + newChart = new CIRPlot((complex16 *)p->gNB->pusch_vars[0].ul_ch_estimates_time[0], frame_parms->ofdm_symbol_size); break; } @@ -705,12 +781,12 @@ void PainterWidgetGnb::makeConnections(int type) int num_re = frame_parms->N_RB_UL * 12 * frame_parms->symbols_per_slot; int Qm = 2; int coded_bits_per_codeword = num_re * Qm; - newChart = new LLRPlot((int16_t *)p->gNB->pusch_vars[0]->llr, coded_bits_per_codeword); + newChart = new LLRPlot((int16_t *)p->gNB->pusch_vars[0].llr, coded_bits_per_codeword); break; } case PlotTypeGnb::puschIQ: { int num_re = frame_parms->N_RB_UL * 12 * frame_parms->symbols_per_slot; - newChart = new IQPlot((complex16 *)p->gNB->pusch_vars[0]->rxdataF_comp[0], num_re); + newChart = new IQPlot((complex16 *)p->gNB->pusch_vars[0].rxdataF_comp[0], num_re); break; } case PlotTypeGnb::puschSNR: { @@ -815,11 +891,42 @@ float PainterWidgetUE::getValue() case PlotTypeUE::timingAdvance: return (float)this->ue->timing_advance; + default: return 0; } } +scopeGraphData_t *PainterWidgetUE::getPlotValue() +{ + scopeData_t *scope = (scopeData_t *)this->ue->scopeData; + scopeGraphData_t **data = (scopeGraphData_t **)scope->liveData; + switch (this->plotType) { + case PlotTypeUE::CIR: + return data[pbchDlChEstimateTime]; + + case PlotTypeUE::pbchLLR: + return data[pbchLlr]; + case PlotTypeUE::pbchIQ: + return data[pbchRxdataF_comp]; + + case PlotTypeUE::pdcchLLR: + return data[pdcchLlr]; + + case PlotTypeUE::pdcchIQ: + return data[pdcchRxdataF_comp]; + + case PlotTypeUE::pdschLLR: + return data[pdschLlr]; + + case PlotTypeUE::pdschIQ: + return data[pdschRxdataF_comp]; + + default: + return nullptr; + } +} + /* @UE Class: this function is called when a resize event is detected, then the widget will be adjusted accordignly. */ void PainterWidgetUE::resizeEvent(QResizeEvent *event) { @@ -890,7 +997,7 @@ void PainterWidgetUE::makeConnections(int type) this->comboBox->setCurrentIndex(static_cast(PlotTypeUE::empty)); break; } - newChart = new LLRPlot((int16_t *)(data[pbchLlr] + 1), data[pbchLlr]->lineSz); + newChart = new LLRPlotUE((int16_t *)(data[pbchLlr] + 1), data[pbchLlr]->lineSz, this); break; } case PlotTypeUE::pbchIQ: { @@ -900,7 +1007,7 @@ void PainterWidgetUE::makeConnections(int type) this->comboBox->setCurrentIndex(static_cast(PlotTypeUE::empty)); break; } - newChart = new IQPlot((complex16 *)(data[pbchRxdataF_comp] + 1), data[pbchRxdataF_comp]->lineSz); + newChart = new IQPlotUE((complex16 *)(data[pbchRxdataF_comp] + 1), data[pbchRxdataF_comp]->lineSz, this); break; } case PlotTypeUE::pdcchLLR: { @@ -910,7 +1017,7 @@ void PainterWidgetUE::makeConnections(int type) this->comboBox->setCurrentIndex(static_cast(PlotTypeUE::empty)); break; } - newChart = new LLRPlot((int16_t *)(data[pdcchLlr] + 1), data[pdcchLlr]->lineSz); + newChart = new LLRPlotUE((int16_t *)(data[pdcchLlr] + 1), data[pdcchLlr]->lineSz, this); break; } case PlotTypeUE::pdcchIQ: { @@ -920,7 +1027,7 @@ void PainterWidgetUE::makeConnections(int type) this->comboBox->setCurrentIndex(static_cast(PlotTypeUE::empty)); break; } - newChart = new IQPlot((complex16 *)(data[pdcchRxdataF_comp] + 1), data[pdcchRxdataF_comp]->lineSz); + newChart = new IQPlotUE((complex16 *)(data[pdcchRxdataF_comp] + 1), data[pdcchRxdataF_comp]->lineSz, this); break; } case PlotTypeUE::pdschLLR: { @@ -930,7 +1037,7 @@ void PainterWidgetUE::makeConnections(int type) this->comboBox->setCurrentIndex(static_cast(PlotTypeUE::empty)); break; } - newChart = new LLRPlot((int16_t *)(data[pdschLlr] + 1), data[pdschLlr]->lineSz); + newChart = new LLRPlotUE((int16_t *)(data[pdschLlr] + 1), data[pdschLlr]->lineSz, this); break; } case PlotTypeUE::pdschIQ: { @@ -940,7 +1047,7 @@ void PainterWidgetUE::makeConnections(int type) this->comboBox->setCurrentIndex(static_cast(PlotTypeUE::empty)); break; } - newChart = new IQPlot((complex16 *)(data[pdschRxdataF_comp] + 1), data[pdschRxdataF_comp]->lineSz); + newChart = new IQPlotUE((complex16 *)(data[pdschRxdataF_comp] + 1), data[pdschRxdataF_comp]->lineSz, this); break; } @@ -1147,6 +1254,7 @@ void nrUEinitQtScope(PHY_VARS_NR_UE *ue) scope->liveData = calloc(sizeof(scopeGraphData_t *), UEdataTypeNumberOfItems); scope->copyData = UEcopyData; + UEcopyDataMutexInit(); ue->scopeData = scope; diff --git a/openair1/PHY/TOOLS/nr_phy_qt_scope.h b/openair1/PHY/TOOLS/nr_phy_qt_scope.h index f10fef9d61..8a00d5fa96 100644 --- a/openair1/PHY/TOOLS/nr_phy_qt_scope.h +++ b/openair1/PHY/TOOLS/nr_phy_qt_scope.h @@ -91,6 +91,14 @@ class ValueProvider { virtual float getValue() = 0; }; +class ValueProviderUE : public ValueProvider { + public: + /// This pure virtual function is meant to provide the graph values to be plotted + virtual scopeGraphData_t *getPlotValue() { + return nullptr; + } +}; + /// An editable GUI field for a dialog box to set certain KPI configurations class ConfigBoxFloat : public QLineEdit { Q_OBJECT @@ -206,7 +214,6 @@ class CIRPlot : public QChart { /// \param event Pointer to the timer event virtual void timerEvent(QTimerEvent *event) override; - private: /// Pointer to the CIR data complex16 *data; @@ -223,6 +230,21 @@ class CIRPlot : public QChart { QValueAxis *axisY; }; +class CIRPlotUE : public CIRPlot { + Q_OBJECT + + public: + CIRPlotUE(complex16 *data, int len, ValueProviderUE *valueProvider) : CIRPlot(data, len), valueProvider(valueProvider) {} + + protected: + /// This function is triggered when the own timer expires. It updates the plotted CIR + /// \param event Pointer to the timer event + virtual void timerEvent(QTimerEvent *event) override; + + private: + ValueProviderUE *valueProvider; +}; + /// Chart class for plotting LLRs class LLRPlot : public QChart { Q_OBJECT @@ -238,7 +260,6 @@ class LLRPlot : public QChart { /// \param event Pointer to the timer event virtual void timerEvent(QTimerEvent *event) override; - private: /// Pointer to the LLR data int16_t *data; @@ -255,6 +276,21 @@ class LLRPlot : public QChart { QValueAxis *axisY; }; +class LLRPlotUE : public LLRPlot { + Q_OBJECT + + public: + LLRPlotUE(int16_t *data, int len, ValueProviderUE *valueProvider) : LLRPlot(data, len), valueProvider(valueProvider) {} + + protected: + /// This function is triggered when the own timer expires. It updates the plotted I/Q constellation diagram + /// \param event Pointer to the timer event + virtual void timerEvent(QTimerEvent *event) override; + + private: + ValueProviderUE *valueProvider; +}; + /// Chart class for plotting the I/Q constellation diagram class IQPlot : public QChart { Q_OBJECT @@ -270,7 +306,6 @@ class IQPlot : public QChart { /// \param event Pointer to the timer event virtual void timerEvent(QTimerEvent *event) override; - private: /// Pointer to the I/Q data complex16 *data; @@ -287,6 +322,22 @@ class IQPlot : public QChart { QValueAxis *axisY; }; +class IQPlotUE : public IQPlot { + Q_OBJECT + + public: + IQPlotUE(complex16 *data, int len, ValueProviderUE *valueProvider) : IQPlot(data, len), valueProvider(valueProvider) {} + + protected: + /// This function is triggered when the own timer expires. It updates the plotted I/Q constellation diagram + /// \param event Pointer to the timer event + virtual void timerEvent(QTimerEvent *event) override; + + private: + /// Pointer to an instance of a class that implements the ValueProvider interface + ValueProviderUE *valueProvider; +}; + /// Generic class for plotting KPI values with min., max. and average bars class KPIPlot : public QChart { Q_OBJECT @@ -422,7 +473,7 @@ class PainterWidgetGnb : public QWidget, public ValueProvider { }; /// Widget showing one selectable UE KPI -class PainterWidgetUE : public QWidget, public ValueProvider { +class PainterWidgetUE : public QWidget, public ValueProviderUE { Q_OBJECT public: @@ -435,6 +486,8 @@ class PainterWidgetUE : public QWidget, public ValueProvider { /// This function provides the current KPI value to be plotted virtual float getValue() override; + virtual scopeGraphData_t *getPlotValue() override; + protected: /// This function is called to change the widget size /// \param event Pointer to the resize event diff --git a/openair1/PHY/TOOLS/nr_phy_scope.c b/openair1/PHY/TOOLS/nr_phy_scope.c index 5a4562cb58..17141c7158 100644 --- a/openair1/PHY/TOOLS/nr_phy_scope.c +++ b/openair1/PHY/TOOLS/nr_phy_scope.c @@ -473,10 +473,10 @@ static void timeResponse (OAIgraph_t *graph, scopeData_t *p, int nb_UEs) { int uestart = 0; // xforms scope designed to display nb_UEs signals #endif for (int ue = uestart; ue < nb_UEs; ue++) { - if ( p->gNB->pusch_vars && p->gNB->pusch_vars[ue] && - p->gNB->pusch_vars[ue]->ul_ch_estimates_time && - p->gNB->pusch_vars[ue]->ul_ch_estimates_time[ant] ) { - scopeSample_t *data= (scopeSample_t *)p->gNB->pusch_vars[ue]->ul_ch_estimates_time[ant]; + if (p->gNB->pusch_vars && + p->gNB->pusch_vars[ue].ul_ch_estimates_time && + p->gNB->pusch_vars[ue].ul_ch_estimates_time[ant] ) { + scopeSample_t *data= (scopeSample_t *)p->gNB->pusch_vars[ue].ul_ch_estimates_time[ant]; if (data != NULL) { for (int i=0; igNB->pusch_vars && - p->gNB->pusch_vars[ue] && - p->gNB->pusch_vars[ue]->llr ) { - int16_t *pusch_llr = (int16_t *)p->gNB->pusch_vars[ue]->llr; + if (p->gNB->pusch_vars && + p->gNB->pusch_vars[ue].llr ) { + int16_t *pusch_llr = (int16_t *)p->gNB->pusch_vars[ue].llr; float *llr=NULL, *bit=NULL; int nx = coded_bits_per_codeword; #ifdef WEBSRVSCOPE @@ -557,11 +556,10 @@ static void puschIQ (OAIgraph_t *graph, scopeData_t *p, int nb_UEs) { int uestart = 0; // xforms scope designed to display nb_UEs signals #endif for (int ue = uestart; ue < nb_UEs; ue++) { - if ( p->gNB->pusch_vars && - p->gNB->pusch_vars[ue] && - p->gNB->pusch_vars[ue]->rxdataF_comp && - p->gNB->pusch_vars[ue]->rxdataF_comp[0] ) { - scopeSample_t *pusch_comp = (scopeSample_t *)p->gNB->pusch_vars[ue]->rxdataF_comp[0]; + if (p->gNB->pusch_vars && + p->gNB->pusch_vars[ue].rxdataF_comp && + p->gNB->pusch_vars[ue].rxdataF_comp[0] ) { + scopeSample_t *pusch_comp = (scopeSample_t *)p->gNB->pusch_vars[ue].rxdataF_comp[0]; float *I=NULL, *Q=NULL; #ifdef WEBSRVSCOPE newsz = websrv_cpiqbuff_tomsg(graph, pusch_comp, sz, 0, 0); @@ -1139,8 +1137,6 @@ static void *nrUEscopeThread(void *arg) { } #endif -pthread_mutex_t UEcopyDataMutex; - STATICFORXSCOPE void nrUEinitScope(PHY_VARS_NR_UE *ue) { AssertFatal(ue->scopeData=malloc(sizeof(scopeData_t)),""); @@ -1150,8 +1146,8 @@ STATICFORXSCOPE void nrUEinitScope(PHY_VARS_NR_UE *ue) #ifndef WEBSRVSCOPE pthread_t forms_thread; threadCreate(&forms_thread, nrUEscopeThread, ue, "scope", -1, OAI_PRIORITY_RT_LOW); + UEcopyDataMutexInit(); #endif - pthread_mutex_init(&UEcopyDataMutex, NULL); } void nrscope_autoinit(void *dataptr) { diff --git a/openair1/PHY/TOOLS/phy_scope_interface.c b/openair1/PHY/TOOLS/phy_scope_interface.c index b567e96b03..6dfcc36c75 100644 --- a/openair1/PHY/TOOLS/phy_scope_interface.c +++ b/openair1/PHY/TOOLS/phy_scope_interface.c @@ -35,9 +35,16 @@ #include "phy_scope_interface.h" #define SOFTSCOPE_ENDFUNC_IDX 0 +#define THREAD_MEM 4 static loader_shlibfunc_t scope_fdesc[]= {{"end_forms",NULL}}; +pthread_mutex_t UEcopyDataMutex; + +int UEcopyDataMutexInit(void) { + return pthread_mutex_init(&UEcopyDataMutex, NULL); +} + int load_softscope(char *exectype, void *initarg) { char libname[64]; sprintf(libname,"%.10sscope",exectype); @@ -56,16 +63,19 @@ int end_forms(void) { void UEcopyData(PHY_VARS_NR_UE *ue, enum UEdataType type, void *dataIn, int elementSz, int colSz, int lineSz) { // Local static copy of the scope data bufs // The active data buf is alterned to avoid interference between the Scope thread (display) and the Rx thread (data input) - // Index of "2" could be set to the number of Rx threads + 1 - static scopeGraphData_t *copyDataBufs[UEdataTypeNumberOfItems][2] = {0}; + // Index of THREAD_MEM could be set to the number of Rx threads + 1. Rx slots could run asynchronous to each other. + // THREAD_MEM = 4 slot process running in parallel is an assumption. THREAD_MEM can be increased if scope appears inconsistent. + static scopeGraphData_t *copyDataBufs[UEdataTypeNumberOfItems][THREAD_MEM] = {0}; static int copyDataBufsIdx[UEdataTypeNumberOfItems] = {0}; scopeData_t *tmp = (scopeData_t *)ue->scopeData; if (tmp) { - // Begin of critical zone between UE Rx threads that might copy new data at the same time: might require a mutex - int newCopyDataIdx = (copyDataBufsIdx[type]==0)?1:0; + // Begin of critical zone between UE Rx threads that might copy new data at the same time: + pthread_mutex_lock(&UEcopyDataMutex); + int newCopyDataIdx = (copyDataBufsIdx[type]<(THREAD_MEM-1))?copyDataBufsIdx[type]+1:0; copyDataBufsIdx[type] = newCopyDataIdx; + pthread_mutex_unlock(&UEcopyDataMutex); // End of critical zone between UE Rx threads // New data will be copied in a different buffer than the live one diff --git a/openair1/PHY/TOOLS/phy_scope_interface.h b/openair1/PHY/TOOLS/phy_scope_interface.h index b6d4480762..19395891ad 100644 --- a/openair1/PHY/TOOLS/phy_scope_interface.h +++ b/openair1/PHY/TOOLS/phy_scope_interface.h @@ -31,15 +31,21 @@ */ #ifndef __PHY_SCOPE_INTERFACE_H__ #define __PHY_SCOPE_INTERFACE_H__ + +#ifdef __cplusplus +#include +#define _Atomic(X) std::atomic< X > +#endif + #include #include typedef struct { - uint32_t nb_total; - uint32_t nb_nack; - uint32_t blockSize; // block size, to be used for throughput calculation - uint16_t nofRBs; - uint8_t dl_mcs; + _Atomic(uint32_t) nb_total; + _Atomic(uint32_t) nb_nack; + _Atomic(uint32_t) blockSize; // block size, to be used for throughput calculation + _Atomic(uint16_t) nofRBs; + _Atomic(uint8_t ) dl_mcs; } extended_kpi_ue; typedef struct { @@ -80,6 +86,7 @@ typedef struct { int load_softscope(char *exectype, void *initarg); int end_forms(void) ; +int UEcopyDataMutexInit(void); void UEcopyData(PHY_VARS_NR_UE *ue, enum UEdataType type, void *dataIn, int elementSz, int colSz, int lineSz); #define UEscopeCopy(ue, type, ...) if(ue->scopeData) ((scopeData_t*)ue->scopeData)->copyData(ue, type, ##__VA_ARGS__); diff --git a/openair1/PHY/defs_gNB.h b/openair1/PHY/defs_gNB.h index 13977c562f..d9557447ff 100644 --- a/openair1/PHY/defs_gNB.h +++ b/openair1/PHY/defs_gNB.h @@ -97,9 +97,7 @@ typedef struct { } NR_gNB_CSIRS_t; typedef struct { - int frame; int dump_frame; - uint16_t rnti; int round_trials[8]; int total_bytes_tx; int total_bytes_rx; @@ -112,8 +110,6 @@ typedef struct { } NR_gNB_SCH_STATS_t; typedef struct { - int frame; - uint16_t rnti; int pucch0_sr_trials; int pucch0_sr_thres; int current_pucch0_sr_stat0; @@ -132,6 +128,17 @@ typedef struct { int pucch2_DTX; } NR_gNB_UCI_STATS_t; +typedef struct { + int frame; + uint16_t rnti; + bool active; + /// statistics for DLSCH measurement collection + NR_gNB_SCH_STATS_t dlsch_stats; + /// statistics for ULSCH measurement collection + NR_gNB_SCH_STATS_t ulsch_stats; + NR_gNB_UCI_STATS_t uci_stats; +} NR_gNB_PHY_STATS_t; + typedef struct { /// Pointers to variables related to DLSCH harq process NR_DL_gNB_HARQ_t harq_process; @@ -141,12 +148,8 @@ typedef struct { int32_t **mod_symbs; /// beamforming weights for UE-spec transmission (antenna ports 5 or 7..14), for each codeword, maximum 4 layers? int32_t ***ue_spec_bf_weights; - /// Allocated RNTI (0 means DLSCH_t is not currently used) - uint16_t rnti; /// Active flag for baseband transmitter processing uint8_t active; - /// HARQ process mask, indicates which processes are currently active - uint16_t harq_mask; /// Number of soft channel bits uint32_t G; } NR_gNB_DLSCH_t; @@ -185,18 +188,13 @@ typedef struct { typedef struct { /// Nfapi ULSCH PDU nfapi_nr_pusch_pdu_t ulsch_pdu; - /// Frame where current HARQ round was sent - uint32_t frame; - /// Slot where current HARQ round was sent - uint32_t slot; /// Index of current HARQ round for this DLSCH uint8_t round; bool new_rx; - /// Status Flag indicating for this ULSCH (idle,active,disabled) - NR_SCH_status_t status; - /// Flag to indicate that the UL configuration has been handled. Used to remove a stale ULSCH when frame wraps around - uint8_t handled; - /////////////////////// ulsch decoding /////////////////////// + /////////////////////// ulsch decoding /////////////////////// + /// flag used to clear d properly (together with d_to_be_cleared below) + /// set to true in nr_fill_ulsch() when new_data_indicator is received + bool harq_to_be_cleared; /// Transport block size (This is A from 38.212 V15.4.0 section 5.1) uint32_t TBS; /// Pointer to the payload (38.212 V15.4.0 section 5.1) @@ -213,6 +211,10 @@ typedef struct { uint32_t C; /// Pointers to code blocks after LDPC coding (38.212 V15.4.0 section 5.3.2) int16_t **d; + /// flag used to clear d properly (together with harq_to_be_cleared above) + /// set to true in nr_ulsch_decoding() when harq_to_be_cleared is true + /// when true, clear d in the next call to function nr_rate_matching_ldpc_rx() + bool *d_to_be_cleared; /// LDPC lifting size (38.212 V15.4.0 table 5.3.2-1) uint32_t Z; /// Number of bits in each code block after rate matching for LDPC code (38.212 V15.4.0 section 5.4.2.1) @@ -225,20 +227,61 @@ typedef struct { ////////////////////////////////////////////////////////////// } NR_UL_gNB_HARQ_t; +typedef struct { + //! estimated received spatial signal power (linear) + unsigned int rx_spatial_power[NB_ANTENNAS_TX][NB_ANTENNAS_RX]; + //! estimated received spatial signal power (dB) + unsigned int rx_spatial_power_dB[NB_ANTENNAS_TX][NB_ANTENNAS_RX]; + //! estimated rssi (dBm) + int rx_rssi_dBm; + //! estimated correlation (wideband linear) between spatial channels (computed in dlsch_demodulation) + int rx_correlation[2]; + //! estimated correlation (wideband dB) between spatial channels (computed in dlsch_demodulation) + int rx_correlation_dB[2]; + /// Wideband CQI (= SINR) + int wideband_cqi[MAX_NUM_RU_PER_gNB]; + /// Wideband CQI in dB (= SINR dB) + int wideband_cqi_dB[MAX_NUM_RU_PER_gNB]; + /// Wideband CQI (sum of all RX antennas, in dB) + char wideband_cqi_tot; + /// Subband CQI per RX antenna and RB (= SINR) + int subband_cqi[MAX_NUM_RU_PER_gNB][275]; + /// Total Subband CQI and RB (= SINR) + int subband_cqi_tot[275]; + /// Subband CQI in dB and RB (= SINR dB) + int subband_cqi_dB[MAX_NUM_RU_PER_gNB][275]; + /// Total Subband CQI and RB + int subband_cqi_tot_dB[275]; +} ulsch_measurements_gNB; typedef struct { + /// Time shift in number of samples estimated based on DMRS-PUSCH + int pusch_est_delay; + /// Max position in OFDM symbol related to time shift estimation based on DMRS-PUSCH + int pusch_delay_max_pos; + /// Max value related to time shift estimation based on DMRS-PUSCH + int pusch_delay_max_val; +} NR_ULSCH_delay_t; + +typedef struct { + uint32_t frame; + uint32_t slot; /// Pointers to 16 HARQ processes for the ULSCH - NR_UL_gNB_HARQ_t *harq_processes[NR_MAX_ULSCH_HARQ_PROCESSES]; + NR_UL_gNB_HARQ_t *harq_process; /// HARQ process mask, indicates which processes are currently active - uint16_t harq_mask; + int harq_pid; /// Allocated RNTI for this ULSCH uint16_t rnti; - /// RNTI type - uint8_t rnti_type; /// Maximum number of LDPC iterations uint8_t max_ldpc_iterations; /// number of iterations used in last LDPC decoding - uint8_t last_iteration_cnt; + uint8_t last_iteration_cnt; + /// Status Flag indicating for this ULSCH + bool active; + /// Flag to indicate that the UL configuration has been handled. Used to remove a stale ULSCH when frame wraps around + uint8_t handled; + NR_ULSCH_delay_t delay; + ulsch_measurements_gNB ulsch_measurements; } NR_gNB_ULSCH_t; typedef struct { @@ -492,8 +535,6 @@ typedef struct gNB_L1_proc_t_s { gNB_L1_rxtx_proc_t L1_proc, L1_proc_tx; } gNB_L1_proc_t; - - typedef struct { // common measurements //! estimated noise power (linear) @@ -517,44 +558,9 @@ typedef struct { //! estimated avg noise power per RB (dBm) int n0_subband_power_tot_dBm[275]; - // gNB measurements (per user) - //! estimated received spatial signal power (linear) - unsigned int rx_spatial_power[NUMBER_OF_NR_ULSCH_MAX][NB_ANTENNAS_TX][NB_ANTENNAS_RX]; - //! estimated received spatial signal power (dB) - unsigned int rx_spatial_power_dB[NUMBER_OF_NR_ULSCH_MAX][NB_ANTENNAS_TX][NB_ANTENNAS_RX]; - //! estimated rssi (dBm) - int rx_rssi_dBm[NUMBER_OF_NR_ULSCH_MAX]; - //! estimated correlation (wideband linear) between spatial channels (computed in dlsch_demodulation) - int rx_correlation[NUMBER_OF_NR_ULSCH_MAX][2]; - //! estimated correlation (wideband dB) between spatial channels (computed in dlsch_demodulation) - int rx_correlation_dB[NUMBER_OF_NR_ULSCH_MAX][2]; - - /// Wideband CQI (= SINR) - int wideband_cqi[NUMBER_OF_NR_ULSCH_MAX][MAX_NUM_RU_PER_gNB]; - /// Wideband CQI in dB (= SINR dB) - int wideband_cqi_dB[NUMBER_OF_NR_ULSCH_MAX][MAX_NUM_RU_PER_gNB]; - /// Wideband CQI (sum of all RX antennas, in dB) - char wideband_cqi_tot[NUMBER_OF_NR_ULSCH_MAX]; - /// Subband CQI per RX antenna and RB (= SINR) - int subband_cqi[NUMBER_OF_NR_ULSCH_MAX][MAX_NUM_RU_PER_gNB][275]; - /// Total Subband CQI and RB (= SINR) - int subband_cqi_tot[NUMBER_OF_NR_ULSCH_MAX][275]; - /// Subband CQI in dB and RB (= SINR dB) - int subband_cqi_dB[NUMBER_OF_NR_ULSCH_MAX][MAX_NUM_RU_PER_gNB][275]; - /// Total Subband CQI and RB - int subband_cqi_tot_dB[NUMBER_OF_NR_ULSCH_MAX][275]; /// PRACH background noise level int prach_I0; - struct delay_s { - /// Time shift in number of samples estimated based on DMRS-PUSCH - int pusch_est_delay; - /// Max position in OFDM symbol related to time shift estimation based on DMRS-PUSCH - int pusch_delay_max_pos; - /// Max value related to time shift estimation based on DMRS-PUSCH - int pusch_delay_max_val; - } delay[NUMBER_OF_NR_ULSCH_MAX]; - } PHY_MEASUREMENTS_gNB; @@ -607,19 +613,18 @@ typedef struct PHY_VARS_gNB_s { int max_nb_pucch; int max_nb_srs; + int max_nb_pdsch; + int max_nb_pusch; + NR_gNB_PBCH pbch; NR_gNB_COMMON common_vars; NR_gNB_PRACH prach_vars; NR_gNB_PRS prs_vars; - NR_gNB_PUSCH *pusch_vars[NUMBER_OF_NR_ULSCH_MAX]; - NR_gNB_PUCCH_t **pucch; - NR_gNB_SRS_t **srs; - NR_gNB_ULSCH_t *ulsch[NUMBER_OF_NR_ULSCH_MAX]; // [Nusers times] - /// statistics for DLSCH measurement collection - NR_gNB_SCH_STATS_t dlsch_stats[NUMBER_OF_NR_SCH_STATS_MAX]; - /// statistics for ULSCH measurement collection - NR_gNB_SCH_STATS_t ulsch_stats[NUMBER_OF_NR_SCH_STATS_MAX]; - NR_gNB_UCI_STATS_t uci_stats[NUMBER_OF_NR_UCI_STATS_MAX]; + NR_gNB_PUSCH *pusch_vars; + NR_gNB_PUCCH_t *pucch; + NR_gNB_SRS_t *srs; + NR_gNB_ULSCH_t *ulsch; + NR_gNB_PHY_STATS_t phy_stats[MAX_MOBILES_PER_GNB]; t_nrPolar_params **polarParams; /// SRS variables @@ -820,11 +825,13 @@ typedef struct processingData_L1tx { nfapi_nr_dl_tti_pdcch_pdu pdcch_pdu[NFAPI_NR_MAX_NB_CORESETS]; nfapi_nr_ul_dci_request_pdus_t ul_pdcch_pdu[NFAPI_NR_MAX_NB_CORESETS]; NR_gNB_CSIRS_t csirs_pdu[NR_SYMBOLS_PER_SLOT]; - NR_gNB_DLSCH_t *dlsch[NUMBER_OF_NR_DLSCH_MAX][2]; + NR_gNB_DLSCH_t **dlsch; NR_gNB_SSB_t ssb[64]; uint16_t num_pdsch_slot; int num_dl_pdcch; int num_ul_pdcch; + /* a reference to the sched_response, to release it when not needed anymore */ + int sched_response_id; } processingData_L1tx_t; #endif diff --git a/openair1/PHY/defs_nr_UE.h b/openair1/PHY/defs_nr_UE.h index 79e75ee325..1543c81e00 100644 --- a/openair1/PHY/defs_nr_UE.h +++ b/openair1/PHY/defs_nr_UE.h @@ -32,6 +32,10 @@ #ifndef __PHY_DEFS_NR_UE__H__ #define __PHY_DEFS_NR_UE__H__ +#ifdef __cplusplus +#include +#define _Atomic(X) std::atomic< X > +#endif #include "defs_nr_common.h" #include "CODING/nrPolar_tools/nr_polar_pbch_defs.h" @@ -316,17 +320,6 @@ typedef struct { #define PBCH_A 24 -typedef struct { - /// \brief Total number of PDU errors. - uint32_t pdu_errors; - /// \brief Total number of PDU errors 128 frames ago. - uint32_t pdu_errors_last; - /// \brief Total number of consecutive PDU errors. - uint32_t pdu_errors_conseq; - /// \brief FER (in percent) . - //uint32_t pdu_fer; -} NR_UE_PBCH; - typedef struct { int16_t amp; bool active; @@ -385,9 +378,6 @@ typedef struct { uint8_t CC_id; /// \brief Mapping of CC_id antennas to cards openair0_rf_map rf_map; - //uint8_t local_flag; - /// \brief Indicator of current run mode of UE (normal_txrx, rx_calib_ue, no_L2_connect, debug_prach) - runmode_t mode; /// \brief Indicator that UE should perform band scanning int UE_scan; /// \brief Indicator that UE should perform coarse scanning around carrier @@ -400,8 +390,8 @@ typedef struct { int if_freq_off; /// \brief Indicator that UE is synchronized to a gNB int is_synchronized; - /// \brief Indicator that UE lost frame synchronization - int lost_sync; + /// \brief Target gNB Nid_cell when UE is resynchronizing + int target_Nid_cell; /// Data structure for UE process scheduling UE_nr_proc_t proc; /// Flag to indicate the UE shouldn't do timing correction at all @@ -440,8 +430,8 @@ typedef struct { nr_ue_if_module_t *if_inst; fapi_nr_config_request_t nrUE_config; + nr_synch_request_t synch_request; - NR_UE_PBCH *pbch_vars[NUMBER_OF_CONNECTED_gNB_MAX]; NR_UE_PRACH *prach_vars[NUMBER_OF_CONNECTED_gNB_MAX]; NR_UE_CSI_IM *csiim_vars[NUMBER_OF_CONNECTED_gNB_MAX]; NR_UE_CSI_RS *csirs_vars[NUMBER_OF_CONNECTED_gNB_MAX]; @@ -652,7 +642,7 @@ typedef struct { SLIST_HEAD(ral_thresholds_lte_poll_s, ral_threshold_phy_t) ral_thresholds_lte_polled[RAL_LINK_PARAM_LTE_MAX]; #endif int dl_errors; - int dl_stats[8]; + _Atomic(int) dl_stats[16]; void* scopeData; // Pointers to hold PDSCH data only for phy simulators void *phy_sim_rxdataF; @@ -661,6 +651,10 @@ typedef struct { void *phy_sim_pdsch_rxdataF_comp; void *phy_sim_pdsch_dl_ch_estimates; void *phy_sim_pdsch_dl_ch_estimates_ext; + uint8_t *phy_sim_dlsch_b; + notifiedFIFO_t phy_config_ind; + notifiedFIFO_t *tx_resume_ind_fifo[NR_MAX_SLOTS_PER_FRAME]; + int tx_wait_for_dlsch[NR_MAX_SLOTS_PER_FRAME]; } PHY_VARS_NR_UE; typedef struct nr_phy_data_tx_s { @@ -679,6 +673,8 @@ typedef struct nr_rxtx_thread_data_s { UE_nr_rxtx_proc_t proc; PHY_VARS_NR_UE *UE; int writeBlockSize; + nr_phy_data_t phy_data; + int tx_wait_for_dlsch; } nr_rxtx_thread_data_t; typedef struct LDPCDecode_ue_s { @@ -704,6 +700,7 @@ typedef struct LDPCDecode_ue_s { time_stats_t ts_deinterleave; time_stats_t ts_rate_unmatch; time_stats_t ts_ldpc_decode; + UE_nr_rxtx_proc_t *proc; } ldpcDecode_ue_t; #include "SIMULATION/ETH_TRANSPORT/defs.h" diff --git a/openair1/PHY/impl_defs_top.h b/openair1/PHY/impl_defs_top.h index 6afbd1bf2b..679fd34a49 100644 --- a/openair1/PHY/impl_defs_top.h +++ b/openair1/PHY/impl_defs_top.h @@ -270,7 +270,7 @@ /* FFS_NR_TODO it defines ue capability which is the number of slots */ /* - between reception of pdsch and tarnsmission of its acknowlegment */ /* - between reception of un uplink grant and its related transmission */ -#define NR_UE_CAPABILITY_SLOT_RX_TO_TX (4) +#define NR_UE_CAPABILITY_SLOT_RX_TO_TX (3) #ifndef NO_RAT_NR #define DURATION_RX_TO_TX (NR_UE_CAPABILITY_SLOT_RX_TO_TX) /* for NR this will certainly depends to such UE capability which is not yet defined */ diff --git a/openair1/SCHED_NR/fapi_nr_l1.c b/openair1/SCHED_NR/fapi_nr_l1.c index 4617189805..d72eb208c3 100644 --- a/openair1/SCHED_NR/fapi_nr_l1.c +++ b/openair1/SCHED_NR/fapi_nr_l1.c @@ -35,6 +35,7 @@ #include "PHY/NR_TRANSPORT/nr_dlsch.h" #include "PHY/NR_TRANSPORT/nr_dci.h" #include "nfapi/oai_integration/vendor_ext.h" +#include "openair2/NR_PHY_INTERFACE/nr_sched_response.h" #define USE_MSGQ 1 @@ -102,11 +103,8 @@ void handle_nr_nfapi_ssb_pdu(processingData_L1tx_t *msgTx,int frame,int slot, }*/ - -void handle_nfapi_nr_csirs_pdu(processingData_L1tx_t *msgTx, - int frame,int slot, - nfapi_nr_dl_tti_csi_rs_pdu *csirs_pdu) { - +void handle_nfapi_nr_csirs_pdu(processingData_L1tx_t *msgTx, int frame, int slot, nfapi_nr_dl_tti_csi_rs_pdu *csirs_pdu) +{ int found = 0; for (int id = 0; id < NR_SYMBOLS_PER_SLOT; id++) { @@ -123,33 +121,30 @@ void handle_nfapi_nr_csirs_pdu(processingData_L1tx_t *msgTx, LOG_E(MAC,"CSI-RS list is full\n"); } - void handle_nr_nfapi_pdsch_pdu(processingData_L1tx_t *msgTx, nfapi_nr_dl_tti_pdsch_pdu *pdsch_pdu, uint8_t *sdu) { - nr_fill_dlsch(msgTx,pdsch_pdu,sdu); } -void nr_schedule_response(NR_Sched_Rsp_t *Sched_INFO){ - - PHY_VARS_gNB *gNB; +void nr_schedule_response(NR_Sched_Rsp_t *Sched_INFO) +{ // copy data from L2 interface into L1 structures module_id_t Mod_id = Sched_INFO->module_id; - nfapi_nr_dl_tti_request_t *DL_req = Sched_INFO->DL_req; - nfapi_nr_tx_data_request_t *TX_req = Sched_INFO->TX_req; - nfapi_nr_ul_tti_request_t *UL_tti_req = Sched_INFO->UL_tti_req; - nfapi_nr_ul_dci_request_t *UL_dci_req = Sched_INFO->UL_dci_req; + nfapi_nr_dl_tti_request_t *DL_req = &Sched_INFO->DL_req; + nfapi_nr_tx_data_request_t *TX_req = &Sched_INFO->TX_req; + nfapi_nr_ul_tti_request_t *UL_tti_req = &Sched_INFO->UL_tti_req; + nfapi_nr_ul_dci_request_t *UL_dci_req = &Sched_INFO->UL_dci_req; frame_t frame = Sched_INFO->frame; sub_frame_t slot = Sched_INFO->slot; AssertFatal(RC.gNB!=NULL,"RC.gNB is null\n"); AssertFatal(RC.gNB[Mod_id]!=NULL,"RC.gNB[%d] is null\n",Mod_id); - gNB = RC.gNB[Mod_id]; + PHY_VARS_gNB *gNB = RC.gNB[Mod_id]; start_meas(&gNB->schedule_response_stats); nfapi_nr_config_request_scf_t *cfg = &gNB->gNB_config; @@ -179,11 +174,13 @@ void nr_schedule_response(NR_Sched_Rsp_t *Sched_INFO){ /*const time_stats_t ts = exec_time_stats_NotifiedFIFO(res); merge_meas(&gNB->phy_proc_tx, &ts); */ - msgTx->num_pdsch_slot=0; - msgTx->num_dl_pdcch=0; - msgTx->num_ul_pdcch=number_ul_dci_pdu; + msgTx->num_pdsch_slot = 0; + msgTx->num_dl_pdcch = 0; + msgTx->num_ul_pdcch = number_ul_dci_pdu; msgTx->slot = slot; msgTx->frame = frame; + /* store the sched_response_id for the TX thread to release it when done */ + msgTx->sched_response_id = Sched_INFO->sched_response_id; for (int i=0;idl_tti_request_body.dl_tti_pdu_list[i]; @@ -212,8 +209,10 @@ 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; - AssertFatal(msgTx->num_pdsch_slot < NUMBER_OF_NR_DLSCH_MAX,"Number of PDSCH PDUs %d exceeded the limit %d\n", - msgTx->num_pdsch_slot, NUMBER_OF_NR_DLSCH_MAX); + AssertFatal(msgTx->num_pdsch_slot < gNB->max_nb_pdsch, + "Number of PDSCH PDUs %d exceeded the limit %d\n", + msgTx->num_pdsch_slot, + gNB->max_nb_pdsch); handle_nr_nfapi_pdsch_pdu(msgTx,&dl_tti_pdu->pdsch_pdu, sdu); } } @@ -221,13 +220,16 @@ void nr_schedule_response(NR_Sched_Rsp_t *Sched_INFO){ for (int i=0; iul_pdcch_pdu[i] = UL_dci_req->ul_dci_pdu_list[i]; + /* Both the current thread and the TX thread will access the sched_info + * at the same time, so increase its reference counter, so that it is + * released only when both threads are done with it. + */ + inc_ref_sched_response(Sched_INFO->sched_response_id); #ifndef USE_MSGQ if (gNB->reorder_thread_disable) pushNotifiedFIFO(&gNB->L1_tx_out,res); else pushNotifiedFIFO(&gNB->L1_tx_filled,res); -#else - //pushNotifiedFIFO(&gNB->L1_tx_out, res); #endif } @@ -270,5 +272,9 @@ void nr_schedule_response(NR_Sched_Rsp_t *Sched_INFO){ if (number_dl_pdu>0) oai_nfapi_dl_tti_req(DL_req); } + + /* this thread is done with the sched_info, decrease the reference counter */ + deref_sched_response(Sched_INFO->sched_response_id); + stop_meas(&gNB->schedule_response_stats); } diff --git a/openair1/SCHED_NR/phy_procedures_nr_gNB.c b/openair1/SCHED_NR/phy_procedures_nr_gNB.c index 5d419a2a45..1679e32275 100644 --- a/openair1/SCHED_NR/phy_procedures_nr_gNB.c +++ b/openair1/SCHED_NR/phy_procedures_nr_gNB.c @@ -207,12 +207,13 @@ void phy_procedures_gNB_TX(processingData_L1tx_t *msgTx, VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_gNB_TX+offset,0); } -void nr_postDecode(PHY_VARS_gNB *gNB, notifiedFIFO_elt_t *req) { +void nr_postDecode(PHY_VARS_gNB *gNB, notifiedFIFO_elt_t *req) +{ ldpcDecode_t *rdata = (ldpcDecode_t*) NotifiedFifoData(req); NR_UL_gNB_HARQ_t *ulsch_harq = rdata->ulsch_harq; NR_gNB_ULSCH_t *ulsch = rdata->ulsch; int r = rdata->segment_r; - nfapi_nr_pusch_pdu_t *pusch_pdu = &gNB->ulsch[rdata->ulsch_id]->harq_processes[rdata->harq_pid]->ulsch_pdu; + nfapi_nr_pusch_pdu_t *pusch_pdu = &gNB->ulsch[rdata->ulsch_id].harq_process->ulsch_pdu; bool decodeSuccess = (rdata->decodeIterations <= rdata->decoderParms.numMaxIter); ulsch_harq->processedSegments++; LOG_D(PHY, "processing result of segment: %d, processed %d/%d\n", @@ -240,83 +241,100 @@ void nr_postDecode(PHY_VARS_gNB *gNB, notifiedFIFO_elt_t *req) { //int dumpsig=0; // if all segments are done if (rdata->nbSegments == ulsch_harq->processedSegments) { - if (decodeSuccess && !gNB->pusch_vars[rdata->ulsch_id]->DTX) { - LOG_D(PHY,"[gNB %d] ULSCH: Setting ACK for SFN/SF %d.%d (pid %d, ndi %d, status %d, round %d, TBS %d, Max interation (all seg) %d)\n", - gNB->Mod_id,ulsch_harq->frame,ulsch_harq->slot,rdata->harq_pid,pusch_pdu->pusch_data.new_data_indicator,ulsch_harq->status,ulsch_harq->round,ulsch_harq->TBS,rdata->decodeIterations); - ulsch_harq->status = NR_SCH_IDLE; - ulsch_harq->round = 0; - ulsch->harq_mask &= ~(1 << rdata->harq_pid); - + if (decodeSuccess && !gNB->pusch_vars[rdata->ulsch_id].DTX) { + LOG_D(PHY, + "[gNB %d] ULSCH: Setting ACK for SFN/SF %d.%d (rnti %x, pid %d, ndi %d, status %d, round %d, TBS %d, Max interation " + "(all seg) %d)\n", + gNB->Mod_id, + ulsch->frame, + ulsch->slot, + ulsch->rnti, + rdata->harq_pid, + pusch_pdu->pusch_data.new_data_indicator, + ulsch->active, + ulsch_harq->round, + ulsch_harq->TBS, + rdata->decodeIterations); + ulsch->active = false; + ulsch_harq->round = 0; LOG_D(PHY, "ULSCH received ok \n"); - nr_fill_indication(gNB,ulsch_harq->frame, ulsch_harq->slot, rdata->ulsch_id, rdata->harq_pid, 0,0); + nr_fill_indication(gNB, ulsch->frame, ulsch->slot, rdata->ulsch_id, rdata->harq_pid, 0, 0); //dumpsig=1; } else { - LOG_D(PHY,"[gNB %d] ULSCH: Setting NAK for SFN/SF %d/%d (pid %d, ndi %d, status %d, round %d, RV %d, prb_start %d, prb_size %d, TBS %d) r %d\n", - gNB->Mod_id, ulsch_harq->frame, ulsch_harq->slot, - rdata->harq_pid, pusch_pdu->pusch_data.new_data_indicator, ulsch_harq->status, - ulsch_harq->round, + LOG_D(PHY, + "[gNB %d] ULSCH: Setting NAK for SFN/SF %d/%d (pid %d, ndi %d, status %d, round %d, RV %d, prb_start %d, prb_size %d, " + "TBS %d) r %d\n", + gNB->Mod_id, + ulsch->frame, + ulsch->slot, + rdata->harq_pid, + pusch_pdu->pusch_data.new_data_indicator, + ulsch->active, + ulsch_harq->round, ulsch_harq->ulsch_pdu.pusch_data.rv_index, - ulsch_harq->ulsch_pdu.rb_start, - ulsch_harq->ulsch_pdu.rb_size, - ulsch_harq->TBS, - r); - ulsch_harq->handled = 1; - + ulsch_harq->ulsch_pdu.rb_start, + ulsch_harq->ulsch_pdu.rb_size, + ulsch_harq->TBS, + r); + ulsch->handled = 1; LOG_D(PHY, "ULSCH %d in error\n",rdata->ulsch_id); - nr_fill_indication(gNB,ulsch_harq->frame, ulsch_harq->slot, rdata->ulsch_id, rdata->harq_pid, 1,0); -// dumpsig=1; + nr_fill_indication(gNB, ulsch->frame, ulsch->slot, rdata->ulsch_id, rdata->harq_pid, 1, 0); + // dumpsig=1; } -/* - if (ulsch_harq->ulsch_pdu.mcs_index == 0 && dumpsig==1) { - int off = ((ulsch_harq->ulsch_pdu.rb_size&1) == 1)? 4:0; + /* + if (ulsch_harq->ulsch_pdu.mcs_index == 0 && dumpsig==1) { + int off = ((ulsch_harq->ulsch_pdu.rb_size&1) == 1)? 4:0; - LOG_M("rxsigF0.m","rxsF0",&gNB->common_vars.rxdataF[0][(ulsch_harq->slot&3)*gNB->frame_parms.ofdm_symbol_size*gNB->frame_parms.symbols_per_slot],gNB->frame_parms.ofdm_symbol_size*gNB->frame_parms.symbols_per_slot,1,1); - LOG_M("rxsigF0_ext.m","rxsF0_ext", - &gNB->pusch_vars[0]->rxdataF_ext[0][ulsch_harq->ulsch_pdu.start_symbol_index*NR_NB_SC_PER_RB * ulsch_harq->ulsch_pdu.rb_size],ulsch_harq->ulsch_pdu.nr_of_symbols*(off+(NR_NB_SC_PER_RB * ulsch_harq->ulsch_pdu.rb_size)),1,1); - LOG_M("chestF0.m","chF0", - &gNB->pusch_vars[0]->ul_ch_estimates[0][ulsch_harq->ulsch_pdu.start_symbol_index*gNB->frame_parms.ofdm_symbol_size],gNB->frame_parms.ofdm_symbol_size,1,1); - LOG_M("chestF0_ext.m","chF0_ext", - &gNB->pusch_vars[0]->ul_ch_estimates_ext[0][(ulsch_harq->ulsch_pdu.start_symbol_index+1)*(off+(NR_NB_SC_PER_RB * ulsch_harq->ulsch_pdu.rb_size))], - (ulsch_harq->ulsch_pdu.nr_of_symbols-1)*(off+(NR_NB_SC_PER_RB * ulsch_harq->ulsch_pdu.rb_size)),1,1); - LOG_M("rxsigF0_comp.m","rxsF0_comp", - &gNB->pusch_vars[0]->rxdataF_comp[0][ulsch_harq->ulsch_pdu.start_symbol_index*(off+(NR_NB_SC_PER_RB * ulsch_harq->ulsch_pdu.rb_size))],ulsch_harq->ulsch_pdu.nr_of_symbols*(off+(NR_NB_SC_PER_RB * ulsch_harq->ulsch_pdu.rb_size)),1,1); - LOG_M("rxsigF0_llr.m","rxsF0_llr", - &gNB->pusch_vars[0]->llr[0],(ulsch_harq->ulsch_pdu.nr_of_symbols-1)*NR_NB_SC_PER_RB * ulsch_harq->ulsch_pdu.rb_size * ulsch_harq->ulsch_pdu.qam_mod_order,1,0); - if (gNB->frame_parms.nb_antennas_rx > 1) { + LOG_M("rxsigF0.m","rxsF0",&gNB->common_vars.rxdataF[0][(ulsch_harq->slot&3)*gNB->frame_parms.ofdm_symbol_size*gNB->frame_parms.symbols_per_slot],gNB->frame_parms.ofdm_symbol_size*gNB->frame_parms.symbols_per_slot,1,1); + LOG_M("rxsigF0_ext.m","rxsF0_ext", + &gNB->pusch_vars[0].rxdataF_ext[0][ulsch_harq->ulsch_pdu.start_symbol_index*NR_NB_SC_PER_RB * + ulsch_harq->ulsch_pdu.rb_size],ulsch_harq->ulsch_pdu.nr_of_symbols*(off+(NR_NB_SC_PER_RB * + ulsch_harq->ulsch_pdu.rb_size)),1,1); LOG_M("chestF0.m","chF0", + &gNB->pusch_vars[0].ul_ch_estimates[0][ulsch_harq->ulsch_pdu.start_symbol_index*gNB->frame_parms.ofdm_symbol_size],gNB->frame_parms.ofdm_symbol_size,1,1); + LOG_M("chestF0_ext.m","chF0_ext", + &gNB->pusch_vars[0]->ul_ch_estimates_ext[0][(ulsch_harq->ulsch_pdu.start_symbol_index+1)*(off+(NR_NB_SC_PER_RB * + ulsch_harq->ulsch_pdu.rb_size))], (ulsch_harq->ulsch_pdu.nr_of_symbols-1)*(off+(NR_NB_SC_PER_RB * + ulsch_harq->ulsch_pdu.rb_size)),1,1); LOG_M("rxsigF0_comp.m","rxsF0_comp", + &gNB->pusch_vars[0].rxdataF_comp[0][ulsch_harq->ulsch_pdu.start_symbol_index*(off+(NR_NB_SC_PER_RB * + ulsch_harq->ulsch_pdu.rb_size))],ulsch_harq->ulsch_pdu.nr_of_symbols*(off+(NR_NB_SC_PER_RB * + ulsch_harq->ulsch_pdu.rb_size)),1,1); LOG_M("rxsigF0_llr.m","rxsF0_llr", + &gNB->pusch_vars[0].llr[0],(ulsch_harq->ulsch_pdu.nr_of_symbols-1)*NR_NB_SC_PER_RB * ulsch_harq->ulsch_pdu.rb_size * + ulsch_harq->ulsch_pdu.qam_mod_order,1,0); if (gNB->frame_parms.nb_antennas_rx > 1) { - LOG_M("rxsigF1_ext.m","rxsF0_ext", - &gNB->pusch_vars[0]->rxdataF_ext[1][ulsch_harq->ulsch_pdu.start_symbol_index*NR_NB_SC_PER_RB * ulsch_harq->ulsch_pdu.rb_size],ulsch_harq->ulsch_pdu.nr_of_symbols*(off+(NR_NB_SC_PER_RB * ulsch_harq->ulsch_pdu.rb_size)),1,1); - LOG_M("chestF1.m","chF1", - &gNB->pusch_vars[0]->ul_ch_estimates[1][ulsch_harq->ulsch_pdu.start_symbol_index*gNB->frame_parms.ofdm_symbol_size],gNB->frame_parms.ofdm_symbol_size,1,1); - LOG_M("chestF1_ext.m","chF1_ext", - &gNB->pusch_vars[0]->ul_ch_estimates_ext[1][(ulsch_harq->ulsch_pdu.start_symbol_index+1)*(off+(NR_NB_SC_PER_RB * ulsch_harq->ulsch_pdu.rb_size))], - (ulsch_harq->ulsch_pdu.nr_of_symbols-1)*(off+(NR_NB_SC_PER_RB * ulsch_harq->ulsch_pdu.rb_size)),1,1); - LOG_M("rxsigF1_comp.m","rxsF1_comp", - &gNB->pusch_vars[0]->rxdataF_comp[1][ulsch_harq->ulsch_pdu.start_symbol_index*(off+(NR_NB_SC_PER_RB * ulsch_harq->ulsch_pdu.rb_size))],ulsch_harq->ulsch_pdu.nr_of_symbols*(off+(NR_NB_SC_PER_RB * ulsch_harq->ulsch_pdu.rb_size)),1,1); - } - exit(-1); + LOG_M("rxsigF1_ext.m","rxsF0_ext", + &gNB->pusch_vars[0].rxdataF_ext[1][ulsch_harq->ulsch_pdu.start_symbol_index*NR_NB_SC_PER_RB * + ulsch_harq->ulsch_pdu.rb_size],ulsch_harq->ulsch_pdu.nr_of_symbols*(off+(NR_NB_SC_PER_RB * + ulsch_harq->ulsch_pdu.rb_size)),1,1); LOG_M("chestF1.m","chF1", + &gNB->pusch_vars[0].ul_ch_estimates[1][ulsch_harq->ulsch_pdu.start_symbol_index*gNB->frame_parms.ofdm_symbol_size],gNB->frame_parms.ofdm_symbol_size,1,1); + LOG_M("chestF1_ext.m","chF1_ext", + &gNB->pusch_vars[0].ul_ch_estimates_ext[1][(ulsch_harq->ulsch_pdu.start_symbol_index+1)*(off+(NR_NB_SC_PER_RB * + ulsch_harq->ulsch_pdu.rb_size))], (ulsch_harq->ulsch_pdu.nr_of_symbols-1)*(off+(NR_NB_SC_PER_RB * + ulsch_harq->ulsch_pdu.rb_size)),1,1); LOG_M("rxsigF1_comp.m","rxsF1_comp", + &gNB->pusch_vars[0].rxdataF_comp[1][ulsch_harq->ulsch_pdu.start_symbol_index*(off+(NR_NB_SC_PER_RB * + ulsch_harq->ulsch_pdu.rb_size))],ulsch_harq->ulsch_pdu.nr_of_symbols*(off+(NR_NB_SC_PER_RB * + ulsch_harq->ulsch_pdu.rb_size)),1,1); + } + exit(-1); - } -*/ + } + */ ulsch->last_iteration_cnt = rdata->decodeIterations; VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_gNB_ULSCH_DECODING,0); } } - void nr_ulsch_procedures(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, int ULSCH_id, uint8_t harq_pid) { NR_DL_FRAME_PARMS *frame_parms = &gNB->frame_parms; - nfapi_nr_pusch_pdu_t *pusch_pdu = &gNB->ulsch[ULSCH_id]->harq_processes[harq_pid]->ulsch_pdu; - - uint8_t l, number_dmrs_symbols = 0; - uint32_t G; - uint16_t start_symbol, number_symbols, nb_re_dmrs; - uint8_t enable_ldpc_offload = gNB->ldpc_offload_flag; - start_symbol = pusch_pdu->start_symbol_index; - number_symbols = pusch_pdu->nr_of_symbols; + nfapi_nr_pusch_pdu_t *pusch_pdu = &gNB->ulsch[ULSCH_id].harq_process->ulsch_pdu; - for (l = start_symbol; l < start_symbol + number_symbols; l++) + uint16_t nb_re_dmrs; + uint8_t enable_ldpc_offload = gNB->ldpc_offload_flag; + uint16_t start_symbol = pusch_pdu->start_symbol_index; + uint16_t number_symbols = pusch_pdu->nr_of_symbols; + + uint8_t number_dmrs_symbols = 0; + for (int l = start_symbol; l < start_symbol + number_symbols; l++) number_dmrs_symbols += ((pusch_pdu->ul_dmrs_symb_pos)>>l)&0x01; if (pusch_pdu->dmrs_config_type==pusch_dmrs_type1) @@ -324,13 +342,13 @@ void nr_ulsch_procedures(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, int ULSCH else nb_re_dmrs = 4*pusch_pdu->num_dmrs_cdm_grps_no_data; - G = nr_get_G(pusch_pdu->rb_size, - number_symbols, - nb_re_dmrs, - number_dmrs_symbols, // number of dmrs symbols irrespective of single or double symbol dmrs - pusch_pdu->qam_mod_order, - pusch_pdu->nrOfLayers); - + uint32_t G = nr_get_G(pusch_pdu->rb_size, + number_symbols, + nb_re_dmrs, + number_dmrs_symbols, // number of dmrs symbols irrespective of single or double symbol dmrs + pusch_pdu->qam_mod_order, + pusch_pdu->nrOfLayers); + AssertFatal(G>0,"G is 0 : rb_size %u, number_symbols %d, nb_re_dmrs %d, number_dmrs_symbols %d, qam_mod_order %u, nrOfLayer %u\n", pusch_pdu->rb_size, number_symbols, @@ -347,37 +365,25 @@ void nr_ulsch_procedures(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, int ULSCH pusch_pdu->qam_mod_order, pusch_pdu->nrOfLayers); - - nr_ulsch_layer_demapping(gNB->pusch_vars[ULSCH_id]->llr, + nr_ulsch_layer_demapping(gNB->pusch_vars[ULSCH_id].llr, pusch_pdu->nrOfLayers, pusch_pdu->qam_mod_order, G, - gNB->pusch_vars[ULSCH_id]->llr_layers); - + gNB->pusch_vars[ULSCH_id].llr_layers); + //---------------------------------------------------------- //------------------- ULSCH unscrambling ------------------- //---------------------------------------------------------- start_meas(&gNB->ulsch_unscrambling_stats); - nr_ulsch_unscrambling(gNB->pusch_vars[ULSCH_id]->llr, - G, - pusch_pdu->data_scrambling_id, - pusch_pdu->rnti); + nr_ulsch_unscrambling(gNB->pusch_vars[ULSCH_id].llr, G, pusch_pdu->data_scrambling_id, pusch_pdu->rnti); stop_meas(&gNB->ulsch_unscrambling_stats); //---------------------------------------------------------- //--------------------- ULSCH decoding --------------------- //---------------------------------------------------------- start_meas(&gNB->ulsch_decoding_stats); - nr_ulsch_decoding(gNB, - ULSCH_id, - gNB->pusch_vars[ULSCH_id]->llr, - frame_parms, - pusch_pdu, - frame_rx, - slot_rx, - harq_pid, - G); - if (enable_ldpc_offload ==0) { + nr_ulsch_decoding(gNB, ULSCH_id, gNB->pusch_vars[ULSCH_id].llr, frame_parms, pusch_pdu, frame_rx, slot_rx, harq_pid, G); + if (enable_ldpc_offload == 0) { while (gNB->nbDecode > 0) { notifiedFIFO_elt_t *req = pullTpool(&gNB->respDecode, &gNB->threadPool); if (req == NULL) @@ -385,25 +391,26 @@ void nr_ulsch_procedures(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, int ULSCH nr_postDecode(gNB, req); delNotifiedFIFO_elt(req); } - } + } stop_meas(&gNB->ulsch_decoding_stats); } #define USE_MSGQ 1 -void nr_fill_indication(PHY_VARS_gNB *gNB, int frame, int slot_rx, int ULSCH_id, uint8_t harq_pid, uint8_t crc_flag, int dtx_flag) { - +void nr_fill_indication(PHY_VARS_gNB *gNB, int frame, int slot_rx, int ULSCH_id, uint8_t harq_pid, uint8_t crc_flag, int dtx_flag) +{ #ifndef USE_MSGQ pthread_mutex_lock(&gNB->UL_INFO_mutex); #endif - NR_gNB_ULSCH_t *ulsch = gNB->ulsch[ULSCH_id]; - NR_UL_gNB_HARQ_t *harq_process = ulsch->harq_processes[harq_pid]; - NR_gNB_SCH_STATS_t *stats=get_ulsch_stats(gNB,ulsch); + + NR_gNB_ULSCH_t *ulsch = &gNB->ulsch[ULSCH_id]; + NR_UL_gNB_HARQ_t *harq_process = ulsch->harq_process; + NR_gNB_PHY_STATS_t *stats = get_phy_stats(gNB, ulsch->rnti); nfapi_nr_pusch_pdu_t *pusch_pdu = &harq_process->ulsch_pdu; // Get estimated timing advance for MAC - int sync_pos = gNB->measurements.delay[ULSCH_id].pusch_est_delay; + int sync_pos = ulsch->delay.pusch_est_delay; // scale the 16 factor in N_TA calculation in 38.213 section 4.2 according to the used FFT size uint16_t bw_scaling = 16 * gNB->frame_parms.ofdm_symbol_size / 2048; @@ -414,7 +421,8 @@ void nr_fill_indication(PHY_VARS_gNB *gNB, int frame, int slot_rx, int ULSCH_id, sync_pos_rounded = sync_pos + (bw_scaling / 2) - 1; else sync_pos_rounded = sync_pos - (bw_scaling / 2) + 1; - if (stats) stats->sync_pos = sync_pos; + if (stats) + stats->ulsch_stats.sync_pos = sync_pos; int timing_advance_update = sync_pos_rounded / bw_scaling; @@ -427,10 +435,17 @@ void nr_fill_indication(PHY_VARS_gNB *gNB, int frame, int slot_rx, int ULSCH_id, if (crc_flag == 0) LOG_D(PHY, "%d.%d : Received PUSCH : Estimated timing advance PUSCH is = %d, timing_advance_update is %d \n", frame,slot_rx,sync_pos,timing_advance_update); // estimate UL_CQI for MAC - int SNRtimes10 = dB_fixed_x10(gNB->pusch_vars[ULSCH_id]->ulsch_power_tot) - - dB_fixed_x10(gNB->pusch_vars[ULSCH_id]->ulsch_noise_power_tot); + int SNRtimes10 = + dB_fixed_x10(gNB->pusch_vars[ULSCH_id].ulsch_power_tot) - dB_fixed_x10(gNB->pusch_vars[ULSCH_id].ulsch_noise_power_tot); - LOG_D(PHY, "%d.%d: Estimated SNR for PUSCH is = %f dB (ulsch_power %f, noise %f) delay %d\n", frame, slot_rx, SNRtimes10/10.0,dB_fixed_x10(gNB->pusch_vars[ULSCH_id]->ulsch_power_tot)/10.0,dB_fixed_x10(gNB->pusch_vars[ULSCH_id]->ulsch_noise_power_tot)/10.0,sync_pos); + LOG_D(PHY, + "%d.%d: Estimated SNR for PUSCH is = %f dB (ulsch_power %f, noise %f) delay %d\n", + frame, + slot_rx, + SNRtimes10 / 10.0, + dB_fixed_x10(gNB->pusch_vars[ULSCH_id].ulsch_power_tot) / 10.0, + dB_fixed_x10(gNB->pusch_vars[ULSCH_id].ulsch_noise_power_tot) / 10.0, + sync_pos); int cqi; if (SNRtimes10 < -640) cqi=0; @@ -443,28 +458,64 @@ void nr_fill_indication(PHY_VARS_gNB *gNB, int frame, int slot_rx, int ULSCH_id, int off = ((pusch_pdu->rb_size&1) == 1)? 4:0; LOG_M("rxsigF0.m","rxsF0",&gNB->common_vars.rxdataF[0][(slot_rx&3)*gNB->frame_parms.ofdm_symbol_size*gNB->frame_parms.symbols_per_slot],gNB->frame_parms.ofdm_symbol_size*gNB->frame_parms.symbols_per_slot,1,1); - LOG_M("rxsigF0_ext.m","rxsF0_ext", - &gNB->pusch_vars[0]->rxdataF_ext[0][pusch_pdu->start_symbol_index*NR_NB_SC_PER_RB * pusch_pdu->rb_size],pusch_pdu->nr_of_symbols*(off+(NR_NB_SC_PER_RB * pusch_pdu->rb_size)),1,1); - LOG_M("chestF0.m","chF0", - &gNB->pusch_vars[0]->ul_ch_estimates[0][pusch_pdu->start_symbol_index*gNB->frame_parms.ofdm_symbol_size],gNB->frame_parms.ofdm_symbol_size,1,1); - LOG_M("chestF0_ext.m","chF0_ext", - &gNB->pusch_vars[0]->ul_ch_estimates_ext[0][(pusch_pdu->start_symbol_index+1)*(off+(NR_NB_SC_PER_RB * pusch_pdu->rb_size))], - (pusch_pdu->nr_of_symbols-1)*(off+(NR_NB_SC_PER_RB * pusch_pdu->rb_size)),1,1); - LOG_M("rxsigF0_comp.m","rxsF0_comp", - &gNB->pusch_vars[0]->rxdataF_comp[0][pusch_pdu->start_symbol_index*(off+(NR_NB_SC_PER_RB * pusch_pdu->rb_size))],pusch_pdu->nr_of_symbols*(off+(NR_NB_SC_PER_RB * pusch_pdu->rb_size)),1,1); - LOG_M("rxsigF0_llr.m","rxsF0_llr", - &gNB->pusch_vars[0]->llr[0],(pusch_pdu->nr_of_symbols-1)*NR_NB_SC_PER_RB *pusch_pdu->rb_size * pusch_pdu->qam_mod_order,1,0); + LOG_M("rxsigF0_ext.m", + "rxsF0_ext", + &gNB->pusch_vars[0].rxdataF_ext[0][pusch_pdu->start_symbol_index * NR_NB_SC_PER_RB * pusch_pdu->rb_size], + pusch_pdu->nr_of_symbols * (off + (NR_NB_SC_PER_RB * pusch_pdu->rb_size)), + 1, + 1); + LOG_M("chestF0.m", + "chF0", + &gNB->pusch_vars[0].ul_ch_estimates[0][pusch_pdu->start_symbol_index * gNB->frame_parms.ofdm_symbol_size], + gNB->frame_parms.ofdm_symbol_size, + 1, + 1); + LOG_M("chestF0_ext.m", + "chF0_ext", + &gNB->pusch_vars[0] + .ul_ch_estimates_ext[0][(pusch_pdu->start_symbol_index + 1) * (off + (NR_NB_SC_PER_RB * pusch_pdu->rb_size))], + (pusch_pdu->nr_of_symbols - 1) * (off + (NR_NB_SC_PER_RB * pusch_pdu->rb_size)), + 1, + 1); + LOG_M("rxsigF0_comp.m", + "rxsF0_comp", + &gNB->pusch_vars[0].rxdataF_comp[0][pusch_pdu->start_symbol_index * (off + (NR_NB_SC_PER_RB * pusch_pdu->rb_size))], + pusch_pdu->nr_of_symbols * (off + (NR_NB_SC_PER_RB * pusch_pdu->rb_size)), + 1, + 1); + LOG_M("rxsigF0_llr.m", + "rxsF0_llr", + &gNB->pusch_vars[0].llr[0], + (pusch_pdu->nr_of_symbols - 1) * NR_NB_SC_PER_RB * pusch_pdu->rb_size * pusch_pdu->qam_mod_order, + 1, + 0); if (gNB->frame_parms.nb_antennas_rx > 1) { LOG_M("rxsigF1.m","rxsF1",&gNB->common_vars.rxdataF[1][(slot_rx&3)*gNB->frame_parms.ofdm_symbol_size*gNB->frame_parms.symbols_per_slot],gNB->frame_parms.ofdm_symbol_size*gNB->frame_parms.symbols_per_slot,1,1); - LOG_M("rxsigF1_ext.m","rxsF1_ext", - &gNB->pusch_vars[0]->rxdataF_ext[1][pusch_pdu->start_symbol_index*NR_NB_SC_PER_RB * pusch_pdu->rb_size],pusch_pdu->nr_of_symbols*(off+(NR_NB_SC_PER_RB * pusch_pdu->rb_size)),1,1); - LOG_M("chestF1.m","chF1", - &gNB->pusch_vars[0]->ul_ch_estimates[1][pusch_pdu->start_symbol_index*gNB->frame_parms.ofdm_symbol_size],gNB->frame_parms.ofdm_symbol_size,1,1); - LOG_M("chestF1_ext.m","chF1_ext", - &gNB->pusch_vars[0]->ul_ch_estimates_ext[1][(pusch_pdu->start_symbol_index+1)*(off+(NR_NB_SC_PER_RB * pusch_pdu->rb_size))], - (pusch_pdu->nr_of_symbols-1)*(off+(NR_NB_SC_PER_RB * pusch_pdu->rb_size)),1,1); - LOG_M("rxsigF1_comp.m","rxsF1_comp", - &gNB->pusch_vars[0]->rxdataF_comp[1][pusch_pdu->start_symbol_index*(off+(NR_NB_SC_PER_RB * pusch_pdu->rb_size))],pusch_pdu->nr_of_symbols*(off+(NR_NB_SC_PER_RB * pusch_pdu->rb_size)),1,1); + LOG_M("rxsigF1_ext.m", + "rxsF1_ext", + &gNB->pusch_vars[0].rxdataF_ext[1][pusch_pdu->start_symbol_index * NR_NB_SC_PER_RB * pusch_pdu->rb_size], + pusch_pdu->nr_of_symbols * (off + (NR_NB_SC_PER_RB * pusch_pdu->rb_size)), + 1, + 1); + LOG_M("chestF1.m", + "chF1", + &gNB->pusch_vars[0].ul_ch_estimates[1][pusch_pdu->start_symbol_index * gNB->frame_parms.ofdm_symbol_size], + gNB->frame_parms.ofdm_symbol_size, + 1, + 1); + LOG_M("chestF1_ext.m", + "chF1_ext", + &gNB->pusch_vars[0] + .ul_ch_estimates_ext[1][(pusch_pdu->start_symbol_index + 1) * (off + (NR_NB_SC_PER_RB * pusch_pdu->rb_size))], + (pusch_pdu->nr_of_symbols - 1) * (off + (NR_NB_SC_PER_RB * pusch_pdu->rb_size)), + 1, + 1); + LOG_M("rxsigF1_comp.m", + "rxsF1_comp", + &gNB->pusch_vars[0].rxdataF_comp[1][pusch_pdu->start_symbol_index * (off + (NR_NB_SC_PER_RB * pusch_pdu->rb_size))], + pusch_pdu->nr_of_symbols * (off + (NR_NB_SC_PER_RB * pusch_pdu->rb_size)), + 1, + 1); } exit(-1); @@ -484,7 +535,8 @@ void nr_fill_indication(PHY_VARS_gNB *gNB, int frame, int slot_rx, int ULSCH_id, gNB->crc_pdu_list[num_crc].ul_cqi = cqi; gNB->crc_pdu_list[num_crc].timing_advance = timing_advance_update; // in terms of dBFS range -128 to 0 with 0.1 step - gNB->crc_pdu_list[num_crc].rssi = (dtx_flag==0) ? 1280 - (10*dB_fixed(32767*32767)-dB_fixed_times10(gNB->pusch_vars[ULSCH_id]->ulsch_power[0])) : 0; + gNB->crc_pdu_list[num_crc].rssi = + (dtx_flag == 0) ? 1280 - (10 * dB_fixed(32767 * 32767) - dB_fixed_times10(gNB->pusch_vars[ULSCH_id].ulsch_power[0])) : 0; gNB->UL_INFO.crc_ind.number_crcs++; @@ -532,7 +584,7 @@ void fill_ul_rb_mask(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx) { } for (int i = 0; i < gNB->max_nb_pucch; i++){ - NR_gNB_PUCCH_t *pucch = gNB->pucch[i]; + NR_gNB_PUCCH_t *pucch = &gNB->pucch[i]; if (pucch) { if ((pucch->active == 1) && (pucch->frame == frame_rx) && @@ -554,30 +606,25 @@ void fill_ul_rb_mask(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx) { } } - for (int ULSCH_id = 0; ULSCH_id < NUMBER_OF_NR_ULSCH_MAX; ULSCH_id++) { - NR_gNB_ULSCH_t *ulsch = gNB->ulsch[ULSCH_id]; + for (int ULSCH_id = 0; ULSCH_id < gNB->max_nb_pusch; ULSCH_id++) { + NR_gNB_ULSCH_t *ulsch = &gNB->ulsch[ULSCH_id]; int harq_pid; - NR_UL_gNB_HARQ_t *ulsch_harq; - if ((ulsch) && - (ulsch->rnti > 0)) { - for (harq_pid=0;harq_pidharq_processes[harq_pid]; - AssertFatal(ulsch_harq!=NULL,"harq_pid %d is not allocated\n",harq_pid); - if ((ulsch_harq->status == NR_ACTIVE) && - (ulsch_harq->frame == frame_rx) && - (ulsch_harq->slot == slot_rx) && - (ulsch_harq->handled == 0)){ - uint8_t symbol_start = ulsch_harq->ulsch_pdu.start_symbol_index; - uint8_t symbol_end = symbol_start + ulsch_harq->ulsch_pdu.nr_of_symbols; - for (int symbol=symbol_start ; symbolframe_parms.frame_type == FDD || - (gNB->frame_parms.frame_type == TDD && gNB->gNB_config.tdd_table.max_tdd_periodicity_list[slot_rx].max_num_of_symbol_per_slot_list[symbol].slot_config.value==1)) { - LOG_D(PHY,"symbol %d Filling rb_mask_ul rb_size %d\n",symbol,ulsch_harq->ulsch_pdu.rb_size); - for (rb=0; rbulsch_pdu.rb_size; rb++) { - rb2 = rb+ulsch_harq->ulsch_pdu.rb_start+ulsch_harq->ulsch_pdu.bwp_start; - gNB->rb_mask_ul[symbol][rb2 >> 5] |= 1U << (rb2 & 31); - } - } + NR_UL_gNB_HARQ_t *ulsch_harq = ulsch->harq_process; + AssertFatal(ulsch_harq != NULL, "harq_pid %d is not allocated\n", harq_pid); + if ((ulsch->active == true) && (ulsch->frame == frame_rx) && (ulsch->slot == slot_rx) && (ulsch->handled == 0)) { + uint8_t symbol_start = ulsch_harq->ulsch_pdu.start_symbol_index; + uint8_t symbol_end = symbol_start + ulsch_harq->ulsch_pdu.nr_of_symbols; + for (int symbol = symbol_start; symbol < symbol_end; symbol++) { + if (gNB->frame_parms.frame_type == FDD + || (gNB->frame_parms.frame_type == TDD + && gNB->gNB_config.tdd_table.max_tdd_periodicity_list[slot_rx] + .max_num_of_symbol_per_slot_list[symbol] + .slot_config.value + == 1)) { + LOG_D(PHY, "symbol %d Filling rb_mask_ul rb_size %d\n", symbol, ulsch_harq->ulsch_pdu.rb_size); + for (rb = 0; rb < ulsch_harq->ulsch_pdu.rb_size; rb++) { + rb2 = rb + ulsch_harq->ulsch_pdu.rb_start + ulsch_harq->ulsch_pdu.bwp_start; + gNB->rb_mask_ul[symbol][rb2 >> 5] |= 1U << (rb2 & 31); } } } @@ -585,7 +632,7 @@ void fill_ul_rb_mask(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx) { } for (int i = 0; i < gNB->max_nb_srs; i++) { - NR_gNB_SRS_t *srs = gNB->srs[i]; + NR_gNB_SRS_t *srs = &gNB->srs[i]; if (srs) { if ((srs->active == 1) && (srs->frame == frame_rx) && (srs->slot == slot_rx)) { nfapi_nr_srs_pdu_t *srs_pdu = &srs->srs_pdu; @@ -686,7 +733,8 @@ int check_srs_pdu(const nfapi_nr_srs_pdu_t *srs_pdu, nfapi_nr_srs_pdu_t *saved_s return 0; } -int phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx) { +int phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx) +{ /* those variables to log T_GNB_PHY_PUCCH_PUSCH_IQ only when we try to decode */ int pucch_decode_done = 0; int pusch_decode_done = 0; @@ -705,18 +753,19 @@ int phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx) { num_symb++; } } - else num_symb=NR_NUMBER_OF_SYMBOLS_PER_SLOT; + else + num_symb = NR_NUMBER_OF_SYMBOLS_PER_SLOT; gNB_I0_measurements(gNB,slot_rx,first_symb,num_symb); - const int soffset = (slot_rx&3) * gNB->frame_parms.symbols_per_slot * gNB->frame_parms.ofdm_symbol_size; - int offset = 10*gNB->frame_parms.ofdm_symbol_size + gNB->frame_parms.first_carrier_offset; - int power_rxF = signal_energy_nodc((int32_t *)&gNB->common_vars.rxdataF[0][soffset+offset+(47*12)],12*18); + const int soffset = (slot_rx & 3) * gNB->frame_parms.symbols_per_slot * gNB->frame_parms.ofdm_symbol_size; + int offset = 10 * gNB->frame_parms.ofdm_symbol_size + gNB->frame_parms.first_carrier_offset; + int power_rxF = signal_energy_nodc((int32_t *)&gNB->common_vars.rxdataF[0][soffset + offset + (47 * 12)], 12 * 18); LOG_D(PHY,"frame %d, slot %d: UL signal energy %d\n",frame_rx,slot_rx,power_rxF); start_meas(&gNB->phy_proc_rx); - for (int i = 0; i < gNB->max_nb_pucch; i++){ - NR_gNB_PUCCH_t *pucch = gNB->pucch[i]; + for (int i = 0; i < gNB->max_nb_pucch; i++) { + NR_gNB_PUCCH_t *pucch = &gNB->pucch[i]; if (pucch) { if (NFAPI_MODE == NFAPI_MODE_PNF) pucch->frame = frame_rx; @@ -739,8 +788,8 @@ int phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx) { nfapi_nr_uci_pucch_pdu_format_0_1_t *uci_pdu_format0 = &gNB->uci_pdu_list[num_ucis].pucch_pdu_format_0_1; offset = pucch_pdu->start_symbol_index*gNB->frame_parms.ofdm_symbol_size + (gNB->frame_parms.first_carrier_offset+pucch_pdu->prb_start*12); - power_rxF = signal_energy_nodc((int32_t *)&gNB->common_vars.rxdataF[0][soffset+offset],12); - LOG_D(PHY,"frame %d, slot %d: PUCCH signal energy %d\n",frame_rx,slot_rx,power_rxF); + power_rxF = signal_energy_nodc((int32_t *)&gNB->common_vars.rxdataF[0][soffset+offset], 12); + LOG_D(PHY,"frame %d, slot %d: PUCCH signal energy %d\n", frame_rx, slot_rx, power_rxF); nr_decode_pucch0(gNB, frame_rx, @@ -750,7 +799,7 @@ int phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx) { gNB->UL_INFO.uci_ind.num_ucis += 1; pucch->active = 0; - break; + break; case 2: num_ucis = gNB->UL_INFO.uci_ind.num_ucis; gNB->UL_INFO.uci_ind.uci_list = &gNB->uci_pdu_list[0]; @@ -760,7 +809,7 @@ int phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx) { gNB->uci_pdu_list[num_ucis].pdu_size = sizeof(nfapi_nr_uci_pucch_pdu_format_2_3_4_t); nfapi_nr_uci_pucch_pdu_format_2_3_4_t *uci_pdu_format2 = &gNB->uci_pdu_list[num_ucis].pucch_pdu_format_2_3_4; - LOG_D(PHY,"%d.%d Calling nr_decode_pucch2\n",frame_rx,slot_rx); + LOG_D(PHY, "%d.%d Calling nr_decode_pucch2\n", frame_rx, slot_rx); nr_decode_pucch2(gNB, frame_rx, slot_rx, @@ -771,109 +820,115 @@ int phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx) { pucch->active = 0; break; default: - AssertFatal(1==0,"Only PUCCH formats 0 and 2 are currently supported\n"); + AssertFatal(1 == 0, "Only PUCCH formats 0 and 2 are currently supported\n"); } } } } - for (int ULSCH_id = 0; ULSCH_id < NUMBER_OF_NR_ULSCH_MAX; ULSCH_id++) { - NR_gNB_ULSCH_t *ulsch = gNB->ulsch[ULSCH_id]; - NR_UL_gNB_HARQ_t *ulsch_harq; + for (int ULSCH_id = 0; ULSCH_id < gNB->max_nb_pusch; ULSCH_id++) { + NR_gNB_ULSCH_t *ulsch = &gNB->ulsch[ULSCH_id]; + NR_UL_gNB_HARQ_t *ulsch_harq = ulsch->harq_process; + AssertFatal(ulsch_harq != NULL, "harq_pid %d is not allocated\n", ulsch->harq_pid); - if ((ulsch) && - (ulsch->rnti > 0)) { - // for for an active HARQ process - for (int harq_pid=0;harq_pidharq_processes[harq_pid]; - AssertFatal(ulsch_harq!=NULL,"harq_pid %d is not allocated\n",harq_pid); - if ((ulsch_harq->status == NR_ACTIVE) && - (ulsch_harq->frame == frame_rx) && - (ulsch_harq->slot == slot_rx) && - (ulsch_harq->handled == 0)){ - - LOG_D(PHY, "PUSCH detection started in frame %d slot %d\n", - frame_rx,slot_rx); - int num_dmrs=0; - for (int s=0;sulsch_pdu.ul_dmrs_symb_pos>>s)&1; + if ((ulsch->active == true) && (ulsch->frame == frame_rx) && (ulsch->slot == slot_rx) && (ulsch->handled == 0)) { + LOG_D(PHY, "PUSCH ID %d with RNTI %x detection started in frame %d slot %d\n", ULSCH_id, ulsch->rnti, frame_rx, slot_rx); + int num_dmrs = 0; + for (int s = 0; s < NR_NUMBER_OF_SYMBOLS_PER_SLOT; s++) + num_dmrs += (ulsch_harq->ulsch_pdu.ul_dmrs_symb_pos >> s) & 1; #ifdef DEBUG_RXDATA - NR_DL_FRAME_PARMS *frame_parms = &gNB->frame_parms; - RU_t *ru = gNB->RU_list[0]; - int slot_offset = frame_parms->get_samples_slot_timestamp(slot_rx,frame_parms,0); - slot_offset -= ru->N_TA_offset; - ((int16_t*)&gNB->common_vars.debugBuff[gNB->common_vars.debugBuff_sample_offset])[0]=(int16_t)ulsch->rnti; - ((int16_t*)&gNB->common_vars.debugBuff[gNB->common_vars.debugBuff_sample_offset])[1]=(int16_t)ulsch_harq->ulsch_pdu.rb_size; - ((int16_t*)&gNB->common_vars.debugBuff[gNB->common_vars.debugBuff_sample_offset])[2]=(int16_t)ulsch_harq->ulsch_pdu.rb_start; - ((int16_t*)&gNB->common_vars.debugBuff[gNB->common_vars.debugBuff_sample_offset])[3]=(int16_t)ulsch_harq->ulsch_pdu.nr_of_symbols; - ((int16_t*)&gNB->common_vars.debugBuff[gNB->common_vars.debugBuff_sample_offset])[4]=(int16_t)ulsch_harq->ulsch_pdu.start_symbol_index; - ((int16_t*)&gNB->common_vars.debugBuff[gNB->common_vars.debugBuff_sample_offset])[5]=(int16_t)ulsch_harq->ulsch_pdu.mcs_index; - ((int16_t*)&gNB->common_vars.debugBuff[gNB->common_vars.debugBuff_sample_offset])[6]=(int16_t)ulsch_harq->ulsch_pdu.pusch_data.rv_index; - ((int16_t*)&gNB->common_vars.debugBuff[gNB->common_vars.debugBuff_sample_offset])[7]=(int16_t)harq_pid; - memcpy(&gNB->common_vars.debugBuff[gNB->common_vars.debugBuff_sample_offset+4],&ru->common.rxdata[0][slot_offset],frame_parms->get_samples_per_slot(slot_rx,frame_parms)*sizeof(int32_t)); - gNB->common_vars.debugBuff_sample_offset+=(frame_parms->get_samples_per_slot(slot_rx,frame_parms)+1000+4); - if(gNB->common_vars.debugBuff_sample_offset>((frame_parms->get_samples_per_slot(slot_rx,frame_parms)+1000+2)*20)) { - FILE *f; - f = fopen("rxdata_buff.raw", "w"); if (f == NULL) exit(1); - fwrite((int16_t*)gNB->common_vars.debugBuff,2,(frame_parms->get_samples_per_slot(slot_rx,frame_parms)+1000+4)*20*2, f); - fclose(f); - exit(-1); - } + NR_DL_FRAME_PARMS *frame_parms = &gNB->frame_parms; + RU_t *ru = gNB->RU_list[0]; + int slot_offset = frame_parms->get_samples_slot_timestamp(slot_rx, frame_parms, 0); + slot_offset -= ru->N_TA_offset; + int32_t sample_offset = gNB->common_vars.debugBuff_sample_offset; + nfapi_nr_pusch_pdu_t *pdu = &ulsch_harq->ulsch_pdu; + int16_t *buf = (int16_t *)&gNB->common_vars.debugBuff[offset]; + buf[0] = (int16_t)ulsch->rnti; + buf[1] = (int16_t)pdu->rb_size; + buf[2] = (int16_t)pdu->rb_start; + buf[3] = (int16_t)pdu->nr_of_symbols; + buf[4] = (int16_t)pdu->start_symbol_index; + buf[5] = (int16_t)pdu->mcs_index; + buf[6] = (int16_t)pdu->pusch_data.rv_index; + buf[7] = (int16_t)ulsch->harq_pid; + memcpy(&gNB->common_vars.debugBuff[gNB->common_vars.debugBuff_sample_offset + 4], + &ru->common.rxdata[0][slot_offset], + frame_parms->get_samples_per_slot(slot_rx, frame_parms) * sizeof(int32_t)); + gNB->common_vars.debugBuff_sample_offset += (frame_parms->get_samples_per_slot(slot_rx, frame_parms) + 1000 + 4); + if (gNB->common_vars.debugBuff_sample_offset > ((frame_parms->get_samples_per_slot(slot_rx, frame_parms) + 1000 + 2) * 20)) { + FILE *f; + f = fopen("rxdata_buff.raw", "w"); + if (f == NULL) + exit(1); + fwrite((int16_t *)gNB->common_vars.debugBuff, + 2, + (frame_parms->get_samples_per_slot(slot_rx, frame_parms) + 1000 + 4) * 20 * 2, + f); + fclose(f); + exit(-1); + } #endif - pusch_decode_done = 1; + pusch_decode_done = 1; - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_NR_RX_PUSCH,1); - start_meas(&gNB->rx_pusch_stats); - nr_rx_pusch(gNB, ULSCH_id, frame_rx, slot_rx, harq_pid); - gNB->pusch_vars[ULSCH_id]->ulsch_power_tot=0; - gNB->pusch_vars[ULSCH_id]->ulsch_noise_power_tot=0; - for (int aarx=0;aarxframe_parms.nb_antennas_rx;aarx++) { - gNB->pusch_vars[ULSCH_id]->ulsch_power[aarx]/=num_dmrs; - gNB->pusch_vars[ULSCH_id]->ulsch_power_tot += gNB->pusch_vars[ULSCH_id]->ulsch_power[aarx]; - gNB->pusch_vars[ULSCH_id]->ulsch_noise_power[aarx]/=num_dmrs; - gNB->pusch_vars[ULSCH_id]->ulsch_noise_power_tot += gNB->pusch_vars[ULSCH_id]->ulsch_noise_power[aarx]; - } - if (dB_fixed_x10(gNB->pusch_vars[ULSCH_id]->ulsch_power_tot) < - dB_fixed_x10(gNB->pusch_vars[ULSCH_id]->ulsch_noise_power_tot) + gNB->pusch_thres) { - NR_gNB_SCH_STATS_t *stats=get_ulsch_stats(gNB,ulsch); - - LOG_D(PHY, "PUSCH not detected in %d.%d (%d,%d,%d)\n",frame_rx,slot_rx, - dB_fixed_x10(gNB->pusch_vars[ULSCH_id]->ulsch_power_tot), - dB_fixed_x10(gNB->pusch_vars[ULSCH_id]->ulsch_noise_power_tot),gNB->pusch_thres); - gNB->pusch_vars[ULSCH_id]->ulsch_power_tot = gNB->pusch_vars[ULSCH_id]->ulsch_noise_power_tot; - gNB->pusch_vars[ULSCH_id]->DTX=1; - if (stats) stats->DTX++; - if (!get_softmodem_params()->phy_test) { - /* in case of phy_test mode, we still want to decode to measure execution time. - Therefore, we don't yet call nr_fill_indication, it will be called later */ - nr_fill_indication(gNB,frame_rx, slot_rx, ULSCH_id, harq_pid, 1,1); - pusch_DTX++; - continue; - } - } else { - LOG_D(PHY, "PUSCH detected in %d.%d (%d,%d,%d)\n",frame_rx,slot_rx, - dB_fixed_x10(gNB->pusch_vars[ULSCH_id]->ulsch_power_tot), - dB_fixed_x10(gNB->pusch_vars[ULSCH_id]->ulsch_noise_power_tot),gNB->pusch_thres); - - gNB->pusch_vars[ULSCH_id]->DTX=0; - } - stop_meas(&gNB->rx_pusch_stats); - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_NR_RX_PUSCH,0); - //LOG_M("rxdataF_comp.m","rxF_comp",gNB->pusch_vars[0]->rxdataF_comp[0],6900,1,1); - //LOG_M("rxdataF_ext.m","rxF_ext",gNB->pusch_vars[0]->rxdataF_ext[0],6900,1,1); - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_NR_ULSCH_PROCEDURES_RX,1); - nr_ulsch_procedures(gNB, frame_rx, slot_rx, ULSCH_id, harq_pid); - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_NR_ULSCH_PROCEDURES_RX,0); - break; - } + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_NR_RX_PUSCH, 1); + start_meas(&gNB->rx_pusch_stats); + nr_rx_pusch(gNB, ULSCH_id, frame_rx, slot_rx, ulsch->harq_pid); + NR_gNB_PUSCH *pusch_vars = &gNB->pusch_vars[ULSCH_id]; + pusch_vars->ulsch_power_tot = 0; + pusch_vars->ulsch_noise_power_tot = 0; + for (int aarx = 0; aarx < gNB->frame_parms.nb_antennas_rx; aarx++) { + pusch_vars->ulsch_power[aarx] /= num_dmrs; + pusch_vars->ulsch_power_tot += pusch_vars->ulsch_power[aarx]; + pusch_vars->ulsch_noise_power[aarx] /= num_dmrs; + pusch_vars->ulsch_noise_power_tot += pusch_vars->ulsch_noise_power[aarx]; } + if (dB_fixed_x10(pusch_vars->ulsch_power_tot) < dB_fixed_x10(pusch_vars->ulsch_noise_power_tot) + gNB->pusch_thres) { + NR_gNB_PHY_STATS_t *stats = get_phy_stats(gNB, ulsch->rnti); + + LOG_D(PHY, + "PUSCH not detected in %d.%d (%d,%d,%d)\n", + frame_rx, + slot_rx, + dB_fixed_x10(pusch_vars->ulsch_power_tot), + dB_fixed_x10(pusch_vars->ulsch_noise_power_tot), + gNB->pusch_thres); + pusch_vars->ulsch_power_tot = pusch_vars->ulsch_noise_power_tot; + pusch_vars->DTX = 1; + if (stats) + stats->ulsch_stats.DTX++; + if (!get_softmodem_params()->phy_test) { + /* in case of phy_test mode, we still want to decode to measure execution time. + Therefore, we don't yet call nr_fill_indication, it will be called later */ + nr_fill_indication(gNB, frame_rx, slot_rx, ULSCH_id, ulsch->harq_pid, 1, 1); + pusch_DTX++; + continue; + } + } else { + LOG_D(PHY, + "PUSCH detected in %d.%d (%d,%d,%d)\n", + frame_rx, + slot_rx, + dB_fixed_x10(pusch_vars->ulsch_power_tot), + dB_fixed_x10(pusch_vars->ulsch_noise_power_tot), + gNB->pusch_thres); + + pusch_vars->DTX = 0; + } + stop_meas(&gNB->rx_pusch_stats); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_NR_RX_PUSCH, 0); + // LOG_M("rxdataF_comp.m","rxF_comp",gNB->pusch_vars[0]->rxdataF_comp[0],6900,1,1); + // LOG_M("rxdataF_ext.m","rxF_ext",gNB->pusch_vars[0]->rxdataF_ext[0],6900,1,1); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_NR_ULSCH_PROCEDURES_RX, 1); + nr_ulsch_procedures(gNB, frame_rx, slot_rx, ULSCH_id, ulsch->harq_pid); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_NR_ULSCH_PROCEDURES_RX, 0); } } for (int i = 0; i < gNB->max_nb_srs; i++) { - NR_gNB_SRS_t *srs = gNB->srs[i]; + NR_gNB_SRS_t *srs = &gNB->srs[i]; if (srs) { if ((srs->active == 1) && (srs->frame == frame_rx) && (srs->slot == slot_rx)) { LOG_D(NR_PHY, "(%d.%d) gNB is waiting for SRS, id = %i\n", frame_rx, slot_rx, i); diff --git a/openair1/SCHED_NR_UE/defs.h b/openair1/SCHED_NR_UE/defs.h index 1439c9fd01..f075a4a621 100644 --- a/openair1/SCHED_NR_UE/defs.h +++ b/openair1/SCHED_NR_UE/defs.h @@ -83,7 +83,7 @@ typedef struct { - uint8_t decoded_output[64]; + uint8_t decoded_output[3]; // PBCH paylod not larger than 3B uint8_t xtra_byte; } fapiPbch_t; @@ -98,17 +98,16 @@ typedef struct { */ void phy_procedures_nrUE_TX(PHY_VARS_NR_UE *ue, UE_nr_rxtx_proc_t *proc, nr_phy_data_tx_t *phy_data); -/*! \brief Scheduling for UE RX procedures in normal subframes. - @param ue Pointer to UE variables on which to act - @param proc Pointer to proc information - @param dlsch_parallel use multithreaded dlsch processing - @param phy_pdcch_config PDCCH Config for this slot - @param txFifo Result fifo if PDSCH is run in parallel -*/ -int phy_procedures_nrUE_RX(PHY_VARS_NR_UE *ue, +void send_slot_ind(notifiedFIFO_t *nf, int slot); + +void pbch_pdcch_processing(PHY_VARS_NR_UE *ue, UE_nr_rxtx_proc_t *proc, nr_phy_data_t *phy_data); +void pdsch_processing(PHY_VARS_NR_UE *ue, + UE_nr_rxtx_proc_t *proc, + nr_phy_data_t *phy_data); + int phy_procedures_slot_parallelization_nrUE_RX(PHY_VARS_NR_UE *ue, UE_nr_rxtx_proc_t *proc, uint8_t abstraction_flag, uint8_t do_pdcch_flag, relaying_type_t r_type); void processSlotTX(void *arg); @@ -166,7 +165,8 @@ void nr_fill_rx_indication(fapi_nr_rx_indication_t *rx_ind, NR_UE_DLSCH_t *dlsch1, uint16_t n_pdus, UE_nr_rxtx_proc_t *proc, - void *typeSpecific); + void *typeSpecific, + uint8_t *b); bool nr_ue_dlsch_procedures(PHY_VARS_NR_UE *ue, UE_nr_rxtx_proc_t *proc, diff --git a/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c b/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c index b64be34f6e..64ec900b2a 100644 --- a/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c +++ b/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c @@ -544,7 +544,17 @@ int8_t nr_ue_scheduled_response(nr_scheduled_response_t *scheduled_response){ int8_t nr_ue_phy_config_request(nr_phy_config_t *phy_config) { fapi_nr_config_request_t *nrUE_config = &PHY_vars_UE_g[phy_config->Mod_id][phy_config->CC_id]->nrUE_config; - if(phy_config != NULL) + if(phy_config != NULL) { memcpy(nrUE_config,&phy_config->config_req,sizeof(fapi_nr_config_request_t)); + pushNotifiedFIFO(&PHY_vars_UE_g[phy_config->Mod_id][phy_config->CC_id]->phy_config_ind, newNotifiedFIFO_elt(1,0,NULL,NULL)); + } return 0; } + +void nr_ue_synch_request(nr_synch_request_t *synch_request) +{ + fapi_nr_synch_request_t *synch_req = &PHY_vars_UE_g[synch_request->Mod_id][synch_request->CC_id]->synch_request.synch_req; + memcpy(synch_req, &synch_request->synch_req, sizeof(fapi_nr_synch_request_t)); + PHY_vars_UE_g[synch_request->Mod_id][synch_request->CC_id]->synch_request.received_synch_request = 1; +} + diff --git a/openair1/SCHED_NR_UE/fapi_nr_ue_l1.h b/openair1/SCHED_NR_UE/fapi_nr_ue_l1.h index a0b0b805af..d83c014fa6 100644 --- a/openair1/SCHED_NR_UE/fapi_nr_ue_l1.h +++ b/openair1/SCHED_NR_UE/fapi_nr_ue_l1.h @@ -47,6 +47,10 @@ int8_t nr_ue_scheduled_response_stub(nr_scheduled_response_t *scheduled_response \param scheduled_response including transmission config(dl_config, ul_config) and data transmission (tx_req)*/ int8_t nr_ue_phy_config_request(nr_phy_config_t *phy_config); +/**\brief NR UE FAPI message to schedule a synchronization with target gNB + \param synch_request including target_Nid_cell*/ +void nr_ue_synch_request(nr_synch_request_t *synch_request); + void update_harq_status(module_id_t module_id, uint8_t harq_pid, uint8_t ack_nack); #endif diff --git a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c index f88b81ad52..664cddcfdf 100644 --- a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c +++ b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c @@ -118,10 +118,9 @@ void nr_fill_rx_indication(fapi_nr_rx_indication_t *rx_ind, NR_UE_DLSCH_t *dlsch1, uint16_t n_pdus, UE_nr_rxtx_proc_t *proc, - void *typeSpecific){ - - NR_DL_FRAME_PARMS *frame_parms = &ue->frame_parms; - + void *typeSpecific, + uint8_t *b) +{ if (n_pdus > 1){ LOG_E(PHY, "In %s: multiple number of DL PDUs not supported yet...\n", __FUNCTION__); } @@ -131,7 +130,7 @@ void nr_fill_rx_indication(fapi_nr_rx_indication_t *rx_ind, if ((pdu_type != FAPI_NR_RX_PDU_TYPE_SSB) && dlsch0) { dl_harq0 = &ue->dl_harq_processes[0][dlsch0->dlsch_config.harq_process_nbr]; trace_NRpdu(DIRECTION_DOWNLINK, - dl_harq0->b, + b, dlsch0->dlsch_config.TBS / 8, WS_C_RNTI, dlsch0->rnti, @@ -147,24 +146,30 @@ void nr_fill_rx_indication(fapi_nr_rx_indication_t *rx_ind, dl_harq0 = &ue->dl_harq_processes[0][dlsch0->dlsch_config.harq_process_nbr]; rx_ind->rx_indication_body[n_pdus - 1].pdsch_pdu.harq_pid = dlsch0->dlsch_config.harq_process_nbr; rx_ind->rx_indication_body[n_pdus - 1].pdsch_pdu.ack_nack = dl_harq0->ack; - rx_ind->rx_indication_body[n_pdus - 1].pdsch_pdu.pdu = dl_harq0->b; + rx_ind->rx_indication_body[n_pdus - 1].pdsch_pdu.pdu = b; rx_ind->rx_indication_body[n_pdus - 1].pdsch_pdu.pdu_length = dlsch0->dlsch_config.TBS / 8; } if(dlsch1) { AssertFatal(1==0,"Second codeword currently not supported\n"); } break; - case FAPI_NR_RX_PDU_TYPE_SSB: - rx_ind->rx_indication_body[n_pdus - 1].ssb_pdu.pdu=malloc(sizeof(((fapiPbch_t*)typeSpecific)->decoded_output)); - memcpy(rx_ind->rx_indication_body[n_pdus - 1].ssb_pdu.pdu, - ((fapiPbch_t*)typeSpecific)->decoded_output, - sizeof(((fapiPbch_t*)typeSpecific)->decoded_output)); - rx_ind->rx_indication_body[n_pdus - 1].ssb_pdu.additional_bits = ((fapiPbch_t*)typeSpecific)->xtra_byte; - rx_ind->rx_indication_body[n_pdus - 1].ssb_pdu.ssb_index = (frame_parms->ssb_index)&0x7; - rx_ind->rx_indication_body[n_pdus - 1].ssb_pdu.ssb_length = frame_parms->Lmax; - rx_ind->rx_indication_body[n_pdus - 1].ssb_pdu.cell_id = frame_parms->Nid_cell; - rx_ind->rx_indication_body[n_pdus - 1].ssb_pdu.ssb_start_subcarrier = frame_parms->ssb_start_subcarrier; - rx_ind->rx_indication_body[n_pdus - 1].ssb_pdu.rsrp_dBm = ue->measurements.ssb_rsrp_dBm[frame_parms->ssb_index]; + case FAPI_NR_RX_PDU_TYPE_SSB: { + fapi_nr_ssb_pdu_t *ssb_pdu = &rx_ind->rx_indication_body[n_pdus - 1].ssb_pdu; + if(typeSpecific) { + NR_DL_FRAME_PARMS *frame_parms = &ue->frame_parms; + fapiPbch_t *pbch = (fapiPbch_t *)typeSpecific; + memcpy(ssb_pdu->pdu, pbch->decoded_output, sizeof(pbch->decoded_output)); + ssb_pdu->additional_bits = pbch->xtra_byte; + ssb_pdu->ssb_index = (frame_parms->ssb_index)&0x7; + ssb_pdu->ssb_length = frame_parms->Lmax; + ssb_pdu->cell_id = frame_parms->Nid_cell; + ssb_pdu->ssb_start_subcarrier = frame_parms->ssb_start_subcarrier; + ssb_pdu->rsrp_dBm = ue->measurements.ssb_rsrp_dBm[frame_parms->ssb_index]; + ssb_pdu->decoded_pdu = true; + } + else + ssb_pdu->decoded_pdu = false; + } break; case FAPI_NR_CSIRS_IND: memcpy(&rx_ind->rx_indication_body[n_pdus - 1].csirs_measurements, @@ -382,7 +387,6 @@ static void nr_ue_pbch_procedures(PHY_VARS_NR_UE *ue, proc, estimateSz, dl_ch_estimates, - ue->pbch_vars[gNB_id], &ue->frame_parms, (ue->frame_parms.ssb_index)&7, SISO, @@ -392,8 +396,6 @@ static void nr_ue_pbch_procedures(PHY_VARS_NR_UE *ue, if (ret==0) { - ue->pbch_vars[gNB_id]->pdu_errors_conseq = 0; - #ifdef DEBUG_PHY_PROC uint16_t frame_tx; LOG_D(PHY,"[UE %d] frame %d, nr_slot_rx %d, Received PBCH (MIB): frame_tx %d. N_RB_DL %d\n", @@ -426,36 +428,12 @@ static void nr_ue_pbch_procedures(PHY_VARS_NR_UE *ue, write_output("H10.m","h10",&(ue->common_vars.dl_ch_estimates[0][2][0]),((ue->frame_parms.Ncp==0)?7:6)*(ue->frame_parms.ofdm_symbol_size),1,1); write_output("rxsigF0.m","rxsF0", ue->common_vars.rxdataF[0],8*ue->frame_parms.ofdm_symbol_size,1,1); - write_output("PBCH_rxF0_ext.m","pbch0_ext",ue->pbch_vars[0]->rxdataF_ext[0],12*4*6,1,1); - write_output("PBCH_rxF0_comp.m","pbch0_comp",ue->pbch_vars[0]->rxdataF_comp[0],12*4*6,1,1); - write_output("PBCH_rxF_llr.m","pbch_llr",ue->pbch_vars[0]->llr,(ue->frame_parms.Ncp==0) ? 1920 : 1728,1,4); exit(-1); */ - ue->pbch_vars[gNB_id]->pdu_errors_conseq++; - ue->pbch_vars[gNB_id]->pdu_errors++; - - if (ue->pbch_vars[gNB_id]->pdu_errors_conseq>=100) { - if (get_softmodem_params()->non_stop) { - LOG_E(PHY,"More that 100 consecutive PBCH errors! Going back to Sync mode!\n"); - ue->lost_sync = 1; - } else { - LOG_E(PHY,"More that 100 consecutive PBCH errors! Exiting!\n"); - exit_fun("More that 100 consecutive PBCH errors! Exiting!\n"); - } - } } - if (frame_rx % 100 == 0) { - ue->pbch_vars[gNB_id]->pdu_errors_last = ue->pbch_vars[gNB_id]->pdu_errors; - } -#ifdef DEBUG_PHY_PROC - LOG_D(PHY,"[UE %d] frame %d, slot %d, PBCH errors = %d, consecutive errors = %d!\n", - ue->Mod_id,frame_rx, nr_slot_rx, - ue->pbch_vars[gNB_id]->pdu_errors, - ue->pbch_vars[gNB_id]->pdu_errors_conseq); -#endif VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_PBCH_PROCEDURES, VCD_FUNCTION_OUT); } @@ -696,6 +674,15 @@ int nr_ue_pdsch_procedures(PHY_VARS_NR_UE *ue, return 0; } +void send_slot_ind(notifiedFIFO_t *nf, int slot) { + if (nf) { + notifiedFIFO_elt_t *newElt = newNotifiedFIFO_elt(sizeof(int), 0, NULL, NULL); + int *msgData = (int *) NotifiedFifoData(newElt); + *msgData = slot; + pushNotifiedFIFO(nf, newElt); + } +} + bool nr_ue_dlsch_procedures(PHY_VARS_NR_UE *ue, UE_nr_rxtx_proc_t *proc, NR_UE_DLSCH_t dlsch[2], @@ -716,7 +703,7 @@ bool nr_ue_dlsch_procedures(PHY_VARS_NR_UE *ue, NR_DL_UE_HARQ_t *dl_harq1 = &ue->dl_harq_processes[1][harq_pid]; uint16_t dmrs_len = get_num_dmrs(dlsch[0].dlsch_config.dlDmrsSymbPos); nr_downlink_indication_t dl_indication; - fapi_nr_rx_indication_t *rx_ind = calloc(1, sizeof(*rx_ind)); + fapi_nr_rx_indication_t rx_ind = {0}; uint16_t number_pdus = 1; // params for UL time alignment procedure NR_UL_TIME_ALIGNMENT_t *ul_time_alignment = &ue->ul_time_alignment[gNB_id]; @@ -739,8 +726,12 @@ bool nr_ue_dlsch_procedures(PHY_VARS_NR_UE *ue, LOG_D(PHY,"AbsSubframe %d.%d Start LDPC Decoder for CW1 [harq_pid %d] ? %d \n", frame_rx%1024, nr_slot_rx, harq_pid, is_cw1_active); // exit dlsch procedures as there are no active dlsch - if (is_cw0_active != ACTIVE && is_cw1_active != ACTIVE) + if (is_cw0_active != ACTIVE && is_cw1_active != ACTIVE) { + // don't wait anymore + const int ack_nack_slot = (proc->nr_slot_rx + dlsch[0].dlsch_config.k1_feedback) % ue->frame_parms.slots_per_frame; + send_slot_ind(ue->tx_resume_ind_fifo[ack_nack_slot], proc->nr_slot_rx); return false; + } // start ldpc decode for CW 0 dl_harq0->G = nr_get_G(dlsch[0].dlsch_config.number_rbs, @@ -762,6 +753,16 @@ bool nr_ue_dlsch_procedures(PHY_VARS_NR_UE *ue, start_meas(&ue->dlsch_decoding_stats); + // create memory to store decoder output + int a_segments = MAX_NUM_NR_DLSCH_SEGMENTS_PER_LAYER*NR_MAX_NB_LAYERS; //number of segments to be allocated + int num_rb = dlsch[0].dlsch_config.number_rbs; + if (num_rb != 273) { + a_segments = a_segments*num_rb; + a_segments = (a_segments/273)+1; + } + uint32_t dlsch_bytes = a_segments*1056; // allocated bytes per segment + __attribute__ ((aligned(32))) uint8_t p_b[dlsch_bytes]; + ret = nr_dlsch_decoding(ue, proc, gNB_id, @@ -772,7 +773,9 @@ bool nr_ue_dlsch_procedures(PHY_VARS_NR_UE *ue, frame_rx, nb_symb_sch, nr_slot_rx, - harq_pid); + harq_pid, + dlsch_bytes, + p_b); LOG_T(PHY,"dlsch decoding, ret = %d\n", ret); @@ -799,8 +802,8 @@ bool nr_ue_dlsch_procedures(PHY_VARS_NR_UE *ue, break; } - nr_fill_dl_indication(&dl_indication, NULL, rx_ind, proc, ue, NULL); - nr_fill_rx_indication(rx_ind, ind_type, ue, &dlsch[0], NULL, number_pdus, proc, NULL); + nr_fill_dl_indication(&dl_indication, NULL, &rx_ind, proc, ue, NULL); + nr_fill_rx_indication(&rx_ind, ind_type, ue, &dlsch[0], NULL, number_pdus, proc, NULL, p_b); LOG_D(PHY, "In %s DL PDU length in bits: %d, in bytes: %d \n", __FUNCTION__, dlsch[0].dlsch_config.TBS, dlsch[0].dlsch_config.TBS / 8); @@ -840,7 +843,9 @@ bool nr_ue_dlsch_procedures(PHY_VARS_NR_UE *ue, frame_rx, nb_symb_sch, nr_slot_rx, - harq_pid); + harq_pid, + dlsch_bytes, + p_b); LOG_T(PHY,"CW dlsch decoding, ret1 = %d\n", ret1); stop_meas(&ue->dlsch_decoding_stats); @@ -857,6 +862,13 @@ bool nr_ue_dlsch_procedures(PHY_VARS_NR_UE *ue, ue->if_inst->dl_indication(&dl_indication, ul_time_alignment); } + // DLSCH decoding finished! don't wait anymore + const int ack_nack_slot = (proc->nr_slot_rx + dlsch[0].dlsch_config.k1_feedback) % ue->frame_parms.slots_per_frame; + send_slot_ind(ue->tx_resume_ind_fifo[ack_nack_slot], proc->nr_slot_rx); + + if (ue->phy_sim_dlsch_b) + memcpy(ue->phy_sim_dlsch_b, p_b, dlsch_bytes); + if (ue->mac_enabled == 1) { // TODO: move this from PHY to MAC layer! /* Time Alignment procedure @@ -989,8 +1001,7 @@ bool nr_ue_dlsch_procedures(PHY_VARS_NR_UE *ue, return dec; } - -int phy_procedures_nrUE_RX(PHY_VARS_NR_UE *ue, +void pbch_pdcch_processing(PHY_VARS_NR_UE *ue, UE_nr_rxtx_proc_t *proc, nr_phy_data_t *phy_data) { @@ -1124,7 +1135,7 @@ int phy_procedures_nrUE_RX(PHY_VARS_NR_UE *ue, p += snprintf(p, end - p, "Harq round stats for Downlink: %d", ue->dl_stats[0]); for (int round = 1; round < 16 && (round < 3 || ue->dl_stats[round] != 0); ++round) p += snprintf(p, end - p,"/%d", ue->dl_stats[round]); - LOG_I(NR_PHY,"%s/0\n", output); + LOG_I(NR_PHY,"%s\n", output); LOG_I(NR_PHY,"============================================\n"); } @@ -1169,41 +1180,44 @@ int phy_procedures_nrUE_RX(PHY_VARS_NR_UE *ue, } dci_cnt = dci_cnt + nr_ue_pdcch_procedures(ue, proc, pdcch_est_size, pdcch_dl_ch_estimates, phy_data, n_ss, rxdataF); } + LOG_D(PHY,"[UE %d] Frame %d, nr_slot_rx %d: found %d DCIs\n", ue->Mod_id, frame_rx, nr_slot_rx, dci_cnt); phy_pdcch_config->nb_search_space = 0; VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SLOT_FEP_PDCCH, VCD_FUNCTION_OUT); +} + +void pdsch_processing(PHY_VARS_NR_UE *ue, + UE_nr_rxtx_proc_t *proc, + nr_phy_data_t *phy_data) { + + int frame_rx = proc->frame_rx; + int nr_slot_rx = proc->nr_slot_rx; + int gNB_id = proc->gNB_id; NR_UE_DLSCH_t *dlsch = &phy_data->dlsch[0]; - if (dci_cnt > 0) { - - LOG_D(PHY,"[UE %d] Frame %d, nr_slot_rx %d: found %d DCIs\n", ue->Mod_id, frame_rx, nr_slot_rx, dci_cnt); - - if (dlsch->active) { - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SLOT_FEP_PDSCH, VCD_FUNCTION_IN); - uint16_t nb_symb_sch = dlsch[0].dlsch_config.number_symbols; - uint16_t start_symb_sch = dlsch[0].dlsch_config.start_symbol; - - LOG_D(PHY," ------ --> PDSCH ChannelComp/LLR Frame.slot %d.%d ------ \n", frame_rx%1024, nr_slot_rx); - //to update from pdsch config - - for (uint16_t m=start_symb_sch;m<(nb_symb_sch+start_symb_sch) ; m++){ - nr_slot_fep(ue, - proc, - m, //to be updated from higher layer - rxdataF); - } - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SLOT_FEP_PDSCH, VCD_FUNCTION_OUT); - } - } else { - LOG_D(PHY,"[UE %d] Frame %d, nr_slot_rx %d: No DCIs found\n", ue->Mod_id, frame_rx, nr_slot_rx); - } - #endif //NR_PDCCH_SCHED - start_meas(&ue->generic_stat); // do procedures for C-RNTI int ret_pdsch = 0; + + const uint32_t rxdataF_sz = ue->frame_parms.samples_per_slot_wCP; + __attribute__ ((aligned(32))) c16_t rxdataF[ue->frame_parms.nb_antennas_rx][rxdataF_sz]; if (dlsch[0].active) { + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SLOT_FEP_PDSCH, VCD_FUNCTION_IN); + uint16_t nb_symb_sch = dlsch[0].dlsch_config.number_symbols; + uint16_t start_symb_sch = dlsch[0].dlsch_config.start_symbol; + + LOG_D(PHY," ------ --> PDSCH ChannelComp/LLR Frame.slot %d.%d ------ \n", frame_rx%1024, nr_slot_rx); + //to update from pdsch config + + for (uint16_t m=start_symb_sch;m<(nb_symb_sch+start_symb_sch) ; m++){ + nr_slot_fep(ue, + proc, + m, //to be updated from higher layer + rxdataF); + } + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SLOT_FEP_PDSCH, VCD_FUNCTION_OUT); + uint8_t nb_re_dmrs; if (dlsch[0].dlsch_config.dmrsConfigType == NFAPI_NR_DMRS_TYPE1) { nb_re_dmrs = 6*dlsch[0].dlsch_config.n_dmrs_cdm_groups; @@ -1243,6 +1257,9 @@ int phy_procedures_nrUE_RX(PHY_VARS_NR_UE *ue, if (ret_pdsch >= 0) nr_ue_dlsch_procedures(ue, proc, dlsch, llr); + else + // don't wait anymore + send_slot_ind(ue->tx_resume_ind_fifo[(proc->nr_slot_rx + dlsch[0].dlsch_config.k1_feedback) % ue->frame_parms.slots_per_frame], proc->nr_slot_rx); stop_meas(&ue->dlsch_procedures_stat); if (cpumeas(CPUMEAS_GETSTATE)) { @@ -1333,7 +1350,6 @@ int phy_procedures_nrUE_RX(PHY_VARS_NR_UE *ue, LOG_D(PHY," ****** end RX-Chain for AbsSubframe %d.%d ****** \n", frame_rx%1024, nr_slot_rx); UEscopeCopy(ue, commonRxdataF, rxdataF, sizeof(int32_t), ue->frame_parms.nb_antennas_rx, rxdataF_sz); - return (0); } diff --git a/openair1/SIMULATION/NR_PHY/dlschsim.c b/openair1/SIMULATION/NR_PHY/dlschsim.c index 42a5fc2dcc..c98bc4ee04 100644 --- a/openair1/SIMULATION/NR_PHY/dlschsim.c +++ b/openair1/SIMULATION/NR_PHY/dlschsim.c @@ -81,6 +81,17 @@ void init_downlink_harq_status(NR_DL_UE_HARQ_t *dl_harq) {} NR_IF_Module_t *NR_IF_Module_init(int Mod_id) { return (NULL); } nfapi_mode_t nfapi_getmode(void) { return NFAPI_MODE_UNKNOWN; } +void inc_ref_sched_response(int _) +{ + LOG_E(PHY, "fatal\n"); + exit(1); +} +void deref_sched_response(int _) +{ + LOG_E(PHY, "fatal\n"); + exit(1); +} + nrUE_params_t nrUE_params={0}; nrUE_params_t *get_nrUE_params(void) { @@ -422,15 +433,14 @@ int main(int argc, char **argv) unsigned char harq_pid = 0; //dlsch->harq_ids[subframe]; processingData_L1tx_t msgDataTx; init_DLSCH_struct(gNB, &msgDataTx); - NR_gNB_DLSCH_t *dlsch = msgDataTx.dlsch[0][0]; - nfapi_nr_dl_tti_pdsch_pdu_rel15_t *rel15 = &dlsch->harq_process.pdsch_pdu.pdsch_pdu_rel15; + NR_gNB_DLSCH_t *dlsch = &msgDataTx.dlsch[0][0]; + 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; unsigned int TBS = 8424; uint8_t nb_re_dmrs = 6; // No data in dmrs symbol uint16_t length_dmrs = 1; uint8_t Nl = 1; uint8_t rvidx = 0; - dlsch->rnti = 1; /*dlsch->harq_processes[0]->mcs = Imcs; dlsch->harq_processes[0]->rvidx = rvidx;*/ //printf("dlschsim harqid %d nb_rb %d, mscs %d\n",dlsch->harq_ids[subframe], @@ -543,9 +553,17 @@ int main(int argc, char **argv) vcd_signal_dumper_dump_function_by_name(VCD_SIGNAL_DUMPER_FUNCTIONS_DLSCH_DECODING0, VCD_FUNCTION_IN); + int a_segments = MAX_NUM_NR_DLSCH_SEGMENTS_PER_LAYER*NR_MAX_NB_LAYERS; //number of segments to be allocated + int num_rb = dlsch0_ue->dlsch_config.number_rbs; + if (num_rb != 273) { + a_segments = a_segments*num_rb; + a_segments = (a_segments/273)+1; + } + uint32_t dlsch_bytes = a_segments*1056; // allocated bytes per segment + __attribute__ ((aligned(32))) uint8_t b[dlsch_bytes]; ret = nr_dlsch_decoding(UE, &proc, 0, channel_output_fixed, &UE->frame_parms, dlsch0_ue, harq_process, frame, nb_symb_sch, - slot,harq_pid); + slot,harq_pid,dlsch_bytes,b); vcd_signal_dumper_dump_function_by_name(VCD_SIGNAL_DUMPER_FUNCTIONS_DLSCH_DECODING0, VCD_FUNCTION_OUT); @@ -556,7 +574,7 @@ int main(int argc, char **argv) errors_bit = 0; for (i = 0; i < TBS; i++) { - estimated_output_bit[i] = (harq_process->b[i / 8] & (1 << (i & 7))) >> (i & 7); + estimated_output_bit[i] = (b[i / 8] & (1 << (i & 7))) >> (i & 7); test_input_bit[i] = (test_input[i / 8] & (1 << (i & 7))) >> (i & 7); // Further correct for multiple segments if (estimated_output_bit[i] != test_input_bit[i]) { diff --git a/openair1/SIMULATION/NR_PHY/dlsim.c b/openair1/SIMULATION/NR_PHY/dlsim.c index 80ff799ab0..5f9beb9ddc 100644 --- a/openair1/SIMULATION/NR_PHY/dlsim.c +++ b/openair1/SIMULATION/NR_PHY/dlsim.c @@ -120,6 +120,10 @@ int8_t nr_mac_rrc_data_req_ue(const module_id_t Mod_idP, return 0; } +int8_t nr_rrc_RA_succeeded(const module_id_t mod_id, const 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) { @@ -324,7 +328,7 @@ int main(int argc, char **argv) //int frame_length_complex_samples_no_prefix; NR_DL_FRAME_PARMS *frame_parms; UE_nr_rxtx_proc_t UE_proc; - NR_Sched_Rsp_t Sched_INFO; + NR_Sched_Rsp_t *Sched_INFO; gNB_MAC_INST *gNB_mac; NR_UE_MAC_INST_t *UE_mac; int cyclic_prefix_type = NFAPI_CP_NORMAL; @@ -936,6 +940,13 @@ int main(int argc, char **argv) UE->phy_sim_pdsch_rxdataF_comp = calloc(sizeof(int32_t *) * frame_parms->nb_antennas_rx * g_nrOfLayers, rx_size); UE->phy_sim_pdsch_dl_ch_estimates = calloc(sizeof(int32_t *) * frame_parms->nb_antennas_rx * g_nrOfLayers, rx_size); UE->phy_sim_pdsch_dl_ch_estimates_ext = calloc(sizeof(int32_t *) * frame_parms->nb_antennas_rx * g_nrOfLayers, rx_size); + int a_segments = MAX_NUM_NR_DLSCH_SEGMENTS_PER_LAYER*NR_MAX_NB_LAYERS; //number of segments to be allocated + if (g_rbSize != 273) { + a_segments = a_segments*g_rbSize; + a_segments = (a_segments/273)+1; + } + uint32_t dlsch_bytes = a_segments*1056; // allocated bytes per segment + UE->phy_sim_dlsch_b = calloc(1, dlsch_bytes); for (SNR = snr0; SNR < snr1; SNR += .2) { @@ -951,8 +962,6 @@ int main(int argc, char **argv) reset_meas(&gNB->tparity); reset_meas(&gNB->toutput); - clear_pdsch_stats(gNB); - uint32_t errors_scrambling[16] = {0}; int n_errors[16] = {0}; int round_trials[16] = {0}; @@ -985,35 +994,40 @@ int main(int argc, char **argv) int harq_pid = slot; NR_DL_UE_HARQ_t *UE_harq_process = &UE->dl_harq_processes[0][harq_pid]; - NR_gNB_DLSCH_t *gNB_dlsch = msgDataTx->dlsch[0][0]; + NR_gNB_DLSCH_t *gNB_dlsch = &msgDataTx->dlsch[0][0]; nfapi_nr_dl_tti_pdsch_pdu_rel15_t *rel15 = &gNB_dlsch->harq_process.pdsch_pdu.pdsch_pdu_rel15; UE_harq_process->ack = 0; round = 0; UE_harq_process->DLround = round; UE_harq_process->first_rx = 1; - + + Sched_INFO = malloc(sizeof(*Sched_INFO)); + if (Sched_INFO == NULL) { + LOG_E(PHY, "out of memory\n"); + exit(1); + } + memset(Sched_INFO, 0, sizeof(*Sched_INFO)); + Sched_INFO->sched_response_id = -1; + while ((roundack==0)) { round_trials[round]++; - clear_nr_nfapi_information(RC.nrmac[0], 0, frame, slot); + clear_nr_nfapi_information(RC.nrmac[0], 0, frame, slot, &Sched_INFO->DL_req, &Sched_INFO->TX_req, &Sched_INFO->UL_dci_req); UE_info->UE_sched_ctrl.harq_processes[harq_pid].ndi = !(trial&1); UE_info->UE_sched_ctrl.harq_processes[harq_pid].round = round; - nr_schedule_ue_spec(0, frame, slot); - Sched_INFO.module_id = 0; - Sched_INFO.CC_id = 0; - Sched_INFO.frame = frame; - Sched_INFO.slot = slot; - Sched_INFO.DL_req = &gNB_mac->DL_req[0]; - Sched_INFO.UL_tti_req = gNB_mac->UL_tti_req_ahead[0]; - Sched_INFO.UL_dci_req = NULL; - Sched_INFO.TX_req = &gNB_mac->TX_req[0]; + nr_schedule_ue_spec(0, frame, slot, &Sched_INFO->DL_req, &Sched_INFO->TX_req); + Sched_INFO->module_id = 0; + Sched_INFO->CC_id = 0; + Sched_INFO->frame = frame; + Sched_INFO->slot = slot; + Sched_INFO->UL_dci_req.numPdus = 0; pushNotifiedFIFO(&gNB->L1_tx_free,msgL1Tx); - nr_schedule_response(&Sched_INFO); + nr_schedule_response(Sched_INFO); /* PTRS values for DLSIM calculations */ - nfapi_nr_dl_tti_request_body_t *dl_req = &gNB_mac->DL_req[Sched_INFO.CC_id].dl_tti_request_body; + nfapi_nr_dl_tti_request_body_t *dl_req = &Sched_INFO->DL_req.dl_tti_request_body; nfapi_nr_dl_tti_request_pdu_t *dl_tti_pdsch_pdu = &dl_req->dl_tti_pdu_list[1]; nfapi_nr_dl_tti_pdsch_pdu_rel15_t *pdsch_pdu_rel15 = &dl_tti_pdsch_pdu->pdsch_pdu.pdsch_pdu_rel15; pdu_bit_map = pdsch_pdu_rel15->pduBitmap; @@ -1151,9 +1165,12 @@ int main(int argc, char **argv) nr_ue_dcireq(&dcireq); //to be replaced with function pointer later nr_ue_scheduled_response(&scheduled_response); - phy_procedures_nrUE_RX(UE, - &UE_proc, - &phy_data); + pbch_pdcch_processing(UE, + &UE_proc, + &phy_data); + pdsch_processing(UE, + &UE_proc, + &phy_data); //---------------------------------------------------------- //---------------------- count errors ---------------------- @@ -1196,7 +1213,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); + estimated_output_bit[i] = (UE->phy_sim_dlsch_b[i/8] & (1 << (i & 7))) >> (i & 7); 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]) { @@ -1247,8 +1264,10 @@ int main(int argc, char **argv) if (print_perf==1) { printf("\ngNB TX function statistics (per %d us slot, NPRB %d, mcs %d, block %d)\n", - 1000>>*scc->ssbSubcarrierSpacing, g_rbSize, g_mcsIndex, - msgDataTx->dlsch[0][0]->harq_process.pdsch_pdu.pdsch_pdu_rel15.TBSize[0]<<3); + 1000 >> *scc->ssbSubcarrierSpacing, + g_rbSize, + g_mcsIndex, + msgDataTx->dlsch[0][0].harq_process.pdsch_pdu.pdsch_pdu_rel15.TBSize[0] << 3); 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"); @@ -1343,6 +1362,7 @@ int main(int argc, char **argv) free(UE->phy_sim_pdsch_rxdataF_comp); free(UE->phy_sim_pdsch_dl_ch_estimates); free(UE->phy_sim_pdsch_dl_ch_estimates_ext); + free(UE->phy_sim_dlsch_b); if (output_fd) fclose(output_fd); diff --git a/openair1/SIMULATION/NR_PHY/pbchsim.c b/openair1/SIMULATION/NR_PHY/pbchsim.c index ee67e8d52e..f16f8fc5f1 100644 --- a/openair1/SIMULATION/NR_PHY/pbchsim.c +++ b/openair1/SIMULATION/NR_PHY/pbchsim.c @@ -67,6 +67,17 @@ openair0_config_t openair0_cfg[MAX_CARDS]; uint8_t const nr_rv_round_map[4] = {0, 2, 3, 1}; +void inc_ref_sched_response(int _) +{ + LOG_E(PHY, "fatal\n"); + exit(1); +} +void deref_sched_response(int _) +{ + LOG_E(PHY, "fatal\n"); + exit(1); +} + uint64_t get_softmodem_optmask(void) {return 0;} static softmodem_params_t softmodem_params; softmodem_params_t *get_softmodem_params(void) { @@ -96,7 +107,8 @@ void nr_fill_rx_indication(fapi_nr_rx_indication_t *rx_ind, NR_UE_DLSCH_t *dlsch1, uint16_t n_pdus, UE_nr_rxtx_proc_t *proc, - void *typeSpecific ) {} + void *typeSpecific, + uint8_t *b) {} int nr_ue_pdcch_procedures(PHY_VARS_NR_UE *ue, UE_nr_rxtx_proc_t *proc, @@ -793,8 +805,8 @@ int main(int argc, char **argv) fapiPbch_t result; ret = nr_rx_pbch(UE, &proc, - estimateSz, dl_ch_estimates, - UE->pbch_vars[0], + estimateSz, + dl_ch_estimates, frame_parms, ssb_index%8, SISO, @@ -813,7 +825,6 @@ int main(int argc, char **argv) for (i=0;i<3;i++){ payload_ret += (result.decoded_output[i] == ((msgDataTx.ssb[ssb_index].ssb_pdu.ssb_pdu_rel15.bchPayload>>(8*i)) & 0xff)); } - //printf("xtra byte gNB: 0x%02x UE: 0x%02x\n",gNB_xtra_byte, UE->pbch_vars[0]->xtra_byte); //printf("ret %d\n", payload_ret); if (payload_ret!=4) n_errors_payload++; diff --git a/openair1/SIMULATION/NR_PHY/prachsim.c b/openair1/SIMULATION/NR_PHY/prachsim.c index d72bf2ed4f..aa441e4c61 100644 --- a/openair1/SIMULATION/NR_PHY/prachsim.c +++ b/openair1/SIMULATION/NR_PHY/prachsim.c @@ -86,6 +86,17 @@ softmodem_params_t *get_softmodem_params(void) {return 0;} instance_t DUuniqInstance=0; instance_t CUuniqInstance=0; +void inc_ref_sched_response(int _) +{ + LOG_E(PHY, "fatal\n"); + exit(1); +} +void deref_sched_response(int _) +{ + LOG_E(PHY, "fatal\n"); + exit(1); +} + int nr_derive_key_ng_ran_star(uint16_t pci, uint64_t nr_arfcn_dl, const uint8_t key[32], uint8_t *key_ng_ran_star) { return 0; @@ -106,6 +117,10 @@ int8_t nr_mac_rrc_data_req_ue(const module_id_t Mod_idP, return 0; } +int8_t nr_rrc_RA_succeeded(const module_id_t mod_id, const 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) { diff --git a/openair1/SIMULATION/NR_PHY/pucchsim.c b/openair1/SIMULATION/NR_PHY/pucchsim.c index 68ba96ab88..a0631767ba 100644 --- a/openair1/SIMULATION/NR_PHY/pucchsim.c +++ b/openair1/SIMULATION/NR_PHY/pucchsim.c @@ -73,6 +73,17 @@ void init_downlink_harq_status(NR_DL_UE_HARQ_t *dl_harq) {} NR_IF_Module_t *NR_IF_Module_init(int Mod_id) { return (NULL); } nfapi_mode_t nfapi_getmode(void) { return NFAPI_MODE_UNKNOWN; } +void inc_ref_sched_response(int _) +{ + LOG_E(PHY, "fatal\n"); + exit(1); +} +void deref_sched_response(int _) +{ + LOG_E(PHY, "fatal\n"); + exit(1); +} + nrUE_params_t nrUE_params={0}; nrUE_params_t *get_nrUE_params(void) { @@ -623,7 +634,7 @@ int main(int argc, char **argv) if(format==0){ nfapi_nr_uci_pucch_pdu_format_0_1_t uci_pdu; nfapi_nr_pucch_pdu_t pucch_pdu; - gNB->uci_stats[0].rnti = 0x1234; + gNB->phy_stats[0].rnti = 0x1234; pucch_pdu.rnti = 0x1234; pucch_pdu.subcarrier_spacing = 1; pucch_pdu.group_hop_flag = PUCCH_GroupHopping&1; diff --git a/openair1/SIMULATION/NR_PHY/ulschsim.c b/openair1/SIMULATION/NR_PHY/ulschsim.c index 325611d68d..69b12e78ee 100644 --- a/openair1/SIMULATION/NR_PHY/ulschsim.c +++ b/openair1/SIMULATION/NR_PHY/ulschsim.c @@ -80,6 +80,17 @@ PHY_VARS_NR_UE *PHY_vars_UE_g[1][1] = { { NULL } }; uint16_t n_rnti = 0x1234; openair0_config_t openair0_cfg[MAX_CARDS]; +void inc_ref_sched_response(int _) +{ + LOG_E(PHY, "fatal\n"); + exit(1); +} +void deref_sched_response(int _) +{ + LOG_E(PHY, "fatal\n"); + exit(1); +} + int nr_postDecode_sim(PHY_VARS_gNB *gNB, notifiedFIFO_elt_t *req) { ldpcDecode_t *rdata = (ldpcDecode_t*) NotifiedFifoData(req); NR_UL_gNB_HARQ_t *ulsch_harq = rdata->ulsch_harq; @@ -455,8 +466,8 @@ int main(int argc, char **argv) uint8_t rvidx = 0; uint8_t UE_id = 0; - NR_gNB_ULSCH_t *ulsch_gNB = gNB->ulsch[UE_id]; - NR_UL_gNB_HARQ_t *harq_process_gNB = ulsch_gNB->harq_processes[harq_pid]; + NR_gNB_ULSCH_t *ulsch_gNB = &gNB->ulsch[UE_id]; + NR_UL_gNB_HARQ_t *harq_process_gNB = ulsch_gNB->harq_process; nfapi_nr_pusch_pdu_t *rel15_ul = &harq_process_gNB->ulsch_pdu; nr_phy_data_tx_t phy_data = {0}; @@ -614,7 +625,7 @@ int main(int argc, char **argv) errors_bit = 0; for (i = 0; i < TBS; i++) { - estimated_output_bit[i] = (ulsch_gNB->harq_processes[harq_pid]->b[i/8] & (1 << (i & 7))) >> (i & 7); + estimated_output_bit[i] = (ulsch_gNB->harq_process->b[i / 8] & (1 << (i & 7))) >> (i & 7); test_input_bit[i] = (test_input[i / 8] & (1 << (i & 7))) >> (i & 7); // Further correct for multiple segments if (estimated_output_bit[i] != test_input_bit[i]) { diff --git a/openair1/SIMULATION/NR_PHY/ulsim.c b/openair1/SIMULATION/NR_PHY/ulsim.c index 4ec8fc3cca..d8ffdcc55e 100644 --- a/openair1/SIMULATION/NR_PHY/ulsim.c +++ b/openair1/SIMULATION/NR_PHY/ulsim.c @@ -116,6 +116,10 @@ int8_t nr_mac_rrc_data_req_ue(const module_id_t Mod_idP, return 0; } +int8_t nr_rrc_RA_succeeded(const module_id_t mod_id, const uint8_t gNB_index) { + return 0; +} + int DU_send_INITIAL_UL_RRC_MESSAGE_TRANSFER(module_id_t module_idP, int CC_idP, int UE_id, @@ -752,13 +756,13 @@ int main(int argc, char **argv) unsigned char harq_pid = 0; - NR_gNB_ULSCH_t *ulsch_gNB = gNB->ulsch[UE_id]; + NR_gNB_ULSCH_t *ulsch_gNB = &gNB->ulsch[UE_id]; - //nfapi_nr_ul_config_ulsch_pdu *rel15_ul = &ulsch_gNB->harq_processes[harq_pid]->ulsch_pdu; - nfapi_nr_ul_tti_request_t *UL_tti_req = malloc(sizeof(*UL_tti_req)); + // nfapi_nr_ul_config_ulsch_pdu *rel15_ul = &ulsch_gNB->harq_process->ulsch_pdu; NR_Sched_Rsp_t *Sched_INFO = malloc(sizeof(*Sched_INFO)); memset((void*)Sched_INFO,0,sizeof(*Sched_INFO)); - Sched_INFO->UL_tti_req=UL_tti_req; + nfapi_nr_ul_tti_request_t *UL_tti_req = &Sched_INFO->UL_tti_req; + Sched_INFO->sched_response_id = -1; nr_phy_data_tx_t phy_data = {0}; @@ -986,8 +990,6 @@ int main(int argc, char **argv) double blerStats[16] = {0}; double berStats[16] = {0}; - clear_pusch_stats(gNB); - uint64_t sum_pusch_delay = 0; int min_pusch_delay = INT_MAX; int max_pusch_delay = INT_MIN; @@ -1223,7 +1225,7 @@ int main(int argc, char **argv) tx_offset = frame_parms->get_samples_slot_timestamp(slot, frame_parms, 0); txlev_sum = 0; for (int aa = 0; aa < UE->frame_parms.nb_antennas_tx; aa++) { - atxlev[aa] = signal_energy(&UE->common_vars.txdata[aa][tx_offset + 5 * frame_parms->ofdm_symbol_size + 4 * frame_parms->nb_prefix_samples + frame_parms->nb_prefix_samples0], + atxlev[aa] = signal_energy((int32_t*)&UE->common_vars.txdata[aa][tx_offset + 5 * frame_parms->ofdm_symbol_size + 4 * frame_parms->nb_prefix_samples + frame_parms->nb_prefix_samples0], frame_parms->ofdm_symbol_size + frame_parms->nb_prefix_samples); txlev_sum += atxlev[aa]; @@ -1304,140 +1306,196 @@ int main(int argc, char **argv) } } + NR_gNB_PUSCH *pusch_vars = &gNB->pusch_vars[UE_id]; if (n_trials == 1 && round == 0) { __attribute__((unused)) int off = ((nb_rb & 1) == 1) ? 4 : 0; LOG_M("rxsigF0_ext.m", "rxsF0_ext", - &gNB->pusch_vars[0]->rxdataF_ext[0][start_symbol * NR_NB_SC_PER_RB * pusch_pdu->rb_size], + &pusch_vars->rxdataF_ext[0][start_symbol * NR_NB_SC_PER_RB * pusch_pdu->rb_size], nb_symb_sch * (off + (NR_NB_SC_PER_RB * pusch_pdu->rb_size)), 1, 1); - LOG_M("chestF0.m", "chF0", &gNB->pusch_vars[0]->ul_ch_estimates[0][start_symbol * frame_parms->ofdm_symbol_size], frame_parms->ofdm_symbol_size, 1, 1); - LOG_M("chestT0.m", "chT0", &gNB->pusch_vars[0]->ul_ch_estimates_time[0][0], frame_parms->ofdm_symbol_size, 1, 1); + LOG_M("chestF0.m", + "chF0", + &pusch_vars->ul_ch_estimates[0][start_symbol * frame_parms->ofdm_symbol_size], + frame_parms->ofdm_symbol_size, + 1, + 1); + LOG_M("chestT0.m", "chT0", &pusch_vars->ul_ch_estimates_time[0][0], frame_parms->ofdm_symbol_size, 1, 1); LOG_M("chestF0_ext.m", "chF0_ext", - &gNB->pusch_vars[0]->ul_ch_estimates_ext[0][(start_symbol + 1) * (off + (NR_NB_SC_PER_RB * pusch_pdu->rb_size))], + &pusch_vars->ul_ch_estimates_ext[0][(start_symbol + 1) * (off + (NR_NB_SC_PER_RB * pusch_pdu->rb_size))], (nb_symb_sch - 1) * (off + (NR_NB_SC_PER_RB * pusch_pdu->rb_size)), 1, 1); LOG_M("rxsigF0_comp.m", "rxsF0_comp", - &gNB->pusch_vars[0]->rxdataF_comp[0][start_symbol * (off + (NR_NB_SC_PER_RB * pusch_pdu->rb_size))], + &pusch_vars->rxdataF_comp[0][start_symbol * (off + (NR_NB_SC_PER_RB * pusch_pdu->rb_size))], nb_symb_sch * (off + (NR_NB_SC_PER_RB * pusch_pdu->rb_size)), 1, 1); LOG_M("chmagF0.m", "chmF0", - &gNB->pusch_vars[0]->ul_ch_mag[0][start_symbol * (off + (NR_NB_SC_PER_RB * pusch_pdu->rb_size))], + &pusch_vars->ul_ch_mag[0][start_symbol * (off + (NR_NB_SC_PER_RB * pusch_pdu->rb_size))], nb_symb_sch * (off + (NR_NB_SC_PER_RB * pusch_pdu->rb_size)), 1, 1); LOG_M("chmagbF0.m", "chmbF0", - &gNB->pusch_vars[0]->ul_ch_magb[0][start_symbol * (off + (NR_NB_SC_PER_RB * pusch_pdu->rb_size))], + &pusch_vars->ul_ch_magb[0][start_symbol * (off + (NR_NB_SC_PER_RB * pusch_pdu->rb_size))], nb_symb_sch * (off + (NR_NB_SC_PER_RB * pusch_pdu->rb_size)), 1, 1); - LOG_M("rxsigF0_llrlayers0.m", "rxsF0_llrlayers0", &gNB->pusch_vars[0]->llr_layers[0][0], (nb_symb_sch - 1) * NR_NB_SC_PER_RB * pusch_pdu->rb_size * mod_order, 1, 0); + LOG_M("rxsigF0_llrlayers0.m", + "rxsF0_llrlayers0", + &pusch_vars->llr_layers[0][0], + (nb_symb_sch - 1) * NR_NB_SC_PER_RB * pusch_pdu->rb_size * mod_order, + 1, + 0); if (precod_nbr_layers == 2) { LOG_M("rxsigF1_ext.m", "rxsF1_ext", - &gNB->pusch_vars[0]->rxdataF_ext[1][start_symbol * NR_NB_SC_PER_RB * pusch_pdu->rb_size], + &pusch_vars->rxdataF_ext[1][start_symbol * NR_NB_SC_PER_RB * pusch_pdu->rb_size], nb_symb_sch * (off + (NR_NB_SC_PER_RB * pusch_pdu->rb_size)), 1, 1); - LOG_M("chestF3.m", "chF3", &gNB->pusch_vars[0]->ul_ch_estimates[3][start_symbol * frame_parms->ofdm_symbol_size], frame_parms->ofdm_symbol_size, 1, 1); + LOG_M("chestF3.m", + "chF3", + &pusch_vars->ul_ch_estimates[3][start_symbol * frame_parms->ofdm_symbol_size], + frame_parms->ofdm_symbol_size, + 1, + 1); LOG_M("chestF3_ext.m", "chF3_ext", - &gNB->pusch_vars[0]->ul_ch_estimates_ext[3][(start_symbol + 1) * (off + (NR_NB_SC_PER_RB * pusch_pdu->rb_size))], + &pusch_vars->ul_ch_estimates_ext[3][(start_symbol + 1) * (off + (NR_NB_SC_PER_RB * pusch_pdu->rb_size))], (nb_symb_sch - 1) * (off + (NR_NB_SC_PER_RB * pusch_pdu->rb_size)), 1, 1); LOG_M("rxsigF2_comp.m", "rxsF2_comp", - &gNB->pusch_vars[0]->rxdataF_comp[2][start_symbol * (off + (NR_NB_SC_PER_RB * pusch_pdu->rb_size))], + &pusch_vars->rxdataF_comp[2][start_symbol * (off + (NR_NB_SC_PER_RB * pusch_pdu->rb_size))], nb_symb_sch * (off + (NR_NB_SC_PER_RB * pusch_pdu->rb_size)), 1, 1); - LOG_M("rxsigF0_llrlayers1.m", "rxsF0_llrlayers1", &gNB->pusch_vars[0]->llr_layers[1][0], (nb_symb_sch - 1) * NR_NB_SC_PER_RB * pusch_pdu->rb_size * mod_order, 1, 0); + LOG_M("rxsigF0_llrlayers1.m", + "rxsF0_llrlayers1", + &pusch_vars->llr_layers[1][0], + (nb_symb_sch - 1) * NR_NB_SC_PER_RB * pusch_pdu->rb_size * mod_order, + 1, + 0); } if (precod_nbr_layers == 4) { LOG_M("rxsigF1_ext.m", "rxsF1_ext", - &gNB->pusch_vars[0]->rxdataF_ext[1][start_symbol * NR_NB_SC_PER_RB * pusch_pdu->rb_size], + &pusch_vars->rxdataF_ext[1][start_symbol * NR_NB_SC_PER_RB * pusch_pdu->rb_size], nb_symb_sch * (off + (NR_NB_SC_PER_RB * pusch_pdu->rb_size)), 1, 1); LOG_M("rxsigF2_ext.m", "rxsF2_ext", - &gNB->pusch_vars[0]->rxdataF_ext[2][start_symbol * NR_NB_SC_PER_RB * pusch_pdu->rb_size], + &pusch_vars->rxdataF_ext[2][start_symbol * NR_NB_SC_PER_RB * pusch_pdu->rb_size], nb_symb_sch * (off + (NR_NB_SC_PER_RB * pusch_pdu->rb_size)), 1, 1); LOG_M("rxsigF3_ext.m", "rxsF3_ext", - &gNB->pusch_vars[0]->rxdataF_ext[3][start_symbol * NR_NB_SC_PER_RB * pusch_pdu->rb_size], + &pusch_vars->rxdataF_ext[3][start_symbol * NR_NB_SC_PER_RB * pusch_pdu->rb_size], nb_symb_sch * (off + (NR_NB_SC_PER_RB * pusch_pdu->rb_size)), 1, 1); - LOG_M("chestF5.m", "chF5", &gNB->pusch_vars[0]->ul_ch_estimates[5][start_symbol * frame_parms->ofdm_symbol_size], frame_parms->ofdm_symbol_size, 1, 1); - LOG_M("chestF10.m", "chF10", &gNB->pusch_vars[0]->ul_ch_estimates[10][start_symbol * frame_parms->ofdm_symbol_size], frame_parms->ofdm_symbol_size, 1, 1); - LOG_M("chestF15.m", "chF15", &gNB->pusch_vars[0]->ul_ch_estimates[15][start_symbol * frame_parms->ofdm_symbol_size], frame_parms->ofdm_symbol_size, 1, 1); + LOG_M("chestF5.m", + "chF5", + &pusch_vars->ul_ch_estimates[5][start_symbol * frame_parms->ofdm_symbol_size], + frame_parms->ofdm_symbol_size, + 1, + 1); + LOG_M("chestF10.m", + "chF10", + &pusch_vars->ul_ch_estimates[10][start_symbol * frame_parms->ofdm_symbol_size], + frame_parms->ofdm_symbol_size, + 1, + 1); + LOG_M("chestF15.m", + "chF15", + &pusch_vars->ul_ch_estimates[15][start_symbol * frame_parms->ofdm_symbol_size], + frame_parms->ofdm_symbol_size, + 1, + 1); LOG_M("chestF5_ext.m", "chF5_ext", - &gNB->pusch_vars[0]->ul_ch_estimates_ext[5][(start_symbol + 1) * (off + (NR_NB_SC_PER_RB * pusch_pdu->rb_size))], + &pusch_vars->ul_ch_estimates_ext[5][(start_symbol + 1) * (off + (NR_NB_SC_PER_RB * pusch_pdu->rb_size))], (nb_symb_sch - 1) * (off + (NR_NB_SC_PER_RB * pusch_pdu->rb_size)), 1, 1); LOG_M("chestF10_ext.m", "chF10_ext", - &gNB->pusch_vars[0]->ul_ch_estimates_ext[10][(start_symbol + 1) * (off + (NR_NB_SC_PER_RB * pusch_pdu->rb_size))], + &pusch_vars->ul_ch_estimates_ext[10][(start_symbol + 1) * (off + (NR_NB_SC_PER_RB * pusch_pdu->rb_size))], (nb_symb_sch - 1) * (off + (NR_NB_SC_PER_RB * pusch_pdu->rb_size)), 1, 1); LOG_M("chestF15_ext.m", "chF15_ext", - &gNB->pusch_vars[0]->ul_ch_estimates_ext[15][(start_symbol + 1) * (off + (NR_NB_SC_PER_RB * pusch_pdu->rb_size))], + &pusch_vars->ul_ch_estimates_ext[15][(start_symbol + 1) * (off + (NR_NB_SC_PER_RB * pusch_pdu->rb_size))], (nb_symb_sch - 1) * (off + (NR_NB_SC_PER_RB * pusch_pdu->rb_size)), 1, 1); LOG_M("rxsigF4_comp.m", "rxsF4_comp", - &gNB->pusch_vars[0]->rxdataF_comp[4][start_symbol * (off + (NR_NB_SC_PER_RB * pusch_pdu->rb_size))], + &pusch_vars->rxdataF_comp[4][start_symbol * (off + (NR_NB_SC_PER_RB * pusch_pdu->rb_size))], nb_symb_sch * (off + (NR_NB_SC_PER_RB * pusch_pdu->rb_size)), 1, 1); LOG_M("rxsigF8_comp.m", "rxsF8_comp", - &gNB->pusch_vars[0]->rxdataF_comp[8][start_symbol * (off + (NR_NB_SC_PER_RB * pusch_pdu->rb_size))], + &pusch_vars->rxdataF_comp[8][start_symbol * (off + (NR_NB_SC_PER_RB * pusch_pdu->rb_size))], nb_symb_sch * (off + (NR_NB_SC_PER_RB * pusch_pdu->rb_size)), 1, 1); LOG_M("rxsigF12_comp.m", "rxsF12_comp", - &gNB->pusch_vars[0]->rxdataF_comp[12][start_symbol * (off + (NR_NB_SC_PER_RB * pusch_pdu->rb_size))], + &pusch_vars->rxdataF_comp[12][start_symbol * (off + (NR_NB_SC_PER_RB * pusch_pdu->rb_size))], nb_symb_sch * (off + (NR_NB_SC_PER_RB * pusch_pdu->rb_size)), 1, 1); - LOG_M("rxsigF0_llrlayers1.m", "rxsF0_llrlayers1", &gNB->pusch_vars[0]->llr_layers[1][0], (nb_symb_sch - 1) * NR_NB_SC_PER_RB * pusch_pdu->rb_size * mod_order, 1, 0); - LOG_M("rxsigF0_llrlayers2.m", "rxsF0_llrlayers2", &gNB->pusch_vars[0]->llr_layers[2][0], (nb_symb_sch - 1) * NR_NB_SC_PER_RB * pusch_pdu->rb_size * mod_order, 1, 0); - LOG_M("rxsigF0_llrlayers3.m", "rxsF0_llrlayers3", &gNB->pusch_vars[0]->llr_layers[3][0], (nb_symb_sch - 1) * NR_NB_SC_PER_RB * pusch_pdu->rb_size * mod_order, 1, 0); + LOG_M("rxsigF0_llrlayers1.m", + "rxsF0_llrlayers1", + &pusch_vars->llr_layers[1][0], + (nb_symb_sch - 1) * NR_NB_SC_PER_RB * pusch_pdu->rb_size * mod_order, + 1, + 0); + LOG_M("rxsigF0_llrlayers2.m", + "rxsF0_llrlayers2", + &pusch_vars->llr_layers[2][0], + (nb_symb_sch - 1) * NR_NB_SC_PER_RB * pusch_pdu->rb_size * mod_order, + 1, + 0); + LOG_M("rxsigF0_llrlayers3.m", + "rxsF0_llrlayers3", + &pusch_vars->llr_layers[3][0], + (nb_symb_sch - 1) * NR_NB_SC_PER_RB * pusch_pdu->rb_size * mod_order, + 1, + 0); } - LOG_M("rxsigF0_llr.m", "rxsF0_llr", &gNB->pusch_vars[0]->llr[0], precod_nbr_layers * (nb_symb_sch - 1) * NR_NB_SC_PER_RB * pusch_pdu->rb_size * mod_order, 1, 0); + LOG_M("rxsigF0_llr.m", + "rxsF0_llr", + &pusch_vars->llr[0], + precod_nbr_layers * (nb_symb_sch - 1) * NR_NB_SC_PER_RB * pusch_pdu->rb_size * mod_order, + 1, + 0); } - if ((gNB->ulsch[0]->last_iteration_cnt >= gNB->ulsch[0]->max_ldpc_iterations + 1) || ul_proc_error == 1) { + if ((ulsch_gNB->last_iteration_cnt >= ulsch_gNB->max_ldpc_iterations + 1) || ul_proc_error == 1) { error_flag = 1; n_errors[round]++; crc_status = 1; @@ -1453,7 +1511,7 @@ int main(int argc, char **argv) if ((pusch_pdu->pdu_bit_map & PUSCH_PDU_BITMAP_PUSCH_PTRS) && (SNR == snr0) && (trial == 0) && (round == 0)) { ptrs_symbols = 0; for (int i = pusch_pdu->start_symbol_index; i < pusch_pdu->start_symbol_index + pusch_pdu->nr_of_symbols; i++) - ptrs_symbols += ((gNB->pusch_vars[UE_id]->ptrs_symbols) >> i) & 1; + ptrs_symbols += ((pusch_vars->ptrs_symbols) >> i) & 1; /* 2*5*(50/2), for RB = 50,K = 2 for 5 OFDM PTRS symbols */ available_bits -= 2 * ptrs_symbols * ((nb_rb + ptrs_freq_density - 1) / ptrs_freq_density); @@ -1461,8 +1519,8 @@ int main(int argc, char **argv) } for (i = 0; i < available_bits; i++) { - if (((UE->ul_harq_processes[harq_pid].f[i] == 0) && (gNB->pusch_vars[UE_id]->llr[i] <= 0)) - || ((UE->ul_harq_processes[harq_pid].f[i] == 1) && (gNB->pusch_vars[UE_id]->llr[i] >= 0))) { + if (((UE->ul_harq_processes[harq_pid].f[i] == 0) && (pusch_vars->llr[i] <= 0)) + || ((UE->ul_harq_processes[harq_pid].f[i] == 1) && (pusch_vars->llr[i] >= 0))) { /*if(errors_scrambling == 0) printf("\x1B[34m" "[frame %d][trial %d]\t1st bit in error in unscrambling = %d\n" "\x1B[0m", frame, trial, i);*/ errors_scrambling[round]++; @@ -1476,8 +1534,7 @@ int main(int argc, char **argv) } for (i = 0; i < TBS; i++) { - - estimated_output_bit[i] = (ulsch_gNB->harq_processes[harq_pid]->b[i / 8] & (1 << (i & 7))) >> (i & 7); + estimated_output_bit[i] = (ulsch_gNB->harq_process->b[i / 8] & (1 << (i & 7))) >> (i & 7); test_input_bit[i] = (UE->ul_harq_processes[harq_pid].b[i / 8] & (1 << (i & 7))) >> (i & 7); if (estimated_output_bit[i] != test_input_bit[i]) { @@ -1489,12 +1546,12 @@ int main(int argc, char **argv) if (n_trials == 1) { for (int r = 0; r < UE->ul_harq_processes[harq_pid].C; r++) for (int i = 0; i < UE->ul_harq_processes[harq_pid].K >> 3; i++) { - if ((UE->ul_harq_processes[harq_pid].c[r][i] ^ ulsch_gNB->harq_processes[harq_pid]->c[r][i]) != 0) + if ((UE->ul_harq_processes[harq_pid].c[r][i] ^ ulsch_gNB->harq_process->c[r][i]) != 0) printf("************"); /*printf("r %d: in[%d] %x, out[%d] %x (%x)\n",r, i,UE->ul_harq_processes[harq_pid].c[r][i], - i,ulsch_gNB->harq_processes[harq_pid]->c[r][i], - UE->ul_harq_processes[harq_pid].c[r][i]^ulsch_gNB->harq_processes[harq_pid]->c[r][i]);*/ + i,ulsch_gNB->harq_process->c[r][i], + UE->ul_harq_processes[harq_pid].c[r][i]^ulsch_gNB->harq_process->c[r][i]);*/ } } if (errors_decoding > 0 && error_flag == 0) { @@ -1506,9 +1563,9 @@ int main(int argc, char **argv) if (!crc_status) effRate += ((double)TBS) / (double)round; - sum_pusch_delay += gNB->measurements.delay[UE_id].pusch_est_delay; - min_pusch_delay = gNB->measurements.delay[UE_id].pusch_est_delay < min_pusch_delay ? gNB->measurements.delay[UE_id].pusch_est_delay : min_pusch_delay; - max_pusch_delay = gNB->measurements.delay[UE_id].pusch_est_delay > max_pusch_delay ? gNB->measurements.delay[UE_id].pusch_est_delay : max_pusch_delay; + sum_pusch_delay += ulsch_gNB->delay.pusch_est_delay; + min_pusch_delay = ulsch_gNB->delay.pusch_est_delay < min_pusch_delay ? ulsch_gNB->delay.pusch_est_delay : min_pusch_delay; + max_pusch_delay = ulsch_gNB->delay.pusch_est_delay > max_pusch_delay ? ulsch_gNB->delay.pusch_est_delay : max_pusch_delay; delay_pusch_est_count++; } // trial loop diff --git a/openair2/COMMON/as_message.h b/openair2/COMMON/as_message.h index b0ca06daec..ef7314697f 100644 --- a/openair2/COMMON/as_message.h +++ b/openair2/COMMON/as_message.h @@ -327,6 +327,13 @@ typedef struct nas_establish_req_s { as_nas_info_t initialNasMsg; /* Initial NAS message to transfer */ } nas_establish_req_t; +/* + * fill me + */ +typedef struct nas_deregistration_req_s { + // fill me +} nas_deregistration_req_t; + /* * AS->NAS - NAS signalling connection establishment indication * AS transfers the initial NAS message to the NAS. diff --git a/openair2/COMMON/rrc_messages_def.h b/openair2/COMMON/rrc_messages_def.h index d93f07d8f8..f70c8bdd0e 100644 --- a/openair2/COMMON/rrc_messages_def.h +++ b/openair2/COMMON/rrc_messages_def.h @@ -62,6 +62,7 @@ MESSAGE_DEF(NAS_KENB_REFRESH_REQ, MESSAGE_PRIORITY_MED, NasKenbRefre MESSAGE_DEF(NAS_CELL_SELECTION_REQ, MESSAGE_PRIORITY_MED, NasCellSelectionReq, nas_cell_selection_req) MESSAGE_DEF(NAS_CONN_ESTABLI_REQ, MESSAGE_PRIORITY_MED, NasConnEstabliReq, nas_conn_establi_req) MESSAGE_DEF(NAS_UPLINK_DATA_REQ, MESSAGE_PRIORITY_MED, NasUlDataReq, nas_ul_data_req) +MESSAGE_DEF(NAS_DEREGISTRATION_REQ, MESSAGE_PRIORITY_MED, NasDeregistrationReq, nas_deregistration_req) MESSAGE_DEF(NAS_RAB_ESTABLI_RSP, MESSAGE_PRIORITY_MED, NasRabEstRsp, nas_rab_est_rsp) diff --git a/openair2/COMMON/rrc_messages_types.h b/openair2/COMMON/rrc_messages_types.h index 64f3b68bfb..359720f92f 100644 --- a/openair2/COMMON/rrc_messages_types.h +++ b/openair2/COMMON/rrc_messages_types.h @@ -75,6 +75,7 @@ #define NAS_CELL_SELECTION_REQ(mSGpTR) (mSGpTR)->ittiMsg.nas_cell_selection_req #define NAS_CONN_ESTABLI_REQ(mSGpTR) (mSGpTR)->ittiMsg.nas_conn_establi_req #define NAS_UPLINK_DATA_REQ(mSGpTR) (mSGpTR)->ittiMsg.nas_ul_data_req +#define NAS_DEREGISTRATION_REQ(mSGpTR) (mSGpTR)->ittiMsg.nas_deregistration_req #define NAS_RAB_ESTABLI_RSP(mSGpTR) (mSGpTR)->ittiMsg.nas_rab_est_rsp @@ -441,6 +442,7 @@ typedef kenb_refresh_req_t NasKenbRefreshReq; typedef cell_info_req_t NasCellSelectionReq; typedef nas_establish_req_t NasConnEstabliReq; typedef ul_info_transfer_req_t NasUlDataReq; +typedef nas_deregistration_req_t NasDeregistrationReq; typedef rab_establish_rsp_t NasRabEstRsp; diff --git a/openair2/E1AP/e1ap_api.c b/openair2/E1AP/e1ap_api.c index 23a9fcd1ea..b67525acca 100644 --- a/openair2/E1AP/e1ap_api.c +++ b/openair2/E1AP/e1ap_api.c @@ -112,9 +112,7 @@ static int drb_config_N3gtpu_create(e1ap_bearer_setup_req_t * const req, create_tunnel_req.ue_id = (req->gNB_cu_cp_ue_id & 0xFFFF); // Create N3 tunnel - int ret = gtpv1u_create_ngu_tunnel(instance, - &create_tunnel_req, - create_tunnel_resp); + int ret = gtpv1u_create_ngu_tunnel(instance, &create_tunnel_req, create_tunnel_resp, nr_pdcp_data_req_drb, sdap_data_req); if (ret != 0) { LOG_E(NR_RRC,"rrc_gNB_process_NGAP_PDUSESSION_SETUP_REQ : gtpv1u_create_ngu_tunnel failed,start to release UE id %ld\n", create_tunnel_req.ue_id); diff --git a/openair2/F1AP/f1ap_cu_rrc_message_transfer.c b/openair2/F1AP/f1ap_cu_rrc_message_transfer.c index f1e0a7ade1..7fc30967de 100644 --- a/openair2/F1AP/f1ap_cu_rrc_message_transfer.c +++ b/openair2/F1AP/f1ap_cu_rrc_message_transfer.c @@ -37,7 +37,7 @@ #include "f1ap_cu_rrc_message_transfer.h" #include "common/ran_context.h" #include "openair3/UTILS/conversions.h" -#include "pdcp.h" +#include "LAYER2/nr_pdcp/nr_pdcp_oai_api.h" /* Initial UL RRC Message Transfer diff --git a/openair2/F1AP/f1ap_cu_ue_context_management.c b/openair2/F1AP/f1ap_cu_ue_context_management.c index 0cb476b2d7..bfa48a4f88 100644 --- a/openair2/F1AP/f1ap_cu_ue_context_management.c +++ b/openair2/F1AP/f1ap_cu_ue_context_management.c @@ -40,7 +40,7 @@ #include "rrc_extern.h" #include "openair2/RRC/NR/rrc_gNB_NGAP.h" #include -#include "pdcp.h" +#include "LAYER2/nr_pdcp/nr_pdcp_oai_api.h" static void setQos(F1AP_NonDynamic5QIDescriptor_t *toFill) { asn1cCalloc(toFill, tmp); @@ -958,7 +958,7 @@ int CU_handle_UE_CONTEXT_RELEASE_COMPLETE(instance_t instance, LOG_E(F1AP, "could not find ue_context of UE RNTI %x\n", rnti); } - pdcp_remove_UE(&ctxt); + nr_pdcp_remove_UE(ctxt.rntiMaybeUEid); LOG_I(F1AP, "Received UE CONTEXT RELEASE COMPLETE: Removing CU UE entry for RNTI %x\n", rnti); f1ap_remove_ue(CUtype, instance, rnti); diff --git a/openair2/GNB_APP/gnb_app.c b/openair2/GNB_APP/gnb_app.c index 6404b26418..84cbf0d424 100644 --- a/openair2/GNB_APP/gnb_app.c +++ b/openair2/GNB_APP/gnb_app.c @@ -49,7 +49,7 @@ #include "f1ap_du_task.h" #include "nfapi/oai_integration/vendor_ext.h" #include -#include "openair2/LAYER2/PDCP_v10.1.0/pdcp.h" +#include "openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.h" #include "openair2/E1AP/e1ap.h" #include "gnb_config.h" extern unsigned char NB_gNB_INST; diff --git a/openair2/GNB_APP/gnb_config.c b/openair2/GNB_APP/gnb_config.c index 4fb0864ad2..14c3be6c2e 100644 --- a/openair2/GNB_APP/gnb_config.c +++ b/openair2/GNB_APP/gnb_config.c @@ -54,7 +54,7 @@ #include "radio/ETHERNET/USERSPACE/LIB/ethernet_lib.h" #include "nfapi_vnf.h" #include "nfapi_pnf.h" -#include "pdcp.h" +#include "nr_pdcp/nr_pdcp_oai_api.h" //#include "L1_paramdef.h" #include "prs_nr_paramdef.h" @@ -2247,6 +2247,6 @@ void nr_read_config_and_init(void) { } if (NODE_IS_CU(RC.nrrrc[0]->node_type) && RC.nrrrc[0]->node_type != ngran_gNB_CUCP) { - pdcp_layer_init(); + nr_pdcp_layer_init(); } } diff --git a/openair2/LAYER2/NR_MAC_UE/config_ue.c b/openair2/LAYER2/NR_MAC_UE/config_ue.c index 8ab321b9e1..8dfc05952d 100644 --- a/openair2/LAYER2/NR_MAC_UE/config_ue.c +++ b/openair2/LAYER2/NR_MAC_UE/config_ue.c @@ -701,6 +701,9 @@ int nr_rrc_mac_config_req_ue(module_id_t module_id, RA_config_t *ra = &mac->ra; fapi_nr_config_request_t *cfg = &mac->phy_config.config_req; + if (mac->dl_config_request == NULL) // for SIB1 reception + mac->dl_config_request = calloc(NR_MAX_SLOTS_PER_FRAME, sizeof(*mac->dl_config_request)); + // TODO do something FAPI-like P5 L1/L2 config interface in config_si, config_mib, etc. if(mibP != NULL){ @@ -726,9 +729,21 @@ int nr_rrc_mac_config_req_ue(module_id_t module_id, } } LOG_I(NR_MAC, "Initializing ul_config_request. num_slots_ul = %d\n", num_slots_ul); - mac->ul_config_request = (fapi_nr_ul_config_request_t *)calloc(num_slots_ul, sizeof(fapi_nr_ul_config_request_t)); + mac->ul_config_request = calloc(num_slots_ul, sizeof(*mac->ul_config_request)); for (int i=0; iul_config_request[i].mutex_ul_config), NULL); + + int num_slots_dl = nr_slots_per_frame[mac->mib->subCarrierSpacingCommon]; + if (cfg->cell_config.frame_duplex_type == TDD) { + num_slots_dl = mac->scc_SIB->tdd_UL_DL_ConfigurationCommon->pattern1.nrofDownlinkSlots; + if (mac->scc_SIB->tdd_UL_DL_ConfigurationCommon->pattern1.nrofDownlinkSymbols > 0) { + num_slots_dl++; + } + } + LOG_I(NR_MAC, "Initializing dl_config_request. num_slots_dl = %d\n", num_slots_dl); + mac->dl_config_request = realloc(mac->dl_config_request, num_slots_dl*sizeof(*mac->dl_config_request)); + memset(mac->dl_config_request, 0, num_slots_dl*sizeof(fapi_nr_dl_config_request_t)); + // Setup the SSB to Rach Occasionsif (cell_group_config->spCellConfig) { mapping according to the config build_ssb_to_ro_map(mac);//->scc, mac->phy_config.config_req.cell_config.frame_duplex_type); if (!get_softmodem_params()->emulate_l1) @@ -752,8 +767,8 @@ int nr_rrc_mac_config_req_ue(module_id_t module_id, config_control_ue(mac); // Setup the SSB to Rach Occasions mapping according to the config build_ssb_to_ro_map(mac); - } - else if (cell_group_config != NULL ){ + + } else if (cell_group_config != NULL) { LOG_I(MAC,"Applying CellGroupConfig from gNodeB\n"); mac->cg = cell_group_config; if (cell_group_config->spCellConfig) @@ -772,20 +787,38 @@ int nr_rrc_mac_config_req_ue(module_id_t module_id, configure_current_BWP(mac, NULL, cell_group_config); config_control_ue(mac); - if (get_softmodem_params()->nsa) { - if (cell_group_config->spCellConfig && cell_group_config->spCellConfig->reconfigurationWithSync) { - if (cell_group_config->spCellConfig->reconfigurationWithSync->rach_ConfigDedicated) { - ra->rach_ConfigDedicated = cell_group_config->spCellConfig->reconfigurationWithSync->rach_ConfigDedicated->choice.uplink; - } - mac->scc = cell_group_config->spCellConfig->reconfigurationWithSync->spCellConfigCommon; - int num_slots = mac->scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofUplinkSlots; - if (mac->scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofUplinkSymbols > 0) { - num_slots++; - } - mac->ul_config_request = calloc(num_slots, sizeof(*mac->ul_config_request)); - config_common_ue(mac,module_id,cc_idP); - mac->crnti = cell_group_config->spCellConfig->reconfigurationWithSync->newUE_Identity; - LOG_I(MAC,"Configuring CRNTI %x\n",mac->crnti); + if (cell_group_config->spCellConfig && cell_group_config->spCellConfig->reconfigurationWithSync) { + LOG_A(NR_MAC, "Received the reconfigurationWithSync in %s\n", __FUNCTION__); + if (cell_group_config->spCellConfig->reconfigurationWithSync->rach_ConfigDedicated) { + ra->rach_ConfigDedicated = cell_group_config->spCellConfig->reconfigurationWithSync->rach_ConfigDedicated->choice.uplink; + } + mac->scc = cell_group_config->spCellConfig->reconfigurationWithSync->spCellConfigCommon; + if (mac->scc_SIB) { + free(mac->scc_SIB); + mac->scc_SIB = NULL; + } + int num_slots = mac->scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofUplinkSlots; + if (mac->scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofUplinkSymbols > 0) { + num_slots++; + } + mac->state = UE_NOT_SYNC; + mac->ra.ra_state = RA_UE_IDLE; + mac->physCellId = *mac->scc->physCellId; + if (!get_softmodem_params()->emulate_l1) { + mac->synch_request.Mod_id = module_id; + mac->synch_request.CC_id = cc_idP; + mac->synch_request.synch_req.target_Nid_cell = mac->physCellId; + mac->if_module->synch_request(&mac->synch_request); + } + mac->ul_config_request = calloc(num_slots, sizeof(*mac->ul_config_request)); + config_common_ue(mac, module_id, cc_idP); + mac->crnti = cell_group_config->spCellConfig->reconfigurationWithSync->newUE_Identity; + LOG_I(MAC, "Configuring CRNTI %x\n", mac->crnti); + + nr_ue_init_mac(module_id); + if (!get_softmodem_params()->emulate_l1) { + mac->if_module->phy_config_request(&mac->phy_config); + mac->phy_config_request_sent = true; } // Setup the SSB to Rach Occasions mapping according to the config diff --git a/openair2/LAYER2/NR_MAC_UE/mac_defs.h b/openair2/LAYER2/NR_MAC_UE/mac_defs.h index e3f4247bd6..25063f3141 100644 --- a/openair2/LAYER2/NR_MAC_UE/mac_defs.h +++ b/openair2/LAYER2/NR_MAC_UE/mac_defs.h @@ -376,8 +376,9 @@ typedef struct { uint32_t ssb_index; /// SSB RSRP in dBm short ssb_rsrp_dBm; + int consecutive_bch_failures; -} NR_PHY_meas_t; +} NR_SSB_meas_t; /*!\brief Top level UE MAC structure */ typedef struct { @@ -441,11 +442,12 @@ typedef struct { int first_ul_tx[NR_MAX_HARQ_PROCESSES]; //// FAPI-like interface message fapi_nr_ul_config_request_t *ul_config_request; - fapi_nr_dl_config_request_t dl_config_request; + fapi_nr_dl_config_request_t *dl_config_request; /// Interface module instances nr_ue_if_module_t *if_module; nr_phy_config_t phy_config; + nr_synch_request_t synch_request; /// BSR report flag management uint8_t BSR_reporting_active; @@ -464,9 +466,9 @@ typedef struct { uint16_t nr_band; uint8_t ssb_subcarrier_offset; - NR_PHY_meas_t phy_measurements; + NR_SSB_meas_t ssb_measurements; - dci_pdu_rel15_t def_dci_pdu_rel15[8]; + dci_pdu_rel15_t def_dci_pdu_rel15[NR_MAX_SLOTS_PER_FRAME][8]; // Defined for abstracted mode nr_downlink_indication_t dl_info; diff --git a/openair2/LAYER2/NR_MAC_UE/mac_proto.h b/openair2/LAYER2/NR_MAC_UE/mac_proto.h index 6015fe27bc..c8eec75d85 100644 --- a/openair2/LAYER2/NR_MAC_UE/mac_proto.h +++ b/openair2/LAYER2/NR_MAC_UE/mac_proto.h @@ -190,6 +190,8 @@ int8_t nr_ue_process_csirs_measurements(module_id_t module_id, frame_t frame, in uint32_t get_ssb_frame(uint32_t test); +void nr_ue_aperiodic_srs_scheduling(NR_UE_MAC_INST_t *mac, long resource_trigger, int frame, int slot); + bool trigger_periodic_scheduling_request(NR_UE_MAC_INST_t *mac, PUCCH_sched_t *pucch, frame_t frame, @@ -371,7 +373,7 @@ void nr_ue_contention_resolution(module_id_t module_id, int cc_id, frame_t frame 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(module_id_t mod_id, frame_t frame, int slot); +void nr_ra_succeeded(const module_id_t mod_id, const uint8_t gNB_index, const frame_t frame, const int slot); void nr_get_RA_window(NR_UE_MAC_INST_t *mac); @@ -441,9 +443,11 @@ static uint8_t nr_extract_dci_info(NR_UE_MAC_INST_t *mac, uint16_t rnti, int ss_type, uint64_t *dci_pdu, - dci_pdu_rel15_t *dci_pdu_rel15); + dci_pdu_rel15_t *dci_pdu_rel15, + int slot); fapi_nr_ul_config_request_t *get_ul_config_request(NR_UE_MAC_INST_t *mac, int slot); +fapi_nr_dl_config_request_t *get_dl_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); diff --git a/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c b/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c index 7fb2295f2d..31c665524e 100644 --- a/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c +++ b/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c @@ -38,7 +38,7 @@ #include "openair2/LAYER2/nr_pdcp/nr_pdcp_entity.h" #include "executables/softmodem-common.h" #include "openair2/LAYER2/nr_pdcp/nr_pdcp.h" -#include "openair2/LAYER2/PDCP_v10.1.0/pdcp.h" +#include "openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.h" #include static NR_UE_MAC_INST_t *nr_ue_mac_inst; @@ -55,6 +55,7 @@ NR_UE_MAC_INST_t * nr_l2_init_ue(NR_UE_RRC_INST_t* rrc_inst) { nr_ue_mac_inst->sib1_decoded = false; nr_ue_mac_inst->phy_config_request_sent = false; nr_ue_mac_inst->state = UE_NOT_SYNC; + memset(&nr_ue_mac_inst->ssb_measurements, 0, sizeof(nr_ue_mac_inst->ssb_measurements)); for (int j=0;jscell_group_config); AssertFatal(rlc_module_init(0) == 0, "%s: Could not initialize RLC layer\n", __FUNCTION__); if (IS_SOFTMODEM_NOS1){ - pdcp_layer_init(); + nr_pdcp_layer_init(); nr_DRB_preconfiguration(nr_ue_mac_inst->crnti); nr_ue_mac_inst->logicalChannelBearer_exist[0] = true; } diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c index c5800cfe14..cfc8be87c9 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c @@ -124,7 +124,7 @@ int16_t get_prach_tx_power(module_id_t mod_id) { NR_UE_MAC_INST_t *mac = get_mac_inst(mod_id); RA_config_t *ra = &mac->ra; - int16_t pathloss = compute_nr_SSB_PL(mac, mac->phy_measurements.ssb_rsrp_dBm); + int16_t pathloss = compute_nr_SSB_PL(mac, mac->ssb_measurements.ssb_rsrp_dBm); int16_t ra_preamble_rx_power = (int16_t)(ra->prach_resources.ra_PREAMBLE_RECEIVED_TARGET_POWER - pathloss + 30); return min(nr_get_Pcmax(mod_id), ra_preamble_rx_power); @@ -674,7 +674,7 @@ void nr_get_prach_resources(module_id_t mod_id, } else { /* TODO: This controls the tx_power of UE and the ramping procedure of RA of UE. Later we can abstract this, perhaps in the proxy. But for the time being lets leave it as below. */ - int16_t dl_pathloss = !get_softmodem_params()->emulate_l1 ? compute_nr_SSB_PL(mac, mac->phy_measurements.ssb_rsrp_dBm) : 0; + int16_t dl_pathloss = !get_softmodem_params()->emulate_l1 ? compute_nr_SSB_PL(mac, mac->ssb_measurements.ssb_rsrp_dBm) : 0; ssb_rach_config(ra, prach_resources, nr_rach_ConfigCommon); ra_preambles_config(prach_resources, mac, dl_pathloss); LOG_D(MAC, "[RAPROC] - Selected RA preamble index %d for contention-based random access procedure... \n", ra->ra_PreambleIndex); @@ -886,7 +886,7 @@ uint8_t nr_ue_get_rach(module_id_t mod_id, if(ra->cfra) { // Reset RA_active flag: it disables Msg3 retransmission (8.3 of TS 38.213) - nr_ra_succeeded(mod_id, frame, nr_slot_tx); + nr_ra_succeeded(mod_id, gNB_id, frame, nr_slot_tx); } } else if (ra->RA_window_cnt == 0 && !ra->RA_RAPID_found) { @@ -1001,13 +1001,14 @@ void nr_ue_contention_resolution(module_id_t module_id, int cc_id, frame_t frame // 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){ - +void nr_ra_succeeded(const module_id_t mod_id, const uint8_t gNB_index, const frame_t frame, const 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); + nr_rrc_RA_succeeded(mod_id, gNB_index); mac->state = UE_CONNECTED; ra->RA_window_cnt = -1; } else { 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 e5b246f5c1..5aa4438af0 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_dci_configuration.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_dci_configuration.c @@ -172,7 +172,7 @@ void config_dci_pdu(NR_UE_MAC_INST_t *mac, fapi_nr_dl_config_dci_dl_pdu_rel15_t rel15->dci_length_options[i] = nr_dci_size(current_DL_BWP, current_UL_BWP, mac->cg, - &mac->def_dci_pdu_rel15[dci_format], + &mac->def_dci_pdu_rel15[dl_config->slot][dci_format], dci_format, NR_RNTI_TC, coreset, @@ -269,7 +269,7 @@ void ue_dci_configuration(NR_UE_MAC_INST_t *mac, fapi_nr_dl_config_request_t *dl uint8_t bwp_id = mac->current_DL_BWP.bwp_id; //NR_ServingCellConfig_t *scd = mac->scg->spCellConfig->spCellConfigDedicated; NR_BWP_DownlinkDedicated_t *bwpd = (bwp_id>0) ? mac->DLbwp[bwp_id-1]->bwp_Dedicated : (mac->cg ? mac->cg->spCellConfig->spCellConfigDedicated->initialDownlinkBWP : NULL); - NR_BWP_DownlinkCommon_t *bwp_Common = (bwp_id>0) ? mac->DLbwp[bwp_id-1]->bwp_Common : &mac->scc_SIB->downlinkConfigCommon.initialDownlinkBWP; + NR_BWP_DownlinkCommon_t *bwp_Common = get_bwp_downlink_common(mac, bwp_id); LOG_D(NR_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); diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c index 4190331a3e..9542e19514 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c @@ -238,6 +238,8 @@ int8_t nr_ue_decode_mib(module_id_t module_id, AssertFatal(mac->mib != NULL, "nr_ue_decode_mib() mac->mib == NULL\n"); + mac->ssb_measurements.consecutive_bch_failures = 0; // resetting decoding failures + uint16_t frame = (mac->mib->systemFrameNumber.buf[0] >> mac->mib->systemFrameNumber.bits_unused); uint16_t frame_number_4lsb = 0; @@ -316,9 +318,6 @@ int8_t nr_ue_decode_mib(module_id_t module_id, mac->first_sync_frame = frame; } - mac->dl_config_request.sfn = frame; - mac->dl_config_request.slot = ssb_start_symbol/14; - if(get_softmodem_params()->phy_test) mac->state = UE_CONNECTED; else if(mac->state == UE_NOT_SYNC) @@ -419,15 +418,15 @@ int8_t nr_ue_process_dci_freq_dom_resource_assignment(nfapi_nr_ue_pusch_pdu_t *p 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) { NR_UE_MAC_INST_t *mac = get_mac_inst(module_id); - dci_pdu_rel15_t *def_dci_pdu_rel15 = &mac->def_dci_pdu_rel15[dci->dci_format]; + dci_pdu_rel15_t *def_dci_pdu_rel15 = &mac->def_dci_pdu_rel15[slot][dci->dci_format]; LOG_D(MAC,"Received dci indication (rnti %x,dci format %d,n_CCE %d,payloadSize %d,payload %llx)\n", dci->rnti,dci->dci_format,dci->n_CCE,dci->payloadSize,*(unsigned long long*)dci->payloadBits); - int8_t ret = nr_extract_dci_info(mac, dci->dci_format, dci->payloadSize, dci->rnti, dci->ss_type, (uint64_t *)dci->payloadBits, def_dci_pdu_rel15); + int8_t ret = nr_extract_dci_info(mac, dci->dci_format, dci->payloadSize, dci->rnti, dci->ss_type, (uint64_t *)dci->payloadBits, def_dci_pdu_rel15, slot); if ((ret&1) == 1) return -1; else if (ret == 2) { dci->dci_format = NR_UL_DCI_FORMAT_0_0; - def_dci_pdu_rel15 = &mac->def_dci_pdu_rel15[dci->dci_format]; + def_dci_pdu_rel15 = &mac->def_dci_pdu_rel15[slot][dci->dci_format]; } int8_t ret_proc = nr_ue_process_dci(module_id, cc_id, gNB_index, frame, slot, def_dci_pdu_rel15, dci); return ret_proc; @@ -445,7 +444,7 @@ int8_t nr_ue_process_dci(module_id_t module_id, int cc_id, uint8_t gNB_index, fr 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_dl_config_request_t *dl_config = get_dl_config_request(mac, slot); uint8_t is_Msg3 = 0; NR_UE_DL_BWP_t *current_DL_BWP = &mac->current_DL_BWP; NR_UE_UL_BWP_t *current_UL_BWP = &mac->current_UL_BWP; @@ -541,6 +540,11 @@ int8_t nr_ue_process_dci(module_id_t module_id, int cc_id, uint8_t gNB_index, fr // - SECOND_DAI // - SRS_RESOURCE_IND + /* SRS_REQUEST */ + AssertFatal(dci->srs_request.nbits == 2, "If SUL is supported in the cell, there is an additional bit in SRS request field\n"); + if(dci->srs_request.val > 0) + nr_ue_aperiodic_srs_scheduling(mac, dci->srs_request.val, frame, slot); + // Schedule PUSCH tda_info = get_ul_tda_info(current_UL_BWP, coreset_type, dci_ind->ss_type, get_rnti_type(mac, rnti), dci->time_domain_assignment.val); if (tda_info.nrOfSymbols == 0) @@ -686,7 +690,7 @@ int8_t nr_ue_process_dci(module_id_t module_id, int cc_id, uint8_t gNB_index, fr /* dmrs symbol positions*/ dlsch_config_pdu_1_0->dlDmrsSymbPos = fill_dmrs_mask(pdsch_config, NR_DL_DCI_FORMAT_1_0, - (get_softmodem_params()->nsa) ? mac->scc->dmrs_TypeA_Position : mac->mib->dmrs_TypeA_Position, + mac->scc ? mac->scc->dmrs_TypeA_Position : mac->mib->dmrs_TypeA_Position, dlsch_config_pdu_1_0->number_symbols, dlsch_config_pdu_1_0->start_symbol, tda_info.mapping_type, @@ -809,6 +813,8 @@ int8_t nr_ue_process_dci(module_id_t module_id, int cc_id, uint8_t gNB_index, fr dlsch_config_pdu_1_0->accumulated_delta_PUCCH, dci->pucch_resource_indicator, 1+dci->pdsch_to_harq_feedback_timing_indicator.val); + + dlsch_config_pdu_1_0->k1_feedback = 1+dci->pdsch_to_harq_feedback_timing_indicator.val; LOG_D(MAC,"(nr_ue_procedures.c) pdu_type=%d\n\n",dl_config->dl_config_list[dl_config->number_pdus].pdu_type); @@ -1071,14 +1077,15 @@ int8_t nr_ue_process_dci(module_id_t module_id, int cc_id, uint8_t gNB_index, fr dlsch_config_pdu_1_1->n_front_load_symb); /* TCI */ - if (mac->dl_config_request.dl_config_list[0].dci_config_pdu.dci_config_rel15.coreset.tci_present_in_dci == 1){ + if (dl_config->dl_config_list[dl_config->number_pdus].dci_config_pdu.dci_config_rel15.coreset.tci_present_in_dci == 1){ // 0 bit if higher layer parameter tci-PresentInDCI is not enabled // otherwise 3 bits as defined in Subclause 5.1.5 of [6, TS38.214] dlsch_config_pdu_1_1->tci_state = dci->transmission_configuration_indication.val; } /* SRS_REQUEST */ - // if SUL is supported in the cell, there is an additional bit in this field and the value of this bit represents table 7.1.1.1-1 TS 38.212 FIXME!!! - dlsch_config_pdu_1_1->srs_config.aperiodicSRS_ResourceTrigger = (dci->srs_request.val & 0x11); // as per Table 7.3.1.1.2-24 TS 38.212 + AssertFatal(dci->srs_request.nbits == 2, "If SUL is supported in the cell, there is an additional bit in SRS request field\n"); + if(dci->srs_request.val > 0 ) + nr_ue_aperiodic_srs_scheduling(mac, dci->srs_request.val, frame, slot); /* CBGTI */ dlsch_config_pdu_1_1->cbgti = dci->cbgti.val; /* CBGFI */ @@ -1106,6 +1113,10 @@ int8_t nr_ue_process_dci(module_id_t module_id, int cc_id, uint8_t gNB_index, fr LOG_D(MAC,"(nr_ue_procedures.c) pdu_type=%d\n\n",dl_config->dl_config_list[dl_config->number_pdus].pdu_type); dl_config->number_pdus = dl_config->number_pdus + 1; + + // send the ack/nack slot number to phy to indicate tx thread to wait for DLSCH decoding + dlsch_config_pdu_1_1->k1_feedback = feedback_ti; + /* 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; dlsch_config_pdu_1_1->qamModOrder = nr_get_Qm_dl(dlsch_config_pdu_1_1->mcs, dlsch_config_pdu_1_1->mcs_table); @@ -1208,14 +1219,12 @@ void set_harq_status(NR_UE_MAC_INST_t *mac, // FIXME k0 != 0 currently not taken into consideration current_harq->dl_frame = frame; current_harq->dl_slot = slot; - if (get_softmodem_params()->emulate_l1) { - int scs = get_softmodem_params()->numerology; - int slots_per_frame = nr_slots_per_frame[scs]; - slot += data_toul_fb; - if (slot >= slots_per_frame) { - frame = (frame + 1) % 1024; - slot %= slots_per_frame; - } + int scs = get_softmodem_params()->numerology; + int slots_per_frame = nr_slots_per_frame[scs]; + slot += data_toul_fb; + if (slot >= slots_per_frame) { + frame = (frame + 1) % 1024; + slot %= slots_per_frame; } LOG_D(NR_PHY,"Setting harq_status for harq_id %d, dl %d.%d, sched ul %d.%d\n", @@ -1564,7 +1573,7 @@ int16_t get_pucch_tx_power_ue(NR_UE_MAC_INST_t *mac, return (PUCCH_POWER_DEFAULT); } - int16_t pathloss = compute_nr_SSB_PL(mac, mac->phy_measurements.ssb_rsrp_dBm); + int16_t pathloss = compute_nr_SSB_PL(mac, mac->ssb_measurements.ssb_rsrp_dBm); int M_pucch_component = (10 * log10((double)(pow(2,scs) * nb_of_prbs))); int16_t pucch_power = P_O_PUCCH + M_pucch_component + pathloss + delta_F_PUCCH + DELTA_TF + G_b_f_c; @@ -1820,10 +1829,14 @@ uint8_t get_downlink_ack(NR_UE_MAC_INST_t *mac, } number_harq_feedback++; - if (current_harq->ack_received) + if (current_harq->ack_received) { ack_data[code_word][dai_current - 1] = current_harq->ack; - else + current_harq->active = false; + current_harq->ack_received = false; + } else { + LOG_W(NR_MAC, "DLSCH ACK/NACK reporting initiated for harq pid %d before DLSCH decoding completed\n", dl_harq_pid); ack_data[code_word][dai_current - 1] = 0; + } dai[code_word][dai_current - 1] = dai_current; pucch->resource_indicator = current_harq->pucch_resource_indicator; @@ -1831,9 +1844,7 @@ uint8_t get_downlink_ack(NR_UE_MAC_INST_t *mac, pucch->N_CCE = current_harq->N_CCE; pucch->delta_pucch = current_harq->delta_pucch; pucch->is_common = current_harq->is_common; - current_harq->active = false; - current_harq->ack_received = false; - LOG_D(PHY,"%4d.%2d Sent %d ack on harq pid %d\n", frame, slot, current_harq->ack, dl_harq_pid); + LOG_D(PHY,"%4d.%2d Sent %d ack on harq pid %d\n", frame, slot, current_harq->ack, dl_harq_pid); } } } @@ -2179,7 +2190,7 @@ uint8_t get_ssb_rsrp_payload(NR_UE_MAC_INST_t *mac, } } AssertFatal(*SSB_resource.list.array[ssb_rsrp[0][0]] == mac->mib_ssb, "Couldn't find corresponding SSB in csi_SSB_ResourceList\n"); - ssb_rsrp[1][0] = mac->phy_measurements.ssb_rsrp_dBm; + ssb_rsrp[1][0] = mac->ssb_measurements.ssb_rsrp_dBm; uint8_t ssbi; @@ -2398,7 +2409,8 @@ static uint8_t nr_extract_dci_info(NR_UE_MAC_INST_t *mac, uint16_t rnti, int ss_type, uint64_t *dci_pdu, - dci_pdu_rel15_t *dci_pdu_rel15) + dci_pdu_rel15_t *dci_pdu_rel15, + int slot) { int pos = 0; @@ -2421,6 +2433,7 @@ static uint8_t nr_extract_dci_info(NR_UE_MAC_INST_t *mac, switch(dci_format) { case NR_DL_DCI_FORMAT_1_0: + switch(rnti_type) { case NR_RNTI_RA: // Freq domain assignment @@ -2465,8 +2478,8 @@ static uint8_t nr_extract_dci_info(NR_UE_MAC_INST_t *mac, //switch to DCI_0_0 if (dci_pdu_rel15->format_indicator == 0) { - dci_pdu_rel15 = &mac->def_dci_pdu_rel15[NR_UL_DCI_FORMAT_0_0]; - return 2+nr_extract_dci_info(mac, NR_UL_DCI_FORMAT_0_0, dci_size, rnti, ss_type, dci_pdu, dci_pdu_rel15); + dci_pdu_rel15 = &mac->def_dci_pdu_rel15[slot][NR_UL_DCI_FORMAT_0_0]; + return 2+nr_extract_dci_info(mac, NR_UL_DCI_FORMAT_0_0, dci_size, rnti, ss_type, dci_pdu, dci_pdu_rel15, slot); } #ifdef DEBUG_EXTRACT_DCI 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); @@ -2656,13 +2669,10 @@ static uint8_t nr_extract_dci_info(NR_UE_MAC_INST_t *mac, //switch to DCI_0_0 if (dci_pdu_rel15->format_indicator == 0) { - dci_pdu_rel15 = &mac->def_dci_pdu_rel15[NR_UL_DCI_FORMAT_0_0]; - return 2+nr_extract_dci_info(mac, NR_UL_DCI_FORMAT_0_0, dci_size, rnti, ss_type, dci_pdu, dci_pdu_rel15); + dci_pdu_rel15 = &mac->def_dci_pdu_rel15[slot][NR_UL_DCI_FORMAT_0_0]; + return 2+nr_extract_dci_info(mac, NR_UL_DCI_FORMAT_0_0, dci_size, rnti, ss_type, dci_pdu, dci_pdu_rel15, slot); } - if (dci_pdu_rel15->format_indicator == 0) - return 1; // discard dci, format indicator not corresponding to dci_format - // Freq domain assignment 0-16 bit fsize = (int)ceil(log2((N_RB * (N_RB + 1)) >> 1)); pos+=fsize; @@ -3256,7 +3266,7 @@ void nr_ue_process_mac_pdu(nr_downlink_indication_t *dl_info, } if ( (ra->RA_active == 1) && ra_success) { - nr_ra_succeeded(module_idP, frameP, slot); + nr_ra_succeeded(module_idP, gNB_index, frameP, slot); } else if (!ra_success){ // TODO: Handle failure of RA procedure @ MAC layer // nr_ra_failed(module_idP, CC_id, prach_resources, frameP, slot); // prach_resources is a PHY structure @@ -3274,41 +3284,26 @@ void nr_ue_process_mac_pdu(nr_downlink_indication_t *dl_info, // check if LCID is valid at current time. case DL_SCH_LCID_DCCH1: // check if LCID is valid at current time. + case DL_SCH_LCID_DTCH ... (DL_SCH_LCID_DTCH + 28): + if (!get_mac_len(pduP, pdu_len, &mac_len, &mac_subheader_len)) + return; + LOG_D(NR_MAC, "%4d.%2d : DLSCH -> LCID %d %d bytes\n", frameP, slot, rx_lcid, mac_len); + + mac_rlc_data_ind(module_idP, + mac->crnti, + gNB_index, + frameP, + ENB_FLAG_NO, + MBMS_FLAG_NO, + rx_lcid, + (char *)(pduP + mac_subheader_len), + mac_len, + 1, + NULL); + break; default: - { - if (!get_mac_len(pduP, pdu_len, &mac_len, &mac_subheader_len)) - return; - LOG_D(NR_MAC, "[UE %d] %4d.%2d : DLSCH -> DL-DTCH %d (gNB %d, %d bytes)\n", module_idP, frameP, slot, rx_lcid, gNB_index, mac_len); - - #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++) - LOG_T(MAC, "%x.", (pduP + mac_subheader_len)[i]); - - LOG_T(MAC, "\n"); - #endif - - if (rx_lcid < NB_RB_MAX && rx_lcid >= DL_SCH_LCID_DCCH) { - - mac_rlc_data_ind(module_idP, - mac->crnti, - gNB_index, - frameP, - ENB_FLAG_NO, - MBMS_FLAG_NO, - rx_lcid, - (char *) (pduP + mac_subheader_len), - mac_len, - 1, - NULL); - } else { - LOG_E(MAC, "[UE %d] Frame %d : unknown LCID %d (gNB %d)\n", module_idP, frameP, rx_lcid, gNB_index); - } - - - break; - } + LOG_W(MAC, "unknown lcid %02x\n", rx_lcid); + break; } pduP += ( mac_subheader_len + mac_len ); pdu_len -= ( mac_subheader_len + mac_len ); diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c index deeb4a181a..a3f4d06b1c 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c @@ -112,11 +112,8 @@ fapi_nr_ul_config_request_t *get_ul_config_request(NR_UE_MAC_INST_t *mac, int sl NR_TDD_UL_DL_ConfigCommon_t *tdd_config = mac->scc==NULL ? mac->scc_SIB->tdd_UL_DL_ConfigurationCommon : mac->scc->tdd_UL_DL_ConfigurationCommon; - //Check if request to access ul_config is for a UL slot - if (is_nr_UL_slot(tdd_config, slot, mac->frame_type) == 0) { - LOG_W(NR_MAC, "Slot %d is not a UL slot. %s called for wrong slot!!!\n", slot, __FUNCTION__); - return NULL; - } + //Check if requested on the right slot + AssertFatal(is_nr_UL_slot(tdd_config, slot, mac->frame_type) != 0, "%s called at wrong slot %d\n", __func__, slot); // 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 @@ -127,16 +124,57 @@ fapi_nr_ul_config_request_t *get_ul_config_request(NR_UE_MAC_INST_t *mac, int sl const int num_slots_ul = tdd_config ? (tdd_config->pattern1.nrofUplinkSlots + (tdd_config->pattern1.nrofUplinkSymbols != 0)) : n; int index = slot % num_slots_ul; - LOG_D(NR_MAC, "In %s slots per %s: %d, num_slots_ul %d, index %d\n", + LOG_D(NR_MAC, "In %s slots per %s: %d, num_slots %d, index %d\n", __FUNCTION__, tdd_config ? "TDD" : "FDD", num_slots_per_tdd, num_slots_ul, index); - if(!mac->ul_config_request) + if (mac->ul_config_request) return &mac->ul_config_request[index]; + else { + LOG_E(NR_MAC, "mac->ul_config_request not set\n"); return NULL; - return &mac->ul_config_request[index]; + } +} + +/* + * This function returns the DL config corresponding to a given DL slot + * from MAC instance . + */ +fapi_nr_dl_config_request_t *get_dl_config_request(NR_UE_MAC_INST_t *mac, int slot) +{ + int index; + if (!mac->scc && !mac->scc_SIB) + index = 0; + else { + NR_TDD_UL_DL_ConfigCommon_t *tdd_config = mac->scc==NULL ? mac->scc_SIB->tdd_UL_DL_ConfigurationCommon : mac->scc->tdd_UL_DL_ConfigurationCommon; + + //Check if requested on the right slot + AssertFatal(is_nr_DL_slot(tdd_config, slot) != 0, "%s called at wrong slot %d\n", __func__, slot); + + // Calculate the index of the DL slot in mac->ul_config_request list. This is + // based on the TDD pattern (slot configuration period) and number of DL+mixed + // slots in the period. TS 38.213 Sec 11.1 + int mu = mac->current_UL_BWP.scs; + const int n = nr_slots_per_frame[mu]; + const int num_slots_per_tdd = tdd_config ? (n >> (7 - tdd_config->pattern1.dl_UL_TransmissionPeriodicity)) : n; + const int num_slots_dl = tdd_config ? (tdd_config->pattern1.nrofDownlinkSlots + (tdd_config->pattern1.nrofDownlinkSymbols != 0)) : n; + + index = slot % num_slots_dl; + LOG_D(NR_MAC, "In %s slots per %s: %d, num_slots %d, index %d\n", + __FUNCTION__, + tdd_config ? "TDD" : "FDD", + num_slots_per_tdd, + num_slots_dl, + index); + } + + if (mac->dl_config_request) return &mac->dl_config_request[index]; + else { + LOG_E(NR_MAC, "mac->dl_config_request not set\n"); + return NULL; + } } void ul_layers_config(NR_UE_MAC_INST_t *mac, nfapi_nr_ue_pusch_pdu_t *pusch_config_pdu, dci_pdu_rel15_t *dci, nr_dci_format_t dci_format) @@ -495,7 +533,7 @@ int nr_config_pusch_pdu(NR_UE_MAC_INST_t *mac, #ifdef DEBUG_MSG3 LOG_D(NR_MAC, "In %s BWP assignment (BWP (start %d, size %d) \n", __FUNCTION__, pusch_config_pdu->bwp_start, pusch_config_pdu->bwp_size); - #endif +#endif // MCS pusch_config_pdu->mcs_index = rar_grant->mcs; @@ -763,6 +801,140 @@ int nr_config_pusch_pdu(NR_UE_MAC_INST_t *mac, } +void configure_srs_pdu(NR_UE_MAC_INST_t *mac, + NR_SRS_Resource_t *srs_resource, + fapi_nr_ul_config_srs_pdu *srs_config_pdu, + int period, int offset) +{ + NR_UE_UL_BWP_t *current_UL_BWP = &mac->current_UL_BWP; + + srs_config_pdu->rnti = mac->crnti; + srs_config_pdu->handle = 0; + srs_config_pdu->bwp_size = current_UL_BWP->BWPSize; + srs_config_pdu->bwp_start = current_UL_BWP->BWPStart; + srs_config_pdu->subcarrier_spacing = current_UL_BWP->scs; + srs_config_pdu->cyclic_prefix = 0; + srs_config_pdu->num_ant_ports = srs_resource->nrofSRS_Ports; + srs_config_pdu->num_symbols = srs_resource->resourceMapping.nrofSymbols; + srs_config_pdu->num_repetitions = srs_resource->resourceMapping.repetitionFactor; + srs_config_pdu->time_start_position = srs_resource->resourceMapping.startPosition; + srs_config_pdu->config_index = srs_resource->freqHopping.c_SRS; + srs_config_pdu->sequence_id = srs_resource->sequenceId; + srs_config_pdu->bandwidth_index = srs_resource->freqHopping.b_SRS; + srs_config_pdu->comb_size = srs_resource->transmissionComb.present - 1; + + switch(srs_resource->transmissionComb.present) { + case NR_SRS_Resource__transmissionComb_PR_n2: + srs_config_pdu->comb_offset = srs_resource->transmissionComb.choice.n2->combOffset_n2; + srs_config_pdu->cyclic_shift = srs_resource->transmissionComb.choice.n2->cyclicShift_n2; + break; + case NR_SRS_Resource__transmissionComb_PR_n4: + srs_config_pdu->comb_offset = srs_resource->transmissionComb.choice.n4->combOffset_n4; + srs_config_pdu->cyclic_shift = srs_resource->transmissionComb.choice.n4->cyclicShift_n4; + break; + default: + LOG_W(NR_MAC, "Invalid or not implemented comb_size!\n"); + } + + srs_config_pdu->frequency_position = srs_resource->freqDomainPosition; + srs_config_pdu->frequency_shift = srs_resource->freqDomainShift; + srs_config_pdu->frequency_hopping = srs_resource->freqHopping.b_hop; + srs_config_pdu->group_or_sequence_hopping = srs_resource->groupOrSequenceHopping; + srs_config_pdu->resource_type = srs_resource->resourceType.present - 1; + if(srs_config_pdu->resource_type > 0) { // not aperiodic + srs_config_pdu->t_srs = period; + srs_config_pdu->t_offset = offset; + } + +#ifdef SRS_DEBUG + LOG_I(NR_MAC,"Frame = %i, slot = %i\n", frame, slot); + LOG_I(NR_MAC,"srs_config_pdu->rnti = 0x%04x\n", srs_config_pdu->rnti); + LOG_I(NR_MAC,"srs_config_pdu->handle = %u\n", srs_config_pdu->handle); + LOG_I(NR_MAC,"srs_config_pdu->bwp_size = %u\n", srs_config_pdu->bwp_size); + LOG_I(NR_MAC,"srs_config_pdu->bwp_start = %u\n", srs_config_pdu->bwp_start); + LOG_I(NR_MAC,"srs_config_pdu->subcarrier_spacing = %u\n", srs_config_pdu->subcarrier_spacing); + LOG_I(NR_MAC,"srs_config_pdu->cyclic_prefix = %u (0: Normal; 1: Extended)\n", srs_config_pdu->cyclic_prefix); + LOG_I(NR_MAC,"srs_config_pdu->num_ant_ports = %u (0 = 1 port, 1 = 2 ports, 2 = 4 ports)\n", srs_config_pdu->num_ant_ports); + LOG_I(NR_MAC,"srs_config_pdu->num_symbols = %u (0 = 1 symbol, 1 = 2 symbols, 2 = 4 symbols)\n", srs_config_pdu->num_symbols); + LOG_I(NR_MAC,"srs_config_pdu->num_repetitions = %u (0 = 1, 1 = 2, 2 = 4)\n", srs_config_pdu->num_repetitions); + LOG_I(NR_MAC,"srs_config_pdu->time_start_position = %u\n", srs_config_pdu->time_start_position); + LOG_I(NR_MAC,"srs_config_pdu->config_index = %u\n", srs_config_pdu->config_index); + LOG_I(NR_MAC,"srs_config_pdu->sequence_id = %u\n", srs_config_pdu->sequence_id); + LOG_I(NR_MAC,"srs_config_pdu->bandwidth_index = %u\n", srs_config_pdu->bandwidth_index); + LOG_I(NR_MAC,"srs_config_pdu->comb_size = %u (0 = comb size 2, 1 = comb size 4, 2 = comb size 8)\n", srs_config_pdu->comb_size); + LOG_I(NR_MAC,"srs_config_pdu->comb_offset = %u\n", srs_config_pdu->comb_offset); + LOG_I(NR_MAC,"srs_config_pdu->cyclic_shift = %u\n", srs_config_pdu->cyclic_shift); + LOG_I(NR_MAC,"srs_config_pdu->frequency_position = %u\n", srs_config_pdu->frequency_position); + LOG_I(NR_MAC,"srs_config_pdu->frequency_shift = %u\n", srs_config_pdu->frequency_shift); + LOG_I(NR_MAC,"srs_config_pdu->frequency_hopping = %u\n", srs_config_pdu->frequency_hopping); + LOG_I(NR_MAC,"srs_config_pdu->group_or_sequence_hopping = %u (0 = No hopping, 1 = Group hopping groupOrSequenceHopping, 2 = Sequence hopping)\n", srs_config_pdu->group_or_sequence_hopping); + LOG_I(NR_MAC,"srs_config_pdu->resource_type = %u (0: aperiodic, 1: semi-persistent, 2: periodic)\n", srs_config_pdu->resource_type); + LOG_I(NR_MAC,"srs_config_pdu->t_srs = %u\n", srs_config_pdu->t_srs); + LOG_I(NR_MAC,"srs_config_pdu->t_offset = %u\n", srs_config_pdu->t_offset); +#endif +} + +// Aperiodic SRS scheduling +void nr_ue_aperiodic_srs_scheduling(NR_UE_MAC_INST_t *mac, long resource_trigger, int frame, int slot) +{ + NR_UE_UL_BWP_t *current_UL_BWP = &mac->current_UL_BWP; + NR_SRS_Config_t *srs_config = current_UL_BWP->srs_Config; + + if (!srs_config) { + LOG_E(NR_MAC, "DCI is triggering aperiodic SRS but there is no SRS configuration\n"); + return; + } + + int slot_offset = 0; + NR_SRS_Resource_t *srs_resource = NULL; + for(int rs = 0; rs < srs_config->srs_ResourceSetToAddModList->list.count; rs++) { + + // Find aperiodic resource set + NR_SRS_ResourceSet_t *srs_resource_set = srs_config->srs_ResourceSetToAddModList->list.array[rs]; + if(srs_resource_set->resourceType.present != NR_SRS_ResourceSet__resourceType_PR_aperiodic) + continue; + // the resource trigger need to match the DCI one + if(srs_resource_set->resourceType.choice.aperiodic->aperiodicSRS_ResourceTrigger != resource_trigger) + continue; + // if slotOffset is null -> offset = 0 + if(srs_resource_set->resourceType.choice.aperiodic->slotOffset) + slot_offset = *srs_resource_set->resourceType.choice.aperiodic->slotOffset; + + // Find the corresponding srs resource + for(int r1 = 0; r1 < srs_resource_set->srs_ResourceIdList->list.count; r1++) { + for (int r2 = 0; r2 < srs_config->srs_ResourceToAddModList->list.count; r2++) { + if ((*srs_resource_set->srs_ResourceIdList->list.array[r1] == srs_config->srs_ResourceToAddModList->list.array[r2]->srs_ResourceId) && + (srs_config->srs_ResourceToAddModList->list.array[r2]->resourceType.present == NR_SRS_Resource__resourceType_PR_aperiodic)) { + srs_resource = srs_config->srs_ResourceToAddModList->list.array[r2]; + break; + } + } + } + } + + if(srs_resource == NULL) { + LOG_E(NR_MAC, "Couldn't find SRS aperiodic resource with trigger %ld\n", resource_trigger); + return; + } + + AssertFatal(slot_offset >= DURATION_RX_TO_TX,"Slot offset between DCI and aperiodic SRS (%d) cannot be less than DURATION_RX_TO_TX (%d)\n", + slot_offset, DURATION_RX_TO_TX); + int n_slots_frame = nr_slots_per_frame[current_UL_BWP->scs]; + int sched_slot = (slot + slot_offset) % n_slots_frame; + NR_TDD_UL_DL_ConfigCommon_t *tdd_config = mac->scc==NULL ? mac->scc_SIB->tdd_UL_DL_ConfigurationCommon : mac->scc->tdd_UL_DL_ConfigurationCommon; + if (!is_nr_UL_slot(tdd_config, sched_slot, mac->frame_type)) { + LOG_E(NR_MAC, "Slot for scheduling aperiodic SRS %d is not an UL slot\n", sched_slot); + return; + } + int sched_frame = frame + (slot + slot_offset >= n_slots_frame) % 1024; + + fapi_nr_ul_config_request_t *ul_config = get_ul_config_request(mac, sched_slot); + fapi_nr_ul_config_srs_pdu *srs_config_pdu = &ul_config->ul_config_list[ul_config->number_pdus].srs_config_pdu; + configure_srs_pdu(mac, srs_resource, srs_config_pdu, 0, 0); + fill_ul_config(ul_config, sched_frame, sched_slot, FAPI_NR_UL_CONFIG_TYPE_SRS); +} + + // Periodic SRS scheduling bool nr_ue_periodic_srs_scheduling(module_id_t mod_id, frame_t frame, slot_t slot) { @@ -812,68 +984,7 @@ bool nr_ue_periodic_srs_scheduling(module_id_t mod_id, frame_t frame, slot_t slo fapi_nr_ul_config_request_t *ul_config = get_ul_config_request(mac, slot); fapi_nr_ul_config_srs_pdu *srs_config_pdu = &ul_config->ul_config_list[ul_config->number_pdus].srs_config_pdu; - srs_config_pdu->rnti = mac->crnti; - srs_config_pdu->handle = 0; - srs_config_pdu->bwp_size = current_UL_BWP->BWPSize; - srs_config_pdu->bwp_start = current_UL_BWP->BWPStart; - srs_config_pdu->subcarrier_spacing = current_UL_BWP->scs; - srs_config_pdu->cyclic_prefix = 0; - srs_config_pdu->num_ant_ports = srs_resource->nrofSRS_Ports; - srs_config_pdu->num_symbols = srs_resource->resourceMapping.nrofSymbols; - srs_config_pdu->num_repetitions = srs_resource->resourceMapping.repetitionFactor; - srs_config_pdu->time_start_position = srs_resource->resourceMapping.startPosition; - srs_config_pdu->config_index = srs_resource->freqHopping.c_SRS; - srs_config_pdu->sequence_id = srs_resource->sequenceId; - srs_config_pdu->bandwidth_index = srs_resource->freqHopping.b_SRS; - srs_config_pdu->comb_size = srs_resource->transmissionComb.present - 1; - - switch(srs_resource->transmissionComb.present) { - case NR_SRS_Resource__transmissionComb_PR_n2: - srs_config_pdu->comb_offset = srs_resource->transmissionComb.choice.n2->combOffset_n2; - srs_config_pdu->cyclic_shift = srs_resource->transmissionComb.choice.n2->cyclicShift_n2; - break; - case NR_SRS_Resource__transmissionComb_PR_n4: - srs_config_pdu->comb_offset = srs_resource->transmissionComb.choice.n4->combOffset_n4; - srs_config_pdu->cyclic_shift = srs_resource->transmissionComb.choice.n4->cyclicShift_n4; - break; - default: - LOG_W(NR_MAC, "Invalid or not implemented comb_size!\n"); - } - - srs_config_pdu->frequency_position = srs_resource->freqDomainPosition; - srs_config_pdu->frequency_shift = srs_resource->freqDomainShift; - srs_config_pdu->frequency_hopping = srs_resource->freqHopping.b_hop; - srs_config_pdu->group_or_sequence_hopping = srs_resource->groupOrSequenceHopping; - srs_config_pdu->resource_type = srs_resource->resourceType.present - 1; - srs_config_pdu->t_srs = period; - srs_config_pdu->t_offset = offset; - -#ifdef SRS_DEBUG - LOG_I(NR_MAC,"Frame = %i, slot = %i\n", frame, slot); - LOG_I(NR_MAC,"srs_config_pdu->rnti = 0x%04x\n", srs_config_pdu->rnti); - LOG_I(NR_MAC,"srs_config_pdu->handle = %u\n", srs_config_pdu->handle); - LOG_I(NR_MAC,"srs_config_pdu->bwp_size = %u\n", srs_config_pdu->bwp_size); - LOG_I(NR_MAC,"srs_config_pdu->bwp_start = %u\n", srs_config_pdu->bwp_start); - LOG_I(NR_MAC,"srs_config_pdu->subcarrier_spacing = %u\n", srs_config_pdu->subcarrier_spacing); - LOG_I(NR_MAC,"srs_config_pdu->cyclic_prefix = %u (0: Normal; 1: Extended)\n", srs_config_pdu->cyclic_prefix); - LOG_I(NR_MAC,"srs_config_pdu->num_ant_ports = %u (0 = 1 port, 1 = 2 ports, 2 = 4 ports)\n", srs_config_pdu->num_ant_ports); - LOG_I(NR_MAC,"srs_config_pdu->num_symbols = %u (0 = 1 symbol, 1 = 2 symbols, 2 = 4 symbols)\n", srs_config_pdu->num_symbols); - LOG_I(NR_MAC,"srs_config_pdu->num_repetitions = %u (0 = 1, 1 = 2, 2 = 4)\n", srs_config_pdu->num_repetitions); - LOG_I(NR_MAC,"srs_config_pdu->time_start_position = %u\n", srs_config_pdu->time_start_position); - LOG_I(NR_MAC,"srs_config_pdu->config_index = %u\n", srs_config_pdu->config_index); - LOG_I(NR_MAC,"srs_config_pdu->sequence_id = %u\n", srs_config_pdu->sequence_id); - LOG_I(NR_MAC,"srs_config_pdu->bandwidth_index = %u\n", srs_config_pdu->bandwidth_index); - LOG_I(NR_MAC,"srs_config_pdu->comb_size = %u (0 = comb size 2, 1 = comb size 4, 2 = comb size 8)\n", srs_config_pdu->comb_size); - LOG_I(NR_MAC,"srs_config_pdu->comb_offset = %u\n", srs_config_pdu->comb_offset); - LOG_I(NR_MAC,"srs_config_pdu->cyclic_shift = %u\n", srs_config_pdu->cyclic_shift); - LOG_I(NR_MAC,"srs_config_pdu->frequency_position = %u\n", srs_config_pdu->frequency_position); - LOG_I(NR_MAC,"srs_config_pdu->frequency_shift = %u\n", srs_config_pdu->frequency_shift); - LOG_I(NR_MAC,"srs_config_pdu->frequency_hopping = %u\n", srs_config_pdu->frequency_hopping); - LOG_I(NR_MAC,"srs_config_pdu->group_or_sequence_hopping = %u (0 = No hopping, 1 = Group hopping groupOrSequenceHopping, 2 = Sequence hopping)\n", srs_config_pdu->group_or_sequence_hopping); - LOG_I(NR_MAC,"srs_config_pdu->resource_type = %u (0: aperiodic, 1: semi-persistent, 2: periodic)\n", srs_config_pdu->resource_type); - LOG_I(NR_MAC,"srs_config_pdu->t_srs = %u\n", srs_config_pdu->t_srs); - LOG_I(NR_MAC,"srs_config_pdu->t_offset = %u\n", srs_config_pdu->t_offset); -#endif + configure_srs_pdu(mac, srs_resource, srs_config_pdu, period, offset); fill_ul_config(ul_config, frame, slot, FAPI_NR_UL_CONFIG_TYPE_SRS); srs_scheduled = true; @@ -895,7 +1006,9 @@ void nr_ue_dl_scheduler(nr_downlink_indication_t *dl_info) 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; + fapi_nr_dl_config_request_t *dl_config = get_dl_config_request(mac, rx_slot); + dl_config->sfn = rx_frame; + dl_config->slot = rx_slot; nr_scheduled_response_t scheduled_response; nr_dcireq_t dcireq; @@ -909,11 +1022,11 @@ void nr_ue_dl_scheduler(nr_downlink_indication_t *dl_info) dcireq.slot = rx_slot; dcireq.dl_config_req.number_pdus = 0; nr_ue_dcireq(&dcireq); //to be replaced with function pointer later - mac->dl_config_request = dcireq.dl_config_req; + *dl_config = dcireq.dl_config_req; nr_schedule_csirs_reception(mac, rx_frame, rx_slot); nr_schedule_csi_for_im(mac, rx_frame, rx_slot); - dcireq.dl_config_req = mac->dl_config_request; + dcireq.dl_config_req = *dl_config; fill_scheduled_response(&scheduled_response, &dcireq.dl_config_req, NULL, NULL, mod_id, cc_id, rx_frame, rx_slot, dl_info->phy_data); if(mac->if_module != NULL && mac->if_module->scheduled_response != NULL) { @@ -1399,6 +1512,8 @@ int nr_ue_pusch_scheduler(NR_UE_MAC_INST_t *mac, uint8_t is_Msg3, frame_t curren case 3: delta = 6; break; + default: + AssertFatal(1 == 0, "Invalid numerology %i\n", mu); } AssertFatal((k2 + delta) >= DURATION_RX_TO_TX, @@ -2175,7 +2290,7 @@ void nr_schedule_csi_for_im(NR_UE_MAC_INST_t *mac, int frame, int slot) { if (csi_measconfig->csi_IM_ResourceToAddModList == NULL) return; - fapi_nr_dl_config_request_t *dl_config = &mac->dl_config_request; + fapi_nr_dl_config_request_t *dl_config = get_dl_config_request(mac, slot); NR_CSI_IM_Resource_t *imcsi; int period, offset; @@ -2229,7 +2344,7 @@ void nr_schedule_csirs_reception(NR_UE_MAC_INST_t *mac, int frame, int slot) { if (csi_measconfig->nzp_CSI_RS_ResourceToAddModList == NULL) return; - fapi_nr_dl_config_request_t *dl_config = &mac->dl_config_request; + fapi_nr_dl_config_request_t *dl_config = get_dl_config_request(mac, slot); NR_NZP_CSI_RS_Resource_t *nzpcsi; int period, offset; NR_UE_DL_BWP_t *current_DL_BWP = &mac->current_DL_BWP; @@ -2551,9 +2666,6 @@ void nr_ue_sib1_scheduler(module_id_t module_idP, NR_UE_MAC_INST_t *mac = get_mac_inst(module_idP); nr_scheduled_response_t scheduled_response; - int frame_s,slot_s; - fapi_nr_dl_config_request_t *dl_config = &mac->dl_config_request; - fapi_nr_dl_config_dci_dl_pdu_rel15_t *rel15; uint8_t scs_ssb = get_softmodem_params()->numerology; uint16_t ssb_offset_point_a = (ssb_start_subcarrier - ssb_subcarrier_offset)/12; @@ -2571,17 +2683,7 @@ void nr_ue_sib1_scheduler(module_id_t module_idP, 1, // If the UE is not configured with a periodicity, the UE assumes a periodicity of a half frame ssb_offset_point_a); - if(mac->search_space_zero == NULL) mac->search_space_zero=calloc(1,sizeof(*mac->search_space_zero)); - if(mac->coreset0 == NULL) mac->coreset0 = calloc(1,sizeof(*mac->coreset0)); - - fill_coresetZero(mac->coreset0, &mac->type0_PDCCH_CSS_config); - fill_searchSpaceZero(mac->search_space_zero, &mac->type0_PDCCH_CSS_config); - rel15 = &dl_config->dl_config_list[dl_config->number_pdus].dci_config_pdu.dci_config_rel15; - rel15->num_dci_options = 1; - rel15->dci_format_options[0] = NR_DL_DCI_FORMAT_1_0; - config_dci_pdu(mac, rel15, dl_config, NR_RNTI_SI, -1); - fill_dci_search_candidates(mac->search_space_zero, rel15, -1, -1); - + int frame_s,slot_s; if(mac->type0_PDCCH_CSS_config.type0_pdcch_ss_mux_pattern == 1){ // same frame as ssb if ((mac->type0_PDCCH_CSS_config.frame & 0x1) == mac->type0_PDCCH_CSS_config.sfn_c) @@ -2594,6 +2696,20 @@ void nr_ue_sib1_scheduler(module_id_t module_idP, frame_s = 0; // same frame as ssb slot_s = mac->type0_PDCCH_CSS_config.n_c; } + fapi_nr_dl_config_request_t *dl_config = &mac->dl_config_request[0]; // Take the first dl_config_request for SIB1 + fapi_nr_dl_config_dci_dl_pdu_rel15_t *rel15; + + if(mac->search_space_zero == NULL) mac->search_space_zero=calloc(1,sizeof(*mac->search_space_zero)); + if(mac->coreset0 == NULL) mac->coreset0 = calloc(1,sizeof(*mac->coreset0)); + + fill_coresetZero(mac->coreset0, &mac->type0_PDCCH_CSS_config); + fill_searchSpaceZero(mac->search_space_zero, &mac->type0_PDCCH_CSS_config); + rel15 = &dl_config->dl_config_list[dl_config->number_pdus].dci_config_pdu.dci_config_rel15; + rel15->num_dci_options = 1; + rel15->dci_format_options[0] = NR_DL_DCI_FORMAT_1_0; + config_dci_pdu(mac, rel15, dl_config, NR_RNTI_SI, -1); + fill_dci_search_candidates(mac->search_space_zero, rel15, -1, -1); + LOG_D(MAC,"Calling fill_scheduled_response, type0_pdcch, num_pdus %d\n",dl_config->number_pdus); fill_scheduled_response(&scheduled_response, dl_config, NULL, NULL, module_idP, cc_id, frame_s, slot_s, phy_data); diff --git a/openair2/LAYER2/NR_MAC_gNB/config.c b/openair2/LAYER2/NR_MAC_gNB/config.c index 38ae19c72a..3b6a6c2df8 100644 --- a/openair2/LAYER2/NR_MAC_gNB/config.c +++ b/openair2/LAYER2/NR_MAC_gNB/config.c @@ -455,6 +455,12 @@ int nr_mac_enable_ue_rrc_processing_timer(module_id_t Mod_idP, rnti_t rnti, NR_S sched_ctrl->rrc_processing_timer = (rrc_reconfiguration_delay<rnti, rrc_reconfiguration_delay); + // it might happen that timing advance command should be sent during the RRC + // processing timer. To prevent this, set a variable as if we would have just + // sent it. This way, another TA command will for sure be sent in some + // frames, after RRC processing timer. + sched_ctrl->ta_frame = (RC.nrmac[Mod_idP]->frame - 1 + 1024) % 1024; + return 0; } @@ -650,7 +656,58 @@ bool nr_mac_update_cellgroup(gNB_MAC_INST *nrmac, uint32_t rnti, NR_CellGroupCon exit(1); } + nr_mac_update_RA(nrmac, rnti, CellGroup); process_CellGroup(CellGroup, &UE->UE_sched_ctrl); return true; } + +bool nr_mac_update_RA(gNB_MAC_INST *nrmac, uint32_t rnti, NR_CellGroupConfig_t *CellGroup) +{ + // Checking for free RA process + NR_COMMON_channels_t *cc = &nrmac->common_channels[0]; + uint8_t ra_index = 0; + 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(NR_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]; + if (CellGroup->spCellConfig && CellGroup->spCellConfig->reconfigurationWithSync + && CellGroup->spCellConfig->reconfigurationWithSync->rach_ConfigDedicated != NULL) { + if (CellGroup->spCellConfig->reconfigurationWithSync->rach_ConfigDedicated->choice.uplink->cfra != NULL) { + ra->cfra = true; + ra->rnti = rnti; + ra->CellGroup = CellGroup; + struct NR_CFRA *cfra = CellGroup->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 < cc->num_active_ssb; i++) { + for (int j = 0; j < num_preamble; j++) { + if (cc->ssb_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; + } + } + } + } + } else { + ra->cfra = false; + ra->rnti = 0; + if (ra->preambles.preamble_list == NULL) { + ra->preambles.num_preambles = MAX_NUM_NR_PRACH_PREAMBLES; + ra->preambles.preamble_list = (uint8_t *)malloc(MAX_NUM_NR_PRACH_PREAMBLES * sizeof(uint8_t)); + for (int i = 0; i < MAX_NUM_NR_PRACH_PREAMBLES; i++) + ra->preambles.preamble_list[i] = i; + } + } + LOG_I(NR_MAC, "Added new %s process for UE RNTI %04x with initial CellGroup\n", ra->cfra ? "CFRA" : "CBRA", rnti); + + return true; +} diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c index c641bf4d15..c4ed4e2d2a 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c @@ -42,8 +42,7 @@ #include "RRC/NR/nr_rrc_extern.h" -//#include "LAYER2/MAC/pre_processor.c" -#include "pdcp.h" +#include "nr_pdcp/nr_pdcp_oai_api.h" #include "intertask_interface.h" @@ -57,10 +56,13 @@ const uint8_t nr_rv_round_map[4] = { 0, 2, 3, 1 }; uint16_t nr_pdcch_order_table[6] = { 31, 31, 511, 2047, 2047, 8191 }; -void clear_nr_nfapi_information(gNB_MAC_INST * gNB, +void clear_nr_nfapi_information(gNB_MAC_INST *gNB, int CC_idP, frame_t frameP, - sub_frame_t slotP) + sub_frame_t slotP, + nfapi_nr_dl_tti_request_t *DL_req, + nfapi_nr_tx_data_request_t *TX_req, + nfapi_nr_ul_dci_request_t *UL_dci_req) { NR_ServingCellConfigCommon_t *scc = gNB->common_channels->ServingCellConfigCommon; @@ -68,10 +70,7 @@ void clear_nr_nfapi_information(gNB_MAC_INST * gNB, UL_tti_req_ahead_initialization(gNB, scc, num_slots, CC_idP, frameP, slotP, *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_dci_request_t *UL_dci_req = &gNB->UL_dci_req[0]; - nfapi_nr_tx_data_request_t *TX_req = &gNB->TX_req[0]; gNB->pdu_index[CC_idP] = 0; @@ -97,23 +96,53 @@ void clear_nr_nfapi_information(gNB_MAC_INST * gNB, future_ul_tti_req->n_ulcch = 0; future_ul_tti_req->n_group = 0; - /* UL_tti_req is a simple pointer into the current UL_tti_req_ahead, i.e., - * it walks over UL_tti_req_ahead in a circular fashion */ - const int current_index = ul_buffer_index(frameP, slotP, *scc->ssbSubcarrierSpacing, gNB->UL_tti_req_ahead_size); - gNB->UL_tti_req[CC_idP] = &gNB->UL_tti_req_ahead[CC_idP][current_index]; TX_req[CC_idP].Number_of_PDUs = 0; - } bool is_xlsch_in_slot(uint64_t bitmap, sub_frame_t slot) { return (bitmap >> (slot % 64)) & 0x01; } -void gNB_dlsch_ulsch_scheduler(module_id_t module_idP, - frame_t frame, - sub_frame_t slot) +/* the structure nfapi_nr_ul_tti_request_t is very big, let's copy only what is necessary */ +static void copy_ul_tti_req(nfapi_nr_ul_tti_request_t *to, nfapi_nr_ul_tti_request_t *from) { + int i; + to->header = from->header; + to->SFN = from->SFN; + to->Slot = from->Slot; + to->n_pdus = from->n_pdus; + to->rach_present = from->rach_present; + to->n_ulsch = from->n_ulsch; + to->n_ulcch = from->n_ulcch; + to->n_group = from->n_group; + + for (i = 0; i < from->n_pdus; i++) { + to->pdus_list[i].pdu_type = from->pdus_list[i].pdu_type; + to->pdus_list[i].pdu_size = from->pdus_list[i].pdu_size; + + switch (from->pdus_list[i].pdu_type) { + case NFAPI_NR_UL_CONFIG_PRACH_PDU_TYPE: + to->pdus_list[i].prach_pdu = from->pdus_list[i].prach_pdu; + break; + case NFAPI_NR_UL_CONFIG_PUSCH_PDU_TYPE: + to->pdus_list[i].pusch_pdu = from->pdus_list[i].pusch_pdu; + break; + case NFAPI_NR_UL_CONFIG_PUCCH_PDU_TYPE: + to->pdus_list[i].pucch_pdu = from->pdus_list[i].pucch_pdu; + break; + case NFAPI_NR_UL_CONFIG_SRS_PDU_TYPE: + to->pdus_list[i].srs_pdu = from->pdus_list[i].srs_pdu; + break; + } + } + + for (i = 0; i < from->n_group; i++) + to->groups_list[i] = from->groups_list[i]; +} + +void gNB_dlsch_ulsch_scheduler(module_id_t module_idP, frame_t frame, sub_frame_t slot, NR_Sched_Rsp_t *sched_info) +{ protocol_ctxt_t ctxt = {0}; PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, module_idP, ENB_FLAG_YES, NOT_A_RNTI, frame, slot,module_idP); @@ -137,7 +166,6 @@ void gNB_dlsch_ulsch_scheduler(module_id_t module_idP, start_meas(&gNB->eNB_scheduler); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_gNB_DLSCH_ULSCH_SCHEDULER,VCD_FUNCTION_IN); - pdcp_run(&ctxt); /* send tick to RLC and RRC every ms */ if ((slot & ((1 << *scc->ssbSubcarrierSpacing) - 1)) == 0) { void nr_rlc_tick(int frame, int subframe); @@ -159,8 +187,7 @@ void gNB_dlsch_ulsch_scheduler(module_id_t module_idP, uint16_t *vrb_map_UL = cc[CC_id].vrb_map_UL; memcpy(&vrb_map_UL[prev_slot % size * MAX_BWP_SIZE], &gNB->ulprbbl, sizeof(uint16_t) * MAX_BWP_SIZE); - clear_nr_nfapi_information(gNB, CC_id, frame, slot); - + clear_nr_nfapi_information(gNB, CC_id, frame, slot, &sched_info->DL_req, &sched_info->TX_req, &sched_info->UL_dci_req); } if ((slot == 0) && (frame & 127) == 0) { @@ -174,12 +201,11 @@ void gNB_dlsch_ulsch_scheduler(module_id_t module_idP, schedule_nr_bwp_switch(module_idP, frame, slot); // This schedules MIB - schedule_nr_mib(module_idP, frame, slot); + schedule_nr_mib(module_idP, frame, slot, &sched_info->DL_req); // This schedules SIB1 if (get_softmodem_params()->sa == 1) - schedule_nr_sib1(module_idP, frame, slot); - + schedule_nr_sib1(module_idP, frame, slot, &sched_info->DL_req, &sched_info->TX_req); // This schedule PRACH if we are not in phy_test mode if (get_softmodem_params()->phy_test == 0) { @@ -196,7 +222,7 @@ void gNB_dlsch_ulsch_scheduler(module_id_t module_idP, } // Schedule CSI-RS transmission - nr_csirs_scheduling(module_idP, frame, slot, nr_slots_per_frame[*scc->ssbSubcarrierSpacing]); + nr_csirs_scheduling(module_idP, frame, slot, nr_slots_per_frame[*scc->ssbSubcarrierSpacing], &sched_info->DL_req); // Schedule CSI measurement reporting nr_csi_meas_reporting(module_idP, frame, slot); @@ -206,22 +232,29 @@ void gNB_dlsch_ulsch_scheduler(module_id_t module_idP, // This schedule RA procedure if not in phy_test mode // Otherwise consider 5G already connected if (get_softmodem_params()->phy_test == 0) { - nr_schedule_RA(module_idP, frame, slot); + nr_schedule_RA(module_idP, frame, slot, &sched_info->UL_dci_req, &sched_info->DL_req, &sched_info->TX_req); } // This schedules the DCI for Uplink and subsequently PUSCH - nr_schedule_ulsch(module_idP, frame, slot); + nr_schedule_ulsch(module_idP, frame, slot, &sched_info->UL_dci_req); // This schedules the DCI for Downlink and PDSCH start_meas(&gNB->schedule_dlsch); - nr_schedule_ue_spec(module_idP, frame, slot); + nr_schedule_ue_spec(module_idP, frame, slot, &sched_info->DL_req, &sched_info->TX_req); stop_meas(&gNB->schedule_dlsch); nr_sr_reporting(gNB, frame, slot); nr_schedule_pucch(gNB, frame, slot); + /* TODO: we copy from gNB->UL_tti_req_ahead[0][current_index], ie. CC_id == 0, + * is more than 1 CC supported? + */ + AssertFatal(MAX_NUM_CCs == 1, "only 1 CC supported\n"); + const int current_index = ul_buffer_index(frame, slot, *scc->ssbSubcarrierSpacing, gNB->UL_tti_req_ahead_size); + copy_ul_tti_req(&sched_info->UL_tti_req, &gNB->UL_tti_req_ahead[0][current_index]); + stop_meas(&gNB->eNB_scheduler); - + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_gNB_DLSCH_ULSCH_SCHEDULER,VCD_FUNCTION_OUT); } diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c index 2729ccc00a..d08d2fefb3 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c @@ -662,8 +662,13 @@ void nr_initiate_ra_proc(module_id_t module_idP, 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) { - +void nr_schedule_RA(module_id_t module_idP, + frame_t frameP, + sub_frame_t slotP, + nfapi_nr_ul_dci_request_t *ul_dci_req, + nfapi_nr_dl_tti_request_t *DL_req, + nfapi_nr_tx_data_request_t *TX_req) +{ gNB_MAC_INST *mac = RC.nrmac[module_idP]; start_meas(&mac->schedule_ra); @@ -674,15 +679,15 @@ void nr_schedule_RA(module_id_t module_idP, frame_t frameP, sub_frame_t slotP) { LOG_D(NR_MAC, "RA[state:%d]\n", ra->state); switch (ra->state) { case Msg2: - nr_generate_Msg2(module_idP, CC_id, frameP, slotP, ra); + nr_generate_Msg2(module_idP, CC_id, frameP, slotP, ra, DL_req, TX_req); break; case Msg3_retransmission: - nr_generate_Msg3_retransmission(module_idP, CC_id, frameP, slotP, ra); + nr_generate_Msg3_retransmission(module_idP, CC_id, frameP, slotP, ra, ul_dci_req); break; case Msg3_dcch_dtch: - nr_generate_Msg3_dcch_dtch_response(module_idP, CC_id, frameP, slotP, ra); + nr_generate_Msg3_dcch_dtch_response(module_idP, CC_id, frameP, slotP, ra, DL_req, TX_req); case Msg4: - nr_generate_Msg4(module_idP, CC_id, frameP, slotP, ra); + nr_generate_Msg4(module_idP, CC_id, frameP, slotP, ra, DL_req, TX_req); break; case WAIT_Msg4_ACK: nr_check_Msg4_Ack(module_idP, CC_id, frameP, slotP, ra); @@ -695,9 +700,13 @@ void nr_schedule_RA(module_id_t module_idP, frame_t frameP, sub_frame_t slotP) { stop_meas(&mac->schedule_ra); } - -void nr_generate_Msg3_retransmission(module_id_t module_idP, int CC_id, frame_t frame, sub_frame_t slot, NR_RA_t *ra) { - +void nr_generate_Msg3_retransmission(module_id_t module_idP, + int CC_id, + frame_t frame, + sub_frame_t slot, + NR_RA_t *ra, + nfapi_nr_ul_dci_request_t *ul_dci_req) +{ 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; @@ -784,8 +793,6 @@ void nr_generate_Msg3_retransmission(module_id_t module_idP, int CC_id, frame_t NR_ControlResourceSet_t *coreset = ra->coreset; AssertFatal(coreset!=NULL,"Coreset cannot be null for RA-Msg3 retransmission\n"); - nfapi_nr_ul_dci_request_t *ul_dci_req = &nr_mac->UL_dci_req[CC_id]; - const int coresetid = coreset->controlResourceSetId; nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu_rel15 = nr_mac->pdcch_pdu_idx[CC_id][coresetid]; if (!pdcch_pdu_rel15) { @@ -1148,8 +1155,14 @@ void nr_add_msg3(module_id_t module_idP, int CC_id, frame_t frameP, sub_frame_t nr_fill_rar(module_idP, ra, RAR_pdu, pusch_pdu); } -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_generate_Msg2(module_id_t module_idP, + int CC_id, + frame_t frameP, + sub_frame_t slotP, + NR_RA_t *ra, + nfapi_nr_dl_tti_request_t *DL_req, + nfapi_nr_tx_data_request_t *TX_req) +{ gNB_MAC_INST *nr_mac = RC.nrmac[module_idP]; NR_COMMON_channels_t *cc = &nr_mac->common_channels[CC_id]; NR_UE_DL_BWP_t *dl_bwp = &ra->DL_BWP; @@ -1198,7 +1211,7 @@ void nr_generate_Msg2(module_id_t module_idP, int CC_id, frame_t frameP, sub_fra } // Checking if the DCI allocation is feasible in current subframe - nfapi_nr_dl_tti_request_body_t *dl_req = &nr_mac->DL_req[CC_id].dl_tti_request_body; + nfapi_nr_dl_tti_request_body_t *dl_req = &DL_req->dl_tti_request_body; if (dl_req->nPDUs > NFAPI_NR_MAX_DL_TTI_PDUS - 2) { LOG_I(NR_MAC, "[RAPROC] Subframe %d: FAPI DL structure is full, skip scheduling UE %d\n", slotP, ra->RA_rnti); return; @@ -1369,16 +1382,24 @@ void nr_generate_Msg2(module_id_t module_idP, int CC_id, frame_t frameP, sub_fra nr_mac->cset0_bwp_size); // 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]; + nfapi_nr_pdu_t *tx_req = &TX_req->pdu_list[TX_req->Number_of_PDUs]; // Program UL processing for Msg3 nr_get_Msg3alloc(module_idP, CC_id, scc, slotP, frameP, ra, nr_mac->tdd_beam_association); nr_add_msg3(module_idP, CC_id, frameP, slotP, ra, (uint8_t *) &tx_req->TLVs[0].value.direct[0]); - if(ra->cfra) { + if (ra->cfra) { + NR_UE_info_t *UE = find_nr_UE(&RC.nrmac[module_idP]->UE_info, ra->rnti); + if (UE) { + const NR_ServingCellConfig_t *servingCellConfig = UE->CellGroup ? UE->CellGroup->spCellConfig->spCellConfigDedicated : NULL; + uint32_t delay_ms = servingCellConfig && servingCellConfig->downlinkBWP_ToAddModList ? NR_RRC_SETUP_DELAY_MS + NR_RRC_BWP_SWITCHING_DELAY_MS : NR_RRC_SETUP_DELAY_MS; + NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl; + sched_ctrl->rrc_processing_timer = (delay_ms << ra->DL_BWP.scs); + } LOG_D(NR_MAC, "Frame %d, Subframe %d: Setting RA-Msg3 reception (CFRA) for SFN.Slot %d.%d\n", frameP, slotP, ra->Msg3_frame, ra->Msg3_slot); + } else { + LOG_D(NR_MAC, "Frame %d, Subframe %d: Setting RA-Msg3 reception (CBRA) for SFN.Slot %d.%d\n", frameP, slotP, ra->Msg3_frame, ra->Msg3_slot); } - else LOG_D(NR_MAC, "Frame %d, Subframe %d: Setting RA-Msg3 reception (CBRA) for SFN.Slot %d.%d\n", frameP, slotP, ra->Msg3_frame, ra->Msg3_slot); T(T_GNB_MAC_DL_RAR_PDU_WITH_DATA, T_INT(module_idP), T_INT(CC_id), T_INT(ra->RA_rnti), T_INT(frameP), T_INT(slotP), T_INT(0), T_BUFFER(&tx_req->TLVs[0].value.direct[0], tx_req->TLVs[0].length)); @@ -1387,9 +1408,9 @@ void nr_generate_Msg2(module_id_t module_idP, int CC_id, frame_t frameP, sub_fra tx_req->PDU_index = pduindex; tx_req->num_TLV = 1; tx_req->TLVs[0].length = tx_req->PDU_length + 2; - 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; + TX_req->SFN = frameP; + TX_req->Number_of_PDUs++; + TX_req->Slot = slotP; // Mark the corresponding symbols RBs as used fill_pdcch_vrb_map(nr_mac, @@ -1592,7 +1613,13 @@ void prepare_dl_pdus(gNB_MAC_INST *nr_mac, LOG_D(NR_MAC,"numDlDci: %i\n", pdcch_pdu_rel15->numDlDci); } -void nr_generate_Msg3_dcch_dtch_response(module_id_t module_idP, int CC_id, frame_t frameP, sub_frame_t slotP, NR_RA_t *ra) +void nr_generate_Msg3_dcch_dtch_response(module_id_t module_idP, + int CC_id, + frame_t frameP, + sub_frame_t slotP, + NR_RA_t *ra, + nfapi_nr_dl_tti_request_t *DL_req, + nfapi_nr_tx_data_request_t *TX_req) { gNB_MAC_INST *nr_mac = RC.nrmac[module_idP]; @@ -1646,7 +1673,7 @@ void nr_generate_Msg3_dcch_dtch_response(module_id_t module_idP, int CC_id, fram } // Checking if the DCI allocation is feasible in current subframe - nfapi_nr_dl_tti_request_body_t *dl_req = &nr_mac->DL_req[CC_id].dl_tti_request_body; + nfapi_nr_dl_tti_request_body_t *dl_req = &DL_req->dl_tti_request_body; if (dl_req->nPDUs > NFAPI_NR_MAX_DL_TTI_PDUS - 2) { LOG_I(NR_MAC, "[RAPROC] Subframe %d: FAPI DL structure is full, skip scheduling UE %d\n", slotP, rnti); return; @@ -1726,15 +1753,15 @@ void nr_generate_Msg3_dcch_dtch_response(module_id_t module_idP, int CC_id, fram 0, time_domain_assignment, CC_id, rnti, 0, mcsIndex, tb_scaling, pduindex, rbStart, rbSize); // 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]; + nfapi_nr_pdu_t *tx_req = &TX_req->pdu_list[TX_req->Number_of_PDUs]; memcpy(tx_req->TLVs[0].value.direct, buf, sizeof(uint8_t) * tb_size); tx_req->PDU_length = tb_size; tx_req->PDU_index = pduindex; tx_req->num_TLV = 1; tx_req->TLVs[0].length = tb_size + 2; - 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; + TX_req->SFN = frameP; + TX_req->Number_of_PDUs++; + TX_req->Slot = slotP; // Mark the corresponding symbols and RBs as used fill_pdcch_vrb_map(nr_mac, @@ -1772,7 +1799,13 @@ void nr_generate_Msg3_dcch_dtch_response(module_id_t module_idP, int CC_id, fram sched_ctrl->ul_failure = 0; } -void nr_generate_Msg4(module_id_t module_idP, int CC_id, frame_t frameP, sub_frame_t slotP, NR_RA_t *ra) +void nr_generate_Msg4(module_id_t module_idP, + int CC_id, + frame_t frameP, + sub_frame_t slotP, + NR_RA_t *ra, + nfapi_nr_dl_tti_request_t *DL_req, + nfapi_nr_tx_data_request_t *TX_req) { gNB_MAC_INST *nr_mac = RC.nrmac[module_idP]; NR_COMMON_channels_t *cc = &nr_mac->common_channels[CC_id]; @@ -1846,7 +1879,7 @@ void nr_generate_Msg4(module_id_t module_idP, int CC_id, frame_t frameP, sub_fra } // Checking if the DCI allocation is feasible in current subframe - nfapi_nr_dl_tti_request_body_t *dl_req = &nr_mac->DL_req[CC_id].dl_tti_request_body; + nfapi_nr_dl_tti_request_body_t *dl_req = &DL_req->dl_tti_request_body; if (dl_req->nPDUs > NFAPI_NR_MAX_DL_TTI_PDUS - 2) { LOG_I(NR_MAC, "[RAPROC] Subframe %d: FAPI DL structure is full, skip scheduling UE %d\n", slotP, ra->rnti); return; @@ -1998,15 +2031,15 @@ void nr_generate_Msg4(module_id_t module_idP, int CC_id, frame_t frameP, sub_fra T_INT(frameP), T_INT(slotP), T_INT(current_harq_pid), T_BUFFER(harq->transportBlock, harq->tb_size)); // 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]; + nfapi_nr_pdu_t *tx_req = &TX_req->pdu_list[TX_req->Number_of_PDUs]; memcpy(tx_req->TLVs[0].value.direct, harq->transportBlock, sizeof(uint8_t) * harq->tb_size); tx_req->PDU_length = harq->tb_size; tx_req->PDU_index = pduindex; tx_req->num_TLV = 1; tx_req->TLVs[0].length = harq->tb_size + 2; - 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; + TX_req->SFN = frameP; + TX_req->Number_of_PDUs++; + TX_req->Slot = slotP; // Mark the corresponding symbols and RBs as used fill_pdcch_vrb_map(nr_mac, diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c index 3224223631..37ceeddbee 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c @@ -42,8 +42,6 @@ #include "common/utils/nr/nr_common.h" -#include "pdcp.h" - #define ENABLE_MAC_PAYLOAD_DEBUG #define DEBUG_eNB_SCHEDULER 1 @@ -91,10 +89,10 @@ void schedule_ssb(frame_t frame, sub_frame_t slot, } -void schedule_nr_mib(module_id_t module_idP, frame_t frameP, sub_frame_t slotP) { +void schedule_nr_mib(module_id_t module_idP, frame_t frameP, sub_frame_t slotP, nfapi_nr_dl_tti_request_t *DL_req) +{ gNB_MAC_INST *gNB = RC.nrmac[module_idP]; NR_COMMON_channels_t *cc; - nfapi_nr_dl_tti_request_t *dl_tti_request; nfapi_nr_dl_tti_request_body_t *dl_req; NR_MIB_t *mib = RC.nrrrc[module_idP]->carrier.mib.message.choice.mib; uint8_t num_tdd_period,num_ssb; @@ -105,8 +103,7 @@ void schedule_nr_mib(module_id_t module_idP, frame_t frameP, sub_frame_t slotP) cc = &gNB->common_channels[CC_id]; NR_ServingCellConfigCommon_t *scc = cc->ServingCellConfigCommon; const int slots_per_frame = nr_slots_per_frame[*scc->ssbSubcarrierSpacing]; - dl_tti_request = &gNB->DL_req[CC_id]; - dl_req = &dl_tti_request->dl_tti_request_body; + dl_req = &DL_req->dl_tti_request_body; // get MIB every 8 frames if(((slotP == 0) && (frameP & 7) == 0) || @@ -257,7 +254,6 @@ void schedule_nr_mib(module_id_t module_idP, frame_t frameP, sub_frame_t slotP) } } - void schedule_nr_SI(module_id_t module_idP, frame_t frameP, sub_frame_t subframeP) { //---------------------------------------- } @@ -522,8 +518,12 @@ void nr_fill_nfapi_dl_sib1_pdu(int Mod_idP, } -void schedule_nr_sib1(module_id_t module_idP, frame_t frameP, sub_frame_t slotP) { - +void schedule_nr_sib1(module_id_t module_idP, + frame_t frameP, + sub_frame_t slotP, + nfapi_nr_dl_tti_request_t *DL_req, + nfapi_nr_tx_data_request_t *TX_req) +{ // TODO: Get these values from RRC const int CC_id = 0; uint8_t candidate_idx = 0; @@ -588,12 +588,12 @@ void schedule_nr_sib1(module_id_t module_idP, frame_t frameP, sub_frame_t slotP) candidate_idx, sib1_sdu_length); - nfapi_nr_dl_tti_request_body_t *dl_req = &gNB_mac->DL_req[CC_id].dl_tti_request_body; + nfapi_nr_dl_tti_request_body_t *dl_req = &DL_req->dl_tti_request_body; int pdu_index = gNB_mac->pdu_index[0]++; nr_fill_nfapi_dl_sib1_pdu(module_idP, dl_req, pdu_index, type0_PDCCH_CSS_config, TBS, tda_info.startSymbolIndex, tda_info.nrOfSymbols); - 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]; + const int ntx_req = TX_req->Number_of_PDUs; + nfapi_nr_pdu_t *tx_req = &TX_req->pdu_list[ntx_req]; // Data to be transmitted memcpy(tx_req->TLVs[0].value.direct, sib1_payload, TBS); @@ -602,9 +602,9 @@ void schedule_nr_sib1(module_id_t module_idP, frame_t frameP, sub_frame_t slotP) tx_req->PDU_index = pdu_index; 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 = frameP; - gNB_mac->TX_req[CC_id].Slot = slotP; + TX_req->Number_of_PDUs++; + TX_req->SFN = frameP; + TX_req->Slot = slotP; type0_PDCCH_CSS_config->active = false; } diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c index 7d3cd511e9..e6f32b1405 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c @@ -873,8 +873,10 @@ nr_pp_impl_dl nr_init_fr1_dlsch_preprocessor(int CC_id) { void nr_schedule_ue_spec(module_id_t module_id, frame_t frame, - sub_frame_t slot) { - + sub_frame_t slot, + nfapi_nr_dl_tti_request_t *DL_req, + nfapi_nr_tx_data_request_t *TX_req) +{ gNB_MAC_INST *gNB_mac = RC.nrmac[module_id]; if (!is_xlsch_in_slot(gNB_mac->dlsch_slot_bitmap[slot / 64], slot)) @@ -885,7 +887,7 @@ void nr_schedule_ue_spec(module_id_t module_id, const int CC_id = 0; NR_ServingCellConfigCommon_t *scc = gNB_mac->common_channels[CC_id].ServingCellConfigCommon; NR_UEs_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; + nfapi_nr_dl_tti_request_body_t *dl_req = &DL_req->dl_tti_request_body; UE_iterator(UE_info->list, UE) { NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl; @@ -1326,16 +1328,16 @@ void nr_schedule_ue_spec(module_id_t module_id, T_INT(frame), T_INT(slot), T_INT(current_harq_pid), T_BUFFER(harq->transportBlock, 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]; + const int ntx_req = TX_req->Number_of_PDUs; + nfapi_nr_pdu_t *tx_req = &TX_req->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->transportBlock, 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; + TX_req->Number_of_PDUs++; + TX_req->SFN = frame; + TX_req->Slot = slot; /* mark UE as scheduled */ sched_pdsch->rbSize = 0; } diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c index 7981db7522..99ce0ab235 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c @@ -1979,11 +1979,6 @@ int get_nrofHARQ_ProcessesForPDSCH(e_NR_PDSCH_ServingCellConfig__nrofHARQ_Proces } } -/* hack data to remove UE in the phy */ -int rnti_to_remove[10]; -volatile int rnti_to_remove_count; -pthread_mutex_t rnti_to_remove_mutex = PTHREAD_MUTEX_INITIALIZER; - void delete_nr_ue_data(NR_UE_info_t *UE, NR_COMMON_channels_t *ccPtr, uid_allocator_t *uia) { NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl; @@ -1997,16 +1992,6 @@ void delete_nr_ue_data(NR_UE_info_t *UE, NR_COMMON_channels_t *ccPtr, uid_alloca LOG_I(NR_MAC, "Remove NR rnti 0x%04x\n", UE->rnti); const rnti_t rnti = UE->rnti; free(UE); - /* hack to remove UE in the phy */ - if (pthread_mutex_lock(&rnti_to_remove_mutex)) - exit(1); - if (rnti_to_remove_count == 10) - exit(1); - rnti_to_remove[rnti_to_remove_count] = rnti; - LOG_W(NR_MAC, "to remove in mac rnti_to_remove[%d] = 0x%04x\n", rnti_to_remove_count, rnti); - rnti_to_remove_count++; - if (pthread_mutex_unlock(&rnti_to_remove_mutex)) - exit(1); /* clear RA process(es?) associated to the UE */ for (int cc_id = 0; cc_id < NFAPI_CC_MAX; cc_id++) { @@ -2015,8 +2000,8 @@ void delete_nr_ue_data(NR_UE_info_t *UE, NR_COMMON_channels_t *ccPtr, uid_alloca if (cc->ra[i].rnti == rnti) { LOG_D(NR_MAC, "free RA process %d for rnti %04x\n", i, rnti); /* is it enough? */ - cc->ra[i].cfra = false; - cc->ra[i].rnti = 0; + cc->ra[i].cfra = false; + cc->ra[i].rnti = 0; cc->ra[i].crnti = 0; } } @@ -2524,16 +2509,6 @@ void mac_remove_nr_ue(gNB_MAC_INST *nr_mac, rnti_t rnti) delete_nr_ue_data(UE, nr_mac->common_channels, &UE_info->uid_allocator); } -void nr_mac_remove_ra_rnti(module_id_t mod_id, rnti_t rnti) { - // Hack to remove UE in the phy (following the same procedure as in function mac_remove_nr_ue) - if (pthread_mutex_lock(&rnti_to_remove_mutex)) exit(1); - if (rnti_to_remove_count == 10) exit(1); - rnti_to_remove[rnti_to_remove_count] = rnti; - LOG_W(NR_MAC, "to remove in mac rnti_to_remove[%d] = 0x%04x\n", rnti_to_remove_count, rnti); - rnti_to_remove_count++; - if (pthread_mutex_unlock(&rnti_to_remove_mutex)) exit(1); -} - uint8_t nr_get_tpc(int target, uint8_t cqi, int incr) { // al values passed to this function are x10 int snrx10 = (cqi*5) - 640; @@ -2563,11 +2538,8 @@ int get_pdsch_to_harq_feedback(NR_PUCCH_Config_t *pucch_Config, } } -void nr_csirs_scheduling(int Mod_idP, - frame_t frame, - sub_frame_t slot, - int n_slots_frame){ - +void nr_csirs_scheduling(int Mod_idP, frame_t frame, sub_frame_t slot, int n_slots_frame, nfapi_nr_dl_tti_request_t *DL_req) +{ int CC_id = 0; NR_UEs_t *UE_info = &RC.nrmac[Mod_idP]->UE_info; gNB_MAC_INST *gNB_mac = RC.nrmac[Mod_idP]; @@ -2606,7 +2578,7 @@ void nr_csirs_scheduling(int Mod_idP, NR_NZP_CSI_RS_Resource_t *nzpcsi; int period, offset; - nfapi_nr_dl_tti_request_body_t *dl_req = &gNB_mac->DL_req[CC_id].dl_tti_request_body; + nfapi_nr_dl_tti_request_body_t *dl_req = &DL_req->dl_tti_request_body; for (int id = 0; id < csi_measconfig->nzp_CSI_RS_ResourceToAddModList->list.count; id++){ nzpcsi = csi_measconfig->nzp_CSI_RS_ResourceToAddModList->list.array[id]; diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c index bc86fded1b..3c314c6c86 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c @@ -478,14 +478,29 @@ void abort_nr_ul_harq(NR_UE_info_t *UE, int8_t harq_pid) sched_ctrl->sched_ul_bytes = 0; } +bool get_UE_waiting_CFRA_msg3(const gNB_MAC_INST *gNB_mac, const int CC_id, const frame_t frame, const sub_frame_t slot) +{ + bool UE_waiting_CFRA_msg3 = false; + for (int i = 0; i < NR_NB_RA_PROC_MAX; i++) { + const NR_RA_t *ra = &gNB_mac->common_channels[CC_id].ra[i]; + if (ra->cfra == true && ra->state == WAIT_Msg3 && frame == ra->Msg3_frame && slot == ra->Msg3_slot) { + UE_waiting_CFRA_msg3 = true; + break; + } + } + return UE_waiting_CFRA_msg3; +} + void handle_nr_ul_harq(const int CC_idP, module_id_t mod_id, frame_t frame, sub_frame_t slot, const nfapi_nr_crc_t *crc_pdu) { - NR_UE_info_t* UE = find_nr_UE(&RC.nrmac[mod_id]->UE_info, crc_pdu->rnti); - if (!UE) { + NR_UE_info_t *UE = find_nr_UE(&RC.nrmac[mod_id]->UE_info, crc_pdu->rnti); + bool UE_waiting_CFRA_msg3 = get_UE_waiting_CFRA_msg3(RC.nrmac[mod_id], CC_idP, frame, slot); + + if (!UE || UE_waiting_CFRA_msg3 == true) { LOG_W(NR_MAC, "handle harq for rnti %04x, in RA process\n", crc_pdu->rnti); for (int i = 0; i < NR_NB_RA_PROC_MAX; ++i) { NR_RA_t *ra = &RC.nrmac[mod_id]->common_channels[CC_idP].ra[i]; @@ -568,9 +583,12 @@ void nr_rx_sdu(const module_id_t gnb_mod_idP, LOG_D(NR_MAC, "rx_sdu for rnti %04x\n", current_rnti); const int target_snrx10 = gNB_mac->pusch_target_snrx10; const int pusch_failure_thres = gNB_mac->pusch_failure_thres; - - NR_UE_info_t* UE = find_nr_UE(&gNB_mac->UE_info, current_rnti); - if (UE) { + + NR_UE_info_t *UE = find_nr_UE(&gNB_mac->UE_info, current_rnti); + bool UE_waiting_CFRA_msg3 = get_UE_waiting_CFRA_msg3(gNB_mac, CC_idP, frameP, slotP); + + if (UE && UE_waiting_CFRA_msg3 == false) { + NR_UE_sched_ctrl_t *UE_scheduling_control = &UE->UE_sched_ctrl; const int8_t harq_pid = UE_scheduling_control->feedback_ul_harq.head; @@ -680,7 +698,6 @@ void nr_rx_sdu(const module_id_t gnb_mod_idP, if(no_sig) { LOG_D(NR_MAC, "Random Access %i failed at state %i (no signal)\n", i, ra->state); - nr_mac_remove_ra_rnti(gnb_mod_idP, ra->rnti); nr_clear_ra_proc(gnb_mod_idP, CC_idP, frameP, ra); } else { @@ -693,25 +710,24 @@ void nr_rx_sdu(const module_id_t gnb_mod_idP, if( (frameP==ra->Msg3_frame) && (slotP==ra->Msg3_slot) ) { LOG_D(NR_MAC, "Random Access %i failed at state %i (TC_RNTI %04x RNTI %04x)\n", i, ra->state,ra->rnti,current_rnti); - nr_mac_remove_ra_rnti(gnb_mod_idP, ra->rnti); nr_clear_ra_proc(gnb_mod_idP, CC_idP, frameP, ra); } continue; } - NR_UE_info_t *UE = add_new_nr_ue(gNB_mac, ra->rnti, ra->CellGroup); - if (!UE) { - LOG_W(NR_MAC, "Random Access %i discarded at state %i (TC_RNTI %04x RNTI %04x): max number of users achieved!\n", i, ra->state,ra->rnti,current_rnti); - nr_mac_remove_ra_rnti(gnb_mod_idP, ra->rnti); + NR_UE_info_t *UE_msg3_stage = UE ? UE : add_new_nr_ue(gNB_mac, ra->rnti, ra->CellGroup); + if (!UE_msg3_stage) { + LOG_W(NR_MAC, "Random Access %i discarded at state %i (TC_RNTI %04x RNTI %04x): max number of users achieved!\n", i, ra->state, ra->rnti, current_rnti); + nr_clear_ra_proc(gnb_mod_idP, CC_idP, frameP, ra); return; } - UE->UE_beam_index = ra->beam_id; + UE_msg3_stage->UE_beam_index = ra->beam_id; // re-initialize ta update variables after RA procedure completion - UE->UE_sched_ctrl.ta_frame = frameP; + UE_msg3_stage->UE_sched_ctrl.ta_frame = frameP; LOG_D(NR_MAC, "reset RA state information for RA-RNTI 0x%04x/index %d\n", @@ -725,19 +741,22 @@ void nr_rx_sdu(const module_id_t gnb_mod_idP, current_rnti, ra->rnti); - NR_UE_sched_ctrl_t *UE_scheduling_control = &UE->UE_sched_ctrl; + NR_UE_sched_ctrl_t *UE_scheduling_control = &UE_msg3_stage->UE_sched_ctrl; - UE_scheduling_control->tpc0 = nr_get_tpc(target_snrx10,ul_cqi,30); + UE_scheduling_control->tpc0 = nr_get_tpc(target_snrx10, ul_cqi, 30); if (timing_advance != 0xffff) UE_scheduling_control->ta_update = timing_advance; UE_scheduling_control->raw_rssi = rssi; UE_scheduling_control->pusch_snrx10 = ul_cqi * 5 - 640; - LOG_D(NR_MAC, "[UE %04x] PUSCH TPC %d and TA %d\n",UE->rnti,UE_scheduling_control->tpc0,UE_scheduling_control->ta_update); - if(ra->cfra) { - + LOG_D(NR_MAC, "[UE %04x] PUSCH TPC %d and TA %d\n", UE_msg3_stage->rnti, UE_scheduling_control->tpc0, UE_scheduling_control->ta_update); + if (ra->cfra) { LOG_A(NR_MAC, "(rnti 0x%04x) CFRA procedure succeeded!\n", ra->rnti); - UE->ra_timer = 0; - nr_mac_remove_ra_rnti(gnb_mod_idP, ra->rnti); + nr_mac_gNB_rrc_ul_failure_reset(gnb_mod_idP, frameP, slotP, ra->rnti); + reset_dl_harq_list(UE_scheduling_control); + reset_ul_harq_list(UE_scheduling_control); + UE_scheduling_control->pusch_consecutive_dtx_cnt = 0; + UE_scheduling_control->ul_failure = 0; + UE_msg3_stage->ra_timer = 0; nr_clear_ra_proc(gnb_mod_idP, CC_idP, frameP, ra); process_CellGroup(ra->CellGroup, UE_scheduling_control); @@ -755,7 +774,7 @@ void nr_rx_sdu(const module_id_t gnb_mod_idP, memcpy(ra->cont_res_id, &sduP[1], sizeof(uint8_t) * 6); // harq_pid set a non valid value because it is not used in this call // the function is only called to decode the contention resolution sub-header - if (nr_process_mac_pdu(gnb_mod_idP, UE, CC_idP, frameP, slotP, sduP, sdu_lenP, -1) == 0) { + if (nr_process_mac_pdu(gnb_mod_idP, UE_msg3_stage, CC_idP, frameP, slotP, sduP, sdu_lenP, -1) == 0) { if (ra->state == Msg3_dcch_dtch) { // Check if the UE identified by C-RNTI still exists at the gNB @@ -785,7 +804,6 @@ void nr_rx_sdu(const module_id_t gnb_mod_idP, } } else { - nr_mac_remove_ra_rnti(gnb_mod_idP, ra->rnti); nr_clear_ra_proc(gnb_mod_idP, CC_idP, frameP, ra); } } @@ -804,14 +822,12 @@ void nr_rx_sdu(const module_id_t gnb_mod_idP, // for CFRA (NSA) do not schedule retransmission of msg3 if (ra->cfra) { LOG_D(NR_MAC, "Random Access %i failed at state %i (NSA msg3 reception failed)\n", i, ra->state); - nr_mac_remove_ra_rnti(gnb_mod_idP, ra->rnti); nr_clear_ra_proc(gnb_mod_idP, CC_idP, frameP, ra); return; } if (ra->msg3_round >= gNB_mac->ul_bler.harq_round_max - 1) { LOG_W(NR_MAC, "Random Access %i failed at state %i (Reached msg3 max harq rounds)\n", i, ra->state); - nr_mac_remove_ra_rnti(gnb_mod_idP, ra->rnti); nr_clear_ra_proc(gnb_mod_idP, CC_idP, frameP, ra); return; } @@ -1981,7 +1997,7 @@ nr_pp_impl_ul nr_init_fr1_ulsch_preprocessor(int CC_id) return nr_fr1_ulsch_preprocessor; } -void nr_schedule_ulsch(module_id_t module_id, frame_t frame, sub_frame_t slot) +void nr_schedule_ulsch(module_id_t module_id, frame_t frame, sub_frame_t slot, nfapi_nr_ul_dci_request_t *ul_dci_req) { gNB_MAC_INST *nr_mac = RC.nrmac[module_id]; /* Uplink data ONLY can be scheduled when the current slot is downlink slot, @@ -1994,8 +2010,6 @@ void nr_schedule_ulsch(module_id_t module_id, frame_t frame, sub_frame_t slot) if (!do_sched) return; - const int CC_id = 0; - nfapi_nr_ul_dci_request_t *ul_dci_req = &nr_mac->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 diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h index fe880785aa..a700c5c652 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h +++ b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h @@ -58,18 +58,21 @@ void nr_mac_config_sib1(gNB_MAC_INST *nrmac, NR_BCCH_DL_SCH_Message_t *sib1); bool nr_mac_add_test_ue(gNB_MAC_INST *nrmac, uint32_t rnti, NR_CellGroupConfig_t *CellGroup); bool nr_mac_prepare_ra_nsa_ue(gNB_MAC_INST *nrmac, uint32_t rnti, NR_CellGroupConfig_t *CellGroup); bool nr_mac_update_cellgroup(gNB_MAC_INST *nrmac, uint32_t rnti, NR_CellGroupConfig_t *CellGroup); +bool nr_mac_update_RA(gNB_MAC_INST *nrmac, uint32_t rnti, NR_CellGroupConfig_t *CellGroup); -void clear_nr_nfapi_information(gNB_MAC_INST * gNB, +void clear_nr_nfapi_information(gNB_MAC_INST *gNB, int CC_idP, - frame_t frameP, - sub_frame_t subframeP); + frame_t frameP, + sub_frame_t slotP, + nfapi_nr_dl_tti_request_t *DL_req, + nfapi_nr_tx_data_request_t *TX_req, + nfapi_nr_ul_dci_request_t *UL_dci_req); void nr_mac_update_timers(module_id_t module_id, frame_t frame, sub_frame_t slot); -void gNB_dlsch_ulsch_scheduler(module_id_t module_idP, - frame_t frame_rxP, sub_frame_t slot_rxP); +void gNB_dlsch_ulsch_scheduler(module_id_t module_idP, frame_t frame_rxP, sub_frame_t slot_rxP, NR_Sched_Rsp_t *sched_info); void schedule_nr_bwp_switch(module_id_t module_id, frame_t frame, @@ -80,7 +83,9 @@ void schedule_nr_bwp_switch(module_id_t module_id, * messages, statistics, HARQ handling, CEs, ... */ void nr_schedule_ue_spec(module_id_t module_id, frame_t frame, - sub_frame_t slot); + sub_frame_t slot, + nfapi_nr_dl_tti_request_t *DL_req, + nfapi_nr_tx_data_request_t *TX_req); uint32_t schedule_control_sib1(module_id_t module_id, int CC_id, @@ -94,21 +99,30 @@ uint32_t schedule_control_sib1(module_id_t module_id, /* \brief default FR1 DL preprocessor init routine, returns preprocessor to call */ nr_pp_impl_dl nr_init_fr1_dlsch_preprocessor(int CC_id); -void schedule_nr_sib1(module_id_t module_idP, frame_t frameP, sub_frame_t subframeP); +void schedule_nr_sib1(module_id_t module_idP, + frame_t frameP, + sub_frame_t slotP, + nfapi_nr_dl_tti_request_t *DL_req, + nfapi_nr_tx_data_request_t *TX_req); -void schedule_nr_mib(module_id_t module_idP, frame_t frameP, sub_frame_t slotP); +void schedule_nr_mib(module_id_t module_idP, frame_t frameP, sub_frame_t slotP, nfapi_nr_dl_tti_request_t *DL_req); /* \brief main UL scheduler function. Calls a preprocessor to decide on * resource allocation, then "post-processes" resource allocation (nFAPI * messages, statistics, HARQ handling, ... */ -void nr_schedule_ulsch(module_id_t module_id, frame_t frame, sub_frame_t slot); +void nr_schedule_ulsch(module_id_t module_id, frame_t frame, sub_frame_t slot, nfapi_nr_ul_dci_request_t *ul_dci_req); /* \brief default FR1 UL preprocessor init routine, returns preprocessor to call */ nr_pp_impl_ul nr_init_fr1_ulsch_preprocessor(int CC_id); /////// Random Access MAC-PHY interface functions and primitives /////// -void nr_schedule_RA(module_id_t module_idP, frame_t frameP, sub_frame_t slotP); +void nr_schedule_RA(module_id_t module_idP, + frame_t frameP, + sub_frame_t slotP, + nfapi_nr_ul_dci_request_t *ul_dci_req, + nfapi_nr_dl_tti_request_t *DL_req, + nfapi_nr_tx_data_request_t *TX_req); /* \brief Function to indicate a received preamble on PRACH. It initiates the RA procedure. @param module_idP Instance ID of gNB @@ -133,7 +147,12 @@ void nr_get_Msg3alloc(module_id_t module_id, NR_RA_t *ra, int16_t *tdd_beam_association); -void nr_generate_Msg3_retransmission(module_id_t module_idP, int CC_id, frame_t frameP, sub_frame_t slotP, NR_RA_t *ra); +void nr_generate_Msg3_retransmission(module_id_t module_idP, + int CC_id, + frame_t frameP, + sub_frame_t slotP, + NR_RA_t *ra, + nfapi_nr_ul_dci_request_t *ul_dci_req); /* \brief Function in gNB to fill RAR pdu when requested by PHY. @param ra Instance of RA resources of gNB @@ -200,10 +219,7 @@ void nr_srs_ri_computation(const nfapi_nr_srs_normalized_channel_iq_matrix_t *nr void nr_schedule_srs(int module_id, frame_t frame, int slot); -void nr_csirs_scheduling(int Mod_idP, - frame_t frame, - sub_frame_t slot, - int n_slots_frame); +void nr_csirs_scheduling(int Mod_idP, frame_t frame, sub_frame_t slot, int n_slots_frame, nfapi_nr_dl_tti_request_t *DL_req); void nr_csi_meas_reporting(int Mod_idP, frame_t frameP, @@ -350,8 +366,6 @@ NR_UE_info_t* add_new_nr_ue(gNB_MAC_INST *nr_mac, rnti_t rntiP, NR_CellGroupConf void mac_remove_nr_ue(gNB_MAC_INST *nr_mac, rnti_t rnti); -void nr_mac_remove_ra_rnti(module_id_t mod_id, rnti_t rnti); - int nr_get_default_pucch_res(int pucch_ResourceCommon); int get_dlscs(nfapi_nr_config_request_t *cfg); @@ -366,13 +380,31 @@ int nr_write_ce_dlsch_pdu(module_id_t module_idP, unsigned char drx_cmd, unsigned char *ue_cont_res_id); -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_generate_Msg2(module_id_t module_idP, + int CC_id, + frame_t frameP, + sub_frame_t slotP, + NR_RA_t *ra, + nfapi_nr_dl_tti_request_t *dl_req, + nfapi_nr_tx_data_request_t *TX_req); -void nr_generate_Msg4(module_id_t module_idP, int CC_id, frame_t frameP, sub_frame_t slotP, NR_RA_t *ra); +void nr_generate_Msg4(module_id_t module_idP, + int CC_id, + frame_t frameP, + sub_frame_t slotP, + NR_RA_t *ra, + nfapi_nr_dl_tti_request_t *DL_req, + nfapi_nr_tx_data_request_t *TX_req); void nr_check_Msg4_Ack(module_id_t module_id, int CC_id, frame_t frame, sub_frame_t slot, NR_RA_t *ra); -void nr_generate_Msg3_dcch_dtch_response(module_id_t module_idP, int CC_id, frame_t frameP, sub_frame_t slotP, NR_RA_t *ra); +void nr_generate_Msg3_dcch_dtch_response(module_id_t module_idP, + int CC_id, + frame_t frameP, + sub_frame_t slotP, + NR_RA_t *ra, + nfapi_nr_dl_tti_request_t *DL_req, + nfapi_nr_tx_data_request_t *TX_req); int binomial(int n, int k); diff --git a/openair2/LAYER2/NR_MAC_gNB/main.c b/openair2/LAYER2/NR_MAC_gNB/main.c index f78e7f224f..5dcaffce94 100644 --- a/openair2/LAYER2/NR_MAC_gNB/main.c +++ b/openair2/LAYER2/NR_MAC_gNB/main.c @@ -33,9 +33,8 @@ #include "NR_MAC_gNB/mac_proto.h" #include "NR_MAC_COMMON/nr_mac_extern.h" #include "assertions.h" -#include "pdcp.h" +#include "nr_pdcp/nr_pdcp_oai_api.h" -#include "LAYER2/nr_pdcp/nr_pdcp_entity.h" #include "RRC/NR/nr_rrc_defs.h" #include "common/utils/LOG/log.h" //#include "RRC/L2_INTERFACE/openair_rrc_L2_interface.h" @@ -250,7 +249,7 @@ void mac_top_init_gNB(ngran_node_t node_type) AssertFatal(rlc_module_init(1) == 0,"Could not initialize RLC layer\n"); // These should be out of here later - if (get_softmodem_params()->usim_test == 0 ) pdcp_layer_init(); + if (get_softmodem_params()->usim_test == 0 ) nr_pdcp_layer_init(); if(IS_SOFTMODEM_NOS1 && get_softmodem_params()->phy_test) nr_DRB_preconfiguration(0x1234); diff --git a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h index 96734aa8b1..1cd0f89736 100644 --- a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h +++ b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h @@ -719,24 +719,15 @@ typedef struct gNB_MAC_INST_s { uint16_t ulprbbl[MAX_BWP_SIZE]; /// NFAPI Config Request Structure 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_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]; /// NFAPI UL TTI Request Structure for future TTIs, dynamically allocated /// because length depends on number of slots nfapi_nr_ul_tti_request_t *UL_tti_req_ahead[NFAPI_CC_MAX]; int UL_tti_req_ahead_size; int vrb_map_UL_size; - /// NFAPI HI/DCI0 Config Request Structure - nfapi_nr_ul_dci_request_t UL_dci_req[NFAPI_CC_MAX]; - /// NFAPI DL PDU structure - nfapi_nr_tx_data_request_t TX_req[NFAPI_CC_MAX]; NR_UEs_t UE_info; diff --git a/openair2/LAYER2/PDCP_v10.1.0/pdcp.h b/openair2/LAYER2/PDCP_v10.1.0/pdcp.h index b4303d1fdd..043ac7fb4a 100644 --- a/openair2/LAYER2/PDCP_v10.1.0/pdcp.h +++ b/openair2/LAYER2/PDCP_v10.1.0/pdcp.h @@ -402,9 +402,7 @@ void pdcp_mbms_run ( void pdcp_run ( const protocol_ctxt_t *const ctxt_pP); uint64_t pdcp_module_init (uint64_t pdcp_optmask, int ue_id); -uint64_t nr_pdcp_module_init(uint64_t _pdcp_optmask, int id); void pdcp_module_cleanup (void); -void nr_ip_over_LTE_DRB_preconfiguration (void); void pdcp_layer_init (void); void pdcp_layer_cleanup (void); #define PDCP2NW_DRIVER_FIFO 21 diff --git a/openair2/LAYER2/nr_pdcp/asn1_utils.c b/openair2/LAYER2/nr_pdcp/asn1_utils.c index 264a2815bb..ab0cdf48fd 100644 --- a/openair2/LAYER2/nr_pdcp/asn1_utils.c +++ b/openair2/LAYER2/nr_pdcp/asn1_utils.c @@ -19,7 +19,7 @@ * contact@openairinterface.org */ -#include "pdcp.h" +#include "common/utils/LOG/log.h" int decode_t_reordering(int v) { diff --git a/openair2/LAYER2/nr_pdcp/nr_pdcp_e1_api.h b/openair2/LAYER2/nr_pdcp/nr_pdcp_e1_api.h index 68b146efeb..f45f3f0458 100644 --- a/openair2/LAYER2/nr_pdcp/nr_pdcp_e1_api.h +++ b/openair2/LAYER2/nr_pdcp/nr_pdcp_e1_api.h @@ -25,7 +25,7 @@ #include "common/utils/oai_asn1.h" #include "NR_RadioBearerConfig.h" -#include "pdcp.h" +#include "nr_pdcp_oai_api.h" #include "LAYER2/nr_rlc/nr_rlc_oai_api.h" #include #include "openair2/SDAP/nr_sdap/nr_sdap.h" diff --git a/openair2/LAYER2/nr_pdcp/nr_pdcp_entity.c b/openair2/LAYER2/nr_pdcp/nr_pdcp_entity.c index e632fb2024..b503fcc010 100644 --- a/openair2/LAYER2/nr_pdcp/nr_pdcp_entity.c +++ b/openair2/LAYER2/nr_pdcp/nr_pdcp_entity.c @@ -176,14 +176,19 @@ static void nr_pdcp_entity_recv_pdu(nr_pdcp_entity_t *entity, } } -static void nr_pdcp_entity_recv_sdu(nr_pdcp_entity_t *entity, - char *buffer, int size, int sdu_id) +static int nr_pdcp_entity_process_sdu(nr_pdcp_entity_t *entity, + char *buffer, + int size, + int sdu_id, + char *pdu_buffer, + int pdu_max_size) { uint32_t count; int sn; int header_size; int integrity_size; - char buf[size + 3 + 4]; + char *buf = pdu_buffer; + DevAssert(size + 3 + 4 <= pdu_max_size); int dc_bit; entity->stats.rxsdu_pkts++; entity->stats.rxsdu_bytes += size; @@ -243,13 +248,11 @@ static void nr_pdcp_entity_recv_sdu(nr_pdcp_entity_t *entity, entity->tx_next++; - entity->deliver_pdu(entity->deliver_pdu_data, entity, buf, - header_size + size + integrity_size, sdu_id); entity->stats.txpdu_pkts++; entity->stats.txpdu_bytes += header_size + size + integrity_size; entity->stats.txpdu_sn = sn; - + return header_size + size + integrity_size; } /* may be called several times, take care to clean previous settings */ @@ -398,7 +401,7 @@ nr_pdcp_entity_t *new_nr_pdcp_entity( void (*deliver_sdu)(void *deliver_sdu_data, struct nr_pdcp_entity_t *entity, char *buf, int size), void *deliver_sdu_data, - void (*deliver_pdu)(void *deliver_pdu_data, struct nr_pdcp_entity_t *entity, + void (*deliver_pdu)(void *deliver_pdu_data, ue_id_t ue_id, int rb_id, char *buf, int size, int sdu_id), void *deliver_pdu_data, int sn_size, @@ -420,7 +423,7 @@ nr_pdcp_entity_t *new_nr_pdcp_entity( ret->type = type; ret->recv_pdu = nr_pdcp_entity_recv_pdu; - ret->recv_sdu = nr_pdcp_entity_recv_sdu; + ret->process_sdu = nr_pdcp_entity_process_sdu; ret->set_security = nr_pdcp_entity_set_security; ret->set_time = nr_pdcp_entity_set_time; diff --git a/openair2/LAYER2/nr_pdcp/nr_pdcp_entity.h b/openair2/LAYER2/nr_pdcp/nr_pdcp_entity.h index 4ad2508e4a..762c91c747 100644 --- a/openair2/LAYER2/nr_pdcp/nr_pdcp_entity.h +++ b/openair2/LAYER2/nr_pdcp/nr_pdcp_entity.h @@ -73,8 +73,8 @@ typedef struct nr_pdcp_entity_t { /* functions provided by the PDCP module */ void (*recv_pdu)(struct nr_pdcp_entity_t *entity, char *buffer, int size); - void (*recv_sdu)(struct nr_pdcp_entity_t *entity, char *buffer, int size, - int sdu_id); + int (*process_sdu)(struct nr_pdcp_entity_t *entity, char *buffer, int size, + int sdu_id, char *pdu_buffer, int pdu_max_size); void (*delete_entity)(struct nr_pdcp_entity_t *entity); void (*get_stats)(struct nr_pdcp_entity_t *entity, nr_pdcp_statistics_t *out); @@ -95,7 +95,7 @@ typedef struct nr_pdcp_entity_t { void (*deliver_sdu)(void *deliver_sdu_data, struct nr_pdcp_entity_t *entity, char *buf, int size); void *deliver_sdu_data; - void (*deliver_pdu)(void *deliver_pdu_data, struct nr_pdcp_entity_t *entity, + void (*deliver_pdu)(void *deliver_pdu_data, ue_id_t ue_id, int rb_id, char *buf, int size, int sdu_id); void *deliver_pdu_data; @@ -176,7 +176,7 @@ nr_pdcp_entity_t *new_nr_pdcp_entity( void (*deliver_sdu)(void *deliver_sdu_data, struct nr_pdcp_entity_t *entity, char *buf, int size), void *deliver_sdu_data, - void (*deliver_pdu)(void *deliver_pdu_data, struct nr_pdcp_entity_t *entity, + void (*deliver_pdu)(void *deliver_pdu_data, ue_id_t ue_id, int rb_id, char *buf, int size, int sdu_id), void *deliver_pdu_data, int sn_size, diff --git a/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.c b/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.c index e4bb7bb4f5..efbb638a7e 100644 --- a/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.c +++ b/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.c @@ -34,7 +34,7 @@ /* from OAI */ #include "oai_asn1.h" -#include "pdcp.h" +#include "nr_pdcp_oai_api.h" #include "LAYER2/nr_rlc/nr_rlc_oai_api.h" #include #include "openair2/SDAP/nr_sdap/nr_sdap.h" @@ -73,7 +73,7 @@ static ngran_node_t node_type; /* NR PDCP and RLC both use "big locks". In some cases a thread may do * lock(rlc) followed by lock(pdcp) (typically when running 'rx_sdu'). * Another thread may first do lock(pdcp) and then lock(rlc) (typically - * the GTP module calls 'pdcp_data_req' that, in a previous implementation + * the GTP module calls 'nr_pdcp_data_req' that, in a previous implementation * was indirectly calling 'rlc_data_req' which does lock(rlc)). * To avoid the resulting deadlock it is enough to ensure that a call * to lock(pdcp) will never be followed by a call to lock(rlc). So, @@ -531,7 +531,13 @@ static void set_node_type() { node_type = get_node_type(); } +/* hack: dummy function needed due to LTE dependencies */ void pdcp_layer_init(void) +{ + abort(); +} + +void nr_pdcp_layer_init(void) { /* hack: be sure to initialize only once */ static pthread_mutex_t m = PTHREAD_MUTEX_INITIALIZER; @@ -647,35 +653,12 @@ static void deliver_sdu_drb(void *_ue, nr_pdcp_entity_t *entity, } } -static void deliver_pdu_drb(void *_ue, nr_pdcp_entity_t *entity, +static void deliver_pdu_drb(void *deliver_pdu_data, ue_id_t ue_id, int rb_id, char *buf, int size, int sdu_id) { - nr_pdcp_ue_t *ue = _ue; - int rb_id; - protocol_ctxt_t ctxt; - int i; - mem_block_t *memblock; + DevAssert(deliver_pdu_data == NULL); + protocol_ctxt_t ctxt = { .enb_flag = 1, .rntiMaybeUEid = ue_id }; - for (i = 0; i < MAX_DRBS_PER_UE; i++) { - if (entity == ue->drb[i]) { - rb_id = i+1; - goto rb_found; - } - } - - LOG_E(PDCP, "%s:%d:%s: fatal, no RB found for UE ID/RNTI %ld\n", __FILE__, __LINE__, __FUNCTION__, ue->rntiMaybeUEid); - exit(1); - -rb_found: - ctxt.module_id = 0; - ctxt.enb_flag = 1; - ctxt.instance = 0; - ctxt.frame = 0; - ctxt.subframe = 0; - ctxt.eNB_index = 0; - ctxt.brOption = 0; - - ctxt.rntiMaybeUEid = ue->rntiMaybeUEid; if (NODE_IS_CU(node_type)) { MessageDef *message_p = itti_alloc_new_message_sized(TASK_PDCP_ENB, 0, GTPV1U_TUNNEL_DATA_REQ, @@ -690,14 +673,14 @@ rb_found: req->buffer = gtpu_buffer_p; req->length = size; req->offset = GTPU_HEADER_OVERHEAD_MAX; - req->ue_id = ue->rntiMaybeUEid; + req->ue_id = ue_id; req->bearer_id = rb_id; LOG_I(PDCP, "%s() (drb %d) sending message to gtp size %d\n", __func__, rb_id, size); extern instance_t CUuniqInstance; itti_send_msg_to_task(TASK_GTPV1_U, CUuniqInstance, message_p); } else { - memblock = get_free_mem_block(size, __FUNCTION__); + mem_block_t *memblock = get_free_mem_block(size, __FUNCTION__); memcpy(memblock->data, buf, size); LOG_D(PDCP, "%s(): (drb %d) calling rlc_data_req size %d\n", __func__, rb_id, size); //for (i = 0; i < size; i++) printf(" %2.2x", (unsigned char)memblock->data[i]); @@ -749,101 +732,26 @@ srb_found: } } -static void deliver_pdu_srb(void *_ue, nr_pdcp_entity_t *entity, - char *buf, int size, int sdu_id) +void deliver_pdu_srb_rlc(void *deliver_pdu_data, ue_id_t ue_id, int srb_id, + char *buf, int size, int sdu_id) { - nr_pdcp_ue_t *ue = _ue; - int srb_id; - int i; - - for (i = 0; i < sizeofArray(ue->srb) ; i++) { - if (entity == ue->srb[i]) { - srb_id = i+1; - goto srb_found; - } - } - - LOG_E(PDCP, "%s:%d:%s: fatal, no SRB found for UE ID/RNTI %ld\n", __FILE__, __LINE__, __FUNCTION__, ue->rntiMaybeUEid); - exit(1); - -srb_found: - - - LOG_D(PDCP, "%s(): (srb %d) calling rlc_data_req size %d\n", __func__, srb_id, size); - //for (i = 0; i < size; i++) printf(" %2.2x", (unsigned char)memblock->data[i]); - //printf("\n"); - if ((RC.nrrrc == NULL) || (!NODE_IS_CU(node_type))) { - if (entity->is_gnb) { - f1ap_dl_rrc_message_t dl_rrc = {.old_gNB_DU_ue_id = 0xFFFFFF, .rrc_container = (uint8_t *)buf, .rrc_container_length = size, .rnti = ue->rntiMaybeUEid, .srb_id = DCCH}; - gNB_RRC_INST *rrc = RC.nrrrc[0]; - rrc->mac_rrc.dl_rrc_message_transfer(0, &dl_rrc); - } else { // UE - mem_block_t *memblock; - protocol_ctxt_t ctxt = {.module_id = 0, .enb_flag = 1, .instance = 0, .frame = 0, .subframe = 0, .eNB_index = 0, .brOption = 0, .rntiMaybeUEid = ue->rntiMaybeUEid}; - memblock = get_free_mem_block(size, __FUNCTION__); - memcpy(memblock->data, buf, size); - enqueue_rlc_data_req(&ctxt, 1, MBMS_FLAG_NO, srb_id, sdu_id, 0, size, memblock); - } - } else { - MessageDef *message_p = itti_alloc_new_message (TASK_RRC_GNB, 0, F1AP_DL_RRC_MESSAGE); - uint8_t *message_buffer = itti_malloc (TASK_RRC_GNB, TASK_CU_F1, size); - memcpy (message_buffer, buf, size); - F1AP_DL_RRC_MESSAGE (message_p).rrc_container = message_buffer; - F1AP_DL_RRC_MESSAGE (message_p).rrc_container_length = size; - F1AP_DL_RRC_MESSAGE (message_p).gNB_CU_ue_id = 0; - F1AP_DL_RRC_MESSAGE (message_p).gNB_DU_ue_id = 0; - F1AP_DL_RRC_MESSAGE (message_p).old_gNB_DU_ue_id = 0xFFFFFFFF; // unknown - F1AP_DL_RRC_MESSAGE(message_p).rnti = ue->rntiMaybeUEid; - F1AP_DL_RRC_MESSAGE (message_p).srb_id = srb_id; - F1AP_DL_RRC_MESSAGE (message_p).execute_duplication = 1; - F1AP_DL_RRC_MESSAGE (message_p).RAT_frequency_priority_information.en_dc = 0; - itti_send_msg_to_task (TASK_CU_F1, 0, message_p); - LOG_D(PDCP, "Send F1AP_DL_RRC_MESSAGE with ITTI\n"); - } + protocol_ctxt_t ctxt = { .enb_flag = 1, .rntiMaybeUEid = ue_id }; + mem_block_t *memblock = get_free_mem_block(size, __FUNCTION__); + memcpy(memblock->data, buf, size); + enqueue_rlc_data_req(&ctxt, 1, MBMS_FLAG_NO, srb_id, sdu_id, 0, size, memblock); } -void pdcp_run(const protocol_ctxt_t *const ctxt_pP) +void deliver_pdu_srb_f1(void *deliver_pdu_data, ue_id_t ue_id, int srb_id, + char *buf, int size, int sdu_id) { - MessageDef *msg_p; - int result; - protocol_ctxt_t ctxt = {.module_id = 0, .enb_flag = 1, .instance = 0, .rntiMaybeUEid = 0, .frame = -1, .subframe = -1, .eNB_index = 0, .brOption = false}; - - while (1) { - itti_poll_msg(ctxt_pP->enb_flag ? TASK_PDCP_ENB : TASK_PDCP_UE, &msg_p); - if (msg_p == NULL){ - break; - } - switch (ITTI_MSG_ID(msg_p)) { - case RRC_DCCH_DATA_REQ: - LOG_D(PDCP, "Received RRC_DCCH_DATA_REQ type at PDCP task \n"); - PROTOCOL_CTXT_SET_BY_MODULE_ID( - &ctxt, - RRC_DCCH_DATA_REQ(msg_p).module_id, - RRC_DCCH_DATA_REQ(msg_p).enb_flag, - RRC_DCCH_DATA_REQ(msg_p).rnti, - RRC_DCCH_DATA_REQ(msg_p).frame, - 0, - RRC_DCCH_DATA_REQ(msg_p).eNB_index); - result = pdcp_data_req(&ctxt, - SRB_FLAG_YES, - RRC_DCCH_DATA_REQ(msg_p).rb_id, - RRC_DCCH_DATA_REQ(msg_p).muip, - RRC_DCCH_DATA_REQ(msg_p).confirmp, - RRC_DCCH_DATA_REQ(msg_p).sdu_size, - RRC_DCCH_DATA_REQ(msg_p).sdu_p, - RRC_DCCH_DATA_REQ(msg_p).mode, - NULL, NULL); - - if (result != true) - LOG_E(PDCP, "PDCP data request failed!\n"); - result = itti_free(ITTI_MSG_ORIGIN_ID(msg_p), RRC_DCCH_DATA_REQ(msg_p).sdu_p); - AssertFatal(result == EXIT_SUCCESS, "Failed to free memory (%d)!\n", result); - break; - default: - LOG_E(PDCP, "Received unexpected message %s\n", ITTI_MSG_NAME(msg_p)); - break; - } - } + DevAssert(deliver_pdu_data != NULL); + gNB_RRC_INST *rrc = deliver_pdu_data; + f1ap_dl_rrc_message_t dl_rrc = {.old_gNB_DU_ue_id = 0xFFFFFF, + .rrc_container = (uint8_t *)buf, + .rrc_container_length = size, + .rnti = ue_id, + .srb_id = srb_id}; + rrc->mac_rrc.dl_rrc_message_transfer(0, &dl_rrc); } static void add_srb(int is_gnb, ue_id_t rntiMaybeUEid, struct NR_SRB_ToAddMod *s, int ciphering_algorithm, int integrity_algorithm, unsigned char *ciphering_key, unsigned char *integrity_key) @@ -864,7 +772,7 @@ static void add_srb(int is_gnb, ue_id_t rntiMaybeUEid, struct NR_SRB_ToAddMod *s } else { pdcp_srb = new_nr_pdcp_entity(NR_PDCP_SRB, is_gnb, srb_id, 0, false, false, // sdap parameters - deliver_sdu_srb, ue, deliver_pdu_srb, ue, + deliver_sdu_srb, ue, NULL, ue, 12, t_Reordering, -1, ciphering_algorithm, integrity_algorithm, @@ -1131,30 +1039,43 @@ uint64_t get_pdcp_optmask(void) return pdcp_optmask; } +/* hack: dummy function needed due to LTE dependencies */ bool pdcp_remove_UE(const protocol_ctxt_t *const ctxt_pP) { - ue_id_t rntiMaybeUEid = ctxt_pP->rntiMaybeUEid; + abort(); +} +bool nr_pdcp_remove_UE(ue_id_t ue_id) +{ nr_pdcp_manager_lock(nr_pdcp_ue_manager); - nr_pdcp_manager_remove_ue(nr_pdcp_ue_manager, rntiMaybeUEid); + nr_pdcp_manager_remove_ue(nr_pdcp_ue_manager, ue_id); nr_pdcp_manager_unlock(nr_pdcp_ue_manager); return 1; } -void pdcp_config_set_security( - const protocol_ctxt_t* const ctxt_pP, - pdcp_t *const pdcp_pP, - const rb_id_t rb_id, - const uint16_t lc_idP, - const uint8_t security_modeP, - uint8_t *const kRRCenc_pP, - uint8_t *const kRRCint_pP, - uint8_t *const kUPenc_pP) +/* hack: dummy function needed due to LTE dependencies */ +void pdcp_config_set_security(const protocol_ctxt_t *const ctxt_pP, + pdcp_t *const pdcp_pP, + const rb_id_t rb_id, + const uint16_t lc_idP, + const uint8_t security_modeP, + uint8_t *const kRRCenc_pP, + uint8_t *const kRRCint_pP, + uint8_t *const kUPenc_pP) +{ + abort(); +} + +void nr_pdcp_config_set_security(ue_id_t ue_id, + const rb_id_t rb_id, + const uint8_t security_modeP, + uint8_t *const kRRCenc_pP, + uint8_t *const kRRCint_pP, + uint8_t *const kUPenc_pP) { nr_pdcp_ue_t *ue; nr_pdcp_entity_t *rb; - ue_id_t ue_id = ctxt_pP->rntiMaybeUEid; int integrity_algorithm; int ciphering_algorithm; @@ -1186,27 +1107,17 @@ void pdcp_config_set_security( nr_pdcp_manager_unlock(nr_pdcp_ue_manager); } -static bool pdcp_data_req_srb(protocol_ctxt_t *ctxt_pP, - const rb_id_t rb_id, - const mui_t muiP, - const confirm_t confirmP, - const sdu_size_t sdu_buffer_size, - unsigned char *const sdu_buffer) +bool nr_pdcp_data_req_srb(ue_id_t ue_id, + const rb_id_t rb_id, + const mui_t muiP, + const sdu_size_t sdu_buffer_size, + unsigned char *const sdu_buffer, + deliver_pdu deliver_pdu_cb, + void *data) { LOG_D(PDCP, "%s() called, size %d\n", __func__, sdu_buffer_size); nr_pdcp_ue_t *ue; nr_pdcp_entity_t *rb; - ue_id_t ue_id = ctxt_pP->rntiMaybeUEid; - - if (ctxt_pP->module_id != 0 || - //ctxt_pP->enb_flag != 1 || - ctxt_pP->instance != 0 || - ctxt_pP->eNB_index != 0 /*|| - ctxt_pP->configured != 1 || - ctxt_pP->brOption != 0*/) { - LOG_E(PDCP, "%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__); - exit(1); - } nr_pdcp_manager_lock(nr_pdcp_ue_manager); @@ -1223,21 +1134,31 @@ static bool pdcp_data_req_srb(protocol_ctxt_t *ctxt_pP, return 0; } - rb->recv_sdu(rb, (char *)sdu_buffer, sdu_buffer_size, muiP); + int max_size = sdu_buffer_size + 3 + 4; // 3: max header, 4: max integrity + char pdu_buf[max_size]; + int pdu_size = rb->process_sdu(rb, (char *)sdu_buffer, sdu_buffer_size, muiP, pdu_buf, max_size); + AssertFatal(rb->deliver_pdu == NULL, "SRB callback should be NULL, to be provided on every invocation\n"); nr_pdcp_manager_unlock(nr_pdcp_ue_manager); + deliver_pdu_cb(data, ue_id, rb_id, pdu_buf, pdu_size, muiP); + return 1; } - -static bool pdcp_data_req_drb(protocol_ctxt_t *ctxt_pP, - const rb_id_t rb_id, - const mui_t muiP, - const confirm_t confirmP, - const sdu_size_t sdu_buffer_size, - unsigned char *const sdu_buffer) +bool nr_pdcp_data_req_drb(protocol_ctxt_t *ctxt_pP, + const srb_flag_t srb_flagP, + const rb_id_t rb_id, + const mui_t muiP, + const confirm_t confirmP, + const sdu_size_t sdu_buffer_size, + unsigned char *const sdu_buffer, + const pdcp_transmission_mode_t mode, + const uint32_t *const sourceL2Id, + const uint32_t *const destinationL2Id) { + DevAssert(srb_flagP == SRB_FLAG_NO); + LOG_D(PDCP, "%s() called, size %d\n", __func__, sdu_buffer_size); nr_pdcp_ue_t *ue; nr_pdcp_entity_t *rb; @@ -1268,10 +1189,15 @@ static bool pdcp_data_req_drb(protocol_ctxt_t *ctxt_pP, return 0; } - rb->recv_sdu(rb, (char *)sdu_buffer, sdu_buffer_size, muiP); + int max_size = sdu_buffer_size + 3 + 4; // 3: max header, 4: max integrity + char pdu_buf[max_size]; + int pdu_size = rb->process_sdu(rb, (char *)sdu_buffer, sdu_buffer_size, muiP, pdu_buf, max_size); + deliver_pdu deliver_pdu_cb = rb->deliver_pdu; nr_pdcp_manager_unlock(nr_pdcp_ue_manager); + deliver_pdu_cb(NULL, ue_id, rb_id, pdu_buf, pdu_size, muiP); + return 1; } @@ -1301,23 +1227,20 @@ bool cu_f1u_data_req(protocol_ctxt_t *ctxt_pP, return ret; } +/* hack: dummy function needed due to LTE dependencies */ bool pdcp_data_req(protocol_ctxt_t *ctxt_pP, - const srb_flag_t srb_flagP, - const rb_id_t rb_id, - const mui_t muiP, - const confirm_t confirmP, - const sdu_size_t sdu_buffer_size, - unsigned char *const sdu_buffer, - const pdcp_transmission_mode_t mode, + const srb_flag_t srb_flagP, + const rb_id_t rb_idP, + const mui_t muiP, + const confirm_t confirmP, + const sdu_size_t sdu_buffer_sizeP, + unsigned char *const sdu_buffer_pP, + const pdcp_transmission_mode_t modeP, const uint32_t *const sourceL2Id, const uint32_t *const destinationL2Id) { - if (srb_flagP) { - return pdcp_data_req_srb(ctxt_pP, rb_id, muiP, confirmP, sdu_buffer_size, sdu_buffer); - } - else{ - return pdcp_data_req_drb(ctxt_pP, rb_id, muiP, confirmP, sdu_buffer_size, sdu_buffer); - } + abort(); + return false; } void pdcp_set_pdcp_data_ind_func(pdcp_data_ind_func_t pdcp_data_ind) diff --git a/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.h b/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.h new file mode 100644 index 0000000000..0fd23d2f6b --- /dev/null +++ b/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.h @@ -0,0 +1,111 @@ +/* + * 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 + */ + +#ifndef NR_PDCP_OAI_API_H +#define NR_PDCP_OAI_API_H + +#include "pdcp.h" +#include "nr_pdcp_ue_manager.h" + +void nr_pdcp_layer_init(void); +uint64_t nr_pdcp_module_init(uint64_t _pdcp_optmask, int id); + +void du_rlc_data_req(const protocol_ctxt_t *const ctxt_pP, + const srb_flag_t srb_flagP, + const MBMS_flag_t MBMS_flagP, + const rb_id_t rb_idP, + const mui_t muiP, + confirm_t confirmP, + sdu_size_t sdu_sizeP, + mem_block_t *sdu_pP); + +bool pdcp_data_ind(const protocol_ctxt_t *const ctxt_pP, + const srb_flag_t srb_flagP, + const MBMS_flag_t MBMS_flagP, + const rb_id_t rb_id, + const sdu_size_t sdu_buffer_size, + mem_block_t *const sdu_buffer, + const uint32_t *const srcID, + const uint32_t *const dstID); + +void nr_pdcp_add_drbs(eNB_flag_t enb_flag, + ue_id_t rntiMaybeUEid, + ue_id_t reestablish_ue_id, + NR_DRB_ToAddModList_t *const drb2add_list, + const uint8_t security_modeP, + uint8_t *const kUPenc, + uint8_t *const kUPint, + struct NR_CellGroupConfig__rlc_BearerToAddModList *rlc_bearer2add_list); + +void nr_DRB_preconfiguration(ue_id_t crntiMaybeUEid); + +bool nr_pdcp_remove_UE(ue_id_t ue_id); + +void nr_pdcp_config_set_security(ue_id_t ue_id, + const rb_id_t rb_id, + const uint8_t security_modeP, + uint8_t *const kRRCenc_pP, + uint8_t *const kRRCint_pP, + uint8_t *const kUPenc_pP); + +bool cu_f1u_data_req(protocol_ctxt_t *ctxt_pP, + const srb_flag_t srb_flagP, + const rb_id_t rb_id, + const mui_t muiP, + const confirm_t confirmP, + const sdu_size_t sdu_buffer_size, + unsigned char *const sdu_buffer, + const pdcp_transmission_mode_t mode, + const uint32_t *const sourceL2Id, + const uint32_t *const destinationL2Id); + +typedef void (*deliver_pdu)(void *data, ue_id_t ue_id, int srb_id, + char *buf, int size, int sdu_id); +/* default implementation of deliver_pdu */ +void deliver_pdu_srb_rlc(void *data, ue_id_t ue_id, int srb_id, char *buf, + int size, int sdu_id); +void deliver_pdu_srb_f1(void *data, ue_id_t ue_id, int srb_id, char *buf, + int size, int sdu_id); +bool nr_pdcp_data_req_srb(ue_id_t ue_id, + const rb_id_t rb_id, + const mui_t muiP, + const sdu_size_t sdu_buffer_size, + unsigned char *const sdu_buffer, + deliver_pdu deliver_cb, + void *data); +bool nr_pdcp_data_req_drb(protocol_ctxt_t *ctxt_pP, + const srb_flag_t srb_flagP, + const rb_id_t rb_id, + const mui_t muiP, + const confirm_t confirmP, + const sdu_size_t sdu_buffer_size, + unsigned char *const sdu_buffer, + const pdcp_transmission_mode_t mode, + const uint32_t *const sourceL2Id, + const uint32_t *const destinationL2Id); + +void nr_pdcp_tick(int frame, int subframe); + +nr_pdcp_ue_manager_t *nr_pdcp_sdap_get_ue_manager(); + +const bool nr_pdcp_get_statistics(ue_id_t ue_id, int srb_flag, int rb_id, nr_pdcp_statistics_t *out); + +#endif /* NR_PDCP_OAI_API_H */ diff --git a/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.c b/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.c index dab6f9fe58..103044f1bc 100644 --- a/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.c +++ b/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.c @@ -21,7 +21,7 @@ /* from openair */ #include "rlc.h" -#include "pdcp.h" +#include "LAYER2/nr_pdcp/nr_pdcp_oai_api.h" /* from nr rlc module */ #include "nr_rlc_asn1_utils.h" diff --git a/openair2/LAYER2/openair2_proc.c b/openair2/LAYER2/openair2_proc.c index 6ef447df5f..d68232b2e2 100644 --- a/openair2/LAYER2/openair2_proc.c +++ b/openair2/LAYER2/openair2_proc.c @@ -34,7 +34,7 @@ #include "LAYER2/RLC/rlc.h" #include "LAYER2/MAC/mac.h" #include "LAYER2/MAC/mac_extern.h" -#include "LAYER2/PDCP_v10.1.0/pdcp.h" +#include "LAYER2/nr_pdcp/nr_pdcp_oai_api.h" #include "common/utils/LOG/log.h" #include "common/ran_context.h" diff --git a/openair2/NR_PHY_INTERFACE/NR_IF_Module.c b/openair2/NR_PHY_INTERFACE/NR_IF_Module.c index 60db353949..117b028c9a 100644 --- a/openair2/NR_PHY_INTERFACE/NR_IF_Module.c +++ b/openair2/NR_PHY_INTERFACE/NR_IF_Module.c @@ -39,12 +39,12 @@ #include "nfapi/oai_integration/vendor_ext.h" #include "nfapi/oai_integration/gnb_ind_vars.h" #include "openair2/PHY_INTERFACE/queue_t.h" +#include "openair2/NR_PHY_INTERFACE/nr_sched_response.h" #define MAX_IF_MODULES 100 //#define UL_HARQ_PRINT static NR_IF_Module_t *nr_if_inst[MAX_IF_MODULES]; -static NR_Sched_Rsp_t NR_Sched_INFO[MAX_IF_MODULES][MAX_NUM_CCs]; extern int oai_nfapi_harq_indication(nfapi_harq_indication_t *harq_ind); extern int oai_nfapi_crc_indication(nfapi_crc_indication_t *crc_ind); extern int oai_nfapi_cqi_indication(nfapi_cqi_indication_t *cqi_ind); @@ -389,7 +389,7 @@ void NR_UL_indication(NR_UL_IND_t *UL_info) { AssertFatal(UL_info!=NULL,"UL_info is null\n"); module_id_t module_id = UL_info->module_id; int CC_id = UL_info->CC_id; - NR_Sched_Rsp_t *sched_info = &NR_Sched_INFO[module_id][CC_id]; + NR_Sched_Rsp_t *sched_info; NR_IF_Module_t *ifi = nr_if_inst[module_id]; LOG_D(NR_PHY,"SFN/SLOT:%d.%d module_id:%d CC_id:%d UL_info[rach_pdus:%zu rx_ind:%zu crcs:%zu]\n", @@ -451,8 +451,6 @@ void NR_UL_indication(NR_UL_IND_t *UL_info) { } if (NFAPI_MODE != NFAPI_MODE_PNF) { gNB_MAC_INST *mac = RC.nrmac[module_id]; - // clear UL DCI prior to handling ULSCH - mac->UL_dci_req[CC_id].numPdus = 0; if (ifi->CC_mask==0) { ifi->current_frame = UL_info->frame; ifi->current_slot = UL_info->slot; @@ -471,21 +469,20 @@ void NR_UL_indication(NR_UL_IND_t *UL_info) { */ nfapi_nr_config_request_scf_t *cfg = &mac->config[CC_id]; int spf = get_spf(cfg); + sched_info = allocate_sched_response(); + // clear UL DCI prior to handling ULSCH + sched_info->UL_dci_req.numPdus = 0; gNB_dlsch_ulsch_scheduler(module_id, - (UL_info->frame+((UL_info->slot>(spf-1-ifi->sl_ahead))?1:0)) % 1024, - (UL_info->slot+ifi->sl_ahead)%spf); + (UL_info->frame + ((UL_info->slot > (spf - 1 - ifi->sl_ahead)) ? 1 : 0)) % 1024, + (UL_info->slot + ifi->sl_ahead) % spf, + sched_info); ifi->CC_mask = 0; sched_info->module_id = module_id; sched_info->CC_id = CC_id; sched_info->frame = (UL_info->frame + ((UL_info->slot>(spf-1-ifi->sl_ahead)) ? 1 : 0)) % 1024; sched_info->slot = (UL_info->slot+ifi->sl_ahead)%spf; - sched_info->DL_req = &mac->DL_req[CC_id]; - sched_info->UL_dci_req = &mac->UL_dci_req[CC_id]; - sched_info->UL_tti_req = mac->UL_tti_req[CC_id]; - - sched_info->TX_req = &mac->TX_req[CC_id]; #ifdef DUMP_FAPI dump_dl(sched_info); #endif @@ -496,10 +493,11 @@ void NR_UL_indication(NR_UL_IND_t *UL_info) { CC_id); ifi->NR_Schedule_response(sched_info); - LOG_D(NR_PHY,"NR_Schedule_response: SFN SLOT:%d %d dl_pdus:%d\n", - sched_info->frame, - sched_info->slot, - sched_info->DL_req->dl_tti_request_body.nPDUs); + LOG_D(NR_PHY, + "NR_Schedule_response: SFN SLOT:%d %d dl_pdus:%d\n", + sched_info->frame, + sched_info->slot, + sched_info->DL_req.dl_tti_request_body.nPDUs); } } } @@ -520,5 +518,7 @@ NR_IF_Module_t *NR_IF_Module_init(int Mod_id) { "allocation of nr_if_inst[%d]->if_mutex fails\n",Mod_id); } + init_sched_response(); + return nr_if_inst[Mod_id]; } diff --git a/openair2/NR_PHY_INTERFACE/NR_IF_Module.h b/openair2/NR_PHY_INTERFACE/NR_IF_Module.h index 47e961da2b..f85d44398f 100644 --- a/openair2/NR_PHY_INTERFACE/NR_IF_Module.h +++ b/openair2/NR_PHY_INTERFACE/NR_IF_Module.h @@ -83,6 +83,8 @@ typedef struct { typedef struct { + /// the ID of this sched_response - used by sched_reponse memory management + int sched_response_id; /// Module ID module_id_t module_id; /// CC ID @@ -92,13 +94,13 @@ typedef struct { /// slot slot_t slot; /// nFAPI DL Config Request - nfapi_nr_dl_tti_request_t *DL_req; + nfapi_nr_dl_tti_request_t DL_req; /// nFAPI UL Config Request - nfapi_nr_ul_tti_request_t *UL_tti_req; + nfapi_nr_ul_tti_request_t UL_tti_req; /// nFAPI UL_DCI Request - nfapi_nr_ul_dci_request_t *UL_dci_req; + nfapi_nr_ul_dci_request_t UL_dci_req; /// Pointers to DL SDUs - nfapi_nr_tx_data_request_t *TX_req; + nfapi_nr_tx_data_request_t TX_req; } NR_Sched_Rsp_t; typedef struct { diff --git a/openair2/NR_PHY_INTERFACE/nr_sched_response.c b/openair2/NR_PHY_INTERFACE/nr_sched_response.c new file mode 100644 index 0000000000..f0aa25781c --- /dev/null +++ b/openair2/NR_PHY_INTERFACE/nr_sched_response.c @@ -0,0 +1,153 @@ +/* + * 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 + */ + +/* sched response memory management */ + +/* A system with reference counting is implemented. + * It is needed because several threads will access the structure, + * which has to be released only when all the threads are done with it. + * So the main thread allocates a sched_response with allocate_sched_response() + * which allocates a sched_response with a reference counter == 1 + * and then for each other thread that will access sched_response, a + * call to inc_ref_sched_response() is done. When a thread has finished + * using the sched_response, it calls deref_sched_response() which will + * in turn call release_sched_response() when the reference counter becomes 0. + * + * The several threads in question are accessing the _same_ sched_response, + * it has not to be confused with the various TX processes that may run in + * parallel and which are accessing _different_ sched_response (the maximum + * number of parallel processes is N_RESP). + */ + +#include "nr_sched_response.h" + +#include +#include + +#include "common/utils/LOG/log.h" +#include "common/utils/assertions.h" + +#define N_RESP 3 +static NR_Sched_Rsp_t resp[N_RESP]; +static int resp_refcount[N_RESP]; +static int resp_freelist_next[N_RESP]; +static int resp_freelist_head; +static pthread_mutex_t resp_mutex = PTHREAD_MUTEX_INITIALIZER; +static bool resp_freelist_inited = false; + +void init_sched_response(void) +{ + /* init only once */ + if (pthread_mutex_lock(&resp_mutex)) + AssertFatal(0, "pthread_mutex_lock failed\n"); + if (resp_freelist_inited) { + if (pthread_mutex_unlock(&resp_mutex)) + AssertFatal(0, "pthread_mutex_unlock failed\n"); + return; + } + resp_freelist_inited = true; + if (pthread_mutex_unlock(&resp_mutex)) + AssertFatal(0, "pthread_mutex_unlock failed\n"); + + int i; + for (i = 0; i < N_RESP - 1; i++) + resp_freelist_next[i] = i + 1; + resp_freelist_next[N_RESP - 1] = -1; + resp_freelist_head = 0; +} + +NR_Sched_Rsp_t *allocate_sched_response(void) +{ + NR_Sched_Rsp_t *ret; + int new_head; + + if (pthread_mutex_lock(&resp_mutex)) + AssertFatal(0, "pthread_mutex_lock failed\n"); + + AssertFatal(resp_freelist_inited, "sched_response used before init\n"); + + if (resp_freelist_head == -1) { + LOG_E(PHY, "fatal: sched_response cannot be allocated, increase N_RESP\n"); + exit(1); + } + + ret = &resp[resp_freelist_head]; + ret->sched_response_id = resp_freelist_head; + resp_refcount[resp_freelist_head] = 1; + + new_head = resp_freelist_next[resp_freelist_head]; + resp_freelist_next[resp_freelist_head] = -1; + resp_freelist_head = new_head; + + if (pthread_mutex_unlock(&resp_mutex)) + AssertFatal(0, "pthread_mutex_unlock failed\n"); + + return ret; +} + +static void release_sched_response(int sched_response_id) +{ + resp_freelist_next[sched_response_id] = resp_freelist_head; + resp_freelist_head = sched_response_id; +} + +void deref_sched_response(int sched_response_id) +{ + /* simulators (ulsim/dlsim) deal with their own sched_response but call + * functions that call this one, let's handle this case with a special + * value -1 where we do nothing (yes it's a hack) + */ + if (sched_response_id == -1) + return; + + if (pthread_mutex_lock(&resp_mutex)) + AssertFatal(0, "pthread_mutex_lock failed\n"); + + AssertFatal(resp_freelist_inited, "sched_response used before init\n"); + AssertFatal(resp_refcount[sched_response_id] > 0, "sched_reponse decreased too much\n"); + + resp_refcount[sched_response_id]--; + if (resp_refcount[sched_response_id] == 0) + release_sched_response(sched_response_id); + + if (pthread_mutex_unlock(&resp_mutex)) + AssertFatal(0, "pthread_mutex_unlock failed\n"); +} + +void inc_ref_sched_response(int sched_response_id) +{ + /* simulators (ulsim/dlsim) deal with their own sched_response but call + * functions that call this one, let's handle this case with a special + * value -1 where we do nothing (yes it's a hack) + */ + if (sched_response_id == -1) + return; + + if (pthread_mutex_lock(&resp_mutex)) + AssertFatal(0, "pthread_mutex_lock failed\n"); + + AssertFatal(resp_freelist_inited, "sched_response used before init\n"); + + resp_refcount[sched_response_id]++; + + if (pthread_mutex_unlock(&resp_mutex)) + AssertFatal(0, "pthread_mutex_unlock failed\n"); +} diff --git a/openair2/NR_PHY_INTERFACE/nr_sched_response.h b/openair2/NR_PHY_INTERFACE/nr_sched_response.h new file mode 100644 index 0000000000..33a0af93d0 --- /dev/null +++ b/openair2/NR_PHY_INTERFACE/nr_sched_response.h @@ -0,0 +1,32 @@ +/* + * 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 + */ + +#ifndef OPENAIR2_NR_PHY_INTERFACE_NR_SCHED_RESPONSE_H +#define OPENAIR2_NR_PHY_INTERFACE_NR_SCHED_RESPONSE_H + +#include "NR_IF_Module.h" + +void init_sched_response(void); +NR_Sched_Rsp_t *allocate_sched_response(void); +void deref_sched_response(int sched_response_id); +void inc_ref_sched_response(int sched_response_id); + +#endif /* OPENAIR2_NR_PHY_INTERFACE_NR_SCHED_RESPONSE_H */ diff --git a/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c b/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c index 87d8527eb9..6aa44194a3 100644 --- a/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c +++ b/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c @@ -66,6 +66,7 @@ queue_t nr_dl_tti_req_queue; queue_t nr_tx_req_queue; queue_t nr_ul_dci_req_queue; queue_t nr_ul_tti_req_queue; +pthread_mutex_t mac_IF_mutex; void nrue_init_standalone_socket(int tx_port, int rx_port) { @@ -304,25 +305,24 @@ static void fill_dl_info_with_pdcch(fapi_nr_dci_indication_t *dci, nfapi_nr_dl_d static void fill_mib_in_rx_ind(nfapi_nr_dl_tti_request_pdu_t *pdu_list, fapi_nr_rx_indication_t *rx_ind, int pdu_idx, int pdu_type) { - AssertFatal(pdu_idx < sizeof(rx_ind->rx_indication_body) / sizeof(rx_ind->rx_indication_body[0]), - "pdu_index (%d) is greater than rx_indication_body size!\n", pdu_idx); - AssertFatal(pdu_idx == rx_ind->number_pdus, "Invalid pdu_idx %d!\n", pdu_idx); + AssertFatal(pdu_idx < sizeof(rx_ind->rx_indication_body) / sizeof(rx_ind->rx_indication_body[0]), + "pdu_index (%d) is greater than rx_indication_body size!\n", pdu_idx); + AssertFatal(pdu_idx == rx_ind->number_pdus, "Invalid pdu_idx %d!\n", pdu_idx); - LOG_T(NR_MAC, "Recevied an SSB and are filling rx_ind with the MIB!\n"); - - nfapi_nr_dl_tti_ssb_pdu_rel15_t *ssb_pdu = &pdu_list->ssb_pdu.ssb_pdu_rel15; - rx_ind->rx_indication_body[pdu_idx].ssb_pdu.cell_id = ssb_pdu->PhysCellId; - rx_ind->rx_indication_body[pdu_idx].ssb_pdu.pdu = MALLOC(3 * sizeof(*rx_ind->rx_indication_body[pdu_idx].ssb_pdu.pdu)); - rx_ind->rx_indication_body[pdu_idx].ssb_pdu.pdu[0] = (ssb_pdu->bchPayload) & 0xff; - rx_ind->rx_indication_body[pdu_idx].ssb_pdu.pdu[1] = (ssb_pdu->bchPayload >> 8) & 0xff; - rx_ind->rx_indication_body[pdu_idx].ssb_pdu.pdu[2] = (ssb_pdu->bchPayload >> 16) & 0xff; - rx_ind->rx_indication_body[pdu_idx].ssb_pdu.rsrp_dBm = ssb_pdu->ssbRsrp; - rx_ind->rx_indication_body[pdu_idx].ssb_pdu.ssb_index = ssb_pdu->SsbBlockIndex; - rx_ind->rx_indication_body[pdu_idx].ssb_pdu.ssb_length = pdu_list->PDUSize; - rx_ind->rx_indication_body[pdu_idx].ssb_pdu.ssb_start_subcarrier = ssb_pdu->SsbSubcarrierOffset; - rx_ind->rx_indication_body[pdu_idx].pdu_type = pdu_type; - rx_ind->number_pdus = pdu_idx + 1; + LOG_T(NR_MAC, "Recevied an SSB and are filling rx_ind with the MIB!\n"); + nfapi_nr_dl_tti_ssb_pdu_rel15_t *ssb_pdu = &pdu_list->ssb_pdu.ssb_pdu_rel15; + rx_ind->rx_indication_body[pdu_idx].ssb_pdu.cell_id = ssb_pdu->PhysCellId; + rx_ind->rx_indication_body[pdu_idx].ssb_pdu.pdu[0] = (ssb_pdu->bchPayload) & 0xff; + rx_ind->rx_indication_body[pdu_idx].ssb_pdu.pdu[1] = (ssb_pdu->bchPayload >> 8) & 0xff; + rx_ind->rx_indication_body[pdu_idx].ssb_pdu.pdu[2] = (ssb_pdu->bchPayload >> 16) & 0xff; + rx_ind->rx_indication_body[pdu_idx].ssb_pdu.rsrp_dBm = ssb_pdu->ssbRsrp; + rx_ind->rx_indication_body[pdu_idx].ssb_pdu.ssb_index = ssb_pdu->SsbBlockIndex; + rx_ind->rx_indication_body[pdu_idx].ssb_pdu.ssb_length = pdu_list->PDUSize; + rx_ind->rx_indication_body[pdu_idx].ssb_pdu.ssb_start_subcarrier = ssb_pdu->SsbSubcarrierOffset; + rx_ind->rx_indication_body[pdu_idx].ssb_pdu.decoded_pdu = true; + rx_ind->rx_indication_body[pdu_idx].pdu_type = pdu_type; + rx_ind->number_pdus = pdu_idx + 1; } static bool is_my_dci(NR_UE_MAC_INST_t *mac, nfapi_nr_dl_dci_pdu_t *received_pdu) @@ -692,7 +692,6 @@ void check_and_process_dci(nfapi_nr_dl_tti_request_t *dl_tti_request, slot = dl_tti_request->Slot; LOG_D(NR_PHY, "[%d, %d] dl_tti_request\n", frame, slot); copy_dl_tti_req_to_dl_info(&mac->dl_info, dl_tti_request); - free_and_zero(dl_tti_request); } /* This checks if the previously recevied DCI matches our current RNTI value. The assumption is that if the DCI matches our RNTI, then the @@ -711,14 +710,12 @@ void check_and_process_dci(nfapi_nr_dl_tti_request_t *dl_tti_request, else { LOG_D(NR_MAC, "Unexpected tx_data_req\n"); } - free_and_zero(tx_data_request); } else if (ul_dci_request) { frame = ul_dci_request->SFN; slot = ul_dci_request->Slot; LOG_D(NR_PHY, "[%d, %d] ul_dci_request\n", frame, slot); copy_ul_dci_data_req_to_dl_info(&mac->dl_info, ul_dci_request); - free_and_zero(ul_dci_request); } else if (ul_tti_request) { frame = ul_tti_request->SFN; @@ -735,7 +732,10 @@ void check_and_process_dci(nfapi_nr_dl_tti_request_t *dl_tti_request, NR_UL_TIME_ALIGNMENT_t ul_time_alignment; memset(&ul_time_alignment, 0, sizeof(ul_time_alignment)); - fill_dci_from_dl_config(&mac->dl_info, &mac->dl_config_request); + if (dl_tti_request || tx_data_request || ul_dci_request) { + fapi_nr_dl_config_request_t *dl_config = get_dl_config_request(mac, slot); + fill_dci_from_dl_config(&mac->dl_info, dl_config); + } nr_ue_dl_scheduler(&mac->dl_info); nr_ue_dl_indication(&mac->dl_info, &ul_time_alignment); @@ -1045,18 +1045,26 @@ int handle_bcch_bch(module_id_t module_id, int cc_id, uint16_t ssb_start_subcarrier, uint16_t cell_id){ return nr_ue_decode_mib(module_id, - cc_id, - gNB_index, - phy_data, - additional_bits, - ssb_length, // Lssb = 64 is not support - ssb_index, - pduP, - ssb_start_subcarrier, - cell_id); + cc_id, + gNB_index, + phy_data, + additional_bits, + ssb_length, // Lssb = 64 is not support + ssb_index, + pduP, + ssb_start_subcarrier, + cell_id); } +void handle_bch_failure(NR_UE_MAC_INST_t *mac) +{ + mac->ssb_measurements.consecutive_bch_failures++; + //TODO handle this properly by scheduling re-synchronization + AssertFatal(mac->ssb_measurements.consecutive_bch_failures < 100, + "Radio link failure caused by 100 consecutive PBCH detection failures.\n"); +} + // L2 Abstraction Layer int handle_bcch_dlsch(module_id_t module_id, int cc_id, unsigned int gNB_index, uint8_t ack_nack, uint8_t *pduP, uint32_t pdu_len){ return nr_ue_decode_BCCH_DL_SCH(module_id, cc_id, gNB_index, ack_nack, pduP, pdu_len); @@ -1069,10 +1077,10 @@ int handle_dci(module_id_t module_id, int cc_id, unsigned int gNB_index, frame_t } -void handle_ssb_meas(NR_UE_MAC_INST_t *mac, uint8_t ssb_index, int16_t rsrp_dbm) +void handle_ssb_meas(NR_UE_MAC_INST_t *mac, uint8_t ssb_index, int16_t rsrp_dbm) { - mac->phy_measurements.ssb_index = ssb_index; - mac->phy_measurements.ssb_rsrp_dBm = rsrp_dbm; + mac->ssb_measurements.ssb_index = ssb_index; + mac->ssb_measurements.ssb_rsrp_dBm = rsrp_dbm; } // L2 Abstraction Layer @@ -1116,6 +1124,9 @@ void update_harq_status(module_id_t module_id, uint8_t harq_pid, uint8_t ack_nac int nr_ue_ul_indication(nr_uplink_indication_t *ul_info) { + + pthread_mutex_lock(&mac_IF_mutex); + module_id_t module_id = ul_info->module_id; NR_UE_MAC_INST_t *mac = get_mac_inst(module_id); @@ -1125,15 +1136,19 @@ int nr_ue_ul_indication(nr_uplink_indication_t *ul_info) NR_TDD_UL_DL_ConfigCommon_t *tdd_UL_DL_ConfigurationCommon = mac->scc != NULL ? mac->scc->tdd_UL_DL_ConfigurationCommon : mac->scc_SIB->tdd_UL_DL_ConfigurationCommon; if (mac->phy_config_request_sent && is_nr_UL_slot(tdd_UL_DL_ConfigurationCommon, ul_info->slot_tx, mac->frame_type)) nr_ue_ul_scheduler(ul_info); + + pthread_mutex_unlock(&mac_IF_mutex); + return 0; } int nr_ue_dl_indication(nr_downlink_indication_t *dl_info, NR_UL_TIME_ALIGNMENT_t *ul_time_alignment){ + pthread_mutex_lock(&mac_IF_mutex); uint32_t ret_mask = 0x0; module_id_t module_id = dl_info->module_id; NR_UE_MAC_INST_t *mac = get_mac_inst(module_id); - fapi_nr_dl_config_request_t *dl_config = &mac->dl_config_request; + fapi_nr_dl_config_request_t *dl_config = get_dl_config_request(mac, dl_info->slot); if ((!dl_info->dci_ind && !dl_info->rx_ind)) { // UL indication to schedule DCI reception @@ -1160,7 +1175,7 @@ int nr_ue_dl_indication(nr_downlink_indication_t *dl_info, NR_UL_TIME_ALIGNMENT_ LOG_D(NR_MAC, "We are filtering a UL_DCI to prevent it from being treated like a DL_DCI\n"); continue; } - dci_pdu_rel15_t *def_dci_pdu_rel15 = &mac->def_dci_pdu_rel15[dci_index->dci_format]; + dci_pdu_rel15_t *def_dci_pdu_rel15 = &mac->def_dci_pdu_rel15[dl_info->slot][dci_index->dci_format]; g_harq_pid = def_dci_pdu_rel15->harq_pid; LOG_T(NR_MAC, "Setting harq_pid = %d and dci_index = %d (based on format)\n", g_harq_pid, dci_index->dci_format); @@ -1180,31 +1195,35 @@ int nr_ue_dl_indication(nr_downlink_indication_t *dl_info, NR_UL_TIME_ALIGNMENT_ for (int i=0; irx_ind->number_pdus; ++i) { + fapi_nr_rx_indication_body_t rx_indication_body = dl_info->rx_ind->rx_indication_body[i]; LOG_D(NR_MAC, "In %s sending DL indication to MAC. 1 PDU type %d of %d total number of PDUs \n", __FUNCTION__, - dl_info->rx_ind->rx_indication_body[i].pdu_type, + rx_indication_body.pdu_type, dl_info->rx_ind->number_pdus); - switch(dl_info->rx_ind->rx_indication_body[i].pdu_type){ + switch(rx_indication_body.pdu_type){ case FAPI_NR_RX_PDU_TYPE_SSB: - handle_ssb_meas(mac, - (dl_info->rx_ind->rx_indication_body+i)->ssb_pdu.ssb_index, - (dl_info->rx_ind->rx_indication_body+i)->ssb_pdu.rsrp_dBm); - ret_mask |= (handle_bcch_bch(dl_info->module_id, dl_info->cc_id, dl_info->gNB_index, dl_info->phy_data, - (dl_info->rx_ind->rx_indication_body+i)->ssb_pdu.pdu, - (dl_info->rx_ind->rx_indication_body+i)->ssb_pdu.additional_bits, - (dl_info->rx_ind->rx_indication_body+i)->ssb_pdu.ssb_index, - (dl_info->rx_ind->rx_indication_body+i)->ssb_pdu.ssb_length, - (dl_info->rx_ind->rx_indication_body+i)->ssb_pdu.ssb_start_subcarrier, - (dl_info->rx_ind->rx_indication_body+i)->ssb_pdu.cell_id)) << FAPI_NR_RX_PDU_TYPE_SSB; - free((dl_info->rx_ind->rx_indication_body+i)->ssb_pdu.pdu); + if(rx_indication_body.ssb_pdu.decoded_pdu) { + handle_ssb_meas(mac, + rx_indication_body.ssb_pdu.ssb_index, + rx_indication_body.ssb_pdu.rsrp_dBm); + ret_mask |= (handle_bcch_bch(dl_info->module_id, dl_info->cc_id, dl_info->gNB_index, dl_info->phy_data, + rx_indication_body.ssb_pdu.pdu, + rx_indication_body.ssb_pdu.additional_bits, + rx_indication_body.ssb_pdu.ssb_index, + rx_indication_body.ssb_pdu.ssb_length, + rx_indication_body.ssb_pdu.ssb_start_subcarrier, + rx_indication_body.ssb_pdu.cell_id)) << FAPI_NR_RX_PDU_TYPE_SSB; + } + else + handle_bch_failure(mac); break; case FAPI_NR_RX_PDU_TYPE_SIB: ret_mask |= (handle_bcch_dlsch(dl_info->module_id, dl_info->cc_id, dl_info->gNB_index, - (dl_info->rx_ind->rx_indication_body+i)->pdsch_pdu.ack_nack, - (dl_info->rx_ind->rx_indication_body+i)->pdsch_pdu.pdu, - (dl_info->rx_ind->rx_indication_body+i)->pdsch_pdu.pdu_length)) << FAPI_NR_RX_PDU_TYPE_SIB; + rx_indication_body.pdsch_pdu.ack_nack, + rx_indication_body.pdsch_pdu.pdu, + rx_indication_body.pdsch_pdu.pdu_length)) << FAPI_NR_RX_PDU_TYPE_SIB; break; case FAPI_NR_RX_PDU_TYPE_DLSCH: ret_mask |= (handle_dlsch(dl_info, ul_time_alignment, i)) << FAPI_NR_RX_PDU_TYPE_DLSCH; @@ -1216,16 +1235,16 @@ int nr_ue_dl_indication(nr_downlink_indication_t *dl_info, NR_UL_TIME_ALIGNMENT_ ret_mask |= (handle_csirs_measurements(dl_info->module_id, dl_info->frame, dl_info->slot, - &(dl_info->rx_ind->rx_indication_body+i)->csirs_measurements)) << FAPI_NR_CSIRS_IND; + &rx_indication_body.csirs_measurements)) << FAPI_NR_CSIRS_IND; break; default: break; } } - free(dl_info->rx_ind); dl_info->rx_ind = NULL; } } + pthread_mutex_unlock(&mac_IF_mutex); return 0; } @@ -1239,6 +1258,7 @@ nr_ue_if_module_t *nr_ue_if_module_init(uint32_t module_id){ nr_ue_if_module_inst[module_id]->current_frame = 0; nr_ue_if_module_inst[module_id]->current_slot = 0; nr_ue_if_module_inst[module_id]->phy_config_request = nr_ue_phy_config_request; + nr_ue_if_module_inst[module_id]->synch_request = nr_ue_synch_request; if (get_softmodem_params()->emulate_l1) nr_ue_if_module_inst[module_id]->scheduled_response = nr_ue_scheduled_response_stub; else @@ -1246,6 +1266,7 @@ nr_ue_if_module_t *nr_ue_if_module_init(uint32_t module_id){ nr_ue_if_module_inst[module_id]->dl_indication = nr_ue_dl_indication; nr_ue_if_module_inst[module_id]->ul_indication = nr_ue_ul_indication; } + pthread_mutex_init(&mac_IF_mutex, NULL); return nr_ue_if_module_inst[module_id]; } @@ -1262,8 +1283,8 @@ int nr_ue_dcireq(nr_dcireq_t *dcireq) { fapi_nr_dl_config_request_t *dl_config = &dcireq->dl_config_req; NR_UE_MAC_INST_t *UE_mac = get_mac_inst(0); - dl_config->sfn = UE_mac->dl_config_request.sfn; - dl_config->slot = UE_mac->dl_config_request.slot; + dl_config->sfn = dcireq->frame; + dl_config->slot = dcireq->slot; LOG_T(PHY, "Entering UE DCI configuration frame %d slot %d \n", dcireq->frame, dcireq->slot); diff --git a/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.h b/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.h index e3adfe7d53..91775794ed 100644 --- a/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.h +++ b/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.h @@ -151,6 +151,16 @@ typedef struct { } nr_phy_config_t; +typedef struct { + /// module id + uint8_t Mod_id; + /// component carrier id + uint8_t CC_id; + /// Flag signaling that synch_request was received + uint8_t received_synch_request; + /// NR UE FAPI message + fapi_nr_synch_request_t synch_req; +} nr_synch_request_t; /* * Generic type of an application-defined callback to return various @@ -171,6 +181,12 @@ typedef int8_t (nr_ue_scheduled_response_f)(nr_scheduled_response_t *scheduled_r */ typedef int8_t (nr_ue_phy_config_request_f)(nr_phy_config_t *phy_config); +/* + * Generic type of an application-defined callback to return various + * types of data to the application. + */ +typedef void (nr_ue_synch_request_f)(nr_synch_request_t *synch_request); + /* * Generic type of an application-defined callback to return various @@ -196,6 +212,7 @@ typedef int (nr_ue_dcireq_f)(nr_dcireq_t *ul_info); typedef struct nr_ue_if_module_s { nr_ue_scheduled_response_f *scheduled_response; nr_ue_phy_config_request_f *phy_config_request; + nr_ue_synch_request_f *synch_request; nr_ue_dl_indication_f *dl_indication; nr_ue_ul_indication_f *ul_indication; //nr_ue_dcireq_f *dcireq; diff --git a/openair2/RRC/LTE/rrc_eNB_S1AP.c b/openair2/RRC/LTE/rrc_eNB_S1AP.c index fbc19d0a47..bc4fc6d8cd 100644 --- a/openair2/RRC/LTE/rrc_eNB_S1AP.c +++ b/openair2/RRC/LTE/rrc_eNB_S1AP.c @@ -921,10 +921,7 @@ int rrc_eNB_process_S1AP_INITIAL_CONTEXT_SETUP_REQ(MessageDef *msg_p, const char create_tunnel_req.rnti = ue_context_p->ue_context.rnti; // warning put zero above // create_tunnel_req.num_tunnels = i; - ret = gtpv1u_create_s1u_tunnel( - instance, - &create_tunnel_req, - &create_tunnel_resp); + ret = gtpv1u_create_s1u_tunnel(instance, &create_tunnel_req, &create_tunnel_resp, pdcp_data_req); if ( ret != 0 ) { LOG_E(RRC,"rrc_eNB_process_S1AP_INITIAL_CONTEXT_SETUP_REQ : gtpv1u_create_s1u_tunnel failed,start to release UE %x\n",ue_context_p->ue_context.rnti); @@ -1234,10 +1231,7 @@ int rrc_eNB_process_S1AP_E_RAB_SETUP_REQ(MessageDef *msg_p, const char *msg_name create_tunnel_req.rnti = ue_context_p->ue_context.rnti; // warning put zero above create_tunnel_req.num_tunnels = e_rab_done; // NN: not sure if we should create a new tunnel: need to check teid, etc. - ret = gtpv1u_create_s1u_tunnel( - instance, - &create_tunnel_req, - &create_tunnel_resp); + ret = gtpv1u_create_s1u_tunnel(instance, &create_tunnel_req, &create_tunnel_resp, pdcp_data_req); if ( ret != 0 ) { LOG_E(RRC,"rrc_eNB_process_S1AP_E_RAB_SETUP_REQ : gtpv1u_create_s1u_tunnel failed,start to release UE %x\n",ue_context_p->ue_context.rnti); @@ -1908,14 +1902,8 @@ int rrc_eNB_send_PATH_SWITCH_REQ(const protocol_ctxt_t *const ctxt_pP, S1AP_PATH_SWITCH_REQ (msg_p).nb_of_e_rabs = e_rabs_done; create_tunnel_req.rnti = ue_context_pP->ue_context.rnti; create_tunnel_req.num_tunnels = e_rabs_done; - gtpv1u_create_s1u_tunnel( - ctxt_pP->instance, - &create_tunnel_req, - &create_tunnel_resp); - rrc_eNB_process_GTPV1U_CREATE_TUNNEL_RESP( - ctxt_pP, - &create_tunnel_resp, - &inde_list[0]); + gtpv1u_create_s1u_tunnel(ctxt_pP->instance, &create_tunnel_req, &create_tunnel_resp, pdcp_data_req); + rrc_eNB_process_GTPV1U_CREATE_TUNNEL_RESP(ctxt_pP, &create_tunnel_resp, &inde_list[0]); for (e_rab = 0; e_rab < e_rabs_done; e_rab++) { S1AP_PATH_SWITCH_REQ (msg_p).e_rabs_tobeswitched[e_rab].e_rab_id = create_tunnel_resp.eps_bearer_id[e_rab]; diff --git a/openair2/RRC/NR/L2_nr_interface.c b/openair2/RRC/NR/L2_nr_interface.c index 4a88b153bd..d8d43e490c 100644 --- a/openair2/RRC/NR/L2_nr_interface.c +++ b/openair2/RRC/NR/L2_nr_interface.c @@ -32,7 +32,6 @@ #include "nr_rrc_defs.h" #include "nr_rrc_extern.h" #include "common/utils/LOG/log.h" -#include "pdcp.h" #include "common/ran_context.h" #include "LAYER2/NR_MAC_COMMON/nr_mac_common.h" #include "LAYER2/NR_MAC_COMMON/nr_mac_extern.h" @@ -43,6 +42,7 @@ #include "NR_BCCH-BCH-Message.h" #include "rrc_gNB_UE_context.h" #include +#include "nr_pdcp/nr_pdcp_oai_api.h" extern RAN_CONTEXT_t RC; @@ -55,56 +55,6 @@ nr_rrc_mac_remove_ue(module_id_t mod_idP, return 0; } -//------------------------------------------------------------------------------ -uint8_t -nr_rrc_data_req( - const protocol_ctxt_t *const ctxt_pP, - const rb_id_t rb_idP, - const mui_t muiP, - const confirm_t confirmP, - const sdu_size_t sdu_sizeP, - uint8_t *const buffer_pP, - const pdcp_transmission_mode_t modeP -) -//------------------------------------------------------------------------------ -{ - - MessageDef *message_p; - // Uses a new buffer to avoid issue with PDCP buffer content that could be changed by PDCP (asynchronous message handling). - uint8_t *message_buffer; - message_buffer = itti_malloc ( - ctxt_pP->enb_flag ? TASK_RRC_GNB : TASK_RRC_UE, - ctxt_pP->enb_flag ? TASK_PDCP_ENB : TASK_PDCP_UE, - sdu_sizeP); - memcpy (message_buffer, buffer_pP, sdu_sizeP); - message_p = itti_alloc_new_message (ctxt_pP->enb_flag ? TASK_RRC_GNB : TASK_RRC_UE, 0, RRC_DCCH_DATA_REQ); - RRC_DCCH_DATA_REQ (message_p).frame = ctxt_pP->frame; - RRC_DCCH_DATA_REQ (message_p).enb_flag = ctxt_pP->enb_flag; - RRC_DCCH_DATA_REQ (message_p).rb_id = rb_idP; - RRC_DCCH_DATA_REQ (message_p).muip = muiP; - RRC_DCCH_DATA_REQ (message_p).confirmp = confirmP; - RRC_DCCH_DATA_REQ (message_p).sdu_size = sdu_sizeP; - RRC_DCCH_DATA_REQ (message_p).sdu_p = message_buffer; - //memcpy (NR_RRC_DCCH_DATA_REQ (message_p).sdu_p, buffer_pP, sdu_sizeP); - RRC_DCCH_DATA_REQ (message_p).mode = modeP; - RRC_DCCH_DATA_REQ (message_p).module_id = ctxt_pP->module_id; - RRC_DCCH_DATA_REQ(message_p).rnti = ctxt_pP->rntiMaybeUEid; - RRC_DCCH_DATA_REQ (message_p).eNB_index = ctxt_pP->eNB_index; - itti_send_msg_to_task ( - ctxt_pP->enb_flag ? TASK_PDCP_ENB : TASK_PDCP_UE, - ctxt_pP->instance, - message_p); - LOG_I(NR_RRC,"send RRC_DCCH_DATA_REQ to PDCP\n"); - - /* Hack: only trigger PDCP if in CU, otherwise it is triggered by RU threads - * Ideally, PDCP would not neet to be triggered like this but react to ITTI - * messages automatically */ - if (ctxt_pP->enb_flag) - pdcp_run(ctxt_pP); - - return true; // TODO should be changed to a CNF message later, currently RRC lite does not used the returned value anyway. -} - uint16_t mac_rrc_nr_data_req(const module_id_t Mod_idP, const int CC_id, const frame_t frameP, diff --git a/openair2/RRC/NR/cucp_cuup_direct.c b/openair2/RRC/NR/cucp_cuup_direct.c index d2c35e2c03..05ec9a837b 100644 --- a/openair2/RRC/NR/cucp_cuup_direct.c +++ b/openair2/RRC/NR/cucp_cuup_direct.c @@ -120,7 +120,11 @@ static int drb_config_gtpu_create(const protocol_ctxt_t *const ctxt_p, } create_tunnel_req.num_tunnels = UE->nb_of_pdusessions; create_tunnel_req.ue_id = UE->rnti; - int ret = gtpv1u_create_ngu_tunnel(getCxtE1(instance)->gtpInstN3, &create_tunnel_req, &create_tunnel_resp); + int ret = gtpv1u_create_ngu_tunnel(getCxtE1(instance)->gtpInstN3, + &create_tunnel_req, + &create_tunnel_resp, + nr_pdcp_data_req_drb, + sdap_data_req); if (ret != 0) { LOG_E(NR_RRC,"rrc_gNB_process_NGAP_PDUSESSION_SETUP_REQ : gtpv1u_create_ngu_tunnel failed,start to release UE rnti %ld\n", diff --git a/openair2/RRC/NR/nr_rrc_common.c b/openair2/RRC/NR/nr_rrc_common.c index 1d231f20bf..c6f27c7325 100644 --- a/openair2/RRC/NR/nr_rrc_common.c +++ b/openair2/RRC/NR/nr_rrc_common.c @@ -37,7 +37,6 @@ #include "COMMON/mac_rrc_primitives.h" #include "common/utils/LOG/log.h" #include "asn1_msg.h" -#include "pdcp.h" #include "common/utils/LOG/vcd_signal_dumper.h" #include "common/ran_context.h" diff --git a/openair2/RRC/NR/nr_rrc_defs.h b/openair2/RRC/NR/nr_rrc_defs.h index e53ad60685..f8d69e942a 100644 --- a/openair2/RRC/NR/nr_rrc_defs.h +++ b/openair2/RRC/NR/nr_rrc_defs.h @@ -271,6 +271,40 @@ typedef struct pdu_session_param_s { uint8_t cause_value; } rrc_pdu_session_param_t; +typedef struct drb_s { + int status; + int defaultDRBid; + int drb_id; + int reestablishPDCP; + int recoverPDCP; + int daps_Config_r16; + struct cnAssociation_s { + int present; + int eps_BearerIdentity; + struct sdap_config_s { + bool defaultDRB; + int pdusession_id; + int sdap_HeaderDL; + int sdap_HeaderUL; + int mappedQoS_FlowsToAdd[QOSFLOW_MAX_VALUE]; + } sdap_config; + } cnAssociation; + struct pdcp_config_s { + int discardTimer; + int pdcp_SN_SizeUL; + int pdcp_SN_SizeDL; + int t_Reordering; + int integrityProtection; + struct headerCompression_s { + int NotUsed; + int present; + } headerCompression; + struct ext1_s { + int cipheringDisabled; + } ext1; + } pdcp_config; +} drb_t; + typedef struct gNB_RRC_UE_s { uint8_t primaryCC_id; NR_SRB_ToAddModList_t *SRB_configList; @@ -278,6 +312,7 @@ typedef struct gNB_RRC_UE_s { NR_DRB_ToAddModList_t *DRB_configList; NR_DRB_ToAddModList_t *DRB_configList2[NR_RRC_TRANSACTION_IDENTIFIER_NUMBER]; NR_DRB_ToReleaseList_t *DRB_Release_configList2[NR_RRC_TRANSACTION_IDENTIFIER_NUMBER]; + drb_t established_drbs[NGAP_MAX_DRBS_PER_UE]; uint8_t DRB_active[NGAP_MAX_DRBS_PER_UE]; NR_SRB_INFO_TABLE_ENTRY Srb[maxSRBs]; // 3gpp max is 3 SRBs, number 1..3, we waste the entry 0 for code simplicity diff --git a/openair2/RRC/NR/nr_rrc_proto.h b/openair2/RRC/NR/nr_rrc_proto.h index 5ad9a71e39..b54165b13f 100644 --- a/openair2/RRC/NR/nr_rrc_proto.h +++ b/openair2/RRC/NR/nr_rrc_proto.h @@ -136,17 +136,6 @@ void nr_rrc_trigger(protocol_ctxt_t *ctxt, int CC_id, int frame, int subframe); \ *reOffset Pointer to RE Offset Value */ void rrc_config_dl_ptrs_params(NR_BWP_Downlink_t *bwp, int *ptrsNrb, int *ptrsMcs, int *epre_Ratio, int * reOffset); -uint8_t -nr_rrc_data_req( - const protocol_ctxt_t *const ctxt_pP, - const rb_id_t rb_idP, - const mui_t muiP, - const confirm_t confirmP, - const sdu_size_t sdu_size, - uint8_t *const buffer_pP, - const pdcp_transmission_mode_t modeP -); - int nr_rrc_mac_remove_ue(module_id_t mod_idP, rnti_t rntiP); diff --git a/openair2/RRC/NR/rrc_gNB.c b/openair2/RRC/NR/rrc_gNB.c index a4f57b0fae..f9447fc57a 100644 --- a/openair2/RRC/NR/rrc_gNB.c +++ b/openair2/RRC/NR/rrc_gNB.c @@ -82,7 +82,7 @@ #include "rrc_gNB_GTPV1U.h" #include "nr_pdcp/nr_pdcp_entity.h" -#include "pdcp.h" +#include "nr_pdcp/nr_pdcp_oai_api.h" #include "intertask_interface.h" #include "SIMULATION/TOOLS/sim.h" // for taus @@ -105,15 +105,6 @@ extern RAN_CONTEXT_t RC; -extern void pdcp_config_set_security(const protocol_ctxt_t *const ctxt_pP, - pdcp_t *const pdcp_pP, - const rb_id_t rb_idP, - const uint16_t lc_idP, - const uint8_t security_modeP, - uint8_t *const kRRCenc, - uint8_t *const kRRCint, - uint8_t *const kUPenc); - static inline uint64_t bitStr_to_uint64(BIT_STRING_t *asn); mui_t rrc_gNB_mui = 0; @@ -582,7 +573,7 @@ static void rrc_gNB_generate_defaultRRCReconfiguration(const protocol_ctxt_t *co ue_context_pP->ue_context.rnti); AssertFatal(!NODE_IS_DU(rrc->node_type), "illegal node type DU!\n"); - nr_rrc_data_req(ctxt_pP, DCCH, rrc_gNB_mui++, SDU_CONFIRM_NO, size, buffer, PDCP_TRANSMISSION_MODE_CONTROL); + nr_pdcp_data_req_srb(ctxt_pP->rntiMaybeUEid, DCCH, rrc_gNB_mui++, size, buffer, deliver_pdu_srb_f1, rrc); if (NODE_IS_DU(rrc->node_type) || NODE_IS_MONOLITHIC(rrc->node_type)) { gNB_RRC_UE_t *ue_p = &ue_context_pP->ue_context; @@ -652,7 +643,8 @@ void fill_DRB_configList(const protocol_ctxt_t *const ctxt_pP, if(drb_is_active(ue_p, drb_id)){ /* Non-GBR flow using the same DRB or a GBR flow with no available DRBs*/ nb_drb_to_setup--; } else { - NR_DRB_ToAddMod_t *DRB_config = generateDRB(ue_p, drb_id, &ue_p->pduSession[i], rrc->configuration.enable_sdap, rrc->security.do_drb_integrity, rrc->security.do_drb_ciphering); + generateDRB(ue_p, drb_id, &ue_p->pduSession[i], rrc->configuration.enable_sdap, rrc->security.do_drb_integrity, rrc->security.do_drb_ciphering); + NR_DRB_ToAddMod_t *DRB_config = generateDRB_ASN1(&ue_p->established_drbs[drb_id-1]); if (drb_id_to_setup_start == 0) drb_id_to_setup_start = DRB_config->drb_Identity; asn1cSeqAdd(&ue_p->DRB_configList->list, DRB_config); @@ -771,14 +763,7 @@ rrc_gNB_generate_dedicatedRRCReconfiguration( ctxt_pP->module_id, DCCH); - nr_rrc_data_req( - ctxt_pP, - DCCH, - rrc_gNB_mui++, - SDU_CONFIRM_NO, - size, - buffer, - PDCP_TRANSMISSION_MODE_CONTROL); + nr_pdcp_data_req_srb(ctxt_pP->rntiMaybeUEid, DCCH, rrc_gNB_mui++, size, buffer, deliver_pdu_srb_f1, rrc); if (NODE_IS_DU(rrc->node_type) || NODE_IS_MONOLITHIC(rrc->node_type)) { nr_mac_update_cellgroup(RC.nrmac[rrc->module_id], ue_context_pP->ue_context.rnti, ue_context_pP->ue_context.masterCellGroup); @@ -945,22 +930,16 @@ rrc_gNB_modify_dedicatedRRCReconfiguration( ctxt_pP->module_id, DCCH); - nr_rrc_data_req( - ctxt_pP, - DCCH, - rrc_gNB_mui++, - SDU_CONFIRM_NO, - size, - buffer, - PDCP_TRANSMISSION_MODE_CONTROL); + gNB_RRC_INST *rrc = RC.nrrrc[ctxt_pP->module_id]; + nr_pdcp_data_req_srb(ctxt_pP->rntiMaybeUEid, DCCH, rrc_gNB_mui++, size, buffer, deliver_pdu_srb_f1, rrc); - if (NODE_IS_DU(RC.nrrrc[ctxt_pP->module_id]->node_type) || NODE_IS_MONOLITHIC(RC.nrrrc[ctxt_pP->module_id]->node_type)) { + if (NODE_IS_DU(rrc->node_type) || NODE_IS_MONOLITHIC(rrc->node_type)) { uint32_t delay_ms = ue_p->masterCellGroup && ue_p->masterCellGroup->spCellConfig && ue_p->masterCellGroup->spCellConfig->spCellConfigDedicated && ue_p->masterCellGroup->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList ? NR_RRC_RECONFIGURATION_DELAY_MS + NR_RRC_BWP_SWITCHING_DELAY_MS : NR_RRC_RECONFIGURATION_DELAY_MS; - nr_mac_enable_ue_rrc_processing_timer(ctxt_pP->module_id, ue_p->rnti, *RC.nrrrc[ctxt_pP->module_id]->carrier.servingcellconfigcommon->ssbSubcarrierSpacing, delay_ms); + nr_mac_enable_ue_rrc_processing_timer(ctxt_pP->module_id, ue_p->rnti, *rrc->carrier.servingcellconfigcommon->ssbSubcarrierSpacing, delay_ms); } } @@ -1035,22 +1014,17 @@ rrc_gNB_generate_dedicatedRRCReconfiguration_release( rrc_gNB_mui, ctxt_pP->module_id, DCCH); - nr_rrc_data_req( - ctxt_pP, - DCCH, - rrc_gNB_mui++, - SDU_CONFIRM_NO, - size, - buffer, - PDCP_TRANSMISSION_MODE_CONTROL); - if (NODE_IS_DU(RC.nrrrc[ctxt_pP->module_id]->node_type) || NODE_IS_MONOLITHIC(RC.nrrrc[ctxt_pP->module_id]->node_type)) { + gNB_RRC_INST *rrc = RC.nrrrc[ctxt_pP->module_id]; + nr_pdcp_data_req_srb(ctxt_pP->rntiMaybeUEid, DCCH, rrc_gNB_mui++, size, buffer, deliver_pdu_srb_f1, rrc); + + if (NODE_IS_DU(rrc->node_type) || NODE_IS_MONOLITHIC(rrc->node_type)) { uint32_t delay_ms = ue_p->masterCellGroup && ue_p->masterCellGroup->spCellConfig && ue_p->masterCellGroup->spCellConfig->spCellConfigDedicated && ue_p->masterCellGroup->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList ? NR_RRC_RECONFIGURATION_DELAY_MS + NR_RRC_BWP_SWITCHING_DELAY_MS : NR_RRC_RECONFIGURATION_DELAY_MS; - nr_mac_enable_ue_rrc_processing_timer(ctxt_pP->module_id, ue_p->rnti, *RC.nrrrc[ctxt_pP->module_id]->carrier.servingcellconfigcommon->ssbSubcarrierSpacing, delay_ms); + nr_mac_enable_ue_rrc_processing_timer(ctxt_pP->module_id, ue_p->rnti, *rrc->carrier.servingcellconfigcommon->ssbSubcarrierSpacing, delay_ms); } } @@ -1289,55 +1263,55 @@ void rrc_gNB_generate_RRCReestablishment(const protocol_ctxt_t *ctxt_pP, } // if (*SRB_configList != NULL) LOG_I(NR_RRC, "Set PDCP security RNTI %04lx nca %ld nia %d in RRCReestablishment\n", ctxt_pP->rntiMaybeUEid, ue_p->ciphering_algorithm, ue_p->integrity_algorithm); - pdcp_config_set_security(ctxt_pP, - NULL, /* pdcp_pP not used anymore in NR */ - DCCH, - DCCH + 2, - enable_ciphering ? ue_p->ciphering_algorithm | (ue_p->integrity_algorithm << 4) : 0 | (ue_p->integrity_algorithm << 4), - kRRCenc, - kRRCint, - kUPenc); + uint8_t security_mode = + enable_ciphering ? ue_p->ciphering_algorithm | (ue_p->integrity_algorithm << 4) : 0 | (ue_p->integrity_algorithm << 4); + + nr_pdcp_config_set_security(ctxt_pP->rntiMaybeUEid, + DCCH, + security_mode, + kRRCenc, + kRRCint, + kUPenc); if (!NODE_IS_CU(rrc->node_type)) { apply_macrlc_config_reest(rrc, ue_context_pP, ctxt_pP, ctxt_pP->rntiMaybeUEid); } - nr_rrc_data_req(ctxt_pP, DCCH, rrc_gNB_mui++, SDU_CONFIRM_NO, size, buffer, PDCP_TRANSMISSION_MODE_CONTROL); + nr_pdcp_data_req_srb(ctxt_pP->rntiMaybeUEid, DCCH, rrc_gNB_mui++, size, buffer, deliver_pdu_srb_f1, rrc); } -//----------------------------------------------------------------------------- -void rrc_gNB_process_RRCReestablishmentComplete(const protocol_ctxt_t *const ctxt_pP, const rnti_t reestablish_rnti, rrc_gNB_ue_context_t *ue_context_pP, const uint8_t xid) -//----------------------------------------------------------------------------- +/* + * Handle RRC Reestablishment Complete Functions + */ + +/// @brief Function used in RRCReestablishmentComplete procedure to reestablish the SRB2. +/// @param old_xid The old RRC transaction id. +/// @param new_xid The new RRC transaction id. +void RRCReestablishmentComplete_fill_SRB2_configList(const protocol_ctxt_t *const ctxt_pP, + rrc_gNB_ue_context_t *ue_context_pP, + const uint8_t old_xid, + const uint8_t new_xid) { gNB_RRC_UE_t *ue_p = &ue_context_pP->ue_context; - LOG_I(NR_RRC, "[RAPROC] UE %04x Logical Channel UL-DCCH, processing NR_RRCReestablishmentComplete from UE (SRB1 Active)\n", ue_p->rnti); - - NR_DRB_ToAddModList_t *DRB_configList = ue_p->DRB_configList; + NR_SRB_ToAddMod_t *SRB2_config = NULL; NR_SRB_ToAddModList_t *SRB_configList = ue_p->SRB_configList; - NR_SRB_ToAddModList_t **SRB_configList2 = NULL; - NR_DRB_ToAddModList_t **DRB_configList2 = NULL; - NR_SRB_ToAddMod_t *SRB2_config = NULL; - NR_DRB_ToAddMod_t *DRB_config = NULL; - //NR_SDAP_Config_t *sdap_config = NULL; - int i = 0; + NR_SRB_ToAddModList_t **SRB_configList2 = NULL; - uint8_t new_xid = rrc_gNB_get_next_transaction_identifier(ctxt_pP->module_id); - int ret = 0; - ue_p->StatusRrc = NR_RRC_CONNECTED; - ue_p->ue_rrc_inactivity_timer = 1; // set rrc inactivity when UE goes into RRC_CONNECTED - ue_p->reestablishment_xid = new_xid; - SRB_configList2 = &ue_p->SRB_configList2[xid]; + SRB_configList2 = &ue_p->SRB_configList2[old_xid]; // get old configuration of SRB2 if (*SRB_configList2 != NULL) { - if((*SRB_configList2)->list.count!=0) { - LOG_D(NR_RRC, "SRB_configList2(%p) count is %d\n SRB_configList2->list.array[0] addr is %p", - SRB_configList2, (*SRB_configList2)->list.count, (*SRB_configList2)->list.array[0]); + if ((*SRB_configList2)->list.count != 0) { + LOG_D(NR_RRC, + "RRC Reestablishment - SRB_configList2(%p) count is %d\n SRB_configList2->list.array[0] addr is %p\n", + SRB_configList2, + (*SRB_configList2)->list.count, + (*SRB_configList2)->list.array[0]); } - for (i = 0; (i < (*SRB_configList2)->list.count) && (i < 3); i++) { - if ((*SRB_configList2)->list.array[i]->srb_Identity == 2 ) { - LOG_D(NR_RRC, "get SRB2_config from (ue_p->SRB_configList2[%d])\n", xid); + for (int i = 0; (i < (*SRB_configList2)->list.count) && (i < 3); i++) { + if ((*SRB_configList2)->list.array[i]->srb_Identity == 2) { + LOG_D(NR_RRC, "RRC Reestablishment - get SRB2_config from (ue_p->SRB_configList2[%d])\n", old_xid); SRB2_config = (*SRB_configList2)->list.array[i]; SRB2_config->reestablishPDCP = CALLOC(1, sizeof(*SRB2_config->reestablishPDCP)); *SRB2_config->reestablishPDCP = NR_SRB_ToAddMod__reestablishPDCP_true; @@ -1346,15 +1320,11 @@ void rrc_gNB_process_RRCReestablishmentComplete(const protocol_ctxt_t *const ctx } } - // SRB2_config = CALLOC(1, sizeof(*SRB2_config)); - // SRB2_config->srb_Identity = 2; - SRB_configList2 = &(ue_p->SRB_configList2[new_xid]); - DRB_configList2 = &(ue_p->DRB_configList2[new_xid]); if (*SRB_configList2) { free(*SRB_configList2); - LOG_D(NR_RRC, "free(ue_p->SRB_configList2[%d])\n", new_xid); + LOG_D(NR_RRC, "RRC Reestablishment - free(ue_p->SRB_configList2[%d])\n", new_xid); } *SRB_configList2 = CALLOC(1, sizeof(**SRB_configList2)); @@ -1363,42 +1333,74 @@ void rrc_gNB_process_RRCReestablishmentComplete(const protocol_ctxt_t *const ctx // Add SRB2 to SRB configuration list asn1cSeqAdd(&SRB_configList->list, SRB2_config); asn1cSeqAdd(&(*SRB_configList2)->list, SRB2_config); - LOG_D(NR_RRC, "Add SRB2_config (srb_Identity:%ld) to ue_p->SRB_configList\n", SRB2_config->srb_Identity); - LOG_D(NR_RRC, "Add SRB2_config (srb_Identity:%ld) to ue_p->SRB_configList2[%d]\n", SRB2_config->srb_Identity, new_xid); + LOG_D(NR_RRC, "RRC Reestablishment - Add SRB2_config (srb_Identity:%ld) to ue_p->SRB_configList\n", SRB2_config->srb_Identity); + LOG_D(NR_RRC, + "RRC Reestablishment - Add SRB2_config (srb_Identity:%ld) to ue_p->SRB_configList2[%d]\n", + SRB2_config->srb_Identity, + new_xid); } else { // SRB configuration list only contains SRB1. - LOG_W(NR_RRC,"SRB2 configuration does not exist in SRB configuration list\n"); - } - - if (*DRB_configList2) { - free(*DRB_configList2); - LOG_D(NR_RRC, "free(ue_p->DRB_configList2[%d])\n", new_xid); - } - - *DRB_configList2 = CALLOC(1, sizeof(**DRB_configList2)); - - if (DRB_configList != NULL) { - LOG_D(NR_RRC, "get DRB_config from (ue_p->DRB_configList)\n"); - - for (i = 0; (i < DRB_configList->list.count) && (i < 3); i++) { - DRB_config = DRB_configList->list.array[i]; - asn1cCallocOne(DRB_config->reestablishPDCP, NR_DRB_ToAddMod__reestablishPDCP_true); - // Add DRB to DRB configuration list, for LTE_RRCConnectionReconfigurationComplete - asn1cSeqAdd(&(*DRB_configList2)->list, DRB_config); - } + LOG_W(NR_RRC, "RRC Reestablishment - SRB2 configuration does not exist in SRB configuration list\n"); } ue_p->Srb[1].Active = 1; if (get_softmodem_params()->sa) { - LOG_W(NR_RRC, "Rework identity mapping need to be done properly!\n"); - gtpv1u_gnb_create_tunnel_req_t create_tunnel_req={0}; + uint8_t send_security_mode_command = false; + nr_rrc_pdcp_config_security(ctxt_pP, ue_context_pP, send_security_mode_command); + LOG_D(NR_RRC, "RRC Reestablishment - set security successfully \n"); + } +} + +/// @brief Function used in RRCReestablishmentComplete procedure to reestablish the DRBs +/// that the UE previously had, it gets the information from the established_drbs +/// struct. +/// @param new_xid The new RRC transaction id. +void RRCReestablishmentComplete_fill_DRB_configList(const protocol_ctxt_t *const ctxt_pP, + rrc_gNB_ue_context_t *ue_context_pP, + const uint8_t new_xid) +{ + gNB_RRC_UE_t *ue_p = &ue_context_pP->ue_context; + NR_DRB_ToAddMod_t *DRB_config = NULL; + NR_DRB_ToAddModList_t **DRB_configList2 = &(ue_p->DRB_configList2[new_xid]); + + if (*DRB_configList2) { + free(*DRB_configList2); + LOG_D(NR_RRC, "RRC Reestablishment - free(ue_p->DRB_configList2[%d])\n", new_xid); + } + + *DRB_configList2 = CALLOC(1, sizeof(**DRB_configList2)); + + for (int i = 0; i < NGAP_MAX_DRBS_PER_UE; i++) { + if (ue_p->established_drbs[i].status != DRB_INACTIVE) { + ue_p->established_drbs[i].reestablishPDCP = NR_DRB_ToAddMod__reestablishPDCP_true; + DRB_config = generateDRB_ASN1(&ue_p->established_drbs[i]); + asn1cCallocOne(DRB_config->reestablishPDCP, NR_DRB_ToAddMod__reestablishPDCP_true); + asn1cSeqAdd(&(*DRB_configList2)->list, DRB_config); + } + } +} + +/// @brief Function used in RRCReestablishmentComplete procedure to update the NGU Tunnels. +/// @param reestablish_rnti is the old C-RNTI +void RRCReestablishmentComplete_update_ngu_tunnel(const protocol_ctxt_t *const ctxt_pP, + rrc_gNB_ue_context_t *ue_context_pP, + const rnti_t reestablish_rnti) +{ + gNB_RRC_UE_t *ue_p = &ue_context_pP->ue_context; + int i = 0; + int j = 0; + int ret = 0; + + if (get_softmodem_params()->sa) { + LOG_W(NR_RRC, "RRC Reestablishment - Rework identity mapping need to be done properly!\n"); + gtpv1u_gnb_create_tunnel_req_t create_tunnel_req = {0}; /* Save e RAB information for later */ - int j; + for (j = 0, i = 0; i < NB_RB_MAX; i++) { if (ue_p->pduSession[i].status == PDU_SESSION_STATUS_ESTABLISHED || ue_p->pduSession[i].status == PDU_SESSION_STATUS_DONE) { create_tunnel_req.pdusession_id[j] = ue_p->pduSession[i].param.pdusession_id; - create_tunnel_req.incoming_rb_id[j] = i+1; + create_tunnel_req.incoming_rb_id[j] = i + 1; create_tunnel_req.outgoing_teid[j] = ue_p->pduSession[i].param.gtp_teid; // to be developped, use the first QFI only create_tunnel_req.outgoing_qfi[j] = ue_p->pduSession[i].param.qos[0].qfi; @@ -1409,14 +1411,11 @@ void rrc_gNB_process_RRCReestablishmentComplete(const protocol_ctxt_t *const ctx } create_tunnel_req.ue_id = ctxt_pP->rntiMaybeUEid; // warning put zero above - create_tunnel_req.num_tunnels = j; - ret = gtpv1u_update_ngu_tunnel( - ctxt_pP->instance, - &create_tunnel_req, - reestablish_rnti); + create_tunnel_req.num_tunnels = j; + ret = gtpv1u_update_ngu_tunnel(ctxt_pP->instance, &create_tunnel_req, reestablish_rnti); - if ( ret != 0 ) { - LOG_E(NR_RRC, "gtpv1u_update_ngu_tunnel failed,start to release UE %x\n", reestablish_rnti); + if (ret != 0) { + LOG_E(NR_RRC, "RRC Reestablishment - gtpv1u_update_ngu_tunnel failed,start to release UE %x\n", reestablish_rnti); ue_p->ue_release_timer_s1 = 1; ue_p->ue_release_timer_thres_s1 = 100; ue_p->ue_release_timer = 0; @@ -1426,34 +1425,72 @@ void rrc_gNB_process_RRCReestablishmentComplete(const protocol_ctxt_t *const ctx return; } } +} + +/// @brief Function used in RRCReestablishmentComplete procedure to update the NAS PDUSessions and the xid. +/// @param old_xid Refers to the old transaction identifier passed to rrc_gNB_process_RRCReestablishmentComplete as xid. +/// @todo parameters yet to process inside the for loop. +/// @todo should test if pdu session are Ok before! inside the for loop. +void RRCReestablishmentComplete_nas_pdu_update(rrc_gNB_ue_context_t *ue_context_pP, const uint8_t old_xid) +{ + gNB_RRC_UE_t *ue_p = &ue_context_pP->ue_context; + /* Add all NAS PDUs to the list */ + for (int i = 0; i < ue_p->nb_of_pdusessions; i++) { + ue_p->pduSession[i].status = PDU_SESSION_STATUS_DONE; + ue_p->pduSession[i].xid = old_xid; + LOG_D(NR_RRC, + "RRC Reestablishment - setting the status for the default DRB (index %d) to (%d,%s)\n", + i, + ue_p->pduSession[i].status, + "PDU_SESSION_STATUS_DONE"); + } +} + +/// @brief Function used in RRCReestablishmentComplete procedure to Free all the NAS PDU buffers. +void RRCReestablishmentComplete_nas_pdu_free(rrc_gNB_ue_context_t *ue_context_pP) +{ + gNB_RRC_UE_t *ue_p = &ue_context_pP->ue_context; + /* Free all NAS PDUs */ + for (int i = 0; i < ue_p->nb_of_pdusessions; i++) { + if (ue_p->pduSession[i].param.nas_pdu.buffer != NULL) { + /* Free the NAS PDU buffer and invalidate it */ + free(ue_p->pduSession[i].param.nas_pdu.buffer); + ue_p->pduSession[i].param.nas_pdu.buffer = NULL; + } + } +} + +/// @brief Function tha processes RRCReestablishmentComplete message sent by the UE, after RRCReestasblishment request. +/// @param ctxt_pP Protocol context containing information regarding the UE and gNB +/// @param reestablish_rnti is the old C-RNTI +/// @param ue_context_pP UE context container information regarding the UE +/// @param xid Transaction Identifier used in RRC messages +void rrc_gNB_process_RRCReestablishmentComplete(const protocol_ctxt_t *const ctxt_pP, + const rnti_t reestablish_rnti, + rrc_gNB_ue_context_t *ue_context_pP, + const uint8_t xid) +{ + gNB_RRC_UE_t *ue_p = &ue_context_pP->ue_context; + LOG_I(NR_RRC, + "[RAPROC] UE %04x Logical Channel UL-DCCH, processing NR_RRCReestablishmentComplete from UE (SRB1 Active)\n", + ue_p->rnti); + + int i = 0; + + uint8_t new_xid = rrc_gNB_get_next_transaction_identifier(ctxt_pP->module_id); + ue_p->StatusRrc = NR_RRC_CONNECTED; + ue_p->ue_rrc_inactivity_timer = 1; // set rrc inactivity when UE goes into RRC_CONNECTED + ue_p->reestablishment_xid = new_xid; + + RRCReestablishmentComplete_fill_SRB2_configList(ctxt_pP, ue_context_pP, xid, new_xid); + RRCReestablishmentComplete_fill_DRB_configList(ctxt_pP, ue_context_pP, new_xid); + RRCReestablishmentComplete_update_ngu_tunnel(ctxt_pP, ue_context_pP, reestablish_rnti); + RRCReestablishmentComplete_nas_pdu_update(ue_context_pP, xid); /* Update RNTI in ue_context */ - LOG_I(NR_RRC, "Updating UEid from %04x to %lx\n", ue_p->rnti, ctxt_pP->rntiMaybeUEid); + LOG_I(NR_RRC, "RRC Reestablishment - Updating UEid from %04x to %lx\n", ue_p->rnti, ctxt_pP->rntiMaybeUEid); rrc_gNB_update_ue_context_rnti(ctxt_pP->rntiMaybeUEid, RC.nrrrc[ctxt_pP->module_id], ue_p->gNB_ue_ngap_id); - if (get_softmodem_params()->sa) { - uint8_t send_security_mode_command = false; - nr_rrc_pdcp_config_security( - ctxt_pP, - ue_context_pP, - send_security_mode_command ? 0 : 1); - LOG_D(NR_RRC, "set security successfully \n"); - } - - uint8_t drb_id_to_setup_start = DRB_configList ? DRB_configList->list.array[0]->drb_Identity : 1; - uint8_t nb_drb_to_setup = DRB_configList ? DRB_configList->list.count : ue_p->nb_of_pdusessions; - /* TODO: hardcoded to 13 for the time being, to be changed? */ - long drb_priority[NGAP_MAX_DRBS_PER_UE] = {13}; - - /* Add all NAS PDUs to the list */ - for (i = 0; i < ue_p->nb_of_pdusessions; i++) { - /* TODO parameters yet to process ... */ - /* TODO should test if pdu session are Ok before! */ - ue_p->pduSession[i].status = PDU_SESSION_STATUS_DONE; - ue_p->pduSession[i].xid = xid; - LOG_D(NR_RRC, "setting the status for the default DRB (index %d) to (%d,%s)\n", i, ue_p->pduSession[i].status, "PDU_SESSION_STATUS_DONE"); - } - gNB_RRC_INST *rrc = RC.nrrrc[ctxt_pP->module_id]; NR_CellGroupConfig_t *cellGroupConfig = calloc(1, sizeof(NR_CellGroupConfig_t)); @@ -1461,51 +1498,62 @@ void rrc_gNB_process_RRCReestablishmentComplete(const protocol_ctxt_t *const ctx ue_p->masterCellGroup->spCellConfig = ue_p->spCellConfigReestablishment; ue_p->spCellConfigReestablishment = NULL; cellGroupConfig->spCellConfig = ue_p->masterCellGroup->spCellConfig; -cellGroupConfig->physicalCellGroupConfig = ue_p->masterCellGroup->physicalCellGroupConfig; + cellGroupConfig->physicalCellGroupConfig = ue_p->masterCellGroup->physicalCellGroupConfig; - fill_mastercellGroupConfig(cellGroupConfig, ue_p->masterCellGroup, rrc->um_on_default_drb, (drb_id_to_setup_start < 2) ? 1 : 0, drb_id_to_setup_start, nb_drb_to_setup, drb_priority); + uint8_t drb_id_to_setup_start = ue_p->DRB_configList ? ue_p->DRB_configList->list.array[0]->drb_Identity : 1; + uint8_t nb_drb_to_setup = ue_p->DRB_configList ? ue_p->DRB_configList->list.count : ue_p->nb_of_pdusessions; + /* TODO: hardcoded to 13 for the time being, to be changed? */ + long drb_priority[NGAP_MAX_DRBS_PER_UE] = {13}; - for(i = 0; i < cellGroupConfig->rlc_BearerToAddModList->list.count; i++) { - cellGroupConfig->rlc_BearerToAddModList->list.array[i]->reestablishRLC = CALLOC(1, sizeof(*cellGroupConfig->rlc_BearerToAddModList->list.array[i]->reestablishRLC)); + fill_mastercellGroupConfig(cellGroupConfig, + ue_p->masterCellGroup, + rrc->um_on_default_drb, + (drb_id_to_setup_start < 2) ? 1 : 0, + drb_id_to_setup_start, + nb_drb_to_setup, + drb_priority); + + for (i = 0; i < cellGroupConfig->rlc_BearerToAddModList->list.count; i++) { + cellGroupConfig->rlc_BearerToAddModList->list.array[i]->reestablishRLC = + CALLOC(1, sizeof(*cellGroupConfig->rlc_BearerToAddModList->list.array[i]->reestablishRLC)); *cellGroupConfig->rlc_BearerToAddModList->list.array[i]->reestablishRLC = NR_RLC_BearerConfig__reestablishRLC_true; } uint8_t buffer[RRC_BUF_SIZE] = {0}; int size = do_RRCReconfiguration(ctxt_pP, - buffer, - RRC_BUF_SIZE, - new_xid, - *SRB_configList2, - DRB_configList, - NULL, - NULL, - NULL, - NULL, // MeasObj_list, - NULL, - ue_context_pP, - &rrc->carrier, - NULL, - NULL, - cellGroupConfig); + buffer, + RRC_BUF_SIZE, + new_xid, + ue_p->SRB_configList2[new_xid], + ue_p->DRB_configList2[new_xid], + NULL, + NULL, + NULL, + NULL, // MeasObj_list, + NULL, + ue_context_pP, + &rrc->carrier, + NULL, + NULL, + cellGroupConfig); - LOG_DUMPMSG(NR_RRC,DEBUG_RRC,(char *)buffer,size, "[MSG] RRC Reconfiguration\n"); + LOG_DUMPMSG(NR_RRC, DEBUG_RRC, (char *)buffer, size, "[MSG] RRC Reconfiguration\n"); - /* Free all NAS PDUs */ - for (i = 0; i < ue_p->nb_of_pdusessions; i++) { - if (ue_p->pduSession[i].param.nas_pdu.buffer != NULL) { - /* Free the NAS PDU buffer and invalidate it */ - free(ue_p->pduSession[i].param.nas_pdu.buffer); - ue_p->pduSession[i].param.nas_pdu.buffer = NULL; - } - } + RRCReestablishmentComplete_nas_pdu_free(ue_context_pP); if (size < 0) { LOG_E(NR_RRC, "RRC decode err!!! do_RRCReconfiguration\n"); return; } else { - LOG_I(NR_RRC, "[gNB %d] Frame %d, Logical Channel DL-DCCH, Generate NR_RRCReconfiguration (bytes %d, UE id %04x)\n", ctxt_pP->module_id, ctxt_pP->frame, size, ue_p->rnti); + LOG_I(NR_RRC, + "[gNB %d] Frame %d, Logical Channel DL-DCCH, Generate NR_RRCReconfiguration (bytes %d, UE id %04x)\n", + ctxt_pP->module_id, + ctxt_pP->frame, + size, + ue_p->rnti); LOG_D(NR_RRC, - "[FRAME %05d][RRC_gNB][MOD %u][][--- PDCP_DATA_REQ/%d Bytes (RRCReconfiguration to UE %04x MUI %d) --->][PDCP][MOD %u][RB %u]\n", + "[FRAME %05d][RRC_gNB][MOD %u][][--- PDCP_DATA_REQ/%d Bytes (RRCReconfiguration to UE %04x MUI %d) --->][PDCP][MOD " + "%u][RB %u]\n", ctxt_pP->frame, ctxt_pP->module_id, size, @@ -1515,16 +1563,20 @@ cellGroupConfig->physicalCellGroupConfig = ue_p->masterCellGroup->physicalCellGr DCCH); nr_mac_update_cellgroup(RC.nrmac[rrc->module_id], ue_context_pP->ue_context.rnti, cellGroupConfig); - nr_rrc_data_req(ctxt_pP, DCCH, rrc_gNB_mui++, SDU_CONFIRM_NO, size, buffer, PDCP_TRANSMISSION_MODE_CONTROL); + nr_pdcp_data_req_srb(ctxt_pP->rntiMaybeUEid, DCCH, rrc_gNB_mui++, size, buffer, deliver_pdu_srb_f1, rrc); } if (NODE_IS_DU(RC.nrrrc[ctxt_pP->module_id]->node_type) || NODE_IS_MONOLITHIC(RC.nrrrc[ctxt_pP->module_id]->node_type)) { - uint32_t delay_ms = ue_p->masterCellGroup && ue_p->masterCellGroup->spCellConfig && ue_p->masterCellGroup->spCellConfig->spCellConfigDedicated + uint32_t delay_ms = ue_p->masterCellGroup && ue_p->masterCellGroup->spCellConfig + && ue_p->masterCellGroup->spCellConfig->spCellConfigDedicated && ue_p->masterCellGroup->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList ? NR_RRC_RECONFIGURATION_DELAY_MS + NR_RRC_BWP_SWITCHING_DELAY_MS : NR_RRC_RECONFIGURATION_DELAY_MS; - nr_mac_enable_ue_rrc_processing_timer(ctxt_pP->module_id, ue_p->rnti, *RC.nrrrc[ctxt_pP->module_id]->carrier.servingcellconfigcommon->ssbSubcarrierSpacing, delay_ms); + nr_mac_enable_ue_rrc_processing_timer(ctxt_pP->module_id, + ue_p->rnti, + *RC.nrrrc[ctxt_pP->module_id]->carrier.servingcellconfigcommon->ssbSubcarrierSpacing, + delay_ms); } } //----------------------------------------------------------------------------- @@ -1566,21 +1618,16 @@ int nr_rrc_reconfiguration_req(rrc_gNB_ue_context_t *const ue_context_pP nr_mac_update_cellgroup(RC.nrmac[ctxt_pP->module_id], ue_context_pP->ue_context.rnti, masterCellGroup); - nr_rrc_data_req(ctxt_pP, - DCCH, - rrc_gNB_mui++, - SDU_CONFIRM_NO, - size, - buffer, - PDCP_TRANSMISSION_MODE_CONTROL); + gNB_RRC_INST *rrc = RC.nrrrc[ctxt_pP->module_id]; + nr_pdcp_data_req_srb(ctxt_pP->rntiMaybeUEid, DCCH, rrc_gNB_mui++, size, buffer, deliver_pdu_srb_f1, rrc); - if (NODE_IS_DU(RC.nrrrc[ctxt_pP->module_id]->node_type) || NODE_IS_MONOLITHIC(RC.nrrrc[ctxt_pP->module_id]->node_type)) { + if (NODE_IS_DU(rrc->node_type) || NODE_IS_MONOLITHIC(rrc->node_type)) { uint32_t delay_ms = ue_p->masterCellGroup && ue_p->masterCellGroup->spCellConfig && ue_p->masterCellGroup->spCellConfig->spCellConfigDedicated && ue_p->masterCellGroup->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList ? NR_RRC_RECONFIGURATION_DELAY_MS + NR_RRC_BWP_SWITCHING_DELAY_MS : NR_RRC_RECONFIGURATION_DELAY_MS; - nr_mac_enable_ue_rrc_processing_timer(ctxt_pP->module_id, ue_p->rnti, *RC.nrrrc[ctxt_pP->module_id]->carrier.servingcellconfigcommon->ssbSubcarrierSpacing, delay_ms); + nr_mac_enable_ue_rrc_processing_timer(ctxt_pP->module_id, ue_p->rnti, *rrc->carrier.servingcellconfigcommon->ssbSubcarrierSpacing, delay_ms); } return 0; @@ -3225,7 +3272,7 @@ void nr_rrc_subframe_process(protocol_ctxt_t *const ctxt_pP, const int CC_id) { gNB_MAC_INST *nrmac = RC.nrmac[ctxt_pP->module_id]; // WHAT A BEAUTIFULL RACE CONDITION !!! mac_remove_nr_ue(nrmac, UE->rnti); rrc_rlc_remove_ue(ctxt_pP); - pdcp_remove_UE(ctxt_pP); + nr_pdcp_remove_UE(ctxt_pP->rntiMaybeUEid); /* remove RRC UE Context */ ue_context_p = rrc_gNB_get_ue_context_by_rnti(rrc, UE->rnti); @@ -3262,7 +3309,7 @@ void nr_rrc_subframe_process(protocol_ctxt_t *const ctxt_pP, const int CC_id) { mac_remove_nr_ue(nrmac, UE->rnti); } rrc_rlc_remove_ue(ctxt_pP); - pdcp_remove_UE(ctxt_pP); + nr_pdcp_remove_UE(ctxt_pP->rntiMaybeUEid); newGtpuDeleteAllTunnels(ctxt_pP->instance, UE->rnti); /* remove RRC UE Context */ @@ -3623,7 +3670,7 @@ rrc_gNB_generate_SecurityModeCommand( gNB_RRC_INST *rrc = RC.nrrrc[ctxt_pP->module_id]; AssertFatal(!NODE_IS_DU(rrc->node_type), "illegal node type DU!\n"); - nr_rrc_data_req(ctxt_pP, DCCH, rrc_gNB_mui++, SDU_CONFIRM_NO, size, buffer, PDCP_TRANSMISSION_MODE_CONTROL); + nr_pdcp_data_req_srb(ctxt_pP->rntiMaybeUEid, DCCH, rrc_gNB_mui++, size, buffer, deliver_pdu_srb_f1, rrc); } void @@ -3649,7 +3696,7 @@ rrc_gNB_generate_UECapabilityEnquiry( gNB_RRC_INST *rrc = RC.nrrrc[ctxt_pP->module_id]; AssertFatal(!NODE_IS_DU(rrc->node_type), "illegal node type DU!\n"); - nr_rrc_data_req(ctxt_pP, DCCH, rrc_gNB_mui++, SDU_CONFIRM_NO, size, buffer, PDCP_TRANSMISSION_MODE_CONTROL); + nr_pdcp_data_req_srb(ctxt_pP->rntiMaybeUEid, DCCH, rrc_gNB_mui++, size, buffer, deliver_pdu_srb_f1, rrc); } //----------------------------------------------------------------------------- @@ -3683,12 +3730,22 @@ rrc_gNB_generate_RRCRelease( rrc_gNB_mui, DCCH); - nr_rrc_data_req(ctxt_pP, DCCH, rrc_gNB_mui++, SDU_CONFIRM_NO, size, buffer, PDCP_TRANSMISSION_MODE_CONTROL); + gNB_RRC_INST *rrc = RC.nrrrc[ctxt_pP->module_id]; + nr_pdcp_data_req_srb(ctxt_pP->rntiMaybeUEid, DCCH, rrc_gNB_mui++, size, buffer, deliver_pdu_srb_f1, rrc); rrc_gNB_send_NGAP_UE_CONTEXT_RELEASE_COMPLETE(ctxt_pP->instance, ue_context_pP->ue_context.gNB_ue_ngap_id); ue_context_pP->ue_context.ue_release_timer_rrc = 1; + /* TODO: 38.331 says for RRC Release that the UE should release everything + * after 60ms or if lower layers acked receipt of release. Hence, from the + * gNB POV, we can free the UE's RRC context as soon as we sent the msg. + * Currently, without the F1 interface, the ue_release timer expiration also + * triggers MAC, so we give it some time. If we send an F1 UE Context release + * message, we can free it immediately. The MAC should release it after these + * 60ms, or the ack of the DLSCH transmission. */ + ue_context_pP->ue_context.ue_release_timer_thres_rrc = 5; + LOG_I(RRC, "delaying UE %ld context removal by 5ms\n", ctxt_pP->rntiMaybeUEid); - if (NODE_IS_CU(RC.nrrrc[ctxt_pP->module_id]->node_type)) { + if (NODE_IS_CU(rrc->node_type)) { uint8_t *message_buffer = itti_malloc (TASK_RRC_GNB, TASK_CU_F1, size); memcpy (message_buffer, buffer, size); MessageDef *m = itti_alloc_new_message(TASK_RRC_GNB, 0, F1AP_UE_CONTEXT_RELEASE_CMD); diff --git a/openair2/RRC/NR/rrc_gNB_NGAP.c b/openair2/RRC/NR/rrc_gNB_NGAP.c index d3efb4b497..1f37210b9c 100644 --- a/openair2/RRC/NR/rrc_gNB_NGAP.c +++ b/openair2/RRC/NR/rrc_gNB_NGAP.c @@ -36,8 +36,9 @@ #include "oai_asn1.h" #include "intertask_interface.h" -#include "pdcp.h" +#include "nr_pdcp/nr_pdcp_oai_api.h" #include "pdcp_primitives.h" +#include "SDAP/nr_sdap/nr_sdap.h" #include "openair3/ocp-gtpu/gtp_itf.h" #include @@ -153,14 +154,9 @@ nr_rrc_pdcp_config_security( } } - pdcp_config_set_security(ctxt_pP, - NULL, /* pdcp_pP not used anymore in NR */ - DCCH, - DCCH + 2, - enable_ciphering ? UE->ciphering_algorithm | (UE->integrity_algorithm << 4) : 0 | (UE->integrity_algorithm << 4), - kRRCenc, - kRRCint, - kUPenc); + uint8_t security_mode = + enable_ciphering ? UE->ciphering_algorithm | (UE->integrity_algorithm << 4) : 0 | (UE->integrity_algorithm << 4); + nr_pdcp_config_set_security(ctxt_pP->rntiMaybeUEid, DCCH, security_mode, kRRCenc, kRRCint, kUPenc); } //------------------------------------------------------------------------------ @@ -396,7 +392,7 @@ int rrc_gNB_process_NGAP_INITIAL_CONTEXT_SETUP_REQ(MessageDef *msg_p, instance_t } create_tunnel_req.ue_id = UE->rnti; gtpv1u_gnb_create_tunnel_resp_t create_tunnel_resp = {0}; - int ret = gtpv1u_create_ngu_tunnel(instance, &create_tunnel_req, &create_tunnel_resp); + int ret = gtpv1u_create_ngu_tunnel(instance, &create_tunnel_req, &create_tunnel_resp, nr_pdcp_data_req_drb, sdap_data_req); if (ret != 0) { LOG_E(NR_RRC, "rrc_gNB_process_NGAP_INITIAL_CONTEXT_SETUP_REQ : gtpv1u_create_ngu_tunnel failed,start to release UE %x\n", UE->rnti); UE->ue_release_timer_ng = 1; @@ -625,7 +621,7 @@ int rrc_gNB_process_NGAP_DOWNLINK_NAS(MessageDef *msg_p, instance_t instance, mu AssertFatal(!NODE_IS_DU(RC.nrrrc[ctxt.module_id]->node_type), "illegal node type DU: receiving NGAP messages at this node\n"); /* Transfer data to PDCP */ rb_id_t srb_id = UE->Srb[2].Active ? DCCH1 : DCCH; - nr_rrc_data_req(&ctxt, srb_id, (*rrc_gNB_mui)++, SDU_CONFIRM_NO, length, buffer, PDCP_TRANSMISSION_MODE_CONTROL); + nr_pdcp_data_req_srb(ctxt.rntiMaybeUEid, srb_id, (*rrc_gNB_mui)++, length, buffer, deliver_pdu_srb_f1, RC.nrrrc[instance]); return 0; } diff --git a/openair2/RRC/NR/rrc_gNB_nsa.c b/openair2/RRC/NR/rrc_gNB_nsa.c index 0a6eb050e5..4b4e06fc0f 100644 --- a/openair2/RRC/NR/rrc_gNB_nsa.c +++ b/openair2/RRC/NR/rrc_gNB_nsa.c @@ -45,7 +45,7 @@ #include #include "UTIL/OSA/osa_defs.h" #include -#include "pdcp.h" +#include "nr_pdcp/nr_pdcp_oai_api.h" 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) { @@ -282,10 +282,7 @@ void rrc_add_nsa_user(gNB_RRC_INST *rrc, rrc_gNB_ue_context_t *ue_context_p, x2a memset(&create_tunnel_resp, 0, sizeof(create_tunnel_resp)); if (!IS_SOFTMODEM_NOS1) { LOG_D(RRC, "Calling gtpv1u_create_s1u_tunnel()\n"); - gtpv1u_create_s1u_tunnel( - ctxt.instance, - &create_tunnel_req, - &create_tunnel_resp); + gtpv1u_create_s1u_tunnel(ctxt.instance, &create_tunnel_req, &create_tunnel_resp, nr_pdcp_data_req_drb); rrc_gNB_process_GTPV1U_CREATE_TUNNEL_RESP( &ctxt, &create_tunnel_resp, @@ -391,7 +388,7 @@ void rrc_remove_nsa_user(gNB_RRC_INST *rrc, int rnti) { return; } - pdcp_remove_UE(&ctxt); + nr_pdcp_remove_UE(ctxt.rntiMaybeUEid); rrc_rlc_remove_ue(&ctxt); diff --git a/openair2/RRC/NR/rrc_gNB_radio_bearers.c b/openair2/RRC/NR/rrc_gNB_radio_bearers.c index 1848601de8..b4d6c55762 100644 --- a/openair2/RRC/NR/rrc_gNB_radio_bearers.c +++ b/openair2/RRC/NR/rrc_gNB_radio_bearers.c @@ -36,65 +36,109 @@ rrc_pdu_session_param_t *find_pduSession(gNB_RRC_UE_t *ue, int id, bool create) return ue->pduSession + j; } -NR_DRB_ToAddMod_t *generateDRB(gNB_RRC_UE_t *ue, uint8_t drb_id, rrc_pdu_session_param_t *pduSession, bool enable_sdap, int do_drb_integrity, int do_drb_ciphering) +void generateDRB(gNB_RRC_UE_t *ue, + uint8_t drb_id, + rrc_pdu_session_param_t *pduSession, + bool enable_sdap, + int do_drb_integrity, + int do_drb_ciphering) +{ + int i; + int qos_flow_index; + drb_t *est_drb = &ue->established_drbs[drb_id - 1]; + if (est_drb->status == DRB_INACTIVE) { + /* DRB Management */ + est_drb->drb_id = drb_id; + est_drb->reestablishPDCP = -1; + est_drb->recoverPDCP = -1; + for (i = 0; i < NGAP_MAX_DRBS_PER_UE; i++) { + if ((est_drb->cnAssociation.sdap_config.pdusession_id == 0 + || est_drb->cnAssociation.sdap_config.pdusession_id == pduSession->param.pdusession_id) + && est_drb->defaultDRBid == 0) { + est_drb->cnAssociation.sdap_config.defaultDRB = true; + est_drb->defaultDRBid = drb_id; + } + } + /* SDAP Configuration */ + est_drb->cnAssociation.present = NR_DRB_ToAddMod__cnAssociation_PR_sdap_Config; + est_drb->cnAssociation.sdap_config.pdusession_id = pduSession->param.pdusession_id; + if (enable_sdap) { + est_drb->cnAssociation.sdap_config.sdap_HeaderDL = NR_SDAP_Config__sdap_HeaderDL_present; + est_drb->cnAssociation.sdap_config.sdap_HeaderUL = NR_SDAP_Config__sdap_HeaderUL_present; + } else { + est_drb->cnAssociation.sdap_config.sdap_HeaderDL = NR_SDAP_Config__sdap_HeaderDL_absent; + est_drb->cnAssociation.sdap_config.sdap_HeaderUL = NR_SDAP_Config__sdap_HeaderUL_absent; + } + for (qos_flow_index = 0; qos_flow_index < pduSession->param.nb_qos; qos_flow_index++) { + est_drb->cnAssociation.sdap_config.mappedQoS_FlowsToAdd[qos_flow_index] = pduSession->param.qos[qos_flow_index].qfi; + if (pduSession->param.qos[qos_flow_index].fiveQI > 5) + est_drb->status = DRB_ACTIVE_NONGBR; + else + est_drb->status = DRB_ACTIVE; + } + /* PDCP Configuration */ + est_drb->pdcp_config.discardTimer = NR_PDCP_Config__drb__discardTimer_infinity; + est_drb->pdcp_config.pdcp_SN_SizeDL = NR_PDCP_Config__drb__pdcp_SN_SizeDL_len18bits; + est_drb->pdcp_config.pdcp_SN_SizeUL = NR_PDCP_Config__drb__pdcp_SN_SizeUL_len18bits; + est_drb->pdcp_config.t_Reordering = NR_PDCP_Config__t_Reordering_ms100; + est_drb->pdcp_config.headerCompression.present = NR_PDCP_Config__drb__headerCompression_PR_notUsed; + est_drb->pdcp_config.headerCompression.NotUsed = 0; + if (do_drb_integrity) + est_drb->pdcp_config.integrityProtection = NR_PDCP_Config__drb__integrityProtection_enabled; + else + est_drb->pdcp_config.integrityProtection = 1; + if (do_drb_ciphering) + est_drb->pdcp_config.ext1.cipheringDisabled = 1; + else + est_drb->pdcp_config.ext1.cipheringDisabled = NR_PDCP_Config__ext1__cipheringDisabled_true; + } +} + +NR_DRB_ToAddMod_t *generateDRB_ASN1(const drb_t *drb_asn1) { NR_DRB_ToAddMod_t *DRB_config = CALLOC(1, sizeof(*DRB_config)); - DRB_config->drb_Identity = drb_id; + NR_SDAP_Config_t *SDAP_config = CALLOC(1, sizeof(NR_SDAP_Config_t)); + asn1cCalloc(DRB_config->cnAssociation, association); - association->present = NR_DRB_ToAddMod__cnAssociation_PR_sdap_Config; + asn1cCalloc(SDAP_config->mappedQoS_FlowsToAdd, sdapFlows); + asn1cCalloc(DRB_config->pdcp_Config, pdcpConfig); + asn1cCalloc(pdcpConfig->drb, drb); + + DRB_config->drb_Identity = drb_asn1->drb_id; + association->present = drb_asn1->cnAssociation.present; /* SDAP Configuration */ - NR_SDAP_Config_t *SDAP_config = CALLOC(1, sizeof(NR_SDAP_Config_t)); - asn1cCalloc(SDAP_config->mappedQoS_FlowsToAdd, sdapFlows); + SDAP_config->pdu_Session = drb_asn1->cnAssociation.sdap_config.pdusession_id; + SDAP_config->sdap_HeaderDL = drb_asn1->cnAssociation.sdap_config.sdap_HeaderDL; + SDAP_config->sdap_HeaderUL = drb_asn1->cnAssociation.sdap_config.sdap_HeaderUL; + SDAP_config->defaultDRB = drb_asn1->cnAssociation.sdap_config.defaultDRB; - SDAP_config->pdu_Session = pduSession->param.pdusession_id; - - if (enable_sdap) { - SDAP_config->sdap_HeaderDL = NR_SDAP_Config__sdap_HeaderDL_present; - SDAP_config->sdap_HeaderUL = NR_SDAP_Config__sdap_HeaderUL_present; - } else { - SDAP_config->sdap_HeaderDL = NR_SDAP_Config__sdap_HeaderDL_absent; - SDAP_config->sdap_HeaderUL = NR_SDAP_Config__sdap_HeaderUL_absent; - } - - SDAP_config->defaultDRB = true; - - for (int qos_flow_index = 0; qos_flow_index < pduSession->param.nb_qos; qos_flow_index++) - { - asn1cSequenceAdd(sdapFlows->list, NR_QFI_t, qfi); - *qfi = pduSession->param.qos[qos_flow_index].qfi; - if(pduSession->param.qos[qos_flow_index].fiveQI > 5) - pduSession->param.used_drbs[drb_id - 1] = DRB_ACTIVE_NONGBR; - else - pduSession->param.used_drbs[drb_id - 1] = DRB_ACTIVE; + for (int qos_flow_index = 0; qos_flow_index < QOSFLOW_MAX_VALUE; qos_flow_index++) { + if (drb_asn1->cnAssociation.sdap_config.mappedQoS_FlowsToAdd[qos_flow_index] != 0) { + asn1cSequenceAdd(sdapFlows->list, NR_QFI_t, qfi); + *qfi = drb_asn1->cnAssociation.sdap_config.mappedQoS_FlowsToAdd[qos_flow_index]; + } } association->choice.sdap_Config = SDAP_config; /* PDCP Configuration */ - asn1cCalloc(DRB_config->pdcp_Config, pdcpConfig); - asn1cCalloc(pdcpConfig->drb, drb); + asn1cCallocOne(drb->discardTimer, drb_asn1->pdcp_config.discardTimer); + asn1cCallocOne(drb->pdcp_SN_SizeUL, drb_asn1->pdcp_config.pdcp_SN_SizeUL); + asn1cCallocOne(drb->pdcp_SN_SizeDL, drb_asn1->pdcp_config.pdcp_SN_SizeDL); + asn1cCallocOne(pdcpConfig->t_Reordering, drb_asn1->pdcp_config.t_Reordering); - asn1cCallocOne(drb->discardTimer, NR_PDCP_Config__drb__discardTimer_infinity); + drb->headerCompression.present = drb_asn1->pdcp_config.headerCompression.present; + drb->headerCompression.choice.notUsed = drb_asn1->pdcp_config.headerCompression.NotUsed; - asn1cCallocOne(drb->pdcp_SN_SizeUL, NR_PDCP_Config__drb__pdcp_SN_SizeUL_len18bits); - asn1cCallocOne(drb->pdcp_SN_SizeDL, NR_PDCP_Config__drb__pdcp_SN_SizeDL_len18bits); - - drb->headerCompression.present = NR_PDCP_Config__drb__headerCompression_PR_notUsed; - drb->headerCompression.choice.notUsed = 0; - - asn1cCallocOne(pdcpConfig->t_Reordering, NR_PDCP_Config__t_Reordering_ms100); - - if (do_drb_integrity) { - asn1cCallocOne(drb->integrityProtection, NR_PDCP_Config__drb__integrityProtection_enabled); + if (!drb_asn1->pdcp_config.integrityProtection) { + asn1cCallocOne(drb->integrityProtection, drb_asn1->pdcp_config.integrityProtection); } - if (!do_drb_ciphering) { + if (!drb_asn1->pdcp_config.ext1.cipheringDisabled) { asn1cCalloc(pdcpConfig->ext1, ext1); - asn1cCallocOne(ext1->cipheringDisabled, NR_PDCP_Config__ext1__cipheringDisabled_true); + asn1cCallocOne(ext1->cipheringDisabled, drb_asn1->pdcp_config.ext1.cipheringDisabled); } - ue->DRB_active[drb_id-1] = DRB_ACTIVE; - return DRB_config; } diff --git a/openair2/RRC/NR/rrc_gNB_radio_bearers.h b/openair2/RRC/NR/rrc_gNB_radio_bearers.h index 62065c1d87..219bc21948 100644 --- a/openair2/RRC/NR/rrc_gNB_radio_bearers.h +++ b/openair2/RRC/NR/rrc_gNB_radio_bearers.h @@ -35,7 +35,24 @@ #define GBR_FLOW (1) #define NONGBR_FLOW (0) -NR_DRB_ToAddMod_t *generateDRB(gNB_RRC_UE_t *rrc_ue, uint8_t drb_id, rrc_pdu_session_param_t *pduSession, bool enable_sdap, int do_drb_integrity, int do_drb_ciphering); +/// @brief Generates an ASN1 DRB-ToAddMod, from the established_drbs in gNB_RRC_UE_t. +/// @param drb_t drb_asn1 +/// @return Returns the ASN1 DRB-ToAddMod structs. +NR_DRB_ToAddMod_t *generateDRB_ASN1(const drb_t *drb_asn1); +/// @brief Creates and stores a DRB in the gNB_RRC_UE_t struct, it doesn't create the actual entity, +/// to create the actual entity use the generateDRB_ASN1. +/// @param ue The gNB_RRC_UE_t struct that holds information for the UEs +/// @param drb_id The Data Radio Bearer Identity to be created for the established DRB. +/// @param pduSession The PDU Session that the DRB is created for. +/// @param enable_sdap If true the SDAP header will be added to the packet, else it will not add or search for SDAP header. +/// @param do_drb_integrity +/// @param do_drb_ciphering +void generateDRB(gNB_RRC_UE_t *ue, + uint8_t drb_id, + rrc_pdu_session_param_t *pduSession, + bool enable_sdap, + int do_drb_integrity, + int do_drb_ciphering); uint8_t next_available_drb(gNB_RRC_UE_t *ue, rrc_pdu_session_param_t *pdusession, bool is_gbr); bool drb_is_active(gNB_RRC_UE_t *ue, uint8_t drb_id); diff --git a/openair2/RRC/NR_UE/L2_interface_ue.c b/openair2/RRC/NR_UE/L2_interface_ue.c index c67069e975..56de3dfa68 100644 --- a/openair2/RRC/NR_UE/L2_interface_ue.c +++ b/openair2/RRC/NR_UE/L2_interface_ue.c @@ -149,39 +149,12 @@ int8_t nr_mac_rrc_data_req_ue(const module_id_t Mod_idP, return 0; } -uint8_t -rrc_data_req_nr_ue( - const protocol_ctxt_t *const ctxt_pP, - const rb_id_t rb_idP, - const mui_t muiP, - const confirm_t confirmP, - const sdu_size_t sdu_sizeP, - uint8_t *const buffer_pP, - const pdcp_transmission_mode_t modeP -) +int8_t nr_rrc_RA_succeeded(const module_id_t mod_id, const uint8_t gNB_index) { - MessageDef *message_p; - // Uses a new buffer to avoid issue with PDCP buffer content that could be changed by PDCP (asynchronous message handling). - uint8_t *message_buffer; - message_buffer = itti_malloc (TASK_RRC_UE, TASK_PDCP_UE, sdu_sizeP); - LOG_D(RRC,"Sending RRC message for SRB %ld, sdu_size %d\n",rb_idP, sdu_sizeP); - memcpy (message_buffer, buffer_pP, sdu_sizeP); - message_p = itti_alloc_new_message ( TASK_RRC_UE, 0, RRC_DCCH_DATA_REQ); - RRC_DCCH_DATA_REQ (message_p).frame = ctxt_pP->frame; - RRC_DCCH_DATA_REQ (message_p).enb_flag = ctxt_pP->enb_flag; - RRC_DCCH_DATA_REQ (message_p).rb_id = rb_idP; - RRC_DCCH_DATA_REQ (message_p).muip = muiP; - RRC_DCCH_DATA_REQ (message_p).confirmp = confirmP; - RRC_DCCH_DATA_REQ (message_p).sdu_size = sdu_sizeP; - RRC_DCCH_DATA_REQ (message_p).sdu_p = message_buffer; - RRC_DCCH_DATA_REQ (message_p).mode = modeP; - RRC_DCCH_DATA_REQ (message_p).module_id = ctxt_pP->module_id; - RRC_DCCH_DATA_REQ(message_p).rnti = ctxt_pP->rntiMaybeUEid; - RRC_DCCH_DATA_REQ (message_p).eNB_index = ctxt_pP->eNB_index; - itti_send_msg_to_task ( - TASK_PDCP_UE, - ctxt_pP->instance, - message_p); - return true; // TODO should be changed to a CNF message later, currently RRC lite does not used the returned value anyway. - + if (NR_UE_rrc_inst[mod_id].Info[gNB_index].T304_active == 1) { + LOG_W(NR_RRC, "T304 was stoped with value %i\n", NR_UE_rrc_inst[mod_id].Info[gNB_index].T304_cnt); + NR_UE_rrc_inst[mod_id].Info[gNB_index].T304_active = 0; + NR_UE_rrc_inst[mod_id].Info[gNB_index].T304_cnt = 0; + } + return 0; } diff --git a/openair2/RRC/NR_UE/rrc_UE.c b/openair2/RRC/NR_UE/rrc_UE.c index ecbaeea17e..dda30839e8 100644 --- a/openair2/RRC/NR_UE/rrc_UE.c +++ b/openair2/RRC/NR_UE/rrc_UE.c @@ -58,7 +58,7 @@ #include "nr-uesoftmodem.h" #include "executables/softmodem-common.h" #include "plmn_data.h" -#include "pdcp.h" +#include "nr_pdcp/nr_pdcp_oai_api.h" #include "UTIL/OSA/osa_defs.h" #include "common/utils/LOG/log.h" #include "common/utils/LOG/vcd_signal_dumper.h" @@ -90,17 +90,6 @@ static const char nr_nas_attach_req_imsi[] = { 0x01, 0x27, 0x11, }; -extern void pdcp_config_set_security( - const protocol_ctxt_t *const ctxt_pP, - pdcp_t *const pdcp_pP, - const rb_id_t rb_idP, - const uint16_t lc_idP, - const uint8_t security_modeP, - uint8_t *const kRRCenc, - uint8_t *const kRRCint, - uint8_t *const kUPenc -); - void nr_rrc_ue_process_ueCapabilityEnquiry( const protocol_ctxt_t *const ctxt_pP, @@ -1286,10 +1275,38 @@ nr_rrc_ue_process_masterCellGroup( xer_fprint(stdout, &asn_DEF_NR_CellGroupConfig, (const void *) cellGroupConfig); } - if( cellGroupConfig->spCellConfig != NULL && cellGroupConfig->spCellConfig->reconfigurationWithSync != NULL){ - //TODO (perform Reconfiguration with sync according to 5.3.5.5.2) - //TODO (resume all suspended radio bearers and resume SCG transmission for all radio bearers, if suspended) - // NSA procedures + // TS 38.331 - Section 5.3.5.5.2 Reconfiguration with sync + if (cellGroupConfig->spCellConfig != NULL && cellGroupConfig->spCellConfig->reconfigurationWithSync != NULL) { + + LOG_A(NR_RRC, "Received the reconfigurationWithSync in %s\n", __FUNCTION__); + + NR_ReconfigurationWithSync_t *reconfigurationWithSync = cellGroupConfig->spCellConfig->reconfigurationWithSync; + NR_UE_rrc_inst[ctxt_pP->module_id].Info[gNB_index].T304_active = 1; + switch (reconfigurationWithSync->t304) { + case NR_ReconfigurationWithSync__t304_ms100: + NR_UE_rrc_inst[ctxt_pP->module_id].Info[gNB_index].T304_cnt = 100; + break; + case NR_ReconfigurationWithSync__t304_ms150: + NR_UE_rrc_inst[ctxt_pP->module_id].Info[gNB_index].T304_cnt = 150; + break; + case NR_ReconfigurationWithSync__t304_ms200: + NR_UE_rrc_inst[ctxt_pP->module_id].Info[gNB_index].T304_cnt = 200; + break; + case NR_ReconfigurationWithSync__t304_ms500: + NR_UE_rrc_inst[ctxt_pP->module_id].Info[gNB_index].T304_cnt = 500; + break; + case NR_ReconfigurationWithSync__t304_ms1000: + NR_UE_rrc_inst[ctxt_pP->module_id].Info[gNB_index].T304_cnt = 1000; + break; + case NR_ReconfigurationWithSync__t304_ms2000: + NR_UE_rrc_inst[ctxt_pP->module_id].Info[gNB_index].T304_cnt = 2000; + break; + case NR_ReconfigurationWithSync__t304_ms10000: + NR_UE_rrc_inst[ctxt_pP->module_id].Info[gNB_index].T304_cnt = 10000; + break; + default: + NR_UE_rrc_inst[ctxt_pP->module_id].Info[gNB_index].T304_cnt = 50; + } } if(NR_UE_rrc_inst[ctxt_pP->module_id].cell_group_config == NULL){ @@ -1372,7 +1389,8 @@ static void rrc_ue_generate_RRCSetupComplete( if (get_softmodem_params()->sa) { as_nas_info_t initialNasMsg; - generateRegistrationRequest(&initialNasMsg, ctxt_pP->module_id); + nr_ue_nas_t *nas = get_ue_nas_info(ctxt_pP->module_id); + generateRegistrationRequest(&initialNasMsg, nas); nas_msg = (char*)initialNasMsg.data; nas_msg_length = initialNasMsg.length; } else { @@ -1397,14 +1415,7 @@ static void rrc_ue_generate_RRCSetupComplete( //for (int i=0;irnti; - rrc_data_req_nr_ue(ctxt_pP, - DCCH, - nr_rrc_mui++, - SDU_CONFIRM_NO, - size, - buffer, - PDCP_TRANSMISSION_MODE_CONTROL); + nr_pdcp_data_req_srb(ctxt_pP->rntiMaybeUEid, DCCH, nr_rrc_mui++, size, buffer, deliver_pdu_srb_rlc, NULL); } int8_t nr_rrc_ue_decode_ccch( const protocol_ctxt_t *const ctxt_pP, const NR_SRB_INFO *const Srb_info, const uint8_t gNB_index ){ @@ -1675,10 +1686,9 @@ int8_t nr_rrc_ue_decode_ccch( const protocol_ctxt_t *const ctxt_pP, const NR_SRB NR_UE_rrc_inst[ctxt_pP->module_id].kgnb[28], NR_UE_rrc_inst[ctxt_pP->module_id].kgnb[29], NR_UE_rrc_inst[ctxt_pP->module_id].kgnb[30], NR_UE_rrc_inst[ctxt_pP->module_id].kgnb[31]); if (securityMode != 0xff) { - pdcp_config_set_security(ctxt_pP, NULL, DCCH, DCCH+2, - NR_UE_rrc_inst[ctxt_pP->module_id].cipheringAlgorithm - | (NR_UE_rrc_inst[ctxt_pP->module_id].integrityProtAlgorithm << 4), - kRRCenc, kRRCint, kUPenc); + uint8_t security_mode = + NR_UE_rrc_inst[ctxt_pP->module_id].cipheringAlgorithm | (NR_UE_rrc_inst[ctxt_pP->module_id].integrityProtAlgorithm << 4); + nr_pdcp_config_set_security(ctxt_pP->rntiMaybeUEid, DCCH, security_mode, kRRCenc, kRRCint, kUPenc); } else { LOG_I(NR_RRC, "skipped pdcp_config_set_security() as securityMode == 0x%02x", securityMode); } @@ -1710,13 +1720,7 @@ int8_t nr_rrc_ue_decode_ccch( const protocol_ctxt_t *const ctxt_pP, const NR_SRB } LOG_T(NR_RRC, "\n"); - rrc_data_req_nr_ue (ctxt_pP, - DCCH, - nr_rrc_mui++, - SDU_CONFIRM_NO, - (enc_rval.encoded + 7) / 8, - buffer, - PDCP_TRANSMISSION_MODE_CONTROL); + nr_pdcp_data_req_srb(ctxt_pP->rntiMaybeUEid, DCCH, nr_rrc_mui++, (enc_rval.encoded + 7) / 8, buffer, deliver_pdu_srb_rlc, NULL); } else LOG_W(NR_RRC,"securityModeCommand->criticalExtensions.present (%d) != NR_SecurityModeCommand__criticalExtensions_PR_securityModeCommand\n", securityModeCommand->criticalExtensions.present); @@ -2202,14 +2206,7 @@ nr_rrc_ue_establish_srb2( nr_rrc_mui, UE_MODULE_ID_TO_INSTANCE(ctxt_pP->module_id), DCCH); - rrc_data_req_nr_ue ( - ctxt_pP, - DCCH, - nr_rrc_mui++, - SDU_CONFIRM_NO, - size, - buffer, - PDCP_TRANSMISSION_MODE_CONTROL); + nr_pdcp_data_req_srb(ctxt_pP->rntiMaybeUEid, DCCH, nr_rrc_mui++, size, buffer, deliver_pdu_srb_rlc, NULL); } // from NR SRB1 @@ -2228,11 +2225,9 @@ nr_rrc_ue_establish_srb2( NR_DL_DCCH_Message_t *dl_dcch_msg = NULL; MessageDef *msg_p; - if (Srb_id != 1) { + if (Srb_id != 1 && Srb_id != 2) { LOG_E(NR_RRC,"[UE %d] Frame %d: Received message on DL-DCCH (SRB%ld), should not have ...\n", ctxt_pP->module_id, ctxt_pP->frame, Srb_id); - } else { - LOG_D(NR_RRC, "Received message on SRB%ld\n", Srb_id); } LOG_D(NR_RRC, "Decoding DL-DCCH Message\n"); @@ -2287,7 +2282,7 @@ nr_rrc_ue_establish_srb2( NR_RRCRelease_IEs__deprioritisationReq__deprioritisationType_frequency; } - itti_send_msg_to_task(TASK_NAS_UE, ctxt_pP->instance, msg_p); + itti_send_msg_to_task(TASK_NAS_NRUE, ctxt_pP->instance, msg_p); break; case NR_DL_DCCH_MessageType__c1_PR_ueCapabilityEnquiry: LOG_I(NR_RRC, "[UE %d] Received Capability Enquiry (gNB %d)\n", ctxt_pP->module_id,gNB_indexP); @@ -2458,21 +2453,8 @@ nr_rrc_ue_establish_srb2( /* Transfer data to PDCP */ PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, ue_mod_id, GNB_FLAG_NO, NR_UE_rrc_inst[ue_mod_id].Info[0].rnti, 0, 0,0); // check if SRB2 is created, if yes request data_req on DCCH1 (SRB2) - if(NR_UE_rrc_inst[ue_mod_id].SRB2_config[0] == NULL) { - rrc_data_req_nr_ue (&ctxt, - DCCH, - nr_rrc_mui++, - SDU_CONFIRM_NO, - length, buffer, - PDCP_TRANSMISSION_MODE_CONTROL); - } else { - rrc_data_req_nr_ue (&ctxt, - DCCH1, - nr_rrc_mui++, - SDU_CONFIRM_NO, - length, buffer, - PDCP_TRANSMISSION_MODE_CONTROL); - } + rb_id_t srb_id = NR_UE_rrc_inst[ue_mod_id].SRB2_config[0] == NULL ? DCCH : DCCH1; + nr_pdcp_data_req_srb(ctxt.rntiMaybeUEid, srb_id, nr_rrc_mui++, length, buffer, deliver_pdu_srb_rlc, NULL); break; } @@ -2616,14 +2598,7 @@ nr_rrc_ue_process_ueCapabilityEnquiry( } LOG_I(NR_RRC, "UECapabilityInformation Encoded %zd bits (%zd bytes)\n",enc_rval.encoded,(enc_rval.encoded+7)/8); - rrc_data_req_nr_ue ( - ctxt_pP, - DCCH, - nr_rrc_mui++, - SDU_CONFIRM_NO, - (enc_rval.encoded + 7) / 8, - buffer, - PDCP_TRANSMISSION_MODE_CONTROL); + nr_pdcp_data_req_srb(ctxt_pP->rntiMaybeUEid, DCCH, nr_rrc_mui++, (enc_rval.encoded + 7) / 8, buffer, deliver_pdu_srb_rlc, NULL); } } } @@ -2862,3 +2837,29 @@ void process_lte_nsa_msg(nsa_msg_t *msg, int msg_len) LOG_E(NR_RRC, "No NSA Message Found\n"); } } + +void *nr_rrc_timers_update() { + + while (1) { + + for (int mod_id = 0; mod_id < NB_NR_UE_INST; mod_id++) { + for (int i = 0; i < NB_SIG_CNX_UE; i++) { + NR_UE_RRC_INFO *timers = &NR_UE_rrc_inst[mod_id].Info[i]; + + // T304 + if (timers->T304_active == 1) { + if ((timers->T304_cnt % 100) == 0) { + LOG_W(NR_RRC, "T304: %u\n", timers->T304_cnt); + } + if (timers->T304_cnt == 1) { + timers->T304_active = 0; + } + timers->T304_cnt--; + } + + } + } + + usleep(1000); + } +} diff --git a/openair2/RRC/NR_UE/rrc_proto.h b/openair2/RRC/NR_UE/rrc_proto.h index 510fbff230..6c0499933e 100644 --- a/openair2/RRC/NR_UE/rrc_proto.h +++ b/openair2/RRC/NR_UE/rrc_proto.h @@ -145,21 +145,15 @@ int8_t nr_mac_rrc_data_req_ue(const module_id_t Mod_idP, const rb_id_t Srb_id, uint8_t *buffer_pP); -uint8_t -rrc_data_req_nr_ue( - const protocol_ctxt_t *const ctxt_pP, - const rb_id_t rb_idP, - const mui_t muiP, - const confirm_t confirmP, - const sdu_size_t sdu_sizeP, - uint8_t *const buffer_pP, - const pdcp_transmission_mode_t modeP -); +int8_t nr_rrc_RA_succeeded(const module_id_t mod_id, const uint8_t gNB_index); /**\brief RRC UE task. \param void *args_p Pointer on arguments to start the task. */ void *rrc_nrue_task(void *args_p); +/**\brief RRC timers update at UE. */ +void *nr_rrc_timers_update(); + /**\brief RRC NSA UE task. \param void *args_p Pointer on arguments to start the task. */ void *recv_msgs_from_lte_ue(void *args_p); diff --git a/openair2/SDAP/nr_sdap/nr_sdap_entity.c b/openair2/SDAP/nr_sdap/nr_sdap_entity.c index 280663e2b0..e81490630c 100644 --- a/openair2/SDAP/nr_sdap/nr_sdap_entity.c +++ b/openair2/SDAP/nr_sdap/nr_sdap_entity.c @@ -21,7 +21,7 @@ #include "nr_sdap_entity.h" #include "common/utils/LOG/log.h" -#include +#include #include #include "openair2/LAYER2/nr_pdcp/nr_pdcp_ue_manager.h" @@ -37,15 +37,20 @@ static nr_sdap_entity_info sdap_info; instance_t *N3GTPUInst = NULL; -nr_pdcp_ue_manager_t *nr_pdcp_sdap_get_ue_manager(void); - void nr_pdcp_submit_sdap_ctrl_pdu(ue_id_t ue_id, rb_id_t sdap_ctrl_pdu_drb, nr_sdap_ul_hdr_t ctrl_pdu) { - nr_pdcp_ue_t *ue; - nr_pdcp_ue_manager_t *nr_pdcp_ue_manager; - nr_pdcp_ue_manager = nr_pdcp_sdap_get_ue_manager(); - ue = nr_pdcp_manager_get_ue(nr_pdcp_ue_manager, ue_id); - ue->drb[sdap_ctrl_pdu_drb-1]->recv_sdu(ue->drb[sdap_ctrl_pdu_drb-1], (char*)&ctrl_pdu, SDAP_HDR_LENGTH, RLC_MUI_UNDEFINED); + + protocol_ctxt_t ctxt = { .rntiMaybeUEid = ue_id }; + nr_pdcp_data_req_drb(&ctxt, + SRB_FLAG_NO, + sdap_ctrl_pdu_drb, + RLC_MUI_UNDEFINED, + SDU_CONFIRM_NO, + SDAP_HDR_LENGTH, + (unsigned char *)&ctrl_pdu, + PDCP_TRANSMISSION_MODE_UNKNOWN, + NULL, + NULL); LOG_D(SDAP, "Control PDU - Submitting Control PDU to DRB ID: %ld\n", sdap_ctrl_pdu_drb); LOG_D(SDAP, "QFI: %u\n R: %u\n D/C: %u\n", ctrl_pdu.QFI, ctrl_pdu.R, ctrl_pdu.DC); return; @@ -87,16 +92,16 @@ static bool nr_sdap_tx_entity(nr_sdap_entity_t *entity, if(!pdcp_ent_has_sdap){ LOG_D(SDAP, "TX - DRB ID: %ld does not have SDAP\n", entity->qfi2drb_table[qfi].drb_id); - ret = pdcp_data_req(ctxt_p, - srb_flag, - sdap_drb_id, - mui, - confirm, - sdu_buffer_size, - sdu_buffer, - pt_mode, - sourceL2Id, - destinationL2Id); + ret = nr_pdcp_data_req_drb(ctxt_p, + srb_flag, + sdap_drb_id, + mui, + confirm, + sdu_buffer_size, + sdu_buffer, + pt_mode, + sourceL2Id, + destinationL2Id); if(!ret) LOG_E(SDAP, "%s:%d:%s: PDCP refused PDU\n", __FILE__, __LINE__, __FUNCTION__); @@ -155,16 +160,16 @@ static bool nr_sdap_tx_entity(nr_sdap_entity_t *entity, * * Downlink gNB side */ - ret = pdcp_data_req(ctxt_p, - srb_flag, - sdap_drb_id, - mui, - confirm, - sdu_buffer_size+offset, - sdap_buf, - pt_mode, - sourceL2Id, - destinationL2Id); + ret = nr_pdcp_data_req_drb(ctxt_p, + srb_flag, + sdap_drb_id, + mui, + confirm, + sdu_buffer_size + offset, + sdap_buf, + pt_mode, + sourceL2Id, + destinationL2Id); if(!ret) LOG_E(SDAP, "%s:%d:%s: PDCP refused PDU\n", __FILE__, __LINE__, __FUNCTION__); diff --git a/openair3/NAS/COMMON/EMM/MSG/FGSDeregistrationRequestUEOriginating.c b/openair3/NAS/COMMON/EMM/MSG/FGSDeregistrationRequestUEOriginating.c new file mode 100644 index 0000000000..0d9a4bbac2 --- /dev/null +++ b/openair3/NAS/COMMON/EMM/MSG/FGSDeregistrationRequestUEOriginating.c @@ -0,0 +1,59 @@ +/* + * 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.c + * \brief registration request procedures for gNB + * \author Yoshio INOUE, Masayuki HARADA + * \email yoshio.inoue@fujitsu.com,masayuki.harada@fujitsu.com + * \date 2020 + * \version 0.1 + */ + +#include +#include +#include +#include + +#include "FGSDeregistrationRequestUEOriginating.h" + +int encode_fgs_deregistration_request_ue_originating(fgs_deregistration_request_ue_originating_msg *drr, + uint8_t *buffer, + uint32_t len) +{ + int encoded = 0; + FGSDeregistrationType *dt = &drr->deregistrationtype; + *(buffer + encoded) = ((dt->switchoff & 0x1) << 7) + | ((dt->reregistration_required & 0x1) << 6) + | ((dt->access_type & 0x3) << 4); + + int encode_result; + if ((encode_result = encode_nas_key_set_identifier(&drr->naskeysetidentifier, 0, buffer + encoded, len - encoded)) < 0) + return encode_result; + + encoded++; + + if ((encode_result = encode_5gs_mobile_identity(&drr->fgsmobileidentity, 0, buffer + encoded, len - encoded)) < 0) + return encode_result; + else + encoded += encode_result; + + return encoded; +} diff --git a/openair3/NAS/COMMON/EMM/MSG/FGSDeregistrationRequestUEOriginating.h b/openair3/NAS/COMMON/EMM/MSG/FGSDeregistrationRequestUEOriginating.h new file mode 100644 index 0000000000..2bccd8a5bd --- /dev/null +++ b/openair3/NAS/COMMON/EMM/MSG/FGSDeregistrationRequestUEOriginating.h @@ -0,0 +1,60 @@ +/* + * 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 + */ + +#ifndef FGS_DEREGISTRATION_REQUEST_UE_ORIGINATING_H_ +#define FGS_DEREGISTRATION_REQUEST_UE_ORIGINATING_H_ + +#include +#include +#include + +#include "ExtendedProtocolDiscriminator.h" +#include "SecurityHeaderType.h" +#include "SpareHalfOctet.h" +#include "MessageType.h" +#include "FGSDeregistrationType.h" +#include "NasKeySetIdentifier.h" +#include "FGSMobileIdentity.h" + +/* + * Message name: De-registration request (UE originating de-registration) + * Description: This message is sent by the UE to the AMF. See TS24.501 table 8.2.12.1.1. + * Significance: dual + * Direction: UE to network + */ + +typedef struct fgs_deregistration_request_ue_originating_msg_tag { + /* Mandatory fields */ + ExtendedProtocolDiscriminator protocoldiscriminator; + SecurityHeaderType securityheadertype: 4; + SpareHalfOctet sparehalfoctet: 4; + MessageType messagetype; + FGSDeregistrationType deregistrationtype; + NasKeySetIdentifier naskeysetidentifier; + FGSMobileIdentity fgsmobileidentity; +} fgs_deregistration_request_ue_originating_msg; + +int encode_fgs_deregistration_request_ue_originating(fgs_deregistration_request_ue_originating_msg *registrationrequest, + uint8_t *buffer, + uint32_t len); + +#endif /* ! defined(REGISTRATION_REQUEST_H_) */ + diff --git a/openair3/NAS/COMMON/EMM/MSG/RegistrationAccept.c b/openair3/NAS/COMMON/EMM/MSG/RegistrationAccept.c index d8fde7e2cc..c34d777bd5 100644 --- a/openair3/NAS/COMMON/EMM/MSG/RegistrationAccept.c +++ b/openair3/NAS/COMMON/EMM/MSG/RegistrationAccept.c @@ -50,6 +50,16 @@ int decode_registration_accept(registration_accept_msg *registration_accept, uin decoded += decoded_result; + if (decoded < len && buffer[decoded] == 0x77) { + registration_accept->guti = calloc(1, sizeof(*registration_accept->guti)); + if (!registration_accept->guti) + return -1; + int mi_dec = decode_5gs_mobile_identity(registration_accept->guti, 0x77, buffer + decoded, len - decoded); + if (mi_dec < 0) + return -1; + decoded += mi_dec; + } + // todo ,Decoding optional fields return decoded; } @@ -64,6 +74,13 @@ int encode_registration_accept(registration_accept_msg *registration_accept, uin *(buffer + encoded) = encode_fgs_registration_result(®istration_accept->fgsregistrationresult); encoded = encoded + 2; + if (registration_accept->guti) { + int mi_enc = encode_5gs_mobile_identity(registration_accept->guti, 0x77, buffer + encoded, len - encoded); + if (mi_enc < 0) + return mi_enc; + encoded += mi_enc; + } + // todo ,Encoding optional fields LOG_FUNC_RETURN(encoded); } diff --git a/openair3/NAS/COMMON/EMM/MSG/RegistrationAccept.h b/openair3/NAS/COMMON/EMM/MSG/RegistrationAccept.h index 08daec2646..e0d3ade23a 100644 --- a/openair3/NAS/COMMON/EMM/MSG/RegistrationAccept.h +++ b/openair3/NAS/COMMON/EMM/MSG/RegistrationAccept.h @@ -38,6 +38,7 @@ #include "SpareHalfOctet.h" #include "MessageType.h" #include "FGSRegistrationResult.h" +#include "FGSMobileIdentity.h" #ifndef REGISTRATION_ACCEPT_H_ #define REGISTRATION_ACCEPT_H_ @@ -56,6 +57,9 @@ typedef struct registration_accept_msg_tag { SpareHalfOctet sparehalfoctet:4; MessageType messagetype; FGSRegistrationResult fgsregistrationresult; + + /* Optional fields */ + FGSMobileIdentity *guti; } registration_accept_msg; int decode_registration_accept(registration_accept_msg *registrationaccept, uint8_t *buffer, uint32_t len); diff --git a/openair3/NAS/COMMON/IES/FGSDeregistrationType.h b/openair3/NAS/COMMON/IES/FGSDeregistrationType.h new file mode 100644 index 0000000000..84a09657d4 --- /dev/null +++ b/openair3/NAS/COMMON/IES/FGSDeregistrationType.h @@ -0,0 +1,46 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.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 + */ + +#ifndef FGS_DEREGISTRATION_TYPE_H_ +#define FGS_DEREGISTRATION_TYPE_H_ + +#include +#include "OctetString.h" + +#define FGS_DEREGISTRATION_TYPE_MINIMUM_LENGTH 1 +#define FGS_DEREGISTRATION_TYPE_MAXIMUM_LENGTH 1 + +typedef struct FGSDeregistrationType_tag { +#define NORMAL_DEREGISTRATION 0 +#define SWITCH_OFF 1 + uint8_t switchoff: 1; +#define REREGISTRATION_NOT_REQUIRED 0 +#define REREGISTRATION_REQUIRED 1 + uint8_t reregistration_required: 1; +#define TGPP_ACCESS 1 +#define NON_TGPP_ACCESS 2 +#define TGPP_AND_NON_TGPP_ACCESS 3 + uint8_t access_type: 2; +} FGSDeregistrationType; + +int encode_fgs_deregistration_type(FGSDeregistrationType *dt, uint8_t iei, uint8_t *buffer, uint32_t len); + +#endif /* FGS_DEREGISTRATION_TYPE_H_ */ diff --git a/openair3/NAS/COMMON/IES/FGSMobileIdentity.c b/openair3/NAS/COMMON/IES/FGSMobileIdentity.c index 3bdddc3619..872fc8e53c 100644 --- a/openair3/NAS/COMMON/IES/FGSMobileIdentity.c +++ b/openair3/NAS/COMMON/IES/FGSMobileIdentity.c @@ -54,8 +54,8 @@ int decode_5gs_mobile_identity(FGSMobileIdentity *fgsmobileidentity, uint8_t iei decoded++; } - ielen = *(buffer + decoded); - decoded++; + ielen = *(uint16_t*)(buffer + decoded); /* length is two bytes */ + decoded += 2; CHECK_LENGTH_DECODER(len - decoded, ielen); uint8_t typeofidentity = *(buffer + decoded) & 0x7; @@ -63,6 +63,8 @@ int decode_5gs_mobile_identity(FGSMobileIdentity *fgsmobileidentity, uint8_t iei if (typeofidentity == FGS_MOBILE_IDENTITY_5G_GUTI) { decoded_rc = decode_guti_5gs_mobile_identity(&fgsmobileidentity->guti, buffer + decoded); + } else { + AssertFatal(false, "Mobile Identity encoding of type %d not implemented\n", typeofidentity); } if (decoded_rc < 0) { diff --git a/openair3/NAS/COMMON/NR_NAS_defs.h b/openair3/NAS/COMMON/NR_NAS_defs.h index 54ac8c037e..b6c0b715fc 100644 --- a/openair3/NAS/COMMON/NR_NAS_defs.h +++ b/openair3/NAS/COMMON/NR_NAS_defs.h @@ -364,6 +364,12 @@ typedef struct __attribute__((packed)) { } securityModeCommand_t; +typedef struct __attribute__((packed)) { + Extendedprotocoldiscriminator_t epd: 8; + Security_header_t sh: 8; + SGSmobilitymanagementmessages_t mt: 8; +} deregistrationRequestUEOriginating_t; + typedef struct { uicc_t *uicc; } nr_user_nas_t; @@ -371,7 +377,7 @@ typedef struct { #define STATIC_ASSERT(test_for_true) _Static_assert((test_for_true), "(" #test_for_true ") failed") #define myCalloc(var, type) type * var=(type*)calloc(sizeof(type),1); #define arrayCpy(tO, FroM) STATIC_ASSERT(sizeof(tO) == sizeof(FroM)) ; memcpy(tO, FroM, sizeof(tO)) -int resToresStar(uint8_t *msg, uicc_t* uicc); +int resToresStar(uint8_t *msg, const uicc_t* uicc); int identityResponse(void **msg, nr_user_nas_t *UE); int authenticationResponse(void **msg, nr_user_nas_t *UE); diff --git a/openair3/NAS/COMMON/nr_common.c b/openair3/NAS/COMMON/nr_common.c index 590ccf65ae..0a7aae2a17 100644 --- a/openair3/NAS/COMMON/nr_common.c +++ b/openair3/NAS/COMMON/nr_common.c @@ -39,7 +39,7 @@ void servingNetworkName(uint8_t *msg, char * imsiStr, int nmc_size) { memcpy(msg+13, imsiStr, 3); } -int resToresStar(uint8_t *msg, uicc_t* uicc) { +int resToresStar(uint8_t *msg, const uicc_t* uicc) { // TS 33.220 annex B.2 => FC=0x6B in TS 33.501 annex A.4 //input S to KDF uint8_t S[128]= {0}; diff --git a/openair3/NAS/NR_UE/nr_nas_msg_sim.c b/openair3/NAS/NR_UE/nr_nas_msg_sim.c index 9d3eb6db76..e20a0fc99e 100644 --- a/openair3/NAS/NR_UE/nr_nas_msg_sim.c +++ b/openair3/NAS/NR_UE/nr_nas_msg_sim.c @@ -42,9 +42,10 @@ #include "kdf.h" #include "PduSessionEstablishRequest.h" #include "PduSessionEstablishmentAccept.h" +#include "RegistrationAccept.h" +#include "FGSDeregistrationRequestUEOriginating.h" #include "intertask_interface.h" #include "openair2/RRC/NAS/nas_config.h" -#include #include #include #include @@ -54,7 +55,7 @@ uint8_t *registration_request_buf; uint32_t registration_request_len; extern char *baseNetAddress; extern uint16_t NB_UE_INST; -static ue_sa_security_key_t ** ue_security_key; +static nr_ue_nas_t nr_ue_nas; static int nas_protected_security_header_encode( char *buffer, @@ -104,6 +105,50 @@ static int _nas_mm_msg_encode_header(const mm_msg_header_t *header, return (size); } +static int fill_suci(FGSMobileIdentity *mi, const uicc_t *uicc) +{ + mi->suci.typeofidentity = FGS_MOBILE_IDENTITY_SUCI; + mi->suci.mncdigit1 = uicc->nmc_size == 2 ? uicc->imsiStr[3] - '0' : uicc->imsiStr[4] - '0'; + mi->suci.mncdigit2 = uicc->nmc_size == 2 ? uicc->imsiStr[4] - '0' : uicc->imsiStr[5] - '0'; + mi->suci.mncdigit3 = uicc->nmc_size == 2 ? 0xF : uicc->imsiStr[3] - '0'; + mi->suci.mccdigit1 = uicc->imsiStr[0] - '0'; + mi->suci.mccdigit2 = uicc->imsiStr[1] - '0'; + mi->suci.mccdigit3 = uicc->imsiStr[2] - '0'; + memcpy(mi->suci.schemeoutput, uicc->imsiStr + 3 + uicc->nmc_size, strlen(uicc->imsiStr) - (3 + uicc->nmc_size)); + return sizeof(Suci5GSMobileIdentity_t); +} + +static int fill_guti(FGSMobileIdentity *mi, const Guti5GSMobileIdentity_t *guti) +{ + AssertFatal(guti != NULL, "UE has no GUTI\n"); + mi->guti = *guti; + return 13; +} + +static int fill_imeisv(FGSMobileIdentity *mi, const uicc_t *uicc) +{ + int i=0; + mi->imeisv.typeofidentity = FGS_MOBILE_IDENTITY_IMEISV; + mi->imeisv.digittac01 = getImeisvDigit(uicc, i++); + mi->imeisv.digittac02 = getImeisvDigit(uicc, i++); + mi->imeisv.digittac03 = getImeisvDigit(uicc, i++); + mi->imeisv.digittac04 = getImeisvDigit(uicc, i++); + mi->imeisv.digittac05 = getImeisvDigit(uicc, i++); + mi->imeisv.digittac06 = getImeisvDigit(uicc, i++); + mi->imeisv.digittac07 = getImeisvDigit(uicc, i++); + mi->imeisv.digittac08 = getImeisvDigit(uicc, i++); + mi->imeisv.digit09 = getImeisvDigit(uicc, i++); + mi->imeisv.digit10 = getImeisvDigit(uicc, i++); + mi->imeisv.digit11 = getImeisvDigit(uicc, i++); + mi->imeisv.digit12 = getImeisvDigit(uicc, i++); + mi->imeisv.digit13 = getImeisvDigit(uicc, i++); + mi->imeisv.digit14 = getImeisvDigit(uicc, i++); + mi->imeisv.digitsv1 = getImeisvDigit(uicc, i++); + mi->imeisv.digitsv2 = getImeisvDigit(uicc, i++); + mi->imeisv.spare = 0x0f; + mi->imeisv.oddeven = 1; + return 19; +} int mm_msg_encode(MM_msg *mm_msg, uint8_t *buffer, uint32_t len) { LOG_FUNC_IN; @@ -140,6 +185,9 @@ int mm_msg_encode(MM_msg *mm_msg, uint8_t *buffer, uint32_t len) { case FGS_UPLINK_NAS_TRANSPORT: encode_result = encode_fgs_uplink_nas_transport(&mm_msg->uplink_nas_transport, buffer, len); break; + case FGS_DEREGISTRATION_REQUEST_UE_ORIGINATING: + encode_result = encode_fgs_deregistration_request_ue_originating(&mm_msg->fgs_deregistration_request_ue_originating, buffer, len); + break; default: LOG_TRACE(ERROR, "EMM-MSG - Unexpected message type: 0x%x", mm_msg->header.message_type); @@ -303,25 +351,18 @@ void derive_kgnb(uint8_t kamf[32], uint32_t count, uint8_t *kgnb){ printf("\n"); } -void derive_ue_keys(int Mod_id, uint8_t *buf, uicc_t *uicc) { +void derive_ue_keys(uint8_t *buf, nr_ue_nas_t *nas) { uint8_t ak[6]; uint8_t sqn[6]; - AssertFatal (Mod_id < NB_UE_INST, "Failed, Mod_id %d is over NB_UE_INST!\n", Mod_id); - if(ue_security_key[Mod_id]){ - // clear old key - memset(ue_security_key[Mod_id],0,sizeof(ue_sa_security_key_t)); - }else{ - // Allocate new memory - ue_security_key[Mod_id]=(ue_sa_security_key_t *)calloc(1,sizeof(ue_sa_security_key_t)); - } - uint8_t *kausf = ue_security_key[Mod_id]->kausf; - uint8_t *kseaf = ue_security_key[Mod_id]->kseaf; - uint8_t *kamf = ue_security_key[Mod_id]->kamf; - uint8_t *knas_int = ue_security_key[Mod_id]->knas_int; - uint8_t *output = ue_security_key[Mod_id]->res; - uint8_t *rand = ue_security_key[Mod_id]->rand; - uint8_t *kgnb = ue_security_key[Mod_id]->kgnb; + DevAssert(nas != NULL); + uint8_t *kausf = nas->security.kausf; + uint8_t *kseaf = nas->security.kseaf; + uint8_t *kamf = nas->security.kamf; + uint8_t *knas_int = nas->security.knas_int; + uint8_t *output = nas->security.res; + uint8_t *rand = nas->security.rand; + uint8_t *kgnb = nas->security.kgnb; // get RAND for authentication request for(int index = 0; index < 16;index++){ @@ -330,17 +371,17 @@ void derive_ue_keys(int Mod_id, uint8_t *buf, uicc_t *uicc) { uint8_t resTemp[16]; uint8_t ck[16], ik[16]; - f2345(uicc->key, rand, resTemp, ck, ik, ak, uicc->opc); + f2345(nas->uicc->key, rand, resTemp, ck, ik, ak, nas->uicc->opc); - transferRES(ck, ik, resTemp, rand, output, uicc); + transferRES(ck, ik, resTemp, rand, output, nas->uicc); for(int index = 0; index < 6; index++){ sqn[index] = buf[26+index]; } - derive_kausf(ck, ik, sqn, kausf, uicc); - derive_kseaf(kausf, kseaf, uicc); - derive_kamf(kseaf, kamf, 0x0000, uicc); + derive_kausf(ck, ik, sqn, kausf, nas->uicc); + derive_kseaf(kausf, kseaf, nas->uicc); + derive_kamf(kseaf, kamf, 0x0000, nas->uicc); derive_knas(0x02, 2, kamf, knas_int); derive_kgnb(kamf,0,kgnb); @@ -370,11 +411,17 @@ void derive_ue_keys(int Mod_id, uint8_t *buf, uicc_t *uicc) { printf("\n"); } -void generateRegistrationRequest(as_nas_info_t *initialNasMsg, int Mod_id) { +nr_ue_nas_t *get_ue_nas_info(module_id_t module_id) +{ + DevAssert(module_id == 0); + return &nr_ue_nas; +} + +void generateRegistrationRequest(as_nas_info_t *initialNasMsg, nr_ue_nas_t *nas) +{ int size = sizeof(mm_msg_header_t); fgs_nas_message_t nas_msg={0}; MM_msg *mm_msg; - uicc_t * uicc=checkUicc(Mod_id); mm_msg = &nas_msg.plain.mm_msg; // set header @@ -393,37 +440,10 @@ void generateRegistrationRequest(as_nas_info_t *initialNasMsg, int Mod_id) { mm_msg->registration_request.fgsregistrationtype = INITIAL_REGISTRATION; mm_msg->registration_request.naskeysetidentifier.naskeysetidentifier = 1; size += 1; - if(0){ - mm_msg->registration_request.fgsmobileidentity.guti.typeofidentity = FGS_MOBILE_IDENTITY_5G_GUTI; - mm_msg->registration_request.fgsmobileidentity.guti.amfregionid = 0xca; - mm_msg->registration_request.fgsmobileidentity.guti.amfpointer = 0; - mm_msg->registration_request.fgsmobileidentity.guti.amfsetid = 1016; - mm_msg->registration_request.fgsmobileidentity.guti.tmsi = 10; - mm_msg->registration_request.fgsmobileidentity.guti.mncdigit1 = - uicc->nmc_size==2 ? uicc->imsiStr[3]-'0' : uicc->imsiStr[4]-'0'; - mm_msg->registration_request.fgsmobileidentity.guti.mncdigit2 = - uicc->nmc_size==2 ? uicc->imsiStr[4]-'0' : uicc->imsiStr[5]-'0'; - mm_msg->registration_request.fgsmobileidentity.guti.mncdigit3 = - uicc->nmc_size==2 ? 0xf : uicc->imsiStr[3]-'0'; - mm_msg->registration_request.fgsmobileidentity.guti.mccdigit1 = uicc->imsiStr[0]-'0'; - mm_msg->registration_request.fgsmobileidentity.guti.mccdigit2 = uicc->imsiStr[1]-'0'; - mm_msg->registration_request.fgsmobileidentity.guti.mccdigit3 = uicc->imsiStr[2]-'0'; - - size += 13; - + if(nas->guti){ + size += fill_guti(&mm_msg->registration_request.fgsmobileidentity, nas->guti); } else { - mm_msg->registration_request.fgsmobileidentity.suci.typeofidentity = FGS_MOBILE_IDENTITY_SUCI; - mm_msg->registration_request.fgsmobileidentity.suci.mncdigit1 = - uicc->nmc_size==2 ? uicc->imsiStr[3]-'0' : uicc->imsiStr[4]-'0'; - mm_msg->registration_request.fgsmobileidentity.suci.mncdigit2 = - uicc->nmc_size==2 ? uicc->imsiStr[4]-'0' : uicc->imsiStr[5]-'0'; - mm_msg->registration_request.fgsmobileidentity.suci.mncdigit3 = - uicc->nmc_size==2 ? 0xf : uicc->imsiStr[3]-'0'; - mm_msg->registration_request.fgsmobileidentity.suci.mccdigit1 = uicc->imsiStr[0]-'0'; - mm_msg->registration_request.fgsmobileidentity.suci.mccdigit2 = uicc->imsiStr[1]-'0'; - mm_msg->registration_request.fgsmobileidentity.suci.mccdigit3 = uicc->imsiStr[2]-'0'; - memcpy(mm_msg->registration_request.fgsmobileidentity.suci.schemeoutput, uicc->imsiStr+3+uicc->nmc_size, strlen(uicc->imsiStr) - (3+uicc->nmc_size)); - size += sizeof(Suci5GSMobileIdentity_t); + size += fill_suci(&mm_msg->registration_request.fgsmobileidentity, nas->uicc); } mm_msg->registration_request.presencemask |= REGISTRATION_REQUEST_5GMM_CAPABILITY_PRESENT; @@ -471,18 +491,7 @@ void generateIdentityResponse(as_nas_info_t *initialNasMsg, uint8_t identitytype mm_msg->fgs_identity_response.messagetype = FGS_IDENTITY_RESPONSE; size += 1; if(identitytype == FGS_MOBILE_IDENTITY_SUCI){ - mm_msg->fgs_identity_response.fgsmobileidentity.suci.typeofidentity = FGS_MOBILE_IDENTITY_SUCI; - mm_msg->fgs_identity_response.fgsmobileidentity.suci.mncdigit1 = - uicc->nmc_size==2 ? uicc->imsiStr[3]-'0' : uicc->imsiStr[4]-'0'; - mm_msg->fgs_identity_response.fgsmobileidentity.suci.mncdigit2 = - uicc->nmc_size==2 ? uicc->imsiStr[4]-'0' : uicc->imsiStr[5]-'0'; - mm_msg->fgs_identity_response.fgsmobileidentity.suci.mncdigit3 = - uicc->nmc_size==2? 0xF : uicc->imsiStr[3]-'0'; - mm_msg->fgs_identity_response.fgsmobileidentity.suci.mccdigit1 = uicc->imsiStr[0]-'0'; - mm_msg->fgs_identity_response.fgsmobileidentity.suci.mccdigit2 = uicc->imsiStr[1]-'0'; - mm_msg->fgs_identity_response.fgsmobileidentity.suci.mccdigit3 = uicc->imsiStr[2]-'0'; - memcpy(mm_msg->registration_request.fgsmobileidentity.suci.schemeoutput, uicc->imsiStr+3+uicc->nmc_size, strlen(uicc->imsiStr) - (3+uicc->nmc_size)); - size += sizeof(Suci5GSMobileIdentity_t); + size += fill_suci(&mm_msg->fgs_identity_response.fgsmobileidentity, uicc); } // encode the message @@ -492,13 +501,13 @@ void generateIdentityResponse(as_nas_info_t *initialNasMsg, uint8_t identitytype } -static void generateAuthenticationResp(int Mod_id,as_nas_info_t *initialNasMsg, uint8_t *buf, uicc_t *uicc){ - - derive_ue_keys(Mod_id,buf,uicc); +static void generateAuthenticationResp(nr_ue_nas_t *nas, as_nas_info_t *initialNasMsg, uint8_t *buf) +{ + derive_ue_keys(buf, nas); OctetString res; res.length = 16; res.value = calloc(1,16); - memcpy(res.value,ue_security_key[Mod_id]->res,16); + memcpy(res.value, nas->security.res, 16); int size = sizeof(mm_msg_header_t); fgs_nas_message_t nas_msg; @@ -528,39 +537,15 @@ static void generateAuthenticationResp(int Mod_id,as_nas_info_t *initialNasMsg, initialNasMsg->length = mm_msg_encode(mm_msg, (uint8_t*)(initialNasMsg->data), size); } -int nas_itti_kgnb_refresh_req(const uint8_t kgnb[32], int instance) { +int nas_itti_kgnb_refresh_req(const uint8_t kgnb[32]) +{ MessageDef *message_p; message_p = itti_alloc_new_message(TASK_NAS_NRUE, 0, NAS_KENB_REFRESH_REQ); memcpy(NAS_KENB_REFRESH_REQ(message_p).kenb, kgnb, sizeof(NAS_KENB_REFRESH_REQ(message_p).kenb)); - return itti_send_msg_to_task(TASK_RRC_NRUE, instance, message_p); + return itti_send_msg_to_task(TASK_RRC_NRUE, 0, message_p); } -static int addImeisv(int Mod_id,MM_msg *mm_msg) -{ - int i=0; - mm_msg->fgs_security_mode_complete.fgsmobileidentity.imeisv.typeofidentity = FGS_MOBILE_IDENTITY_IMEISV; - mm_msg->fgs_security_mode_complete.fgsmobileidentity.imeisv.digittac01 = getImeisvDigit(Mod_id,i++); - mm_msg->fgs_security_mode_complete.fgsmobileidentity.imeisv.digittac02 = getImeisvDigit(Mod_id,i++); - mm_msg->fgs_security_mode_complete.fgsmobileidentity.imeisv.digittac03 = getImeisvDigit(Mod_id,i++); - mm_msg->fgs_security_mode_complete.fgsmobileidentity.imeisv.digittac04 = getImeisvDigit(Mod_id,i++); - mm_msg->fgs_security_mode_complete.fgsmobileidentity.imeisv.digittac05 = getImeisvDigit(Mod_id,i++); - mm_msg->fgs_security_mode_complete.fgsmobileidentity.imeisv.digittac06 = getImeisvDigit(Mod_id,i++); - mm_msg->fgs_security_mode_complete.fgsmobileidentity.imeisv.digittac07 = getImeisvDigit(Mod_id,i++); - mm_msg->fgs_security_mode_complete.fgsmobileidentity.imeisv.digittac08 = getImeisvDigit(Mod_id,i++); - mm_msg->fgs_security_mode_complete.fgsmobileidentity.imeisv.digit09 = getImeisvDigit(Mod_id,i++); - mm_msg->fgs_security_mode_complete.fgsmobileidentity.imeisv.digit10 = getImeisvDigit(Mod_id,i++); - mm_msg->fgs_security_mode_complete.fgsmobileidentity.imeisv.digit11 = getImeisvDigit(Mod_id,i++); - mm_msg->fgs_security_mode_complete.fgsmobileidentity.imeisv.digit12 = getImeisvDigit(Mod_id,i++); - mm_msg->fgs_security_mode_complete.fgsmobileidentity.imeisv.digit13 = getImeisvDigit(Mod_id,i++); - mm_msg->fgs_security_mode_complete.fgsmobileidentity.imeisv.digit14 = getImeisvDigit(Mod_id,i++); - mm_msg->fgs_security_mode_complete.fgsmobileidentity.imeisv.digitsv1 = getImeisvDigit(Mod_id,i++); - mm_msg->fgs_security_mode_complete.fgsmobileidentity.imeisv.digitsv2 = getImeisvDigit(Mod_id,i++); - mm_msg->fgs_security_mode_complete.fgsmobileidentity.imeisv.spare = 0x0f; - mm_msg->fgs_security_mode_complete.fgsmobileidentity.imeisv.oddeven = 1; - return 19; -} - -static void generateSecurityModeComplete(int Mod_id,as_nas_info_t *initialNasMsg) +static void generateSecurityModeComplete(nr_ue_nas_t *nas, as_nas_info_t *initialNasMsg) { int size = sizeof(mm_msg_header_t); fgs_nas_message_t nas_msg; @@ -589,7 +574,7 @@ static void generateSecurityModeComplete(int Mod_id,as_nas_info_t *initialNasMsg mm_msg->fgs_security_mode_complete.messagetype = FGS_SECURITY_MODE_COMPLETE; size += 1; - size += addImeisv(Mod_id, mm_msg); + size += fill_imeisv(&mm_msg->fgs_security_mode_complete.fgsmobileidentity, nas->uicc); mm_msg->fgs_security_mode_complete.fgsnasmessagecontainer.nasmessagecontainercontents.value = registration_request_buf; mm_msg->fgs_security_mode_complete.fgsnasmessagecontainer.nasmessagecontainercontents.length = registration_request_len; @@ -602,9 +587,9 @@ static void generateSecurityModeComplete(int Mod_id,as_nas_info_t *initialNasMsg initialNasMsg->length = security_header_len + mm_msg_encode(mm_msg, (uint8_t*)(initialNasMsg->data+security_header_len), size-security_header_len); - stream_cipher.key = ue_security_key[Mod_id]->knas_int; + stream_cipher.key = nas->security.knas_int; stream_cipher.key_length = 16; - stream_cipher.count = 0; + stream_cipher.count = nas->security.mm_counter++; stream_cipher.bearer = 1; stream_cipher.direction = 0; stream_cipher.message = (unsigned char *)(initialNasMsg->data + 6); @@ -622,7 +607,32 @@ static void generateSecurityModeComplete(int Mod_id,as_nas_info_t *initialNasMsg } } -static void generateRegistrationComplete(int Mod_id, as_nas_info_t *initialNasMsg, SORTransparentContainer *sortransparentcontainer) { +static void decodeRegistrationAccept(uint8_t *buf, int len, nr_ue_nas_t *nas) +{ + registration_accept_msg reg_acc = {0}; + /* it seems there is no 5G corresponding emm_msg_decode() function, so here + * we just jump to the right decision */ + buf += 7; /* skip security header */ + buf += 2; /* skip prot discriminator, security header, half octet */ + AssertFatal(*buf == 0x42, "this is not a NAS Registration Accept\n"); + buf++; + int decoded = decode_registration_accept(®_acc, buf, len); + AssertFatal(decoded > 0, "could not decode registration accept\n"); + if (reg_acc.guti) { + AssertFatal(reg_acc.guti->guti.typeofidentity == FGS_MOBILE_IDENTITY_5G_GUTI, + "registration accept 5GS Mobile Identity is not GUTI, but %d\n", + reg_acc.guti->guti.typeofidentity); + nas->guti = malloc(sizeof(*nas->guti)); + AssertFatal(nas->guti, "out of memory\n"); + *nas->guti = reg_acc.guti->guti; + free(reg_acc.guti); /* no proper memory management for NAS decoded messages */ + } else { + LOG_W(NAS, "no GUTI in registration accept\n"); + } +} + +static void generateRegistrationComplete(nr_ue_nas_t *nas, as_nas_info_t *initialNasMsg, SORTransparentContainer *sortransparentcontainer) +{ //wait send RRCReconfigurationComplete and InitialContextSetupResponse sleep(1); int length = 0; @@ -682,9 +692,9 @@ static void generateRegistrationComplete(int Mod_id, as_nas_info_t *initialNasMs } initialNasMsg->length = length; - stream_cipher.key = ue_security_key[Mod_id]->knas_int; + stream_cipher.key = nas->security.knas_int; stream_cipher.key_length = 16; - stream_cipher.count = 1; + stream_cipher.count = nas->security.mm_counter++; stream_cipher.bearer = 1; stream_cipher.direction = 0; stream_cipher.message = (unsigned char *)(initialNasMsg->data + 6); @@ -715,7 +725,55 @@ void decodeDownlinkNASTransport(as_nas_info_t *initialNasMsg, uint8_t * pdu_buff } } -static void generatePduSessionEstablishRequest(int Mod_id, uicc_t * uicc, as_nas_info_t *initialNasMsg){ +static void generateDeregistrationRequest(nr_ue_nas_t *nas, as_nas_info_t *initialNasMsg, const nas_deregistration_req_t *req) +{ + fgs_nas_message_t nas_msg = {0}; + fgs_nas_message_security_protected_t *sp_msg; + sp_msg = &nas_msg.security_protected; + sp_msg->header.protocol_discriminator = FGS_MOBILITY_MANAGEMENT_MESSAGE; + sp_msg->header.security_header_type = INTEGRITY_PROTECTED_AND_CIPHERED; + sp_msg->header.message_authentication_code = 0; + sp_msg->header.sequence_number = 2; + int size = sizeof(fgs_nas_message_security_header_t); + + fgs_deregistration_request_ue_originating_msg *dereg_req = &sp_msg->plain.mm_msg.fgs_deregistration_request_ue_originating; + dereg_req->protocoldiscriminator = FGS_MOBILITY_MANAGEMENT_MESSAGE; + size += 1; + dereg_req->securityheadertype = INTEGRITY_PROTECTED_AND_CIPHERED_WITH_NEW_SECU_CTX; + size += 1; + dereg_req->messagetype = FGS_DEREGISTRATION_REQUEST_UE_ORIGINATING; + size += 1; + dereg_req->deregistrationtype.switchoff = NORMAL_DEREGISTRATION; + dereg_req->deregistrationtype.reregistration_required = REREGISTRATION_NOT_REQUIRED; + dereg_req->deregistrationtype.access_type = TGPP_ACCESS; + dereg_req->naskeysetidentifier.naskeysetidentifier = 1; + size += 1; + size += fill_guti(&dereg_req->fgsmobileidentity, nas->guti); + + // encode the message + initialNasMsg->data = calloc(size, sizeof(Byte_t)); + int security_header_len = nas_protected_security_header_encode((char *)(initialNasMsg->data), &nas_msg.header, size); + + initialNasMsg->length = security_header_len + mm_msg_encode(&sp_msg->plain.mm_msg, (uint8_t *)(initialNasMsg->data + security_header_len), size - security_header_len); + + nas_stream_cipher_t stream_cipher = { + .key = nas->security.knas_int, + .key_length = 16, + .count = nas->security.mm_counter++, + .bearer = 1, + .direction = 0, + .message = (unsigned char *)(initialNasMsg->data + 6), + .blength = (initialNasMsg->length - 6) << 3, /* length in bits */ + }; + uint8_t mac[4]; + nas_stream_encrypt_eia2(&stream_cipher, mac); + + for(int i = 0; i < 4; i++) + initialNasMsg->data[2 + i] = mac[i]; +} + +static void generatePduSessionEstablishRequest(nr_ue_nas_t *nas, as_nas_info_t *initialNasMsg) +{ //wait send RegistrationComplete usleep(100*150); int size = 0; @@ -766,25 +824,25 @@ static void generatePduSessionEstablishRequest(int Mod_id, uicc_t * uicc, as_nas mm_msg->uplink_nas_transport.pdusessionid = 10; mm_msg->uplink_nas_transport.requesttype = 1; size += 3; - const bool has_nssai_sd = uicc->nssai_sd != 0xffffff; // 0xffffff means "no SD", TS 23.003 + const bool has_nssai_sd = nas->uicc->nssai_sd != 0xffffff; // 0xffffff means "no SD", TS 23.003 const size_t nssai_len = has_nssai_sd ? 4 : 1; mm_msg->uplink_nas_transport.snssai.length = nssai_len; //Fixme: it seems there are a lot of memory errors in this: this value was on the stack, // but pushed in a itti message to another thread // this kind of error seems in many places in 5G NAS mm_msg->uplink_nas_transport.snssai.value = calloc(1, nssai_len); - mm_msg->uplink_nas_transport.snssai.value[0] = uicc->nssai_sst; + mm_msg->uplink_nas_transport.snssai.value[0] = nas->uicc->nssai_sst; if (has_nssai_sd) { - mm_msg->uplink_nas_transport.snssai.value[1] = (uicc->nssai_sd >> 16) & 0xFF; - mm_msg->uplink_nas_transport.snssai.value[2] = (uicc->nssai_sd >> 8) & 0xFF; - mm_msg->uplink_nas_transport.snssai.value[3] = (uicc->nssai_sd) & 0xFF; + mm_msg->uplink_nas_transport.snssai.value[1] = (nas->uicc->nssai_sd >> 16) & 0xFF; + mm_msg->uplink_nas_transport.snssai.value[2] = (nas->uicc->nssai_sd >> 8) & 0xFF; + mm_msg->uplink_nas_transport.snssai.value[3] = (nas->uicc->nssai_sd) & 0xFF; } size += 1 + 1 + nssai_len; - int dnnSize=strlen(uicc->dnnStr); + int dnnSize=strlen(nas->uicc->dnnStr); mm_msg->uplink_nas_transport.dnn.value=calloc(1,dnnSize+1); mm_msg->uplink_nas_transport.dnn.length = dnnSize + 1; mm_msg->uplink_nas_transport.dnn.value[0] = dnnSize; - memcpy(mm_msg->uplink_nas_transport.dnn.value+1,uicc->dnnStr, dnnSize); + memcpy(mm_msg->uplink_nas_transport.dnn.value + 1, nas->uicc->dnnStr, dnnSize); size += (1+1+dnnSize+1); // encode the message @@ -793,9 +851,9 @@ static void generatePduSessionEstablishRequest(int Mod_id, uicc_t * uicc, as_nas initialNasMsg->length = security_header_len + mm_msg_encode(mm_msg, (uint8_t*)(initialNasMsg->data+security_header_len), size-security_header_len); - stream_cipher.key = ue_security_key[Mod_id]->knas_int; + stream_cipher.key = nas->security.knas_int; stream_cipher.key_length = 16; - stream_cipher.count = 0; + stream_cipher.count = nas->security.sm_counter++; stream_cipher.bearer = 1; stream_cipher.direction = 0; stream_cipher.message = (unsigned char *)(initialNasMsg->data + 6); @@ -838,17 +896,27 @@ uint8_t get_msg_type(uint8_t *pdu_buffer, uint32_t length) { return msg_type; } +static void send_nas_uplink_data_req(instance_t instance, const as_nas_info_t *initial_nas_msg) +{ + MessageDef *msg = itti_alloc_new_message(TASK_NAS_NRUE, 0, NAS_UPLINK_DATA_REQ); + ul_info_transfer_req_t *req = &NAS_UPLINK_DATA_REQ(msg); + req->UEid = instance; + req->nasMsg.data = (uint8_t *) initial_nas_msg->data; + req->nasMsg.length = initial_nas_msg->length; + itti_send_msg_to_task(TASK_RRC_NRUE, instance, msg); +} + void *nas_nrue_task(void *args_p) { MessageDef *msg_p; instance_t instance; - unsigned int Mod_id; int result; uint8_t msg_type = 0; uint8_t *pdu_buffer = NULL; - ue_security_key=(ue_sa_security_key_t **)calloc(1,sizeof(ue_sa_security_key_t*)*NB_UE_INST); + nr_ue_nas.uicc = checkUicc(0); + nr_ue_nas_t *nas = get_ue_nas_info(0); itti_mark_task_ready (TASK_NAS_NRUE); while(1) { @@ -857,15 +925,7 @@ void *nas_nrue_task(void *args_p) if (msg_p != NULL) { instance = msg_p->ittiMsgHeader.originInstance; - Mod_id = instance ; - uicc_t *uicc=checkUicc(Mod_id); - LOG_I(NAS, "[UE %d] Received %s\n", Mod_id, ITTI_MSG_NAME(msg_p)); - - if (instance == INSTANCE_DEFAULT) { - printf("%s:%d: FATAL: instance is INSTANCE_DEFAULT, should not happen.\n", - __FILE__, __LINE__); - exit_fun("exit... \n"); - } + AssertFatal(instance == 0, "cannot handle more than one UE!\n"); switch (ITTI_MSG_ID(msg_p)) { case INITIALIZE_MESSAGE: @@ -881,8 +941,8 @@ void *nas_nrue_task(void *args_p) case NAS_CELL_SELECTION_CNF: LOG_I(NAS, - "[UE %d] Received %s: errCode %u, cellID %u, tac %u\n", - Mod_id, + "[UE %ld] Received %s: errCode %u, cellID %u, tac %u\n", + instance, ITTI_MSG_NAME(msg_p), NAS_CELL_SELECTION_CNF(msg_p).errCode, NAS_CELL_SELECTION_CNF(msg_p).cellID, @@ -895,49 +955,40 @@ void *nas_nrue_task(void *args_p) break; case NAS_CELL_SELECTION_IND: - LOG_I(NAS, "[UE %d] Received %s: cellID %u, tac %u\n", Mod_id, ITTI_MSG_NAME(msg_p), NAS_CELL_SELECTION_IND(msg_p).cellID, NAS_CELL_SELECTION_IND(msg_p).tac); + LOG_I(NAS, "[UE %ld] Received %s: cellID %u, tac %u\n", instance, ITTI_MSG_NAME(msg_p), NAS_CELL_SELECTION_IND(msg_p).cellID, NAS_CELL_SELECTION_IND(msg_p).tac); /* TODO not processed by NAS currently */ break; case NAS_PAGING_IND: - LOG_I(NAS, "[UE %d] Received %s: cause %u\n", Mod_id, ITTI_MSG_NAME(msg_p), NAS_PAGING_IND(msg_p).cause); + LOG_I(NAS, "[UE %ld] Received %s: cause %u\n", instance, ITTI_MSG_NAME(msg_p), NAS_PAGING_IND(msg_p).cause); /* TODO not processed by NAS currently */ break; case NAS_CONN_ESTABLI_CNF: { - LOG_I(NAS, "[UE %d] Received %s: errCode %u, length %u\n", Mod_id, ITTI_MSG_NAME(msg_p), NAS_CONN_ESTABLI_CNF(msg_p).errCode, NAS_CONN_ESTABLI_CNF(msg_p).nasMsg.length); + LOG_I(NAS, "[UE %ld] Received %s: errCode %u, length %u\n", instance, ITTI_MSG_NAME(msg_p), NAS_CONN_ESTABLI_CNF(msg_p).errCode, NAS_CONN_ESTABLI_CNF(msg_p).nasMsg.length); pdu_buffer = NAS_CONN_ESTABLI_CNF(msg_p).nasMsg.data; msg_type = get_msg_type(pdu_buffer, NAS_CONN_ESTABLI_CNF(msg_p).nasMsg.length); if (msg_type == REGISTRATION_ACCEPT) { LOG_I(NAS, "[UE] Received REGISTRATION ACCEPT message\n"); + decodeRegistrationAccept(pdu_buffer, NAS_CONN_ESTABLI_CNF(msg_p).nasMsg.length, nas); as_nas_info_t initialNasMsg; memset(&initialNasMsg, 0, sizeof(as_nas_info_t)); - generateRegistrationComplete(Mod_id, &initialNasMsg, NULL); + generateRegistrationComplete(nas, &initialNasMsg, NULL); if (initialNasMsg.length > 0) { - MessageDef *message_p; - message_p = itti_alloc_new_message(TASK_NAS_NRUE, 0, NAS_UPLINK_DATA_REQ); - NAS_UPLINK_DATA_REQ(message_p).UEid = Mod_id; - NAS_UPLINK_DATA_REQ(message_p).nasMsg.data = (uint8_t *)initialNasMsg.data; - NAS_UPLINK_DATA_REQ(message_p).nasMsg.length = initialNasMsg.length; - itti_send_msg_to_task(TASK_RRC_NRUE, instance, message_p); + send_nas_uplink_data_req(instance, &initialNasMsg); LOG_I(NAS, "Send NAS_UPLINK_DATA_REQ message(RegistrationComplete)\n"); } as_nas_info_t pduEstablishMsg; memset(&pduEstablishMsg, 0, sizeof(as_nas_info_t)); - generatePduSessionEstablishRequest(Mod_id, uicc, &pduEstablishMsg); + generatePduSessionEstablishRequest(nas, &pduEstablishMsg); if (pduEstablishMsg.length > 0) { - MessageDef *message_p; - message_p = itti_alloc_new_message(TASK_NAS_NRUE, 0, NAS_UPLINK_DATA_REQ); - NAS_UPLINK_DATA_REQ(message_p).UEid = Mod_id; - NAS_UPLINK_DATA_REQ(message_p).nasMsg.data = (uint8_t *)pduEstablishMsg.data; - NAS_UPLINK_DATA_REQ(message_p).nasMsg.length = pduEstablishMsg.length; - itti_send_msg_to_task(TASK_RRC_NRUE, instance, message_p); + send_nas_uplink_data_req(instance, &pduEstablishMsg); LOG_I(NAS, "Send NAS_UPLINK_DATA_REQ message(PduSessionEstablishRequest)\n"); } } else if (msg_type == FGS_PDU_SESSION_ESTABLISHMENT_ACC) { @@ -948,24 +999,38 @@ void *nas_nrue_task(void *args_p) } case NAS_CONN_RELEASE_IND: - LOG_I(NAS, "[UE %d] Received %s: cause %u\n", Mod_id, ITTI_MSG_NAME (msg_p), + LOG_I(NAS, "[UE %ld] Received %s: cause %u\n", instance, ITTI_MSG_NAME (msg_p), NAS_CONN_RELEASE_IND (msg_p).cause); - + itti_wait_tasks_unblock(); /* will unblock ITTI to stop nr-uesoftmodem */ break; case NAS_UPLINK_DATA_CNF: - LOG_I(NAS, "[UE %d] Received %s: UEid %u, errCode %u\n", Mod_id, ITTI_MSG_NAME (msg_p), + LOG_I(NAS, "[UE %ld] Received %s: UEid %u, errCode %u\n", instance, ITTI_MSG_NAME (msg_p), NAS_UPLINK_DATA_CNF (msg_p).UEid, NAS_UPLINK_DATA_CNF (msg_p).errCode); break; + case NAS_DEREGISTRATION_REQ: { + LOG_I(NAS, "[UE %ld] Received %s\n", instance, ITTI_MSG_NAME(msg_p)); + if (nas->guti) { + nas_deregistration_req_t *req = &NAS_DEREGISTRATION_REQ(msg_p); + as_nas_info_t initialNasMsg = {0}; + generateDeregistrationRequest(nas, &initialNasMsg, req); + send_nas_uplink_data_req(instance, &initialNasMsg); + } else { + LOG_E(NAS, "no GUTI, cannot trigger deregistration request\n"); + } + } + break; + case NAS_DOWNLINK_DATA_IND: { - LOG_I(NAS, "[UE %d] Received %s: UEid %u, length %u , buffer %p\n", Mod_id, - ITTI_MSG_NAME (msg_p), - Mod_id, - NAS_DOWNLINK_DATA_IND(msg_p).nasMsg.length, - NAS_DOWNLINK_DATA_IND(msg_p).nasMsg.data); + LOG_I(NAS, + "[UE %ld] Received %s: length %u , buffer %p\n", + instance, + ITTI_MSG_NAME(msg_p), + NAS_DOWNLINK_DATA_IND(msg_p).nasMsg.length, + NAS_DOWNLINK_DATA_IND(msg_p).nasMsg.data); as_nas_info_t initialNasMsg={0}; pdu_buffer = NAS_DOWNLINK_DATA_IND(msg_p).nasMsg.data; @@ -974,18 +1039,21 @@ void *nas_nrue_task(void *args_p) switch(msg_type){ case FGS_IDENTITY_REQUEST: - generateIdentityResponse(&initialNasMsg,*(pdu_buffer+3), uicc); + generateIdentityResponse(&initialNasMsg, *(pdu_buffer + 3), nas->uicc); break; case FGS_AUTHENTICATION_REQUEST: - generateAuthenticationResp(Mod_id,&initialNasMsg, pdu_buffer, uicc); + generateAuthenticationResp(nas, &initialNasMsg, pdu_buffer); break; case FGS_SECURITY_MODE_COMMAND: - nas_itti_kgnb_refresh_req(ue_security_key[Mod_id]->kgnb, instance); - generateSecurityModeComplete(Mod_id,&initialNasMsg); + nas_itti_kgnb_refresh_req(nas->security.kgnb); + generateSecurityModeComplete(nas, &initialNasMsg); break; case FGS_DOWNLINK_NAS_TRANSPORT: decodeDownlinkNASTransport(&initialNasMsg, pdu_buffer); break; + case FGS_DEREGISTRATION_ACCEPT: + LOG_I(NAS, "received deregistration accept\n"); + break; case FGS_PDU_SESSION_ESTABLISHMENT_ACC: { uint8_t offset = 0; @@ -1017,25 +1085,17 @@ void *nas_nrue_task(void *args_p) } break; default: - LOG_W(NR_RRC,"unknow message type %d\n",msg_type); + LOG_W(NR_RRC,"unknown message type %d\n",msg_type); break; } - if(initialNasMsg.length > 0){ - MessageDef *message_p; - message_p = itti_alloc_new_message(TASK_NAS_NRUE, 0, NAS_UPLINK_DATA_REQ); - NAS_UPLINK_DATA_REQ(message_p).UEid = Mod_id; - NAS_UPLINK_DATA_REQ(message_p).nasMsg.data = (uint8_t *)initialNasMsg.data; - - NAS_UPLINK_DATA_REQ(message_p).nasMsg.length = initialNasMsg.length; - itti_send_msg_to_task(TASK_RRC_NRUE, instance, message_p); - LOG_I(NAS, "Send NAS_UPLINK_DATA_REQ message\n"); + if (initialNasMsg.length > 0) + send_nas_uplink_data_req(instance, &initialNasMsg); } - } break; default: - LOG_E(NAS, "[UE %d] Received unexpected message %s\n", Mod_id, ITTI_MSG_NAME (msg_p)); + LOG_E(NAS, "[UE %ld] Received unexpected message %s\n", instance, ITTI_MSG_NAME (msg_p)); break; } diff --git a/openair3/NAS/NR_UE/nr_nas_msg_sim.h b/openair3/NAS/NR_UE/nr_nas_msg_sim.h index abdc5b2e75..fbf0362949 100644 --- a/openair3/NAS/NR_UE/nr_nas_msg_sim.h +++ b/openair3/NAS/NR_UE/nr_nas_msg_sim.h @@ -36,9 +36,11 @@ #include "FGSIdentityResponse.h" #include "FGSAuthenticationResponse.h" #include "FGSNASSecurityModeComplete.h" +#include "FGSDeregistrationRequestUEOriginating.h" #include "RegistrationComplete.h" #include "as_message.h" #include "FGSUplinkNasTransport.h" +#include #define PLAIN_5GS_MSG 0b0000 #define INTEGRITY_PROTECTED 0b0001 @@ -49,6 +51,8 @@ #define REGISTRATION_REQUEST 0b01000001 /* 65 = 0x41 */ #define REGISTRATION_ACCEPT 0b01000010 /* 66 = 0x42 */ #define REGISTRATION_COMPLETE 0b01000011 /* 67 = 0x43 */ +#define FGS_DEREGISTRATION_REQUEST_UE_ORIGINATING 0b01000101 +#define FGS_DEREGISTRATION_ACCEPT 0b01000110 #define FGS_AUTHENTICATION_REQUEST 0b01010110 /* 86 = 0x56 */ #define FGS_AUTHENTICATION_RESPONSE 0b01010111 /* 87 = 0x57 */ #define FGS_IDENTITY_REQUEST 0b01011011 /* 91 = 0x5b */ @@ -78,8 +82,16 @@ typedef struct { uint8_t res[16]; uint8_t rand[16]; uint8_t kgnb[32]; + uint32_t mm_counter; + uint32_t sm_counter; } ue_sa_security_key_t; +typedef struct { + uicc_t *uicc; + ue_sa_security_key_t security; + Guti5GSMobileIdentity_t *guti; +} nr_ue_nas_t; + typedef enum fgs_protocol_discriminator_e { /* Protocol discriminator identifier for 5GS Mobility Management */ FGS_MOBILITY_MANAGEMENT_MESSAGE = 0x7E, @@ -108,6 +120,7 @@ typedef union { registration_request_msg registration_request; fgs_identiy_response_msg fgs_identity_response; fgs_authentication_response_msg fgs_auth_response; + fgs_deregistration_request_ue_originating_msg fgs_deregistration_request_ue_originating; fgs_security_mode_complete_msg fgs_security_mode_complete; registration_complete_msg registration_complete; fgs_uplink_nas_transport_msg uplink_nas_transport; @@ -158,7 +171,8 @@ typedef struct { fgs_sm_nas_msg_header_t sm_nas_msg_header; } dl_nas_transport_t; -void generateRegistrationRequest(as_nas_info_t *initialNasMsg, int Mod_id); +nr_ue_nas_t *get_ue_nas_info(module_id_t module_id); +void generateRegistrationRequest(as_nas_info_t *initialNasMsg, nr_ue_nas_t *nas); void *nas_nrue_task(void *args_p); #endif /* __NR_NAS_MSG_SIM_H__*/ diff --git a/openair3/UICC/usim_interface.c b/openair3/UICC/usim_interface.c index 51a50fc8b8..fe91ff7d8d 100644 --- a/openair3/UICC/usim_interface.c +++ b/openair3/UICC/usim_interface.c @@ -116,9 +116,8 @@ uicc_t * checkUicc(int Mod_id) { return (uicc_t*) uiccArray[Mod_id]; } -uint8_t getImeisvDigit(int Mod_id,uint8_t i) +uint8_t getImeisvDigit(const uicc_t *uicc, uint8_t i) { - uicc_t * uicc=checkUicc(Mod_id); uint8_t r = 0; uint8_t l = strlen(uicc->imeisvStr); if (l > IMEISV_STR_MAX_LENGTH) { diff --git a/openair3/UICC/usim_interface.h b/openair3/UICC/usim_interface.h index 4c779f5a7f..1a275db887 100644 --- a/openair3/UICC/usim_interface.h +++ b/openair3/UICC/usim_interface.h @@ -73,6 +73,5 @@ typedef struct { uicc_t *checkUicc(int Mod_id); uicc_t *init_uicc(char *sectionName); void uicc_milenage_generate(uint8_t * autn, uicc_t *uicc); -uicc_t * checkUicc(int Mod_id); -uint8_t getImeisvDigit(int Mod_id,uint8_t i); +uint8_t getImeisvDigit(const uicc_t *uicc, uint8_t i); #endif diff --git a/openair3/ocp-gtpu/gtp_itf.cpp b/openair3/ocp-gtpu/gtp_itf.cpp index 2f60d5238c..d8e1dc2314 100644 --- a/openair3/ocp-gtpu/gtp_itf.cpp +++ b/openair3/ocp-gtpu/gtp_itf.cpp @@ -17,6 +17,7 @@ extern "C" { #include #include #include +#include #include #include "openair2/SDAP/nr_sdap/nr_sdap.h" #include "sim.h" @@ -647,7 +648,9 @@ teid_t newGtpuCreateTunnel(instance_t instance, int gtpv1u_create_s1u_tunnel(instance_t instance, const gtpv1u_enb_create_tunnel_req_t *create_tunnel_req, - gtpv1u_enb_create_tunnel_resp_t *create_tunnel_resp) { + gtpv1u_enb_create_tunnel_resp_t *create_tunnel_resp, + gtpCallback callBack) +{ LOG_D(GTPU, "[%ld] Start create tunnels for UE ID %u, num_tunnels %d, sgw_S1u_teid %x\n", instance, create_tunnel_req->rnti, @@ -674,7 +677,7 @@ int gtpv1u_create_s1u_tunnel(instance_t instance, -1, // no pdu session in 4G create_tunnel_req->sgw_addr[i], dstport, - pdcp_data_req, + callBack, NULL); create_tunnel_resp->status=0; create_tunnel_resp->rnti=create_tunnel_req->rnti; @@ -711,10 +714,10 @@ int gtpv1u_update_s1u_tunnel( auto it=inst->ue2te_mapping.find(prior_rnti); if ( it != inst->ue2te_mapping.end() ) { - LOG_W(GTPU,"[%ld] Update a not existing tunnel, start create the new one (new ue id %u, old ue id %u)\n", instance, create_tunnel_req->rnti, prior_rnti); pthread_mutex_unlock(&globGtp.gtp_lock); - gtpv1u_enb_create_tunnel_resp_t tmp; - (void)gtpv1u_create_s1u_tunnel(instance, create_tunnel_req, &tmp); + AssertFatal(false, "logic bug: update of non-existing tunnel (new ue id %u, old ue id %u)\n", create_tunnel_req->rnti, prior_rnti); + /* we don't know if we need 4G or 5G PDCP and can therefore not create a + * new tunnel */ return 0; } @@ -724,9 +727,12 @@ int gtpv1u_update_s1u_tunnel( return 0; } -int gtpv1u_create_ngu_tunnel( const instance_t instance, - const gtpv1u_gnb_create_tunnel_req_t *const create_tunnel_req, - gtpv1u_gnb_create_tunnel_resp_t *const create_tunnel_resp) { +int gtpv1u_create_ngu_tunnel(const instance_t instance, + const gtpv1u_gnb_create_tunnel_req_t *const create_tunnel_req, + gtpv1u_gnb_create_tunnel_resp_t *const create_tunnel_resp, + gtpCallback callBack, + gtpCallbackSDAP callBackSDAP) +{ LOG_D(GTPU, "[%ld] Start create tunnels for ue id %lu, num_tunnels %d, sgw_S1u_teid %x\n", instance, create_tunnel_req->ue_id, @@ -748,8 +754,8 @@ int gtpv1u_create_ngu_tunnel( const instance_t instance, create_tunnel_req->outgoing_qfi[i], create_tunnel_req->dst_addr[i], dstport, - pdcp_data_req, - sdap_data_req); + callBack, + callBackSDAP); create_tunnel_resp->status=0; create_tunnel_resp->ue_id=create_tunnel_req->ue_id; create_tunnel_resp->num_tunnels=create_tunnel_req->num_tunnels; diff --git a/openair3/ocp-gtpu/gtp_itf.h b/openair3/ocp-gtpu/gtp_itf.h index 8729be9fa5..9592070ca9 100644 --- a/openair3/ocp-gtpu/gtp_itf.h +++ b/openair3/ocp-gtpu/gtp_itf.h @@ -51,8 +51,10 @@ extern "C" { // the parameter originInstance will be sent back in each message from gtp to the creator void gtpv1uReceiver(int h); void gtpv1uProcessTimeout(int handle,void *arg); - int gtpv1u_create_s1u_tunnel(const instance_t instance, const gtpv1u_enb_create_tunnel_req_t *create_tunnel_req, - gtpv1u_enb_create_tunnel_resp_t *create_tunnel_resp); + int gtpv1u_create_s1u_tunnel(const instance_t instance, + const gtpv1u_enb_create_tunnel_req_t *create_tunnel_req, + gtpv1u_enb_create_tunnel_resp_t *create_tunnel_resp, + gtpCallback callBack); int gtpv1u_update_s1u_tunnel(const instance_t instanceP, const gtpv1u_enb_create_tunnel_req_t *create_tunnel_req_pP, const rnti_t prior_rnti @@ -66,12 +68,12 @@ extern "C" { int gtpv1u_delete_x2u_tunnel( const instance_t instanceP, const gtpv1u_enb_delete_tunnel_req_t *const req_pP); - int - gtpv1u_create_ngu_tunnel( - const instance_t instanceP, - const gtpv1u_gnb_create_tunnel_req_t *const create_tunnel_req_pP, - gtpv1u_gnb_create_tunnel_resp_t *const create_tunnel_resp_pP); - + int gtpv1u_create_ngu_tunnel(const instance_t instanceP, + const gtpv1u_gnb_create_tunnel_req_t *const create_tunnel_req_pP, + gtpv1u_gnb_create_tunnel_resp_t *const create_tunnel_resp_pP, + gtpCallback callBack, + gtpCallbackSDAP callBackSDAP); + int gtpv1u_delete_ngu_tunnel( const instance_t instance, gtpv1u_gnb_delete_tunnel_req_t *req); diff --git a/radio/AW2SORI/oaiori.c b/radio/AW2SORI/oaiori.c index 43d24b40c5..b9368bb22b 100644 --- a/radio/AW2SORI/oaiori.c +++ b/radio/AW2SORI/oaiori.c @@ -22,7 +22,6 @@ #include #include #include -#include #include #include "common_lib.h" diff --git a/radio/USRP/README.md b/radio/USRP/README.md index 131be06436..b89cabe649 100644 --- a/radio/USRP/README.md +++ b/radio/USRP/README.md @@ -4,33 +4,46 @@ OAI works with the most common USRP models like, B200, B200mini, B210, X310, N30 The USRP can be configured in the RU section of the config file. The field "sdr_addrs" uses the same syntax as the USRP device identification string (https://files.ettus.com/manual/page_identification.html). Here are a few examples +```bash sdr_addrs = "addr=192.168.10.2" # uses a single 10Gb Ethernet interface on an N3x0 or X3x0 or X4x0 + sdr_addrs = "addr=192.168.10.2,second_addr=192.168.20.2" # uses 2 10Gb Ethernet interfaces on a N3x0 or X3x0 or X4x0 (requires that you flashed the FPGA wth the XG image) +``` you can also use the multi USRP feature and specify multiple USRPs, in which case you will get the aggregated number of channels on all the devices +```bash sdr_addrs = "addr0=192.168.10.2,addr1=192.168.30.2" +``` You can specify if you want to use external or interal clock or time source either by adding the parameters in the sdr_addrs field or by using the fields clock_src or time_src +```bash sdr_addrs = "addr=192.168.10.2,clock_source=external,time_source=external" +``` is equivalent to +```bash sdr_addrs = "addr=192.168.10.2" clock_src = "external" time_src = "external" +``` -Valid choices for clock and time source are "internal", "external", and "gpsdo" +Valid choices for clock and time source are "internal", "external", and "gpsdo". -Careful: the USRP remembers the choice of the clock source. If you want to make sure it uses always the same, always specify the clock_source and time_source. +Note 1: the USRP remembers the choice of the clock source. If you want to make sure it uses always the same, always specify the clock_source and time_source. + +Note 2: when using multiple USRPs they always have to be synchronized using "external" or "gpsdo" Last but not least you may specify that only a specfic subdevice of the USRP is used. See also https://files.ettus.com/manual/page_configuration.html#config_subdev For example on a USRP N310 the following fields will specify that you use channel 0 of subdevice A. +```bash tx_subdev = "A:0" rx_subdev = "A:0" +``` -When combining this with the multi USRP feature you can easily create a distributed antenna array with only 1 channel used at each USRP. \ No newline at end of file +When combining this with the multi USRP feature you can easily create a distributed antenna array with only 1 channel used at each USRP.