diff --git a/.clang-format b/.clang-format index a7248821a9..3b0be979ba 100644 --- a/.clang-format +++ b/.clang-format @@ -62,6 +62,7 @@ ForEachMacros: - BOOST_FOREACH - RB_FOREACH - UE_iterator + - FOR_EACH_SEQ_ARR IncludeBlocks: Preserve IncludeCategories: - Regex: '^' diff --git a/CMakeLists.txt b/CMakeLists.txt index 57d165ea05..8f8a6006bf 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -652,7 +652,6 @@ add_library(SCHED_LIB ${SCHED_SRC}) target_link_libraries(SCHED_LIB PRIVATE asn1_lte_rrc_hdrs) set(SCHED_NR_SRC - ${OPENAIR1_DIR}/SCHED_NR/fapi_nr_l1.c ${OPENAIR1_DIR}/SCHED_NR/phy_procedures_nr_gNB.c ${OPENAIR1_DIR}/SCHED_NR/nr_prach_procedures.c ${OPENAIR1_DIR}/SCHED_NR/phy_frame_config_nr.c @@ -939,7 +938,6 @@ set(PHY_SRC_UE ${OPENAIR1_DIR}/PHY/NR_TRANSPORT/nr_dci.c ${OPENAIR1_DIR}/PHY/NR_TRANSPORT/nr_dci_tools.c ${OPENAIR1_DIR}/PHY/NR_TRANSPORT/nr_dlsch.c - ${OPENAIR1_DIR}/PHY/NR_TRANSPORT/nr_dlsch_tools.c ${OPENAIR1_DIR}/PHY/NR_TRANSPORT/nr_dlsch_coding.c ${OPENAIR1_DIR}/PHY/NR_TRANSPORT/nr_ulsch_decoding.c ${OPENAIR1_DIR}/PHY/NR_TRANSPORT/nr_ulsch.c @@ -1215,7 +1213,6 @@ 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 @@ -1283,12 +1280,6 @@ set (MISC_NFAPI_LTE add_library(MISC_NFAPI_LTE_LIB ${MISC_NFAPI_LTE}) -set (MISC_NFAPI_NR - ${OPENAIR1_DIR}/SCHED/nfapi_nr_dummy.c - ) - -add_library(MISC_NFAPI_NR_LIB ${MISC_NFAPI_NR}) - add_library(L2 ${L2_SRC} ${MAC_SRC} @@ -2091,7 +2082,7 @@ if (${T_TRACER}) oai_eth_transpro HASHTABLE UTIL SECURITY SCHED_LIB SCHED_NR_LIB SCHED_RU_LIB SCHED_UE_LIB SCHED_NR_UE_LIB NFAPI_LIB NFAPI_PNF_LIB NFAPI_VNF_LIB NFAPI_USER_LIB - MISC_NFAPI_LTE_LIB MISC_NFAPI_NR_LIB + MISC_NFAPI_LTE_LIB PHY_COMMON PHY PHY_UE PHY_NR PHY_NR_COMMON PHY_NR_UE PHY_RU L2 L2_LTE L2_NR L2_LTE_NR L2_UE NR_L2_UE MAC_NR_COMMON MAC_UE_NR ngap GTPV1U SCTP_CLIENT MME_APP LIB_NAS_UE SIMU diff --git a/ci-scripts/cls_containerize.py b/ci-scripts/cls_containerize.py index 3cebcb24d7..cd07851319 100644 --- a/ci-scripts/cls_containerize.py +++ b/ci-scripts/cls_containerize.py @@ -47,6 +47,7 @@ import helpreadme as HELP import constants as CONST import cls_oaicitest from cls_ci_helper import archiveArtifact +from collections import deque #----------------------------------------------------------- # Helper functions used here and in other classes @@ -165,25 +166,26 @@ def CopyinServiceLog(ssh, lSourcePath, svcName, wd_yaml, ctx): ssh.run(f'docker compose -f {wd_yaml} logs {svcName} --no-log-prefix &> {remote_filename}') return archiveArtifact(ssh, ctx, remote_filename) -def GetRunningServices(ssh, file): +def GetDeployedServices(ssh, file): ret = ssh.run(f'docker compose -f {file} config --services') if ret.returncode != 0: + logging.error("could not get services") return None allServices = ret.stdout.splitlines() - running_services = [] + deployed_services = [] for s in allServices: - # outputs the hash if the container is running - ret = ssh.run(f'docker compose -f {file} ps --all --quiet -- {s}') + # outputs the hash if the container has been deployed (but might be stopped) + ret = ssh.run(f'docker compose -f {file} ps --all --quiet -- {s}', silent=True) if ret.returncode != 0: - logging.info(f"service {s}: {ret.stdout}") + # error: should not happen as we iterate over docker-provided service list + logging.error(f"service {s}: {ret.stdout}") elif ret.stdout == "": - logging.warning(f"could not retrieve information for service {s}") + logging.info(f"service {s} not deployed") else: c = ret.stdout - logging.debug(f'running service {s} with container id {c}') - running_services.append((s, c)) - logging.info(f'stopping services: {running_services}') - return running_services + logging.info(f'service {s} with container id {c}') + deployed_services.append(s) + return deployed_services def CheckLogs(self, filename, HTML, RAN): success = True @@ -215,6 +217,24 @@ def CheckLogs(self, filename, HTML, RAN): else: HTML.CreateHtmlTestRowQueue(opt, 'OK', [HTML.htmleNBFailureMsg]) HTML.htmleNBFailureMsg = "" + elif 'xapp' in name: + opt = f"Undeploy {name}" + with open(f'{filename}', "r") as f: + last_line = deque(f, maxlen=1).pop() + if ('Test xApp run SUCCESSFULLY' in last_line): + HTML.CreateHtmlTestRowQueue(opt, 'OK', ["xApp run successfully"]) + else: + HTML.CreateHtmlTestRowQueue(opt, 'KO', ["xApp didn't run successfully"]) + success = False + elif 'RIC' in name: + opt = f"Undeploy {name}" + with open(f'{filename}', 'r') as f: + last_line = deque(f, maxlen=1).pop() + if ('Removing E2 Node' in last_line): + HTML.CreateHtmlTestRowQueue(opt, 'OK', ["nearRT-RIC run successfully"]) + else: + HTML.CreateHtmlTestRowQueue(opt, 'KO', ["nearRT-RIC didn't run successfully"]) + success = False else: logging.info(f"Skipping analysis of log '{filename}': no submatch for xNB/UE") logging.debug(f"log check: file {filename} passed analysis {success}") @@ -715,7 +735,6 @@ class Containerize(): def DeployObject(self, ctx, node, HTML): num_attempts = self.num_attempts lSourcePath = self.eNBSourceCodePath - logging.debug(f'Deploying OAI Object on server: {node}') yaml = self.yamlPath.strip('/') wd = f'{lSourcePath}/{yaml}' wd_yaml = f'{wd}/docker-compose.y*ml' @@ -726,6 +745,7 @@ class Containerize(): logging.error(msg) HTML.CreateHtmlTestRowQueue('N/A', 'KO', [msg]) return False + logging.info(f'\u001B[1mDeploying object(s) "{services}" on server {node}\u001B[0m') ExistEnvFilePrint(ssh, wd) WriteEnvFile(ssh, services, wd, self.deploymentTag, self.flexricTag) if num_attempts <= 0: @@ -750,36 +770,68 @@ class Containerize(): imagesInfo = info.stdout.splitlines()[1:] logging.debug(f'{info.stdout.splitlines()[1:]}') if deployed: - HTML.CreateHtmlTestRowQueue('N/A', 'OK', ['\n'.join(imagesInfo)]) + HTML.CreateHtmlTestRowQueue(self.services, 'OK', ['\n'.join(imagesInfo)]) + logging.info('\u001B[1m Deploying objects Pass\u001B[0m') else: - HTML.CreateHtmlTestRowQueue('N/A', 'KO', ['\n'.join(imagesInfo)]) + HTML.CreateHtmlTestRowQueue(self.services, 'KO', ['\n'.join(imagesInfo)]) + logging.error('\u001B[1m Deploying objects Failed\u001B[0m') return deployed + def StopObject(self, ctx, node, HTML): + lSourcePath = self.eNBSourceCodePath + if not self.services: + raise ValueError(f'no services provided') + logging.info(f'\u001B[1m Stopping objects "{self.services}" from server: {node}\u001B[0m') + reqServices = self.services.split() + yaml = self.yamlPath.strip('/') + wd = f'{lSourcePath}/{yaml}' + wd_yaml = f'{wd}/docker-compose.y*ml' + with cls_cmd.getConnection(node) as ssh: + ExistEnvFilePrint(ssh, wd) + services = GetDeployedServices(ssh, wd_yaml) + success = [] + fail = [] + for s in reqServices: + if s in services: + ssh.run(f'docker compose -f {wd_yaml} stop -- {s}') + success.append(s) + else: + logging.error(f"no such service {s}") + fail.append(s) + if success == reqServices: + logging.info('\u001B[1m Stopping object Pass\u001B[0m') + HTML.CreateHtmlTestRowQueue(self.services, 'OK', [f'Stopped {self.services}']) + else: + logging.error('\u001B[1m Stopping object Failed\u001B[0m') + HTML.CreateHtmlTestRowQueue(self.services, 'KO', [f'Failed stopping {" ".join(fail)}, succeeded {" ".join(success)}']) + return success + def UndeployObject(self, ctx, node, HTML, RAN): lSourcePath = self.eNBSourceCodePath - logging.debug(f'\u001B[1m Undeploying OAI Object from server: {node}\u001B[0m') + logging.info(f'\u001B[1m Undeploying all objects from server {node}\u001B[0m') yaml = self.yamlPath.strip('/') wd = f'{lSourcePath}/{yaml}' + wd_yaml = f'{wd}/docker-compose.y*ml' with cls_cmd.getConnection(node) as ssh: ExistEnvFilePrint(ssh, wd) - services = GetRunningServices(ssh, f"{wd}/docker-compose.y*ml") + services = GetDeployedServices(ssh, wd_yaml) copyin_res = None + ssh.run(f'docker compose -f {wd_yaml} stop') if services is not None: - all_serv = " ".join([s for s, _ in services]) - ssh.run(f'docker compose -f {wd}/docker-compose.y*ml stop -- {all_serv}') - copyin_res = [CopyinServiceLog(ssh, lSourcePath, s, f"{wd}/docker-compose.y*ml", ctx) for s, _ in services] + copyin_res = [CopyinServiceLog(ssh, lSourcePath, s, wd_yaml, ctx) for s in services] else: logging.warning('could not identify services to stop => no log file') - ssh.run(f'docker compose -f {wd}/docker-compose.y*ml down -v') + ssh.run(f'docker compose -f {wd_yaml} down -v') ssh.run(f'rm {wd}/.env') if not copyin_res: HTML.CreateHtmlTestRowQueue('N/A', 'KO', ['Could not copy logfile(s)']) - return False + logging.error(f"could not copy all files: {copyin_res=} {services=}") + success = False else: log_results = [CheckLogs(self, f, HTML, RAN) for f in copyin_res] success = all(log_results) if success: - logging.info('\u001B[1m Undeploying OAI Object Pass\u001B[0m') + logging.info('\u001B[1m Undeploying objects Pass\u001B[0m') else: - logging.error('\u001B[1m Undeploying OAI Object Failed\u001B[0m') + logging.error('\u001B[1m Undeploying objects Failed\u001B[0m') return success diff --git a/ci-scripts/conf_files/gnb-vnf.sa.band78.273prb.aerial.conf b/ci-scripts/conf_files/gnb-vnf.sa.band78.273prb.aerial.conf index f26891d8f2..9446d08ebf 100644 --- a/ci-scripts/conf_files/gnb-vnf.sa.band78.273prb.aerial.conf +++ b/ci-scripts/conf_files/gnb-vnf.sa.band78.273prb.aerial.conf @@ -32,7 +32,7 @@ gNBs = pdsch_AntennaPorts_N1 = 2; pusch_AntennaPorts = 2; do_CSIRS = 1; - do_SRS = 0; + do_SRS = 1; min_rxtxtime = 2; servingCellConfigCommon = ( @@ -155,7 +155,7 @@ gNBs = nrofUplinkSlots = 3; #1; nrofUplinkSymbols = 0; - ssPBCH_BlockPower = -25; + ssPBCH_BlockPower = -15; } ); @@ -195,7 +195,7 @@ MACRLCs = ( remote_s_portd = 50010; // pnf p7 port [!] tr_s_preference = "aerial"; tr_n_preference = "local_RRC"; - pusch_TargetSNRx10 = 200; # 150; + pusch_TargetSNRx10 = 280; # 150; pucch_TargetSNRx10 = 200; #200; dl_max_mcs = 28; ul_max_mcs = 28; diff --git a/ci-scripts/conf_files/gnb-vnf.sa.band78.273prb.aerial.ul-heavy.conf b/ci-scripts/conf_files/gnb-vnf.sa.band78.273prb.aerial.ul-heavy.conf index 90662226ed..43207d63ec 100644 --- a/ci-scripts/conf_files/gnb-vnf.sa.band78.273prb.aerial.ul-heavy.conf +++ b/ci-scripts/conf_files/gnb-vnf.sa.band78.273prb.aerial.ul-heavy.conf @@ -24,9 +24,9 @@ gNBs = pdsch_AntennaPorts_N1 = 2; pusch_AntennaPorts = 2; do_CSIRS = 1; - do_SRS = 0; + do_SRS = 1; min_rxtxtime = 2; - + force_UL256qam_off = 1; servingCellConfigCommon = ( { #spCellConfigCommon @@ -187,7 +187,7 @@ MACRLCs = ( remote_s_portd = 50010; // pnf p7 port [!] tr_s_preference = "aerial"; tr_n_preference = "local_RRC"; - pusch_TargetSNRx10 = 220; # 150; + pusch_TargetSNRx10 = 260; # 150; pucch_TargetSNRx10 = 200; #200; dl_max_mcs = 28; ul_max_mcs = 28; diff --git a/ci-scripts/datalog_rt_stats.100.2x2.yaml b/ci-scripts/datalog_rt_stats.100.2x2.yaml index 7c5cb48add..360ba57402 100644 --- a/ci-scripts/datalog_rt_stats.100.2x2.yaml +++ b/ci-scripts/datalog_rt_stats.100.2x2.yaml @@ -15,7 +15,6 @@ Ref : DLSCH encoding : 200.0 L1 Rx processing : 530.0 PUSCH inner-receiver : 360.0 - Schedule Response : 1.0 DL & UL scheduling timing : 17.0 UL Indication : 1.0 Slot Indication : 13.0 @@ -31,7 +30,6 @@ DeviationThreshold : DLSCH encoding : 0.25 L1 Rx processing : 0.25 PUSCH inner-receiver : 0.25 - Schedule Response : 1.00 DL & UL scheduling timing : 0.25 UL Indication : 1.00 Slot Indication : 0.50 diff --git a/ci-scripts/datalog_rt_stats.1x1.60.yaml b/ci-scripts/datalog_rt_stats.1x1.60.yaml index 5e0564977b..b418b74940 100644 --- a/ci-scripts/datalog_rt_stats.1x1.60.yaml +++ b/ci-scripts/datalog_rt_stats.1x1.60.yaml @@ -15,7 +15,6 @@ Ref : DLSCH encoding : 110.0 L1 Rx processing : 345.0 PUSCH inner-receiver : 150.0 - Schedule Response : 1.0 DL & UL scheduling timing : 5.0 UL Indication : 1.0 Slot Indication : 6.0 @@ -31,7 +30,6 @@ DeviationThreshold : DLSCH encoding : 0.25 L1 Rx processing : 0.25 PUSCH inner-receiver : 0.25 - Schedule Response : 1.00 DL & UL scheduling timing : 0.50 UL Indication : 1.00 Slot Indication : 0.50 diff --git a/ci-scripts/datalog_rt_stats.2x2.yaml b/ci-scripts/datalog_rt_stats.2x2.yaml index 7d489c171e..25009bad10 100644 --- a/ci-scripts/datalog_rt_stats.2x2.yaml +++ b/ci-scripts/datalog_rt_stats.2x2.yaml @@ -15,7 +15,6 @@ Ref : DLSCH encoding : 230.0 L1 Rx processing : 175.0 PUSCH inner-receiver : 100.0 - Schedule Response : 3.0 DL & UL scheduling timing : 11.0 UL Indication : 3.0 Slot Indication : 14.0 @@ -28,7 +27,6 @@ DeviationThreshold : DLSCH encoding : 0.25 L1 Rx processing : 0.25 PUSCH inner-receiver : 0.25 - Schedule Response : 1.00 DL & UL scheduling timing : 0.50 UL Indication : 1.00 Slot Indication : 0.25 diff --git a/ci-scripts/datalog_rt_stats.60.2x2.yaml b/ci-scripts/datalog_rt_stats.60.2x2.yaml index 7352136764..6df6fded54 100644 --- a/ci-scripts/datalog_rt_stats.60.2x2.yaml +++ b/ci-scripts/datalog_rt_stats.60.2x2.yaml @@ -15,7 +15,6 @@ Ref : DLSCH encoding : 140.0 L1 Rx processing : 345.0 PUSCH inner-receiver : 155.0 - Schedule Response : 1.0 DL & UL scheduling timing : 8.0 UL Indication : 3.0 Slot Indication : 9.0 @@ -31,7 +30,6 @@ DeviationThreshold : DLSCH encoding : 0.25 L1 Rx processing : 0.25 PUSCH inner-receiver : 0.25 - Schedule Response : 1.00 DL & UL scheduling timing : 0.35 UL Indication : 1.00 Slot Indication : 0.35 diff --git a/ci-scripts/datalog_rt_stats.default.yaml b/ci-scripts/datalog_rt_stats.default.yaml index be3f8b277e..65fd678b0f 100644 --- a/ci-scripts/datalog_rt_stats.default.yaml +++ b/ci-scripts/datalog_rt_stats.default.yaml @@ -15,7 +15,6 @@ Ref : DLSCH encoding : 90.0 L1 Rx processing : 290.0 PUSCH inner-receiver : 115.0 - Schedule Response : 1.0 DL & UL scheduling timing : 4.0 UL Indication : 2.0 Slot Indication : 5.0 @@ -31,7 +30,6 @@ DeviationThreshold : DLSCH encoding : 0.25 L1 Rx processing : 0.25 PUSCH inner-receiver : 0.25 - Schedule Response : 1.00 DL & UL scheduling timing : 0.50 UL Indication : 1.00 Slot Indication : 0.50 diff --git a/ci-scripts/main.py b/ci-scripts/main.py index 2428df83af..8aadad76bb 100644 --- a/ci-scripts/main.py +++ b/ci-scripts/main.py @@ -214,7 +214,7 @@ def ExecuteActionWithParam(action, ctx, node): core_op = getattr(cls_oaicitest.OaiCiTest, action) success = core_op(cn_id, ctx, HTML) - elif action == 'Deploy_Object' or action == 'Undeploy_Object' or action == "Create_Workspace": + elif action == 'Deploy_Object' or action == 'Undeploy_Object' or action == "Create_Workspace" or action == "Stop_Object": CONTAINERS.yamlPath = test.findtext('yaml_path') string_field=test.findtext('d_retx_th') if (string_field is not None): @@ -227,6 +227,8 @@ def ExecuteActionWithParam(action, ctx, node): CONTAINERS.deploymentTag = cls_containerize.CreateTag(CONTAINERS.ranCommitID, CONTAINERS.ranBranch, CONTAINERS.ranAllowMerge) if action == 'Deploy_Object': success = CONTAINERS.DeployObject(ctx, node, HTML) + elif action == 'Stop_Object': + success = CONTAINERS.StopObject(ctx, node, HTML) elif action == 'Undeploy_Object': success = CONTAINERS.UndeployObject(ctx, node, HTML, RAN) elif action == 'Create_Workspace': diff --git a/ci-scripts/tests/deployment.py b/ci-scripts/tests/deployment.py index e7efc707bf..10bd2c843f 100644 --- a/ci-scripts/tests/deployment.py +++ b/ci-scripts/tests/deployment.py @@ -60,6 +60,33 @@ class TestDeploymentMethods(unittest.TestCase): self.assertTrue(deploy) self.assertTrue(undeploy) + def test_stop_services(self): + self.cont.yamlPath = 'tests/simple-undep/' + self.cont.deploymentTag = "noble" + # should deploy both testA and testB + deploy = self.cont.DeployObject(self.ctx, self.node, self.html) + # should fail (no such service) + self.cont.services = "testC" + stopC = self.cont.StopObject(self.ctx, self.node, self.html) + # should stop testA + self.cont.services = "testA" + stopA = self.cont.StopObject(self.ctx, self.node, self.html) + # should (re-)stop testA (no-op) + self.cont.services = "testA" + stopA2 = self.cont.StopObject(self.ctx, self.node, self.html) + # should deploy testB + self.cont.services = "testB" + stopB = self.cont.StopObject(self.ctx, self.node, self.html) + # should not undeploy anything (everything already stopped) + self.cont.services = None + undeployAll = self.cont.UndeployObject(self.ctx, self.node, self.html, self.ran) + self.assertTrue(deploy) + self.assertFalse(stopC) + self.assertTrue(stopA) + self.assertTrue(stopA2) + self.assertTrue(stopB) + self.assertTrue(undeployAll) + def test_deployfails(self): # fails reliably old = self.cont.yamlPath diff --git a/ci-scripts/tests/simple-undep/docker-compose.yml b/ci-scripts/tests/simple-undep/docker-compose.yml new file mode 100644 index 0000000000..6f88826a9a --- /dev/null +++ b/ci-scripts/tests/simple-undep/docker-compose.yml @@ -0,0 +1,23 @@ +services: + testA: + image: ubuntu:${TAG:-jammy} + container_name: test_container_A + cap_drop: + - ALL + entrypoint: /bin/bash -c "sleep infinity" + healthcheck: + test: /bin/bash -c "true" + interval: 1s + timeout: 1s + retries: 1 + testB: + image: ubuntu:${TAG:-jammy} + container_name: test_container_B + cap_drop: + - ALL + entrypoint: /bin/bash -c "sleep infinity" + healthcheck: + test: /bin/bash -c "true" + interval: 1s + timeout: 1s + retries: 1 diff --git a/ci-scripts/xml_class_list.yml b/ci-scripts/xml_class_list.yml index 615454bbea..a20b78fc99 100755 --- a/ci-scripts/xml_class_list.yml +++ b/ci-scripts/xml_class_list.yml @@ -20,6 +20,7 @@ - Build_Image - Build_Run_Tests - Deploy_Object + - Stop_Object - Undeploy_Object - Cppcheck_Analysis - Deploy_Run_OC_PhySim diff --git a/ci-scripts/xml_files/container_5g_flexric_rfsim.xml b/ci-scripts/xml_files/container_5g_flexric_rfsim.xml index 536952a2bc..135eab6b68 100644 --- a/ci-scripts/xml_files/container_5g_flexric_rfsim.xml +++ b/ci-scripts/xml_files/container_5g_flexric_rfsim.xml @@ -42,6 +42,13 @@ 002006 444444 100002 + 100003 + 100004 + 100005 + 100006 + 100007 + 100008 + 100009 100001 222221 222222 @@ -95,10 +102,10 @@ Deploy_Object - Deploy OAI FlexRIC + Deploy OAI nearRT-RIC localhost ci-scripts/yaml_files/5g_rfsimulator_flexric - oai-flexric + nearRT-RIC @@ -151,16 +158,72 @@ + Stop_Object + Stop RC monitoring xApp + localhost + ci-scripts/yaml_files/5g_rfsimulator_flexric + xapp-rc-moni + + + + Stop_Object + Stop KPM monitoring xApp + localhost + ci-scripts/yaml_files/5g_rfsimulator_flexric + xapp-kpm-moni + + + + Stop_Object + Stop KPM monitoring and RC control xApp + localhost + ci-scripts/yaml_files/5g_rfsimulator_flexric + xapp-kpm-rc + + + + Stop_Object + Stop custom SMs monitoring xApp + localhost + ci-scripts/yaml_files/5g_rfsimulator_flexric + xapp-gtp-mac-rlc-pdcp-moni + + + + Stop_Object + Stop OAI UEs + localhost + ci-scripts/yaml_files/5g_rfsimulator_flexric + oai-nr-ue oai-nr-ue2 + + + + Stop_Object + Stop OAI gNB + localhost + ci-scripts/yaml_files/5g_rfsimulator_flexric + oai-gnb + + + + Stop_Object + Stop nearRT-RIC + localhost + ci-scripts/yaml_files/5g_rfsimulator_flexric + nearRT-RIC + + + Undeploy_Object - Undeploy RAN and Flexric + Undeploy RAN and FlexRIC localhost ci-scripts/yaml_files/5g_rfsimulator_flexric true - + Deploy_Object - RC monitoring + Deploy RC monitoring localhost ci-scripts/yaml_files/5g_rfsimulator_flexric xapp-rc-moni @@ -168,7 +231,7 @@ Deploy_Object - KPM monitoring + Deploy KPM monitoring localhost ci-scripts/yaml_files/5g_rfsimulator_flexric xapp-kpm-moni @@ -176,7 +239,7 @@ Deploy_Object - KPM monitoring and RC control + Deploy KPM monitoring and RC control localhost ci-scripts/yaml_files/5g_rfsimulator_flexric xapp-kpm-rc @@ -184,7 +247,7 @@ Deploy_Object - Custom SMs monitoring + Deploy custom SMs monitoring localhost ci-scripts/yaml_files/5g_rfsimulator_flexric xapp-gtp-mac-rlc-pdcp-moni diff --git a/ci-scripts/xml_files/container_5g_rfsim_u0_25prb.xml b/ci-scripts/xml_files/container_5g_rfsim_u0_25prb.xml index d563b3aab4..3bb99de4ab 100644 --- a/ci-scripts/xml_files/container_5g_rfsim_u0_25prb.xml +++ b/ci-scripts/xml_files/container_5g_rfsim_u0_25prb.xml @@ -36,6 +36,11 @@ 020003 030001 030002 + 050001 + 050002 + 050003 + 020001 + 020002 100001 222222 @@ -139,12 +144,32 @@ 90 + + Custom_Command + Trigger PDU Session Release via gNB telnet + acamas + echo ci pdu_session_release 2 | ncat 192.168.71.140 9090 + + + + Custom_Command + Add PDU Session via UE telnet + acamas + echo ci add_pdu_session 6,7 | ncat 192.168.71.150 8091 + + + + Custom_Command + Trigger PDU Session Release via gNB telnet + acamas + echo ci pdu_session_release 6 | ncat 192.168.71.140 9090 + + Undeploy_Object true Undeploy all OAI 5G stack localhost - oai-vnf oai-pnf ci-scripts/yaml_files/5g_rfsimulator_u0_25prb 1,0,0,0 1,0,0,0 diff --git a/ci-scripts/xml_files/container_sa_aerial_quectel.xml b/ci-scripts/xml_files/container_sa_aerial_quectel.xml index 05d35d0171..bf3f702219 100644 --- a/ci-scripts/xml_files/container_sa_aerial_quectel.xml +++ b/ci-scripts/xml_files/container_sa_aerial_quectel.xml @@ -88,8 +88,8 @@ Iperf - iperf (DL/UDP/500M)(30 sec)(single-ue profile) - -u -b 500M -t 30 -R + iperf (DL/UDP/800M)(30 sec)(single-ue profile) + -u -b 800M -t 30 -R oc-cn5g-20897-aerial up2-aerial 25 @@ -98,8 +98,8 @@ Iperf - iperf (UL/UDP/40M)(30 sec)(single-ue profile) - -u -b 40M -t 30 -l 1428 + iperf (UL/UDP/150M)(30 sec)(single-ue profile) + -u -b 150M -t 30 -l 1428 oc-cn5g-20897-aerial up2-aerial 25 @@ -119,9 +119,9 @@ Iperf - Optional iperf (UL/UDP/90M)(30 sec)(single-ue profile) + Optional iperf (UL/UDP/200M)(30 sec)(single-ue profile) true - -u -b 90M -t 30 -l 1428 + -u -b 200M -t 30 -l 1428 oc-cn5g-20897-aerial up2-aerial 25 diff --git a/ci-scripts/xml_files/container_sa_aerial_quectel_ul_heavy.xml b/ci-scripts/xml_files/container_sa_aerial_quectel_ul_heavy.xml index ab38b72295..baf525f167 100644 --- a/ci-scripts/xml_files/container_sa_aerial_quectel_ul_heavy.xml +++ b/ci-scripts/xml_files/container_sa_aerial_quectel_ul_heavy.xml @@ -97,8 +97,8 @@ Iperf - iperf (UL/UDP/200M)(30 sec)(single-ue profile) - -u -b 200M -t 30 -l 1428 + iperf (UL/UDP/300M)(30 sec)(single-ue profile) + -u -b 300M -t 30 -l 1428 oc-cn5g-20897-aerial up2-aerial 10 @@ -107,9 +107,9 @@ Iperf - iperf (UL/UDP/220M)(30 sec)(single-ue profile) + iperf (UL/UDP/380M)(30 sec)(single-ue profile) true - -u -b 220M -t 30 -l 1428 + -u -b 380M -t 30 -l 1428 oc-cn5g-20897-aerial up2-aerial 10 diff --git a/ci-scripts/xml_files/container_sa_n310_2X2_100MHz_quectel.xml b/ci-scripts/xml_files/container_sa_n310_2X2_100MHz_quectel.xml index a4d72398e1..ad98afcd32 100644 --- a/ci-scripts/xml_files/container_sa_n310_2X2_100MHz_quectel.xml +++ b/ci-scripts/xml_files/container_sa_n310_2X2_100MHz_quectel.xml @@ -146,7 +146,6 @@ Undeploy gNB matix ci-scripts/yaml_files/5g_sa_n310_2x2_100MHz - oai-gnb 10,100,100,100 10,100,100,100 diff --git a/ci-scripts/xml_files/container_sa_n310_2X2_60MHz_quectel.xml b/ci-scripts/xml_files/container_sa_n310_2X2_60MHz_quectel.xml index ab7188c023..a809fafa2c 100644 --- a/ci-scripts/xml_files/container_sa_n310_2X2_60MHz_quectel.xml +++ b/ci-scripts/xml_files/container_sa_n310_2X2_60MHz_quectel.xml @@ -146,7 +146,6 @@ Undeploy gNB matix ci-scripts/yaml_files/5g_sa_n310_2x2_60MHz - oai-gnb 15,100,100,100 20,100,100,100 diff --git a/ci-scripts/xml_files/container_sa_n310_4X4_60MHz_quectel.xml b/ci-scripts/xml_files/container_sa_n310_4X4_60MHz_quectel.xml index d7cf992aa4..d4d0d51258 100644 --- a/ci-scripts/xml_files/container_sa_n310_4X4_60MHz_quectel.xml +++ b/ci-scripts/xml_files/container_sa_n310_4X4_60MHz_quectel.xml @@ -146,7 +146,6 @@ Undeploy VNF-PNF matix ci-scripts/yaml_files/5g_sa_n310_4x4_60MHz - oai-vnf oai-pnf 10,100,100,100 10,100,100,100 diff --git a/ci-scripts/yaml_files/5g_rfsimulator_flexric/docker-compose.yml b/ci-scripts/yaml_files/5g_rfsimulator_flexric/docker-compose.yml index 8e1688dff3..5bb8d0246d 100644 --- a/ci-scripts/yaml_files/5g_rfsimulator_flexric/docker-compose.yml +++ b/ci-scripts/yaml_files/5g_rfsimulator_flexric/docker-compose.yml @@ -1,7 +1,7 @@ services: - oai-flexric: + nearRT-RIC: image: ${REGISTRY-oaisoftwarealliance/}oai-flexric:${FLEXRIC_TAG:-develop} - container_name: oai-flexric + container_name: nearRT-RIC networks: public_net: ipv4_address: 192.168.70.150 @@ -17,7 +17,7 @@ services: command: "stdbuf -o0 /usr/local/flexric/xApp/c/monitor/xapp_rc_moni" container_name: xapp-rc-moni depends_on: - - oai-flexric + - nearRT-RIC - oai-gnb networks: public_net: @@ -34,7 +34,7 @@ services: command: "stdbuf -o0 /usr/local/flexric/xApp/c/monitor/xapp_kpm_moni" container_name: xapp-kpm-moni depends_on: - - oai-flexric + - nearRT-RIC - oai-gnb networks: public_net: @@ -51,7 +51,7 @@ services: command: "stdbuf -o0 /usr/local/flexric/xApp/c/kpm_rc/xapp_kpm_rc" container_name: xapp-kpm-rc depends_on: - - oai-flexric + - nearRT-RIC - oai-gnb networks: public_net: @@ -68,7 +68,7 @@ services: command: "stdbuf -o0 /usr/local/flexric/xApp/c/monitor/xapp_gtp_mac_rlc_pdcp_moni" container_name: xapp-gtp-mac-rlc-pdcp-moni depends_on: - - oai-flexric + - nearRT-RIC - oai-gnb networks: public_net: @@ -88,7 +88,7 @@ services: USE_ADDITIONAL_OPTIONS: -E --rfsim --log_config.global_log_options level,nocolor,time ASAN_OPTIONS: detect_leaks=0 depends_on: - - oai-flexric + - nearRT-RIC networks: public_net: ipv4_address: 192.168.70.151 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 722290aa38..c4a4e2ebea 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 @@ -97,8 +97,9 @@ services: - ALL environment: USE_ADDITIONAL_OPTIONS: --nfapi VNF --log_config.global_log_options level,nocolor,time + --telnetsrv --telnetsrv.listenaddr 192.168.71.140 --telnetsrv.shrmod ci NFAPI_TRACE_LEVEL: info - ASAN_OPTIONS: detect_leaks=0 + ASAN_OPTIONS: detect_leaks=0:detect_odr_violation=0 depends_on: - oai-ext-dn networks: @@ -122,7 +123,7 @@ services: environment: USE_ADDITIONAL_OPTIONS: --nfapi PNF --rfsim --log_config.global_log_options level,nocolor,time NFAPI_TRACE_LEVEL: info - ASAN_OPTIONS: detect_leaks=0 + ASAN_OPTIONS: detect_leaks=0:detect_odr_violation=0 depends_on: - oai-vnf networks: @@ -147,7 +148,10 @@ services: - NET_ADMIN # for interface bringup - NET_RAW # for ping environment: - USE_ADDITIONAL_OPTIONS: --rfsim -r 25 --numerology 0 --uicc0.imsi 208990100001100 --band 66 -C 2152680000 --CO -400000000 --ssb 48 --rfsimulator.serveraddr 192.168.71.141 --extra-pdu-id 2 --log_config.global_log_options level,nocolor,time + USE_ADDITIONAL_OPTIONS: --rfsim -r 25 --numerology 0 --uicc0.imsi 208990100001100 --band 66 -C 2152680000 --CO -400000000 --ssb 48 + --rfsimulator.serveraddr 192.168.71.141 --extra-pdu-id 2 --log_config.global_log_options level,nocolor,time + --telnetsrv --telnetsrv.shrmod ciUE --telnetsrv.listenaddr 192.168.71.150 --telnetsrv.listenport 8091 + ASAN_OPTIONS: detect_leaks=0:detect_odr_violation=0 depends_on: - oai-pnf networks: diff --git a/common/utils/LOG/log.c b/common/utils/LOG/log.c index 91c97ac1ac..23aa075ca1 100644 --- a/common/utils/LOG/log.c +++ b/common/utils/LOG/log.c @@ -461,9 +461,15 @@ int register_log_component(const char *name, const char *fext, int compidx) } if (computed_compidx >= 0 && computed_compidx log_component[computed_compidx].name = strdup(name); - g_log->log_component[computed_compidx].stream = stdout; - g_log->log_component[computed_compidx].filelog = 0; + log_component_t *c = &g_log->log_component[computed_compidx]; + c->name = strdup(name); + int n = snprintf(c->headerName, sizeof(c->headerName), "[%s", c->name); + if (n >= sizeof(c->headerName) - 1) // snprintf() truncated + n = sizeof(c->headerName) - 2; + c->headerName[n] = ']'; + c->headerName[n + 1] = 0; + c->stream = stdout; + c->filelog = 0; g_log->log_rarely_used[computed_compidx].filelog_name = calloc(1, strlen(name) + 16); /* /tmp/.%s */ sprintf(g_log->log_rarely_used[computed_compidx].filelog_name, "/tmp/%s.", name); strncat(g_log->log_rarely_used[computed_compidx].filelog_name, fext, 3); @@ -509,12 +515,15 @@ int logInit (void) for (int i = 0; i < MAX_LOG_PREDEF_COMPONENTS; i++) register_log_component(comp_name[i], comp_extension[i], i); - for (int i=0 ; log_level_names[i].name != NULL ; i++) - g_log->level2string[i] = toupper(log_level_names[i].name[0]); // uppercased first letter of level name - g_log->filelog_name = "/tmp/openair.log"; log_getconfig(g_log); + for (int i = 0; log_level_names[i].name != NULL; i++) + if (g_log->flag & FLAG_LEVEL) + snprintf(g_log->level2string[i], sizeof g_log->level2string[i], " %c ", toupper(log_level_names[i].name[0])); + else + snprintf(g_log->level2string[i], sizeof g_log->level2string[i], " "); + // set all unused component items to 0, they are for non predefined components for (int i=MAX_LOG_PREDEF_COMPONENTS; i < MAX_LOG_COMPONENTS; i++) { memset(&(g_log->log_component[i]),0,sizeof(log_component_t)); @@ -575,8 +584,7 @@ static inline int log_header(log_component_t *c, struct tm utc_time; if (gmtime_r(&t.tv_sec, &utc_time) == NULL) abort(); - snprintf(timeString, sizeof(timeString), "%04d-%02d-%02d %02d:%02d:%02d.%06lu UTC ", - utc_time.tm_year + 1900, utc_time.tm_mon + 1, utc_time.tm_mday, + snprintf(timeString, sizeof(timeString), "[%02d:%02d:%02d.%06lu] ", utc_time.tm_hour, utc_time.tm_min, utc_time.tm_sec, t.tv_nsec / 1000); } else { snprintf(timeString, sizeof(timeString), "%lu.%06lu ", @@ -593,15 +601,18 @@ static inline int log_header(log_component_t *c, } else { threadIdString[0] = 0; } - return snprintf(log_buffer, buffsize, "%s%s%s[%s] %c %s%s", - flag & FLAG_NOCOLOR ? "" : log_level_highlight_start[level], - timeString, - threadIdString, - c->name, - flag & FLAG_LEVEL ? g_log->level2string[level] : ' ', - l, - threadname - ); + + return snprintf(log_buffer, + buffsize, + "%s%s%s%-8s%s%-*s%s", + flag & FLAG_NOCOLOR ? "" : log_level_highlight_start[level], + timeString, + threadIdString, + c->headerName, + g_log->level2string[level], // will print space if no level selected + l[0] == 0 ? 0 : 32, + l, + threadname); } void logRecord_mt(const char *file, diff --git a/common/utils/LOG/log.h b/common/utils/LOG/log.h index c873b0d418..312f2c9510 100644 --- a/common/utils/LOG/log.h +++ b/common/utils/LOG/log.h @@ -206,6 +206,7 @@ typedef struct { typedef struct { const char *name; + char headerName[19]; int level; int filelog; FILE *stream; @@ -217,7 +218,7 @@ typedef struct { typedef struct { log_component_t log_component[MAX_LOG_COMPONENTS]; log_component_back_t log_rarely_used[MAX_LOG_COMPONENTS]; - char level2string[NUM_LOG_LEVEL]; + char level2string[NUM_LOG_LEVEL][4]; int flag; char *filelog_name; debug_flags_t debug_mask; diff --git a/common/utils/nr/nr_common.c b/common/utils/nr/nr_common.c index 8e6a16c97d..a842f66443 100644 --- a/common/utils/nr/nr_common.c +++ b/common/utils/nr/nr_common.c @@ -459,12 +459,50 @@ bool compare_relative_ul_channel_bw(int nr_band, int scs, int channel_bandwidth, return rel_bw > limit; } -uint16_t get_band(uint64_t downlink_frequency, int32_t delta_duplex) +static bool check_delta_duplex(int index, uint64_t dlfreq_khz, uint64_t ulfreq_khz, int64_t dlbw, int64_t ulbw) +{ + int uldl_min_offset = nr_bandtable[index].dl_min - nr_bandtable[index].ul_min; + int txrx_offset = dlfreq_khz - ulfreq_khz; + LOG_I(NR_PHY, "dlfreq:%ld ulfreq:%ld deltaduplex:%d khz, uldl_min_offset:%d khz\n", + dlfreq_khz, ulfreq_khz, txrx_offset, uldl_min_offset); + if (txrx_offset == uldl_min_offset) + return true; + + int band = nr_bandtable[index].band; + + // Refer to section 5.4.4 in spec 38.101-5 + if (band == 256 && txrx_offset >= 165000 && txrx_offset <= 215000) + return true; + if (band == 255 && txrx_offset >= -130500 && txrx_offset <= -72500) + return true; + if (band == 254 && txrx_offset >= 862000 && txrx_offset <= 885000) + return true; + + // Refer to section 5.4.4 in spec 38.101-1 for these bands 24, 91-94, 109 + if (band == 24 && (txrx_offset == -101500 || txrx_offset == -120500)) + return true; + //Delta duplex is also a range for these bands n91-n94, n109. + if ((band >= 91 && band <= 94) || band == 109) { + dlbw = ((dlbw / 1000) + 1) * 1000; + ulbw = ((ulbw / 1000) + 1) * 1000; + int lower_limit = nr_bandtable[index].dl_min - nr_bandtable[index].ul_max + ((dlbw + ulbw) >> 1); + int upper_limit = nr_bandtable[index].dl_max - nr_bandtable[index].ul_min - ((dlbw + ulbw) >> 1); + LOG_I(NR_PHY, "Band %d dlbw:%ld Khz, ulbw: %ld Khz RXTX lower limit:%d khz, upper limit:%d khz\n", + band, dlbw, ulbw, lower_limit, upper_limit); + + if (txrx_offset >= lower_limit && txrx_offset <= upper_limit) + return true; + } + + return false; +} + +uint16_t get_band(uint64_t downlink_frequency, int32_t delta_duplex, int64_t dlbw, int64_t ulbw) { const int64_t dl_freq_khz = downlink_frequency / 1000; const int32_t delta_duplex_khz = delta_duplex / 1000; + const int64_t ul_freq_khz = dl_freq_khz + delta_duplex_khz; - uint64_t center_freq_diff_khz = UINT64_MAX; // 2^64 uint16_t current_band = 0; for (int ind = 0; ind < sizeofArray(nr_bandtable); ind++) { @@ -472,17 +510,13 @@ uint16_t get_band(uint64_t downlink_frequency, int32_t delta_duplex) if (dl_freq_khz < nr_bandtable[ind].dl_min || dl_freq_khz > nr_bandtable[ind].dl_max) continue; - int32_t current_offset_khz = nr_bandtable[ind].ul_min - nr_bandtable[ind].dl_min; - - if (current_offset_khz != delta_duplex_khz) + if (ul_freq_khz < nr_bandtable[ind].ul_min || ul_freq_khz > nr_bandtable[ind].ul_max) continue; - int64_t center_frequency_khz = (nr_bandtable[ind].dl_max + nr_bandtable[ind].dl_min) / 2; + if (!check_delta_duplex(ind, dl_freq_khz, ul_freq_khz, dlbw, ulbw)) + continue; - if (labs(dl_freq_khz - center_frequency_khz) < center_freq_diff_khz){ - current_band = nr_bandtable[ind].band; - center_freq_diff_khz = labs(dl_freq_khz - center_frequency_khz); - } + current_band = nr_bandtable[ind].band; } printf("DL frequency %"PRIu64": band %d, UL frequency %"PRIu64"\n", @@ -541,8 +575,8 @@ int cce_to_reg_interleaving(const int R, int k, int n_shift, const int C, int L, return f; } -void get_coreset_rballoc(uint8_t *FreqDomainResource,int *n_rb,int *rb_offset) { - +void get_coreset_rballoc(const uint8_t *FreqDomainResource, int *n_rb, int *rb_offset) +{ uint8_t count=0, start=0, start_set=0; uint64_t bitmap = (((uint64_t)FreqDomainResource[0])<<37)| @@ -565,7 +599,7 @@ void get_coreset_rballoc(uint8_t *FreqDomainResource,int *n_rb,int *rb_offset) { } // According to 38.211 7.3.2.2 -int get_coreset_num_cces(uint8_t *FreqDomainResource, int duration) +int get_coreset_num_cces(const uint8_t *FreqDomainResource, int duration) { int num_rbs; int rb_offset; diff --git a/common/utils/nr/nr_common.h b/common/utils/nr/nr_common.h index e0d68a45ad..52eb305824 100644 --- a/common/utils/nr/nr_common.h +++ b/common/utils/nr/nr_common.h @@ -280,12 +280,12 @@ uint32_t to_nrarfcn(int nr_bandP, uint64_t dl_CarrierFreq, uint8_t scs_index, ui int cce_to_reg_interleaving(const int R, int k, int n_shift, const int C, int L, const int N_regs); int get_SLIV(uint8_t S, uint8_t L); -void get_coreset_rballoc(uint8_t *FreqDomainResource,int *n_rb,int *rb_offset); -int get_coreset_num_cces(uint8_t *FreqDomainResource, int duration); +void get_coreset_rballoc(const uint8_t *FreqDomainResource, int *n_rb, int *rb_offset); +int get_coreset_num_cces(const uint8_t *FreqDomainResource, int duration); int get_nr_table_idx(int nr_bandP, uint8_t scs_index); int32_t get_delta_duplex(int nr_bandP, uint8_t scs_index); frame_type_t get_frame_type(uint16_t nr_bandP, uint8_t scs_index); -uint16_t get_band(uint64_t downlink_frequency, int32_t delta_duplex); +uint16_t get_band(uint64_t downlink_frequency, int32_t delta_duplex, int64_t dlbw, int64_t ulbw); int NRRIV2BW(int locationAndBandwidth,int N_RB); int NRRIV2PRBOFFSET(int locationAndBandwidth,int N_RB); int PRBalloc_to_locationandbandwidth0(int NPRB,int RBstart,int BWPsize); diff --git a/common/utils/telnetsrv/CMakeLists.txt b/common/utils/telnetsrv/CMakeLists.txt index a249596d97..40380c0418 100644 --- a/common/utils/telnetsrv/CMakeLists.txt +++ b/common/utils/telnetsrv/CMakeLists.txt @@ -62,7 +62,7 @@ add_dependencies(telnetsrv telnetsrv_ci) message(STATUS "Add CI specific telnet functions for nrUE in telnetsrv_ciUE.so") add_library(telnetsrv_ciUE MODULE telnetsrv_ciUE.c) -target_link_libraries(telnetsrv_ciUE PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs UTIL) +target_link_libraries(telnetsrv_ciUE PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs UTIL NR_L2_UE nr_nas) add_dependencies(telnetsrv telnetsrv_ciUE) message(STATUS "Add bearer specific telnet functions in libtelnetsrv_bearer.so") diff --git a/common/utils/telnetsrv/telnetsrv_ci.c b/common/utils/telnetsrv/telnetsrv_ci.c index 291f1f37a2..8b00d529c5 100644 --- a/common/utils/telnetsrv/telnetsrv_ci.c +++ b/common/utils/telnetsrv/telnetsrv_ci.c @@ -39,6 +39,7 @@ #include "openair2/LAYER2/nr_rlc/nr_rlc_entity_am.h" #include "openair2/LAYER2/NR_MAC_gNB/mac_proto.h" #include "openair2/RRC/NR/rrc_gNB_mobility.h" +#include "openair3/NGAP/ngap_gNB_ue_context.h" #define TELNETSERVERCODE #include "telnetsrv.h" @@ -284,6 +285,86 @@ static int get_current_bwp(char *buf, int debug, telnet_printfunc_t prnt) return 0; } +/** @brief Trigger NGAP PDU Session Release for one or more PDU sessions associated with a UE ID/ + * Syntax: trigger_pdu_session_release [ue_id=gNB_ue_ngap_id(int,opt)],pdusession_id(int)[,pdusession_id(int)...] + * - If the gNB_ue_ngap_id is omitted, it is fetched from the only UE present in the RRC layer + * - At least one valid PDU session ID must be provided + * @param[in] buf Comma-separated input string: [ue_id=gNB_ue_ngap_id(int,opt)],PDU1[,PDU2,...] + * @param[in] debug Not used. + * @param[in] prnt Callback for telnet output printing. + * @return 0 on success; negative value on error. */ +static int trigger_ngap_pdu_session_release(char *buf, int debug, telnet_printfunc_t prnt) +{ + if (buf == NULL) { + ERROR_MSG_RET("Missing input. Usage: trigger_pdu_session_release [ue_id=gNB_ue_ngap_id(int,opt)],pdusession_id(int)[,pdusession_id(int)...]\n"); + } + + char *tokens[NGAP_MAX_PDU_SESSION + 1]; + int count = 0; + + for (char *tok = strtok(buf, ","); tok != NULL && count < (int)sizeofArray(tokens); tok = strtok(NULL, ",")) { + tokens[count++] = tok; + } + + if (count < 1) { + ERROR_MSG_RET("Invalid input. Usage: trigger_pdu_session_release [ue_id=gNB_ue_ngap_id(int,opt)],pdusession_id(int)[,pdusession_id(int)...]\n"); + } + + int gNB_ue_ngap_id = -1; + int pdu_start_index = 0; + + if (strncmp(tokens[0], "ue_id=", 6) == 0) { + gNB_ue_ngap_id = atoi(tokens[0] + 6); + pdu_start_index = 1; + } else { + // No UE ID: infer it + if (!RC.nrrrc) + ERROR_MSG_RET("No RRC present\n"); + rrc_gNB_ue_context_t *ue = get_single_rrc_ue(); + if (!ue) + ERROR_MSG_RET("No single UE in RRC present\n"); + gNB_ue_ngap_id = ue->ue_context.rrc_ue_id; + } + + if (pdu_start_index >= count) { + ERROR_MSG_RET("No pdusession_id(int) provided\n"); + } + + ngap_gNB_ue_context_t *ngap = ngap_get_ue_context(gNB_ue_ngap_id); + if (!ngap) { + ERROR_MSG_RET("No NGAP UE context for gNB_ue_ngap_id %d\n", gNB_ue_ngap_id); + } + + MessageDef *message_p = itti_alloc_new_message(TASK_NGAP, 0, NGAP_PDUSESSION_RELEASE_COMMAND); + ngap_pdusession_release_command_t *msg = &NGAP_PDUSESSION_RELEASE_COMMAND(message_p); + memset(msg, 0, sizeof(*msg)); + + msg->amf_ue_ngap_id = ngap->amf_ue_ngap_id; + msg->gNB_ue_ngap_id = ngap->gNB_ue_ngap_id; + + int nb_sessions = 0; + for (int i = pdu_start_index; i < count; ++i) { + int sid = atoi(tokens[i]); + if (sid < 1 || sid > 255) { + ERROR_MSG_RET("Invalid pdusession_id(int): %s (must be between 1 and 255)\n", tokens[i]); + } + msg->pdusession_release_params[nb_sessions++].pdusession_id = sid; + } + + msg->nb_pdusessions_torelease = nb_sessions; + + if (prnt) { + prnt("Triggering NGAP PDU Session Release for gNB_ue_ngap_id=%d: releasing pdusession_id=%d", gNB_ue_ngap_id); + for (int i = 0; i < nb_sessions; ++i) { + prnt(" %d,", msg->pdusession_release_params[i].pdusession_id); + } + prnt("\n"); + } + + itti_send_msg_to_task(TASK_RRC_GNB, 0, message_p); + return 0; +} + static telnetshell_cmddef_t cicmds[] = { {"get_single_rnti", "", get_single_rnti}, {"force_reestab", "[rnti(hex,opt)]", trigger_reestab}, @@ -294,6 +375,7 @@ static telnetshell_cmddef_t cicmds[] = { {"fetch_du_by_ue_id", "[rrc_ue_id(int,opt)]", fetch_du_by_ue_id}, {"get_current_bwp", "[rnti(hex,opt)]", get_current_bwp}, {"trigger_n2_ho", "[neighbour_pci(uint32_t),ueId(uint32_t)]", rrc_gNB_trigger_n2_ho}, + {"pdu_session_release", "[gNB_ue_ngap_id(int,opt)]", trigger_ngap_pdu_session_release}, {"", "", NULL}, }; diff --git a/common/utils/telnetsrv/telnetsrv_ciUE.c b/common/utils/telnetsrv/telnetsrv_ciUE.c index 88320a6ce0..6f86f1678f 100644 --- a/common/utils/telnetsrv/telnetsrv_ciUE.c +++ b/common/utils/telnetsrv/telnetsrv_ciUE.c @@ -39,6 +39,7 @@ #include "openair2/RRC/NR_UE/rrc_proto.h" #include "openair1/PHY/phy_extern_nr_ue.h" #include "openair1/PHY/defs_nr_common.h" +#include "openair3/NAS/NR_UE/nr_nas_msg.h" #define TELNETSERVERCODE #include "telnetsrv.h" @@ -52,6 +53,14 @@ const char* NR_UE_L2_STATE_STR[] = { #undef UE_STATE }; +static int get_default_ue_id(void) +{ + NR_UE_RRC_INST_t *rrc = get_NR_UE_rrc_inst(0); + if (!rrc) + return -1; + return rrc->ue_id; +} + /** * Get the synchronization state of a UE. * @@ -132,6 +141,40 @@ static int get_dl_toa(char *buf, int debug, telnet_printfunc_t prnt) return 0; } +static int add_pdu_session(char *buf, int debug, telnet_printfunc_t prnt) +{ + int ue_id = -1; + int pdusession_id = -1; + + if (!buf) { + ERROR_MSG_RET("Missing argument: expected PDUSessionID[,UE_ID]\n"); + } + + // Try parsing values in the form: "PDUSessionID[,UE_ID]" + int n = sscanf(buf, "%d,%d", &pdusession_id, &ue_id); + if (n == 1) { + // Only PDUSessionID provided: use default UE ID + ue_id = get_default_ue_id(); + if (ue_id < 0) + ERROR_MSG_RET("No default UE context found\n"); + } else if (n != 2) { + ERROR_MSG_RET("Invalid format: expected PDUSessionID[,UE_ID]\n"); + } + + if (pdusession_id < 0 || pdusession_id > 255) + ERROR_MSG_RET("PDUSessionID must be in range [0,255]\n"); + if (ue_id < 0) + ERROR_MSG_RET("UE_ID must be >= 0\n"); + + nr_ue_nas_t *nas = get_ue_nas_info(ue_id); + if (!nas) + ERROR_MSG_RET("No NAS context found for UE_ID %d\n", ue_id); + + request_pdusession(nas, pdusession_id); + prnt("Triggered PDU session request for UE %d with ID %d\n", ue_id, pdusession_id); + return 0; +} + /* Telnet shell command definitions */ static telnetshell_cmddef_t cicmds[] = { {"sync_state", "[UE_ID(int,opt)]", get_sync_state}, @@ -140,6 +183,7 @@ static telnetshell_cmddef_t cicmds[] = { {"force_crnti_ra", "", force_crnti_ra}, {"deregistration", "", force_deregistration}, {"get_max_dl_toa", "[ant]", get_dl_toa}, + {"add_pdu_session", "[PDUSessionID(int)],[UE_ID(int,opt)]", add_pdu_session}, {"", "", NULL}, }; diff --git a/common/utils/telnetsrv/telnetsrv_o1.c b/common/utils/telnetsrv/telnetsrv_o1.c index ac368885f6..9ff56e3521 100644 --- a/common/utils/telnetsrv/telnetsrv_o1.c +++ b/common/utils/telnetsrv/telnetsrv_o1.c @@ -105,10 +105,10 @@ static int get_stats(char *buf, int debug, telnet_printfunc_t prnt) int bw_index = get_supported_band_index(scs, fr, nrb); int bw_mhz = get_supported_bw_mhz(fr, bw_index); - const mac_stats_t *stat = &mac->mac_stats; - static mac_stats_t last = {0}; - int diff_used = stat->used_prb_aggregate - last.used_prb_aggregate; - int diff_total = stat->total_prb_aggregate - last.total_prb_aggregate; + const dlul_mac_stats_t *stat = &mac->mac_stats; + static dlul_mac_stats_t last = {0}; + int diff_used = stat->dl.used_prb_aggregate - last.dl.used_prb_aggregate; + int diff_total = stat->dl.total_prb_aggregate - last.dl.total_prb_aggregate; int load = diff_total > 0 ? 100 * diff_used / diff_total : 0; last = *stat; diff --git a/doc/Doxyfile b/doc/Doxyfile index 5f96bc2e4a..85cb5776c0 100644 --- a/doc/Doxyfile +++ b/doc/Doxyfile @@ -1916,8 +1916,6 @@ INPUT = \ @CMAKE_CURRENT_SOURCE_DIR@/../openair2/E1AP/e1ap_api.h \ @CMAKE_CURRENT_SOURCE_DIR@/../openair2/E1AP/e1ap_setup.c \ @CMAKE_CURRENT_SOURCE_DIR@/../openair2/E1AP/e1ap_asnc.h \ -@CMAKE_CURRENT_SOURCE_DIR@/../openair2/NR_PHY_INTERFACE/nr_sched_response.h \ -@CMAKE_CURRENT_SOURCE_DIR@/../openair2/NR_PHY_INTERFACE/nr_sched_response.c \ @CMAKE_CURRENT_SOURCE_DIR@/../openair2/NR_PHY_INTERFACE/NR_IF_Module.h \ @CMAKE_CURRENT_SOURCE_DIR@/../openair2/NR_PHY_INTERFACE/NR_IF_Module.c \ @CMAKE_CURRENT_SOURCE_DIR@/../openair2/SDAP/nr_sdap/nr_sdap.h \ @@ -2012,7 +2010,6 @@ INPUT = \ @CMAKE_CURRENT_SOURCE_DIR@/../openair1/PHY/NR_TRANSPORT/nr_transport_common_proto.h \ @CMAKE_CURRENT_SOURCE_DIR@/../openair1/PHY/NR_TRANSPORT/nr_sss.c \ @CMAKE_CURRENT_SOURCE_DIR@/../openair1/PHY/NR_TRANSPORT/nr_uci_tools_common.c \ -@CMAKE_CURRENT_SOURCE_DIR@/../openair1/PHY/NR_TRANSPORT/nr_dlsch_tools.c \ @CMAKE_CURRENT_SOURCE_DIR@/../openair1/PHY/NR_TRANSPORT/nr_dlsch_coding.c \ @CMAKE_CURRENT_SOURCE_DIR@/../openair1/PHY/NR_TRANSPORT/nr_prach.c \ @CMAKE_CURRENT_SOURCE_DIR@/../openair1/PHY/NR_TRANSPORT/nr_scrambling.c \ @@ -2294,10 +2291,8 @@ INPUT = \ @CMAKE_CURRENT_SOURCE_DIR@/../openair1/SCHED_NR/phy_frame_config_nr.c \ @CMAKE_CURRENT_SOURCE_DIR@/../openair1/SCHED_NR/phy_frame_config_nr.h \ @CMAKE_CURRENT_SOURCE_DIR@/../openair1/SCHED_NR/nr_prach_procedures.c \ -@CMAKE_CURRENT_SOURCE_DIR@/../openair1/SCHED_NR/fapi_nr_l1.h \ @CMAKE_CURRENT_SOURCE_DIR@/../openair1/SCHED_NR/phy_procedures_nr_gNB.c \ @CMAKE_CURRENT_SOURCE_DIR@/../openair1/SCHED_NR/sched_nr.h \ -@CMAKE_CURRENT_SOURCE_DIR@/../openair1/SCHED_NR/fapi_nr_l1.c \ @CMAKE_CURRENT_SOURCE_DIR@/../openair1/SCHED_NR/nr_ru_procedures.c \ @CMAKE_CURRENT_SOURCE_DIR@/../radio/ETHERNET/if_defs.h \ @CMAKE_CURRENT_SOURCE_DIR@/../radio/ETHERNET/ethernet_lib.h \ diff --git a/doc/E1AP/e1ap_procedures.md b/doc/E1AP/e1ap_procedures.md index c46c710333..8857eee26b 100644 --- a/doc/E1AP/e1ap_procedures.md +++ b/doc/E1AP/e1ap_procedures.md @@ -72,3 +72,36 @@ sequenceDiagram u->>c: BEARER CONTEXT MODIFICATION RESPONSE Note over c: e1apCUCP_handle_BEARER_CONTEXT_MODIFICATION_RESPONSE ``` + +## PDU Session Release + +```mermaid +sequenceDiagram + participant AMF + participant CUCP + participant CUUP + participant DU + participant UE + + AMF->>CUCP: NG PDU SESSION RESOURCE RELEASE COMMAND + Note over CUCP: ngap_gNB_handle_pdusession_release_command + CUCP->>CUCP: rrc_gNB_process_NGAP_PDUSESSION_RELEASE_COMMAND + Note over CUCP: set status PDU_SESSION_STATUS_TORELEASE + CUCP->>CUUP: E1 Bearer Context Modification Request + Note over CUUP: release_gtpu_tunnel (GTP tunnel, PDCP, SDAP) + CUUP->>CUCP: E1 Bearer Context Modification Response + Note over CUCP: rrc_gNB_send_f1_drb_release_request + CUCP->>DU: F1 UE Context Modification Request + Note over DU: handle_ue_context_drbs_release (release in MAC/RLC) + DU->>CUCP: F1 UE Context Modification Response + Note over CUCP: rrc_CU_process_ue_context_modification_response + Note over CUCP: replace existing CellGroupConfig + Note over CUCP: rrc_gNB_generate_dedicatedRRCReconfiguration + CUCP->>UE: RRCReconfiguration (DRB release list, NAS PDU) + UE->>CUCP: RRCReconfigurationComplete + Note over CUCP: handle_rrcReconfigurationComplete + Note over CUCP: rrc_gNB_send_NGAP_PDUSESSION_RELEASE_RESPONSE + CUCP->>AMF: NG PDU SESSION RESOURCE RELEASE RESPONSE + Note over CUCP: rm_drbs_by_pdusession (from stored RRC list) + Note over CUCP: rm_pduSession (from stored RRC list) +``` diff --git a/doc/NR_NFAPI_archi.md b/doc/NR_NFAPI_archi.md index 8065ddb4fc..8e6647f73c 100644 --- a/doc/NR_NFAPI_archi.md +++ b/doc/NR_NFAPI_archi.md @@ -161,9 +161,9 @@ unpack function is called. ## P7 DL Transmission by VNF DL messages are scheduled at the VNF, through gNB_dlsch_ulsch_scheduler(). gNB_dlsch_ulsch_scheduler() is called when -handling a SLOT.indication message in trigger_scheduler(). +handling a SLOT.indication message in phy_nr_slot_indication(). -The function trigger_scheduler(nfapi_nr_slot_indication_scf_t *slot_ind) calls the functions oai_nfapi_[DL P7 msg]_ +The function phy_nr_slot_indication(nfapi_nr_slot_indication_scf_t *slot_ind) calls the functions oai_nfapi_[DL P7 msg]_ req(), calling in turn call the send_p7_msg function pointer, which contain the logic to pack the message into a buffer and send it to the PNF. Finally, NR_UL_indication is called to process the other P7 messages received from the PNF that were put in theire @@ -215,7 +215,7 @@ bool nfapi_vnf_p7_tx_data_req(nfapi_vnf_p7_config_t* config, nfapi_nr_tx_data_re graph TD softmodem_start[nr-softmodem init] --> P5_configuration[configure_nr_nfapi_vnf] --> transport_init[Transport mechanism init] --> send_first_msg[Send first P5 message to PNF] transport_init[Transport mechanism init] --> P5_recv_loop[P5 receive loop] -- P5 Message processing --> P5_recv_loop[P5 receive loop] - P5_recv_loop[P5 receive loop] -- Start.response callback called --> P7_config[P7 Configuration] --> P7_loop[P7 Loop] --> P7_msg_recv[P7 message received] --> call_vnf_handle_p7[Call vnf_nr_handle_p7_msg] --> hdr_unpack[Unpack header] --> call_specific_p7_handler[Call specific P7 message handler] --> slot_ind[Is a SLOT.indication?] -- Yes --> trig_scheduler[Call trigger_scheduler] --> gNB_ulsch_dlsch_sched[Call gNB_dlsch_ulsch_scheduler] --> send_p7_dl[Process and send P7 messages to PNF] --> call_ul_ind[Call NR_UL_indication] --> proc_p7[Process P7 messages in queue] --> P7_loop[P7 Loop] + P5_recv_loop[P5 receive loop] -- Start.response callback called --> P7_config[P7 Configuration] --> P7_loop[P7 Loop] --> P7_msg_recv[P7 message received] --> call_vnf_handle_p7[Call vnf_nr_handle_p7_msg] --> hdr_unpack[Unpack header] --> call_specific_p7_handler[Call specific P7 message handler] --> slot_ind[Is a SLOT.indication?] -- Yes --> trig_scheduler[Call phy_nr_slot_indication] --> gNB_ulsch_dlsch_sched[Call gNB_dlsch_ulsch_scheduler] --> send_p7_dl[Process and send P7 messages to PNF] --> call_ul_ind[Call NR_UL_indication] --> proc_p7[Process P7 messages in queue] --> P7_loop[P7 Loop] slot_ind[Is a SLOT.indication?] -- No --> put_queue[Put message in queue] --> P7_loop[P7 Loop]; diff --git a/doc/SW-archi-graph.md b/doc/SW-archi-graph.md index cf826e6e43..467ce5cd04 100644 --- a/doc/SW-archi-graph.md +++ b/doc/SW-archi-graph.md @@ -1,74 +1,97 @@ +This document is a high-level overview over the L1 threading mechanism. + ```mermaid flowchart TB - A[ru_thread] --> RFin>block rx_rf] --> feprx - feprx --> half-slot --> end_feprx - feprx --> second-thread -- block_end_feprx --> end_feprx>feprx] - end_feprx --> rx_nr_prach_ru -rx_nr_prach_ru -- block_queue_singleton --> resp_L1>resp L1] -resp_L1 -- async launch --> rx_func -resp_L1 -- immediate return --> RFin - -subgraph rxfunc -rx_func_implem[rx_func] - subgraph rxfuncbeg - handle_nr_slot_ind - --> rnti_to_remove-mgmt - --> L1_nr_prach_procedures - --> apply_nr_rotation_RX - end - subgraph phy_procedures_gNB_uespec_RX - fill_ul_rb_mask - --> pucch(decode each gNB->pucch) - -->nr_fill_ul_indication - --> nr_ulsch_procedures - --> nr_ulsch_decoding - --> segInParallel[[all segments decode in parallel]] - --> barrier_end_of_ulsch_decoding - end - subgraph NR_UL_indication - handle_nr_rach - --> handle_nr_uci - --> handle_nr_ulsch - subgraph gNB_dlsch_ulsch_scheduler - run_pdcp - --> schedule_xxxx - end - handle_nr_ulsch --> gNB_dlsch_ulsch_scheduler - subgraph NR_Schedule_response - L1_tx_free3>L1_tx_free] - --> handle_nr_nfapi_xxx_pdu - --> sendTxFilled((L1_tx_filled)) - --> nr_fill_ul_xxx - --> nr_schedule_rx_prach() - end - gNB_dlsch_ulsch_scheduler --> NR_Schedule_response - end - rx_func_implem --> rxfuncbeg - rxfuncbeg --> phy_procedures_gNB_uespec_RX -phy_procedures_gNB_uespec_RX --> NR_UL_indication --- block_queue_block_PNF_monolithic --> L1_tx_free2>L1 tx filled] --- async launch --> tx_func -L1_tx_free2 -- send_msg --> rsp((resp_L1)) -end -rx_func --> rxfunc - - -subgraph tx_func - direction LR - subgraph phy_procedures_gNB_TX - dcitop[nr_generate dci top] - --> nr_generate_csi_rs - --> apply_nr_rotation_TX - -- send_msg --> end_tx_func((L1_tx_out)) - end - subgraph tx_reorder_thread - L1_tx_out>L1_tx_out] - --> reorder{re order} --> reorder - reorder --> ru_tx_func - reorder --> L1_tx_free((L1_tx_free)) - ru_tx_func --> feptx_prec - --> feptx_ofdm - end -end - + ru_thread --> RFin[block rx_rf] --> UL{is UL slot?} + UL -- yes --> wait_free_rx_tti --> fep_rx --> rx_nr_prach_ru --> msg:L1_tx_out + UL -- no --> msg:L1_tx_out + msg:L1_tx_out -- asnyc launch --> L1_tx_thread + msg:L1_tx_out --> RFin ``` + +The main thread is `ru_thread()`. It blocks on reception of radio samples +(either time domain or frequency domain). In the case of an UL slot, it waits +that no more than N UL jobs are scheduled (via `wait_free_rx_tti()`, which +waits on queue `L1_rx_out`, cf. the RX L1 processing further below). Then: + +- if the radio is time domain-based, it performs RX front-end processing (RX + FEP -> `fep_rx()`, i.e. DFT) to reach a frequency domain representation of + the RX signal, as well as does DFT for PRACH. +- if the radio is frequency domain-based, nothing is done. + +Afterwards, it triggers TX processing by pushing a message into the FIFO queue +`L1_tx_out`, which asynchronously starts a TX job in `L1_tx_thread()` (see +below). After that, it blocks again on reception on the radio. + + +```mermaid +flowchart TB + L1_tx_thread --> TX_in[block L1_tx_out] --> NR_slot_indication + + subgraph tx_func + + NR_slot_indication --> msg:resp_L1 --> phy_procedures_gNB_tx --> ru_tx_func + NR_slot_indication["run the scheduler: + - monolithic: run_scheduler_monolithic() + - nFAPI: send indication via pnf_send_slot_ind()"] + msg:resp_L1 -- async launch --> L1_RX_thread + end + ru_tx_func --> TX_in +``` + +The `L1_tx_thread()` processes individual TX jobs sequentially, by waiting for +new messages on queue `L1_tx_out`, signalling individual TX jobs. For each +message, it calls `tx_func()` which does in order: + +- run the scheduler through `NR_slot_indication`, which corresponds to a + "Slot.indication" in FAPI parlance. This runs the scheduler, and schedules a + given slot (either downlink, uplink, or both). +- trigger RX processing by pushing a message into the FIFO queue `resp_L1`, + asynchronously starting an RX job in `L1_rx_thread()` (see below). +- process the current L1 TX job through `phy_procedures_gNB_tx()` +- write to the radio board via `ru_tx_func()`. + +After these steps, `tx_func()` return to `L1_tx_thread()`, which will wait for +the next TX job. + +```mermaid +flowchart TB + L1_rx_thread --> RX_in[block resp_L1] --> L1_nr_prach_proc + + subgraph rx_func + + L1_nr_prach_proc --> phase_comp{apply phase comp.?} + phase_comp -- yes --> apply_nr_rotation --> phy_procedures_gNB_uespec_RX + phase_comp -- no --> phy_procedures_gNB_uespec_RX + phy_procedures_gNB_uespec_RX --> NR_ul_indication --> msg:L1_rx_out + NR_ul_indication["run the scheduler: NR_UL_indication()"] + msg:L1_rx_out -- async signal free --> ru_thread + end + msg:L1_rx_out --> RX_in +``` + +The `L1_rx_thread()` processes individual RX jobs sequentially. It waits for a +new RX job through the queue `resp_L1`, and then calls `rx_func()`, which does +in order: + +- run PRACH processing via `L1_nr_prach_proc()` +- optionally apply rotation to the RX signal if phase compensation is to be + applied +- run the current L1 RX job through (`phy_procedures_gNB_uespec_RX()`), which + notably includes PUCCH, PUSCH, SRS processing +- call the scheduler through `NR_ul_indication()`, which corresponds to FAPI + uplink messages (e.g., `RX_data.indication`, `CRC.indication`, + `UCI.indication` etc.) +- signal completion via FIFO queue `L1_rx_out()`, which tells `ru_thread()` + that RX processing finished. + +The signalling of scheduler data is done through a variable `UL_INFO`, which is +filled by `L1_nr_prach_proc()` (for PRACH) and `phy_procedures_gNB_uespec_RX()` +(for PUCCH, PUSCH, SRS). + +After these steps, `rx_func()` returns to `L1_rx_thread()`, which will wait the +next RX job. + +Note that while individual TX (RX) jobs are run sequentially through +`L1_tx_thread()` (`L1_rx_thread()`), both TX and RX processing run in +parallel. diff --git a/doc/SW_archi.md b/doc/SW_archi.md index c47a3cbc91..78004a5a74 100644 --- a/doc/SW_archi.md +++ b/doc/SW_archi.md @@ -177,7 +177,7 @@ it would be better to call **NR_UL_indication()** now instead of before (on prev * nr_common_signal_procedures() generate common signals {: .func4} -* nr_generate_dci_top() +* nr_generate_dci() generate DCI: the scheduling informtion for each UE in both DL and UL {: .func4} * nr_generate_pdsch() diff --git a/doc/nfapi.md b/doc/nfapi.md index 214aa2799f..8b9197b056 100644 --- a/doc/nfapi.md +++ b/doc/nfapi.md @@ -242,10 +242,10 @@ To see the (any) periodical output at the PNF, define `NFAPI_TRACE_LEVEL=info`. This output shows: ``` -41056.739654 [I] 3556767424: pnf_p7_slot_ind: [P7:1] msgs ontime 489 thr DL 0.06 UL 0.01 msg late 0 (vtime) +41056.739654 [I] 3556767424: nr_pnf_p7_get_msgs: [P7:1] msgs ontime 489 thr DL 0.06 UL 0.01 msg late 0 (vtime) ``` -The first numbers are timestamps. `pnf_p7_slot_ind` is the name of the +The first numbers are timestamps. `nr_pnf_p7_get_msgs` is the name of the functions that prints the output. `[P7:1]` refers to the fact that these are information on P7, of PHY ID 1. Finally, `msgs ontime 489` means that in the last window (since the last print), 489 messages arrived at the PNF in total. diff --git a/executables/lte-softmodem.c b/executables/lte-softmodem.c index 80b532607e..6ff535fb5b 100644 --- a/executables/lte-softmodem.c +++ b/executables/lte-softmodem.c @@ -194,13 +194,7 @@ void handle_nr_srs_measurements(const module_id_t module_id, void set_default_frame_parms(LTE_DL_FRAME_PARMS *frame_parms[MAX_NUM_CCs]); /* TODO these declarations are to be removed */ -void nr_schedule_dl_tti_req(void) {}; -void nr_schedule_ul_dci_req() {}; -void nr_schedule_tx_req() {}; -void nr_schedule_ul_tti_req() {}; void nr_slot_select() {}; -void NR_UL_indication(NR_UL_IND_t *UL_INFO) {}; -void gNB_dlsch_ulsch_scheduler() {}; /*------------------------------------------------------------------------*/ diff --git a/executables/lte-uesoftmodem.c b/executables/lte-uesoftmodem.c index b212ceb3f1..f36bdde2b5 100644 --- a/executables/lte-uesoftmodem.c +++ b/executables/lte-uesoftmodem.c @@ -156,10 +156,6 @@ extern char uecap_xer[1024]; char uecap_xer_in=0; /* TODO these declarations are to be removed */ -void nr_schedule_dl_tti_req(void) {}; -void nr_schedule_ul_dci_req() {}; -void nr_schedule_tx_req() {}; -void nr_schedule_ul_tti_req() {}; void nr_slot_select() {}; /* see file openair2/LAYER2/MAC/main.c for why abstraction_flag is needed diff --git a/executables/nr-cuup.c b/executables/nr-cuup.c index 0c2c9cdf3f..df2f633d95 100644 --- a/executables/nr-cuup.c +++ b/executables/nr-cuup.c @@ -51,8 +51,9 @@ static void initialize_agent(ngran_node_t node_type, e2_agent_args_t oai_args) printf("After RCconfig_NR_E2agent %s %s \n",oai_args.sm_dir, oai_args.ip ); - fr_args_t args = { .ip = oai_args.ip }; // init_fr_args(0, NULL); - memcpy(args.libs_dir, oai_args.sm_dir, 128); + fr_args_t args = {0}; + memcpy(args.ip, oai_args.ip, FR_IP_ADDRESS_LEN); + memcpy(args.libs_dir, oai_args.sm_dir, FR_CONF_FILE_LEN); sleep(1); diff --git a/executables/nr-gnb.c b/executables/nr-gnb.c index b866a83222..94fc22cf46 100644 --- a/executables/nr-gnb.c +++ b/executables/nr-gnb.c @@ -55,7 +55,6 @@ #include "PHY/defs_gNB.h" #include "PHY/defs_nr_common.h" #include "PHY/impl_defs_nr.h" -#include "SCHED_NR/fapi_nr_l1.h" #include "SCHED_NR/phy_frame_config_nr.h" #include "SCHED_NR/sched_nr.h" #include "assertions.h" @@ -65,7 +64,6 @@ #include "nfapi/oai_integration/vendor_ext.h" #include "nfapi_nr_interface_scf.h" #include "notified_fifo.h" -#include "openair2/NR_PHY_INTERFACE/nr_sched_response.h" #include "thread-pool.h" #include "time_meas.h" #include "utils.h" @@ -82,8 +80,6 @@ static void tx_func(processingData_L1tx_t *info) int slot_rx = info->slot_rx; LOG_D(NR_PHY, "%d.%d running tx_func\n", frame_tx, slot_tx); PHY_VARS_gNB *gNB = info->gNB; - module_id_t module_id = gNB->Mod_id; - uint8_t CC_id = gNB->CC_id; NR_IF_Module_t *ifi = gNB->if_inst; nfapi_nr_config_request_scf_t *cfg = &gNB->gNB_config; @@ -94,15 +90,22 @@ static void tx_func(processingData_L1tx_t *info) reset_active_ulsch(gNB, frame_rx); } + clear_slot_beamid(gNB, slot_tx); + + nfapi_nr_slot_indication_scf_t ind = {.sfn = frame_tx, .slot = slot_tx}; start_meas(&gNB->slot_indication_stats); - ifi->NR_slot_indication(module_id, CC_id, frame_tx, slot_tx); + // this variable is very big (multiple MB), so we put it into static storage + // to not overflow the stack while still having it in local (function) scope + // also, tx_func() is only executed by one thread, serially + static NR_Sched_Rsp_t sched_response; + ifi->NR_slot_indication(&ind, &sched_response); stop_meas(&gNB->slot_indication_stats); - gNB->msgDataTx->timestamp_tx = info->timestamp_tx; - info = gNB->msgDataTx; + info->gNB = gNB; // At this point, MAC scheduler just ran, including scheduling // PRACH/PUCCH/PUSCH, so trigger RX chain processing + nr_save_ul_tti_req(gNB, &sched_response.UL_tti_req); LOG_D(NR_PHY, "Trigger RX for %d.%d\n", frame_rx, slot_rx); notifiedFIFO_elt_t *res = newNotifiedFIFO_elt(sizeof(processingData_L1_t), 0, &gNB->resp_L1, NULL); processingData_L1_t *syncMsg = NotifiedFifoData(res); @@ -119,7 +122,13 @@ static void tx_func(processingData_L1tx_t *info) if (tx_slot_type == NR_DOWNLINK_SLOT || tx_slot_type == NR_MIXED_SLOT || get_softmodem_params()->continuous_tx || IS_SOFTMODEM_RFSIM || cfg->analog_beamforming_ve.analog_beam_list) { start_meas(&info->gNB->phy_proc_tx); - phy_procedures_gNB_TX(info, frame_tx, slot_tx, 1); + phy_procedures_gNB_TX(info->gNB, + &sched_response.DL_req, + &sched_response.TX_req, + &sched_response.UL_dci_req, + frame_tx, + slot_tx, + 1); PHY_VARS_gNB *gNB = info->gNB; processingData_RU_t syncMsgRU; @@ -131,14 +140,6 @@ static void tx_func(processingData_L1tx_t *info) ru_tx_func((void *)&syncMsgRU); stop_meas(&info->gNB->phy_proc_tx); } - - if (NFAPI_MODE == NFAPI_MONOLITHIC) { - /* this thread is done with the sched_info, decrease the reference counter. - * This only applies for monolithic; in the PNF, the memory is allocated in - * a ring buffer that should never be overwritten (one frame duration). */ - LOG_D(NR_PHY, "Calling deref_sched_response for id %d (tx_func) in %d.%d\n", info->sched_response_id, frame_tx, slot_tx); - deref_sched_response(info->sched_response_id); - } } void *L1_rx_thread(void *arg) @@ -248,7 +249,6 @@ static size_t dump_L1_meas_stats(PHY_VARS_gNB *gNB, RU_t *ru, char *output, size output += print_meas_log(&gNB->ul_indication_stats, "UL Indication", NULL, NULL, output, end - output); output += print_meas_log(&gNB->slot_indication_stats, "Slot Indication", NULL, NULL, output, end - output); output += print_meas_log(&gNB->rx_pusch_stats, "PUSCH inner-receiver", NULL, NULL, output, end - output); - output += print_meas_log(&gNB->schedule_response_stats, "Schedule Response", NULL, NULL, output, end - output); output += print_meas_log(&gNB->rx_prach, "PRACH RX", NULL, NULL, output, end - output); if (ru->feprx) output += print_meas_log(&ru->ofdm_demod_stats, "feprx", NULL, NULL, output, end - output); @@ -310,7 +310,6 @@ void *nrL1_stats_thread(void *param) { reset_meas(&gNB->ul_indication_stats); reset_meas(&gNB->slot_indication_stats); reset_meas(&gNB->rx_pusch_stats); - reset_meas(&gNB->schedule_response_stats); reset_meas(&gNB->dlsch_scrambling_stats); reset_meas(&gNB->dlsch_modulation_stats); reset_meas(&gNB->dlsch_resource_mapping_stats); @@ -358,14 +357,6 @@ void init_gNB_Tpool(int inst) // create the TX thread responsible for TX processing start event (L1_tx_out msg queue), then launch tx_func() threadCreate(&gNB->L1_tx_thread, L1_tx_thread, (void *)gNB, "L1_tx_thread", gNB->L1_tx_thread_core, OAI_PRIORITY_RT_MAX); - notifiedFIFO_elt_t *msgL1Tx = newNotifiedFIFO_elt(sizeof(processingData_L1tx_t), 0, &gNB->L1_tx_out, NULL); - processingData_L1tx_t *msgDataTx = (processingData_L1tx_t *)NotifiedFifoData(msgL1Tx); - memset(msgDataTx, 0, sizeof(processingData_L1tx_t)); - init_DLSCH_struct(gNB, msgDataTx); - memset(msgDataTx->ssb, 0, 64 * sizeof(NR_gNB_SSB_t)); - // this will be removed when the msgDataTx is not necessary anymore - gNB->msgDataTx = msgDataTx; - if (!IS_SOFTMODEM_NOSTATS) threadCreate(&proc->L1_stats_thread, nrL1_stats_thread, (void *)gNB, "L1_stats", -1, OAI_PRIORITY_RT_LOW); } @@ -442,7 +433,6 @@ void init_gNB() AssertFatal((gNB->if_inst = NR_IF_Module_init(inst)) != NULL, "Cannot register interface"); LOG_I(NR_PHY, "Registered with MAC interface module (%p)\n", gNB->if_inst); - gNB->if_inst->NR_Schedule_response = nr_schedule_response; gNB->if_inst->NR_PHY_config_req = nr_phy_config_request; gNB->prach_energy_counter = 0; diff --git a/executables/nr-softmodem.c b/executables/nr-softmodem.c index 0bd583662b..125bfbd898 100644 --- a/executables/nr-softmodem.c +++ b/executables/nr-softmodem.c @@ -423,8 +423,6 @@ int start_L1L2(module_id_t gnb_id) /* block threads */ oai_exit = 0; sync_var = -1; - extern void init_sched_response(void); - init_sched_response(); /* update config */ gNB_MAC_INST *mac = RC.nrmac[0]; @@ -473,8 +471,9 @@ static void initialize_agent(ngran_node_t node_type, e2_agent_args_t oai_args) printf("After RCconfig_NR_E2agent %s %s \n",oai_args.sm_dir, oai_args.ip ); - fr_args_t args = { .ip = oai_args.ip }; // init_fr_args(0, NULL); - memcpy(args.libs_dir, oai_args.sm_dir, 128); + fr_args_t args = {0}; + memcpy(args.ip, oai_args.ip, FR_IP_ADDRESS_LEN); + memcpy(args.libs_dir, oai_args.sm_dir, FR_CONF_FILE_LEN); sleep(1); const gNB_RRC_INST* rrc = RC.nrrrc[0]; diff --git a/nfapi/oai_integration/nfapi_pnf.c b/nfapi/oai_integration/nfapi_pnf.c index 3de11d8003..bb3ac8555b 100644 --- a/nfapi/oai_integration/nfapi_pnf.c +++ b/nfapi/oai_integration/nfapi_pnf.c @@ -55,7 +55,6 @@ #include "PHY/INIT/phy_init.h" #include "PHY/INIT/nr_phy_init.h" #include "PHY/LTE_TRANSPORT/transport_proto.h" -#include "openair1/SCHED_NR/fapi_nr_l1.h" #include "openair1/PHY/NR_TRANSPORT/nr_dlsch.h" #include "openair1/PHY/defs_gNB.h" #include @@ -1108,17 +1107,6 @@ void pnf_nr_phy_deallocate_p7_vendor_ext(void *header) free(header); } -extern void nr_schedule_ul_dci_req(PHY_VARS_gNB *gNB, nfapi_nr_ul_dci_request_t *UL_dci_req); -int pnf_phy_ul_dci_req(gNB_L1_rxtx_proc_t *proc, nfapi_pnf_p7_config_t *pnf_p7, nfapi_nr_ul_dci_request_t *req) -{ - DevAssert(RC.gNB != NULL && RC.gNB[0] != NULL); - PHY_VARS_gNB *gNB = RC.gNB[0]; // phy_inst? - - nr_schedule_ul_dci_req(gNB, req); - - return 0; -} - int pnf_phy_hi_dci0_req(L1_rxtx_proc_t *proc, nfapi_pnf_p7_config_t *pnf_p7, nfapi_hi_dci0_request_t *req) { if (req->hi_dci0_request_body.number_of_dci == 0 && req->hi_dci0_request_body.number_of_hi == 0) @@ -1149,21 +1137,6 @@ int pnf_phy_hi_dci0_req(L1_rxtx_proc_t *proc, nfapi_pnf_p7_config_t *pnf_p7, nfa } -// from dl_tti_req_fn fptr -extern void nr_schedule_dl_tti_req(PHY_VARS_gNB *gNB, nfapi_nr_dl_tti_request_t *DL_req); -int pnf_phy_dl_tti_req(gNB_L1_rxtx_proc_t *proc, nfapi_pnf_p7_config_t *pnf_p7, nfapi_nr_dl_tti_request_t *DL_req) -{ - DevAssert(proc == NULL); - DevAssert(sync_var == 0); - DevAssert(RC.gNB != NULL && RC.gNB[0] != NULL); - PHY_VARS_gNB *gNB = RC.gNB[0]; // phy_inst? - - nr_schedule_dl_tti_req(gNB, DL_req); - - return 0; -} - - int pnf_phy_dl_config_req(L1_rxtx_proc_t *proc, nfapi_pnf_p7_config_t *pnf_p7, nfapi_dl_config_request_t *req) { if (RC.eNB == 0) { @@ -1256,18 +1229,6 @@ int pnf_phy_dl_config_req(L1_rxtx_proc_t *proc, nfapi_pnf_p7_config_t *pnf_p7, n } -extern void nr_schedule_tx_req(PHY_VARS_gNB *gNB, nfapi_nr_tx_data_request_t *TX_req); -int pnf_phy_tx_data_req(nfapi_pnf_p7_config_t *pnf_p7, nfapi_nr_tx_data_request_t *req) -{ - DevAssert(RC.gNB != NULL && RC.gNB[0] != NULL); - PHY_VARS_gNB *gNB = RC.gNB[0]; // phy_inst? - - nr_schedule_tx_req(gNB, req); - - return 0; -} - - int pnf_phy_tx_req(nfapi_pnf_p7_config_t *pnf_p7, nfapi_tx_request_t *req) { uint16_t sfn = NFAPI_SFNSF2SFN(req->sfn_sf); uint16_t sf = NFAPI_SFNSF2SF(req->sfn_sf); @@ -1293,16 +1254,6 @@ int pnf_phy_tx_req(nfapi_pnf_p7_config_t *pnf_p7, nfapi_tx_request_t *req) { return 0; } -extern void nr_schedule_ul_tti_req(PHY_VARS_gNB *gNB, nfapi_nr_ul_tti_request_t *UL_tti_req); -int pnf_phy_ul_tti_req(gNB_L1_rxtx_proc_t *proc, nfapi_pnf_p7_config_t *pnf_p7, nfapi_nr_ul_tti_request_t *req) -{ - DevAssert(RC.gNB != NULL && RC.gNB[0] != NULL); - PHY_VARS_gNB *gNB = RC.gNB[0]; // phy_inst? - - nr_schedule_ul_tti_req(gNB, req); - return 0; -} - int pnf_phy_ul_config_req(L1_rxtx_proc_t *proc, nfapi_pnf_p7_config_t *pnf_p7, nfapi_ul_config_request_t *req) { if (0)LOG_D(PHY,"[PNF] UL_CONFIG_REQ %s() sfn_sf:%d pdu:%d rach_prach_frequency_resources:%d srs_present:%u\n", __FUNCTION__, @@ -1711,10 +1662,10 @@ int nr_start_request(nfapi_pnf_config_t *config, nfapi_pnf_phy_config_t *phy, nf } // NR - p7_config->dl_tti_req_fn = &pnf_phy_dl_tti_req; - p7_config->ul_tti_req_fn = &pnf_phy_ul_tti_req; - p7_config->ul_dci_req_fn = &pnf_phy_ul_dci_req; - p7_config->tx_data_req_fn = &pnf_phy_tx_data_req; + p7_config->dl_tti_req_fn = NULL; + p7_config->ul_tti_req_fn = NULL; + p7_config->ul_dci_req_fn = NULL; + p7_config->tx_data_req_fn = NULL; // LTE p7_config->dl_config_req = &pnf_phy_dl_config_req; @@ -1825,13 +1776,6 @@ int nr_start_request(nfapi_pnf_config_t *config, nfapi_pnf_phy_config_t *phy, nf nfapi_nr_send_pnf_start_resp(config, p7_config->phy_id); printf("[PNF] Sending first P7 slot indication\n"); #endif -#if 1 - nfapi_pnf_p7_slot_ind(p7_config, p7_config->phy_id, 0, 0); - printf("[PNF] Sent first P7 slot ind\n"); -#else - nfapi_pnf_p7_subframe_ind(p7_config, p7_config->phy_id, 0); // SFN_SF set to zero - correct??? - printf("[PNF] Sent first P7 subframe ind\n"); -#endif return 0; } @@ -2321,7 +2265,7 @@ static void maybe_slow_down_pnf(int mu) last_execution = current_execution; } -void handle_nr_slot_ind(uint16_t sfn, uint16_t slot) +void handle_nr_slot_ind(uint16_t sfn, uint16_t slot, NR_Sched_Rsp_t *sched_resp) { nfapi_pnf_p7_config_t *config = p7_config_g; pnf_p7_t *_this = (pnf_p7_t *)(config); @@ -2352,7 +2296,14 @@ void handle_nr_slot_ind(uint16_t sfn, uint16_t slot) oai_nfapi_nr_slot_indication(&ind); // copy data from appropriate p7 slot buffers into channel structures for PHY processing - nfapi_pnf_p7_slot_ind(config, config->phy_id, sfn, slot); + nfapi_pnf_p7_get_msgs(config, + config->phy_id, + sfn, + slot, + &sched_resp->DL_req, + &sched_resp->UL_tti_req, + &sched_resp->UL_dci_req, + &sched_resp->TX_req); return; } diff --git a/nfapi/oai_integration/nfapi_pnf.h b/nfapi/oai_integration/nfapi_pnf.h index 0ba0676f10..ad2df72ad3 100644 --- a/nfapi/oai_integration/nfapi_pnf.h +++ b/nfapi/oai_integration/nfapi_pnf.h @@ -28,7 +28,8 @@ void configure_nfapi_pnf(char *vnf_ip_addr, int vnf_p5_port, char *pnf_ip_addr, void configure_nr_nfapi_pnf(char *vnf_ip_addr, int vnf_p5_port, char *pnf_ip_addr, int pnf_p7_port, int vnf_p7_port); void oai_subframe_ind(uint16_t sfn, uint16_t sf); -void handle_nr_slot_ind(uint16_t sfn, uint16_t slot); +struct NR_Sched_Rsp; +void handle_nr_slot_ind(uint16_t sfn, uint16_t slot, struct NR_Sched_Rsp *resp); void sfnslot_add_slot(int mu, uint16_t *sfn, uint16_t *slot, int offset); int oai_nfapi_nr_slot_indication(nfapi_nr_slot_indication_scf_t *ind); diff --git a/nfapi/oai_integration/nfapi_vnf.c b/nfapi/oai_integration/nfapi_vnf.c index 5ea99de7ea..b251d9d762 100644 --- a/nfapi/oai_integration/nfapi_vnf.c +++ b/nfapi/oai_integration/nfapi_vnf.c @@ -124,7 +124,6 @@ int vnf_nr_unpack_vendor_extension_tlv(nfapi_tl_t *tl, { return -1; } -void install_nr_schedule_handlers(NR_IF_Module_t *if_inst); void install_schedule_handlers(IF_Module_t *if_inst); extern int sf_ahead; @@ -326,71 +325,6 @@ int pnf_config_resp_cb(nfapi_vnf_config_t *config, int p5_idx, nfapi_pnf_config_ return 0; } -int wake_gNB_rxtx(PHY_VARS_gNB *gNB, uint16_t sfn, uint16_t slot) { - struct timespec curr_t; - clock_gettime(CLOCK_MONOTONIC,&curr_t); - //NFAPI_TRACE(NFAPI_TRACE_INFO, "\n wake_gNB_rxtx before assignment sfn:%d slot:%d TIME %d.%d",sfn,slot,curr_t.tv_sec,curr_t.tv_nsec); - gNB_L1_proc_t *proc=&gNB->proc; - gNB_L1_rxtx_proc_t *L1_proc= (slot&1)? &proc->L1_proc : &proc->L1_proc_tx; - - NR_DL_FRAME_PARMS *fp = &gNB->frame_parms; - //NFAPI_TRACE(NFAPI_TRACE_INFO, "%s(eNB:%p, sfn:%d, sf:%d)\n", __FUNCTION__, eNB, sfn, sf); - //int i; - struct timespec wait; - clock_gettime(CLOCK_REALTIME, &wait); - wait.tv_sec = 0; - wait.tv_nsec +=5000L; - //wait.tv_nsec = 0; - // wake up TX for subframe n+sf_ahead - // lock the TX mutex and make sure the thread is ready - AssertFatal(gNB->if_inst->sl_ahead==6,"gNB->if_inst->sl_ahead %d : This is hard-coded to 6 in nfapi P7!!!\n",gNB->if_inst->sl_ahead); - if (pthread_mutex_timedlock(&L1_proc->mutex,&wait) != 0) { - LOG_E( PHY, "[gNB] ERROR pthread_mutex_lock for gNB RXTX thread %d (IC %d)\n", L1_proc->slot_rx&1,L1_proc->instance_cnt ); - exit_fun( "error locking mutex_rxtx" ); - return(-1); - } - - { - static uint16_t old_slot = 0; - static uint16_t old_sfn = 0; - proc->slot_rx = old_slot; - proc->frame_rx = old_sfn; - // Try to be 1 frame back - old_slot = slot; - old_sfn = sfn; - //NFAPI_TRACE(NFAPI_TRACE_INFO, "\n wake_gNB_rxtx after assignment sfn:%d slot:%d",proc->frame_rx,proc->slot_rx); - if (old_slot == 0 && old_sfn % 100 == 0) LOG_W( PHY,"[gNB] sfn/slot:%d%d old_sfn/slot:%d%d proc[rx:%d%d]\n", sfn, slot, old_sfn, old_slot, proc->frame_rx, proc->slot_rx); - } - - ++L1_proc->instance_cnt; - //LOG_D( PHY,"[VNF-subframe_ind] sfn/sf:%d:%d proc[frame_rx:%d subframe_rx:%d] L1_proc->instance_cnt_rxtx:%d \n", sfn, sf, proc->frame_rx, proc->subframe_rx, L1_proc->instance_cnt_rxtx); - // We have just received and processed the common part of a subframe, say n. - // TS_rx is the last received timestamp (start of 1st slot), TS_tx is the desired - // transmitted timestamp of the next TX slot (first). - // The last (TS_rx mod samples_per_frame) was n*samples_per_tti, - // we want to generate subframe (n+N), so TS_tx = TX_rx+N*samples_per_tti, - // and proc->subframe_tx = proc->subframe_rx+sf_ahead - L1_proc->timestamp_tx = proc->timestamp_rx + (gNB->if_inst->sl_ahead *fp->samples_per_subframe); - L1_proc->frame_rx = proc->frame_rx; - L1_proc->slot_rx = proc->slot_rx; - L1_proc->frame_tx = (L1_proc->slot_rx > (19-gNB->if_inst->sl_ahead)) ? (L1_proc->frame_rx+1)&1023 : L1_proc->frame_rx; - L1_proc->slot_tx = (L1_proc->slot_rx + gNB->if_inst->sl_ahead)%20; - - //LOG_D(PHY, "sfn/sf:%d%d proc[rx:%d%d] rx:%d%d] About to wake rxtx thread\n\n", sfn, slot, proc->frame_rx, proc->slot_rx, L1_proc->frame_rx, L1_proc->slot_rx); - //NFAPI_TRACE(NFAPI_TRACE_INFO, "\nEntering wake_gNB_rxtx sfn %d slot %d\n",L1_proc->frame_rx,L1_proc->slot_rx); - // the thread can now be woken up - if (pthread_cond_signal(&L1_proc->cond) != 0) { - LOG_E( PHY, "[gNB] ERROR pthread_cond_signal for gNB RXn-TXnp4 thread\n"); - exit_fun( "ERROR pthread_clond_signal" ); - return(-1); - } - - //LOG_D(PHY,"%s() About to attempt pthread_mutex_unlock\n", __FUNCTION__); - pthread_mutex_unlock( &L1_proc->mutex ); - //LOG_D(PHY,"%s() UNLOCKED pthread_mutex_unlock\n", __FUNCTION__); - return(0); -} - int wake_eNB_rxtx(PHY_VARS_eNB *eNB, uint16_t sfn, uint16_t sf) { L1_proc_t *proc=&eNB->proc; L1_rxtx_proc_t *L1_proc= (sf&1)? &proc->L1_proc : &proc->L1_proc_tx; @@ -498,28 +432,6 @@ int phy_sync_indication(struct nfapi_vnf_p7_config *config, uint8_t sync) { } -int phy_slot_indication(struct nfapi_vnf_p7_config *config, uint16_t phy_id, uint16_t sfn, uint16_t slot) { - static uint8_t first_time = 1; - - if (first_time) { - NFAPI_TRACE(NFAPI_TRACE_INFO, "[VNF] slot indication %d.%d\n", sfn, slot); - first_time = 0; - } - - if (RC.gNB && RC.gNB[0]->configured) { - // uint16_t sfn = NFAPI_SFNSF2SFN(sfn_sf); - // uint16_t sf = NFAPI_SFNSF2SF(sfn_sf); - LOG_D(PHY,"[VNF] slot indication sfn:%d slot:%d\n", sfn, slot); - wake_gNB_rxtx(RC.gNB[0], sfn, slot); // DONE: find NR equivalent - } else { - NFAPI_TRACE(NFAPI_TRACE_INFO, "[VNF] %s() RC.gNB:%p\n", __FUNCTION__, RC.gNB); - - if (RC.gNB) NFAPI_TRACE(NFAPI_TRACE_INFO, "RC.gNB[0]->configured:%d\n", RC.gNB[0]->configured); - } - - return 0; -} - int phy_subframe_indication(struct nfapi_vnf_p7_config *config, uint16_t phy_id, uint16_t sfn_sf) { static uint8_t first_time = 1; @@ -971,65 +883,63 @@ int phy_cqi_indication(struct nfapi_vnf_p7_config *config, nfapi_cqi_indication_ //NR phy indication -NR_Sched_Rsp_t g_sched_resp; -void gNB_dlsch_ulsch_scheduler(module_id_t module_idP, frame_t frame, slot_t slot, NR_Sched_Rsp_t* sched_info); int oai_nfapi_dl_tti_req(nfapi_nr_dl_tti_request_t *dl_config_req); int oai_nfapi_ul_tti_req(nfapi_nr_ul_tti_request_t *ul_tti_req); int oai_nfapi_tx_data_req(nfapi_nr_tx_data_request_t* tx_data_req); int oai_nfapi_ul_dci_req(nfapi_nr_ul_dci_request_t* ul_dci_req); -int trigger_scheduler(nfapi_nr_slot_indication_scf_t *slot_ind) -{ - // Call into the scheduler (this is hardcoded and should be init properly!) - // memset(sched_resp, 0, sizeof(*sched_resp)); - gNB_dlsch_ulsch_scheduler(0, slot_ind->sfn, slot_ind->slot, &g_sched_resp); - -#ifdef ENABLE_AERIAL - bool send_slt_resp = false; - if (g_sched_resp.DL_req.dl_tti_request_body.nPDUs> 0) { - oai_fapi_dl_tti_req(&g_sched_resp.DL_req); - send_slt_resp = true; - } - if (g_sched_resp.UL_tti_req.n_pdus > 0) { - oai_fapi_ul_tti_req(&g_sched_resp.UL_tti_req); - send_slt_resp = true; - } - if (g_sched_resp.TX_req.Number_of_PDUs > 0) { - oai_fapi_tx_data_req(&g_sched_resp.TX_req); - send_slt_resp = true; - } - if (g_sched_resp.UL_dci_req.numPdus > 0) { - oai_fapi_ul_dci_req(&g_sched_resp.UL_dci_req); - send_slt_resp = true; - } - if (send_slt_resp) { - oai_fapi_send_end_request(0,slot_ind->sfn, slot_ind->slot); - } -#else - if (g_sched_resp.DL_req.dl_tti_request_body.nPDUs > 0) - oai_nfapi_dl_tti_req(&g_sched_resp.DL_req); - - if (g_sched_resp.UL_tti_req.n_pdus > 0) - oai_nfapi_ul_tti_req(&g_sched_resp.UL_tti_req); - - if (g_sched_resp.TX_req.Number_of_PDUs > 0) - oai_nfapi_tx_data_req(&g_sched_resp.TX_req); - - if (g_sched_resp.UL_dci_req.numPdus > 0) - oai_nfapi_ul_dci_req(&g_sched_resp.UL_dci_req); -#endif - - NR_UL_IND_t ind = {.frame = slot_ind->sfn, .slot = slot_ind->slot, }; - NR_UL_indication(&ind); - - return 1; -} - int phy_nr_slot_indication(nfapi_nr_slot_indication_scf_t *ind) { LOG_D(MAC, "VNF SFN/Slot %d.%d \n", ind->sfn, ind->slot); - trigger_scheduler(ind); + // this variable is very big (multiple MB), so we put it into static storage + // to not overflow the stack while still having it in local (function) scope + // also, phy_nr_slot_indication() is only executed by one thread, serially + static NR_Sched_Rsp_t sched_response; + NR_IF_Module_t *ifi = RC.nrmac[0]->if_inst; + ifi->NR_slot_indication(ind, &sched_response); + +#ifdef ENABLE_AERIAL + bool send_slt_resp = false; + if (sched_response.DL_req.dl_tti_request_body.nPDUs> 0) { + oai_fapi_dl_tti_req(&sched_response.DL_req); + send_slt_resp = true; + } + if (sched_response.UL_tti_req.n_pdus > 0) { + oai_fapi_ul_tti_req(&sched_response.UL_tti_req); + send_slt_resp = true; + } + if (sched_response.TX_req.Number_of_PDUs > 0) { + oai_fapi_tx_data_req(&sched_response.TX_req); + send_slt_resp = true; + } + if (sched_response.UL_dci_req.numPdus > 0) { + oai_fapi_ul_dci_req(&sched_response.UL_dci_req); + send_slt_resp = true; + } + if (send_slt_resp) { + oai_fapi_send_end_request(0, ind->sfn, ind->slot); + } +#else + if (sched_response.DL_req.dl_tti_request_body.nPDUs > 0) + oai_nfapi_dl_tti_req(&sched_response.DL_req); + + if (sched_response.UL_tti_req.n_pdus > 0) + oai_nfapi_ul_tti_req(&sched_response.UL_tti_req); + + if (sched_response.TX_req.Number_of_PDUs > 0) + oai_nfapi_tx_data_req(&sched_response.TX_req); + + if (sched_response.UL_dci_req.numPdus > 0) + oai_nfapi_ul_dci_req(&sched_response.UL_dci_req); +#endif + + /* the below works because the function behind the callback collects + * messages from queue into which messages have been copied. + * TODO we should have different callbacks for received messages and call + * into the scheduler separately for each message instead of one big one. */ + NR_UL_IND_t ul_ind = {.frame = ind->sfn, .slot = ind->slot, }; + ifi->NR_UL_indication(&ul_ind); return 1; } @@ -1305,7 +1215,7 @@ void *configure_nr_p7_vnf(void *ptr) p7_vnf->config->port = p7_vnf->local_port; #ifndef ENABLE_AERIAL p7_vnf->config->sync_indication = &phy_sync_indication; - p7_vnf->config->slot_indication = &phy_slot_indication; + p7_vnf->config->slot_indication = NULL; p7_vnf->config->harq_indication = &phy_harq_indication; #endif p7_vnf->config->nr_crc_indication = &phy_nr_crc_indication; @@ -1367,7 +1277,7 @@ void *vnf_p7_thread_start(void *ptr) { p7_vnf->config->port = p7_vnf->local_port; p7_vnf->config->sync_indication = &phy_sync_indication; p7_vnf->config->subframe_indication = &phy_subframe_indication; - p7_vnf->config->slot_indication = &phy_slot_indication; + p7_vnf->config->slot_indication = NULL; p7_vnf->config->harq_indication = &phy_harq_indication; p7_vnf->config->crc_indication = &phy_crc_indication; diff --git a/nfapi/open-nFAPI/pnf/inc/pnf_p7.h b/nfapi/open-nFAPI/pnf/inc/pnf_p7.h index 5805e07445..3040d9de09 100644 --- a/nfapi/open-nFAPI/pnf/inc/pnf_p7.h +++ b/nfapi/open-nFAPI/pnf/inc/pnf_p7.h @@ -145,8 +145,14 @@ int pnf_nr_p7_message_pump(pnf_p7_t* pnf_p7); int pnf_p7_pack_and_send_p7_message(pnf_p7_t* pnf_p7, nfapi_p7_message_header_t* msg, uint32_t msg_len); int pnf_p7_send_message(pnf_p7_t* pnf_p7, uint8_t* msg, uint32_t msg_len); - -int pnf_p7_slot_ind(pnf_p7_t* config, uint16_t phy_id, uint16_t sfn, uint16_t slot); +int nr_pnf_p7_get_msgs(pnf_p7_t* pnf_p7, + uint16_t phy_id, + uint16_t sfn, + uint16_t slot, + nfapi_nr_dl_tti_request_t* ret_dl_tti, + nfapi_nr_ul_tti_request_t* ret_ul_tti, + nfapi_nr_ul_dci_request_t* ret_ul_dci, + nfapi_nr_tx_data_request_t* ret_tx_data); int pnf_p7_subframe_ind(pnf_p7_t* config, uint16_t phy_id, uint16_t sfn_sf); int nfapi_pnf_p7_nr_slot_ind(nfapi_pnf_p7_config_t* config, nfapi_nr_slot_indication_scf_t* ind); int nfapi_pnf_p7_nr_rx_data_ind(nfapi_pnf_p7_config_t* config, nfapi_nr_rx_data_indication_t* ind); diff --git a/nfapi/open-nFAPI/pnf/public_inc/nfapi_pnf_interface.h b/nfapi/open-nFAPI/pnf/public_inc/nfapi_pnf_interface.h index 957e032f69..6576f6406e 100644 --- a/nfapi/open-nFAPI/pnf/public_inc/nfapi_pnf_interface.h +++ b/nfapi/open-nFAPI/pnf/public_inc/nfapi_pnf_interface.h @@ -856,7 +856,7 @@ int nfapi_pnf_p7_start(nfapi_pnf_p7_config_t* config); */ int nfapi_pnf_p7_stop(nfapi_pnf_p7_config_t* config); -/*! NR Slot indication +/*! NR get stuff * message copied from nfapi_pnf_p7_subframe_ind * \param config A pointer to a PNF P7 config * \param phy_id The phy_id for the phy instance @@ -868,8 +868,14 @@ int nfapi_pnf_p7_stop(nfapi_pnf_p7_config_t* config); * * If messages are not in the subframe buffer, they dummy subframe messages will be sent */ -int nfapi_pnf_p7_slot_ind(nfapi_pnf_p7_config_t* config, uint16_t phy_id, uint16_t sfn, uint16_t slot); - +int nfapi_pnf_p7_get_msgs(nfapi_pnf_p7_config_t* config, + uint16_t phy_id, + uint16_t sfn, + uint16_t slot, + nfapi_nr_dl_tti_request_t* ret_dl_tti, + nfapi_nr_ul_tti_request_t* ret_ul_tti, + nfapi_nr_ul_dci_request_t* ret_ul_dci, + nfapi_nr_tx_data_request_t* ret_tx_data); /*! Subframe indication * \param config A pointer to a PNF P7 config diff --git a/nfapi/open-nFAPI/pnf/src/pnf_p7.c b/nfapi/open-nFAPI/pnf/src/pnf_p7.c index e2b6d253d2..197bac22b7 100644 --- a/nfapi/open-nFAPI/pnf/src/pnf_p7.c +++ b/nfapi/open-nFAPI/pnf/src/pnf_p7.c @@ -672,145 +672,157 @@ void send_dummy_subframe(pnf_p7_t* pnf_p7, uint16_t sfn_sf) } } +int nr_pnf_p7_get_msgs(pnf_p7_t* pnf_p7, + uint16_t phy_id, + uint16_t sfn, + uint16_t slot, + nfapi_nr_dl_tti_request_t* ret_dl_tti, + nfapi_nr_ul_tti_request_t* ret_ul_tti, + nfapi_nr_ul_dci_request_t* ret_ul_dci, + nfapi_nr_tx_data_request_t* ret_tx_data) +{ + if (pthread_mutex_lock(&(pnf_p7->mutex)) != 0) { + NFAPI_TRACE(NFAPI_TRACE_INFO, "failed to lock mutex\n"); + return -1; + } -int pnf_p7_slot_ind(pnf_p7_t* pnf_p7, uint16_t phy_id, uint16_t sfn, uint16_t slot) -{ - //This function is aligned with rx sfn/slot + // save the curren time, sfn and slot + // TODO useful? + pnf_p7->slot_start_time_hr = pnf_get_current_time_hr(); - // We could either send an event to the p7 thread have have it run the - // subframe or we could handle it here and lock access to the subframe - // buffers. If we do it on the p7 thread then we run the risk of blocking - // on the udp send. - - // todo : consider a more efficent lock mechasium - //uint16_t NUM_SLOTS = 20;//10* 2^mu - - if(pthread_mutex_lock(&(pnf_p7->mutex)) != 0) - { - NFAPI_TRACE(NFAPI_TRACE_INFO, "failed to lock mutex\n"); - return -1; - } + // We align the pnf_p7 sfn/slot with tx sfn/slot, and vnf is synced with pnf_p7 sfn/slot. This is so that the scheduler runs + // slot_ahead from rx thread. + pnf_p7->sfn = sfn; + pnf_p7->slot = slot; - // save the curren time, sfn and slot - pnf_p7->slot_start_time_hr = pnf_get_current_time_hr(); + uint32_t tx_slot_dec = NFAPI_SFNSLOT2DEC(pnf_p7->mu, sfn, slot); + uint8_t buffer_index_tx = tx_slot_dec % NFAPI_SLOTNUM(pnf_p7->mu); - //We align the pnf_p7 sfn/slot with tx sfn/slot, and vnf is synced with pnf_p7 sfn/slot. This is so that the scheduler runs slot_ahead from rx thread. + // If the subframe_buffer has been configured + if (pnf_p7->_public.slot_buffer_size != 0) // for now value is same as sf_buffer_size + { + // apply the shift to the incoming sfn_sf + if (pnf_p7->slot_shift != 0) // see in vnf_build_send_dl_node_sync + { + uint16_t shifted_slot = slot + pnf_p7->slot_shift; - pnf_p7->sfn = sfn; - pnf_p7->slot = slot; + // adjust for wrap-around + if (shifted_slot < 0) + shifted_slot += NFAPI_MAX_SFNSLOTDEC(pnf_p7->mu); + else if (shifted_slot > NFAPI_MAX_SFNSLOTDEC(pnf_p7->mu)) + shifted_slot -= NFAPI_MAX_SFNSLOTDEC(pnf_p7->mu); - uint32_t tx_slot_dec = NFAPI_SFNSLOT2DEC(pnf_p7->mu, sfn,slot); - uint8_t buffer_index_tx = tx_slot_dec % NFAPI_SLOTNUM(pnf_p7->mu); + //NFAPI_TRACE(NFAPI_TRACE_INFO, "Applying shift %d to sfn/slot (%d -> %d)\n", pnf_p7->sfn_slot_shift, + //NFAPI_SFNSF2DEC(sfn_slot), shifted_sfn_slot); + slot = shifted_slot; - // If the subframe_buffer has been configured - if(pnf_p7->_public.slot_buffer_size!= 0) // for now value is same as sf_buffer_size - { + // + // why does the shift not apply to pnf_p7->sfn_sf??? + // - // apply the shift to the incoming sfn_sf - if(pnf_p7->slot_shift != 0) // see in vnf_build_send_dl_node_sync - { - uint16_t shifted_slot = slot + pnf_p7->slot_shift; + pnf_p7->slot_shift = 0; + } - // adjust for wrap-around - if(shifted_slot < 0) - shifted_slot += NFAPI_MAX_SFNSLOTDEC(pnf_p7->mu); - else if(shifted_slot > NFAPI_MAX_SFNSLOTDEC(pnf_p7->mu)) - shifted_slot -= NFAPI_MAX_SFNSLOTDEC(pnf_p7->mu); - - // NFAPI_TRACE(NFAPI_TRACE_INFO, "Applying shift %d to sfn/slot (%d -> %d)\n", pnf_p7->sfn_slot_shift, NFAPI_SFNSF2DEC(sfn_slot), shifted_sfn_slot); - slot = shifted_slot; - - // - // why does the shift not apply to pnf_p7->sfn_sf??? - // - - pnf_p7->slot_shift = 0; - } - - nfapi_pnf_p7_slot_buffer_t* tx_slot_buffer = &(pnf_p7->slot_buffer[buffer_index_tx]); + nfapi_pnf_p7_slot_buffer_t* tx_slot_buffer = &(pnf_p7->slot_buffer[buffer_index_tx]); + ret_dl_tti->SFN = sfn; + ret_dl_tti->Slot = slot; + ret_dl_tti->dl_tti_request_body.nPDUs = 0; + ret_tx_data->SFN = sfn; + ret_tx_data->Slot = slot; + ret_tx_data->Number_of_PDUs = 0; nfapi_nr_dl_tti_request_t* dl_tti_req = &tx_slot_buffer->dl_tti_req; - nfapi_nr_tx_data_request_t* tx_data_req = &tx_slot_buffer->tx_data_req; - if (dl_tti_req->dl_tti_request_body.nPDUs > 0 && dl_tti_req->SFN == sfn && dl_tti_req->Slot == slot) { - DevAssert(pnf_p7->_public.dl_tti_req_fn != NULL); - DevAssert(pnf_p7->_public.tx_data_req_fn != NULL); - if (tx_data_req->Number_of_PDUs > 0 && tx_data_req->SFN == sfn && tx_data_req->Slot == slot) { - (pnf_p7->_public.dl_tti_req_fn)(NULL, &(pnf_p7->_public), dl_tti_req); - (pnf_p7->_public.tx_data_req_fn)(&(pnf_p7->_public), tx_data_req); - } else { - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%4d.%2d no corresponding tx_data.request for dl_tti.request, dropping\n", sfn, slot); + nfapi_nr_tx_data_request_t* txd = &tx_slot_buffer->tx_data_req; + if (dl_tti_req->SFN == sfn && dl_tti_req->Slot == slot && txd->SFN == sfn && txd->Slot == slot) { + nfapi_nr_dl_tti_request_body_t* p_tti = &dl_tti_req->dl_tti_request_body; + int ret_idx = 0; + for (int i = 0; i < p_tti->nPDUs; ++i) { + int tx_index = p_tti->dl_tti_pdu_list[i].pdsch_pdu.pdsch_pdu_rel15.pduIndex - 1; + if (tx_index >= txd->Number_of_PDUs) { + NFAPI_TRACE(NFAPI_TRACE_ERROR, + "%4d.%2d no corresponding tx_data.request for dl_tti.request index %d, dropping\n", + sfn, + slot, + tx_index); + continue; + } + ret_dl_tti->dl_tti_request_body.dl_tti_pdu_list[ret_idx] = p_tti->dl_tti_pdu_list[i]; + // TODO avoid huge copy + ret_tx_data->pdu_list[ret_idx] = txd->pdu_list[i]; + ret_idx++; } + ret_dl_tti->dl_tti_request_body.nPDUs = ret_idx; + ret_tx_data->Number_of_PDUs = ret_idx; + tx_slot_buffer->dl_tti_req.SFN = -1; tx_slot_buffer->dl_tti_req.Slot = -1; tx_slot_buffer->tx_data_req.SFN = -1; tx_slot_buffer->tx_data_req.Slot = -1; } - if (tx_data_req->Number_of_PDUs > 0 && tx_data_req->SFN == sfn && tx_data_req->Slot == slot) { - // there is a tx_data.request in this slot, but no corresponding - // dl_tti.request (when they need to come pairwise) - NFAPI_TRACE(NFAPI_TRACE_ERROR, "%4d.%2d no corresponding dl_tti.request for tx_data.request, dropping\n", sfn, slot); - tx_slot_buffer->tx_data_req.SFN = -1; - tx_slot_buffer->tx_data_req.Slot = -1; - } - if(tx_slot_buffer->ul_tti_req.n_pdus > 0 && tx_slot_buffer->ul_tti_req.SFN == sfn && tx_slot_buffer->ul_tti_req.Slot == slot) - { - DevAssert(pnf_p7->_public.ul_tti_req_fn != NULL); - (pnf_p7->_public.ul_tti_req_fn)(NULL, &(pnf_p7->_public), &tx_slot_buffer->ul_tti_req); + ret_ul_tti->SFN = sfn; + ret_ul_tti->Slot = slot; + ret_ul_tti->n_pdus = 0; + if (tx_slot_buffer->ul_tti_req.SFN == sfn && tx_slot_buffer->ul_tti_req.Slot == slot) { + nfapi_nr_ul_tti_request_t* p = &tx_slot_buffer->ul_tti_req; + ret_ul_tti->n_pdus = p->n_pdus; + for (int i = 0; i < p->n_pdus; ++i) + ret_ul_tti->pdus_list[i] = p->pdus_list[i]; tx_slot_buffer->ul_tti_req.SFN = -1; tx_slot_buffer->ul_tti_req.Slot = -1; - } + } - if(tx_slot_buffer->ul_dci_req.numPdus > 0 && tx_slot_buffer->ul_dci_req.SFN == sfn && tx_slot_buffer->ul_dci_req.Slot == slot) - { - DevAssert(pnf_p7->_public.ul_dci_req_fn != NULL); - (pnf_p7->_public.ul_dci_req_fn)(NULL, &(pnf_p7->_public), &tx_slot_buffer->ul_dci_req); + ret_ul_dci->SFN = sfn; + ret_ul_dci->Slot = slot; + ret_ul_dci->numPdus = 0; + if (tx_slot_buffer->ul_dci_req.SFN == sfn && tx_slot_buffer->ul_dci_req.Slot == slot) { + nfapi_nr_ul_dci_request_t* p = &tx_slot_buffer->ul_dci_req; + ret_ul_dci->numPdus = p->numPdus; + for (int i = 0; i < p->numPdus; ++i) + ret_ul_dci->ul_dci_pdu_list[i] = p->ul_dci_pdu_list[i]; tx_slot_buffer->ul_dci_req.SFN = -1; tx_slot_buffer->ul_dci_req.Slot = -1; - } + } - //send the periodic timing info if configured - if(pnf_p7->_public.timing_info_mode_periodic && (pnf_p7->timing_info_period_counter++) == pnf_p7->_public.timing_info_period) - { - pnf_nr_pack_and_send_timing_info(pnf_p7); + // send the periodic timing info if configured + if (pnf_p7->_public.timing_info_mode_periodic && (pnf_p7->timing_info_period_counter++) == pnf_p7->_public.timing_info_period) { + pnf_nr_pack_and_send_timing_info(pnf_p7); - pnf_p7->timing_info_period_counter = 0; - } - else if(pnf_p7->_public.timing_info_mode_aperiodic && pnf_p7->timing_info_aperiodic_send) - { - pnf_nr_pack_and_send_timing_info(pnf_p7); + pnf_p7->timing_info_period_counter = 0; + } else if (pnf_p7->_public.timing_info_mode_aperiodic && pnf_p7->timing_info_aperiodic_send) { + pnf_nr_pack_and_send_timing_info(pnf_p7); - pnf_p7->timing_info_aperiodic_send = 0; - } - else - { - pnf_p7->timing_info_ms_counter++; - } - - } + pnf_p7->timing_info_aperiodic_send = 0; + } else { + pnf_p7->timing_info_ms_counter++; + } + } if (sfn % 128 == 0 && slot == 0) { pnf_p7_nr_stats_t* s = &pnf_p7->nr_stats; int ontime = s->dl_tti.ontime + s->ul_tti.ontime + s->ul_dci.ontime + s->tx_data.ontime; int late = s->dl_tti.late + s->ul_tti.late + s->ul_dci.late + s->tx_data.late; - float dl_thr = (float) s->dl.bytes * 8 / 1000 / 1000 / 1.28f; // every 128 frames = 1.28 s - float ul_thr = (float) s->ul.bytes * 8 / 1000 / 1000 / 1.28f; - NFAPI_TRACE(NFAPI_TRACE_INFO, "[P7:%d] msgs ontime %d thr DL %.2f UL %.2f msg late %d (vtime)\n", pnf_p7->_public.phy_id, ontime, dl_thr, ul_thr, late); + float dl_thr = (float)s->dl.bytes * 8 / 1000 / 1000 / 1.28f; // every 128 frames = 1.28 s + float ul_thr = (float)s->ul.bytes * 8 / 1000 / 1000 / 1.28f; + NFAPI_TRACE(NFAPI_TRACE_INFO, + "[P7:%d] msgs ontime %d thr DL %.2f UL %.2f msg late %d (vtime)\n", + pnf_p7->_public.phy_id, + ontime, + dl_thr, + ul_thr, + late); memset(s, 0, sizeof(*s)); } - if(pthread_mutex_unlock(&(pnf_p7->mutex)) != 0) - { - NFAPI_TRACE(NFAPI_TRACE_INFO, "failed to unlock mutex\n"); - return -1; - } + if (pthread_mutex_unlock(&(pnf_p7->mutex)) != 0) { + NFAPI_TRACE(NFAPI_TRACE_INFO, "failed to unlock mutex\n"); + return -1; + } - return 0; + return 0; } - - int pnf_p7_subframe_ind(pnf_p7_t* pnf_p7, uint16_t phy_id, uint16_t sfn_sf) { // We could either send an event to the p7 thread have have it run the diff --git a/nfapi/open-nFAPI/pnf/src/pnf_p7_interface.c b/nfapi/open-nFAPI/pnf/src/pnf_p7_interface.c index b021e67fc9..af02ef7a4e 100644 --- a/nfapi/open-nFAPI/pnf/src/pnf_p7_interface.c +++ b/nfapi/open-nFAPI/pnf/src/pnf_p7_interface.c @@ -89,15 +89,22 @@ int nfapi_pnf_p7_stop(nfapi_pnf_p7_config_t* config) return 0; } -int nfapi_pnf_p7_slot_ind(nfapi_pnf_p7_config_t* config, uint16_t phy_id, uint16_t sfn, uint16_t slot) +int nfapi_pnf_p7_get_msgs(nfapi_pnf_p7_config_t* config, + uint16_t phy_id, + uint16_t sfn, + uint16_t slot, + nfapi_nr_dl_tti_request_t* ret_dl_tti, + nfapi_nr_ul_tti_request_t* ret_ul_tti, + nfapi_nr_ul_dci_request_t* ret_ul_dci, + nfapi_nr_tx_data_request_t* ret_tx_data) { - // Verify that config is not null - if(config == 0) - return -1; - - pnf_p7_t* _this = (pnf_p7_t*)(config); + // Verify that config is not null + if (config == 0) + return -1; - return pnf_p7_slot_ind(_this, phy_id, sfn, slot); + pnf_p7_t* _this = (pnf_p7_t*)(config); + + return nr_pnf_p7_get_msgs(_this, phy_id, sfn, slot, ret_dl_tti, ret_ul_tti, ret_ul_dci, ret_tx_data); } int nfapi_pnf_p7_subframe_ind(nfapi_pnf_p7_config_t* config, uint16_t phy_id, uint16_t sfn_sf) diff --git a/nfapi/open-nFAPI/pnf/tests/pnf_cunit_main.c b/nfapi/open-nFAPI/pnf/tests/pnf_cunit_main.c index bd6bedbea5..3460d4d9d7 100644 --- a/nfapi/open-nFAPI/pnf/tests/pnf_cunit_main.c +++ b/nfapi/open-nFAPI/pnf/tests/pnf_cunit_main.c @@ -1210,12 +1210,6 @@ void send_dl_subframe_msgs_interleaved(int p7Sock, int phy_id, struct sockaddr_i //free(req.tx_request_body.tx_pdu_list); } -void send_slot_indication(phy_info_t* phy_info) -{ - // DONE: add sfn and slot as members in the phy_info - nfapi_pnf_p7_slot_ind(phy_info->config, phy_info->phy_id, phy_info->sfn, phy_info->slot); -} - void send_subframe_indication(phy_info_t* phy_info) { nfapi_pnf_p7_subframe_ind(phy_info->config, phy_info->phy_id, phy_info->sfn_sf); diff --git a/openair1/PHY/CODING/nrLDPC_coding/nrLDPC_coding_segment/nrLDPC_coding_segment_decoder.c b/openair1/PHY/CODING/nrLDPC_coding/nrLDPC_coding_segment/nrLDPC_coding_segment_decoder.c index 3fece46ac8..374ecb4b19 100644 --- a/openair1/PHY/CODING/nrLDPC_coding/nrLDPC_coding_segment/nrLDPC_coding_segment_decoder.c +++ b/openair1/PHY/CODING/nrLDPC_coding/nrLDPC_coding_segment/nrLDPC_coding_segment_decoder.c @@ -36,7 +36,6 @@ #include "PHY/NR_TRANSPORT/nr_ulsch.h" #include "PHY/NR_TRANSPORT/nr_dlsch.h" #include "SCHED_NR/sched_nr.h" -#include "SCHED_NR/fapi_nr_l1.h" #include "defs.h" #include "common/utils/LOG/vcd_signal_dumper.h" #include "common/utils/LOG/log.h" diff --git a/openair1/PHY/CODING/nrLDPC_coding/nrLDPC_coding_xdma/nrLDPC_coding_xdma.c b/openair1/PHY/CODING/nrLDPC_coding/nrLDPC_coding_xdma/nrLDPC_coding_xdma.c index b23db3781d..1d9aa53d25 100644 --- a/openair1/PHY/CODING/nrLDPC_coding/nrLDPC_coding_xdma/nrLDPC_coding_xdma.c +++ b/openair1/PHY/CODING/nrLDPC_coding/nrLDPC_coding_xdma/nrLDPC_coding_xdma.c @@ -38,7 +38,6 @@ #include "PHY/NR_TRANSPORT/nr_transport_proto.h" #include "PHY/NR_TRANSPORT/nr_ulsch.h" #include "PHY/defs_gNB.h" -#include "SCHED_NR/fapi_nr_l1.h" #include "SCHED_NR/sched_nr.h" #include "common/utils/LOG/log.h" #include "common/utils/LOG/vcd_signal_dumper.h" diff --git a/openair1/PHY/INIT/nr_init.c b/openair1/PHY/INIT/nr_init.c index 7a360e30ff..58ad0f2449 100644 --- a/openair1/PHY/INIT/nr_init.c +++ b/openair1/PHY/INIT/nr_init.c @@ -39,11 +39,13 @@ #include #include "PHY/NR_TRANSPORT/nr_ulsch.h" #include "PHY/NR_REFSIG/nr_refsig.h" -#include "SCHED_NR/fapi_nr_l1.h" #include "PHY/NR_REFSIG/ul_ref_seq_nr.h" #include #include "nfapi/open-nFAPI/fapi/inc/nr_fapi_p5_utils.h" +static void init_DLSCH_struct(PHY_VARS_gNB *gNB); +static void destroy_DLSCH_struct(const PHY_VARS_gNB *gNB); + int l1_north_init_gNB() { AssertFatal(RC.nb_nr_L1_inst > 0, "Failed to init PHY callbacks: nb_nr_L1_inst = %d\n", RC.nb_nr_L1_inst); @@ -58,7 +60,6 @@ int l1_north_init_gNB() LOG_D(NR_PHY, "RC.gNB[%d]: installing callbacks\n", i); RC.gNB[i]->if_inst->NR_PHY_config_req = nr_phy_config_request; - RC.gNB[i]->if_inst->NR_Schedule_response = nr_schedule_response; } return 0; @@ -155,6 +156,8 @@ void phy_init_nr_gNB(PHY_VARS_gNB *gNB) /// Transport init necessary for NR synchro init_nr_transport(gNB); + init_DLSCH_struct(gNB); + gNB->nr_srs_info = (nr_srs_info_t **)malloc16_clear(gNB->max_nb_srs * sizeof(nr_srs_info_t*)); for (int id = 0; id < gNB->max_nb_srs; id++) { gNB->nr_srs_info[id] = (nr_srs_info_t *)malloc16_clear(sizeof(nr_srs_info_t)); @@ -241,6 +244,8 @@ void phy_free_nr_gNB(PHY_VARS_gNB *gNB) reset_nr_transport(gNB); + destroy_DLSCH_struct(gNB); + NR_gNB_COMMON * common_vars = &gNB->common_vars; for (int j = 0; j < common_vars->num_beams_period; j++) { if (common_vars->beam_id) @@ -281,13 +286,6 @@ void phy_free_nr_gNB(PHY_VARS_gNB *gNB) } -//Adding nr_schedule_handler -void install_nr_schedule_handlers(NR_IF_Module_t *if_inst) -{ - if_inst->NR_PHY_config_req = nr_phy_config_request; - if_inst->NR_Schedule_response = nr_schedule_response; -} - void nr_phy_config_request_sim(PHY_VARS_gNB *gNB, int N_RB_DL, int N_RB_UL, @@ -366,7 +364,7 @@ void nr_phy_config_request(NR_PHY_Config_t *phy_config) fp->ul_CarrierFreq = ((ul_bw_khz>>1) + gNB_config->carrier_config.uplink_frequency.value)*1000 ; int32_t dlul_offset = fp->ul_CarrierFreq - fp->dl_CarrierFreq; - fp->nr_band = get_band(fp->dl_CarrierFreq, dlul_offset); + fp->nr_band = get_band(fp->dl_CarrierFreq, dlul_offset, dl_bw_khz, ul_bw_khz); LOG_I(PHY, "DL frequency %lu Hz, UL frequency %lu Hz: band %d, uldl offset %d Hz\n", fp->dl_CarrierFreq, fp->ul_CarrierFreq, fp->nr_band, dlul_offset); @@ -401,37 +399,27 @@ void nr_phy_config_request(NR_PHY_Config_t *phy_config) init_timeshift_rotation(fp); } -void init_DLSCH_struct(PHY_VARS_gNB *gNB, processingData_L1tx_t *msg) +static void init_DLSCH_struct(PHY_VARS_gNB *gNB) { 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; + gNB->dlsch = calloc(gNB->max_nb_pdsch, sizeof(*gNB->dlsch)); for (int i = 0; i < gNB->max_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); - } + gNB->dlsch[i] = new_gNB_dlsch(fp, grid_size); } } -void reset_DLSCH_struct(const PHY_VARS_gNB *gNB, processingData_L1tx_t *msg) +static void destroy_DLSCH_struct(const PHY_VARS_gNB *gNB) { const NR_DL_FRAME_PARMS *fp = &gNB->frame_parms; 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 < gNB->max_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_gNB_dlsch(&gNB->dlsch[i], grid_size, fp); } - free(msg->dlsch); + free(gNB->dlsch); } void init_nr_transport(PHY_VARS_gNB *gNB) diff --git a/openair1/PHY/INIT/nr_parms.c b/openair1/PHY/INIT/nr_parms.c index 2ace21eab5..cc31dc173a 100644 --- a/openair1/PHY/INIT/nr_parms.c +++ b/openair1/PHY/INIT/nr_parms.c @@ -379,15 +379,13 @@ int nr_init_frame_parms_ue(NR_DL_FRAME_PARMS *fp, fp->N_RB_SL = config->carrier_config.sl_grid_size[fp->numerology_index]; fp->frame_type = get_frame_type(fp->nr_band, fp->numerology_index); - int32_t uplink_frequency_offset = get_delta_duplex(fp->nr_band, fp->numerology_index); + int64_t uplink_frequency_offset = fp->ul_CarrierFreq - fp->dl_CarrierFreq; uplink_frequency_offset *= 1000; - LOG_I(PHY, "Initializing frame parms: DL frequency %lu Hz, UL frequency %lu Hz: band %d, uldl offset %d Hz\n", fp->dl_CarrierFreq, fp->ul_CarrierFreq, fp->nr_band, uplink_frequency_offset); + LOG_I(PHY, "Initializing frame parms: DL frequency %lu Hz, UL frequency %lu Hz: band %d, uldl offset %ld Hz\n", fp->dl_CarrierFreq, fp->ul_CarrierFreq, fp->nr_band, uplink_frequency_offset); AssertFatal(fp->frame_type==config->cell_config.frame_duplex_type, "Invalid duplex type (frame_type %d,cell_config.frame_duplex_type %d) in config request file for band %d\n", fp->frame_type,config->cell_config.frame_duplex_type,fp->nr_band); - AssertFatal(fp->ul_CarrierFreq == (fp->dl_CarrierFreq + uplink_frequency_offset), "Disagreement in uplink frequency for band %d: ul_CarrierFreq = %lu Hz vs expected %lu Hz\n", fp->nr_band, fp->ul_CarrierFreq, fp->dl_CarrierFreq + uplink_frequency_offset); - LOG_I(PHY,"Initializing frame parms for mu %d, N_RB %d, Ncp %d\n",fp->numerology_index, fp->N_RB_DL, Ncp); @@ -508,7 +506,7 @@ int nr_init_frame_parms_ue_sl(NR_DL_FRAME_PARMS *fp, fp->ofdm_offset_divisor = ofdm_offset_divisor; fp->threequarter_fs = threequarter_fs; - fp->nr_band = get_band(config->sl_carrier_config.sl_frequency, 0); + fp->nr_band = get_band(config->sl_carrier_config.sl_frequency, 0, 0, 0); fp->att_rx = 0; fp->att_tx = 0; @@ -522,8 +520,6 @@ int nr_init_frame_parms_ue_sl(NR_DL_FRAME_PARMS *fp, fp->Ncp = config->sl_bwp_config.sl_cyclic_prefix; fp->frame_type = get_frame_type(fp->nr_band, fp->numerology_index); - int32_t uplink_frequency_offset = get_delta_duplex(fp->nr_band, fp->numerology_index); - uplink_frequency_offset *= 1000; uint64_t bw_khz = (12 * config->sl_carrier_config.sl_grid_size) * (15 << config->sl_bwp_config.sl_scs); // REfer to section 3GPP spec 38.101 5.4E.2.1 @@ -539,20 +535,14 @@ int nr_init_frame_parms_ue_sl(NR_DL_FRAME_PARMS *fp, LOG_D(PHY, "CarrierFreq %lu Hz\n", fp->sl_CarrierFreq); LOG_I(PHY, - "Initializing frame parms: DL frequency %lu Hz, UL frequency %lu Hz SL frequency %lu Hz: band %d, uldl offset %d Hz\n", + "Initializing frame parms: DL frequency %lu Hz, UL frequency %lu Hz SL frequency %lu Hz: band %d\n", fp->dl_CarrierFreq, fp->ul_CarrierFreq, fp->sl_CarrierFreq, - fp->nr_band, - uplink_frequency_offset); + fp->nr_band); AssertFatal(fp->frame_type == TDD, "Sidelink bands only support TDD"); - AssertFatal(fp->ul_CarrierFreq == (fp->dl_CarrierFreq + uplink_frequency_offset), - "Disagreement in uplink frequency for band %d: ul_CarrierFreq = %lu Hz vs expected %lu Hz\n", - fp->nr_band, - fp->ul_CarrierFreq, - fp->dl_CarrierFreq + uplink_frequency_offset); LOG_I(PHY, "Initializing frame parms for mu %d, N_RB %d, Ncp %d\n", fp->numerology_index, fp->N_RB_DL, fp->Ncp); diff --git a/openair1/PHY/INIT/nr_phy_init.h b/openair1/PHY/INIT/nr_phy_init.h index 1b1a0fa1b0..f556498f0f 100644 --- a/openair1/PHY/INIT/nr_phy_init.h +++ b/openair1/PHY/INIT/nr_phy_init.h @@ -46,9 +46,6 @@ int l1_north_init_gNB(void); void init_nr_transport(PHY_VARS_gNB *gNB); void reset_nr_transport(PHY_VARS_gNB *gNB); -void init_DLSCH_struct(PHY_VARS_gNB *gNB, processingData_L1tx_t *msg); -void reset_DLSCH_struct(const PHY_VARS_gNB *gNB, processingData_L1tx_t *msg); - void RCconfig_nrUE_prs(void *cfg); void init_nr_prs_ue_vars(PHY_VARS_NR_UE *ue); void nr_init_dl_harq_processes(NR_DL_UE_HARQ_t harq_list[2][NR_MAX_DLSCH_HARQ_PROCESSES], int number_of_processes, int num_rb); diff --git a/openair1/PHY/NR_TRANSPORT/nr_dci.c b/openair1/PHY/NR_TRANSPORT/nr_dci.c index 0548c8fc10..2df2df8eb0 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_dci.c +++ b/openair1/PHY/NR_TRANSPORT/nr_dci.c @@ -51,11 +51,11 @@ static void nr_pdcch_scrambling(uint32_t *in, uint32_t size, uint32_t Nid, uint3 out[i] = in[i] ^ seq[i]; } -static void nr_generate_dci(PHY_VARS_gNB *gNB, - nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu_rel15, - int txdataF_offset, - NR_DL_FRAME_PARMS *frame_parms, - int slot) +void nr_generate_dci(PHY_VARS_gNB *gNB, + const nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu_rel15, + int txdataF_offset, + NR_DL_FRAME_PARMS *frame_parms, + int slot) { // fill reg list per symbol int reg_list[MAX_DCI_CORESET][NR_MAX_PDCCH_AGG_LEVEL * NR_NB_REG_PER_CCE]; @@ -237,16 +237,3 @@ static void nr_generate_dci(PHY_VARS_gNB *gNB, *(unsigned long long *)dci_pdu->Payload); } // for (int d=0;dnumDlDci;d++) } - -void nr_generate_dci_top(processingData_L1tx_t *msgTx, int slot, int txdataF_offset) -{ - PHY_VARS_gNB *gNB = msgTx->gNB; - NR_DL_FRAME_PARMS *frame_parms = &gNB->frame_parms; - start_meas(&gNB->dci_generation_stats); - for (int i = 0; i < msgTx->num_ul_pdcch; i++) - nr_generate_dci(msgTx->gNB, &msgTx->ul_pdcch_pdu[i].pdcch_pdu.pdcch_pdu_rel15, txdataF_offset, frame_parms, slot); - for (int i = 0; i < msgTx->num_dl_pdcch; i++) - nr_generate_dci(msgTx->gNB, &msgTx->pdcch_pdu[i].pdcch_pdu_rel15, txdataF_offset, frame_parms, slot); - stop_meas(&gNB->dci_generation_stats); -} - diff --git a/openair1/PHY/NR_TRANSPORT/nr_dci.h b/openair1/PHY/NR_TRANSPORT/nr_dci.h index e735069975..57651f03a2 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_dci.h +++ b/openair1/PHY/NR_TRANSPORT/nr_dci.h @@ -26,7 +26,11 @@ #include "PHY/NR_REFSIG/nr_refsig.h" #include "nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface.h" -void nr_generate_dci_top(processingData_L1tx_t *msgTx, int slot, int txdataF_offset); +void nr_generate_dci(PHY_VARS_gNB *gNB, + const nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu_rel15, + int txdataF_offset, + NR_DL_FRAME_PARMS *frame_parms, + int slot); int16_t find_nr_pdcch(int frame,int slot, PHY_VARS_gNB *gNB,find_type_t type); @@ -42,6 +46,6 @@ void nr_fill_ul_dci(PHY_VARS_gNB *gNB, int slot, nfapi_nr_ul_dci_request_pdus_t *pdcch_pdu); -void nr_fill_reg_list(int cce_list[MAX_DCI_CORESET][NR_MAX_PDCCH_AGG_LEVEL * NR_NB_REG_PER_CCE], nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu_rel15); +void nr_fill_reg_list(int cce_list[MAX_DCI_CORESET][NR_MAX_PDCCH_AGG_LEVEL * NR_NB_REG_PER_CCE], const nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu_rel15); #endif //__PHY_NR_TRANSPORT_DCI__H diff --git a/openair1/PHY/NR_TRANSPORT/nr_dci_tools.c b/openair1/PHY/NR_TRANSPORT/nr_dci_tools.c index 538b54ac0b..c2d2ab7a24 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_dci_tools.c +++ b/openair1/PHY/NR_TRANSPORT/nr_dci_tools.c @@ -42,7 +42,7 @@ int compfunc(const void *a, const void *b) return (*(int *)a - *(int *)b); } -void nr_fill_reg_list(int reg_list[MAX_DCI_CORESET][NR_MAX_PDCCH_AGG_LEVEL * NR_NB_REG_PER_CCE], nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu_rel15) +void nr_fill_reg_list(int reg_list[MAX_DCI_CORESET][NR_MAX_PDCCH_AGG_LEVEL * NR_NB_REG_PER_CCE], const nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu_rel15) { int bsize = pdcch_pdu_rel15->RegBundleSize; int R = pdcch_pdu_rel15->InterleaverSize; diff --git a/openair1/PHY/NR_TRANSPORT/nr_dlsch.c b/openair1/PHY/NR_TRANSPORT/nr_dlsch.c index 535c68f419..8df7b4814c 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_dlsch.c +++ b/openair1/PHY/NR_TRANSPORT/nr_dlsch.c @@ -51,7 +51,7 @@ static void nr_pdsch_codeword_scrambling(uint8_t *in, uint32_t size, uint8_t q, nr_codeword_scrambling(in, size, q, Nid, n_RNTI, out); } -static int do_ptrs_symbol(nfapi_nr_dl_tti_pdsch_pdu_rel15_t *rel15, +static int do_ptrs_symbol(const nfapi_nr_dl_tti_pdsch_pdu_rel15_t *rel15, int start_sc, int symbol_sz, c16_t *txF, @@ -339,7 +339,7 @@ static inline void neg_dmrs(c16_t *in, c16_t *out, int sz) static inline int do_onelayer(NR_DL_FRAME_PARMS *frame_parms, int slot, - nfapi_nr_dl_tti_pdsch_pdu_rel15_t *rel15, + const nfapi_nr_dl_tti_pdsch_pdu_rel15_t *rel15, int layer, c16_t *output, c16_t *txl_start, @@ -457,7 +457,7 @@ static inline void do_txdataF(c16_t **txdataF, int symbol_sz, c16_t txdataF_precoding[][symbol_sz], PHY_VARS_gNB *gNB, - nfapi_nr_dl_tti_pdsch_pdu_rel15_t *rel15, + const nfapi_nr_dl_tti_pdsch_pdu_rel15_t *rel15, int ant, int start_sc, int txdataF_offset_per_symbol) @@ -465,7 +465,7 @@ static inline void do_txdataF(c16_t **txdataF, NR_DL_FRAME_PARMS *frame_parms = &gNB->frame_parms; int rb = 0; uint16_t subCarrier = start_sc; - nfapi_nr_tx_precoding_and_beamforming_t *pb = &rel15->precodingAndBeamforming; + const nfapi_nr_tx_precoding_and_beamforming_t *pb = &rel15->precodingAndBeamforming; while (rb < rel15->rbSize) { // get pmi info const int pmi = (pb->prg_size > 0) ? (pb->prgs_list[(int)rb / pb->prg_size].pm_idx) : 0; @@ -555,8 +555,7 @@ static int do_one_dlsch(unsigned char *input_ptr, PHY_VARS_gNB *gNB, NR_gNB_DLSC time_stats_t *dlsch_scrambling_stats = &gNB->dlsch_scrambling_stats; time_stats_t *dlsch_modulation_stats = &gNB->dlsch_modulation_stats; - NR_DL_gNB_HARQ_t *harq = &dlsch->harq_process; - nfapi_nr_dl_tti_pdsch_pdu_rel15_t *rel15 = &harq->pdsch_pdu.pdsch_pdu_rel15; + const nfapi_nr_dl_tti_pdsch_pdu_rel15_t *rel15 = &dlsch->pdsch_pdu->pdsch_pdu_rel15; const int layerSz = frame_parms->N_RB_DL * NR_SYMBOLS_PER_SLOT * NR_NB_SC_PER_RB; const int symbol_sz=frame_parms->ofdm_symbol_size; const int dmrs_Type = rel15->dmrsConfigType; @@ -580,7 +579,6 @@ static int do_one_dlsch(unsigned char *input_ptr, PHY_VARS_gNB *gNB, NR_gNB_DLSC /* PTRS */ uint16_t dlPtrsSymPos = 0; int n_ptrs = 0; - uint32_t ptrsSymbPerSlot = 0; if (rel15->pduBitmap & 0x1) { set_ptrs_symb_idx(&dlPtrsSymPos, rel15->NrOfSymbols, @@ -588,15 +586,13 @@ static int do_one_dlsch(unsigned char *input_ptr, PHY_VARS_gNB *gNB, NR_gNB_DLSC 1 << rel15->PTRSTimeDensity, rel15->dlDmrsSymbPos); n_ptrs = (rel15->rbSize + rel15->PTRSFreqDensity - 1) / rel15->PTRSFreqDensity; - ptrsSymbPerSlot = get_ptrs_symbols_in_slot(dlPtrsSymPos, rel15->StartSymbolIndex, rel15->NrOfSymbols); } - harq->unav_res = ptrsSymbPerSlot * n_ptrs; #ifdef DEBUG_DLSCH printf("PDSCH encoding:\nPayload:\n"); - for (int i = 0; i < (harq->B >> 3); i += 16) { + for (int i = 0; i < (dlsch->B >> 3); i += 16) { for (int j = 0; j < 16; j++) - printf("0x%02x\t", harq->pdu[i + j]); + printf("0x%02x\t", dlsch->pdu[i + j]); printf("\n"); } printf("\nEncoded payload:\n"); @@ -609,7 +605,7 @@ static int do_one_dlsch(unsigned char *input_ptr, PHY_VARS_gNB *gNB, NR_gNB_DLSC #endif if (IS_SOFTMODEM_DLSIM) - memcpy(harq->f, input_ptr, (encoded_length + 7) >> 3); + memcpy(dlsch->f, input_ptr, (encoded_length + 7) >> 3); c16_t mod_symbs[rel15->NrOfCodewords][encoded_length] __attribute__((aligned(64))); for (int codeWord = 0; codeWord < rel15->NrOfCodewords; codeWord++) { @@ -680,7 +676,7 @@ static int do_one_dlsch(unsigned char *input_ptr, PHY_VARS_gNB *gNB, NR_gNB_DLSC // pmi = prgs_list[rbidx/prg_size].pm_idx, rbidx =0,...,rbSize-1 // The Precoding matrix: // The Codebook Type I - nfapi_nr_tx_precoding_and_beamforming_t *pb = &rel15->precodingAndBeamforming; + const nfapi_nr_tx_precoding_and_beamforming_t *pb = &rel15->precodingAndBeamforming; // beam number in multi-beam scenario (concurrent beams) int bitmap = SL_to_bitmap(rel15->StartSymbolIndex, rel15->NrOfSymbols); int beam_nb = beam_index_allocation(gNB->enable_analog_das, @@ -777,9 +773,8 @@ static int do_one_dlsch(unsigned char *input_ptr, PHY_VARS_gNB *gNB, NR_gNB_DLSC return ((size_output_tb + 511) >> 9) << 6; } -void nr_generate_pdsch(processingData_L1tx_t *msgTx, int frame, int slot) +void nr_generate_pdsch(PHY_VARS_gNB *gNB, int n_dlsch, NR_gNB_DLSCH_t *dlsch_array, int frame, int slot) { - PHY_VARS_gNB *gNB = msgTx->gNB; NR_DL_FRAME_PARMS *frame_parms = &gNB->frame_parms; time_stats_t *dlsch_encoding_stats = &gNB->dlsch_encoding_stats; time_stats_t *tinput = &gNB->tinput; @@ -792,10 +787,9 @@ void nr_generate_pdsch(processingData_L1tx_t *msgTx, int frame, int slot) size_t size_output = 0; - for (int dlsch_id = 0; dlsch_id < msgTx->num_pdsch_slot; dlsch_id++) { - NR_gNB_DLSCH_t *dlsch = msgTx->dlsch[dlsch_id]; - NR_DL_gNB_HARQ_t *harq = &dlsch->harq_process; - nfapi_nr_dl_tti_pdsch_pdu_rel15_t *rel15 = &harq->pdsch_pdu.pdsch_pdu_rel15; + for (int i = 0; i < n_dlsch; i++) { + NR_gNB_DLSCH_t *dlsch = &dlsch_array[i]; + const nfapi_nr_dl_tti_pdsch_pdu_rel15_t *rel15 = &dlsch->pdsch_pdu->pdsch_pdu_rel15; LOG_D(PHY, "pdsch: BWPStart %d, BWPSize %d, rbStart %d, rbsize %d\n", @@ -819,10 +813,10 @@ void nr_generate_pdsch(processingData_L1tx_t *msgTx, int frame, int slot) n_ptrs = (rel15->rbSize + rel15->PTRSFreqDensity - 1) / rel15->PTRSFreqDensity; ptrsSymbPerSlot = get_ptrs_symbols_in_slot(dlPtrsSymPos, rel15->StartSymbolIndex, rel15->NrOfSymbols); } - harq->unav_res = ptrsSymbPerSlot * n_ptrs; + dlsch->unav_res = ptrsSymbPerSlot * n_ptrs; /// CRC, coding, interleaving and rate matching - AssertFatal(harq->pdu != NULL, "%4d.%2d no HARQ PDU for PDSCH generation\n", msgTx->frame, msgTx->slot); + AssertFatal(dlsch->pdu != NULL, "%4d.%2d no PDU for PDSCH generation\n", frame, slot); /* output and its parts for each dlsch should be aligned on 64 bytes (or 8 * 64 bits) * => size_output is a sum of parts sizes rounded up to a multiple of 8 * 64 @@ -836,7 +830,8 @@ void nr_generate_pdsch(processingData_L1tx_t *msgTx, int frame, int slot) start_meas(dlsch_encoding_stats); if (nr_dlsch_encoding(gNB, - msgTx, + n_dlsch, + dlsch_array, frame, slot, frame_parms, @@ -854,8 +849,8 @@ void nr_generate_pdsch(processingData_L1tx_t *msgTx, int frame, int slot) stop_meas(dlsch_encoding_stats); unsigned char *output_ptr = output; - for (int dlsch_id = 0; dlsch_id < msgTx->num_pdsch_slot; dlsch_id++) { - output_ptr += do_one_dlsch(output_ptr, gNB, msgTx->dlsch[dlsch_id], slot); + for (int i = 0; i < n_dlsch; i++) { + output_ptr += do_one_dlsch(output_ptr, gNB, &dlsch_array[i], slot); } } diff --git a/openair1/PHY/NR_TRANSPORT/nr_dlsch.h b/openair1/PHY/NR_TRANSPORT/nr_dlsch.h index 15f48825f5..0a82b2c47f 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_dlsch.h +++ b/openair1/PHY/NR_TRANSPORT/nr_dlsch.h @@ -35,15 +35,11 @@ #include "PHY/defs_gNB.h" -void nr_fill_dlsch_dl_tti_req(processingData_L1tx_t *msgTx, nfapi_nr_dl_tti_pdsch_pdu *pdsch_pdu); -void nr_fill_dlsch_tx_req(processingData_L1tx_t *msgTx, int idx, uint8_t *sdu); - -void nr_generate_pdsch(processingData_L1tx_t *msgTx, - int frame, - int slot); +void nr_generate_pdsch(PHY_VARS_gNB *gNB, int n_dlsch, NR_gNB_DLSCH_t *dlsch_array, int frame, int slot); int nr_dlsch_encoding(PHY_VARS_gNB *gNB, - processingData_L1tx_t *msgTx, + int n_dlsch, + NR_gNB_DLSCH_t *dlsch_array, int frame, uint8_t slot, NR_DL_FRAME_PARMS *frame_parms, diff --git a/openair1/PHY/NR_TRANSPORT/nr_dlsch_coding.c b/openair1/PHY/NR_TRANSPORT/nr_dlsch_coding.c index 56a849a4af..f74685ed71 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_dlsch_coding.c +++ b/openair1/PHY/NR_TRANSPORT/nr_dlsch_coding.c @@ -52,20 +52,19 @@ void free_gNB_dlsch(NR_gNB_DLSCH_t *dlsch, uint16_t N_RB, const NR_DL_FRAME_PARM a_segments = a_segments / 273 + 1; } - NR_DL_gNB_HARQ_t *harq = &dlsch->harq_process; - if (harq->b) { - free16(harq->b, a_segments * 1056); - harq->b = NULL; + if (dlsch->b) { + free16(dlsch->b, a_segments * 1056); + dlsch->b = NULL; } - if (harq->f) { - free16(harq->f, N_RB * NR_SYMBOLS_PER_SLOT * NR_NB_SC_PER_RB * 8 * NR_MAX_NB_LAYERS); - harq->f = NULL; + if (dlsch->f) { + free16(dlsch->f, N_RB * NR_SYMBOLS_PER_SLOT * NR_NB_SC_PER_RB * 8 * NR_MAX_NB_LAYERS); + dlsch->f = NULL; } for (int r = 0; r < a_segments; r++) { - free(harq->c[r]); - harq->c[r] = NULL; + free(dlsch->c[r]); + dlsch->c[r] = NULL; } - free(harq->c); + free(dlsch->c); } NR_gNB_DLSCH_t new_gNB_dlsch(NR_DL_FRAME_PARMS *frame_parms, uint16_t N_RB) @@ -80,34 +79,33 @@ NR_gNB_DLSCH_t new_gNB_dlsch(NR_DL_FRAME_PARMS *frame_parms, uint16_t N_RB) 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; + NR_gNB_DLSCH_t dlsch = {0}; - NR_DL_gNB_HARQ_t *harq = &dlsch.harq_process; - bzero(harq, sizeof(NR_DL_gNB_HARQ_t)); - harq->b = malloc16(dlsch_bytes); - AssertFatal(harq->b, "cannot allocate memory for harq->b\n"); - bzero(harq->b, dlsch_bytes); + dlsch.b = malloc16(dlsch_bytes); + AssertFatal(dlsch.b, "cannot allocate memory for dlsch.b\n"); + bzero(dlsch.b, dlsch_bytes); - harq->c = (uint8_t **)malloc16(a_segments * sizeof(uint8_t *)); + dlsch.c = (uint8_t **)malloc16(a_segments * sizeof(uint8_t *)); for (int r = 0; r < a_segments; r++) { // account for filler in first segment and CRCs for multiple segment case // [hna] 8448 is the maximum CB size in NR // 68*348 = 68*(maximum size of Zc) // In section 5.3.2 in 38.212, the for loop is up to N + 2*Zc (maximum size of N is 66*Zc, therefore 68*Zc) - harq->c[r] = malloc16(8448); - AssertFatal(harq->c[r], "cannot allocate harq->c[%d]\n", r); - bzero(harq->c[r], 8448); + dlsch.c[r] = malloc16(8448); + AssertFatal(dlsch.c[r], "cannot allocate dlsch.c[%d]\n", r); + bzero(dlsch.c[r], 8448); } - harq->f = malloc16(N_RB * NR_SYMBOLS_PER_SLOT * NR_NB_SC_PER_RB * 8 * NR_MAX_NB_LAYERS); - AssertFatal(harq->f, "cannot allocate harq->f\n"); - bzero(harq->f, N_RB * NR_SYMBOLS_PER_SLOT * NR_NB_SC_PER_RB * 8 * NR_MAX_NB_LAYERS); + dlsch.f = malloc16(N_RB * NR_SYMBOLS_PER_SLOT * NR_NB_SC_PER_RB * 8 * NR_MAX_NB_LAYERS); + AssertFatal(dlsch.f, "cannot allocate dlsch->f\n"); + bzero(dlsch.f, N_RB * NR_SYMBOLS_PER_SLOT * NR_NB_SC_PER_RB * 8 * NR_MAX_NB_LAYERS); return (dlsch); } int nr_dlsch_encoding(PHY_VARS_gNB *gNB, - processingData_L1tx_t *msgTx, + int n_dlsch, + NR_gNB_DLSCH_t *dlsch_array, int frame, uint8_t slot, NR_DL_FRAME_PARMS *frame_parms, @@ -122,28 +120,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); - nrLDPC_TB_encoding_parameters_t TBs[msgTx->num_pdsch_slot]; + nrLDPC_TB_encoding_parameters_t TBs[n_dlsch]; memset(TBs, 0, sizeof(TBs)); - nrLDPC_slot_encoding_parameters_t slot_parameters = {.frame = frame, - .slot = slot, - .nb_TBs = msgTx->num_pdsch_slot, - .threadPool = &gNB->threadPool, - .tinput = tinput, - .tprep = tprep, - .tparity = tparity, - .toutput = toutput, - .TBs = TBs}; int num_segments = 0; - for (int dlsch_id = 0; dlsch_id < msgTx->num_pdsch_slot; dlsch_id++) { - NR_gNB_DLSCH_t *dlsch = msgTx->dlsch[dlsch_id]; + for (int i = 0; i < n_dlsch; i++) { + NR_gNB_DLSCH_t *dlsch = &dlsch_array[i]; - NR_DL_gNB_HARQ_t *harq = &dlsch->harq_process; unsigned int crc = 1; - nfapi_nr_dl_tti_pdsch_pdu_rel15_t *rel15 = &harq->pdsch_pdu.pdsch_pdu_rel15; + const nfapi_nr_dl_tti_pdsch_pdu_rel15_t *rel15 = &dlsch->pdsch_pdu->pdsch_pdu_rel15; uint32_t A = rel15->TBSize[0] << 3; - unsigned char *a = harq->pdu; + unsigned char *a = dlsch->pdu; if (rel15->rnti != SI_RNTI) { ws_trace_t tmp = {.nr = true, .direction = DIRECTION_DOWNLINK, @@ -182,9 +170,8 @@ int nr_dlsch_encoding(PHY_VARS_gNB *gNB, // printf("CRC %x (A %d)\n",crc,A); // printf("a0 %d a1 %d a2 %d\n", a[A>>3], a[1+(A>>3)], a[2+(A>>3)]); B = A + 24; - // harq->b = a; AssertFatal((A / 8) + 4 <= max_bytes, "A %d is too big (A/8+4 = %d > %d)\n", A, (A / 8) + 4, max_bytes); - memcpy(harq->b, a, (A / 8) + 4); // why is this +4 if the CRC is only 3 bytes? + memcpy(dlsch->b, a, (A / 8) + 4); // why is this +4 if the CRC is only 3 bytes? } else { // Add 16-bit crc (polynomial A) to payload crc = crc16(a, A) >> 16; @@ -193,21 +180,19 @@ int nr_dlsch_encoding(PHY_VARS_gNB *gNB, // printf("CRC %x (A %d)\n",crc,A); // printf("a0 %d a1 %d \n", a[A>>3], a[1+(A>>3)]); B = A + 16; - // harq->b = a; AssertFatal((A / 8) + 3 <= max_bytes, "A %d is too big (A/8+3 = %d > %d)\n", A, (A / 8) + 3, max_bytes); - memcpy(harq->b, a, (A / 8) + 3); // using 3 bytes to mimic the case of 24 bit crc + memcpy(dlsch->b, a, (A / 8) + 3); // using 3 bytes to mimic the case of 24 bit crc } - nrLDPC_TB_encoding_parameters_t *TB_parameters = &TBs[dlsch_id]; + nrLDPC_TB_encoding_parameters_t *TB_parameters = &TBs[i]; - // The harq_pid is not unique among the active HARQ processes in the instance so we use dlsch_id instead - TB_parameters->harq_unique_pid = dlsch_id; + // The harq_pid is not unique among the active HARQ processes in the instance so we use i instead + TB_parameters->harq_unique_pid = i; TB_parameters->BG = rel15->maintenance_parms_v3.ldpcBaseGraph; - TB_parameters->Z = harq->Z; TB_parameters->A = A; start_meas(dlsch_segmentation_stats); - TB_parameters->Kb = nr_segmentation(harq->b, - harq->c, + TB_parameters->Kb = nr_segmentation(dlsch->b, + dlsch->c, B, &TB_parameters->C, &TB_parameters->K, @@ -228,20 +213,19 @@ int nr_dlsch_encoding(PHY_VARS_gNB *gNB, size_t segments_offset = 0; size_t dlsch_offset = 0; - for (int dlsch_id = 0; dlsch_id < msgTx->num_pdsch_slot; dlsch_id++) { - NR_gNB_DLSCH_t *dlsch = msgTx->dlsch[dlsch_id]; - NR_DL_gNB_HARQ_t *harq = &dlsch->harq_process; - nfapi_nr_dl_tti_pdsch_pdu_rel15_t *rel15 = &harq->pdsch_pdu.pdsch_pdu_rel15; + for (int i = 0; i < n_dlsch; i++) { + NR_gNB_DLSCH_t *dlsch = &dlsch_array[i]; + const nfapi_nr_dl_tti_pdsch_pdu_rel15_t *rel15 = &dlsch->pdsch_pdu->pdsch_pdu_rel15; - nrLDPC_TB_encoding_parameters_t *TB_parameters = &TBs[dlsch_id]; + nrLDPC_TB_encoding_parameters_t *TB_parameters = &TBs[i]; #ifdef DEBUG_DLSCH_CODING for (int r = 0; r < TB_parameters->C; r++) { - LOG_D(PHY, "Encoder: B %d F %d \n", harq->B, TB_parameters->F); + LOG_D(PHY, "Encoder: B %d F %d \n", dlsch->B, TB_parameters->F); LOG_D(PHY, "start ldpc encoder segment %d/%d\n", r, TB_parameters->C); - LOG_D(PHY, "input %d %d %d %d %d \n", harq->c[r][0], harq->c[r][1], harq->c[r][2], harq->c[r][3], harq->c[r][4]); + LOG_D(PHY, "input %d %d %d %d %d \n", dlsch->c[r][0], dlsch->c[r][1], dlsch->c[r][2], dlsch->c[r][3], dlsch->c[r][4]); for (int cnt = 0; cnt < 22 * (TB_parameters->Z) / 8; cnt++) { - LOG_D(PHY, "%d ", harq->c[r][cnt]); + LOG_D(PHY, "%d ", dlsch->c[r][cnt]); } LOG_D(PHY, "\n"); } @@ -259,7 +243,7 @@ int nr_dlsch_encoding(PHY_VARS_gNB *gNB, rel15->NrOfSymbols, nb_re_dmrs, get_num_dmrs(rel15->dlDmrsSymbPos), - harq->unav_res, + dlsch->unav_res, rel15->qamModOrder[0], rel15->nrOfLayers); @@ -270,7 +254,7 @@ int nr_dlsch_encoding(PHY_VARS_gNB *gNB, for (int r = 0; r < TB_parameters->C; r++) { nrLDPC_segment_encoding_parameters_t *segment_parameters = &TB_parameters->segments[r]; - segment_parameters->c = harq->c[r]; + segment_parameters->c = dlsch->c[r]; segment_parameters->E = nr_get_E(TB_parameters->G, TB_parameters->C, TB_parameters->Qm, rel15->nrOfLayers, r); reset_meas(&segment_parameters->ts_interleave); @@ -287,10 +271,19 @@ int nr_dlsch_encoding(PHY_VARS_gNB *gNB, dlsch_offset += ceil_mod(dlsch_size, 8 * 64); } + nrLDPC_slot_encoding_parameters_t slot_parameters = {.frame = frame, + .slot = slot, + .nb_TBs = n_dlsch, + .threadPool = &gNB->threadPool, + .tinput = tinput, + .tprep = tprep, + .tparity = tparity, + .toutput = toutput, + .TBs = TBs}; gNB->nrLDPC_coding_interface.nrLDPC_coding_encoder(&slot_parameters); - for (int dlsch_id = 0; dlsch_id < msgTx->num_pdsch_slot; dlsch_id++) { - nrLDPC_TB_encoding_parameters_t *TB_parameters = &TBs[dlsch_id]; + for (int i = 0; i < n_dlsch; i++) { + nrLDPC_TB_encoding_parameters_t *TB_parameters = &TBs[i]; for (int r = 0; r < TB_parameters->C; r++) { nrLDPC_segment_encoding_parameters_t *segment_parameters = &TB_parameters->segments[r]; merge_meas(dlsch_interleaving_stats, &segment_parameters->ts_interleave); diff --git a/openair1/PHY/NR_TRANSPORT/nr_dlsch_tools.c b/openair1/PHY/NR_TRANSPORT/nr_dlsch_tools.c deleted file mode 100644 index 3f1d988c53..0000000000 --- a/openair1/PHY/NR_TRANSPORT/nr_dlsch_tools.c +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The OpenAirInterface Software Alliance licenses this file to You under - * the OAI Public License, Version 1.1 (the "License"); you may not use this file - * except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.openairinterface.org/?page_id=698 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - *------------------------------------------------------------------------------- - * For more information about the OpenAirInterface (OAI) Software Alliance: - * contact@openairinterface.org - */ - -/*! \file PHY/NR_TRANSPORT/nr_dlsch_tools.c -* \brief Top-level routines for decoding DLSCH transport channel from 38-214, V15.2.0 2018-06 -* \author Guy De Souza -* \date 2018 -* \version 0.1 -* \company Eurecom -* \email: desouza@eurecom.fr -* \note - -* \warning -*/ - -#include "nr_dlsch.h" -#include "../../../nfapi/oai_integration/vendor_ext.h" - -void nr_fill_dlsch_dl_tti_req(processingData_L1tx_t *msgTx, nfapi_nr_dl_tti_pdsch_pdu *pdsch_pdu) -{ - 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)); - AssertFatal(msgTx->num_pdsch_slot == pdsch_pdu->pdsch_pdu_rel15.pduIndex, - "PDSCH PDU index %d does not match msgTx index %d\n", - pdsch_pdu->pdsch_pdu_rel15.pduIndex, - msgTx->num_pdsch_slot); - msgTx->num_pdsch_slot++; - harq->pdu = NULL; -} - -void nr_fill_dlsch_tx_req(processingData_L1tx_t *msgTx, int idx, uint8_t *sdu) -{ - AssertFatal(sdu != NULL, "sdu is null\n"); - - /* not sure if FAPI could transmit DL_TTI_req and TX_req in different orders. - * for the moment, assume they are in the same order (and check!) */ - NR_gNB_DLSCH_t *dlsch = &msgTx->dlsch[idx][0]; - NR_DL_gNB_HARQ_t *harq = &dlsch->harq_process; - nfapi_nr_dl_tti_pdsch_pdu *pdsch = &harq->pdsch_pdu; - AssertFatal(pdsch->pdsch_pdu_rel15.pduIndex == idx, "PDSCH PDU index %d does not match %d\n", pdsch->pdsch_pdu_rel15.pduIndex, idx); - harq->pdu = sdu; -} diff --git a/openair1/PHY/NR_TRANSPORT/nr_prs.c b/openair1/PHY/NR_TRANSPORT/nr_prs.c index 6f26b9a07f..799912713d 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_prs.c +++ b/openair1/PHY/NR_TRANSPORT/nr_prs.c @@ -13,7 +13,7 @@ int nr_generate_prs(int slot, int16_t amp, prs_config_t *prs_cfg, nfapi_nr_config_request_scf_t *config, - NR_DL_FRAME_PARMS *frame_parms) + const NR_DL_FRAME_PARMS *frame_parms) { int k_prime = 0, k = 0, idx; diff --git a/openair1/PHY/NR_TRANSPORT/nr_transport_proto.h b/openair1/PHY/NR_TRANSPORT/nr_transport_proto.h index 0714f3dde3..29fca5975e 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_transport_proto.h +++ b/openair1/PHY/NR_TRANSPORT/nr_transport_proto.h @@ -45,7 +45,7 @@ int nr_generate_prs(int slot, int16_t amp, prs_config_t *prs_cfg, nfapi_nr_config_request_scf_t *config, - NR_DL_FRAME_PARMS *frame_parms); + const NR_DL_FRAME_PARMS *frame_parms); /*! \fn int nr_generate_pss diff --git a/openair1/PHY/NR_TRANSPORT/nr_ulsch.c b/openair1/PHY/NR_TRANSPORT/nr_ulsch.c index 4621e184a6..06aef61935 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_ulsch.c +++ b/openair1/PHY/NR_TRANSPORT/nr_ulsch.c @@ -59,8 +59,88 @@ static NR_gNB_ULSCH_t *find_nr_ulsch(PHY_VARS_gNB *gNB, uint16_t rnti, int pid) return ulsch; } +static void dump_pusch_pdu(int instance, int frame, int slot, nfapi_nr_pusch_pdu_t *pusch_pdu) +{ + LOG_D(PHY, + "[gNB %d] %d.%d ULSCH PDU pdu_bit_map %u " + "rnti %u " + "handle %u " + "bwp_size %u " + "bwp_start %u " + "subcarrier_spacing %u " + "cyclic_prefix %u " + "target_code_rate %u " + "qam_mod_order %u " + "mcs_index %u " + "mcs_table %u " + "transform_precoding %u " + "data_scrambling_id %u " + "nrOfLayers %u " + "ul_dmrs_symb_pos %u " + "dmrs_config_type %u " + "ul_dmrs_scrambling_id %u " + "scid %u " + "num_dmrs_cdm_grps_no_data %u " + "dmrs_ports %u " + "resource_alloc %u " + "rb_start %u " + "rb_size %u " + "vrb_to_prb_mapping %u " + "frequency_hopping %u " + "tx_direct_current_location %u " + "uplink_frequency_shift_7p5khz %u " + "start_symbol_index %u " + "nr_of_symbols %u " + "tbslbrm %u " + "ldpcBaseGraph %u " + "pusch_data->rv_index %u " + "pusch_data->harq_process_id %u " + "pusch_data->new_data_indicator %u " + "pusch_data->num_cb %u\n", + instance, + frame, + slot, + pusch_pdu->pdu_bit_map, + pusch_pdu->rnti, + pusch_pdu->handle, + pusch_pdu->bwp_size, + pusch_pdu->bwp_start, + pusch_pdu->subcarrier_spacing, + pusch_pdu->cyclic_prefix, + pusch_pdu->target_code_rate, + pusch_pdu->qam_mod_order, + pusch_pdu->mcs_index, + pusch_pdu->mcs_table, + pusch_pdu->transform_precoding, + pusch_pdu->data_scrambling_id, + pusch_pdu->nrOfLayers, + pusch_pdu->ul_dmrs_symb_pos, + pusch_pdu->dmrs_config_type, + pusch_pdu->ul_dmrs_scrambling_id, + pusch_pdu->scid, + pusch_pdu->num_dmrs_cdm_grps_no_data, + pusch_pdu->dmrs_ports, + pusch_pdu->resource_alloc, + pusch_pdu->rb_start, + pusch_pdu->rb_size, + pusch_pdu->vrb_to_prb_mapping, + pusch_pdu->frequency_hopping, + pusch_pdu->tx_direct_current_location, + pusch_pdu->uplink_frequency_shift_7p5khz, + pusch_pdu->start_symbol_index, + pusch_pdu->nr_of_symbols, + pusch_pdu->maintenance_parms_v3.tbSizeLbrmBytes, + pusch_pdu->maintenance_parms_v3.ldpcBaseGraph, + pusch_pdu->pusch_data.rv_index, + pusch_pdu->pusch_data.harq_process_id, + pusch_pdu->pusch_data.new_data_indicator, + pusch_pdu->pusch_data.num_cb); +} + + void nr_fill_ulsch(PHY_VARS_gNB *gNB, int frame, int slot, nfapi_nr_pusch_pdu_t *ulsch_pdu) { + dump_pusch_pdu(gNB->Mod_id, frame, slot, ulsch_pdu); int harq_pid = ulsch_pdu->pusch_data.harq_process_id; NR_gNB_ULSCH_t *ulsch = find_nr_ulsch(gNB, ulsch_pdu->rnti, harq_pid); if (ulsch == NULL) { diff --git a/openair1/PHY/NR_TRANSPORT/nr_ulsch_decoding.c b/openair1/PHY/NR_TRANSPORT/nr_ulsch_decoding.c index 239b6f2f29..24d4950dfa 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_ulsch_decoding.c +++ b/openair1/PHY/NR_TRANSPORT/nr_ulsch_decoding.c @@ -35,7 +35,6 @@ #include "PHY/NR_TRANSPORT/nr_ulsch.h" #include "PHY/NR_TRANSPORT/nr_dlsch.h" #include "SCHED_NR/sched_nr.h" -#include "SCHED_NR/fapi_nr_l1.h" #include "defs.h" #include "common/utils/LOG/vcd_signal_dumper.h" #include "common/utils/LOG/log.h" diff --git a/openair1/PHY/NR_UE_ESTIMATION/nr_ue_measurements.c b/openair1/PHY/NR_UE_ESTIMATION/nr_ue_measurements.c index 7d6ab8e6f2..4c8c57d9fd 100644 --- a/openair1/PHY/NR_UE_ESTIMATION/nr_ue_measurements.c +++ b/openair1/PHY/NR_UE_ESTIMATION/nr_ue_measurements.c @@ -236,6 +236,7 @@ void nr_ue_ssb_rsrp_measurements(PHY_VARS_NR_UE *ue, .meas_type = NFAPI_NR_SS_MEAS, .Nid_cell = ue->frame_parms.Nid_cell, .rsrp_dBm = ue->measurements.ssb_rsrp_dBm[ssb_index], + .sinr_dB = ue->measurements.ssb_sinr_dB[ssb_index], .ssb_index = ssb_index, .is_neighboring_cell = false, }; diff --git a/openair1/PHY/TOOLS/imscope/imgui.ini b/openair1/PHY/TOOLS/imscope/imgui.ini index 3fc08b6f7c..f3269ebfc6 100644 --- a/openair1/PHY/TOOLS/imscope/imgui.ini +++ b/openair1/PHY/TOOLS/imscope/imgui.ini @@ -1,13 +1,47 @@ +[Window][WindowOverViewport_11111111] +Pos=0,19 +Size=1920,927 +Collapsed=0 + [Window][Debug##Default] Pos=60,60 Size=400,400 Collapsed=0 +[Window][Status bar] +Pos=0,914 +Size=1920,32 +Collapsed=0 +DockId=0x00000004,0 + +[Window][Global scope settings] +Pos=697,153 +Size=545,478 +Collapsed=0 + +[Window][PUSCH SLOT IQ] +Pos=0,257 +Size=789,655 +Collapsed=0 +DockId=0x0000000B,0 + +[Window][PUSCH LLRs] +Pos=791,257 +Size=1129,655 +Collapsed=0 +DockId=0x0000000C,0 + +[Window][Time domain samples] +Pos=997,201 +Size=923,711 +Collapsed=0 +DockId=0x0000000E,0 + [Window][NR KPI] Pos=0,19 Size=1133,667 Collapsed=0 -DockId=0x00000005,0 +DockId=0x00000007,0 [Window][Dear ImGui Demo] Pos=531,19 @@ -21,79 +55,223 @@ Size=529,667 Collapsed=0 DockId=0x00000002,0 -[Window][WindowOverViewport_11111111] -Pos=0,19 -Size=1280,701 -Collapsed=0 - -[Window][Status bar] -Pos=0,688 -Size=1280,32 -Collapsed=0 -DockId=0x00000004,0 - -[Window][Global scope settings] -Pos=1038,19 -Size=242,667 -Collapsed=0 -DockId=0x00000006,0 - [Window][UE KPI] -Pos=532,19 -Size=528,667 +Pos=0,19 +Size=1920,180 Collapsed=0 -DockId=0x00000008,0 +DockId=0x00000007,0 [Window][UE PDSCH IQ] -Pos=0,19 -Size=530,667 +Pos=997,201 +Size=923,711 Collapsed=0 -DockId=0x00000005,1 - -[Window][Time domain samples] -Pos=0,19 -Size=1036,667 -Collapsed=0 -DockId=0x00000005,0 +DockId=0x0000000E,3 [Window][Time domain samples - before sync] -Pos=0,19 -Size=530,667 +Pos=0,201 +Size=995,711 Collapsed=0 -DockId=0x00000005,2 +DockId=0x0000000D,0 [Window][Broadcast channel] -Pos=0,19 -Size=530,667 +Pos=997,201 +Size=923,711 Collapsed=0 -DockId=0x00000005,3 +DockId=0x0000000E,1 [Window][RX IQ] Pos=532,19 Size=528,667 Collapsed=0 -DockId=0x00000008,0 +DockId=0x00000001,0 -[Window][PUSCH SLOT IQ] -Pos=0,19 -Size=1036,667 +[Window][UE PDSCH Chan est] +Pos=997,201 +Size=923,711 Collapsed=0 -DockId=0x00000005,1 +DockId=0x0000000E,2 -[Window][PUSCH LLRs] -Pos=0,19 -Size=1036,667 +[Window][UE PDSCH IQ before compensation] +Pos=0,201 +Size=995,711 Collapsed=0 -DockId=0x00000005,2 +DockId=0x0000000D,1 + +[Window][gNB Scope] +Pos=-4,30 +Size=1728,834 +Collapsed=0 + +[Window][UE Scope] +Pos=-1,23 +Size=1922,902 +Collapsed=0 + +[Window][Dear ImGui Demo/##Basket_379447C1] +IsChild=1 +Size=1202,260 + +[Window][Dear ImGui Demo/ResizableChild_D5443E47] +IsChild=1 +Size=1153,32 + +[Window][Dear ImGui Demo/Red_1D4E05CE] +IsChild=1 +Size=200,100 + +[Window][Delete?] +Pos=804,420 +Size=311,105 +Collapsed=0 + +[Window][Stacked 1] +Pos=755,387 +Size=409,172 +Collapsed=0 + +[Window][Example: Simple layout] +Pos=354,164 +Size=981,698 +Collapsed=0 + +[Window][Example: Simple layout/left pane_AED60EF8] +IsChild=1 +Size=150,644 + +[Window][Example: Log] +Pos=60,60 +Size=500,400 +Collapsed=0 + +[Window][Example: Auto-resizing window] +Pos=179,108 +Size=654,437 +Collapsed=0 + +[Window][gNB Scope/##pusch_time_domain_5637DE0C] +IsChild=1 +Size=1728,302 + +[Window][gNB Scope/##pusch_iq_903C5250] +IsChild=1 +Size=408,500 + +[Window][gNB Scope/##pusch_llr_FE553CCC] +IsChild=1 +Size=1443,502 + +[Window][Dear ImGui Demo/##Tree_C1CE970E] +IsChild=1 +Size=1132,260 + +[Window][Dear ImGui Demo/##Basket_97A64F14] +IsChild=1 +Size=1132,260 + +[Window][Dear ImGui Demo/##Basket_745C408A] +IsChild=1 +Size=1132,260 + +[Window][UE Scope/##ue_kpi_A22981AC] +IsChild=1 +Size=1839,183 + +[Window][UE Scope/##ue_iq_plots_F23AA7B4] +IsChild=1 +Size=814,517 + +[Window][UE Scope/##ue_plots0_D75041C0] +IsChild=1 +Size=1067,610 + +[Window][UE Scope/##ue_plots1_A0577156] +IsChild=1 +Size=733,604 + +[Window][UE PDCCH IQ] +Pos=997,201 +Size=923,711 +Collapsed=0 +DockId=0x0000000E,4 + +[Window][UE PDCCH LLR] +Pos=0,201 +Size=995,711 +Collapsed=0 +DockId=0x0000000D,2 + +[Table][0xC9935533,3] +Column 0 Weight=1.0000 +Column 1 Weight=1.0000 +Column 2 Weight=1.0000 + +[Table][0xE0773582,3] +Column 0 Weight=1.0000 +Column 1 Weight=1.0000 +Column 2 Weight=1.0000 + +[Table][0x45A0E60D,7] +RefScale=13 +Column 0 Width=49 +Column 1 Width=112 +Column 2 Width=112 +Column 3 Width=112 +Column 4 Width=112 +Column 5 Width=112 +Column 6 Width=112 + +[Table][0xDA36A7E0,6] +RefScale=13 +Column 0 Width=28 Sort=0v +Column 1 Width=42 +Column 2 Width=73 +Column 3 Width=68 +Column 4 Weight=1.0000 +Column 5 Width=-1 + +[Table][0x0919F5A2,14] +RefScale=13 +Column 0 Width=56 +Column 1 Width=19 +Column 2 Width=19 +Column 3 Width=19 +Column 4 Width=19 +Column 5 Width=19 +Column 6 Width=19 +Column 7 Width=19 +Column 8 Width=19 +Column 9 Width=19 +Column 10 Width=19 +Column 11 Width=19 +Column 12 Width=19 +Column 13 Width=19 + +[Table][0x8DFA6E86,2] +Column 0 Weight=1.0000 +Column 1 Weight=1.0000 + +[Table][0xFABAAEF7,2] +Column 0 Weight=1.0000 +Column 1 Weight=1.0000 + +[Table][0xC179E37C,3] +RefScale=13 +Column 0 Width=108 Sort=0v +Column 1 Width=63 +Column 2 Width=-1 [Docking][Data] -DockSpace ID=0x7C6B3D9B Window=0xA87D555D Pos=0,19 Size=1280,701 Split=Y Selected=0x71C89FCB - DockNode ID=0x00000003 Parent=0x7C6B3D9B SizeRef=1280,667 Split=X - DockNode ID=0x00000001 Parent=0x00000003 SizeRef=1319,720 Split=X Selected=0x6627CA6C - DockNode ID=0x00000007 Parent=0x00000001 SizeRef=530,667 Split=X Selected=0x93FDECFF - DockNode ID=0x00000005 Parent=0x00000007 SizeRef=1036,334 CentralNode=1 Selected=0x93FDECFF - DockNode ID=0x00000006 Parent=0x00000007 SizeRef=242,334 Selected=0xFAA8D9D5 - DockNode ID=0x00000008 Parent=0x00000001 SizeRef=528,667 Selected=0x6627CA6C - DockNode ID=0x00000002 Parent=0x00000003 SizeRef=529,720 Selected=0xB903C8C9 - DockNode ID=0x00000004 Parent=0x7C6B3D9B SizeRef=1280,32 HiddenTabBar=1 Selected=0xD9B9B9C7 +DockSpace ID=0x7C6B3D9B Window=0xA87D555D Pos=0,19 Size=1920,927 Split=Y Selected=0x71C89FCB + DockNode ID=0x00000003 Parent=0x7C6B3D9B SizeRef=1280,667 Split=X + DockNode ID=0x00000001 Parent=0x00000003 SizeRef=1319,720 Split=Y Selected=0x6627CA6C + DockNode ID=0x00000009 Parent=0x00000001 SizeRef=1920,236 Split=Y Selected=0x6627CA6C + DockNode ID=0x00000007 Parent=0x00000009 SizeRef=1920,180 CentralNode=1 Selected=0x6627CA6C + DockNode ID=0x00000008 Parent=0x00000009 SizeRef=1920,711 Split=X Selected=0x3A5D5B36 + DockNode ID=0x0000000D Parent=0x00000008 SizeRef=995,711 Selected=0xF0B5A18D + DockNode ID=0x0000000E Parent=0x00000008 SizeRef=923,711 Selected=0x752F58D8 + DockNode ID=0x0000000A Parent=0x00000001 SizeRef=1920,655 Split=X Selected=0x93FDECFF + DockNode ID=0x0000000B Parent=0x0000000A SizeRef=789,444 Selected=0x93FDECFF + DockNode ID=0x0000000C Parent=0x0000000A SizeRef=1129,444 Selected=0x43E927D5 + DockNode ID=0x00000002 Parent=0x00000003 SizeRef=529,720 Selected=0xB903C8C9 + DockNode ID=0x00000004 Parent=0x7C6B3D9B SizeRef=1280,32 HiddenTabBar=1 Selected=0xD9B9B9C7 diff --git a/openair1/PHY/TOOLS/imscope/imscope.cpp b/openair1/PHY/TOOLS/imscope/imscope.cpp index cce7a595f7..a80b5cfd98 100644 --- a/openair1/PHY/TOOLS/imscope/imscope.cpp +++ b/openair1/PHY/TOOLS/imscope/imscope.cpp @@ -100,6 +100,7 @@ class LLRPlot { ImScopeDataWrapper &scope_data = scope_array[type]; if (ImPlot::BeginPlot(label)) { + ImPlot::SetupAxes(nullptr, nullptr, ImPlotAxisFlags_AutoFit, ImPlotAxisFlags_AutoFit); if (!frozen || next) { if (scope_data.is_data_ready) { iq_procedure_timer.Add(scope_data.data.time_taken_in_ns); @@ -205,6 +206,7 @@ class IQHist { if (plot_type == 0) { float x = ImGui::CalcItemWidth(); if (ImPlot::BeginPlot(label.c_str(), {x, x})) { + ImPlot::SetupAxes(nullptr, nullptr, ImPlotAxisFlags_AutoFit, ImPlotAxisFlags_AutoFit); ImPlot::PlotHistogram2D(label.c_str(), iq_data->real.data(), iq_data->imag.data(), @@ -217,6 +219,7 @@ class IQHist { } else if (plot_type == 2) { float x = ImGui::CalcItemWidth(); if (ImPlot::BeginPlot(label.c_str(), {x, x})) { + ImPlot::SetupAxes(nullptr, nullptr, ImPlotAxisFlags_AutoFit, ImPlotAxisFlags_AutoFit); int points_drawn = 0; while (points_drawn < iq_data->len) { // Limit the amount of data plotted with PlotScatter call (issue with vertices/draw call) @@ -232,6 +235,7 @@ class IQHist { } } else if (plot_type == 1) { if (ImPlot::BeginPlot(label.c_str())) { + ImPlot::SetupAxes(nullptr, nullptr, ImPlotAxisFlags_AutoFit, ImPlotAxisFlags_AutoFit); ImPlot::PlotLine(label.c_str(), iq_data->power.data(), iq_data->len); ImPlot::EndPlot(); } @@ -364,6 +368,7 @@ class IQSlotHeatmap { static std::vector symbol_boundaries = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13}; if (ImPlot::BeginPlot(label.c_str(), {(float)ImGui::GetWindowWidth() * 0.9f, 0})) { auto num_sc = num_rb * NR_NB_SC_PER_RB; + ImPlot::SetupAxes(nullptr, nullptr, ImPlotAxisFlags_AutoFit, ImPlotAxisFlags_AutoFit); ImPlot::SetupAxes("symbols", "subcarriers"); ImPlot::SetupAxisLimits(ImAxis_X1, num_symbols, 0); ImPlot::SetupAxisLimits(ImAxis_Y1, num_sc, 0); @@ -429,6 +434,7 @@ void ShowUeScope(void *data_void_ptr, float t) rbs_buffer.AddPoint(t, getKPIUE()->nofRBs); bler.AddPoint(t, (float)getKPIUE()->nb_nack / (float)getKPIUE()->nb_total); mcs.AddPoint(t, (float)getKPIUE()->dl_mcs); + ImPlot::SetupAxes(nullptr, nullptr, ImPlotAxisFlags_AutoFit, ImPlotAxisFlags_AutoFit); ImPlot::SetupAxes("time", "noOfRbs"); ImPlot::SetupAxisLimits(ImAxis_X1, t - history, t, ImGuiCond_Always); ImPlot::SetupAxisLimits(ImAxis_Y1, 0, NR_MAX_RB); @@ -444,6 +450,23 @@ void ShowUeScope(void *data_void_ptr, float t) } ImGui::End(); + if (ImGui::Begin("UE PDCCH IQ")) { + static auto iq_data = new IQData(); + static auto pdcch_iq_hist = new IQHist("PDCCH IQ"); + bool new_data = false; + if (pdcch_iq_hist->ShouldReadData()) { + new_data = iq_data->TryCollect(&scope_array[pdcchRxdataF_comp], t, pdcch_iq_hist->GetEpsilon(), iq_procedure_timer); + } + pdcch_iq_hist->Draw(iq_data, t, new_data); + } + ImGui::End(); + + if (ImGui::Begin("UE PDCCH LLR")) { + static auto llr_plot = new LLRPlot(); + llr_plot->Draw(t, pdcchLlr, "PDCCH LLR"); + } + ImGui::End(); + if (ImGui::Begin("UE PDSCH IQ")) { static auto iq_data = new IQData(); static auto pdsch_iq_hist = new IQHist("PDSCH IQ"); @@ -710,6 +733,7 @@ void *imscope_thread(void *data_void_ptr) static float t = 0; static bool show_imgui_demo_window = false; static bool show_implot_demo_window = false; + static bool show_scope_settings_window = false; ImGui::DockSpaceOverViewport(); if (ImGui::BeginMainMenuBar()) { if (ImGui::BeginMenu("File")) { @@ -729,6 +753,12 @@ void *imscope_thread(void *data_void_ptr) } ImGui::EndMenu(); } + if (ImGui::BeginMenu("Settings")) { + if (ImGui::MenuItem("Global scope settings")) { + show_scope_settings_window = !show_scope_settings_window; + } + ImGui::EndMenu(); + } ImGui::EndMainMenuBar(); } @@ -739,16 +769,6 @@ void *imscope_thread(void *data_void_ptr) } ImGui::End(); - ImGui::Begin("Global scope settings"); - ImGui::ShowStyleSelector("ImGui Style"); - ImPlot::ShowStyleSelector("ImPlot Style"); - ImPlot::ShowColormapSelector("ImPlot Colormap"); - ImGui::SliderInt("FPS target", &target_fps, 12, 60); - if (ImGui::IsItemHovered()) { - ImGui::SetTooltip("Reduces scope flickering in unfrozen mode. Can reduce impact on perfromance of the modem"); - } - ImGui::End(); - t += ImGui::GetIO().DeltaTime; iq_procedure_timer.UpdateAverage(t); @@ -765,7 +785,19 @@ void *imscope_thread(void *data_void_ptr) ImPlot::ShowDemoWindow(); if (show_imgui_demo_window) ImGui::ShowDemoWindow(); - + // Settings + if (show_scope_settings_window) { + ImGui::SetNextWindowPos(ImGui::GetMainViewport()->GetCenter(), ImGuiCond_FirstUseEver, ImVec2(0.5f, 0.5f)); + ImGui::Begin("Global scope settings", &show_scope_settings_window); + ImGui::ShowStyleSelector("ImGui Style"); + ImPlot::ShowStyleSelector("ImPlot Style"); + ImPlot::ShowColormapSelector("ImPlot Colormap"); + ImGui::SliderInt("FPS target", &target_fps, 12, 60); + if (ImGui::IsItemHovered()) { + ImGui::SetTooltip("Reduces scope flickering in unfrozen mode. Can reduce impact on perfromance of the modem"); + } + ImGui::End(); + } // Rendering ImGui::Render(); glViewport(0, 0, display_w, display_h); diff --git a/openair1/PHY/defs_gNB.h b/openair1/PHY/defs_gNB.h index ef12f20ce5..abc700f9d2 100644 --- a/openair1/PHY/defs_gNB.h +++ b/openair1/PHY/defs_gNB.h @@ -53,30 +53,6 @@ typedef struct { int lut[MAX_PUCCH0_NID][160][14]; } NR_gNB_PUCCH0_LUT_t; -typedef struct { - /// Nfapi DLSCH PDU - nfapi_nr_dl_tti_pdsch_pdu pdsch_pdu; - /// pointer to pdu from MAC interface (this is "a" in 36.212) - uint8_t *pdu; - /// Pointer to the payload - uint8_t *b; - /// Pointers to transport block segments - uint8_t **c; - /// Frame where current HARQ round was sent - uint32_t frame; - /// Interleaver outputs - uint8_t *f; - /// LDPC lifting size - uint32_t Z; - /// REs unavailable for DLSCH (overlapping with PTRS, CSIRS etc.) - uint32_t unav_res; -} NR_DL_gNB_HARQ_t; - -typedef struct { - uint8_t active; - nfapi_nr_dl_tti_csi_rs_pdu csirs_pdu; -} NR_gNB_CSIRS_t; - typedef struct { int dump_frame; int round_trials[8]; @@ -121,19 +97,20 @@ typedef struct { } NR_gNB_PHY_STATS_t; typedef struct { - /// Pointers to variables related to DLSCH harq process - NR_DL_gNB_HARQ_t harq_process; - /// Active flag for baseband transmitter processing - uint8_t active; - /// Number of soft channel bits - uint32_t G; + /// Nfapi DLSCH PDU + const nfapi_nr_dl_tti_pdsch_pdu *pdsch_pdu; + /// pointer to pdu from MAC interface (this is "a" in 36.212) + uint8_t *pdu; + /// Pointer to the payload + uint8_t *b; + /// Pointers to transport block segments + uint8_t **c; + /// Interleaver outputs + uint8_t *f; + /// REs unavailable for DLSCH (overlapping with PTRS, CSIRS etc.) + uint32_t unav_res; } NR_gNB_DLSCH_t; -typedef struct { - bool active; - nfapi_nr_dl_tti_ssb_pdu ssb_pdu; -} NR_gNB_SSB_t; - typedef struct { uint8_t NumPRSResources; prs_config_t prs_cfg[NR_MAX_PRS_RESOURCES_PER_SET]; @@ -409,6 +386,8 @@ typedef struct PHY_VARS_gNB_s { NR_gNB_COMMON common_vars; prach_list_t prach_list; + // TODO: can we remove c from NR_gNB_DLSCH_t and put it on the stack? + NR_gNB_DLSCH_t *dlsch; NR_gNB_PRS prs_vars; NR_gNB_PUSCH *pusch_vars; NR_gNB_PUCCH_t *pucch; @@ -494,7 +473,6 @@ typedef struct PHY_VARS_gNB_s { time_stats_t rx_pusch_symbol_processing_stats; time_stats_t ul_indication_stats; time_stats_t slot_indication_stats; - time_stats_t schedule_response_stats; time_stats_t ulsch_decoding_stats; time_stats_t ts_deinterleave; time_stats_t ts_rate_unmatch; @@ -522,7 +500,6 @@ typedef struct PHY_VARS_gNB_s { int L1_rx_thread_core; pthread_t L1_tx_thread; int L1_tx_thread_core; - struct processingData_L1tx *msgDataTx; void *scopeData; } PHY_VARS_gNB; @@ -599,16 +576,6 @@ typedef struct processingData_L1tx { int slot_rx; openair0_timestamp timestamp_tx; PHY_VARS_gNB *gNB; - 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; - 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; typedef struct processingData_L1rx { diff --git a/openair1/PHY/nr_phy_common/inc/nr_phy_common.h b/openair1/PHY/nr_phy_common/inc/nr_phy_common.h index 8303c510c7..a2011e1fa6 100644 --- a/openair1/PHY/nr_phy_common/inc/nr_phy_common.h +++ b/openair1/PHY/nr_phy_common/inc/nr_phy_common.h @@ -365,7 +365,7 @@ void nr_channel_level(const int symbol, int32_t avg[nb_rx * Nl], const uint32_t len); void nr_scale_channel(int size, int ch_estimates_ext[][size], int symb, uint32_t len, int nrOfLayers, int nb_rx, int shift_ch_ext); -bool generate_srs_nr(NR_DL_FRAME_PARMS *frame_parms, +bool generate_srs_nr(const NR_DL_FRAME_PARMS *frame_parms, c16_t **txdataF, uint16_t symbol_offset, int bwp_start, diff --git a/openair1/PHY/nr_phy_common/src/nr_phy_common_srs.c b/openair1/PHY/nr_phy_common/src/nr_phy_common_srs.c index ba5d792428..ad21978e06 100644 --- a/openair1/PHY/nr_phy_common/src/nr_phy_common_srs.c +++ b/openair1/PHY/nr_phy_common/src/nr_phy_common_srs.c @@ -139,7 +139,7 @@ static int compute_n_b(frame_t frame_number, * See TS 38.211 - Section 6.4.1.4 Sounding reference signal * ***************************************************************************/ -bool generate_srs_nr(NR_DL_FRAME_PARMS *frame_parms, +bool generate_srs_nr(const NR_DL_FRAME_PARMS *frame_parms, c16_t **txdataF, uint16_t symbol_offset, int bwp_start, diff --git a/openair1/SCHED/nfapi_lte_dummy.c b/openair1/SCHED/nfapi_lte_dummy.c index be532a0c54..fa59cbdb71 100644 --- a/openair1/SCHED/nfapi_lte_dummy.c +++ b/openair1/SCHED/nfapi_lte_dummy.c @@ -9,30 +9,12 @@ typedef struct pnf_p7_t pnf_p7_t; typedef struct vnf_t vnf_t; typedef struct vnf_p7_t vnf_p7_t; -void handle_nfapi_nr_pdcch_pdu(PHY_VARS_gNB *gNB, - int frame, int slot, - nfapi_nr_dl_tti_pdcch_pdu *pdcch_pdu){} - -void handle_nr_nfapi_ssb_pdu(PHY_VARS_gNB *gNB,int frame,int slot, - nfapi_nr_dl_tti_request_pdu_t *dl_tti_pdu){} - -void handle_nr_nfapi_pdsch_pdu(processingData_L1tx_t *msgTx, - nfapi_nr_dl_tti_pdsch_pdu *pdsch_pdu, - uint8_t *sdu){ -} -void handle_nfapi_nr_csirs_pdu(processingData_L1tx_t *msgTx, - int frame, int slot, - nfapi_nr_dl_tti_csi_rs_pdu *csirs_pdu){ - } int l1_north_init_gNB(void){return 0;} int slot_ahead = 6; //uint8_t nfapi_mode=0; NR_IF_Module_t *NR_IF_Module_init(int Mod_id) {return NULL;} -void handle_nfapi_nr_ul_dci_pdu(PHY_VARS_gNB *gNB, - int frame, int slot, - nfapi_nr_ul_dci_request_pdus_t *ul_dci_request_pdu){} void nr_fill_ulsch(PHY_VARS_gNB *gNB, int frame, int slot, @@ -47,8 +29,6 @@ void nr_schedule_rx_prach(PHY_VARS_gNB *gNB, int SFN, int Slot, nfapi_nr_prach_p void nr_phy_config_request(NR_PHY_Config_t *gNB){} -void install_nr_schedule_handlers(NR_IF_Module_t *if_inst){} - void nr_dump_frame_parms(NR_DL_FRAME_PARMS *fp){} bool vnf_nr_send_p5_msg(vnf_t *vnf, uint16_t p5_idx, nfapi_nr_p4_p5_message_header_t *msg, uint32_t msg_len) diff --git a/openair1/SCHED/nfapi_nr_dummy.c b/openair1/SCHED/nfapi_nr_dummy.c deleted file mode 100644 index 7377a455dd..0000000000 --- a/openair1/SCHED/nfapi_nr_dummy.c +++ /dev/null @@ -1,49 +0,0 @@ -//Dummy NR defs to avoid linking errors - -#include "PHY/defs_gNB.h" -#include "nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface_scf.h" -#include "openair2/NR_PHY_INTERFACE/NR_IF_Module.h" -#include "openair1/PHY/LTE_TRANSPORT/transport_common.h" - -void handle_nfapi_nr_pdcch_pdu(PHY_VARS_gNB *gNB, - int frame, int slot, - nfapi_nr_dl_tti_pdcch_pdu *pdcch_pdu){} - -void handle_nr_nfapi_ssb_pdu(PHY_VARS_gNB *gNB,int frame,int slot, - nfapi_nr_dl_tti_request_pdu_t *dl_tti_pdu){} - -void handle_nr_nfapi_pdsch_pdu(processingData_L1tx_t *msgTx, - nfapi_nr_dl_tti_pdsch_pdu *pdsch_pdu, - uint8_t *sdu){ -} -void handle_nfapi_nr_csirs_pdu(processingData_L1tx_t *msgTx, - int frame, int slot, - nfapi_nr_dl_tti_csi_rs_pdu *csirs_pdu){ - } -int l1_north_init_gNB(void){return 0;} - -int slot_ahead = 6; -//uint8_t nfapi_mode=0; -NR_IF_Module_t *NR_IF_Module_init(int Mod_id) {return NULL;} - -void handle_nfapi_nr_ul_dci_pdu(PHY_VARS_gNB *gNB, - int frame, int slot, - nfapi_nr_ul_dci_request_pdus_t *ul_dci_request_pdu){} -void nr_fill_ulsch(PHY_VARS_gNB *gNB, - int frame, - int slot, - nfapi_nr_pusch_pdu_t *ulsch_pdu){} -void nr_fill_pucch(PHY_VARS_gNB *gNB, - int frame, - int slot, - nfapi_nr_pucch_pdu_t *pucch_pdu){} -void nr_schedule_rx_prach(PHY_VARS_gNB *gNB, int SFN, int Slot, nfapi_nr_prach_pdu_t *prach_pdu) -{ -} - -void nr_phy_config_request(NR_PHY_Config_t *gNB){} - -void install_nr_schedule_handlers(NR_IF_Module_t *if_inst){} - -//void nr_dump_frame_parms(NR_DL_FRAME_PARMS *fp){} - diff --git a/openair1/SCHED_NR/fapi_nr_l1.c b/openair1/SCHED_NR/fapi_nr_l1.c deleted file mode 100644 index 9e4ab67efc..0000000000 --- a/openair1/SCHED_NR/fapi_nr_l1.c +++ /dev/null @@ -1,232 +0,0 @@ -/* - * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The OpenAirInterface Software Alliance licenses this file to You under - * the OAI Public License, Version 1.1 (the "License"); you may not use this file - * except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.openairinterface.org/?page_id=698 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - *------------------------------------------------------------------------------- - * For more information about the OpenAirInterface (OAI) Software Alliance: - * contact@openairinterface.org - */ - -/*! \file fapi_nr_l1.c - * \brief functions for FAPI L1 interface - * \author R. Knopp, WEI-TAI CHEN - * \date 2017, 2018 - * \version 0.1 - * \company Eurecom, NTUST - * \email: knopp@eurecom.fr, kroempa@gmail.com - * \note - * \warning - */ -#include "fapi_nr_l1.h" -#include "common/ran_context.h" -#include "PHY/NR_TRANSPORT/nr_transport_proto.h" -#include "PHY/NR_TRANSPORT/nr_dlsch.h" -#include "PHY/NR_TRANSPORT/nr_dci.h" -#include "nfapi/oai_integration/vendor_ext.h" -#include "openair2/NR_PHY_INTERFACE/nr_sched_response.h" -#include "nfapi/oai_integration/nfapi_vnf.h" - -void handle_nr_nfapi_ssb_pdu(processingData_L1tx_t *msgTx,int frame,int slot, - nfapi_nr_dl_tti_request_pdu_t *dl_tti_pdu) -{ - - AssertFatal(dl_tti_pdu->ssb_pdu.ssb_pdu_rel15.bchPayloadFlag== 1, "bchPayloadFlat %d != 1\n", - dl_tti_pdu->ssb_pdu.ssb_pdu_rel15.bchPayloadFlag); - - uint8_t i_ssb = dl_tti_pdu->ssb_pdu.ssb_pdu_rel15.SsbBlockIndex; - - LOG_D(NR_PHY,"%d.%d : ssb index %d pbch_pdu: %x\n",frame,slot,i_ssb,dl_tti_pdu->ssb_pdu.ssb_pdu_rel15.bchPayload); - if (msgTx->ssb[i_ssb].active) - AssertFatal(1==0,"SSB PDU with index %d already active\n",i_ssb); - else { - msgTx->ssb[i_ssb].active = true; - memcpy((void*)&msgTx->ssb[i_ssb].ssb_pdu,&dl_tti_pdu->ssb_pdu,sizeof(dl_tti_pdu->ssb_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_NUMBER_OF_SYMBOLS_PER_SLOT; id++) { - NR_gNB_CSIRS_t *csirs = &msgTx->csirs_pdu[id]; - if (csirs->active == 0) { - LOG_D(NR_PHY,"Frame %d Slot %d CSI_RS with ID %d is now active\n",frame,slot,id); - csirs->active = 1; - memcpy((void*)&csirs->csirs_pdu, (void*)csirs_pdu, sizeof(nfapi_nr_dl_tti_csi_rs_pdu)); - found = 1; - break; - } - } - if (found == 0) - LOG_E(MAC,"CSI-RS list is full\n"); -} - -void nr_schedule_dl_tti_req(PHY_VARS_gNB *gNB, nfapi_nr_dl_tti_request_t *DL_req) -{ - DevAssert(gNB != NULL); - DevAssert(DL_req != NULL); - nfapi_nr_config_request_scf_t *cfg = &gNB->gNB_config; - - int frame = DL_req->SFN; - int slot = DL_req->Slot; - - int slot_type = nr_slot_select(cfg, frame, slot); - DevAssert(slot_type == NR_DOWNLINK_SLOT || slot_type == NR_MIXED_SLOT); - - processingData_L1tx_t *msgTx = gNB->msgDataTx; - msgTx->slot = slot; - msgTx->frame = frame; - - uint8_t number_dl_pdu = DL_req->dl_tti_request_body.nPDUs; - - for (int i = 0; i < number_dl_pdu; i++) { - nfapi_nr_dl_tti_request_pdu_t *dl_tti_pdu = &DL_req->dl_tti_request_body.dl_tti_pdu_list[i]; - LOG_D(NR_PHY, "NFAPI: dl_pdu %d : type %d\n", i, dl_tti_pdu->PDUType); - switch (dl_tti_pdu->PDUType) { - case NFAPI_NR_DL_TTI_SSB_PDU_TYPE: - handle_nr_nfapi_ssb_pdu(msgTx, frame, slot, dl_tti_pdu); - break; - - case NFAPI_NR_DL_TTI_PDCCH_PDU_TYPE: - LOG_D(NR_PHY, "frame %d, slot %d, Got NFAPI_NR_DL_TTI_PDCCH_PDU_TYPE for %d.%d\n", frame, slot, DL_req->SFN, DL_req->Slot); - msgTx->pdcch_pdu[msgTx->num_dl_pdcch] = dl_tti_pdu->pdcch_pdu; - msgTx->num_dl_pdcch++; - break; - - case NFAPI_NR_DL_TTI_CSI_RS_PDU_TYPE: - LOG_D(NR_PHY, "frame %d, slot %d, Got NFAPI_NR_DL_TTI_CSI_RS_PDU_TYPE for %d.%d\n", frame, slot, DL_req->SFN, DL_req->Slot); - handle_nfapi_nr_csirs_pdu(msgTx, frame, slot, &dl_tti_pdu->csi_rs_pdu); - break; - - case NFAPI_NR_DL_TTI_PDSCH_PDU_TYPE: - LOG_D(NR_PHY, "frame %d, slot %d, Got NFAPI_NR_DL_TTI_PDSCH_PDU_TYPE for %d.%d\n", frame, slot, DL_req->SFN, DL_req->Slot); - nr_fill_dlsch_dl_tti_req(msgTx, &dl_tti_pdu->pdsch_pdu); - } - } -} - -void nr_schedule_ul_tti_req(PHY_VARS_gNB *gNB, nfapi_nr_ul_tti_request_t *UL_tti_req) -{ - DevAssert(gNB != NULL); - DevAssert(UL_tti_req != NULL); - - int frame = UL_tti_req->SFN; - int slot = UL_tti_req->Slot; - - for (int i = 0; i < UL_tti_req->n_pdus; i++) { - int type = UL_tti_req->pdus_list[i].pdu_type; - LOG_D(NR_PHY, - "frame %d, slot %d got %s for %d.%d\n", - frame, - slot, - txt_nfapi_nr_ul_config_pdu_type[type], - UL_tti_req->SFN, - UL_tti_req->Slot); - switch (type) { - case NFAPI_NR_UL_CONFIG_PUSCH_PDU_TYPE: - nr_fill_ulsch(gNB, UL_tti_req->SFN, UL_tti_req->Slot, &UL_tti_req->pdus_list[i].pusch_pdu); - break; - case NFAPI_NR_UL_CONFIG_PUCCH_PDU_TYPE: - nr_fill_pucch(gNB, UL_tti_req->SFN, UL_tti_req->Slot, &UL_tti_req->pdus_list[i].pucch_pdu); - break; - case NFAPI_NR_UL_CONFIG_PRACH_PDU_TYPE: { - nfapi_nr_prach_pdu_t *prach_pdu = &UL_tti_req->pdus_list[i].prach_pdu; - prach_item_t *prach = nr_schedule_rx_prach(gNB, UL_tti_req->SFN, UL_tti_req->Slot, prach_pdu); - if (!prach) - LOG_W(NR_PHY_RACH, "Error in scheduling rach\n"); - } break; - case NFAPI_NR_UL_CONFIG_SRS_PDU_TYPE: - nr_fill_srs(gNB, UL_tti_req->SFN, UL_tti_req->Slot, &UL_tti_req->pdus_list[i].srs_pdu); - break; - } - } -} - -void nr_schedule_tx_req(PHY_VARS_gNB *gNB, nfapi_nr_tx_data_request_t *TX_req) -{ - DevAssert(gNB != NULL); - DevAssert(TX_req != NULL); - processingData_L1tx_t *msgTx = gNB->msgDataTx; - - for (int idx = 0; idx < TX_req->Number_of_PDUs; ++idx) { - uint8_t *sdu = (uint8_t *)TX_req->pdu_list[idx].TLVs[0].value.direct; - nr_fill_dlsch_tx_req(msgTx, idx, sdu); - } -} - -void nr_schedule_ul_dci_req(PHY_VARS_gNB *gNB, nfapi_nr_ul_dci_request_t *UL_dci_req) -{ - DevAssert(gNB != NULL); - DevAssert(UL_dci_req != NULL); - processingData_L1tx_t *msgTx = gNB->msgDataTx; - - msgTx->num_ul_pdcch = UL_dci_req->numPdus; - for (int i = 0; i < UL_dci_req->numPdus; i++) - msgTx->ul_pdcch_pdu[i] = UL_dci_req->ul_dci_pdu_list[i]; -} - -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; - frame_t frame = Sched_INFO->frame; - slot_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); - - PHY_VARS_gNB *gNB = RC.gNB[Mod_id]; - start_meas(&gNB->schedule_response_stats); - - nfapi_nr_config_request_scf_t *cfg = &gNB->gNB_config; - - int slot_type = nr_slot_select(cfg, frame, slot); - - clear_slot_beamid(gNB, slot); // reset beam_id information for the slot to be processed - DevAssert(NFAPI_MODE == NFAPI_MONOLITHIC); - bool is_dl = slot_type == NR_DOWNLINK_SLOT || slot_type == NR_MIXED_SLOT; - - processingData_L1tx_t *msgTx = gNB->msgDataTx; - /* store the sched_response_id for the TX thread to release it when done */ - msgTx->sched_response_id = Sched_INFO->sched_response_id; - - DevAssert(Sched_INFO->DL_req.SFN == frame); - DevAssert(Sched_INFO->DL_req.Slot == slot); - - if (is_dl) { - nr_schedule_dl_tti_req(gNB, &Sched_INFO->DL_req); - } - - nr_schedule_ul_tti_req(gNB, &Sched_INFO->UL_tti_req); - - if (is_dl) { - nr_schedule_tx_req(gNB, &Sched_INFO->TX_req); - - nr_schedule_ul_dci_req(gNB, &Sched_INFO->UL_dci_req); - /* 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); - } - - /* this thread is done with the sched_info, decrease the reference counter */ - if ((slot_type == NR_DOWNLINK_SLOT || slot_type == NR_MIXED_SLOT) && NFAPI_MODE == NFAPI_MONOLITHIC) { - LOG_D(NR_PHY, "Calling dref_sched_response for id %d in %d.%d (sched_response)\n", Sched_INFO->sched_response_id, frame, slot); - deref_sched_response(Sched_INFO->sched_response_id); - } - stop_meas(&gNB->schedule_response_stats); -} diff --git a/openair1/SCHED_NR/fapi_nr_l1.h b/openair1/SCHED_NR/fapi_nr_l1.h deleted file mode 100644 index 59df4fb30d..0000000000 --- a/openair1/SCHED_NR/fapi_nr_l1.h +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The OpenAirInterface Software Alliance licenses this file to You under - * the OAI Public License, Version 1.1 (the "License"); you may not use this file - * except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.openairinterface.org/?page_id=698 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - *------------------------------------------------------------------------------- - * For more information about the OpenAirInterface (OAI) Software Alliance: - * contact@openairinterface.org - */ - -/*! \file fapi_nr_l1.h - * \brief function prototypes for FAPI L1 interface - * \author R. Knopp, WEI-TAI CHEN - * \date 2017, 2018 - * \version 0.1 - * \company Eurecom, NTUST - * \email: knopp@eurecom.fr, kroempa@gmail.com - * \note - * \warning - */ - -#include "PHY/defs_gNB.h" -#include "SCHED_NR/sched_nr.h" -#include "nfapi_nr_interface_scf.h" - -// added -void handle_nr_nfapi_ssb_pdu(processingData_L1tx_t *msgTx, - int frame,int slot, - nfapi_nr_dl_tti_request_pdu_t *dl_tti_pdu); - -void nr_schedule_response(NR_Sched_Rsp_t *Sched_INFO); - -void handle_nfapi_nr_csirs_pdu(processingData_L1tx_t *msgTx, - int frame, int slot, - nfapi_nr_dl_tti_csi_rs_pdu *csirs_pdu); - -void handle_nfapi_nr_pdcch_pdu(PHY_VARS_gNB *gNB, - int frame, int subframe, - nfapi_nr_dl_tti_pdcch_pdu *dcl_dl_pdu); - -void handle_nr_nfapi_pdsch_pdu(processingData_L1tx_t *msgTx, - nfapi_nr_dl_tti_pdsch_pdu *pdsch_pdu, - uint8_t *sdu); - -void nr_fill_indication(PHY_VARS_gNB *gNB, - int frame, - int slot_rx, - int UE_id, - uint8_t harq_pid, - uint8_t crc_flag, - int dtx_flag, - nfapi_nr_crc_t *crc, - nfapi_nr_rx_data_pdu_t *pdu); -//added - -void handle_nfapi_nr_ul_dci_pdu(PHY_VARS_gNB *gNB, - int frame, int slot, - nfapi_nr_ul_dci_request_pdus_t *ul_dci_request_pdu); diff --git a/openair1/SCHED_NR/nr_prach_procedures.c b/openair1/SCHED_NR/nr_prach_procedures.c index e6cd15b4a9..d5d6a8860e 100644 --- a/openair1/SCHED_NR/nr_prach_procedures.c +++ b/openair1/SCHED_NR/nr_prach_procedures.c @@ -33,7 +33,6 @@ #include "PHY/defs_gNB.h" #include "PHY/NR_TRANSPORT/nr_transport_proto.h" #include "nfapi_nr_interface_scf.h" -#include "fapi_nr_l1.h" #include "nfapi_pnf.h" #include "common/utils/LOG/log.h" #include "common/utils/LOG/vcd_signal_dumper.h" diff --git a/openair1/SCHED_NR/phy_frame_config_nr.c b/openair1/SCHED_NR/phy_frame_config_nr.c index 085ce8e087..9479e960a8 100644 --- a/openair1/SCHED_NR/phy_frame_config_nr.c +++ b/openair1/SCHED_NR/phy_frame_config_nr.c @@ -152,7 +152,7 @@ void set_tdd_config_nr(nfapi_nr_config_request_scf_t *cfg, frame_structure_t *fs } } -int nr_slot_select(nfapi_nr_config_request_scf_t *cfg, int nr_frame, int nr_slot) +int nr_slot_select(const nfapi_nr_config_request_scf_t *cfg, int nr_frame, int nr_slot) { (void) nr_frame; diff --git a/openair1/SCHED_NR/phy_frame_config_nr.h b/openair1/SCHED_NR/phy_frame_config_nr.h index 11ae4bf5c6..687fd2bc51 100644 --- a/openair1/SCHED_NR/phy_frame_config_nr.h +++ b/openair1/SCHED_NR/phy_frame_config_nr.h @@ -53,7 +53,7 @@ void set_tdd_config_nr(nfapi_nr_config_request_scf_t *cfg, frame_structure_t *fs * @param nr_slot : slot number @returns int : downlink, uplink or mixed slot type*/ -int nr_slot_select(nfapi_nr_config_request_scf_t *cfg, int nr_frame, int nr_slot); +int nr_slot_select(const nfapi_nr_config_request_scf_t *cfg, int nr_frame, int nr_slot); void do_tdd_config_sim(PHY_VARS_gNB *gNB, int mu); diff --git a/openair1/SCHED_NR/phy_procedures_nr_gNB.c b/openair1/SCHED_NR/phy_procedures_nr_gNB.c index 51e8c771e5..e9ff83cf40 100644 --- a/openair1/SCHED_NR/phy_procedures_nr_gNB.c +++ b/openair1/SCHED_NR/phy_procedures_nr_gNB.c @@ -27,7 +27,6 @@ #include "PHY/NR_TRANSPORT/nr_dci.h" #include "PHY/NR_ESTIMATION/nr_ul_estimation.h" #include "nfapi/open-nFAPI/nfapi/public_inc/nfapi_interface.h" -#include "fapi_nr_l1.h" #include "common/utils/LOG/log.h" #include "common/utils/LOG/vcd_signal_dumper.h" #include "PHY/INIT/nr_phy_init.h" @@ -45,10 +44,29 @@ //#define DEBUG_RXDATA //#define SRS_IND_DEBUG +static void nr_fill_indication(PHY_VARS_gNB *gNB, + int frame, + int slot_rx, + int UE_id, + uint8_t harq_pid, + uint8_t crc_flag, + int dtx_flag, + nfapi_nr_crc_t *crc, + nfapi_nr_rx_data_pdu_t *pdu); + +static void nr_fill_indication(PHY_VARS_gNB *gNB, + int frame, + int slot_rx, + int ULSCH_id, + uint8_t harq_pid, + uint8_t crc_flag, + int dtx_flag, + nfapi_nr_crc_t *crc, + nfapi_nr_rx_data_pdu_t *pdu); int beam_index_allocation(bool das, int fapi_beam_index, - nfapi_nr_analog_beamforming_ve_t *analog_bf, + const nfapi_nr_analog_beamforming_ve_t *analog_bf, NR_gNB_COMMON *common_vars, int slot, int symbols_per_slot, @@ -84,10 +102,10 @@ int beam_index_allocation(bool das, return idx; } -void nr_common_signal_procedures(PHY_VARS_gNB *gNB, int frame, int slot, nfapi_nr_dl_tti_ssb_pdu ssb_pdu) +void nr_common_signal_procedures(PHY_VARS_gNB *gNB, int frame, int slot, const nfapi_nr_dl_tti_ssb_pdu *ssb_pdu) { NR_DL_FRAME_PARMS *fp = &gNB->frame_parms; - nfapi_nr_dl_tti_ssb_pdu_rel15_t *pdu = &ssb_pdu.ssb_pdu_rel15; + const nfapi_nr_dl_tti_ssb_pdu_rel15_t *pdu = &ssb_pdu->ssb_pdu_rel15; uint8_t ssb_index = pdu->SsbBlockIndex; LOG_D(PHY,"common_signal_procedures: frame %d, slot %d ssb index %d\n", frame, slot, ssb_index); @@ -135,7 +153,7 @@ void nr_common_signal_procedures(PHY_VARS_gNB *gNB, int frame, int slot, nfapi_n fp->ssb_start_subcarrier); LOG_D(PHY,"SS TX: frame %d, slot %d, start_symbol %d\n", frame, slot, ssb_start_symbol); - nfapi_nr_tx_precoding_and_beamforming_t *pb = &pdu->precoding_and_beamforming; + const nfapi_nr_tx_precoding_and_beamforming_t *pb = &pdu->precoding_and_beamforming; c16_t ***txdataF = gNB->common_vars.txdataF; int txdataF_offset = slot * fp->samples_per_slot_wCP; // beam number in a scenario with multiple concurrent beams @@ -173,7 +191,7 @@ void nr_common_signal_procedures(PHY_VARS_gNB *gNB, int frame, int slot, nfapi_n #endif nr_generate_pbch(gNB, - &ssb_pdu, + ssb_pdu, &txdataF[beam_nb][0][txdataF_offset], ssb_start_symbol, n_hf, @@ -186,24 +204,64 @@ void nr_common_signal_procedures(PHY_VARS_gNB *gNB, int frame, int slot, nfapi_n void clear_slot_beamid(PHY_VARS_gNB *gNB, int slot) { LOG_D(PHY, "Clearing beam_id structure for slot %d\n", slot); - NR_DL_FRAME_PARMS *fp = &gNB->frame_parms; + int slot_sz = gNB->frame_parms.symbols_per_slot; for (int i = 0; i < gNB->common_vars.num_beams_period; i++) { if (gNB->common_vars.beam_id) - memset(&gNB->common_vars.beam_id[i][slot * fp->symbols_per_slot], -1, fp->symbols_per_slot * sizeof(int)); + memset(&gNB->common_vars.beam_id[i][slot * slot_sz], -1, slot_sz * sizeof(**gNB->common_vars.beam_id)); } } -void phy_procedures_gNB_TX(processingData_L1tx_t *msgTx, +static void nr_generate_csi_rs_gNB(PHY_VARS_gNB *gNB, + int slot, + const nfapi_nr_config_request_scf_t *cfg, + const nfapi_nr_dl_tti_csi_rs_pdu *csi_rs_pdu) +{ + const nfapi_nr_dl_tti_csi_rs_pdu_rel15_t *csi_params = &csi_rs_pdu->csi_rs_pdu_rel15; + if (csi_params->csi_type == 2) // ZP-CSI + return; + + csi_mapping_parms_t mapping_parms = + get_csi_mapping_parms(csi_params->row, csi_params->freq_domain, csi_params->symb_l0, csi_params->symb_l1); + const nfapi_nr_tx_precoding_and_beamforming_t *pb = &csi_params->precodingAndBeamforming; + int csi_bitmap = 0; + int lprime_num = mapping_parms.lprime + 1; + for (int j = 0; j < mapping_parms.size; j++) + csi_bitmap |= ((1 << lprime_num) - 1) << mapping_parms.loverline[j]; + int beam_nb = beam_index_allocation(gNB->enable_analog_das, + pb->prgs_list[0].dig_bf_interface_list[0].beam_idx, + &cfg->analog_beamforming_ve, + &gNB->common_vars, + slot, + gNB->frame_parms.symbols_per_slot, + csi_bitmap); + + nr_generate_csi_rs(&gNB->frame_parms, + &mapping_parms, + gNB->TX_AMP, + slot, + csi_params->freq_density, + csi_params->start_rb, + csi_params->nr_of_rbs, + csi_params->symb_l0, + csi_params->symb_l1, + csi_params->row, + csi_params->scramb_id, + csi_params->power_control_offset_ss, + csi_params->cdm_type, + gNB->common_vars.txdataF[beam_nb]); +} + +void phy_procedures_gNB_TX(PHY_VARS_gNB *gNB, + const nfapi_nr_dl_tti_request_t *DL_req, + const nfapi_nr_tx_data_request_t *TX_req, + const nfapi_nr_ul_dci_request_t *UL_dci_req, int frame, int slot, int do_meas) { - PHY_VARS_gNB *gNB = msgTx->gNB; - NR_DL_FRAME_PARMS *fp = &gNB->frame_parms; + const NR_DL_FRAME_PARMS *fp = &gNB->frame_parms; nfapi_nr_config_request_scf_t *cfg = &gNB->gNB_config; - int slot_prs = 0; - int txdataF_offset = slot * fp->samples_per_slot_wCP; - prs_config_t *prs_config = NULL; + const int txdataF_offset = slot * fp->samples_per_slot_wCP; if ((cfg->cell_config.frame_duplex_type.value == TDD) && (nr_slot_select(cfg,frame,slot) == NR_UPLINK_SLOT)) return; @@ -213,101 +271,60 @@ void phy_procedures_gNB_TX(processingData_L1tx_t *msgTx, // clear the transmit data array and beam index for the current slot for (int i = 0; i < gNB->common_vars.num_beams_period; i++) { for (int aa = 0; aa < cfg->carrier_config.num_tx_ant.value; aa++) { - memset(&gNB->common_vars.txdataF[i][aa][txdataF_offset], 0, fp->samples_per_slot_wCP * sizeof(int32_t)); + memset(&gNB->common_vars.txdataF[i][aa][txdataF_offset], 0, fp->samples_per_slot_wCP * sizeof(***gNB->common_vars.txdataF)); } } // Check for PRS slot - section 7.4.1.7.4 in 3GPP rel16 38.211 for(int rsc_id = 0; rsc_id < gNB->prs_vars.NumPRSResources; rsc_id++) { - prs_config = &gNB->prs_vars.prs_cfg[rsc_id]; + prs_config_t *prs_config = &gNB->prs_vars.prs_cfg[rsc_id]; for (int i = 0; i < prs_config->PRSResourceRepetition; i++) { if( (((frame*fp->slots_per_frame + slot) - (prs_config->PRSResourceSetPeriod[1] + prs_config->PRSResourceOffset)+prs_config->PRSResourceSetPeriod[0])%prs_config->PRSResourceSetPeriod[0]) == i*prs_config->PRSResourceTimeGap ) { - slot_prs = (slot - i*prs_config->PRSResourceTimeGap + fp->slots_per_frame)%fp->slots_per_frame; + int slot_prs = (slot - i * prs_config->PRSResourceTimeGap + fp->slots_per_frame) % fp->slots_per_frame; LOG_D(PHY,"gNB_TX: frame %d, slot %d, slot_prs %d, PRS Resource ID %d\n",frame, slot, slot_prs, rsc_id); nr_generate_prs(slot_prs, &gNB->common_vars.txdataF[0][0][txdataF_offset], AMP, prs_config, cfg, fp); } } } - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_gNB_COMMON_TX,1); - for (int i = 0; i < fp->Lmax; i++) { - if (msgTx->ssb[i].active) { - nr_common_signal_procedures(gNB, frame, slot, msgTx->ssb[i].ssb_pdu); - msgTx->ssb[i].active = false; + for (int i = 0; i < UL_dci_req->numPdus; ++i) + nr_generate_dci(gNB, &UL_dci_req->ul_dci_pdu_list[i].pdcch_pdu.pdcch_pdu_rel15, txdataF_offset, &gNB->frame_parms, slot); + + int num_pdsch = 0; + for (int i = 0; i < DL_req->dl_tti_request_body.nPDUs; ++i) { + const nfapi_nr_dl_tti_request_pdu_t *dl_tti_pdu = &DL_req->dl_tti_request_body.dl_tti_pdu_list[i]; + switch (dl_tti_pdu->PDUType) { + case NFAPI_NR_DL_TTI_SSB_PDU_TYPE: + nr_common_signal_procedures(gNB, frame, slot, &dl_tti_pdu->ssb_pdu); + break; + case NFAPI_NR_DL_TTI_PDCCH_PDU_TYPE: + nr_generate_dci(gNB, &dl_tti_pdu->pdcch_pdu.pdcch_pdu_rel15, txdataF_offset, &gNB->frame_parms, slot); + break; + case NFAPI_NR_DL_TTI_CSI_RS_PDU_TYPE: + nr_generate_csi_rs_gNB(gNB, slot, cfg, &dl_tti_pdu->csi_rs_pdu); + break; + case NFAPI_NR_DL_TTI_PDSCH_PDU_TYPE: { + int tx_data_idx = dl_tti_pdu->pdsch_pdu.pdsch_pdu_rel15.pduIndex; + DevAssert(tx_data_idx < TX_req->Number_of_PDUs); + // reuse dlsch variables, as there are multiple very large memory + // buffers + gNB->dlsch[num_pdsch].pdsch_pdu = &dl_tti_pdu->pdsch_pdu; + gNB->dlsch[num_pdsch].pdu = (uint8_t *)TX_req->pdu_list[tx_data_idx].TLVs[0].value.direct; + DevAssert(num_pdsch < gNB->max_nb_pdsch); + num_pdsch++; + } break; } } - - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_gNB_COMMON_TX,0); - - int num_pdcch_pdus = msgTx->num_ul_pdcch + msgTx->num_dl_pdcch; - - if (num_pdcch_pdus > 0) { - LOG_D(PHY, "[gNB %d] Frame %d slot %d Calling nr_generate_dci_top (number of UL/DL PDCCH PDUs %d/%d)\n", - gNB->Mod_id, frame, slot, msgTx->num_ul_pdcch, msgTx->num_dl_pdcch); - - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_gNB_PDCCH_TX,1); - - nr_generate_dci_top(msgTx, slot, txdataF_offset); - - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_gNB_PDCCH_TX,0); - } - msgTx->num_dl_pdcch = 0; - msgTx->num_ul_pdcch = 0; - if (msgTx->num_pdsch_slot > 0) { + if (num_pdsch > 0) { VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_GENERATE_DLSCH,1); - LOG_D(PHY, "PDSCH generation started (%d) in frame %d.%d\n", msgTx->num_pdsch_slot,frame,slot); - nr_generate_pdsch(msgTx, frame, slot); + LOG_D(PHY, "PDSCH generation started (%d) in frame %d.%d\n", num_pdsch, frame, slot); + nr_generate_pdsch(gNB, num_pdsch, gNB->dlsch, frame, slot); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_GENERATE_DLSCH,0); } - msgTx->num_pdsch_slot = 0; - - for (int i = 0; i < NR_SYMBOLS_PER_SLOT; i++){ - NR_gNB_CSIRS_t *csirs = &msgTx->csirs_pdu[i]; - if (csirs->active == 1) { - LOG_D(PHY, "CSI-RS generation started in frame %d.%d\n",frame,slot); - nfapi_nr_dl_tti_csi_rs_pdu_rel15_t *csi_params = &csirs->csirs_pdu.csi_rs_pdu_rel15; - if (csi_params->csi_type == 2) { // ZP-CSI - csirs->active = 0; - return; - } - csi_mapping_parms_t mapping_parms = get_csi_mapping_parms(csi_params->row, - csi_params->freq_domain, - csi_params->symb_l0, - csi_params->symb_l1); - nfapi_nr_tx_precoding_and_beamforming_t *pb = &csi_params->precodingAndBeamforming; - int csi_bitmap = 0; - int lprime_num = mapping_parms.lprime + 1; - for (int j = 0; j < mapping_parms.size; j++) - csi_bitmap |= ((1 << lprime_num) - 1) << mapping_parms.loverline[j]; - int beam_nb = beam_index_allocation(gNB->enable_analog_das, - pb->prgs_list[0].dig_bf_interface_list[0].beam_idx, - &cfg->analog_beamforming_ve, - &gNB->common_vars, - slot, - fp->symbols_per_slot, - csi_bitmap); - - nr_generate_csi_rs(&gNB->frame_parms, - &mapping_parms, - gNB->TX_AMP, - slot, - csi_params->freq_density, - csi_params->start_rb, - csi_params->nr_of_rbs, - csi_params->symb_l0, - csi_params->symb_l1, - csi_params->row, - csi_params->scramb_id, - csi_params->power_control_offset_ss, - csi_params->cdm_type, - gNB->common_vars.txdataF[beam_nb]); - csirs->active = 0; - } - } //apply the OFDM symbol rotation here start_meas(&gNB->phase_comp_stats); @@ -537,24 +554,24 @@ static int nr_ulsch_procedures(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, boo return ret_nr_ulsch_decoding; } -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, - nfapi_nr_crc_t *crc, - nfapi_nr_rx_data_pdu_t *pdu) +static 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, + nfapi_nr_crc_t *crc, + nfapi_nr_rx_data_pdu_t *pdu) { - 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); + NR_UL_gNB_HARQ_t *harq_process = gNB->ulsch[ULSCH_id].harq_process; + NR_gNB_PHY_STATS_t *stats = get_phy_stats(gNB, gNB->ulsch[ULSCH_id].rnti); + NR_gNB_PUSCH *pusch = &gNB->pusch_vars[ULSCH_id]; nfapi_nr_pusch_pdu_t *pusch_pdu = &harq_process->ulsch_pdu; // Get estimated timing advance for MAC - int sync_pos = ulsch->delay.est_delay; + const int sync_pos = gNB->ulsch[ULSCH_id].delay.est_delay; // scale the 16 factor in N_TA calculation in 38.213 section 4.2 according to the used FFT size uint16_t bw_scaling = 16 * gNB->frame_parms.ofdm_symbol_size / 2048; @@ -584,16 +601,15 @@ void nr_fill_indication(PHY_VARS_gNB *gNB, 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(pusch->ulsch_power_tot) - dB_fixed_x10(pusch->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, + dB_fixed_x10(pusch->ulsch_power_tot) / 10.0, + dB_fixed_x10(pusch->ulsch_noise_power_tot) / 10.0, sync_pos); int cqi; @@ -609,8 +625,7 @@ void nr_fill_indication(PHY_VARS_gNB *gNB, crc->ul_cqi = cqi; crc->timing_advance = timing_advance_update; // in terms of dBFS range -128 to 0 with 0.1 step - crc->rssi = - (dtx_flag == 0) ? 1280 - (10 * dB_fixed(32767 * 32767) - dB_fixed_times10(gNB->pusch_vars[ULSCH_id].ulsch_power[0])) : 0; + crc->rssi = (dtx_flag == 0) ? 1280 - (10 * dB_fixed(32767 * 32767) - dB_fixed_times10(pusch->ulsch_power[0])) : 0; pdu->handle = pusch_pdu->handle; pdu->rnti = pusch_pdu->rnti; @@ -627,18 +642,18 @@ void nr_fill_indication(PHY_VARS_gNB *gNB, } // Function to fill UL RB mask to be used for N0 measurements -static void fill_ul_rb_mask(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, uint32_t rb_mask_ul[14][9]) +static void fill_ul_rb_mask(PHY_VARS_gNB *gNB, + int frame_rx, + int slot_rx, + uint32_t rb_mask_ul[14][9], + nfapi_nr_max_num_of_symbol_per_slot_t *slot_conf) { - int rb = 0; - int rb2 = 0; - int prbpos = 0; - for (int symbol = 0; symbol < 14; symbol++) { for (int m = 0; m < 9; m++) { rb_mask_ul[symbol][m] = 0; for (int i = 0; i < 32; i++) { - prbpos = (m * 32) + i; - if (prbpos>gNB->frame_parms.N_RB_UL) + int prbpos = (m * 32) + i; + if (prbpos > gNB->frame_parms.N_RB_UL) break; rb_mask_ul[symbol][m] |= (gNB->ulprbbl[prbpos] > 0 ? 1U : 0) << i; } @@ -646,23 +661,27 @@ static void fill_ul_rb_mask(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, uint32 } for (int i = 0; i < gNB->max_nb_pucch; i++){ - NR_gNB_PUCCH_t *pucch = &gNB->pucch[i]; - if (pucch) { - if ((pucch->active == 1) && - (pucch->frame == frame_rx) && - (pucch->slot == slot_rx) ) { - nfapi_nr_pucch_pdu_t *pucch_pdu = &pucch->pucch_pdu; - LOG_D(PHY,"%d.%d pucch %d : start_symbol %d, nb_symbols %d, prb_size %d\n",frame_rx,slot_rx,i,pucch_pdu->start_symbol_index,pucch_pdu->nr_of_symbols,pucch_pdu->prb_size); - for (int symbol=pucch_pdu->start_symbol_index ; symbol<(pucch_pdu->start_symbol_index+pucch_pdu->nr_of_symbols);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)) { - for (rb=0; rbprb_size; rb++) { - rb2 = rb + pucch_pdu->bwp_start + - ((symbol < pucch_pdu->start_symbol_index+(pucch_pdu->nr_of_symbols>>1)) || (pucch_pdu->freq_hop_flag == 0) ? - pucch_pdu->prb_start : pucch_pdu->second_hop_prb); - rb_mask_ul[symbol][rb2>>5] |= (((uint32_t)1)<<(rb2&31)); - } - } + const NR_gNB_PUCCH_t *pucch = gNB->pucch + i; + if (!(pucch && pucch->active && pucch->frame == frame_rx && pucch->slot == slot_rx)) + continue; + const nfapi_nr_pucch_pdu_t *pucch_pdu = &pucch->pucch_pdu; + const int start = pucch_pdu->start_symbol_index; + LOG_D(PHY, + "%d.%d pucch %d : start_symbol %d, nb_symbols %d, prb_size %d\n", + frame_rx, + slot_rx, + i, + start, + pucch_pdu->nr_of_symbols, + pucch_pdu->prb_size); + for (int symbol = start; symbol < (start + pucch_pdu->nr_of_symbols); symbol++) { + if (gNB->frame_parms.frame_type == FDD || (gNB->frame_parms.frame_type == TDD && slot_conf[symbol].slot_config.value == 1)) { + for (int rb = 0; rb < pucch_pdu->prb_size; rb++) { + int rb2 = + rb + pucch_pdu->bwp_start + + ((symbol < start + (pucch_pdu->nr_of_symbols >> 1)) || (pucch_pdu->freq_hop_flag == 0) ? pucch_pdu->prb_start + : pucch_pdu->second_hop_prb); + rb_mask_ul[symbol][rb2 >> 5] |= 1U << (rb2 & 31); } } } @@ -672,21 +691,16 @@ static void fill_ul_rb_mask(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, uint32 NR_gNB_ULSCH_t *ulsch = &gNB->ulsch[ULSCH_id]; NR_UL_gNB_HARQ_t *ulsch_harq = ulsch->harq_process; AssertFatal(ulsch_harq != NULL, "harq_pid %d is not allocated\n", ulsch->harq_pid); - if ((ulsch->active == 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; - rb_mask_ul[symbol][rb2 >> 5] |= 1U << (rb2 & 31); - } + if (!(ulsch->active && ulsch->frame == frame_rx && ulsch->slot == slot_rx && !ulsch->handled)) + continue; + uint8_t symbol_start = ulsch_harq->ulsch_pdu.start_symbol_index; + uint8_t symbol_end = symbol_start + ulsch_harq->ulsch_pdu.nr_of_symbols; + for (int symbol = symbol_start; symbol < symbol_end; symbol++) { + if (gNB->frame_parms.frame_type == FDD || (gNB->frame_parms.frame_type == TDD && slot_conf[symbol].slot_config.value == 1)) { + LOG_D(PHY, "symbol %d Filling rb_mask_ul rb_size %d\n", symbol, ulsch_harq->ulsch_pdu.rb_size); + for (int rb = 0; rb < ulsch_harq->ulsch_pdu.rb_size; rb++) { + int rb2 = rb + ulsch_harq->ulsch_pdu.rb_start + ulsch_harq->ulsch_pdu.bwp_start; + rb_mask_ul[symbol][rb2 >> 5] |= 1U << (rb2 & 31); } } } @@ -694,52 +708,59 @@ static void fill_ul_rb_mask(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, uint32 for (int i = 0; i < gNB->max_nb_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; - for(int symbol = 0; symbol < (1 << srs_pdu->num_symbols); symbol++) { - for(rb = srs_pdu->bwp_start; rb < (srs_pdu->bwp_start+srs_pdu->bwp_size); rb++) { - rb_mask_ul[srs_pdu->time_start_position + symbol][rb >> 5] |= 1U << (rb & 31); - } - } + if (!(srs && srs->active && srs->frame == frame_rx && srs->slot == slot_rx)) + continue; + nfapi_nr_srs_pdu_t *srs_pdu = &srs->srs_pdu; + for (int symbol = 0; symbol < (1 << srs_pdu->num_symbols); symbol++) { + for (int rb = srs_pdu->bwp_start; rb < (srs_pdu->bwp_start + srs_pdu->bwp_size); rb++) { + rb_mask_ul[srs_pdu->time_start_position + symbol][rb >> 5] |= 1U << (rb & 31); } } } } -int fill_srs_reported_symbol(nfapi_nr_srs_reported_symbol_t *reported_symbol, - const nfapi_nr_srs_pdu_t *srs_pdu, - const int N_RB_UL, - const int16_t *snr_per_rb, - const int srs_est) { +static int fill_srs_reported_symbol(nfapi_nr_srs_reported_symbol_t *reported_symbol, + const nfapi_nr_srs_pdu_t *srs_pdu, + const int N_RB_UL, + const int16_t *snr_per_rb, + const int srs_est) +{ reported_symbol->num_prgs = srs_pdu->beamforming.num_prgs; for (int prg_idx = 0; prg_idx < reported_symbol->num_prgs; prg_idx++) { - if (srs_est<0) { - reported_symbol->prg_list[prg_idx].rb_snr = 0xFF; + uint8_t *snr = &reported_symbol->prg_list[prg_idx].rb_snr; + if (srs_est < 0) { + *snr = 0xFF; } else if (snr_per_rb[prg_idx] < -64) { - reported_symbol->prg_list[prg_idx].rb_snr = 0; + *snr = 0; } else if (snr_per_rb[prg_idx] > 63) { - reported_symbol->prg_list[prg_idx].rb_snr = 0xFE; + *snr = 0xFE; } else { - reported_symbol->prg_list[prg_idx].rb_snr = (snr_per_rb[prg_idx] + 64) << 1; + *snr = (snr_per_rb[prg_idx] + 64) << 1; } } return 0; } -int fill_srs_channel_matrix(uint8_t *channel_matrix, - const nfapi_nr_srs_pdu_t *srs_pdu, - const nr_srs_info_t *nr_srs_info, - const uint8_t normalized_iq_representation, - const uint16_t num_gnb_antenna_elements, - const uint16_t num_ue_srs_ports, - const uint16_t prg_size, - const uint16_t num_prgs, - const NR_DL_FRAME_PARMS *frame_parms, - const c16_t srs_estimated_channel_freq[][1 << srs_pdu->num_ant_ports] - [frame_parms->ofdm_symbol_size * (1 << srs_pdu->num_symbols)]) +static int fill_srs_channel_matrix( + nfapi_nr_srs_normalized_channel_iq_matrix_t *nr_srs_channel_iq_matrix, + const nfapi_nr_srs_pdu_t *srs_pdu, + const nr_srs_info_t *nr_srs_info, + const uint8_t normalized_iq_representation, + const uint16_t num_gnb_antenna_elements, + const uint16_t num_ue_srs_ports, + const uint16_t prg_size, + const uint16_t num_prgs, + const NR_DL_FRAME_PARMS *frame_parms, + const c16_t srs_estimated_channel_freq[][1 << srs_pdu->num_ant_ports] + [frame_parms->ofdm_symbol_size * (1 << srs_pdu->num_symbols)]) { + nr_srs_channel_iq_matrix->normalized_iq_representation = normalized_iq_representation; + nr_srs_channel_iq_matrix->num_gnb_antenna_elements = num_gnb_antenna_elements; + nr_srs_channel_iq_matrix->num_ue_srs_ports = num_ue_srs_ports; + nr_srs_channel_iq_matrix->prg_size = prg_size; + nr_srs_channel_iq_matrix->num_prgs = num_prgs; + uint8_t *channel_matrix = nr_srs_channel_iq_matrix->channel_matrix; const uint64_t subcarrier_offset = frame_parms->first_carrier_offset + srs_pdu->bwp_start*NR_NB_SC_PER_RB; const uint16_t step = prg_size*NR_NB_SC_PER_RB; @@ -837,75 +858,73 @@ int phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, N int pusch_decode_done = 0; int pusch_DTX = 0; + const NR_DL_FRAME_PARMS *frame_parms = &gNB->frame_parms; + const int symb_sz = frame_parms->ofdm_symbol_size; + const int nb_symb = frame_parms->symbols_per_slot; + const int ant = gNB->frame_parms.nb_antennas_rx; VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_gNB_UESPEC_RX,1); LOG_D(PHY,"phy_procedures_gNB_uespec_RX frame %d, slot %d\n",frame_rx,slot_rx); - // Mask of occupied RBs, per symbol and PRB - uint32_t rb_mask_ul[14][9]; - fill_ul_rb_mask(gNB, frame_rx, slot_rx, rb_mask_ul); + { + // Mask of occupied RBs, per symbol and PRB + uint32_t rb_mask_ul[14][9]; + nfapi_nr_max_num_of_symbol_per_slot_t *slot_conf = NULL; + if (frame_parms->frame_type == TDD) + slot_conf = gNB->gNB_config.tdd_table.max_tdd_periodicity_list[slot_rx].max_num_of_symbol_per_slot_list; + fill_ul_rb_mask(gNB, frame_rx, slot_rx, rb_mask_ul, slot_conf); - int first_symb=0,num_symb=0; - if (gNB->frame_parms.frame_type == TDD) - for(int symbol_count=0; symbol_countgNB_config.tdd_table.max_tdd_periodicity_list[slot_rx].max_num_of_symbol_per_slot_list[symbol_count].slot_config.value==1) { - if (num_symb==0) first_symb=symbol_count; - num_symb++; + int first_symb = 0, num_symb = 0; + if (frame_parms->frame_type == TDD) + for (int symbol_count = 0; symbol_count < NR_NUMBER_OF_SYMBOLS_PER_SLOT; symbol_count++) { + if (slot_conf[symbol_count].slot_config.value == 1) { + if (num_symb == 0) + first_symb = symbol_count; + num_symb++; + } } - } - else - num_symb = NR_NUMBER_OF_SYMBOLS_PER_SLOT; - gNB_I0_measurements(gNB, slot_rx, first_symb, num_symb, rb_mask_ul); + else + num_symb = NR_NUMBER_OF_SYMBOLS_PER_SLOT; + gNB_I0_measurements(gNB, slot_rx, first_symb, num_symb, rb_mask_ul); + } - const int soffset = (slot_rx & 3) * gNB->frame_parms.symbols_per_slot * gNB->frame_parms.ofdm_symbol_size; + const int soffset = (slot_rx & 3) * nb_symb * symb_sz; start_meas(&gNB->phy_proc_rx); for (int i = 0; i < gNB->max_nb_pucch; i++) { NR_gNB_PUCCH_t *pucch = &gNB->pucch[i]; - if (pucch) { - if (pucch->active && (pucch->frame == frame_rx) && (pucch->slot == slot_rx)) { - c16_t **rxdataF = gNB->common_vars.rxdataF[pucch->beam_nb]; - pucch_decode_done = 1; - nfapi_nr_pucch_pdu_t *pucch_pdu = &pucch->pucch_pdu; - UL_INFO->uci_ind.uci_list = UL_INFO->uci_pdu_list; - nfapi_nr_uci_t *uci = UL_INFO->uci_ind.uci_list + UL_INFO->uci_ind.num_ucis; - switch (pucch_pdu->format_type) { - case 0: - UL_INFO->uci_ind.sfn = frame_rx; - UL_INFO->uci_ind.slot = slot_rx; - uci->pdu_type = NFAPI_NR_UCI_FORMAT_0_1_PDU_TYPE; - uci->pdu_size = sizeof(nfapi_nr_uci_pucch_pdu_format_0_1_t); - nfapi_nr_uci_pucch_pdu_format_0_1_t *uci_pdu_format0 = &uci->pucch_pdu_format_0_1; - - int offset = pucch_pdu->start_symbol_index * gNB->frame_parms.ofdm_symbol_size - + (gNB->frame_parms.first_carrier_offset + pucch_pdu->prb_start * 12); - LOG_D(NR_PHY, - "frame %d, slot %d: PUCCH signal energy %d\n", - frame_rx, - slot_rx, - signal_energy_nodc(&rxdataF[0][soffset + offset], 12)); - - nr_decode_pucch0(gNB, rxdataF, frame_rx, slot_rx, uci_pdu_format0, pucch_pdu); - - UL_INFO->uci_ind.num_ucis += 1; - pucch->active = false; - break; - case 2: - UL_INFO->uci_ind.sfn = frame_rx; - UL_INFO->uci_ind.slot = slot_rx; - uci->pdu_type = NFAPI_NR_UCI_FORMAT_2_3_4_PDU_TYPE; - uci->pdu_size = sizeof(nfapi_nr_uci_pucch_pdu_format_2_3_4_t); - nfapi_nr_uci_pucch_pdu_format_2_3_4_t *uci_pdu_format2 = &uci->pucch_pdu_format_2_3_4; - - LOG_D(PHY, "%d.%d Calling nr_decode_pucch2\n", frame_rx, slot_rx); - nr_decode_pucch2(gNB, rxdataF, frame_rx, slot_rx, uci_pdu_format2, pucch_pdu); - - UL_INFO->uci_ind.num_ucis += 1; - pucch->active = false; - break; - default: - AssertFatal(1 == 0, "Only PUCCH formats 0 and 2 are currently supported\n"); - } - } + if (!(pucch && pucch->active && pucch->frame == frame_rx && pucch->slot == slot_rx)) + continue; + c16_t **rxdataF = gNB->common_vars.rxdataF[pucch->beam_nb]; + pucch_decode_done = 1; + nfapi_nr_pucch_pdu_t *pucch_pdu = &pucch->pucch_pdu; + UL_INFO->uci_ind.uci_list = UL_INFO->uci_pdu_list; + nfapi_nr_uci_t *uci = UL_INFO->uci_ind.uci_list + UL_INFO->uci_ind.num_ucis; + UL_INFO->uci_ind.sfn = frame_rx; + UL_INFO->uci_ind.slot = slot_rx; + switch (pucch_pdu->format_type) { + case 0: + uci->pdu_type = NFAPI_NR_UCI_FORMAT_0_1_PDU_TYPE; + uci->pdu_size = sizeof(nfapi_nr_uci_pucch_pdu_format_0_1_t); + nfapi_nr_uci_pucch_pdu_format_0_1_t *uci_pdu_format0 = &uci->pucch_pdu_format_0_1; + int offset = pucch_pdu->start_symbol_index * symb_sz + (frame_parms->first_carrier_offset + pucch_pdu->prb_start * 12); + LOG_D(NR_PHY, + "frame %d, slot %d: PUCCH signal energy %d\n", + frame_rx, + slot_rx, + signal_energy_nodc(&rxdataF[0][soffset + offset], 12)); + nr_decode_pucch0(gNB, rxdataF, frame_rx, slot_rx, uci_pdu_format0, pucch_pdu); + break; + case 2: + uci->pdu_type = NFAPI_NR_UCI_FORMAT_2_3_4_PDU_TYPE; + uci->pdu_size = sizeof(nfapi_nr_uci_pucch_pdu_format_2_3_4_t); + nfapi_nr_uci_pucch_pdu_format_2_3_4_t *uci_pdu_format2 = &uci->pucch_pdu_format_2_3_4; + LOG_D(PHY, "%d.%d Calling nr_decode_pucch2\n", frame_rx, slot_rx); + nr_decode_pucch2(gNB, rxdataF, frame_rx, slot_rx, uci_pdu_format2, pucch_pdu); + break; + default: + AssertFatal(1 == 0, "Only PUCCH formats 0 and 2 are currently supported\n"); } + UL_INFO->uci_ind.num_ucis += 1; + pucch->active = false; } UL_INFO->crc_ind.sfn = frame_rx; @@ -915,104 +934,103 @@ int phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, N UL_INFO->rx_ind.slot = slot_rx; UL_INFO->rx_ind.pdu_list = UL_INFO->rx_pdu_list; bool ulsch_to_decode[gNB->max_nb_pusch]; - bzero((void *)ulsch_to_decode, sizeof(ulsch_to_decode)); + bzero(ulsch_to_decode, sizeof(ulsch_to_decode)); for (int ULSCH_id = 0; ULSCH_id < gNB->max_nb_pusch; ULSCH_id++) { NR_gNB_ULSCH_t *ulsch = &gNB->ulsch[ULSCH_id]; NR_UL_gNB_HARQ_t *ulsch_harq = ulsch->harq_process; AssertFatal(ulsch_harq != NULL, "harq_pid %d is not allocated\n", ulsch->harq_pid); - if ((ulsch->active == 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); - nfapi_nr_pusch_pdu_t *pdu = &ulsch_harq->ulsch_pdu; - int num_dmrs = count_bits64_with_mask(pdu->ul_dmrs_symb_pos, 0, NR_NUMBER_OF_SYMBOLS_PER_SLOT); + if (!(ulsch->active && ulsch->frame == frame_rx && ulsch->slot == slot_rx && !ulsch->handled)) + continue; + LOG_D(PHY, "PUSCH ID %d with RNTI %x detection started in frame %d slot %d\n", ULSCH_id, ulsch->rnti, frame_rx, slot_rx); + nfapi_nr_pusch_pdu_t *pdu = &ulsch_harq->ulsch_pdu; + int num_dmrs = count_bits64_with_mask(pdu->ul_dmrs_symb_pos, 0, NR_NUMBER_OF_SYMBOLS_PER_SLOT); #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; - int32_t sample_offset = gNB->common_vars.debugBuff_sample_offset; - int16_t *buf = (int16_t *)&gNB->common_vars.debugBuff[offset]; - buf[0] = (int16_t)ulsch->rnti; - buf[1] = (int16_t)pdu->rb_size; - buf[2] = (int16_t)pdu->rb_start; - buf[3] = (int16_t)pdu->nr_of_symbols; - buf[4] = (int16_t)pdu->start_symbol_index; - buf[5] = (int16_t)pdu->mcs_index; - buf[6] = (int16_t)pdu->pusch_data.rv_index; - buf[7] = (int16_t)ulsch->harq_pid; - memcpy(&gNB->common_vars.debugBuff[gNB->common_vars.debugBuff_sample_offset + 4], - &ru->common.rxdata[0][slot_offset], - frame_parms->get_samples_per_slot(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); - } + RU_t *ru = gNB->RU_list[0]; + int slot_offset = frame_parms->get_samples_slot_timestamp(slot_rx, frame_parms, 0); + slot_offset -= ru->N_TA_offset; + int32_t sample_offset = gNB->common_vars.debugBuff_sample_offset; + int16_t buf = (int16_t *)&gNB->common_vars.debugBuff[offset]; + buf[0] = (int16_t)ulsch->rnti; + buf[1] = (int16_t)pdu->rb_size; + buf[2] = (int16_t)pdu->rb_start; + buf[3] = (int16_t)pdu->nr_of_symbols; + buf[4] = (int16_t)pdu->start_symbol_index; + buf[5] = (int16_t)pdu->mcs_index; + buf[6] = (int16_t)pdu->pusch_data.rv_index; + buf[7] = (int16_t)ulsch->harq_pid; + memcpy(&gNB->common_vars.debugBuff[gNB->common_vars.debugBuff_sample_offset + 4], + &ru->common.rxdata[0][slot_offset], + 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_tp(gNB, ULSCH_id, frame_rx, slot_rx, ulsch->harq_pid, ulsch->beam_nb); - NR_gNB_PUSCH *pusch_vars = &gNB->pusch_vars[ULSCH_id]; - pusch_vars->ulsch_power_tot = 0; - pusch_vars->ulsch_noise_power_tot = 0; - for (int aarx = 0; aarx < 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 */ - nfapi_nr_crc_t *crc = &UL_INFO->crc_ind.crc_list[UL_INFO->crc_ind.number_crcs++]; - nfapi_nr_rx_data_pdu_t *pdu = &UL_INFO->rx_ind.pdu_list[UL_INFO->rx_ind.number_of_pdus++]; - nr_fill_indication(gNB, frame_rx, slot_rx, ULSCH_id, ulsch->harq_pid, 1, 1, crc, pdu); - pusch_DTX++; - gNBdumpScopeData(gNB, ulsch->slot, ulsch->frame, "ULSCH_DTX"); - continue; - } - } else { - LOG_D(PHY, - "PUSCH detected in %d.%d (%d,%d,%d)\n", - frame_rx, - slot_rx, - dB_fixed_x10(pusch_vars->ulsch_power_tot), - dB_fixed_x10(pusch_vars->ulsch_noise_power_tot), - gNB->pusch_thres); - - pusch_vars->DTX = 0; - } - ulsch_to_decode[ULSCH_id] = true; - stop_meas(&gNB->rx_pusch_stats); - 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_RX_PUSCH, 1); + start_meas(&gNB->rx_pusch_stats); + nr_rx_pusch_tp(gNB, ULSCH_id, frame_rx, slot_rx, ulsch->harq_pid, ulsch->beam_nb); + NR_gNB_PUSCH *pusch_vars = &gNB->pusch_vars[ULSCH_id]; + pusch_vars->ulsch_power_tot = 0; + pusch_vars->ulsch_noise_power_tot = 0; + for (int aarx = 0; aarx < ant; 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 */ + nfapi_nr_crc_t *crc = &UL_INFO->crc_ind.crc_list[UL_INFO->crc_ind.number_crcs++]; + nfapi_nr_rx_data_pdu_t *pdu = &UL_INFO->rx_ind.pdu_list[UL_INFO->rx_ind.number_of_pdus++]; + nr_fill_indication(gNB, frame_rx, slot_rx, ULSCH_id, ulsch->harq_pid, 1, 1, crc, pdu); + pusch_DTX++; + gNBdumpScopeData(gNB, ulsch->slot, ulsch->frame, "ULSCH_DTX"); + continue; + } + } else { + LOG_D(PHY, + "PUSCH detected in %d.%d (%d,%d,%d)\n", + frame_rx, + slot_rx, + dB_fixed_x10(pusch_vars->ulsch_power_tot), + dB_fixed_x10(pusch_vars->ulsch_noise_power_tot), + gNB->pusch_thres); + + pusch_vars->DTX = 0; + } + ulsch_to_decode[ULSCH_id] = true; + stop_meas(&gNB->rx_pusch_stats); + 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); } /* Do ULSCH decoding time measurement only when number of PUSCH is limited to 1 @@ -1033,251 +1051,298 @@ int phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, N * measurement per processed TB.*/ if (gNB->max_nb_pusch == 1) stop_meas(&gNB->ulsch_decoding_stats); + for (int i = 0; i < gNB->max_nb_srs; i++) { NR_gNB_SRS_t *srs = &gNB->srs[i]; - if (srs) { - if ((srs->active == true) && (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); + if (!(srs && srs->active && srs->frame == frame_rx && srs->slot == slot_rx)) + continue; + LOG_D(NR_PHY, "(%d.%d) gNB is waiting for SRS, id = %i\n", frame_rx, slot_rx, i); - start_meas(&gNB->rx_srs_stats); + start_meas(&gNB->rx_srs_stats); - NR_DL_FRAME_PARMS *frame_parms = &gNB->frame_parms; - nfapi_nr_srs_pdu_t *srs_pdu = &srs->srs_pdu; - uint8_t N_symb_SRS = 1 << srs_pdu->num_symbols; - c16_t srs_received_signal[frame_parms->nb_antennas_rx][frame_parms->ofdm_symbol_size * N_symb_SRS]; - c16_t srs_received_noise[frame_parms->nb_antennas_rx][frame_parms->ofdm_symbol_size * N_symb_SRS]; - c16_t srs_estimated_channel_freq[frame_parms->nb_antennas_rx][1 << srs_pdu->num_ant_ports] - [frame_parms->ofdm_symbol_size * N_symb_SRS] __attribute__((aligned(32))); - c16_t srs_estimated_channel_time[frame_parms->nb_antennas_rx][1 << srs_pdu->num_ant_ports][frame_parms->ofdm_symbol_size] - __attribute__((aligned(32))); - c16_t srs_estimated_channel_time_shifted[frame_parms->nb_antennas_rx][1 << srs_pdu->num_ant_ports] - [frame_parms->ofdm_symbol_size]; - int16_t snr_per_rb[srs_pdu->bwp_size]; + nfapi_nr_srs_pdu_t *srs_pdu = &srs->srs_pdu; + uint8_t N_symb_SRS = 1 << srs_pdu->num_symbols; + c16_t srs_received_signal[ant][symb_sz * N_symb_SRS]; + c16_t srs_received_noise[ant][symb_sz * N_symb_SRS]; + c16_t srs_estimated_channel_freq[ant][1 << srs_pdu->num_ant_ports][symb_sz * N_symb_SRS] __attribute__((aligned(32))); + c16_t srs_estimated_channel_time[ant][1 << srs_pdu->num_ant_ports][symb_sz] __attribute__((aligned(32))); + c16_t srs_estimated_channel_time_shifted[ant][1 << srs_pdu->num_ant_ports][symb_sz]; + int16_t snr_per_rb[srs_pdu->bwp_size]; - start_meas(&gNB->generate_srs_stats); + start_meas(&gNB->generate_srs_stats); - if (check_and_configure_srs_info(srs_pdu, gNB->nr_srs_info[i])) { - generate_srs_nr(frame_parms, - gNB->nr_srs_info[i]->srs_generated_signal, - 0, - srs_pdu->bwp_start, - gNB->nr_srs_info[i], - AMP, - frame_rx, - slot_rx); - } - stop_meas(&gNB->generate_srs_stats); - c16_t **rxdataF = gNB->common_vars.rxdataF[srs->beam_nb]; - start_meas(&gNB->get_srs_signal_stats); - int srs_est = nr_get_srs_signal(gNB, rxdataF, frame_rx, slot_rx, srs_pdu, gNB->nr_srs_info[i], srs_received_signal, srs_received_noise); - stop_meas(&gNB->get_srs_signal_stats); - - if (srs_est >= 0) { - start_meas(&gNB->srs_channel_estimation_stats); - nr_srs_channel_estimation(gNB, - frame_rx, - slot_rx, - srs_pdu, - gNB->nr_srs_info[i], - (const c16_t**)gNB->nr_srs_info[i]->srs_generated_signal, - srs_received_signal, - srs_received_noise, - srs_estimated_channel_freq, - srs_estimated_channel_time, - srs_estimated_channel_time_shifted, - snr_per_rb, - &gNB->srs->snr); - stop_meas(&gNB->srs_channel_estimation_stats); - } - - if ((gNB->srs->snr * 10) < gNB->srs_thres) { - srs_est = -1; - } - - T(T_GNB_PHY_UL_FREQ_CHANNEL_ESTIMATE, - T_INT(0), - T_INT(srs_pdu->rnti), - T_INT(frame_rx), - T_INT(0), - T_INT(0), - T_BUFFER(srs_estimated_channel_freq[0][0], frame_parms->ofdm_symbol_size * sizeof(int32_t))); - - T(T_GNB_PHY_UL_TIME_CHANNEL_ESTIMATE, - T_INT(0), - T_INT(srs_pdu->rnti), - T_INT(frame_rx), - T_INT(0), - T_INT(0), - T_BUFFER(srs_estimated_channel_time_shifted[0][0], frame_parms->ofdm_symbol_size * sizeof(int32_t))); - - T(T_GNB_PHY_UL_SNR_ESTIMATE, - T_INT(0), - T_INT(srs_pdu->rnti), - T_INT(frame_rx), - T_INT(0), - T_INT(0), - T_BUFFER(snr_per_rb, srs_pdu->bwp_size * sizeof(int16_t))); - - UL_INFO->srs_ind.sfn = frame_rx; - UL_INFO->srs_ind.slot = slot_rx; - - // data model difficult to understand, nfapi do malloc for this pointer - UL_INFO->srs_ind.pdu_list = UL_INFO->srs_pdu_list; - nfapi_nr_srs_indication_pdu_t *srs_indication = UL_INFO->srs_pdu_list + UL_INFO->srs_ind.number_of_pdus++; - srs_indication->handle = srs_pdu->handle; - srs_indication->rnti = srs_pdu->rnti; - start_meas(&gNB->srs_timing_advance_stats); - srs_indication->timing_advance_offset = srs_est >= 0 ? nr_est_timing_advance_srs(frame_parms, srs_estimated_channel_time[0]) : 0xFFFF; - stop_meas(&gNB->srs_timing_advance_stats); - srs_indication->timing_advance_offset_nsec = srs_est >= 0 ? (int16_t)((((int32_t)srs_indication->timing_advance_offset - 31) * ((int32_t)TC_NSEC_x32768)) >> 15) : 0xFFFF; - switch (srs_pdu->srs_parameters_v4.usage) { - case 0: - LOG_W(NR_PHY, "SRS report was not requested by MAC\n"); - return 0; - case 1 << NFAPI_NR_SRS_BEAMMANAGEMENT: - srs_indication->srs_usage = NFAPI_NR_SRS_BEAMMANAGEMENT; - break; - case 1 << NFAPI_NR_SRS_CODEBOOK: - srs_indication->srs_usage = NFAPI_NR_SRS_CODEBOOK; - break; - case 1 << NFAPI_NR_SRS_NONCODEBOOK: - srs_indication->srs_usage = NFAPI_NR_SRS_NONCODEBOOK; - break; - case 1 << NFAPI_NR_SRS_ANTENNASWITCH: - srs_indication->srs_usage = NFAPI_NR_SRS_ANTENNASWITCH; - break; - default: - LOG_E(NR_PHY, "Invalid srs_pdu->srs_parameters_v4.usage %i\n", srs_pdu->srs_parameters_v4.usage); - } - srs_indication->report_type = srs_pdu->srs_parameters_v4.report_type[0]; - -#ifdef SRS_IND_DEBUG - LOG_I(NR_PHY, "UL_INFO->srs_ind.sfn = %i\n", UL_INFO->srs_ind.sfn); - LOG_I(NR_PHY, "UL_INFO->srs_ind.slot = %i\n", UL_INFO->srs_ind.slot); - LOG_I(NR_PHY, "srs_indication->rnti = %04x\n", srs_indication->rnti); - LOG_I(NR_PHY, "srs_indication->timing_advance = %i\n", srs_indication->timing_advance_offset); - LOG_I(NR_PHY, "srs_indication->timing_advance_offset_nsec = %i\n", srs_indication->timing_advance_offset_nsec); - LOG_I(NR_PHY, "srs_indication->srs_usage = %i\n", srs_indication->srs_usage); - LOG_I(NR_PHY, "srs_indication->report_type = %i\n", srs_indication->report_type); -#endif - - nfapi_srs_report_tlv_t *report_tlv = &srs_indication->report_tlv; - report_tlv->tag = 0; - report_tlv->length = 0; - - start_meas(&gNB->srs_report_tlv_stats); - switch (srs_indication->srs_usage) { - case NFAPI_NR_SRS_BEAMMANAGEMENT: { - start_meas(&gNB->srs_beam_report_stats); - nfapi_nr_srs_beamforming_report_t nr_srs_bf_report; - nr_srs_bf_report.prg_size = srs_pdu->beamforming.prg_size; - nr_srs_bf_report.num_symbols = 1 << srs_pdu->num_symbols; - nr_srs_bf_report.wide_band_snr = srs_est >= 0 ? (gNB->srs->snr + 64) << 1 : 0xFF; // 0xFF will be set if this field is invalid - nr_srs_bf_report.num_reported_symbols = 1 << srs_pdu->num_symbols; - AssertFatal(nr_srs_bf_report.num_reported_symbols == 1, - "nr_srs_bf_report.num_reported_symbols %i not handled yet!\n", - nr_srs_bf_report.num_reported_symbols); - fill_srs_reported_symbol(&nr_srs_bf_report.reported_symbol_list[0], srs_pdu, frame_parms->N_RB_UL, snr_per_rb, srs_est); - -#ifdef SRS_IND_DEBUG - LOG_I(NR_PHY, "nr_srs_bf_report.prg_size = %i\n", nr_srs_bf_report.prg_size); - LOG_I(NR_PHY, "nr_srs_bf_report.num_symbols = %i\n", nr_srs_bf_report.num_symbols); - LOG_I(NR_PHY, "nr_srs_bf_report.wide_band_snr = %i (%i dB)\n", nr_srs_bf_report.wide_band_snr, (nr_srs_bf_report.wide_band_snr >> 1) - 64); - LOG_I(NR_PHY, "nr_srs_bf_report.num_reported_symbols = %i\n", nr_srs_bf_report.num_reported_symbols); - LOG_I(NR_PHY, "nr_srs_bf_report.reported_symbol_list[0].num_prgs = %i\n", nr_srs_bf_report.reported_symbol_list[0].num_prgs); - for (int prg_idx = 0; prg_idx < nr_srs_bf_report.reported_symbol_list[0].num_prgs; prg_idx++) { - LOG_I(NR_PHY, - "nr_srs_beamforming_report.reported_symbol_list[0].prg_list[%3i].rb_snr = %i (%i dB)\n", - prg_idx, - nr_srs_bf_report.reported_symbol_list[0].prg_list[prg_idx].rb_snr, - (nr_srs_bf_report.reported_symbol_list[0].prg_list[prg_idx].rb_snr >> 1) - 64); - } -#endif - - report_tlv->length = pack_nr_srs_beamforming_report(&nr_srs_bf_report, report_tlv->value, sizeof(report_tlv->value)); - stop_meas(&gNB->srs_beam_report_stats); - break; - } - - case NFAPI_NR_SRS_CODEBOOK: { - start_meas(&gNB->srs_iq_matrix_stats); - nfapi_nr_srs_normalized_channel_iq_matrix_t nr_srs_channel_iq_matrix; - nr_srs_channel_iq_matrix.normalized_iq_representation = srs_pdu->srs_parameters_v4.iq_representation; - nr_srs_channel_iq_matrix.num_gnb_antenna_elements = gNB->frame_parms.nb_antennas_rx; - nr_srs_channel_iq_matrix.num_ue_srs_ports = srs_pdu->srs_parameters_v4.num_total_ue_antennas; - nr_srs_channel_iq_matrix.prg_size = srs_pdu->srs_parameters_v4.prg_size; - nr_srs_channel_iq_matrix.num_prgs = srs_pdu->srs_parameters_v4.srs_bandwidth_size / srs_pdu->srs_parameters_v4.prg_size; - fill_srs_channel_matrix(nr_srs_channel_iq_matrix.channel_matrix, - srs_pdu, - gNB->nr_srs_info[i], - nr_srs_channel_iq_matrix.normalized_iq_representation, - nr_srs_channel_iq_matrix.num_gnb_antenna_elements, - nr_srs_channel_iq_matrix.num_ue_srs_ports, - nr_srs_channel_iq_matrix.prg_size, - nr_srs_channel_iq_matrix.num_prgs, - &gNB->frame_parms, - srs_estimated_channel_freq); - -#ifdef SRS_IND_DEBUG - LOG_I(NR_PHY, "nr_srs_channel_iq_matrix.normalized_iq_representation = %i\n", nr_srs_channel_iq_matrix.normalized_iq_representation); - LOG_I(NR_PHY, "nr_srs_channel_iq_matrix.num_gnb_antenna_elements = %i\n", nr_srs_channel_iq_matrix.num_gnb_antenna_elements); - LOG_I(NR_PHY, "nr_srs_channel_iq_matrix.num_ue_srs_ports = %i\n", nr_srs_channel_iq_matrix.num_ue_srs_ports); - LOG_I(NR_PHY, "nr_srs_channel_iq_matrix.prg_size = %i\n", nr_srs_channel_iq_matrix.prg_size); - LOG_I(NR_PHY, "nr_srs_channel_iq_matrix.num_prgs = %i\n", nr_srs_channel_iq_matrix.num_prgs); - c16_t *channel_matrix16 = (c16_t *)nr_srs_channel_iq_matrix.channel_matrix; - c8_t *channel_matrix8 = (c8_t *)nr_srs_channel_iq_matrix.channel_matrix; - for (int uI = 0; uI < nr_srs_channel_iq_matrix.num_ue_srs_ports; uI++) { - for (int gI = 0; gI < nr_srs_channel_iq_matrix.num_gnb_antenna_elements; gI++) { - for (int pI = 0; pI < nr_srs_channel_iq_matrix.num_prgs; pI++) { - uint16_t index = - uI * nr_srs_channel_iq_matrix.num_gnb_antenna_elements * nr_srs_channel_iq_matrix.num_prgs + gI * nr_srs_channel_iq_matrix.num_prgs + pI; - LOG_I(NR_PHY, - "(uI %i, gI %i, pI %i) channel_matrix --> real %i, imag %i\n", - uI, - gI, - pI, - nr_srs_channel_iq_matrix.normalized_iq_representation == 0 ? channel_matrix8[index].r : channel_matrix16[index].r, - nr_srs_channel_iq_matrix.normalized_iq_representation == 0 ? channel_matrix8[index].i : channel_matrix16[index].i); - } - } - } -#endif - - report_tlv->length = pack_nr_srs_normalized_channel_iq_matrix(&nr_srs_channel_iq_matrix, report_tlv->value, sizeof(report_tlv->value)); - stop_meas(&gNB->srs_iq_matrix_stats); - break; - } - - case NFAPI_NR_SRS_NONCODEBOOK: - case NFAPI_NR_SRS_ANTENNASWITCH: - LOG_W(NR_PHY, "PHY procedures for this SRS usage are not implemented yet!\n"); - break; - - default: - AssertFatal(1 == 0, "Invalid SRS usage\n"); - } - stop_meas(&gNB->srs_report_tlv_stats); - -#ifdef SRS_IND_DEBUG - LOG_I(NR_PHY, "report_tlv->tag = %i\n", report_tlv->tag); - LOG_I(NR_PHY, "report_tlv->length = %i\n", report_tlv->length); - char *value = (char *)report_tlv->value; - for (int b = 0; b < report_tlv->length; b++) { - LOG_I(NR_PHY, "value[%i] = 0x%02x\n", b, value[b] & 0xFF); - } -#endif - srs->active = false; - stop_meas(&gNB->rx_srs_stats); - } + if (check_and_configure_srs_info(srs_pdu, gNB->nr_srs_info[i])) { + generate_srs_nr(frame_parms, + gNB->nr_srs_info[i]->srs_generated_signal, + 0, + srs_pdu->bwp_start, + gNB->nr_srs_info[i], + AMP, + frame_rx, + slot_rx); } + stop_meas(&gNB->generate_srs_stats); + c16_t **rxdataF = gNB->common_vars.rxdataF[srs->beam_nb]; + start_meas(&gNB->get_srs_signal_stats); + int srs_est = + nr_get_srs_signal(gNB, rxdataF, frame_rx, slot_rx, srs_pdu, gNB->nr_srs_info[i], srs_received_signal, srs_received_noise); + stop_meas(&gNB->get_srs_signal_stats); + + if (srs_est >= 0) { + start_meas(&gNB->srs_channel_estimation_stats); + nr_srs_channel_estimation(gNB, + frame_rx, + slot_rx, + srs_pdu, + gNB->nr_srs_info[i], + (const c16_t **)gNB->nr_srs_info[i]->srs_generated_signal, + srs_received_signal, + srs_received_noise, + srs_estimated_channel_freq, + srs_estimated_channel_time, + srs_estimated_channel_time_shifted, + snr_per_rb, + &gNB->srs->snr); + stop_meas(&gNB->srs_channel_estimation_stats); + } + + if ((gNB->srs->snr * 10) < gNB->srs_thres) { + srs_est = -1; + } + + T(T_GNB_PHY_UL_FREQ_CHANNEL_ESTIMATE, + T_INT(0), + T_INT(srs_pdu->rnti), + T_INT(frame_rx), + T_INT(0), + T_INT(0), + T_BUFFER(srs_estimated_channel_freq[0][0], symb_sz * sizeof(int32_t))); + + T(T_GNB_PHY_UL_TIME_CHANNEL_ESTIMATE, + T_INT(0), + T_INT(srs_pdu->rnti), + T_INT(frame_rx), + T_INT(0), + T_INT(0), + T_BUFFER(srs_estimated_channel_time_shifted[0][0], symb_sz * sizeof(int32_t))); + + T(T_GNB_PHY_UL_SNR_ESTIMATE, + T_INT(0), + T_INT(srs_pdu->rnti), + T_INT(frame_rx), + T_INT(0), + T_INT(0), + T_BUFFER(snr_per_rb, srs_pdu->bwp_size * sizeof(int16_t))); + + UL_INFO->srs_ind.sfn = frame_rx; + UL_INFO->srs_ind.slot = slot_rx; + + // data model difficult to understand, nfapi do malloc for this pointer + UL_INFO->srs_ind.pdu_list = UL_INFO->srs_pdu_list; + nfapi_nr_srs_indication_pdu_t *srs_indication = UL_INFO->srs_pdu_list + UL_INFO->srs_ind.number_of_pdus++; + srs_indication->handle = srs_pdu->handle; + srs_indication->rnti = srs_pdu->rnti; + start_meas(&gNB->srs_timing_advance_stats); + srs_indication->timing_advance_offset = + srs_est >= 0 ? nr_est_timing_advance_srs(frame_parms, srs_estimated_channel_time[0]) : 0xFFFF; + stop_meas(&gNB->srs_timing_advance_stats); + srs_indication->timing_advance_offset_nsec = + srs_est >= 0 ? (int16_t)((((int32_t)srs_indication->timing_advance_offset - 31) * ((int32_t)TC_NSEC_x32768)) >> 15) + : 0xFFFF; + switch (srs_pdu->srs_parameters_v4.usage) { + case 0: + LOG_W(NR_PHY, "SRS report was not requested by MAC\n"); + return 0; + case 1 << NFAPI_NR_SRS_BEAMMANAGEMENT: + srs_indication->srs_usage = NFAPI_NR_SRS_BEAMMANAGEMENT; + break; + case 1 << NFAPI_NR_SRS_CODEBOOK: + srs_indication->srs_usage = NFAPI_NR_SRS_CODEBOOK; + break; + case 1 << NFAPI_NR_SRS_NONCODEBOOK: + srs_indication->srs_usage = NFAPI_NR_SRS_NONCODEBOOK; + break; + case 1 << NFAPI_NR_SRS_ANTENNASWITCH: + srs_indication->srs_usage = NFAPI_NR_SRS_ANTENNASWITCH; + break; + default: + LOG_E(NR_PHY, "Invalid srs_pdu->srs_parameters_v4.usage %i\n", srs_pdu->srs_parameters_v4.usage); + } + srs_indication->report_type = srs_pdu->srs_parameters_v4.report_type[0]; + +#ifdef SRS_IND_DEBUG + LOG_I(NR_PHY, "UL_INFO->srs_ind.sfn = %i\n", UL_INFO->srs_ind.sfn); + LOG_I(NR_PHY, "UL_INFO->srs_ind.slot = %i\n", UL_INFO->srs_ind.slot); + LOG_I(NR_PHY, "srs_indication->rnti = %04x\n", srs_indication->rnti); + LOG_I(NR_PHY, "srs_indication->timing_advance = %i\n", srs_indication->timing_advance_offset); + LOG_I(NR_PHY, "srs_indication->timing_advance_offset_nsec = %i\n", srs_indication->timing_advance_offset_nsec); + LOG_I(NR_PHY, "srs_indication->srs_usage = %i\n", srs_indication->srs_usage); + LOG_I(NR_PHY, "srs_indication->report_type = %i\n", srs_indication->report_type); +#endif + + nfapi_srs_report_tlv_t *report_tlv = &srs_indication->report_tlv; + report_tlv->tag = 0; + report_tlv->length = 0; + + start_meas(&gNB->srs_report_tlv_stats); + switch (srs_indication->srs_usage) { + case NFAPI_NR_SRS_BEAMMANAGEMENT: { + start_meas(&gNB->srs_beam_report_stats); + nfapi_nr_srs_beamforming_report_t nr_srs_bf_report; + nr_srs_bf_report.prg_size = srs_pdu->beamforming.prg_size; + nr_srs_bf_report.num_symbols = 1 << srs_pdu->num_symbols; + nr_srs_bf_report.wide_band_snr = + srs_est >= 0 ? (gNB->srs->snr + 64) << 1 : 0xFF; // 0xFF will be set if this field is invalid + nr_srs_bf_report.num_reported_symbols = 1 << srs_pdu->num_symbols; + AssertFatal(nr_srs_bf_report.num_reported_symbols == 1, + "nr_srs_bf_report.num_reported_symbols %i not handled yet!\n", + nr_srs_bf_report.num_reported_symbols); + fill_srs_reported_symbol(&nr_srs_bf_report.reported_symbol_list[0], srs_pdu, frame_parms->N_RB_UL, snr_per_rb, srs_est); + +#ifdef SRS_IND_DEBUG + LOG_I(NR_PHY, "nr_srs_bf_report.prg_size = %i\n", nr_srs_bf_report.prg_size); + LOG_I(NR_PHY, "nr_srs_bf_report.num_symbols = %i\n", nr_srs_bf_report.num_symbols); + LOG_I(NR_PHY, + "nr_srs_bf_report.wide_band_snr = %i (%i dB)\n", + nr_srs_bf_report.wide_band_snr, + (nr_srs_bf_report.wide_band_snr >> 1) - 64); + LOG_I(NR_PHY, "nr_srs_bf_report.num_reported_symbols = %i\n", nr_srs_bf_report.num_reported_symbols); + LOG_I(NR_PHY, + "nr_srs_bf_report.reported_symbol_list[0].num_prgs = %i\n", + nr_srs_bf_report.reported_symbol_list[0].num_prgs); + for (int prg_idx = 0; prg_idx < nr_srs_bf_report.reported_symbol_list[0].num_prgs; prg_idx++) { + LOG_I(NR_PHY, + "nr_srs_beamforming_report.reported_symbol_list[0].prg_list[%3i].rb_snr = %i (%i dB)\n", + prg_idx, + nr_srs_bf_report.reported_symbol_list[0].prg_list[prg_idx].rb_snr, + (nr_srs_bf_report.reported_symbol_list[0].prg_list[prg_idx].rb_snr >> 1) - 64); + } +#endif + + report_tlv->length = pack_nr_srs_beamforming_report(&nr_srs_bf_report, report_tlv->value, sizeof(report_tlv->value)); + stop_meas(&gNB->srs_beam_report_stats); + break; + } + + case NFAPI_NR_SRS_CODEBOOK: { + start_meas(&gNB->srs_iq_matrix_stats); + nfapi_nr_srs_normalized_channel_iq_matrix_t nr_srs_channel_iq_matrix; + fill_srs_channel_matrix(&nr_srs_channel_iq_matrix, + srs_pdu, + gNB->nr_srs_info[i], + srs_pdu->srs_parameters_v4.iq_representation, + ant, + srs_pdu->srs_parameters_v4.num_total_ue_antennas, + srs_pdu->srs_parameters_v4.prg_size, + srs_pdu->srs_parameters_v4.srs_bandwidth_size / srs_pdu->srs_parameters_v4.prg_size, + frame_parms, + srs_estimated_channel_freq); + +#ifdef SRS_IND_DEBUG + LOG_I(NR_PHY, + "nr_srs_channel_iq_matrix.normalized_iq_representation = %i\n", + nr_srs_channel_iq_matrix.normalized_iq_representation); + LOG_I(NR_PHY, + "nr_srs_channel_iq_matrix.num_gnb_antenna_elements = %i\n", + nr_srs_channel_iq_matrix.num_gnb_antenna_elements); + LOG_I(NR_PHY, "nr_srs_channel_iq_matrix.num_ue_srs_ports = %i\n", nr_srs_channel_iq_matrix.num_ue_srs_ports); + LOG_I(NR_PHY, "nr_srs_channel_iq_matrix.prg_size = %i\n", nr_srs_channel_iq_matrix.prg_size); + LOG_I(NR_PHY, "nr_srs_channel_iq_matrix.num_prgs = %i\n", nr_srs_channel_iq_matrix.num_prgs); + c16_t *channel_matrix16 = (c16_t *)nr_srs_channel_iq_matrix.channel_matrix; + c8_t *channel_matrix8 = (c8_t *)nr_srs_channel_iq_matrix.channel_matrix; + for (int uI = 0; uI < nr_srs_channel_iq_matrix.num_ue_srs_ports; uI++) { + for (int gI = 0; gI < nr_srs_channel_iq_matrix.num_gnb_antenna_elements; gI++) { + for (int pI = 0; pI < nr_srs_channel_iq_matrix.num_prgs; pI++) { + uint16_t index = uI * nr_srs_channel_iq_matrix.num_gnb_antenna_elements * nr_srs_channel_iq_matrix.num_prgs + + gI * nr_srs_channel_iq_matrix.num_prgs + pI; + LOG_I( + NR_PHY, + "(uI %i, gI %i, pI %i) channel_matrix --> real %i, imag %i\n", + uI, + gI, + pI, + nr_srs_channel_iq_matrix.normalized_iq_representation == 0 ? channel_matrix8[index].r : channel_matrix16[index].r, + nr_srs_channel_iq_matrix.normalized_iq_representation == 0 ? channel_matrix8[index].i + : channel_matrix16[index].i); + } + } + } +#endif + + report_tlv->length = + pack_nr_srs_normalized_channel_iq_matrix(&nr_srs_channel_iq_matrix, report_tlv->value, sizeof(report_tlv->value)); + stop_meas(&gNB->srs_iq_matrix_stats); + break; + } + + case NFAPI_NR_SRS_NONCODEBOOK: + case NFAPI_NR_SRS_ANTENNASWITCH: + LOG_W(NR_PHY, "PHY procedures for this SRS usage are not implemented yet!\n"); + break; + + default: + AssertFatal(1 == 0, "Invalid SRS usage\n"); + } + stop_meas(&gNB->srs_report_tlv_stats); + +#ifdef SRS_IND_DEBUG + LOG_I(NR_PHY, "report_tlv->tag = %i\n", report_tlv->tag); + LOG_I(NR_PHY, "report_tlv->length = %i\n", report_tlv->length); + char *value = (char *)report_tlv->value; + for (int b = 0; b < report_tlv->length; b++) { + LOG_I(NR_PHY, "value[%i] = 0x%02x\n", b, value[b] & 0xFF); + } +#endif + srs->active = false; + stop_meas(&gNB->rx_srs_stats); } stop_meas(&gNB->phy_proc_rx); if (pucch_decode_done || pusch_decode_done) { - T(T_GNB_PHY_PUCCH_PUSCH_IQ, T_INT(frame_rx), T_INT(slot_rx), T_BUFFER(&gNB->common_vars.rxdataF[0][0][0], gNB->frame_parms.symbols_per_slot * gNB->frame_parms.ofdm_symbol_size * 4)); + T(T_GNB_PHY_PUCCH_PUSCH_IQ, + T_INT(frame_rx), + T_INT(slot_rx), + T_BUFFER(&gNB->common_vars.rxdataF[0][0][0], nb_symb * symb_sz * 4)); } VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_gNB_UESPEC_RX,0); return pusch_DTX; } + +void nr_save_ul_tti_req(PHY_VARS_gNB *gNB, nfapi_nr_ul_tti_request_t *UL_tti_req) +{ + DevAssert(gNB != NULL); + DevAssert(UL_tti_req != NULL); + + int frame = UL_tti_req->SFN; + int slot = UL_tti_req->Slot; + + for (int i = 0; i < UL_tti_req->n_pdus; i++) { + int type = UL_tti_req->pdus_list[i].pdu_type; + LOG_D(NR_PHY, + "frame %d, slot %d got %s for %d.%d\n", + frame, + slot, + txt_nfapi_nr_ul_config_pdu_type[type], + UL_tti_req->SFN, + UL_tti_req->Slot); + switch (type) { + case NFAPI_NR_UL_CONFIG_PUSCH_PDU_TYPE: + nr_fill_ulsch(gNB, UL_tti_req->SFN, UL_tti_req->Slot, &UL_tti_req->pdus_list[i].pusch_pdu); + break; + case NFAPI_NR_UL_CONFIG_PUCCH_PDU_TYPE: + nr_fill_pucch(gNB, UL_tti_req->SFN, UL_tti_req->Slot, &UL_tti_req->pdus_list[i].pucch_pdu); + break; + case NFAPI_NR_UL_CONFIG_PRACH_PDU_TYPE: { + nfapi_nr_prach_pdu_t *prach_pdu = &UL_tti_req->pdus_list[i].prach_pdu; + prach_item_t *prach = nr_schedule_rx_prach(gNB, UL_tti_req->SFN, UL_tti_req->Slot, prach_pdu); + if (!prach) + LOG_W(NR_PHY_RACH, "Error in scheduling rach\n"); + } break; + case NFAPI_NR_UL_CONFIG_SRS_PDU_TYPE: + nr_fill_srs(gNB, UL_tti_req->SFN, UL_tti_req->Slot, &UL_tti_req->pdus_list[i].srs_pdu); + break; + } + } +} diff --git a/openair1/SCHED_NR/sched_nr.h b/openair1/SCHED_NR/sched_nr.h index 40c32c2199..da71809589 100644 --- a/openair1/SCHED_NR/sched_nr.h +++ b/openair1/SCHED_NR/sched_nr.h @@ -33,10 +33,17 @@ #include "phy_frame_config_nr.h" void nr_set_ssb_first_subcarrier(nfapi_nr_config_request_scf_t *cfg, NR_DL_FRAME_PARMS *fp); -void phy_procedures_gNB_TX(processingData_L1tx_t *msgTx, int frame_tx, int slot_tx, int do_meas); +void phy_procedures_gNB_TX(PHY_VARS_gNB *gNB, + const nfapi_nr_dl_tti_request_t *DL_req, + const nfapi_nr_tx_data_request_t *TX_req, + const nfapi_nr_ul_dci_request_t *UL_dci_req, + int frame, + int slot, + int do_meas); +void nr_save_ul_tti_req(PHY_VARS_gNB *gNB, nfapi_nr_ul_tti_request_t *UL_tti_req); int phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, NR_UL_IND_t *UL_INFO); void L1_nr_prach_procedures(PHY_VARS_gNB *gNB, int frame, int slot, nfapi_nr_rach_indication_t *rach_ind); -void nr_common_signal_procedures (PHY_VARS_gNB *gNB,int frame,int slot,nfapi_nr_dl_tti_ssb_pdu ssb_pdu); +void nr_common_signal_procedures (PHY_VARS_gNB *gNB,int frame,int slot, const nfapi_nr_dl_tti_ssb_pdu *ssb_pdu); void nr_feptx_ofdm(RU_t *ru,int frame_tx,int tti_tx); void nr_feptx0(RU_t *ru,int tti_tx,int first_symbol, int num_symbols, int aa); void nr_feptx_prec(RU_t *ru,int frame_tx,int tti_tx); @@ -49,7 +56,7 @@ void nr_phy_free_RU(RU_t *ru); void clear_slot_beamid(PHY_VARS_gNB *gNB, int slot); int beam_index_allocation(bool das, int fapi_beam_index, - nfapi_nr_analog_beamforming_ve_t *analog_bf, + const nfapi_nr_analog_beamforming_ve_t *analog_bf, NR_gNB_COMMON *common_vars, int slot, int symbols_per_slot, diff --git a/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c b/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c index cbdd91c949..a3e86ce433 100644 --- a/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c +++ b/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c @@ -230,6 +230,88 @@ static void nr_ue_scheduled_response_dl(NR_UE_MAC_INST_t *mac, dl_config->number_pdus = 0; } +static void dump_pusch_pdu(int instance, int frame, int slot, nfapi_nr_ue_pusch_pdu_t *pusch_pdu) +{ + LOG_D(PHY, + "[UE %d] %d.%d ULSCH PDU pdu_bit_map %u " + "rnti %u " + "handle %u " + "bwp_size %u " + "bwp_start %u " + "subcarrier_spacing %u " + "cyclic_prefix %u " + "target_code_rate %u " + "qam_mod_order %u " + "mcs_index %u " + "mcs_table %u " + "transform_precoding %u " + "data_scrambling_id %u " + "nrOfLayers %u " + "Tpmi %u " + "ul_dmrs_symb_pos %u " + "dmrs_config_type %u " + "ul_dmrs_scrambling_id %u " + "scid %u " + "num_dmrs_cdm_grps_no_data %u " + "dmrs_ports %u " + "resource_alloc %u " + "rb_start %u " + "rb_size %u " + "vrb_to_prb_mapping %u " + "frequency_hopping %u " + "tx_direct_current_location %u " + "uplink_frequency_shift_7p5khz %u " + "start_symbol_index %u " + "nr_of_symbols %u " + "tbslbrm %u " + "ldpcBaseGraph %u " + "ulsch_indicator %u " + "pusch_data->rv_index %u " + "pusch_data->harq_process_id %u " + "pusch_data->new_data_indicator %u " + "pusch_data->num_cb %u\n", + instance, + frame, + slot, + pusch_pdu->pdu_bit_map, + pusch_pdu->rnti, + pusch_pdu->handle, + pusch_pdu->bwp_size, + pusch_pdu->bwp_start, + pusch_pdu->subcarrier_spacing, + pusch_pdu->cyclic_prefix, + pusch_pdu->target_code_rate, + pusch_pdu->qam_mod_order, + pusch_pdu->mcs_index, + pusch_pdu->mcs_table, + pusch_pdu->transform_precoding, + pusch_pdu->data_scrambling_id, + pusch_pdu->nrOfLayers, + pusch_pdu->Tpmi, + pusch_pdu->ul_dmrs_symb_pos, + pusch_pdu->dmrs_config_type, + pusch_pdu->ul_dmrs_scrambling_id, + pusch_pdu->scid, + pusch_pdu->num_dmrs_cdm_grps_no_data, + pusch_pdu->dmrs_ports, + pusch_pdu->resource_alloc, + pusch_pdu->rb_start, + pusch_pdu->rb_size, + pusch_pdu->vrb_to_prb_mapping, + pusch_pdu->frequency_hopping, + pusch_pdu->tx_direct_current_location, + pusch_pdu->uplink_frequency_shift_7p5khz, + pusch_pdu->start_symbol_index, + pusch_pdu->nr_of_symbols, + pusch_pdu->tbslbrm, + pusch_pdu->ldpcBaseGraph, + pusch_pdu->ulsch_indicator, + pusch_pdu->pusch_data.rv_index, + pusch_pdu->pusch_data.harq_process_id, + pusch_pdu->pusch_data.new_data_indicator, + pusch_pdu->pusch_data.num_cb); +} + static void nr_ue_scheduled_response_ul(PHY_VARS_NR_UE *phy, fapi_nr_ul_config_request_t *ul_config, nr_phy_data_tx_t *phy_data) { fapi_nr_ul_config_request_pdu_t *pdu = fapiLockIterator(ul_config, ul_config->frame, ul_config->slot); @@ -251,6 +333,7 @@ static void nr_ue_scheduled_response_ul(PHY_VARS_NR_UE *phy, fapi_nr_ul_config_r pdu->pusch_config_pdu.num_dmrs_cdm_grps_no_data); memcpy(pusch_pdu, &pdu->pusch_config_pdu, sizeof(*pusch_pdu)); + dump_pusch_pdu(phy->Mod_id, ul_config->frame, ul_config->slot, pusch_pdu); if (pdu->pusch_config_pdu.tx_request_body.fapiTxPdu) { LOG_D(PHY, "%d.%d Copying %d bytes to harq_process_ul_ue->a (harq_pid %d)\n", diff --git a/openair1/SIMULATION/NR_PHY/dlschsim.c b/openair1/SIMULATION/NR_PHY/dlschsim.c index c475bfc039..ea4a068b6e 100644 --- a/openair1/SIMULATION/NR_PHY/dlschsim.c +++ b/openair1/SIMULATION/NR_PHY/dlschsim.c @@ -439,10 +439,7 @@ int main(int argc, char **argv) nr_init_dl_harq_processes(UE->dl_harq_processes, 8, nb_rb); 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 = &gNB->dlsch[0]; //time_stats_t *rm_stats, *te_stats, *i_stats; unsigned int TBS = 8424; uint8_t nb_re_dmrs = 6; // No data in dmrs symbol @@ -459,19 +456,24 @@ int main(int argc, char **argv) TBS = nr_compute_tbs(mod_order,rate, nb_rb, nb_symb_sch, nb_re_dmrs*length_dmrs, 0, 0, Nl); printf("available bits %u TBS %u mod_order %d\n", available_bits, TBS, mod_order); //dlsch->harq_ids[subframe]= 0; - rel15->rbSize = nb_rb; - rel15->NrOfSymbols = nb_symb_sch; - rel15->qamModOrder[0] = mod_order; - rel15->nrOfLayers = Nl; - rel15->TBSize[0] = TBS>>3; - rel15->targetCodeRate[0] = rate; - rel15->NrOfCodewords = 1; - rel15->dmrsConfigType = NFAPI_NR_DMRS_TYPE1; - rel15->dlDmrsSymbPos = 4; - rel15->mcsIndex[0] = Imcs; - rel15->numDmrsCdmGrpsNoData = 1; - rel15->maintenance_parms_v3.tbSizeLbrmBytes = Tbslbrm; - rel15->maintenance_parms_v3.ldpcBaseGraph = get_BG(TBS, rate); + nfapi_nr_dl_tti_pdsch_pdu pdsch_pdu = { + .pdsch_pdu_rel15 = { + .rbSize = nb_rb, + .NrOfSymbols = nb_symb_sch, + .qamModOrder[0] = mod_order, + .nrOfLayers = Nl, + .TBSize[0] = TBS >> 3, + .targetCodeRate[0] = rate, + .NrOfCodewords = 1, + .dmrsConfigType = NFAPI_NR_DMRS_TYPE1, + .dlDmrsSymbPos = 4, + .mcsIndex[0] = Imcs, + .numDmrsCdmGrpsNoData = 1, + .maintenance_parms_v3.tbSizeLbrmBytes = Tbslbrm, + .maintenance_parms_v3.ldpcBaseGraph = get_BG(TBS, rate), + }, + }; + dlsch->pdsch_pdu = &pdsch_pdu; double modulated_input[16 * 68 * 384]; // [hna] 16 segments, 68*Zc short channel_output_fixed[16 * 68 * 384]; //unsigned char *estimated_output; @@ -498,7 +500,7 @@ int main(int argc, char **argv) printf("harq process ue mcs = %d Qm = %d, symb %d\n", dlsch0_ue->dlsch_config.mcs, dlsch0_ue->dlsch_config.qamModOrder, nb_symb_sch); uint8_t test_input[TBS / 8 + 4]; // + 3 for CRC + 1 additional byte, see nr_dlsch_encoding() - dlsch->harq_process.pdu = test_input; + dlsch->pdu = test_input; //unsigned char test_input[TBS / 8] __attribute__ ((aligned(16))); for (i = 0; i < TBS / 8; i++) test_input[i] = (unsigned char) rand(); @@ -512,11 +514,10 @@ int main(int argc, char **argv) //printf("crc32: [0]->0x%08x\n",crc24c(test_input, 32)); // generate signal - unsigned char output[rel15->rbSize * NR_SYMBOLS_PER_SLOT * NR_NB_SC_PER_RB * NR_MAX_NB_LAYERS] __attribute__((aligned(64))); + unsigned char output[nb_rb * NR_SYMBOLS_PER_SLOT * NR_NB_SC_PER_RB * NR_MAX_NB_LAYERS] __attribute__((aligned(64))); bzero(output, sizeof(output)); if (input_fd == NULL) { - msgDataTx.num_pdsch_slot = 1; - nr_dlsch_encoding(gNB, &msgDataTx, frame, slot, frame_parms, output, NULL, NULL, NULL, NULL, NULL, NULL, NULL); + nr_dlsch_encoding(gNB, 1, dlsch, frame, slot, frame_parms, output, NULL, NULL, NULL, NULL, NULL, NULL, NULL); } for (SNR = snr0; SNR < snr1 && !stop; SNR += snr_step) { @@ -622,8 +623,6 @@ int main(int argc, char **argv) free_channel_desc_scm(gNB2UE); - reset_DLSCH_struct(gNB, &msgDataTx); - int nb_slots_to_set = (1 << mu) * NR_NUMBER_OF_SUBFRAMES_PER_FRAME; for (int i = 0; i < nb_slots_to_set; ++i) free(gNB->gNB_config.tdd_table.max_tdd_periodicity_list[i].max_num_of_symbol_per_slot_list); diff --git a/openair1/SIMULATION/NR_PHY/dlsim.c b/openair1/SIMULATION/NR_PHY/dlsim.c index c03e3c0046..82984657d3 100644 --- a/openair1/SIMULATION/NR_PHY/dlsim.c +++ b/openair1/SIMULATION/NR_PHY/dlsim.c @@ -62,7 +62,6 @@ #include "PHY/defs_nr_common.h" #include "PHY/impl_defs_nr.h" #include "PHY/phy_vars_nr_ue.h" -#include "SCHED_NR/fapi_nr_l1.h" #include "SCHED_NR/sched_nr.h" #include "SCHED_NR_UE/defs.h" #include "SCHED_NR_UE/fapi_nr_ue_l1.h" @@ -286,7 +285,6 @@ nrUE_params_t *get_nrUE_params(void) { return &nrUE_params; } - void validate_input_pmi(nfapi_nr_config_request_scf_t *gNB_config, nr_pdsch_AntennaPorts_t pdsch_AntennaPorts, int nrOfLayers, @@ -974,13 +972,6 @@ int main(int argc, char **argv) int ret = 1; initNamedTpool(gNBthreads, &gNB->threadPool, true, "gNB-tpool"); initNotifiedFIFO(&gNB->L1_tx_out); - // we create 2 threads for L1 tx processing - processingData_L1tx_t *msgDataTx = malloc(sizeof(processingData_L1tx_t)); - init_DLSCH_struct(gNB, msgDataTx); - msgDataTx->slot = slot; - msgDataTx->frame = frame; - memset(msgDataTx->ssb, 0, 64*sizeof(NR_gNB_SSB_t)); - gNB->msgDataTx = msgDataTx; // Buffers to store internal memory of slot process int rx_size = (((14 * UE->frame_parms.N_RB_DL * 12 * sizeof(int32_t)) + 15) >> 4) << 4; @@ -1059,8 +1050,13 @@ int main(int argc, char **argv) n_false_positive = 0; if (n_trials== 1) num_rounds = 1; - 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; + NR_gNB_DLSCH_t *gNB_dlsch = &gNB->dlsch[0]; + memset(Sched_INFO, 0, sizeof(*Sched_INFO)); + Sched_INFO->sched_response_id = -1; + nfapi_nr_dl_tti_request_body_t *dl_req = &Sched_INFO->DL_req.dl_tti_request_body; + // scheduler will place PDSCH second (after PDCCH), verification below + 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; for (trial = 0; trial < n_trials && !stop; trial++) { @@ -1082,11 +1078,9 @@ int main(int argc, char **argv) UE_harq_process->DLround = round; UE_harq_process->first_rx = 1; - memset(Sched_INFO, 0, sizeof(*Sched_INFO)); - Sched_INFO->sched_response_id = -1; - while (round < num_rounds && !UE_harq_process->decodeResult && !stop) { - clear_nr_nfapi_information(RC.nrmac[0], 0, frame, slot, &Sched_INFO->DL_req, &Sched_INFO->TX_req, &Sched_INFO->UL_dci_req); + reset_sched_response(Sched_INFO, frame, slot, 0, 0); + clear_nr_nfapi_information(RC.nrmac[0], 0, frame, slot); UE_info->UE_sched_ctrl.harq_processes[harq_pid].ndi = !(trial&1); UE_info->UE_sched_ctrl.harq_processes[harq_pid].round = round; @@ -1094,18 +1088,13 @@ int main(int argc, char **argv) NR_SCHED_LOCK(&gNB_mac->sched_lock); nr_schedule_ue_spec(0, frame, slot, &Sched_INFO->DL_req, &Sched_INFO->TX_req); NR_SCHED_UNLOCK(&gNB_mac->sched_lock); - 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; - nr_schedule_response(Sched_INFO); + + /* check that second message is indeed PDSCH */ + DevAssert(dl_tti_pdsch_pdu->PDUType == NFAPI_NR_DL_TTI_PDSCH_PDU_TYPE); /* PTRS values for DLSIM calculations */ - 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; + // This is already in DL procedures?? if(pdu_bit_map & 0x1) { set_ptrs_symb_idx(&dlPtrsSymPos, pdsch_pdu_rel15->NrOfSymbols, @@ -1113,16 +1102,12 @@ int main(int argc, char **argv) 1<PTRSTimeDensity, pdsch_pdu_rel15->dlDmrsSymbPos); ptrsSymbPerSlot = get_ptrs_symbols_in_slot(dlPtrsSymPos, pdsch_pdu_rel15->StartSymbolIndex, pdsch_pdu_rel15->NrOfSymbols); - ptrsRePerSymb = ((rel15->rbSize + rel15->PTRSFreqDensity - 1) / rel15->PTRSFreqDensity); + ptrsRePerSymb = ((pdsch_pdu_rel15->rbSize + pdsch_pdu_rel15->PTRSFreqDensity - 1) / pdsch_pdu_rel15->PTRSFreqDensity); LOG_D(PHY,"[DLSIM] PTRS Symbols in a slot: %2u, RE per Symbol: %3u, RE in a slot %4d\n", ptrsSymbPerSlot, ptrsRePerSymb, ptrsSymbPerSlot * ptrsRePerSymb); } - msgDataTx->ssb[0].ssb_pdu.ssb_pdu_rel15.bchPayload=0x001234; - msgDataTx->ssb[0].ssb_pdu.ssb_pdu_rel15.SsbBlockIndex = 0; - msgDataTx->gNB = gNB; - start_meas(&gNB->phy_proc_tx); - phy_procedures_gNB_TX(msgDataTx,frame,slot,1); + phy_procedures_gNB_TX(gNB, &Sched_INFO->DL_req, &Sched_INFO->TX_req, &Sched_INFO->UL_dci_req, frame, slot, 1); stop_meas(&gNB->phy_proc_tx); int txdataF_offset = slot * frame_parms->samples_per_slot_wCP; @@ -1197,9 +1182,9 @@ int main(int argc, char **argv) double ts = 1.0/(frame_parms->subcarrier_spacing * frame_parms->ofdm_symbol_size); //Compute AWGN variance - sigma2_dB = 10 * log10((double)txlev_sum * ((double)UE->frame_parms.ofdm_symbol_size/(12*rel15->rbSize))) - SNR; + sigma2_dB = 10 * log10((double)txlev_sum * ((double)UE->frame_parms.ofdm_symbol_size/(12*pdsch_pdu_rel15->rbSize))) - SNR; sigma2 = pow(10, sigma2_dB/10); - if (n_trials==1) printf("sigma2 %f (%f dB), txlev_sum %f (factor %f)\n",sigma2,sigma2_dB,10*log10((double)txlev_sum),(double)(double)UE->frame_parms.ofdm_symbol_size/(12*rel15->rbSize)); + if (n_trials==1) printf("sigma2 %f (%f dB), txlev_sum %f (factor %f)\n",sigma2,sigma2_dB,10*log10((double)txlev_sum),(double)(double)UE->frame_parms.ofdm_symbol_size/(12*pdsch_pdu_rel15->rbSize)); for (aa = 0; aa < n_rx; aa++) { bzero(r_re[aa], slot_length * sizeof(double)); @@ -1241,22 +1226,22 @@ int main(int argc, char **argv) int16_t *UE_llr = (int16_t*)UE->phy_sim_pdsch_llr; - TBS = dlsch0->dlsch_config.TBS;//rel15->TBSize[0]; + TBS = dlsch0->dlsch_config.TBS; uint16_t length_dmrs = get_num_dmrs(dlsch0->dlsch_config.dlDmrsSymbPos); uint16_t nb_rb = dlsch0->dlsch_config.number_rbs; uint8_t nb_re_dmrs = dlsch0->dlsch_config.dmrsConfigType == NFAPI_NR_DMRS_TYPE1 ? 6*dlsch0->dlsch_config.n_dmrs_cdm_groups : 4*dlsch0->dlsch_config.n_dmrs_cdm_groups; uint8_t mod_order = dlsch0->dlsch_config.qamModOrder; uint8_t nb_symb_sch = dlsch0->dlsch_config.number_symbols; uint32_t unav_res = ptrsSymbPerSlot * ptrsRePerSymb; - available_bits = nr_get_G(nb_rb, nb_symb_sch, nb_re_dmrs, length_dmrs, unav_res, mod_order, rel15->nrOfLayers); + available_bits = nr_get_G(nb_rb, nb_symb_sch, nb_re_dmrs, length_dmrs, unav_res, mod_order, pdsch_pdu_rel15->nrOfLayers); if (pdu_bit_map & 0x1) { if (trial == 0 && round == 0) { - printf("[DLSIM][PTRS] Available bits are: %5u, removed PTRS bits are: %5u \n", available_bits, (ptrsSymbPerSlot * ptrsRePerSymb * rel15->nrOfLayers * mod_order)); + printf("[DLSIM][PTRS] Available bits are: %5u, removed PTRS bits are: %5u \n", available_bits, (ptrsSymbPerSlot * ptrsRePerSymb * pdsch_pdu_rel15->nrOfLayers * mod_order)); } } for (i = 0; i < available_bits; i++) { - const uint8_t current_bit = (gNB_dlsch->harq_process.f[i / 8] & (1 << (i & 7))) >> (i & 7); + const uint8_t current_bit = (gNB_dlsch->f[i / 8] & (1 << (i & 7))) >> (i & 7); if (((current_bit == 0) && (UE_llr[i] <= 0)) || ((current_bit == 1) && (UE_llr[i] >= 0))) { if (errors_scrambling[round] == 0) { LOG_D(PHY,"First bit in error in unscrambling = %d\n",i); @@ -1270,13 +1255,13 @@ int main(int argc, char **argv) } // round if (test_input_bit == NULL) { - test_input_bit = (unsigned char *)malloc16(8 * rel15->TBSize[0]); - estimated_output_bit = (unsigned char *)malloc16(8 * rel15->TBSize[0]); + test_input_bit = (unsigned char *)malloc16(8 * pdsch_pdu_rel15->TBSize[0]); + estimated_output_bit = (unsigned char *)malloc16(8 * pdsch_pdu_rel15->TBSize[0]); } for (i = 0; i < TBS; i++) { 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 + test_input_bit[i] = (gNB_dlsch->b[i / 8] & (1 << (i & 7))) >> (i & 7); // Further correct for multiple segments if (estimated_output_bit[i] != test_input_bit[i]) { if(errors_bit == 0) @@ -1320,7 +1305,7 @@ int main(int argc, char **argv) printf("), Channel BER (%e", berStats[0]); for (int r = 1; r < num_rounds; r++) printf(",%e", berStats[r]); - printf(") Avg round %.2f, Eff Rate %.4f bits/slot, Eff Throughput %.2f, TBS %u bits/slot\n", roundStats, effRate, effRate / (8 * rel15->TBSize[0]) * 100, 8 * rel15->TBSize[0]); + printf(") Avg round %.2f, Eff Rate %.4f bits/slot, Eff Throughput %.2f, TBS %u bits/slot\n", roundStats, effRate, effRate / (8 * pdsch_pdu_rel15->TBSize[0]) * 100, 8 * pdsch_pdu_rel15->TBSize[0]); printf("*****************************************\n"); printf("\n"); // writing to csv file @@ -1328,7 +1313,7 @@ int main(int argc, char **argv) fprintf(csv_file,"%f,%d/%d,",SNR,n_false_positive,n_trials); for (int r = 0; r < num_rounds; r++) fprintf(csv_file,"%d/%d,%u/%u,%f,%e,",n_errors[r], round_trials[r], errors_scrambling[r], available_bits * round_trials[r],blerStats[r],berStats[r]); - fprintf(csv_file,"%.2f,%.4f,%.2f,%u\n", roundStats, effRate, effRate / (8 * rel15->TBSize[0]) * 100, 8 * rel15->TBSize[0]); + fprintf(csv_file,"%.2f,%.4f,%.2f,%u\n", roundStats, effRate, effRate / (8 * pdsch_pdu_rel15->TBSize[0]) * 100, 8 * pdsch_pdu_rel15->TBSize[0]); } if (print_perf==1) { printf("\ngNB TX function statistics (per %d us slot, NPRB %d, mcs %d, C %d, block %d)\n", @@ -1336,7 +1321,7 @@ int main(int argc, char **argv) g_rbSize, g_mcsIndex, UE->dl_harq_processes[0][slot].C, - 8 * rel15->TBSize[0]); + 8 * pdsch_pdu_rel15->TBSize[0]); printDistribution(&gNB->phy_proc_tx,table_tx,"PHY proc tx"); printStatIndent2(&gNB->dci_generation_stats, "DCI encoding time"); printStatIndent2(&gNB->dlsch_encoding_stats,"DLSCH encoding time"); @@ -1378,8 +1363,8 @@ int main(int argc, char **argv) const uint32_t numReSym = (g_rbSize * 12 + 15) & (~15); for (int l = 0; l < g_nrOfLayers; l++) { for (int r = 0; r < n_rx; r++) { - const int s = rel15->StartSymbolIndex; - const int n = rel15->NrOfSymbols; + const int s = pdsch_pdu_rel15->StartSymbolIndex; + const int n = pdsch_pdu_rel15->NrOfSymbols; for (int i = s; i < s + n; i++) { const uint32_t dmrsBitMap = phy_data.dlsch[0].dlsch_config.dlDmrsSymbPos; const uint32_t dmrsCfg = phy_data.dlsch[0].dlsch_config.dmrsConfigType; @@ -1415,7 +1400,7 @@ int main(int argc, char **argv) break; } - if (effRate >= (eff_tp_check * 8 * rel15->TBSize[0])) { + if (effRate >= (eff_tp_check * 8 * pdsch_pdu_rel15->TBSize[0])) { printf("PDSCH test OK\n"); ret = 0; break; diff --git a/openair1/SIMULATION/NR_PHY/pbchsim.c b/openair1/SIMULATION/NR_PHY/pbchsim.c index 4b44b34091..c86744afaa 100644 --- a/openair1/SIMULATION/NR_PHY/pbchsim.c +++ b/openair1/SIMULATION/NR_PHY/pbchsim.c @@ -519,10 +519,10 @@ int main(int argc, char **argv) exit(-1); } - processingData_L1tx_t msgDataTx; // generate signal 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]; + nfapi_nr_dl_tti_ssb_pdu ssb_pdu[64] = {0}; if (input_fd==NULL) { for (i=0; iLmax; i++) { @@ -530,10 +530,10 @@ int main(int argc, char **argv) const int sc_offset = frame_parms->freq_range == FR1 ? ssb_subcarrier_offset<freq_range == FR1 ? gNB->gNB_config.ssb_table.ssb_offset_point_a.value<gNB_config.ssb_table.ssb_offset_point_a.value << (mu - 2); - msgDataTx.ssb[i].ssb_pdu.ssb_pdu_rel15.bchPayload = 0x55dd33; - msgDataTx.ssb[i].ssb_pdu.ssb_pdu_rel15.SsbBlockIndex = i; - msgDataTx.ssb[i].ssb_pdu.ssb_pdu_rel15.SsbSubcarrierOffset = sc_offset; - msgDataTx.ssb[i].ssb_pdu.ssb_pdu_rel15.ssbOffsetPointA = prb_offset; + ssb_pdu[i].ssb_pdu_rel15.bchPayload = 0x55dd33; + ssb_pdu[i].ssb_pdu_rel15.SsbBlockIndex = i; + ssb_pdu[i].ssb_pdu_rel15.SsbSubcarrierOffset = sc_offset; + ssb_pdu[i].ssb_pdu_rel15.ssbOffsetPointA = prb_offset; start_symbol = nr_get_ssb_start_symbol(frame_parms,i); int slot = start_symbol/14; @@ -541,7 +541,7 @@ int main(int argc, char **argv) for (aa=0; aaframe_parms.nb_antennas_tx; aa++) memset(gNB->common_vars.txdataF[0][aa], 0, frame_parms->samples_per_slot_wCP * sizeof(int32_t)); - nr_common_signal_procedures (gNB,frame,slot,msgDataTx.ssb[i].ssb_pdu); + nr_common_signal_procedures (gNB,frame,slot, &ssb_pdu[i]); int samp = frame_parms->get_samples_slot_timestamp(slot, frame_parms, 0); for (aa=0; aaframe_parms.nb_antennas_tx; aa++) { @@ -744,7 +744,7 @@ int main(int argc, char **argv) gNB->gNB_config.ssb_table.ssb_subcarrier_offset.value, frame_parms->Lmax); int payload_ret = (result.xtra_byte == xtra_byte); - nfapi_nr_dl_tti_ssb_pdu_rel15_t *pdu = &msgDataTx.ssb[ssb_index].ssb_pdu.ssb_pdu_rel15; + nfapi_nr_dl_tti_ssb_pdu_rel15_t *pdu = &ssb_pdu[ssb_index].ssb_pdu_rel15; for (int i = 0; i < 3; i++) payload_ret += (result.decoded_output[i] == ((pdu->bchPayload >> (8 * i)) & 0xff)); // printf("ret %d\n", payload_ret); diff --git a/openair1/SIMULATION/NR_PHY/ulsim.c b/openair1/SIMULATION/NR_PHY/ulsim.c index b7f93cdf3a..85c165b00d 100644 --- a/openair1/SIMULATION/NR_PHY/ulsim.c +++ b/openair1/SIMULATION/NR_PHY/ulsim.c @@ -60,7 +60,6 @@ #include "PHY/defs_nr_common.h" #include "PHY/impl_defs_nr.h" #include "PHY/phy_vars_nr_ue.h" -#include "SCHED_NR/fapi_nr_l1.h" #include "SCHED_NR/sched_nr.h" #include "SCHED_NR_UE/defs.h" #include "SCHED_NR_UE/fapi_nr_ue_l1.h" @@ -727,11 +726,6 @@ int main(int argc, char *argv[]) else initNamedTpool(gNBthreads, &gNB->threadPool, true, "gNB-tpool"); - processingData_L1tx_t *msgDataTx = malloc(sizeof(processingData_L1tx_t)); - msgDataTx->slot = -1; - gNB->msgDataTx = msgDataTx; - //gNB_config = &gNB->gNB_config; - NR_UL_IND_t UL_INFO = {0}; UL_INFO.crc_ind.crc_list = UL_INFO.crc_pdu_list; UL_INFO.rx_ind.pdu_list = UL_INFO.rx_pdu_list; @@ -1284,6 +1278,9 @@ int main(int argc, char *argv[]) srs_pdu->beamforming.prg_size = 1; } + /* load FAPI into RX of L1 */ + nr_save_ul_tti_req(gNB, &Sched_INFO->UL_tti_req); + /// UE UL PDUs UE->ul_harq_processes[harq_pid].round = round; @@ -1291,9 +1288,6 @@ int main(int argc, char *argv[]) UE_proc.frame_tx = frame; UE_proc.gNB_id = 0; - // prepare ULSCH/PUSCH reception - nr_schedule_response(Sched_INFO); - // --------- setting parameters for UE -------- nr_scheduled_response_t scheduled_response = {.ul_config = &ul_config, .phy_data = (void *)&phy_data}; diff --git a/openair2/COMMON/e1ap_messages_types.h b/openair2/COMMON/e1ap_messages_types.h index 788236ca05..6906d54704 100644 --- a/openair2/COMMON/e1ap_messages_types.h +++ b/openair2/COMMON/e1ap_messages_types.h @@ -475,6 +475,14 @@ typedef struct pdu_session_to_mod_s { DRB_nGRAN_to_mod_t DRBnGRanModList[E1AP_MAX_NUM_DRBS]; } pdu_session_to_mod_t; +/** PDU Session Resource To Remove List (3GPP TS 38.463 clause 9.3.3.12) */ +typedef struct { + // PDU Session ID (M) + long sessionId; + // Cause (O) + e1ap_cause_t cause; +} pdu_session_to_remove_t; + /** * Bearer Context Setup Request message, clause 9.2.2.1 of 3GPP TS 38.463 */ @@ -534,6 +542,9 @@ typedef struct e1ap_bearer_mod_req_s { // NG-RAN PDU Session Resource To Modify List (O) int numPDUSessionsMod; pdu_session_to_mod_t pduSessionMod[E1AP_MAX_NUM_PDU_SESSIONS]; + // NG-RAN PDU Session Resource To Remove List (O) + int numPDUSessionsRem; + pdu_session_to_remove_t pduSessionRem[E1AP_MAX_NUM_PDU_SESSIONS]; } e1ap_bearer_mod_req_t; typedef struct e1ap_bearer_release_cmd_s { diff --git a/openair2/E1AP/lib/e1ap_bearer_context_management.c b/openair2/E1AP/lib/e1ap_bearer_context_management.c index 109b0008d3..f2593f103c 100644 --- a/openair2/E1AP/lib/e1ap_bearer_context_management.c +++ b/openair2/E1AP/lib/e1ap_bearer_context_management.c @@ -1631,6 +1631,20 @@ E1AP_E1AP_PDU_t *encode_E1_bearer_context_mod_request(const e1ap_bearer_mod_req_ *ieC3_1 = e1_encode_pdu_session_to_mod_item(i); } } + + // NG-RAN PDU Session Resource To Remove List (O) + if (in->numPDUSessionsRem) { + asn1cSequenceAdd(out->protocolIEs.list, E1AP_BearerContextModificationRequestIEs_t, remList); + E1AP_NG_RAN_BearerContextModificationRequest_t *msgNGRAN = encode_ng_ran_to_mod(remList); + msgNGRAN->id = E1AP_ProtocolIE_ID_id_PDU_Session_Resource_To_Remove_List; + msgNGRAN->criticality = E1AP_Criticality_reject; + msgNGRAN->value.present = E1AP_NG_RAN_BearerContextModificationRequest__value_PR_PDU_Session_Resource_To_Remove_List; + E1AP_PDU_Session_Resource_To_Remove_List_t *pdu2Remove = &msgNGRAN->value.choice.PDU_Session_Resource_To_Remove_List; + for (const pdu_session_to_remove_t *i = in->pduSessionRem; i < in->pduSessionRem + in->numPDUSessionsRem; i++) { + asn1cSequenceAdd(pdu2Remove->list, E1AP_PDU_Session_Resource_To_Remove_Item_t, ieC4_1); + ieC4_1->pDU_Session_ID = i->sessionId; + } + } return pdu; } @@ -1854,6 +1868,19 @@ bool decode_E1_bearer_context_mod_request(const E1AP_E1AP_PDU_t *pdu, e1ap_beare CHECK_E1AP_DEC(e1_decode_pdu_session_to_mod_item(out->pduSessionMod + i, modList->list.array[i])); } break; + case E1AP_ProtocolIE_ID_id_PDU_Session_Resource_To_Remove_List: + /* PDU Session Resource To Remove List (see 9.3.3.12 of TS 38.463) */ + _E1_EQ_CHECK_INT(msgNGRAN->value.present, + E1AP_NG_RAN_BearerContextModificationRequest__value_PR_PDU_Session_Resource_To_Remove_List); + E1AP_PDU_Session_Resource_To_Remove_List_t *remList = &msgNGRAN->value.choice.PDU_Session_Resource_To_Remove_List; + out->numPDUSessionsRem = remList->list.count; + // Loop through all PDU sessions to remove + for (int i = 0; i < remList->list.count; i++) { + E1AP_PDU_Session_Resource_To_Remove_Item_t *remItem = remList->list.array[i]; + pdu_session_to_remove_t *pduRem = &out->pduSessionRem[i]; + pduRem->sessionId = remItem->pDU_Session_ID; + } + break; default: PRINT_ERROR("Unknown msgNGRAN->id in E1 Setup Modification Request\n"); return false; @@ -1924,6 +1951,9 @@ e1ap_bearer_mod_req_t cp_bearer_context_mod_request(const e1ap_bearer_mod_req_t cp.pduSession[i] = cp_pdu_session_item(&msg->pduSession[i]); for (int i = 0; i < msg->numPDUSessionsMod; i++) cp.pduSessionMod[i] = cp_pdu_session_to_mod_item(&msg->pduSessionMod[i]); + // Copy PDU sessions to remove (simple struct copy, no deep copy needed) + for (int i = 0; i < msg->numPDUSessionsRem; i++) + cp.pduSessionRem[i] = msg->pduSessionRem[i]; return cp; } @@ -2037,6 +2067,15 @@ bool eq_bearer_context_mod_request(const e1ap_bearer_mod_req_t *a, const e1ap_be if (!eq_pdu_session_to_mod_item(&a->pduSessionMod[i], &b->pduSessionMod[i])) return false; } + // PDU Sessions to Remove + _E1_EQ_CHECK_INT(a->numPDUSessionsRem, b->numPDUSessionsRem); + for (int i = 0; i < a->numPDUSessionsRem; i++) { + const pdu_session_to_remove_t *pduRemA = &a->pduSessionRem[i]; + const pdu_session_to_remove_t *pduRemB = &b->pduSessionRem[i]; + _E1_EQ_CHECK_LONG(pduRemA->sessionId, pduRemB->sessionId); + _E1_EQ_CHECK_INT(pduRemA->cause.type, pduRemB->cause.type); + _E1_EQ_CHECK_INT(pduRemA->cause.value, pduRemB->cause.value); + } return true; } @@ -2114,129 +2153,129 @@ struct E1AP_E1AP_PDU *encode_E1_bearer_context_mod_response(const e1ap_bearer_mo ie2->criticality = E1AP_Criticality_reject; ie2->value.present = E1AP_BearerContextModificationResponseIEs__value_PR_GNB_CU_UP_UE_E1AP_ID; ie2->value.choice.GNB_CU_UP_UE_E1AP_ID = msg->gNB_cu_up_ue_id; - // NG-RAN PDU Session Resource Modified List (O) - asn1cSequenceAdd(out->protocolIEs.list, E1AP_BearerContextModificationResponseIEs_t, ie3); - ie3->id = E1AP_ProtocolIE_ID_id_System_BearerContextModificationResponse; - ie3->criticality = E1AP_Criticality_ignore; - // CHOICE System (O) - ie3->value.present = E1AP_BearerContextModificationResponseIEs__value_PR_System_BearerContextModificationResponse; - E1AP_System_BearerContextModificationResponse_t *sys = &ie3->value.choice.System_BearerContextModificationResponse; - // NG-RAN - E1AP_ProtocolIE_Container_4932P29_t *ngran = calloc_or_fail(1, sizeof(*ngran)); - sys->present = E1AP_System_BearerContextModificationResponse_PR_nG_RAN_BearerContextModificationResponse; - sys->choice.nG_RAN_BearerContextModificationResponse = (struct E1AP_ProtocolIE_Container *)ngran; - asn1cSequenceAdd(ngran->list, E1AP_NG_RAN_BearerContextModificationResponse_t, list); - // PDU Session Resource Modified List (O) - list->id = E1AP_ProtocolIE_ID_id_PDU_Session_Resource_Modified_List; - list->criticality = E1AP_Criticality_reject; - list->value.present = E1AP_NG_RAN_BearerContextModificationResponse__value_PR_PDU_Session_Resource_Modified_List; - E1AP_PDU_Session_Resource_Modified_List_t *pdu_mod_l = &list->value.choice.PDU_Session_Resource_Modified_List; - for (int i = 0; i < msg->numPDUSessionsMod; ++i) { - // PDU Session Resource Modified Item (1..maxnoofPDUSessionResource) - const pdu_session_modif_t *pdu = &msg->pduSessionMod[i]; - asn1cSequenceAdd(pdu_mod_l->list, E1AP_PDU_Session_Resource_Modified_Item_t, iePdu); - // PDU Session ID (M) - iePdu->pDU_Session_ID = pdu->id; - // Security Result (O) - if (pdu->confidentialityProtectionIndication || pdu->integrityProtectionIndication) { - iePdu->securityResult = calloc_or_fail(1, sizeof(*iePdu->securityResult)); - if (pdu->confidentialityProtectionIndication) - iePdu->securityResult->confidentialityProtectionResult = *pdu->confidentialityProtectionIndication; - if (pdu->integrityProtectionIndication) - iePdu->securityResult->integrityProtectionResult = *pdu->integrityProtectionIndication; - } - // NG DL UP Transport Layer Information (O) - if (pdu->ng_DL_UP_TL_info) { - iePdu->nG_DL_UP_TNL_Information = calloc_or_fail(1, sizeof(*iePdu->nG_DL_UP_TNL_Information)); - *iePdu->nG_DL_UP_TNL_Information = e1_encode_up_tnl_info(pdu->ng_DL_UP_TL_info); - } - // DRB Modified List (O) - if (pdu->numDRBModified > 0) { - iePdu->dRB_Modified_List_NG_RAN = calloc_or_fail(1, sizeof(*iePdu->dRB_Modified_List_NG_RAN)); - E1AP_DRB_Modified_List_NG_RAN_t *drb_mod_l = iePdu->dRB_Modified_List_NG_RAN; - for (int j = 0; j < pdu->numDRBModified; ++j) { - const DRB_nGRAN_modified_t *drb = &pdu->DRBnGRanModList[j]; - asn1cSequenceAdd(drb_mod_l->list, E1AP_DRB_Modified_Item_NG_RAN_t, drb_mod); - // DRB ID (M) - drb_mod->dRB_ID = drb->id; - // Flow Setup List (O) - if (drb->numQosFlowSetup) - drb_mod->flow_Setup_List = calloc_or_fail(1, sizeof(*drb_mod->flow_Setup_List)); - for (int q = 0; q < drb->numQosFlowSetup; ++q) { - asn1cSequenceAdd(drb_mod->flow_Setup_List->list, E1AP_QoS_Flow_Item_t, qos_mod); - qos_mod->qoS_Flow_Identifier = drb->qosFlows[q].qfi; - } - // Flow Failed List (O) - if (drb->numQosFlowFailed) - drb_mod->flow_Failed_List = calloc_or_fail(1, sizeof(*drb_mod->flow_Failed_List)); - for (int q = 0; q < drb->numQosFlowFailed; ++q) { - asn1cSequenceAdd(drb_mod->flow_Failed_List->list, E1AP_QoS_Flow_Failed_Item_t, fail); - encode_qos_flow_failed_item(fail, &drb->qosFlowsFailed[q]); - } - - // PDCP Status Information (O) - if (drb->pdcp_status) { - asn1cCalloc(drb_mod->pDCP_SN_Status_Information, pdcp); - *pdcp = encode_pdcp_status_info(drb->pdcp_status); - } - - // UL UP Parameters (O) - if (drb->numUpParam) - drb_mod->uL_UP_Transport_Parameters = calloc_or_fail(1, sizeof(*drb_mod->uL_UP_Transport_Parameters)); - for (const up_params_t *k = drb->ul_UP_Params; k < drb->ul_UP_Params + drb->numUpParam; k++) { - asn1cSequenceAdd(drb_mod->uL_UP_Transport_Parameters->list, E1AP_UP_Parameters_Item_t, up); - up->uP_TNL_Information = e1_encode_up_tnl_info(&k->tl_info); - up->cell_Group_ID = k->cell_group_id; + if (msg->numPDUSessionsMod > 0) { + // NG-RAN PDU Session Resource Modified List (O) + asn1cSequenceAdd(out->protocolIEs.list, E1AP_BearerContextModificationResponseIEs_t, ie3); + ie3->id = E1AP_ProtocolIE_ID_id_System_BearerContextModificationResponse; + ie3->criticality = E1AP_Criticality_ignore; + // CHOICE System (O) + ie3->value.present = E1AP_BearerContextModificationResponseIEs__value_PR_System_BearerContextModificationResponse; + E1AP_System_BearerContextModificationResponse_t *sys = &ie3->value.choice.System_BearerContextModificationResponse; + // NG-RAN + E1AP_ProtocolIE_Container_4932P29_t *ngran = calloc_or_fail(1, sizeof(*ngran)); + sys->present = E1AP_System_BearerContextModificationResponse_PR_nG_RAN_BearerContextModificationResponse; + sys->choice.nG_RAN_BearerContextModificationResponse = (struct E1AP_ProtocolIE_Container *)ngran; + asn1cSequenceAdd(ngran->list, E1AP_NG_RAN_BearerContextModificationResponse_t, list); + // PDU Session Resource Modified List (O) + list->id = E1AP_ProtocolIE_ID_id_PDU_Session_Resource_Modified_List; + list->criticality = E1AP_Criticality_reject; + list->value.present = E1AP_NG_RAN_BearerContextModificationResponse__value_PR_PDU_Session_Resource_Modified_List; + E1AP_PDU_Session_Resource_Modified_List_t *pdu_mod_l = &list->value.choice.PDU_Session_Resource_Modified_List; + for (int i = 0; i < msg->numPDUSessionsMod; ++i) { + // PDU Session Resource Modified Item (1..maxnoofPDUSessionResource) + const pdu_session_modif_t *pdu = &msg->pduSessionMod[i]; + asn1cSequenceAdd(pdu_mod_l->list, E1AP_PDU_Session_Resource_Modified_Item_t, iePdu); + // PDU Session ID (M) + iePdu->pDU_Session_ID = pdu->id; + // Security Result (O) + if (pdu->confidentialityProtectionIndication || pdu->integrityProtectionIndication) { + iePdu->securityResult = calloc_or_fail(1, sizeof(*iePdu->securityResult)); + if (pdu->confidentialityProtectionIndication) + iePdu->securityResult->confidentialityProtectionResult = *pdu->confidentialityProtectionIndication; + if (pdu->integrityProtectionIndication) + iePdu->securityResult->integrityProtectionResult = *pdu->integrityProtectionIndication; + } + // NG DL UP Transport Layer Information (O) + if (pdu->ng_DL_UP_TL_info) { + iePdu->nG_DL_UP_TNL_Information = calloc_or_fail(1, sizeof(*iePdu->nG_DL_UP_TNL_Information)); + *iePdu->nG_DL_UP_TNL_Information = e1_encode_up_tnl_info(pdu->ng_DL_UP_TL_info); + } + // DRB Modified List (O) + if (pdu->numDRBModified > 0) { + iePdu->dRB_Modified_List_NG_RAN = calloc_or_fail(1, sizeof(*iePdu->dRB_Modified_List_NG_RAN)); + E1AP_DRB_Modified_List_NG_RAN_t *drb_mod_l = iePdu->dRB_Modified_List_NG_RAN; + for (int j = 0; j < pdu->numDRBModified; ++j) { + const DRB_nGRAN_modified_t *drb = &pdu->DRBnGRanModList[j]; + asn1cSequenceAdd(drb_mod_l->list, E1AP_DRB_Modified_Item_NG_RAN_t, drb_mod); + // DRB ID (M) + drb_mod->dRB_ID = drb->id; + // Flow Setup List (O) + if (drb->numQosFlowSetup) + drb_mod->flow_Setup_List = calloc_or_fail(1, sizeof(*drb_mod->flow_Setup_List)); + for (int q = 0; q < drb->numQosFlowSetup; ++q) { + asn1cSequenceAdd(drb_mod->flow_Setup_List->list, E1AP_QoS_Flow_Item_t, qos_mod); + qos_mod->qoS_Flow_Identifier = drb->qosFlows[q].qfi; + } + // Flow Failed List (O) + if (drb->numQosFlowFailed) + drb_mod->flow_Failed_List = calloc_or_fail(1, sizeof(*drb_mod->flow_Failed_List)); + for (int q = 0; q < drb->numQosFlowFailed; ++q) { + asn1cSequenceAdd(drb_mod->flow_Failed_List->list, E1AP_QoS_Flow_Failed_Item_t, fail); + encode_qos_flow_failed_item(fail, &drb->qosFlowsFailed[q]); + } + // PDCP Status Information (O) + if (drb->pdcp_status) { + asn1cCalloc(drb_mod->pDCP_SN_Status_Information, pdcp); + *pdcp = encode_pdcp_status_info(drb->pdcp_status); + } + // UL UP Parameters (O) + if (drb->numUpParam) + drb_mod->uL_UP_Transport_Parameters = calloc_or_fail(1, sizeof(*drb_mod->uL_UP_Transport_Parameters)); + for (const up_params_t *k = drb->ul_UP_Params; k < drb->ul_UP_Params + drb->numUpParam; k++) { + asn1cSequenceAdd(drb_mod->uL_UP_Transport_Parameters->list, E1AP_UP_Parameters_Item_t, up); + up->uP_TNL_Information = e1_encode_up_tnl_info(&k->tl_info); + up->cell_Group_ID = k->cell_group_id; + } } } - } - // DRB Failed To Modify List (O) - if (pdu->numDRBFailedToMod > 0) { - iePdu->dRB_Failed_To_Modify_List_NG_RAN = calloc_or_fail(1, sizeof(*iePdu->dRB_Failed_To_Modify_List_NG_RAN)); - E1AP_DRB_Failed_To_Modify_List_NG_RAN_t *ngran = iePdu->dRB_Failed_To_Modify_List_NG_RAN; - for (int j = 0; j < pdu->numDRBFailedToMod; ++j) { - const DRB_nGRAN_failed_t *drb = &pdu->DRBnGRanFailedModList[j]; - asn1cSequenceAdd(ngran->list, E1AP_DRB_Failed_To_Modify_Item_NG_RAN_t, fail_to_mod); - encode_drb_failed_item((E1AP_DRB_Failed_Item_NG_RAN_t *)fail_to_mod, drb); - } - } - // DRB Setup List (O) - if (pdu->numDRBSetup > 0) { - iePdu->dRB_Setup_List_NG_RAN = calloc_or_fail(1, sizeof(*iePdu->dRB_Setup_List_NG_RAN)); - E1AP_DRB_Setup_List_NG_RAN_t *drb_setup = iePdu->dRB_Setup_List_NG_RAN; - for (int j = 0; j < pdu->numDRBModified; ++j) { - const DRB_nGRAN_setup_t *drb = &pdu->DRBnGRanSetupList[j]; - asn1cSequenceAdd(drb_setup->list, E1AP_DRB_Setup_Item_NG_RAN_t, item); - // DRB ID (M) - item->dRB_ID = drb->id; - // UL UP Parameters (M) - for (const up_params_t *k = drb->UpParamList; k < drb->UpParamList + drb->numUpParam; k++) { - asn1cSequenceAdd(item->uL_UP_Transport_Parameters.list, E1AP_UP_Parameters_Item_t, up); - up->uP_TNL_Information = e1_encode_up_tnl_info(&k->tl_info); - up->cell_Group_ID = drb->UpParamList->cell_group_id; - } - // Flow Setup List (M) - for (int q = 0; q < drb->numQosFlowSetup; ++q) { - asn1cSequenceAdd(item->flow_Setup_List.list, E1AP_QoS_Flow_Item_t, qos); - qos->qoS_Flow_Identifier = drb->qosFlows[q].qfi; - } - // Flow Failed List (O) - if (drb->numQosFlowFailed) - item->flow_Failed_List = calloc_or_fail(1, sizeof(*item->flow_Failed_List)); - for (int q = 0; q < drb->numQosFlowFailed; ++q) { - asn1cSequenceAdd(item->flow_Failed_List->list, E1AP_QoS_Flow_Failed_Item_t, fail); - encode_qos_flow_failed_item(fail, &drb->qosFlowsFailed[q]); + // DRB Failed To Modify List (O) + if (pdu->numDRBFailedToMod > 0) { + iePdu->dRB_Failed_To_Modify_List_NG_RAN = calloc_or_fail(1, sizeof(*iePdu->dRB_Failed_To_Modify_List_NG_RAN)); + E1AP_DRB_Failed_To_Modify_List_NG_RAN_t *ngran = iePdu->dRB_Failed_To_Modify_List_NG_RAN; + for (int j = 0; j < pdu->numDRBFailedToMod; ++j) { + const DRB_nGRAN_failed_t *drb = &pdu->DRBnGRanFailedModList[j]; + asn1cSequenceAdd(ngran->list, E1AP_DRB_Failed_To_Modify_Item_NG_RAN_t, fail_to_mod); + encode_drb_failed_item((E1AP_DRB_Failed_Item_NG_RAN_t *)fail_to_mod, drb); } } - } - // DRB Failed List (O) - if (pdu->numDRBFailed) { - iePdu->dRB_Failed_List_NG_RAN = calloc_or_fail(1, sizeof(*iePdu->dRB_Failed_List_NG_RAN)); - E1AP_DRB_Failed_List_NG_RAN_t *ngran = iePdu->dRB_Failed_List_NG_RAN; - for (int j = 0; j < pdu->numDRBFailed; ++j) { - const DRB_nGRAN_failed_t *drb = &pdu->DRBnGRanFailedList[j]; - asn1cSequenceAdd(ngran->list, E1AP_DRB_Failed_Item_NG_RAN_t, fail); - encode_drb_failed_item(fail, drb); + // DRB Setup List (O) + if (pdu->numDRBSetup > 0) { + iePdu->dRB_Setup_List_NG_RAN = calloc_or_fail(1, sizeof(*iePdu->dRB_Setup_List_NG_RAN)); + E1AP_DRB_Setup_List_NG_RAN_t *drb_setup = iePdu->dRB_Setup_List_NG_RAN; + for (int j = 0; j < pdu->numDRBModified; ++j) { + const DRB_nGRAN_setup_t *drb = &pdu->DRBnGRanSetupList[j]; + asn1cSequenceAdd(drb_setup->list, E1AP_DRB_Setup_Item_NG_RAN_t, item); + // DRB ID (M) + item->dRB_ID = drb->id; + // UL UP Parameters (M) + for (const up_params_t *k = drb->UpParamList; k < drb->UpParamList + drb->numUpParam; k++) { + asn1cSequenceAdd(item->uL_UP_Transport_Parameters.list, E1AP_UP_Parameters_Item_t, up); + up->uP_TNL_Information = e1_encode_up_tnl_info(&k->tl_info); + up->cell_Group_ID = drb->UpParamList->cell_group_id; + } + // Flow Setup List (M) + for (int q = 0; q < drb->numQosFlowSetup; ++q) { + asn1cSequenceAdd(item->flow_Setup_List.list, E1AP_QoS_Flow_Item_t, qos); + qos->qoS_Flow_Identifier = drb->qosFlows[q].qfi; + } + // Flow Failed List (O) + if (drb->numQosFlowFailed) + item->flow_Failed_List = calloc_or_fail(1, sizeof(*item->flow_Failed_List)); + for (int q = 0; q < drb->numQosFlowFailed; ++q) { + asn1cSequenceAdd(item->flow_Failed_List->list, E1AP_QoS_Flow_Failed_Item_t, fail); + encode_qos_flow_failed_item(fail, &drb->qosFlowsFailed[q]); + } + } + } + // DRB Failed List (O) + if (pdu->numDRBFailed) { + iePdu->dRB_Failed_List_NG_RAN = calloc_or_fail(1, sizeof(*iePdu->dRB_Failed_List_NG_RAN)); + E1AP_DRB_Failed_List_NG_RAN_t *ngran = iePdu->dRB_Failed_List_NG_RAN; + for (int j = 0; j < pdu->numDRBFailed; ++j) { + const DRB_nGRAN_failed_t *drb = &pdu->DRBnGRanFailedList[j]; + asn1cSequenceAdd(ngran->list, E1AP_DRB_Failed_Item_NG_RAN_t, fail); + encode_drb_failed_item(fail, drb); + } } } } diff --git a/openair2/E1AP/lib/e1ap_lib_includes.h b/openair2/E1AP/lib/e1ap_lib_includes.h index 028993e6fd..adafbe0ae5 100644 --- a/openair2/E1AP/lib/e1ap_lib_includes.h +++ b/openair2/E1AP/lib/e1ap_lib_includes.h @@ -78,6 +78,7 @@ #include "E1AP_DRB-To-Modify-Item-NG-RAN.h" #include "E1AP_PDU-Session-Resource-To-Setup-Mod-Item.h" #include "E1AP_DRB-To-Setup-Mod-Item-NG-RAN.h" +#include "E1AP_PDU-Session-Resource-To-Remove-Item.h" // E1 Bearer Context Modification Response #include "E1AP_PDU-Session-Resource-Modified-Item.h" #include "E1AP_DRB-Modified-List-NG-RAN.h" diff --git a/openair2/E1AP/tests/e1ap_lib_test.c b/openair2/E1AP/tests/e1ap_lib_test.c index b168ff9e82..50116514fb 100644 --- a/openair2/E1AP/tests/e1ap_lib_test.c +++ b/openair2/E1AP/tests/e1ap_lib_test.c @@ -538,6 +538,14 @@ static void test_bearer_context_modification_request(void) .DRBnGRanList[0] = drb_to_setup, }; + // PDU Session to Remove + pdu_session_to_remove_t pdu_session_to_remove = { + .sessionId = 2, + // Note: cause is optional extension IE, currently encoding/decoding only handles sessionId + .cause.type = 0, + .cause.value = 0, + }; + // Initialize the Bearer Context Modification Request e1ap_bearer_mod_req_t orig = { .gNB_cu_cp_ue_id = 0x1234, @@ -548,6 +556,8 @@ static void test_bearer_context_modification_request(void) .pduSession[0] = pdusession_setup_item, .numPDUSessionsMod = 1, .pduSessionMod[0] = pdusession_mod_item, + .numPDUSessionsRem = 1, + .pduSessionRem[0] = pdu_session_to_remove, }; *orig.bearerContextStatus = BEARER_SUSPEND; *orig.inactivityTimer = 1000; diff --git a/openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_kpm.c b/openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_kpm.c index 02760c4984..8933b802a0 100644 --- a/openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_kpm.c +++ b/openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_kpm.c @@ -54,10 +54,12 @@ typedef struct { ue_id_e2sm_t* ue_id; // Optional - // only used to retreive MAC/RLC stats + // only used to retrieve MAC/RLC stats NR_UE_info_t** ue_info_list; }arr_ue_id_t; +static e2_node_level_stats_t node_stats[2] = {0}; // [0] node stats collected in previous reporting period; [1] current node stats + static meas_data_lst_t fill_kpm_meas_data_item(const meas_info_format_1_lst_t* meas_info_lst, const size_t len, const uint32_t gran_period_ms, cudu_ue_info_pair_t ue_info, const size_t ue_idx) { meas_data_lst_t data_item = {0}; @@ -74,7 +76,7 @@ static meas_data_lst_t fill_kpm_meas_data_item(const meas_info_format_1_lst_t* m char* meas_info_name_str = cp_ba_to_str(meas_info_lst[i].meas_type.name); - data_item.meas_record_lst[i] = get_kpm_meas_value(meas_info_name_str, gran_period_ms, ue_info, ue_idx); + data_item.meas_record_lst[i] = get_kpm_meas_value(meas_info_name_str, gran_period_ms, ue_info, ue_idx, node_stats); free(meas_info_name_str); } @@ -153,6 +155,8 @@ static kpm_ind_msg_format_3_t fill_kpm_ind_msg_frm_3(arr_ue_id_t* arr_ue_id, con msg_frm_3.meas_report_per_ue[i].ind_msg_format_1 = fill_kpm_ind_msg_frm_1(ue_info, i, act_def_fr_1); } + node_stats[0] = cp_node_level_stats(&node_stats[1]); + return msg_frm_3; } @@ -288,8 +292,10 @@ static arr_ue_id_t filter_ues_by_s_nssai_in_du_or_monolithic(const test_info_lst const ngran_node_t node_type = get_e2_node_type(); + gNB_MAC_INST *mac = RC.nrmac[0]; + NR_SCHED_LOCK(&mac->sched_lock); // Take MAC info - UE_iterator(RC.nrmac[0]->UE_info.connected_ue_list, ue) { + UE_iterator(mac->UE_info.connected_ue_list, ue) { NR_UE_sched_ctrl_t *sched_ctrl = &ue->UE_sched_ctrl; // UE matches if any of its DRBs matches for (size_t l = 0; l < seq_arr_size(&sched_ctrl->lc_config); ++l) { @@ -316,6 +322,10 @@ static arr_ue_id_t filter_ues_by_s_nssai_in_du_or_monolithic(const test_info_lst AssertFatal(arr_ue_id.sz < MAX_MOBILES_PER_GNB, "cannot have more UEs than global UE number maximum\n"); } + node_stats[1].mac_stats.dl.total_prb_aggregate = mac->mac_stats.dl.total_prb_aggregate; + node_stats[1].mac_stats.ul.total_prb_aggregate = mac->mac_stats.ul.total_prb_aggregate; + NR_SCHED_UNLOCK(&mac->sched_lock); + free(sd); // if NULL, nothing happens return arr_ue_id; diff --git a/openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_kpm_subs.c b/openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_kpm_subs.c index 80579e1754..d3381cadd3 100644 --- a/openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_kpm_subs.c +++ b/openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_kpm_subs.c @@ -23,6 +23,18 @@ #include +e2_node_level_stats_t cp_node_level_stats(const e2_node_level_stats_t *src) +{ + e2_node_level_stats_t dst = { + .mac_stats.dl.total_prb_aggregate = src->mac_stats.dl.total_prb_aggregate, + .mac_stats.dl.used_prb_aggregate = src->mac_stats.dl.used_prb_aggregate, + .mac_stats.ul.total_prb_aggregate = src->mac_stats.ul.total_prb_aggregate, + .mac_stats.ul.used_prb_aggregate = src->mac_stats.ul.used_prb_aggregate, + }; + + return dst; +} + /* measurements that need to store values from previous reporting period have a limitation when it comes to multiple subscriptions to the same UEs; ric_req_id is unique per subscription */ typedef struct uldlcounter { @@ -46,7 +58,7 @@ static nr_pdcp_statistics_t get_pdcp_stats_per_drb(const uint32_t rrc_ue_id, con /* 3GPP TS 28.522 - section 5.1.2.1.1.1 note: this measurement is calculated as per spec */ -static meas_record_lst_t fill_DRB_PdcpSduVolumeDL(__attribute__((unused))uint32_t gran_period_ms, cudu_ue_info_pair_t ue_info, const size_t ue_idx) +static meas_record_lst_t fill_DRB_PdcpSduVolumeDL(__attribute__((unused))uint32_t gran_period_ms, cudu_ue_info_pair_t ue_info, const size_t ue_idx, __attribute__((unused))e2_node_level_stats_t* node_stats) { meas_record_lst_t meas_record = {0}; @@ -57,7 +69,7 @@ static meas_record_lst_t fill_DRB_PdcpSduVolumeDL(__attribute__((unused))uint32_ meas_record.value = INTEGER_MEAS_VALUE; // Get DL data volume delivered to PDCP layer - meas_record.int_val = (pdcp.rxsdu_bytes - last_pdcp_sdu_total_bytes[ue_idx].dl)*8/1000; // [kb] + meas_record.int_val = (pdcp.rxsdu_bytes - last_pdcp_sdu_total_bytes[ue_idx].dl)*8/1000000; // [Mb] last_pdcp_sdu_total_bytes[ue_idx].dl = pdcp.rxsdu_bytes; return meas_record; @@ -65,7 +77,7 @@ static meas_record_lst_t fill_DRB_PdcpSduVolumeDL(__attribute__((unused))uint32_ /* 3GPP TS 28.522 - section 5.1.2.1.2.1 note: this measurement is calculated as per spec */ -static meas_record_lst_t fill_DRB_PdcpSduVolumeUL(__attribute__((unused))uint32_t gran_period_ms, cudu_ue_info_pair_t ue_info, const size_t ue_idx) +static meas_record_lst_t fill_DRB_PdcpSduVolumeUL(__attribute__((unused))uint32_t gran_period_ms, cudu_ue_info_pair_t ue_info, const size_t ue_idx, __attribute__((unused))e2_node_level_stats_t* node_stats) { meas_record_lst_t meas_record = {0}; @@ -76,7 +88,7 @@ static meas_record_lst_t fill_DRB_PdcpSduVolumeUL(__attribute__((unused))uint32_ meas_record.value = INTEGER_MEAS_VALUE; // Get UL data volume delivered from PDCP layer - meas_record.int_val = (pdcp.txsdu_bytes - last_pdcp_sdu_total_bytes[ue_idx].ul)*8/1000; // [kb] + meas_record.int_val = (pdcp.txsdu_bytes - last_pdcp_sdu_total_bytes[ue_idx].ul)*8/1000000; // [Mb] last_pdcp_sdu_total_bytes[ue_idx].ul = pdcp.txsdu_bytes; return meas_record; @@ -103,7 +115,7 @@ static nr_rlc_statistics_t get_rlc_stats_per_drb(const rnti_t rnti, const int rb /* 3GPP TS 28.522 - section 5.1.3.3.3 note: by default this measurement is calculated for previous 100ms (openair2/LAYER2/nr_rlc/nr_rlc_entity.c:118, 173, 213); please, update according to your needs */ -static meas_record_lst_t fill_DRB_RlcSduDelayDl(__attribute__((unused))uint32_t gran_period_ms, cudu_ue_info_pair_t ue_info, __attribute__((unused))const size_t ue_idx) +static meas_record_lst_t fill_DRB_RlcSduDelayDl(__attribute__((unused))uint32_t gran_period_ms, cudu_ue_info_pair_t ue_info, __attribute__((unused))const size_t ue_idx, __attribute__((unused))e2_node_level_stats_t* node_stats) { meas_record_lst_t meas_record = {0}; @@ -122,7 +134,7 @@ static meas_record_lst_t fill_DRB_RlcSduDelayDl(__attribute__((unused))uint32_t /* 3GPP TS 28.522 - section 5.1.1.3.1 note: per spec, average UE throughput in DL (taken into consideration values from all UEs, and averaged) here calculated as: UE specific throughput in DL */ -static meas_record_lst_t fill_DRB_UEThpDl(uint32_t gran_period_ms, cudu_ue_info_pair_t ue_info, const size_t ue_idx) +static meas_record_lst_t fill_DRB_UEThpDl(uint32_t gran_period_ms, cudu_ue_info_pair_t ue_info, const size_t ue_idx, __attribute__((unused))e2_node_level_stats_t* node_stats) { meas_record_lst_t meas_record = {0}; @@ -141,7 +153,7 @@ static meas_record_lst_t fill_DRB_UEThpDl(uint32_t gran_period_ms, cudu_ue_info_ /* 3GPP TS 28.522 - section 5.1.1.3.3 note: per spec, average UE throughput in UL (taken into consideration values from all UEs, and averaged) here calculated as: UE specific throughput in UL */ -static meas_record_lst_t fill_DRB_UEThpUl(uint32_t gran_period_ms, cudu_ue_info_pair_t ue_info, const size_t ue_idx) +static meas_record_lst_t fill_DRB_UEThpUl(uint32_t gran_period_ms, cudu_ue_info_pair_t ue_info, const size_t ue_idx, __attribute__((unused))e2_node_level_stats_t* node_stats) { meas_record_lst_t meas_record = {0}; @@ -159,32 +171,30 @@ static meas_record_lst_t fill_DRB_UEThpUl(uint32_t gran_period_ms, cudu_ue_info_ } /* 3GPP TS 28.522 - section 5.1.1.2.1 - note: per spec, DL PRB usage [%] = (total used PRBs for DL traffic / total available PRBs for DL traffic) * 100 - here calculated as: aggregated DL PRBs (t) - aggregated DL PRBs (t-gran_period) */ -static meas_record_lst_t fill_RRU_PrbTotDl(__attribute__((unused))uint32_t gran_period_ms, cudu_ue_info_pair_t ue_info, const size_t ue_idx) + note: this measurement is calculated as per spec */ +static meas_record_lst_t fill_RRU_PrbTotDl(__attribute__((unused))uint32_t gran_period_ms, cudu_ue_info_pair_t ue_info, const size_t ue_idx, e2_node_level_stats_t* node_stats) { meas_record_lst_t meas_record = {0}; meas_record.value = INTEGER_MEAS_VALUE; // Get the number of DL PRBs - meas_record.int_val = ue_info.ue->mac_stats.dl.total_rbs - last_total_prbs[ue_idx].dl; // [PRBs] + meas_record.int_val = (ue_info.ue->mac_stats.dl.total_rbs - last_total_prbs[ue_idx].dl) * 100 / (node_stats[1].mac_stats.dl.total_prb_aggregate - node_stats[0].mac_stats.dl.total_prb_aggregate); // [%] last_total_prbs[ue_idx].dl = ue_info.ue->mac_stats.dl.total_rbs; return meas_record; } /* 3GPP TS 28.522 - section 5.1.1.2.2 - note: per spec, UL PRB usage [%] = (total used PRBs for UL traffic / total available PRBs for UL traffic) * 100 - here calculated as: aggregated UL PRBs (t) - aggregated UL PRBs (t-gran_period) */ -static meas_record_lst_t fill_RRU_PrbTotUl(__attribute__((unused))uint32_t gran_period_ms, cudu_ue_info_pair_t ue_info, const size_t ue_idx) + note: this measurement is calculated as per spec */ +static meas_record_lst_t fill_RRU_PrbTotUl(__attribute__((unused))uint32_t gran_period_ms, cudu_ue_info_pair_t ue_info, const size_t ue_idx, e2_node_level_stats_t* node_stats) { meas_record_lst_t meas_record = {0}; meas_record.value = INTEGER_MEAS_VALUE; // Get the number of UL PRBs - meas_record.int_val = ue_info.ue->mac_stats.ul.total_rbs - last_total_prbs[ue_idx].ul; // [PRBs] + meas_record.int_val = (ue_info.ue->mac_stats.ul.total_rbs - last_total_prbs[ue_idx].ul) * 100 / (node_stats[1].mac_stats.ul.total_prb_aggregate - node_stats[0].mac_stats.ul.total_prb_aggregate); // [%] last_total_prbs[ue_idx].ul = ue_info.ue->mac_stats.ul.total_rbs; return meas_record; @@ -217,7 +227,7 @@ void init_kpm_subs_data(void) } } -meas_record_lst_t get_kpm_meas_value(char* kpm_meas_name, uint32_t gran_period_ms, cudu_ue_info_pair_t ue_info, const size_t ue_idx) +meas_record_lst_t get_kpm_meas_value(char* kpm_meas_name, uint32_t gran_period_ms, cudu_ue_info_pair_t ue_info, const size_t ue_idx, e2_node_level_stats_t* node_stats) { assert(kpm_meas_name != NULL); @@ -226,7 +236,7 @@ meas_record_lst_t get_kpm_meas_value(char* kpm_meas_name, uint32_t gran_period_m assert(found_entry != NULL && "Unsupported KPM measurement name"); kv_measure_t *kv_found = (kv_measure_t *)found_entry->data; - meas_record_lst_t meas_record = kv_found->value(gran_period_ms, ue_info, ue_idx); + meas_record_lst_t meas_record = kv_found->value(gran_period_ms, ue_info, ue_idx, node_stats); return meas_record; } diff --git a/openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_kpm_subs.h b/openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_kpm_subs.h index 7dbd807fa1..e612ca2bab 100644 --- a/openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_kpm_subs.h +++ b/openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_kpm_subs.h @@ -34,7 +34,13 @@ typedef struct { } cudu_ue_info_pair_t; -typedef meas_record_lst_t (*kpm_meas_fp)(uint32_t gran_period_ms, cudu_ue_info_pair_t ue_info, const size_t ue_idx); +typedef struct { + dlul_mac_stats_t mac_stats; +} e2_node_level_stats_t; + +e2_node_level_stats_t cp_node_level_stats(const e2_node_level_stats_t *src); + +typedef meas_record_lst_t (*kpm_meas_fp)(uint32_t gran_period_ms, cudu_ue_info_pair_t ue_info, const size_t ue_idx, e2_node_level_stats_t* node_stats); typedef struct{ char* key; @@ -44,6 +50,6 @@ typedef struct{ void init_kpm_subs_data(void); -meas_record_lst_t get_kpm_meas_value(char* kpm_meas_name, uint32_t gran_period_ms, cudu_ue_info_pair_t ue_info, const size_t ue_idx); +meas_record_lst_t get_kpm_meas_value(char* kpm_meas_name, uint32_t gran_period_ms, cudu_ue_info_pair_t ue_info, const size_t ue_idx, e2_node_level_stats_t* node_stats); #endif diff --git a/openair2/E2AP/flexric b/openair2/E2AP/flexric index df754a8553..6a595d8b24 160000 --- a/openair2/E2AP/flexric +++ b/openair2/E2AP/flexric @@ -1 +1 @@ -Subproject commit df754a85537f6db255b5330b8d83eda6a2742f25 +Subproject commit 6a595d8b243601b7148f60b5cb2cec47658e58c5 diff --git a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c index 3b26bf0a35..13f2eca955 100644 --- a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c +++ b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c @@ -2819,11 +2819,13 @@ uint16_t nr_dci_size(const NR_UE_DL_BWP_t *DL_BWP, dci_pdu->harq_pid.nbits = 4; dci_pdu->frequency_domain_assignment.nbits = (uint8_t)ceil(log2((N_RB * (N_RB + 1)) >>1)); // Freq domain assignment -- hopping scenario to be updated size += dci_pdu->frequency_domain_assignment.nbits; - if(alt_size >= size) - size += alt_size - size; // Padding to match 1_0 size - else if (ss_type == NR_SearchSpace__searchSpaceType_PR_common) { - dci_pdu->frequency_domain_assignment.nbits -= (size - alt_size); - size = alt_size; + if (alt_size) { + if(alt_size >= size) + size += alt_size - size; // Padding to match 1_0 size + else if (ss_type == NR_SearchSpace__searchSpaceType_PR_common) { + dci_pdu->frequency_domain_assignment.nbits -= (size - alt_size); + size = alt_size; + } } // UL/SUL indicator assumed to be 0 break; @@ -3133,7 +3135,7 @@ uint16_t nr_dci_size(const NR_UE_DL_BWP_t *DL_BWP, default: AssertFatal(1==0, "Invalid NR DCI format %d\n", format); } - LOG_D(NR_MAC, "DCI size: %d\n", size); + LOG_D(NR_MAC, "DCI format %d size: %d alt_size %d\n", format, size, alt_size); return size; } diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c index 714d2eacfd..bd9ea09041 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c @@ -555,6 +555,7 @@ int nr_config_pusch_pdu(NR_UE_MAC_INST_t *mac, pusch_config_pdu->tbslbrm = 0; } else if (dci) { + pusch_config_pdu->subcarrier_spacing = scs; pusch_config_pdu->ulsch_indicator = dci->ulsch_indicator; if (dci->csi_request.nbits > 0 && dci->csi_request.val > 0) { AssertFatal(csi_report, "CSI report needs to be present in case of CSI request\n"); diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c index a102411721..6a9cce656a 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c @@ -59,13 +59,7 @@ uint8_t nr_get_rv(int rel_round) return nr_rv_round_map[rel_round]; } -void clear_nr_nfapi_information(gNB_MAC_INST *gNB, - int CC_idP, - frame_t frameP, - slot_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 clear_nr_nfapi_information(gNB_MAC_INST *gNB, int CC_idP, frame_t frameP, slot_t slotP) { /* called below and in simulators, so we assume a lock but don't require it */ const int num_slots = gNB->frame_structure.numb_slots_frame; @@ -75,16 +69,8 @@ void clear_nr_nfapi_information(gNB_MAC_INST *gNB, gNB->pdu_index[CC_idP] = 0; - DL_req[CC_idP].SFN = frameP; - DL_req[CC_idP].Slot = slotP; - DL_req[CC_idP].dl_tti_request_body.nPDUs = 0; - DL_req[CC_idP].dl_tti_request_body.nGroup = 0; memset(pdcch, 0, sizeof(*pdcch) * MAX_NUM_CORESET); - UL_dci_req[CC_idP].SFN = frameP; - UL_dci_req[CC_idP].Slot = slotP; - UL_dci_req[CC_idP].numPdus = 0; - /* advance last round's future UL_tti_req to be ahead of current frame/slot */ const int size = gNB->UL_tti_req_ahead_size; const int prev_slot = frameP * num_slots + slotP + size - 1; @@ -100,8 +86,6 @@ void clear_nr_nfapi_information(gNB_MAC_INST *gNB, future_ul_tti_req->n_ulsch = 0; future_ul_tti_req->n_ulcch = 0; future_ul_tti_req->n_group = 0; - - TX_req[CC_idP].Number_of_PDUs = 0; } static void clear_beam_information(NR_beam_info_t *beam_info, int frame, int slot, int slots_per_frame) @@ -191,7 +175,7 @@ void gNB_dlsch_ulsch_scheduler(module_id_t module_idP, frame_t frame, slot_t slo uint16_t *vrb_map_UL = cc[CC_id].vrb_map_UL[i]; 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, &sched_info->DL_req, &sched_info->TX_req, &sched_info->UL_dci_req); + clear_nr_nfapi_information(gNB, CC_id, frame, slot); } bool wait_prach_completed = gNB->num_scheduled_prach_rx >= NUM_PRACH_RX_FOR_NOISE_ESTIMATE; diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c index d848cf99c8..fd1cf7f9f3 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c @@ -649,9 +649,8 @@ static void pf_dl(gNB_MAC_INST *mac, stats->current_bytes = 0; stats->current_rbs = 0; - /* Check if this UE should get TA (every 100 frames). If we add the CE, - * ta_apply will be reset */ - if (frame == ((sched_ctrl->ta_frame + 100) % 1024)) + /* Check if this UE should get TA. If we add the CE, ta_apply will be reset */ + if (frame == sched_ctrl->ta_frame) sched_ctrl->ta_apply = true; int total_rem_ues = 0; @@ -690,7 +689,7 @@ static void pf_dl(gNB_MAC_INST *mac, update_dlsch_buffer(pp_pdsch->frame, pp_pdsch->slot, UE); /* Check DL buffer and skip this UE if no bytes and no TA necessary */ - if (sched_ctrl->num_total_bytes == 0 && frame != (sched_ctrl->ta_frame + 100) % 1024) + if (sched_ctrl->num_total_bytes == 0 && sched_ctrl->ta_apply == false) continue; /* Calculate coeff */ @@ -871,8 +870,8 @@ static void pf_dl(gNB_MAC_INST *mac, // awaiting. Therefore, for the time being, we put a fixed overhead of 12 // (for 4 PDUs) and optionally + 2 for TA. Once RLC gives the number of // PDUs, we replace with 3 * numPDUs - const int oh = 3 * 4 + 2 * (frame == (sched_ctrl->ta_frame + 100) % 1024); - //const int oh = 3 * sched_ctrl->dl_pdus_total + 2 * (frame == (sched_ctrl->ta_frame + 100) % 1024); + const int oh = 3 * 4 + (sched_ctrl->ta_apply ? 2 : 0); + //const int oh = 3 * sched_ctrl->dl_pdus_total + (sched_ctrl->ta_apply ? 2 : 0); nr_find_nb_rb(sched_pdsch.Qm, sched_pdsch.R, 1, // no transform precoding for DL @@ -1224,7 +1223,7 @@ void post_process_dlsch(gNB_MAC_INST *nr_mac, post_process_pdsch_t *pdsch, NR_UE T(T_GNB_MAC_RETRANSMISSION_DL_PDU_WITH_DATA, T_INT(module_id), T_INT(CC_id), T_INT(rnti), T_INT(frame), T_INT(slot), T_INT(current_harq_pid), T_INT(harq->round), T_BUFFER(harq->transportBlock.buf, TBS)); UE->mac_stats.dl.total_rbs_retx += sched_pdsch->rbSize; - nr_mac->mac_stats.used_prb_aggregate += sched_pdsch->rbSize; + nr_mac->mac_stats.dl.used_prb_aggregate += sched_pdsch->rbSize; } else { /* initial transmission */ LOG_D(NR_MAC, "Initial HARQ transmission in %d.%d\n", frame, slot); uint8_t *buf = allocate_transportBlock_buffer(&harq->transportBlock, TBS); @@ -1338,7 +1337,7 @@ void post_process_dlsch(gNB_MAC_INST *nr_mac, post_process_pdsch_t *pdsch, NR_UE UE->mac_stats.dl.num_mac_sdu += sdus; UE->mac_stats.dl.current_rbs = sched_pdsch->rbSize; UE->mac_stats.dl.total_sdu_bytes += dlsch_total_bytes; - nr_mac->mac_stats.used_prb_aggregate += sched_pdsch->rbSize; + nr_mac->mac_stats.dl.used_prb_aggregate += sched_pdsch->rbSize; /* save retransmission information */ harq->sched_pdsch = *sched_pdsch; @@ -1349,8 +1348,9 @@ void post_process_dlsch(gNB_MAC_INST *nr_mac, post_process_pdsch_t *pdsch, NR_UE // ta command is sent, values are reset if (sched_ctrl->ta_apply) { sched_ctrl->ta_apply = false; - sched_ctrl->ta_frame = frame; - LOG_D(NR_MAC, "%d.%2d UE %04x TA scheduled, resetting TA frame\n", frame, slot, UE->rnti); + sched_ctrl->ta_update = 31; + sched_ctrl->ta_frame = (frame + 100) % MAX_FRAME_NUMBER; + LOG_D(NR_MAC, "%d.%2d UE %04x TA scheduled, setting next TA frame to %d\n", frame, slot, UE->rnti, sched_ctrl->ta_frame); } T(T_GNB_MAC_DL_PDU_WITH_DATA, T_INT(module_id), T_INT(CC_id), T_INT(rnti), @@ -1387,8 +1387,8 @@ void nr_schedule_ue_spec(module_id_t module_id, return; NR_ServingCellConfigCommon_t *scc = gNB_mac->common_channels[CC_id].ServingCellConfigCommon; - const NR_BWP_t *initialDL = &scc->downlinkConfigCommon->initialDownlinkBWP->genericParameters; - gNB_mac->mac_stats.total_prb_aggregate += NRRIV2BW(initialDL->locationAndBandwidth, MAX_BWP_SIZE); + int bw = scc->downlinkConfigCommon->frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->carrierBandwidth; + gNB_mac->mac_stats.dl.total_prb_aggregate += bw; nfapi_nr_dl_tti_request_body_t *dl_req = &DL_req->dl_tti_request_body; post_process_pdsch_t pdsch = { frame, slot, dl_req, TX_req }; diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c index a81841d9c0..128f2db336 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c @@ -125,6 +125,8 @@ static const uint16_t cqi_table3[16][2] = {{0, 0}, static void determine_aggregation_level_search_order(int agg_level_search_order[NUM_PDCCH_AGG_LEVELS], float pdcch_cl_adjust); +static int nr_mac_interrupt_ue_transmission(gNB_MAC_INST *mac, NR_UE_info_t *UE, int slots, int slots_per_frame); + uint8_t get_dl_nrOfLayers(const NR_UE_sched_ctrl_t *sched_ctrl, const nr_dci_format_t dci_format) { // TODO check this but it should be enough for now @@ -3435,7 +3437,7 @@ void nr_measgap_scheduling(gNB_MAC_INST *nr_mac, frame_t frame, sub_frame_t slot continue; const int slots_frame = nr_mac->frame_structure.numb_slots_frame; - const frame_t f = (frame + (slot + mgc->n_slots_advance) / slots_frame) % 1024; + const frame_t f = (frame + (slot + mgc->n_slots_advance) / slots_frame) % MAX_FRAME_NUMBER; const slot_t s = (slot + mgc->n_slots_advance) % slots_frame; // TS 38 331 - Section 5.5.2.9 Measurement gap configuration @@ -3446,7 +3448,7 @@ void nr_measgap_scheduling(gNB_MAC_INST *nr_mac, frame_t frame, sub_frame_t slot // start a timer to stop scheduling UE during MeasGap, or extend timer for // duration of measGap with existing follow-up action if (!nr_timer_is_active(t) || nr_timer_remaining_time(t) < mgc->mgl_slots) { - nr_mac_interrupt_ue_transmission(nr_mac, UE, mgc->mgl_slots); + nr_mac_interrupt_ue_transmission(nr_mac, UE, mgc->mgl_slots, slots_frame); } } } @@ -3530,7 +3532,7 @@ int nr_mac_get_reconfig_delay_slots(NR_SubcarrierSpacing_t scs) return (delay_ms << scs) + sl_ahead; } -int nr_mac_interrupt_ue_transmission(gNB_MAC_INST *mac, NR_UE_info_t *UE, int slots) +static int nr_mac_interrupt_ue_transmission(gNB_MAC_INST *mac, NR_UE_info_t *UE, int slots, int slots_per_frame) { DevAssert(mac != NULL); DevAssert(UE != NULL); @@ -3539,11 +3541,11 @@ int nr_mac_interrupt_ue_transmission(gNB_MAC_INST *mac, NR_UE_info_t *UE, int sl nr_timer_setup(&UE->UE_sched_ctrl.transm_interrupt, slots, 1); nr_timer_start(&UE->UE_sched_ctrl.transm_interrupt); - // it might happen that timing advance command should be sent during the UE - // inactivity time. To prevent this, 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 the inactivity of the UE. - UE->UE_sched_ctrl.ta_frame = (mac->frame - 1 + 1024) % 1024; + // it might happen that timing advance command should be sent during the UE inactivity time. + // To prevent this, delay next TA command just after the UE inactivity time. + const int inactive_frames = slots / slots_per_frame + 1; + if ((UE->UE_sched_ctrl.ta_frame - mac->frame + MAX_FRAME_NUMBER) % MAX_FRAME_NUMBER < inactive_frames) + UE->UE_sched_ctrl.ta_frame = (mac->frame + inactive_frames) % MAX_FRAME_NUMBER; LOG_D(NR_MAC, "UE %04x: Interrupt UE transmission (%d slots)\n", UE->rnti, slots); return 0; diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c index 94325bf26b..3f546d41b4 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c @@ -811,7 +811,7 @@ static void nr_rx_ra_sdu(const module_id_t mod_id, } // re-initialize ta update variables after RA procedure completion - UE->UE_sched_ctrl.ta_frame = frame; + UE->UE_sched_ctrl.ta_frame = (frame + 100) % MAX_FRAME_NUMBER; LOG_A(NR_MAC, "%4d.%2d PUSCH with TC_RNTI 0x%04x received correctly\n", frame, slot, rnti); @@ -2455,6 +2455,7 @@ void post_process_ulsch(gNB_MAC_INST *nr_mac, post_process_pusch_t *pusch, NR_UE } UE->mac_stats.ul.current_bytes = sched_pusch->tb_size; UE->mac_stats.ul.current_rbs = sched_pusch->rbSize; + nr_mac->mac_stats.ul.used_prb_aggregate += sched_pusch->rbSize; sched_ctrl->last_ul_frame = sched_pusch->frame; sched_ctrl->last_ul_slot = sched_pusch->slot; @@ -2697,6 +2698,7 @@ static void nr_ulsch_preprocessor(gNB_MAC_INST *nr_mac, post_process_pusch_t *pp int tda = seq_arr_dist(&nr_mac->ul_tda, seq_arr_front(&nr_mac->ul_tda), tda_info); AssertFatal(tda >= 0 && tda < 16, "illegal TDA index %d\n", tda); + nr_mac->mac_stats.ul.total_prb_aggregate += bw; int len[num_beams]; for (int i = 0; i < num_beams; i++) len[i] = rb_len; diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h index cfe02755b2..29398c9edf 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h +++ b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h @@ -65,16 +65,9 @@ void nr_mac_prepare_ra_ue(gNB_MAC_INST *nrmac, NR_UE_info_t *UE); bool add_new_UE_RA(gNB_MAC_INST *nr_mac, NR_UE_info_t *UE); int nr_mac_get_reconfig_delay_slots(NR_SubcarrierSpacing_t scs); -int nr_mac_interrupt_ue_transmission(gNB_MAC_INST *mac, NR_UE_info_t *UE, int slots); int nr_transmission_action_indicator_stop(gNB_MAC_INST *mac, NR_UE_info_t *UE_info); -void clear_nr_nfapi_information(gNB_MAC_INST *gNB, - int CC_idP, - frame_t frameP, - slot_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 clear_nr_nfapi_information(gNB_MAC_INST *gNB, int CC_idP, frame_t frameP, slot_t slotP); void nr_mac_update_timers(module_id_t module_id, frame_t frame, slot_t slot); diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c index 064857a8e3..cf0f2286bc 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c +++ b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c @@ -329,7 +329,7 @@ static int handle_ue_context_drbs_setup(NR_UE_info_t *UE, *rlc_BearerConfig->rlc_Config->choice.am->dl_AM_RLC.sn_FieldLength = NR_SN_FieldLengthAM_size12; *rlc_BearerConfig->rlc_Config->choice.am->ul_AM_RLC.sn_FieldLength = NR_SN_FieldLengthAM_size12; } - + AssertFatal(rlc_BearerConfig->rlc_Config, "We expect rlc-Config to be always present when we configure a DRB\n"); nr_rlc_add_drb(UE->rnti, drb->id, rlc_BearerConfig); nr_lc_config_t c = {.lcid = rlc_BearerConfig->logicalChannelIdentity, .nssai = drb->nr.nssai}; @@ -381,12 +381,9 @@ static int handle_ue_context_drbs_release(NR_UE_info_t *UE, { DevAssert(req_drbs != NULL && cellGroupConfig != NULL); instance_t f1inst = get_f1_gtp_instance(); - cellGroupConfig->rlc_BearerToReleaseList = calloc(1, sizeof(*cellGroupConfig->rlc_BearerToReleaseList)); AssertFatal(cellGroupConfig->rlc_BearerToReleaseList != NULL, "out of memory\n"); - /* Note: the actual GTP tunnels are already removed in the F1AP message - * decoding */ for (int i = 0; i < drbs_len; i++) { const f1ap_drb_to_release_t *drb = &req_drbs[i]; @@ -401,7 +398,7 @@ static int handle_ue_context_drbs_release(NR_UE_info_t *UE, if (idx < cellGroupConfig->rlc_BearerToAddModList->list.count) { nr_mac_remove_lcid(&UE->UE_sched_ctrl, lcid); nr_rlc_release_entity(UE->rnti, lcid); - if (f1inst >= 0) + if (f1inst >= 0) /* Delete F1 tunnel */ newGtpuDeleteOneTunnel(f1inst, UE->rnti, drb->id); asn_sequence_del(&cellGroupConfig->rlc_BearerToAddModList->list, idx, 1); long *plcid = malloc(sizeof(*plcid)); @@ -980,8 +977,15 @@ void dl_rrc_message_transfer(const f1ap_dl_rrc_message_t *dl_rrc) pthread_mutex_unlock(&mac->sched_lock); nr_rlc_remove_ue(dl_rrc->gNB_DU_ue_id); nr_rlc_update_id(*dl_rrc->old_gNB_DU_ue_id, dl_rrc->gNB_DU_ue_id); - /* 38.331 clause 5.3.7.4: apply the specified configuration defined in 9.2.1 for SRB1 */ - nr_rlc_reconfigure_entity(dl_rrc->gNB_DU_ue_id, 1, NULL); + /* 38.331 clause 5.3.7.4: apply gNB RLC configuration for SRB1 to match the UE RLC configuration defined in 9.2.1 */ + nr_rlc_configuration_t rlc_configuration = mac->rlc_config; // use configuration file values for timers t_poll_retransmit, t_reassembly and t_status_prohibit + rlc_configuration.srb.poll_pdu = -1; + rlc_configuration.srb.poll_byte = -1; + rlc_configuration.srb.max_retx_threshold = 8; + rlc_configuration.srb.sn_field_length = 12; + NR_RLC_Config_t *rlc_Config = nr_srb_config(&rlc_configuration); + nr_rlc_reconfigure_entity(dl_rrc->gNB_DU_ue_id, 1, rlc_Config); + ASN_STRUCT_FREE(asn_DEF_NR_RLC_Config, rlc_Config); instance_t f1inst = get_f1_gtp_instance(); if (f1inst >= 0) // we actually use F1-U gtpv1u_update_ue_id(f1inst, *dl_rrc->old_gNB_DU_ue_id, dl_rrc->gNB_DU_ue_id); diff --git a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h index d6a9ae1497..aa8b2b8644 100644 --- a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h +++ b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h @@ -870,6 +870,11 @@ typedef struct { uint64_t used_prb_aggregate; } mac_stats_t; +typedef struct dlul_mac_stats { + mac_stats_t dl; + mac_stats_t ul; +} dlul_mac_stats_t; + /// helper type to encapsulate a frame/slot combination in a single type. /// Currently only used in the UL preprocessor. Note: if you use this type /// further, please refactor it into a common type first. @@ -996,7 +1001,7 @@ typedef struct gNB_MAC_INST_s { pthread_mutex_t sched_lock; - mac_stats_t mac_stats; + dlul_mac_stats_t mac_stats; uint64_t num_scheduled_prach_rx; } gNB_MAC_INST; diff --git a/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c b/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c index 99bf846d4d..dff2f2b663 100644 --- a/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c +++ b/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c @@ -3538,6 +3538,24 @@ static NR_SpCellConfig_t *get_initial_SpCellConfig(int uid, return SpCellConfig; } +struct NR_RLC_Config *nr_srb_config(const nr_rlc_configuration_t *default_rlc_config) +{ + NR_RLC_Config_t *rlc_Config = calloc(1, sizeof(NR_RLC_Config_t)); + rlc_Config->present = NR_RLC_Config_PR_am; + rlc_Config->choice.am = calloc(1, sizeof(*rlc_Config->choice.am)); + rlc_Config->choice.am->dl_AM_RLC.sn_FieldLength = calloc(1, sizeof(NR_SN_FieldLengthAM_t)); + *(rlc_Config->choice.am->dl_AM_RLC.sn_FieldLength) = encode_sn_field_length_am(default_rlc_config->srb.sn_field_length); + rlc_Config->choice.am->dl_AM_RLC.t_Reassembly = encode_t_reassembly(default_rlc_config->srb.t_reassembly); + rlc_Config->choice.am->dl_AM_RLC.t_StatusProhibit = encode_t_status_prohibit(default_rlc_config->srb.t_status_prohibit); + rlc_Config->choice.am->ul_AM_RLC.sn_FieldLength = calloc(1, sizeof(NR_SN_FieldLengthAM_t)); + *(rlc_Config->choice.am->ul_AM_RLC.sn_FieldLength) = encode_sn_field_length_am(default_rlc_config->srb.sn_field_length); + rlc_Config->choice.am->ul_AM_RLC.t_PollRetransmit = encode_t_poll_retransmit(default_rlc_config->srb.t_poll_retransmit); + rlc_Config->choice.am->ul_AM_RLC.pollPDU = encode_poll_pdu(default_rlc_config->srb.poll_pdu); + rlc_Config->choice.am->ul_AM_RLC.pollByte = encode_poll_byte(default_rlc_config->srb.poll_byte); + rlc_Config->choice.am->ul_AM_RLC.maxRetxThreshold = encode_max_retx_threshold(default_rlc_config->srb.max_retx_threshold); + return rlc_Config; +} + NR_RLC_BearerConfig_t *get_SRB_RLC_BearerConfig(long channelId, long priority, long bucketSizeDuration, @@ -3551,20 +3569,7 @@ NR_RLC_BearerConfig_t *get_SRB_RLC_BearerConfig(long channelId, rlc_BearerConfig->servedRadioBearer->choice.srb_Identity = channelId; rlc_BearerConfig->reestablishRLC = NULL; - NR_RLC_Config_t *rlc_Config = calloc(1, sizeof(NR_RLC_Config_t)); - rlc_Config->present = NR_RLC_Config_PR_am; - rlc_Config->choice.am = calloc(1, sizeof(*rlc_Config->choice.am)); - rlc_Config->choice.am->dl_AM_RLC.sn_FieldLength = calloc(1, sizeof(NR_SN_FieldLengthAM_t)); - *(rlc_Config->choice.am->dl_AM_RLC.sn_FieldLength) = encode_sn_field_length_am(default_rlc_config->srb.sn_field_length); - rlc_Config->choice.am->dl_AM_RLC.t_Reassembly = encode_t_reassembly(default_rlc_config->srb.t_reassembly); - rlc_Config->choice.am->dl_AM_RLC.t_StatusProhibit = encode_t_status_prohibit(default_rlc_config->srb.t_status_prohibit); - rlc_Config->choice.am->ul_AM_RLC.sn_FieldLength = calloc(1, sizeof(NR_SN_FieldLengthAM_t)); - *(rlc_Config->choice.am->ul_AM_RLC.sn_FieldLength) = encode_sn_field_length_am(default_rlc_config->srb.sn_field_length); - rlc_Config->choice.am->ul_AM_RLC.t_PollRetransmit = encode_t_poll_retransmit(default_rlc_config->srb.t_poll_retransmit); - rlc_Config->choice.am->ul_AM_RLC.pollPDU = encode_poll_pdu(default_rlc_config->srb.poll_pdu); - rlc_Config->choice.am->ul_AM_RLC.pollByte = encode_poll_byte(default_rlc_config->srb.poll_byte); - rlc_Config->choice.am->ul_AM_RLC.maxRetxThreshold = encode_max_retx_threshold(default_rlc_config->srb.max_retx_threshold); - rlc_BearerConfig->rlc_Config = rlc_Config; + rlc_BearerConfig->rlc_Config = nr_srb_config(default_rlc_config); NR_LogicalChannelConfig_t *logicalChannelConfig = calloc(1, sizeof(NR_LogicalChannelConfig_t)); logicalChannelConfig->ul_SpecificParameters = calloc(1, sizeof(*logicalChannelConfig->ul_SpecificParameters)); @@ -3584,10 +3589,9 @@ NR_RLC_BearerConfig_t *get_SRB_RLC_BearerConfig(long channelId, return rlc_BearerConfig; } -static void nr_drb_config(struct NR_RLC_Config *rlc_Config, - NR_RLC_Config_PR rlc_config_pr, - const nr_rlc_configuration_t *default_rlc_config) +struct NR_RLC_Config *nr_drb_config(NR_RLC_Config_PR rlc_config_pr, const nr_rlc_configuration_t *default_rlc_config) { + NR_RLC_Config_t *rlc_Config = calloc(1, sizeof(NR_RLC_Config_t)); switch (rlc_config_pr) { case NR_RLC_Config_PR_um_Bi_Directional: // RLC UM Bi-directional Bearer configuration @@ -3620,6 +3624,7 @@ static void nr_drb_config(struct NR_RLC_Config *rlc_Config, break; } rlc_Config->present = rlc_config_pr; + return rlc_Config; } NR_RLC_BearerConfig_t *get_DRB_RLC_BearerConfig(long lcChannelId, @@ -3635,9 +3640,7 @@ NR_RLC_BearerConfig_t *get_DRB_RLC_BearerConfig(long lcChannelId, rlc_BearerConfig->servedRadioBearer->choice.drb_Identity = drbId; rlc_BearerConfig->reestablishRLC = NULL; - NR_RLC_Config_t *rlc_Config = calloc(1, sizeof(NR_RLC_Config_t)); - nr_drb_config(rlc_Config, rlc_conf, default_rlc_config); - rlc_BearerConfig->rlc_Config = rlc_Config; + rlc_BearerConfig->rlc_Config = nr_drb_config(rlc_conf, default_rlc_config); NR_LogicalChannelConfig_t *logicalChannelConfig = calloc(1, sizeof(NR_LogicalChannelConfig_t)); logicalChannelConfig->ul_SpecificParameters = calloc(1, sizeof(*logicalChannelConfig->ul_SpecificParameters)); diff --git a/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.h b/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.h index 89ce03e7f5..466f18c0de 100644 --- a/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.h +++ b/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.h @@ -112,6 +112,9 @@ NR_CellGroupConfig_t *get_default_secondaryCellGroup(const NR_ServingCellConfigC NR_ReconfigurationWithSync_t *get_reconfiguration_with_sync(rnti_t rnti, uid_t uid, const NR_ServingCellConfigCommon_t *scc, int frame); +struct NR_RLC_Config *nr_srb_config(const nr_rlc_configuration_t *default_rlc_config); +struct NR_RLC_Config *nr_drb_config(NR_RLC_Config_PR rlc_config_pr, const nr_rlc_configuration_t *default_rlc_config); + NR_RLC_BearerConfig_t *get_SRB_RLC_BearerConfig(long channelId, long priority, long bucketSizeDuration, diff --git a/openair2/LAYER2/nr_pdcp/cucp_cuup_handler.c b/openair2/LAYER2/nr_pdcp/cucp_cuup_handler.c index 4b95963257..ecdf3dfd72 100644 --- a/openair2/LAYER2/nr_pdcp/cucp_cuup_handler.c +++ b/openair2/LAYER2/nr_pdcp/cucp_cuup_handler.c @@ -259,17 +259,58 @@ void e1_bearer_context_setup(const e1ap_bearer_setup_req_t *req) get_e1_if()->bearer_setup_response(&resp); } +static void release_gtpu_tunnel(uint32_t ue_id, int pdusession_id) +{ + instance_t n3inst = get_n3_gtp_instance(); + + // Handle N3 tunnel (1 tunnel per PDU session) + if (n3inst >= 0) { + LOG_I(E1AP, "UE %u: Deleting N3 tunnel for PDU session %d\n", ue_id, pdusession_id); + int result = newGtpuDeleteOneTunnel(n3inst, ue_id, pdusession_id); + if (result == GTPNOK) { + LOG_E(E1AP, "UE %u: Failed to delete N3 tunnel for PDU session %d\n", ue_id, pdusession_id); + } + } +} + +static void release_f1_drbs(uint32_t ue_id, int pdusession_id) +{ + instance_t f1inst = get_f1_gtp_instance(); + // Handle F1 tunnels (1 tunnel per DRB, fetch PDCP entities and get DRB IDs) + int drb_ids[MAX_DRBS_PER_UE]; + int n_drbs = nr_pdcp_get_drb_ids_for_pdusession(ue_id, pdusession_id, drb_ids); + if (n_drbs > 0) { + LOG_I(E1AP, "UE %u: Deleting %d F1 tunnels for PDU session %d\n", ue_id, n_drbs, pdusession_id); + // Delete each F1 tunnel using the DRB IDs + for (int i = 0; i < n_drbs; i++) { + int drb_id = drb_ids[i]; + if (f1inst >= 0) { + int result = newGtpuDeleteOneTunnel(f1inst, ue_id, drb_id); + if (result == GTPNOK) { + LOG_E(E1AP, "UE %u: Failed to delete F1 tunnel for DRB %d\n", ue_id, drb_id); + } + } + // Release PDCP entity + nr_pdcp_release_drb(ue_id, drb_id); + } + } else { + LOG_W(E1AP, "UE %u: No DRBs found for PDU session %d\n", ue_id, pdusession_id); + } +} + /** * @brief Fill Bearer Context Modification Response and send to callback */ void e1_bearer_context_modif(const e1ap_bearer_mod_req_t *req) { - AssertFatal(req->numPDUSessionsMod > 0, "need at least one PDU session to modify\n"); + AssertFatal(req->numPDUSessionsMod > 0 || req->numPDUSessionsRem > 0, + "need at least one PDU session to modify or release (mod=%u, rel=%u)\n", + req->numPDUSessionsMod, + req->numPDUSessionsRem); e1ap_bearer_modif_resp_t modif = { .gNB_cu_cp_ue_id = req->gNB_cu_cp_ue_id, .gNB_cu_up_ue_id = req->gNB_cu_up_ue_id, - .numPDUSessionsMod = req->numPDUSessionsMod, }; instance_t f1inst = get_f1_gtp_instance(); @@ -284,6 +325,7 @@ void e1_bearer_context_modif(const e1ap_bearer_mod_req_t *req) req->pduSessionMod[i].numDRB2Modify); modif.pduSessionMod[i].id = req->pduSessionMod[i].sessionId; modif.pduSessionMod[i].numDRBModified = req->pduSessionMod[i].numDRB2Modify; + modif.numPDUSessionsMod++; /* DRBs to modify */ for (int j = 0; j < req->pduSessionMod[i].numDRB2Modify; j++) { const DRB_nGRAN_to_mod_t *to_modif = &req->pduSessionMod[i].DRBnGRanModList[j]; @@ -347,6 +389,15 @@ void e1_bearer_context_modif(const e1ap_bearer_mod_req_t *req) } } + /* PDU Session Resource To Remove List (see 9.3.3.12 of TS 38.463) */ + for (int i = 0; i < req->numPDUSessionsRem; i++) { + modif.pduSessionMod[i].id = req->pduSessionRem[i].sessionId; + modif.numPDUSessionsMod++; + release_gtpu_tunnel(req->gNB_cu_up_ue_id, req->pduSessionRem[i].sessionId); + release_f1_drbs(req->gNB_cu_up_ue_id, req->pduSessionRem[i].sessionId); + nr_sdap_delete_entity(req->gNB_cu_up_ue_id, req->pduSessionRem[i].sessionId); + } + get_e1_if()->bearer_modif_response(&modif); } diff --git a/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.c b/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.c index 94d44fe8ce..3fd4c4bdd4 100644 --- a/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.c +++ b/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.c @@ -653,6 +653,30 @@ void nr_pdcp_add_srbs(eNB_flag_t enb_flag, LOG_W(PDCP, "nr_pdcp_add_srbs() with void list\n"); } +/** @brief Get DRB IDs for a specific PDU session */ +int nr_pdcp_get_drb_ids_for_pdusession(ue_id_t ue_id, long pdusession_id, int *drb_ids) +{ + int num_found = 0; + nr_pdcp_manager_lock(nr_pdcp_ue_manager); + nr_pdcp_ue_t *ue = nr_pdcp_manager_get_ue(nr_pdcp_ue_manager, ue_id); + if (ue) { + for (int i = 0; i < MAX_DRBS_PER_UE; i++) { + nr_pdcp_entity_t *drb = ue->drb[i]; + if (drb && drb->pdusession_id == pdusession_id) { + if (num_found < MAX_DRBS_PER_UE) { + drb_ids[num_found] = drb->rb_id; + num_found++; + } else { + LOG_W(PDCP, "Found more DRBs than MAX_DRBS_PER_UE=%d\n", MAX_DRBS_PER_UE); + break; + } + } + } + } + nr_pdcp_manager_unlock(nr_pdcp_ue_manager); + return num_found; +} + uint64_t get_pdcp_optmask(void) { return pdcp_optmask; diff --git a/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.h b/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.h index 884ea11f60..75435ed695 100644 --- a/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.h +++ b/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.h @@ -66,6 +66,7 @@ void nr_pdcp_reconfigure_srb(ue_id_t ue_id, int srb_id, long t_Reordering); void nr_pdcp_reconfigure_drb(ue_id_t ue_id, int drb_id, NR_PDCP_Config_t *pdcp_config); void nr_pdcp_release_srb(ue_id_t ue_id, int srb_id); void nr_pdcp_release_drb(ue_id_t ue_id, int drb_id); +int nr_pdcp_get_drb_ids_for_pdusession(ue_id_t ue_id, long pdusession_id, int *drb_ids); void add_srb(int is_gnb, ue_id_t UEid, diff --git a/openair2/LAYER2/nr_pdcp/nr_pdcp_ue_manager.c b/openair2/LAYER2/nr_pdcp/nr_pdcp_ue_manager.c index 07edfb5814..f4dc5c1d5d 100644 --- a/openair2/LAYER2/nr_pdcp/nr_pdcp_ue_manager.c +++ b/openair2/LAYER2/nr_pdcp/nr_pdcp_ue_manager.c @@ -178,7 +178,7 @@ void nr_pdcp_ue_add_srb_pdcp_entity(nr_pdcp_ue_t *ue, int srb_id, nr_pdcp_entity /* must be called with lock acquired */ void nr_pdcp_ue_add_drb_pdcp_entity(nr_pdcp_ue_t *ue, int drb_id, nr_pdcp_entity_t *entity) { - if (drb_id < 1 || drb_id > 5) { + if (drb_id < 1 || drb_id > MAX_DRBS_PER_UE) { LOG_E(PDCP, "%s:%d:%s: fatal, bad drb id\n", __FILE__, __LINE__, __FUNCTION__); exit(1); } diff --git a/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.c b/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.c index e187541fd5..126f9fb51c 100644 --- a/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.c +++ b/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.c @@ -672,7 +672,7 @@ void nr_rlc_reconfigure_entity(int ue_id, int lc_id, NR_RLC_Config_t *rlc_Config void nr_rlc_add_srb(int ue_id, int srb_id, const NR_RLC_BearerConfig_t *rlc_BearerConfig) { - struct NR_RLC_Config *r = rlc_BearerConfig->rlc_Config; + NR_RLC_Config_t *r = rlc_BearerConfig->rlc_Config; int t_status_prohibit; int t_poll_retransmit; int poll_pdu; @@ -682,8 +682,7 @@ void nr_rlc_add_srb(int ue_id, int srb_id, const NR_RLC_BearerConfig_t *rlc_Bear int sn_field_length; LOG_D(RLC, "Trying to add SRB %d\n", srb_id); - AssertFatal(srb_id > 0 && srb_id < 4, - "Invalid srb id %d\n", srb_id); + AssertFatal(srb_id > 0 && srb_id < 4, "Invalid srb id %d\n", srb_id); if (r && r->present == NR_RLC_Config_PR_am) { struct NR_RLC_Config__am *am; diff --git a/openair2/NR_PHY_INTERFACE/NR_IF_Module.c b/openair2/NR_PHY_INTERFACE/NR_IF_Module.c index 2352870ace..18944a8099 100644 --- a/openair2/NR_PHY_INTERFACE/NR_IF_Module.c +++ b/openair2/NR_PHY_INTERFACE/NR_IF_Module.c @@ -41,7 +41,6 @@ #include "nfapi/oai_integration/gnb_ind_vars.h" #include "nfapi/oai_integration/vendor_ext.h" #include "nfapi_interface.h" -#include "openair2/NR_PHY_INTERFACE/nr_sched_response.h" #include "openair2/PHY_INTERFACE/queue_t.h" #include "utils.h" #include "nfapi/oai_integration/nfapi_pnf.h" @@ -379,52 +378,25 @@ static void match_crc_rx_pdu(nfapi_nr_rx_data_indication_t *rx_ind, nfapi_nr_crc } } -extern void handle_nr_slot_ind(uint16_t sfn, uint16_t slot); -static void pnf_send_slot_ind(module_id_t module_id, int CC_id, int frame, int slot) +extern void handle_nr_slot_ind(uint16_t sfn, uint16_t slot, NR_Sched_Rsp_t *sched_response); +static void pnf_send_slot_ind(const nfapi_nr_slot_indication_scf_t *ind, NR_Sched_Rsp_t *rsp) { - (void)module_id; - (void)CC_id; - handle_nr_slot_ind(frame, slot); + module_id_t module_id = 0; + int CC_id = 0; + reset_sched_response(rsp, ind->sfn, ind->slot, module_id, CC_id); + handle_nr_slot_ind(ind->sfn, ind->slot, rsp); } -static void run_scheduler_monolithic(module_id_t module_id, int CC_id, int frame, int slot) +static void run_scheduler_monolithic(const nfapi_nr_slot_indication_scf_t *ind, NR_Sched_Rsp_t *rsp) { - NR_IF_Module_t *ifi = nr_if_inst[module_id]; - - LOG_D(NR_MAC, "Calling scheduler for %d.%d\n", frame, slot); - NR_Sched_Rsp_t *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, frame, slot, sched_info); - ifi->CC_mask = 0; - sched_info->module_id = module_id; - sched_info->CC_id = CC_id; - sched_info->frame = frame; - sched_info->slot = slot; - /* - 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 - - AssertFatal(ifi->NR_Schedule_response != NULL, "nr_schedule_response is null (mod %d, cc %d)\n", module_id, 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); + module_id_t module_id = 0; + int CC_id = 0; + reset_sched_response(rsp, ind->sfn, ind->slot, module_id, CC_id); + gNB_dlsch_ulsch_scheduler(rsp->module_id, ind->sfn, ind->slot, rsp); } -void NR_UL_indication(NR_UL_IND_t *UL_info) { +static 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; @@ -501,17 +473,47 @@ NR_IF_Module_t *NR_IF_Module_init(int Mod_id) { nr_if_inst[Mod_id]->CC_mask=0; nr_if_inst[Mod_id]->NR_UL_indication = NR_UL_indication; - if (NFAPI_MODE == NFAPI_MONOLITHIC) + if (NFAPI_MODE == NFAPI_MONOLITHIC) { nr_if_inst[Mod_id]->NR_slot_indication = run_scheduler_monolithic; - else if (NFAPI_MODE == NFAPI_MODE_PNF) + } else if (NFAPI_MODE == NFAPI_MODE_PNF) { nr_if_inst[Mod_id]->NR_slot_indication = pnf_send_slot_ind; - else // NFAPI_MODE_VNF - NULL; + } else { // NFAPI_MODE_VNF + DevAssert(NFAPI_MODE == NFAPI_MODE_VNF || NFAPI_MODE == NFAPI_MODE_AERIAL); + nr_if_inst[Mod_id]->NR_slot_indication = run_scheduler_monolithic; + } AssertFatal(pthread_mutex_init(&nr_if_inst[Mod_id]->if_mutex,NULL)==0, "allocation of nr_if_inst[%d]->if_mutex fails\n",Mod_id); } - init_sched_response(); - return nr_if_inst[Mod_id]; } + +void reset_sched_response(NR_Sched_Rsp_t *sched_response, int frame, int slot, int module_id, int CC_id) +{ + sched_response->module_id = module_id; + sched_response->CC_id = CC_id; + sched_response->frame = frame; + sched_response->slot = slot; + + + nfapi_nr_dl_tti_request_t *DL_req = &sched_response->DL_req; + DL_req->SFN = frame; + DL_req->Slot = slot; + DL_req->dl_tti_request_body.nPDUs = 0; + DL_req->dl_tti_request_body.nGroup = 0; + + nfapi_nr_ul_dci_request_t *UL_dci_req = &sched_response->UL_dci_req; + UL_dci_req->SFN = frame; + UL_dci_req->Slot = slot; + UL_dci_req->numPdus = 0; + + nfapi_nr_ul_tti_request_t *UL_tti_req = &sched_response->UL_tti_req; + UL_tti_req->SFN = frame; + UL_tti_req->Slot = slot; + UL_tti_req->n_pdus = 0; + + nfapi_nr_tx_data_request_t *TX_req = &sched_response->TX_req; + TX_req->SFN = frame; + TX_req->Slot = slot; + TX_req->Number_of_PDUs = 0; +} diff --git a/openair2/NR_PHY_INTERFACE/NR_IF_Module.h b/openair2/NR_PHY_INTERFACE/NR_IF_Module.h index 52a0f28871..49219a0af1 100644 --- a/openair2/NR_PHY_INTERFACE/NR_IF_Module.h +++ b/openair2/NR_PHY_INTERFACE/NR_IF_Module.h @@ -91,7 +91,7 @@ typedef struct { // Downlink slot P7 -typedef struct { +typedef struct NR_Sched_Rsp { /// the ID of this sched_response - used by sched_reponse memory management int sched_response_id; /// Module ID @@ -111,6 +111,7 @@ typedef struct { /// Pointers to DL SDUs nfapi_nr_tx_data_request_t TX_req; } NR_Sched_Rsp_t; +void reset_sched_response(NR_Sched_Rsp_t *sched_response, int frame, int slot, int module_id, int CC_id); typedef struct { uint8_t Mod_id; @@ -121,8 +122,7 @@ typedef struct { typedef struct NR_IF_Module_s { //define the function pointer void (*NR_UL_indication)(NR_UL_IND_t *UL_INFO); - void (*NR_Schedule_response)(NR_Sched_Rsp_t *Sched_INFO); - void (*NR_slot_indication)(module_id_t module_idP, int CC_id, int frame, int slot); + void (*NR_slot_indication)(const nfapi_nr_slot_indication_scf_t *ind, NR_Sched_Rsp_t *rsp); void (*NR_PHY_config_req)(NR_PHY_Config_t *config_INFO); uint32_t CC_mask; uint16_t current_frame; @@ -136,9 +136,4 @@ NR_IF_Module_t *NR_IF_Module_init(int Mod_id); void NR_IF_Module_kill(int Mod_id); -void NR_UL_indication(NR_UL_IND_t *UL_INFO); - -/*Interface for Downlink, transmitting the DLSCH SDU, DCI SDU*/ -void NR_Schedule_Response(NR_Sched_Rsp_t *Sched_INFO); - #endif /*_NFAPI_INTERFACE_NR_H_*/ diff --git a/openair2/NR_PHY_INTERFACE/nr_sched_response.c b/openair2/NR_PHY_INTERFACE/nr_sched_response.c deleted file mode 100644 index 9c66b21536..0000000000 --- a/openair2/NR_PHY_INTERFACE/nr_sched_response.c +++ /dev/null @@ -1,157 +0,0 @@ -/* - * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The OpenAirInterface Software Alliance licenses this file to You under - * the OAI Public License, Version 1.1 (the "License"); you may not use this file - * except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.openairinterface.org/?page_id=698 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - *------------------------------------------------------------------------------- - * For more information about the OpenAirInterface (OAI) Software Alliance: - * contact@openairinterface.org - */ - -/* 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 -#include "NR_PHY_INTERFACE/NR_IF_Module.h" -#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) -{ - LOG_D(NR_MAC,"Releasing sched_response %d\n",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"); - - LOG_D(NR_MAC,"resp_refcount[%d] %d\n",sched_response_id,resp_refcount[sched_response_id]); - 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; - - LOG_D(NR_MAC,"Incrementing sched_resp resp_refounct[%d] = %d\n", - sched_response_id,resp_refcount[sched_response_id]); - 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 deleted file mode 100644 index 33a0af93d0..0000000000 --- a/openair2/NR_PHY_INTERFACE/nr_sched_response.h +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The OpenAirInterface Software Alliance licenses this file to You under - * the OAI Public License, Version 1.1 (the "License"); you may not use this file - * except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.openairinterface.org/?page_id=698 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - *------------------------------------------------------------------------------- - * For more information about the OpenAirInterface (OAI) Software Alliance: - * contact@openairinterface.org - */ - -#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/RRC/NR/MESSAGES/asn1_msg.c b/openair2/RRC/NR/MESSAGES/asn1_msg.c index 2136e966ab..585b1e48e2 100644 --- a/openair2/RRC/NR/MESSAGES/asn1_msg.c +++ b/openair2/RRC/NR/MESSAGES/asn1_msg.c @@ -519,7 +519,13 @@ static NR_RRCReconfiguration_IEs_t *build_RRCReconfiguration_IEs(const nr_rrc_re cfg->drb_ToAddModList = params->drb_config_list; cfg->securityConfig = params->security_config; cfg->srb3_ToRelease = NULL; - cfg->drb_ToReleaseList = params->drb_release_list; + if (params->n_drb_rel) { + asn1cCalloc(cfg->drb_ToReleaseList, to_release); + for (int i = 0; i < params->n_drb_rel; i++) { + asn1cSequenceAdd(to_release->list, NR_DRB_Identity_t, DRB_release); + *DRB_release = params->drb_rel[i]; + } + } } /* measConfig */ diff --git a/openair2/RRC/NR/MESSAGES/asn1_msg.h b/openair2/RRC/NR/MESSAGES/asn1_msg.h index 48a0ea734b..eb8da91c2a 100644 --- a/openair2/RRC/NR/MESSAGES/asn1_msg.h +++ b/openair2/RRC/NR/MESSAGES/asn1_msg.h @@ -64,7 +64,8 @@ typedef struct { uint8_t transaction_id; NR_SRB_ToAddModList_t *srb_config_list; NR_DRB_ToAddModList_t *drb_config_list; - NR_DRB_ToReleaseList_t *drb_release_list; + int *drb_rel; + int n_drb_rel; NR_SecurityConfig_t *security_config; NR_MeasConfig_t *meas_config; byte_array_t dedicated_NAS_msg_list[MAX_DRBS_PER_UE]; diff --git a/openair2/RRC/NR/MESSAGES/tests/test_asn1_msg.cpp b/openair2/RRC/NR/MESSAGES/tests/test_asn1_msg.cpp index 1f92c5aae5..025978218e 100644 --- a/openair2/RRC/NR/MESSAGES/tests/test_asn1_msg.cpp +++ b/openair2/RRC/NR/MESSAGES/tests/test_asn1_msg.cpp @@ -88,7 +88,6 @@ TEST(nr_asn1, paging) void free_RRCReconfiguration_params(nr_rrc_reconfig_param_t params) { ASN_STRUCT_FREE(asn_DEF_NR_MeasConfig, params.meas_config); - ASN_STRUCT_FREE(asn_DEF_NR_DRB_ToReleaseList, params.drb_release_list); ASN_STRUCT_FREE(asn_DEF_NR_DRB_ToAddModList, params.drb_config_list); ASN_STRUCT_FREE(asn_DEF_NR_SRB_ToAddModList, params.srb_config_list); ASN_STRUCT_FREE(asn_DEF_NR_SecurityConfig, params.security_config); diff --git a/openair2/RRC/NR/nr_rrc_defs.h b/openair2/RRC/NR/nr_rrc_defs.h index 27e17e03f0..4d24a771c0 100644 --- a/openair2/RRC/NR/nr_rrc_defs.h +++ b/openair2/RRC/NR/nr_rrc_defs.h @@ -97,7 +97,6 @@ typedef enum pdu_session_satus_e { PDU_SESSION_STATUS_TOMODIFY, // ENDC NSA PDU_SESSION_STATUS_FAILED, PDU_SESSION_STATUS_TORELEASE, // to release DRB between eNB and UE - PDU_SESSION_STATUS_RELEASED } pdu_session_status_t; typedef struct pdusession_s { @@ -149,6 +148,12 @@ typedef enum { RRC_UECAPABILITY_ENQUIRY, } rrc_action_t; +/* Small state for delaying NG-triggered actions (setup/release) */ +typedef struct { + int max_delays; + bool ongoing_transaction; +} delayed_action_state_t; + typedef struct nr_redcap_ue_cap { bool support_of_redcap_r17; bool support_of_16drb_redcap_r17; @@ -167,8 +172,6 @@ typedef struct nr_handover_context_s nr_handover_context_t; typedef struct gNB_RRC_UE_s { time_t last_seen; // last time this UE has been accessed - NR_DRB_ToReleaseList_t *DRB_ReleaseList; - NR_SRB_INFO_TABLE_ENTRY Srb[NR_NUM_SRB]; NR_MeasConfig_t *measConfig; nr_handover_context_t *ho_context; @@ -244,8 +247,7 @@ typedef struct gNB_RRC_UE_s { byte_array_t nas_pdu; /* hack, see rrc_gNB_process_NGAP_PDUSESSION_SETUP_REQ() for more info */ - int max_delays_pdu_session; - bool ongoing_pdusession_setup_request; + delayed_action_state_t delayed_action; nr_redcap_ue_cap_t *redcap_cap; } gNB_RRC_UE_t; diff --git a/openair2/RRC/NR/nr_rrc_proto.h b/openair2/RRC/NR/nr_rrc_proto.h index 777ea9a8d1..a36a0778c6 100644 --- a/openair2/RRC/NR/nr_rrc_proto.h +++ b/openair2/RRC/NR/nr_rrc_proto.h @@ -66,12 +66,6 @@ void *rrc_gnb_task(void *args_p); int nr_rrc_reconfiguration_req(gNB_RRC_INST *rrc, gNB_RRC_UE_t *ue_p, const int dl_bwp_id, const int ul_bwp_id); -void rrc_gNB_generate_dedicatedRRCReconfiguration_release(gNB_RRC_INST *rrc, - gNB_RRC_UE_t *ue_p, - uint8_t xid, - uint32_t nas_length, - uint8_t *nas_buffer); - NR_MeasConfig_t *nr_rrc_get_measconfig(const gNB_RRC_INST *rrc, uint64_t nr_cellid); bool ue_associated_to_cuup(const gNB_RRC_INST *rrc, const gNB_RRC_UE_t *ue); @@ -128,5 +122,6 @@ NR_SRB_ToAddModList_t *createSRBlist(gNB_RRC_UE_t *ue, uint8_t reestablish); NR_DRB_ToAddModList_t *createDRBlist(gNB_RRC_UE_t *ue, bool reestablish, bool do_integrity, bool do_ciphering); void activate_srb(gNB_RRC_UE_t *UE, int srb_id); void e1_notify_pdcp_status(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, const ngap_drb_status_t *drb_status); +void init_delayed_action(delayed_action_state_t *delayed_action); #endif diff --git a/openair2/RRC/NR/rrc_gNB.c b/openair2/RRC/NR/rrc_gNB.c index dcc17ec2c0..b18e820e91 100644 --- a/openair2/RRC/NR/rrc_gNB.c +++ b/openair2/RRC/NR/rrc_gNB.c @@ -115,6 +115,97 @@ mui_t rrc_gNB_mui = 0; +/* Per-transaction max_delays counter to limit retry attempts */ +#define MAX_DELAYS 100 + +/** @brief clone and re-enqueue an NGAP message after delaying + * delays the ongoing transaction (in msg_p) by setting a timer to wait + * 10ms; upon expiry, delivers to RRC, which sends the message to itself */ +static void delay_transaction(MessageDef *msg_p, int wait_us) +{ + MessagesIds id = ITTI_MSG_ID(msg_p); + AssertFatal(id == NGAP_PDUSESSION_SETUP_REQ || id == NGAP_PDUSESSION_RELEASE_COMMAND, + "delay_transaction(): unsupported message id %d\n", + id); + + MessageDef *new = itti_alloc_new_message(TASK_RRC_GNB, 0, id); + + // Copy only the specific message struct, not the entire union. + // The union (msg_t) contains all message types and is much larger than + // the allocated space (which is sized for the specific message type only). + if (id == NGAP_PDUSESSION_SETUP_REQ) { + NGAP_PDUSESSION_SETUP_REQ(new) = NGAP_PDUSESSION_SETUP_REQ(msg_p); + } else if (id == NGAP_PDUSESSION_RELEASE_COMMAND) { + NGAP_PDUSESSION_RELEASE_COMMAND(new) = NGAP_PDUSESSION_RELEASE_COMMAND(msg_p); + } + + int instance = msg_p->ittiMsgHeader.originInstance; + long timer_id; + timer_setup(0, wait_us, TASK_RRC_GNB, instance, TIMER_ONE_SHOT, new, &timer_id); +} + +static void reset_delayed_action(delayed_action_state_t *delayed_action) +{ + delayed_action->ongoing_transaction = false; + delayed_action->max_delays = 0; +} + +void init_delayed_action(delayed_action_state_t *delayed_action) +{ + delayed_action->ongoing_transaction = true; + delayed_action->max_delays = MAX_DELAYS; +} + +/* \brief checks if any transaction is ongoing for any xid of this UE */ +static bool transaction_ongoing(const gNB_RRC_UE_t *UE) +{ + for (int xid = 0; xid < NR_RRC_TRANSACTION_IDENTIFIER_NUMBER; ++xid) { + if (UE->xids[xid] != RRC_ACTION_NONE) + return true; + } + return false; +} + +/** @brief delay control: returns true if delayed, false if should proceed + * This is a hack. We observed that with some UEs, PDU session requests might + * come in quick succession, faster than the RRC reconfiguration for the PDU + * session requests can be carried out (UE is doing reconfig, and second PDU + * session request arrives). We don't have currently the means to "queue up" + * these transactions, which would probably involve some rework of the RRC. + * To still allow these requests to come in and succeed, we below check and delay transactions + * for 10ms. However, to not accidentally end up in infinite loops, the + * maximum number is capped on a per-UE basis as indicated in variable + * max_delays_pdu_session. See commit 277f8da0 for more details. */ +static bool rrc_delay_transaction(instance_t instance, MessageDef *msg_p) +{ + uint32_t cu_ue_id = 0; + if (ITTI_MSG_ID(msg_p) == NGAP_PDUSESSION_SETUP_REQ) { + cu_ue_id = NGAP_PDUSESSION_SETUP_REQ(msg_p).gNB_ue_ngap_id; + } else if (ITTI_MSG_ID(msg_p) == NGAP_PDUSESSION_RELEASE_COMMAND) { + cu_ue_id = NGAP_PDUSESSION_RELEASE_COMMAND(msg_p).gNB_ue_ngap_id; + } + AssertFatal(cu_ue_id > 0, "cu_ue_id not found in message %s\n", ITTI_MSG_NAME(msg_p)); + + rrc_gNB_ue_context_t *ue_context_p = rrc_gNB_get_ue_context(RC.nrrrc[instance], cu_ue_id); + DevAssert(ue_context_p); + + gNB_RRC_UE_t *UE = &ue_context_p->ue_context; + bool delay = UE->delayed_action.ongoing_transaction && UE->delayed_action.max_delays > 0; + /* Check if any PDU session action is ongoing */ + if (delay || transaction_ongoing(UE)) { + int wait_us = 10000; + LOG_I(NR_RRC, + "UE %d: ongoing transaction, delaying incoming transaction by %d us\n", + UE->rrc_ue_id, + wait_us); + delay_transaction(msg_p, wait_us); + UE->delayed_action.max_delays--; + return true; /* delayed */ + } + LOG_D(NR_RRC, "UE %d: no delayed action ongoing, proceeding with incoming transaction\n", UE->rrc_ue_id); + return false; /* not delayed */ +} + typedef struct deliver_ue_ctxt_release_data_t { gNB_RRC_INST *rrc; f1ap_ue_context_rel_cmd_t *release_cmd; @@ -366,6 +457,10 @@ NR_DRB_ToAddModList_t *createDRBlist(gNB_RRC_UE_t *ue, bool reestablish, bool do LOG_D(NR_RRC, "PDU Session %d not found, skip\n", drb->pdusession_id); continue; } + if (pduSession->status > PDU_SESSION_STATUS_TOMODIFY) { + LOG_D(NR_RRC, "PDU Session %d is not to add/mod\n", drb->pdusession_id); + continue; + } pdusession_t *session = &pduSession->param; NR_DRB_ToAddMod_t *drb_ToAddMod = calloc_or_fail(1, sizeof(*drb_ToAddMod)); drb_ToAddMod->drb_Identity = drb->drb_id; @@ -625,10 +720,10 @@ static NR_ReportConfigToAddMod_t *prepare_a3_event_report(const nr_a3_event_t *a void free_RRCReconfiguration_params(nr_rrc_reconfig_param_t params) { - ASN_STRUCT_FREE(asn_DEF_NR_DRB_ToReleaseList, params.drb_release_list); ASN_STRUCT_FREE(asn_DEF_NR_DRB_ToAddModList, params.drb_config_list); ASN_STRUCT_FREE(asn_DEF_NR_SRB_ToAddModList, params.srb_config_list); ASN_STRUCT_FREE(asn_DEF_NR_SecurityConfig, params.security_config); + free(params.drb_rel); for (int i = 0; i < params.num_nas_msg; i++) FREE_AND_ZERO_BYTE_ARRAY(params.dedicated_NAS_msg_list[i]); } @@ -706,19 +801,37 @@ nr_rrc_reconfig_param_t get_RRCReconfiguration_params(gNB_RRC_INST *rrc, gNB_RRC nr_rrc_reconfig_param_t params = {.cell_group_config = UE->masterCellGroup, .transaction_id = xid, .drb_config_list = DRBs, - .drb_release_list = UE->DRB_ReleaseList, .meas_config = UE->measConfig, .srb_config_list = SRBs}; - UE->DRB_ReleaseList = NULL; // pointer transferred to params FOR_EACH_SEQ_ARR(rrc_pdu_session_param_t *, item, &UE->pduSessions) { pdusession_t *session = &item->param; + // Collect NAS PDUs if (session->nas_pdu.len > 0) { params.dedicated_NAS_msg_list[params.num_nas_msg++] = session->nas_pdu; session->nas_pdu.buf = NULL; session->nas_pdu.len = 0; LOG_D(NR_RRC, "Transfer NAS info with size %ld to RRCReconfiguration params\n", session->nas_pdu.len); } + // Collect DRBs to release for PDU sessions marked for release + if (item->status == PDU_SESSION_STATUS_TORELEASE) { + if (!params.drb_rel) + params.drb_rel = calloc_or_fail(MAX_DRBS_PER_UE, sizeof(int)); + FOR_EACH_SEQ_ARR (drb_t *, drb, &UE->drbs) { + if (drb->pdusession_id == session->pdusession_id) { + if (params.n_drb_rel >= MAX_DRBS_PER_UE) { + LOG_E(NR_RRC, "UE %d: Too many DRBs to release (max %d)\n", UE->rrc_ue_id, MAX_DRBS_PER_UE); + break; + } + params.drb_rel[params.n_drb_rel++] = drb->drb_id; + LOG_D(NR_RRC, + "UE %d: Added DRB %d to release list for PDU session %d\n", + UE->rrc_ue_id, + drb->drb_id, + session->pdusession_id); + } + } + } } if (UE->nas_pdu.len > 0) { @@ -746,21 +859,24 @@ static void rrc_gNB_generate_dedicatedRRCReconfiguration(gNB_RRC_INST *rrc, gNB_ { /* do not re-establish PDCP for any bearer */ nr_rrc_reconfig_param_t params = get_RRCReconfiguration_params(rrc, ue_p, 0, false); - ue_p->xids[params.transaction_id] = RRC_PDUSESSION_ESTABLISH; + FOR_EACH_SEQ_ARR(rrc_pdu_session_param_t *, item, &ue_p->pduSessions) { + if (item->status == PDU_SESSION_STATUS_NEW) { + item->status = PDU_SESSION_STATUS_DONE; + continue; + } + // Set xid for all PDU sessions + item->xid = params.transaction_id; + } + + // Set xid for RRC transaction + ue_p->xids[params.transaction_id] = params.n_drb_rel > 0 ? RRC_PDUSESSION_RELEASE : RRC_PDUSESSION_ESTABLISH; + byte_array_t msg = rrc_gNB_encode_RRCReconfiguration(rrc, ue_p, params); if (msg.len <= 0) { LOG_E(NR_RRC, "UE %d: Failed to generate RRCReconfiguration\n", ue_p->rrc_ue_id); return; } - FOR_EACH_SEQ_ARR(rrc_pdu_session_param_t *, item, &ue_p->pduSessions) { - if (item->param.nas_pdu.buf) - item->xid = params.transaction_id; - if (item->status < PDU_SESSION_STATUS_ESTABLISHED) { - item->status = PDU_SESSION_STATUS_DONE; - } - } - LOG_UE_DL_EVENT(ue_p, "Generate RRCReconfiguration (bytes %ld, xid %d)\n", msg.len, params.transaction_id); const uint32_t msg_id = NR_DL_DCCH_MessageType__c1_PR_rrcReconfiguration; nr_rrc_transfer_protected_rrc_message(rrc, ue_p, DL_SCH_LCID_DCCH, msg_id, msg.buf, msg.len); @@ -831,44 +947,27 @@ void rrc_gNB_modify_dedicatedRRCReconfiguration(gNB_RRC_INST *rrc, gNB_RRC_UE_t free_byte_array(msg); } -//----------------------------------------------------------------------------- -void rrc_gNB_generate_dedicatedRRCReconfiguration_release(gNB_RRC_INST *rrc, - gNB_RRC_UE_t *ue_p, - uint8_t xid, - uint32_t nas_length, - uint8_t *nas_buffer) -//----------------------------------------------------------------------------- +static void rrc_gNB_send_f1_drb_release_request(gNB_RRC_INST *rrc, gNB_RRC_UE_t *ue_p, int *drb_to_release, int n_drb_to_release) { - nr_rrc_reconfig_param_t params = {.transaction_id = xid}; + f1_ue_data_t ue_data = cu_get_f1_ue_data(ue_p->rrc_ue_id); + RETURN_IF_INVALID_ASSOC_ID(ue_data.du_assoc_id); + f1ap_ue_context_mod_req_t req = { + .gNB_CU_ue_id = ue_p->rrc_ue_id, + .gNB_DU_ue_id = ue_data.secondary_ue, + .servCellIndex = 0, + }; + req.plmn = malloc_or_fail(sizeof(*req.plmn)); + *req.plmn = rrc->configuration.plmn[0]; + req.nr_cellid = malloc_or_fail(sizeof(*req.nr_cellid)); + *req.nr_cellid = rrc->nr_cellid; + req.drbs_rel = malloc_or_fail(sizeof(*req.drbs_rel)); + req.drbs_rel_len = n_drb_to_release; + memcpy(req.drbs_rel, drb_to_release, n_drb_to_release * sizeof(int)); - NR_DRB_ToReleaseList_t *to_release = CALLOC(sizeof(*to_release), 1); - FOR_EACH_SEQ_ARR(rrc_pdu_session_param_t *, item, &ue_p->pduSessions) { - if ((item->status != PDU_SESSION_STATUS_TORELEASE) && item->xid != xid) - continue; - FOR_EACH_SEQ_ARR(drb_t *, drb, &ue_p->drbs) { - if (drb->pdusession_id == item->param.pdusession_id) { - asn1cSequenceAdd(to_release->list, NR_DRB_Identity_t, DRB_release); - *DRB_release = drb->drb_id; // DRB ID - } - } - } - params.drb_release_list = to_release; - - if (nas_length > 0) { - params.dedicated_NAS_msg_list[params.num_nas_msg].buf = nas_buffer; - params.dedicated_NAS_msg_list[params.num_nas_msg++].len = nas_length; - } - byte_array_t msg = do_RRCReconfiguration(¶ms); - if (msg.len <= 0) { - LOG_E(NR_RRC, "UE %d: Failed to generate RRCReconfiguration\n", ue_p->rrc_ue_id); - return; - } - LOG_DUMPMSG(NR_RRC, DEBUG_RRC, msg.buf, msg.len, "[MSG] RRC Reconfiguration\n"); - LOG_I(NR_RRC, "UE %d: Generate NR_RRCReconfiguration (bytes %ld)\n", ue_p->rrc_ue_id, msg.len); - const uint32_t msg_id = NR_DL_DCCH_MessageType__c1_PR_rrcReconfiguration; - nr_rrc_transfer_protected_rrc_message(rrc, ue_p, DL_SCH_LCID_DCCH, msg_id, msg.buf, msg.len); - free_RRCReconfiguration_params(params); - free_byte_array(msg); + /* send UE Context Modification to DU without attaching any RRC container */ + rrc->mac_rrc.ue_context_modification_request(ue_data.du_assoc_id, &req); + LOG_I(NR_RRC, "UE %d: send F1 UE Context Modification Request with DRB release (%d DRBs)\n", ue_p->rrc_ue_id, req.drbs_rel_len); + free_ue_context_mod_req(&req); } static void fill_security_info(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, security_information_t *secInfo) @@ -1847,10 +1946,8 @@ static void handle_rrcReconfigurationComplete(gNB_RRC_INST *rrc, gNB_RRC_UE_t *U switch (UE->xids[xid]) { case RRC_PDUSESSION_RELEASE: { - gtpv1u_gnb_delete_tunnel_req_t req = {0}; - gtpv1u_delete_ngu_tunnel(rrc->module_id, &req); - // NGAP_PDUSESSION_RELEASE_RESPONSE rrc_gNB_send_NGAP_PDUSESSION_RELEASE_RESPONSE(rrc, UE, xid); + reset_delayed_action(&UE->delayed_action); } break; case RRC_PDUSESSION_ESTABLISH: if (UE->n_initial_pdu > 0) { @@ -1865,6 +1962,7 @@ static void handle_rrcReconfigurationComplete(gNB_RRC_INST *rrc, gNB_RRC_UE_t *U LOG_W(NR_RRC, "UE %d: RRC Reconfiguration Complete for PDU session establishment, but no PDU sessions were setup\n", UE->rrc_ue_id); + reset_delayed_action(&UE->delayed_action); break; case RRC_PDUSESSION_MODIFY: rrc_gNB_send_NGAP_PDUSESSION_MODIFY_RESP(rrc, UE, xid); @@ -1881,9 +1979,6 @@ static void handle_rrcReconfigurationComplete(gNB_RRC_INST *rrc, gNB_RRC_UE_t *U break; } - if (UE->xids[xid] == RRC_PDUSESSION_ESTABLISH) - UE->ongoing_pdusession_setup_request = false; - UE->xids[xid] = RRC_ACTION_NONE; for (int i = 0; i < NR_RRC_TRANSACTION_IDENTIFIER_NUMBER; ++i) { if (UE->xids[i] != RRC_ACTION_NONE) { @@ -2728,15 +2823,19 @@ void rrc_gNB_process_e1_bearer_context_setup_failure(e1ap_bearer_context_setup_f */ void rrc_gNB_process_e1_bearer_context_modif_resp(const e1ap_bearer_modif_resp_t *resp) { + LOG_I(NR_RRC, "Received E1AP Bearer Context Modification Response for UE CU-CP ID %d\n", resp->gNB_cu_cp_ue_id); gNB_RRC_INST *rrc = RC.nrrrc[0]; rrc_gNB_ue_context_t *ue_context_p = rrc_gNB_get_ue_context(rrc, resp->gNB_cu_cp_ue_id); if (ue_context_p == NULL) { LOG_E(RRC, "no UE with CU-CP UE ID %d found\n", resp->gNB_cu_cp_ue_id); return; } + gNB_RRC_UE_t *ue = &ue_context_p->ue_context; int n_drb_mod = 0; int drb_ids[MAX_DRBS_PER_UE] = {0}; + int drb_to_release[MAX_DRBS_PER_UE] = {0}; + int n_drb_to_release = 0; e1_pdcp_status_info_t pdcp_status[MAX_DRBS_PER_UE] = {0}; for (int i = 0; i < resp->numPDUSessionsMod; ++i) { const pdu_session_modif_t *pdu = &resp->pduSessionMod[i]; @@ -2749,13 +2848,32 @@ void rrc_gNB_process_e1_bearer_context_modif_resp(const e1ap_bearer_modif_resp_t pdcp_status[n_drb_mod++] = *pdu->DRBnGRanModList[j].pdcp_status; } } + // Collect DRBs to release for PDU sessions marked for release + rrc_pdu_session_param_t *pdu_session = find_pduSession(&ue->pduSessions, pdu->id); + if (pdu_session && pdu_session->status == PDU_SESSION_STATUS_TORELEASE) { + FOR_EACH_SEQ_ARR(drb_t *, drb, &ue->drbs) { + if (drb->pdusession_id == pdu->id) { + DevAssert(n_drb_to_release < MAX_DRBS_PER_UE); + drb_to_release[n_drb_to_release++] = drb->drb_id; + } + } + if (n_drb_to_release == 0) { + LOG_E(NR_RRC, "UE %d: no DRBs to release for PDU session %ld\n", ue->rrc_ue_id, pdu->id); + } + } } + if (n_drb_mod) { LOG_I(NR_RRC, "UE %d: received PDU Status Info - send UL RAN Status Transfer\n", resp->gNB_cu_cp_ue_id); - gNB_RRC_UE_t *ue = &ue_context_p->ue_context; if (ue->ho_context && ue->ho_context->source) ue->ho_context->source->ho_status_transfer(rrc, ue, n_drb_mod, drb_ids, pdcp_status); } + + // Send F1 UE Context Modification Request with DRB release + if (n_drb_to_release) { + LOG_I(NR_RRC, "Send F1 UE Context Modification Request with DRB to release\n"); + rrc_gNB_send_f1_drb_release_request(rrc, ue, drb_to_release, n_drb_to_release); + } } /** @brief E1AP Bearer Context Modification Failure processing on CU-CP */ @@ -2852,7 +2970,6 @@ static const char *get_pdusession_status_text(pdu_session_status_t status) case PDU_SESSION_STATUS_TOMODIFY: return "to-modify"; case PDU_SESSION_STATUS_FAILED: return "failed"; case PDU_SESSION_STATUS_TORELEASE: return "to-release"; - case PDU_SESSION_STATUS_RELEASED: return "released"; default: AssertFatal(false, "illegal PDU status code %d\n", status); return "illegal"; } return "illegal"; @@ -2978,7 +3095,8 @@ void *rrc_gnb_task(void *args_p) { break; case NGAP_PDUSESSION_SETUP_REQ: - rrc_gNB_process_NGAP_PDUSESSION_SETUP_REQ(msg_p, instance); + if (!rrc_delay_transaction(instance, msg_p)) + rrc_gNB_process_NGAP_PDUSESSION_SETUP_REQ(msg_p, instance); break; case NGAP_PDUSESSION_MODIFY_REQ: @@ -2986,7 +3104,8 @@ void *rrc_gnb_task(void *args_p) { break; case NGAP_PDUSESSION_RELEASE_COMMAND: - rrc_gNB_process_NGAP_PDUSESSION_RELEASE_COMMAND(msg_p, instance); + if (!rrc_delay_transaction(instance, msg_p)) + rrc_gNB_process_NGAP_PDUSESSION_RELEASE_COMMAND(&NGAP_PDUSESSION_RELEASE_COMMAND(msg_p), RC.nrrrc[instance]); break; case NGAP_DL_RAN_STATUS_TRANSFER: diff --git a/openair2/RRC/NR/rrc_gNB_NGAP.c b/openair2/RRC/NR/rrc_gNB_NGAP.c index 3b30341371..8ba7b3e950 100644 --- a/openair2/RRC/NR/rrc_gNB_NGAP.c +++ b/openair2/RRC/NR/rrc_gNB_NGAP.c @@ -789,29 +789,6 @@ void rrc_gNB_send_NGAP_PDUSESSION_SETUP_RESP(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE return; } -/* \brief checks if any transaction is ongoing for any xid of this UE */ -static bool transaction_ongoing(const gNB_RRC_UE_t *UE) -{ - for (int xid = 0; xid < NR_RRC_TRANSACTION_IDENTIFIER_NUMBER; ++xid) { - if (UE->xids[xid] != RRC_ACTION_NONE) - return true; - } - return false; -} - -/* \brief delays the ongoing transaction (in msg_p) by setting a timer to wait - * 10ms; upon expiry, delivers to RRC, which sends the message to itself */ -static void delay_transaction(MessageDef *msg_p, int wait_us) -{ - MessageDef *new = itti_alloc_new_message(TASK_RRC_GNB, 0, NGAP_PDUSESSION_SETUP_REQ); - ngap_pdusession_setup_req_t *n = &NGAP_PDUSESSION_SETUP_REQ(new); - *n = NGAP_PDUSESSION_SETUP_REQ(msg_p); - - int instance = msg_p->ittiMsgHeader.originInstance; - long timer_id; - timer_setup(0, wait_us, TASK_RRC_GNB, instance, TIMER_ONE_SHOT, new, &timer_id); -} - /** * @brief Fill PDU Session Resource Setup Response with a list of PDU Session Resources Failed to Setup * and send ITTI message to TASK_NGAP @@ -883,25 +860,6 @@ void rrc_gNB_process_NGAP_PDUSESSION_SETUP_REQ(MessageDef *msg_p, instance_t ins UE->amf_ue_ngap_id = msg->amf_ue_ngap_id; - /* This is a hack. We observed that with some UEs, PDU session requests might - * come in quick succession, faster than the RRC reconfiguration for the PDU - * session requests can be carried out (UE is doing reconfig, and second PDU - * session request arrives). We don't have currently the means to "queue up" - * these transactions, which would probably involve some rework of the RRC. - * To still allow these requests to come in and succeed, we below check and delay transactions - * for 10ms. However, to not accidentally end up in infinite loops, the - * maximum number is capped on a per-UE basis as indicated in variable - * max_delays_pdu_session. */ - if (!UE->ongoing_pdusession_setup_request) - UE->max_delays_pdu_session = 100; - - if (UE->max_delays_pdu_session > 0 && (transaction_ongoing(UE) || UE->ongoing_pdusession_setup_request)) { - int wait_us = 10000; - LOG_I(RRC, "UE %d: delay PDU session setup by %d us, pending %d retries\n", UE->rrc_ue_id, wait_us, UE->max_delays_pdu_session); - delay_transaction(msg_p, wait_us); - UE->max_delays_pdu_session--; - return; - } pdusession_t to_setup[NGAP_MAX_PDU_SESSION] = {0}; for (int i = 0; i < msg->nb_pdusessions_tosetup; ++i) @@ -916,7 +874,8 @@ void rrc_gNB_process_NGAP_PDUSESSION_SETUP_REQ(MessageDef *msg_p, instance_t ins send_ngap_pdu_session_setup_resp_fail(instance, msg, cause); rrc_forward_ue_nas_message(rrc, UE); } else { - UE->ongoing_pdusession_setup_request = true; + // Set ongoing_transaction flag to true + init_delayed_action(&UE->delayed_action); } } @@ -1562,68 +1521,75 @@ void rrc_gNB_send_NGAP_PDUSESSION_RELEASE_RESPONSE(gNB_RRC_INST *rrc, gNB_RRC_UE DevAssert(resp->nb_of_pdusessions_released < NGAP_MAX_PDU_SESSION); resp->pdusession_release[resp->nb_of_pdusessions_released++].pdusession_id = pdusession->pdusession_id; } - session->status = PDU_SESSION_STATUS_RELEASED; } } + for (int i = 0; i < resp->nb_of_pdusessions_released; ++i) { + rm_pduSession(&UE->pduSessions, &UE->drbs, resp->pdusession_release[i].pdusession_id); + } + LOG_I(NR_RRC, "NGAP PDUSESSION RELEASE RESPONSE: rrc_ue_id %u release_pdu_sessions %d\n", resp->gNB_ue_ngap_id, resp->nb_of_pdusessions_released); itti_send_msg_to_task (TASK_NGAP, rrc->module_id, msg_p); } -//------------------------------------------------------------------------------ -int rrc_gNB_process_NGAP_PDUSESSION_RELEASE_COMMAND(MessageDef *msg_p, instance_t instance) -//------------------------------------------------------------------------------ +/** @brief Process NG PDU Session Resource Release command (8.2.2 of 3GPP TS 38.413) + * upon reception the NG-RAN node shall execute the release of the requested PDU sessions. + * For each PDU session to be released the NG-RAN node shall release the corresponding + * resources over Uu and over NG, if any. */ +int rrc_gNB_process_NGAP_PDUSESSION_RELEASE_COMMAND(ngap_pdusession_release_command_t *cmd, gNB_RRC_INST *rrc) { - uint32_t gNB_ue_ngap_id; - ngap_pdusession_release_command_t *cmd = &NGAP_PDUSESSION_RELEASE_COMMAND(msg_p); - gNB_ue_ngap_id = cmd->gNB_ue_ngap_id; - gNB_RRC_INST *rrc = RC.nrrrc[instance]; + uint32_t gNB_ue_ngap_id = cmd->gNB_ue_ngap_id; rrc_gNB_ue_context_t *ue_context_p = rrc_gNB_get_ue_context(rrc, gNB_ue_ngap_id); if (!ue_context_p) { - LOG_E(NR_RRC, "[gNB %ld] not found ue context gNB_ue_ngap_id %u \n", instance, gNB_ue_ngap_id); + LOG_E(NR_RRC, "[gNB %d] UE context not found for gNB_ue_ngap_id %u \n", rrc->module_id, gNB_ue_ngap_id); return -1; } - LOG_I(NR_RRC, "[gNB %ld] gNB_ue_ngap_id %u \n", instance, gNB_ue_ngap_id); gNB_RRC_UE_t *UE = &ue_context_p->ue_context; - LOG_I( - NR_RRC, "PDU Session Release Command: AMF_UE_NGAP_ID %lu rrc_ue_id %u release_pdusessions %d \n", cmd->amf_ue_ngap_id, gNB_ue_ngap_id, cmd->nb_pdusessions_torelease); - bool found = false; - uint8_t xid = rrc_gNB_get_next_transaction_identifier(rrc->module_id); - UE->xids[xid] = RRC_PDUSESSION_RELEASE; + LOG_I(NR_RRC, "NG PDU Session Release command: AMF_UE_NGAP_ID=%lu, rrc_ue_id=%u, nb_pdusessions_torelease=%d \n", + cmd->amf_ue_ngap_id, + gNB_ue_ngap_id, + cmd->nb_pdusessions_torelease); + e1ap_bearer_mod_req_t req = {0}; for (int pdusession = 0; pdusession < cmd->nb_pdusessions_torelease; pdusession++) { rrc_pdu_session_param_t *pduSession = find_pduSession(&UE->pduSessions, cmd->pdusession_release_params[pdusession].pdusession_id); if (!pduSession) { LOG_E(NR_RRC, "Failed to release non-existing PDU Session %d\n", cmd->pdusession_release_params[pdusession].pdusession_id); continue; } - if (pduSession->status == PDU_SESSION_STATUS_FAILED) { - pduSession->xid = xid; + if (pduSession->status == PDU_SESSION_STATUS_TORELEASE) { + LOG_W(NR_RRC, "PDU Session %d already set to be released\n", pduSession->param.pdusession_id); continue; } - if (pduSession->status == PDU_SESSION_STATUS_ESTABLISHED) { - found = true; - LOG_I(NR_RRC, "RELEASE pdusession %d \n", pduSession->param.pdusession_id); - pduSession->status = PDU_SESSION_STATUS_TORELEASE; - pduSession->xid = xid; - } + // Set PDU session to release, regardless of the status + LOG_I(NR_RRC, "Set PDU Session %d to release\n", pduSession->param.pdusession_id); + pdu_session_to_remove_t *release = &req.pduSessionRem[req.numPDUSessionsRem++]; + release->sessionId = pduSession->param.pdusession_id; + release->cause.type = E1AP_CAUSE_RADIO_NETWORK; + release->cause.value = E1AP_RADIO_CAUSE_NORMAL_RELEASE; + pduSession->status = PDU_SESSION_STATUS_TORELEASE; } - if (found) { - // TODO RRCReconfiguration To UE - LOG_I(NR_RRC, "Send RRCReconfiguration To UE \n"); - rrc_gNB_generate_dedicatedRRCReconfiguration_release(rrc, UE, xid, cmd->nas_pdu.len, cmd->nas_pdu.buf); + if (req.numPDUSessionsRem == 0) { + LOG_E(NR_RRC, "Received NG PDU Session Release Command but no PDU Sessions to release\n"); + return -1; + } else if (!ue_associated_to_cuup(rrc, UE)) { + LOG_E(NR_RRC, "UE %d is not associated to CU-UP\n", UE->rrc_ue_id); + // TODO handle, e.g., only trigger F1 release + return 0; } else { - // gtp tunnel delete - LOG_I(NR_RRC, "gtp tunnel delete all tunnels for UE %04x\n", UE->rnti); - gtpv1u_gnb_delete_tunnel_req_t req = {0}; - req.ue_id = UE->rnti; - gtpv1u_delete_ngu_tunnel(rrc->module_id, &req); - // NGAP_PDUSESSION_RELEASE_RESPONSE - rrc_gNB_send_NGAP_PDUSESSION_RELEASE_RESPONSE(rrc, UE, xid); - LOG_I(NR_RRC, "Send PDU Session Release Response \n"); + /* If present, store NAS-PDU in the UE context for later inclusion in RRCReconfiguration */ + if (cmd->nas_pdu.len > 0) { + UE->nas_pdu = copy_byte_array(cmd->nas_pdu); + } + LOG_I(NR_RRC, "Send F1 Bearer Context Modification Request with PDU Session release \n"); + req.gNB_cu_cp_ue_id = UE->rrc_ue_id; + req.gNB_cu_up_ue_id = UE->rrc_ue_id; + sctp_assoc_t assoc_id = get_existing_cuup_for_ue(rrc, UE); + rrc->cucp_cuup.bearer_context_mod(assoc_id, &req); } + init_delayed_action(&UE->delayed_action); return 0; } diff --git a/openair2/RRC/NR/rrc_gNB_NGAP.h b/openair2/RRC/NR/rrc_gNB_NGAP.h index 91c7722c52..c3f692ff5f 100644 --- a/openair2/RRC/NR/rrc_gNB_NGAP.h +++ b/openair2/RRC/NR/rrc_gNB_NGAP.h @@ -78,7 +78,7 @@ void rrc_gNB_send_NGAP_UE_CONTEXT_RELEASE_COMPLETE(instance_t instance, uint32_t void rrc_gNB_send_NGAP_UE_CAPABILITIES_IND(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, const NR_UECapabilityInformation_t *const ue_cap_info); -int rrc_gNB_process_NGAP_PDUSESSION_RELEASE_COMMAND(MessageDef *msg_p, instance_t instance); +int rrc_gNB_process_NGAP_PDUSESSION_RELEASE_COMMAND(ngap_pdusession_release_command_t *cmd, gNB_RRC_INST *rrc); void rrc_gNB_send_NGAP_PDUSESSION_RELEASE_RESPONSE(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, uint8_t xid); diff --git a/openair2/RRC/NR/rrc_gNB_UE_context.c b/openair2/RRC/NR/rrc_gNB_UE_context.c index 9a2c3fb6f6..86838927ab 100644 --- a/openair2/RRC/NR/rrc_gNB_UE_context.c +++ b/openair2/RRC/NR/rrc_gNB_UE_context.c @@ -218,8 +218,6 @@ rrc_gNB_ue_context_t *rrc_gNB_create_ue_context(sctp_assoc_t assoc_id, ue->rrc_ue_id); bool success = cu_add_f1_ue_data(ue->rrc_ue_id, &ue_data); DevAssert(success); - ue->max_delays_pdu_session = 20; /* see rrc_gNB_process_NGAP_PDUSESSION_SETUP_REQ() */ - ue->ongoing_pdusession_setup_request = false; // Initialise setup PDU Sessions list seq_arr_init(&ue->pduSessions, sizeof(rrc_pdu_session_param_t)); diff --git a/openair2/RRC/NR/rrc_gNB_radio_bearers.c b/openair2/RRC/NR/rrc_gNB_radio_bearers.c index 5af84f0399..c636e9e639 100644 --- a/openair2/RRC/NR/rrc_gNB_radio_bearers.c +++ b/openair2/RRC/NR/rrc_gNB_radio_bearers.c @@ -141,6 +141,62 @@ rrc_pdu_session_param_t *add_pduSession(seq_arr_t *sessions_ptr, const pdusessio return added; } +static bool eq_drb_pdu_session_id(const void *vval, const void *vit) +{ + const int *id = (const int *)vval; + const drb_t *elem = (const drb_t *)vit; + return elem->pdusession_id == *id; +} + +/** @brief Finds the first DRB with the given PDU session ID. + * @return Pointer to matching drb_t or NULL if not found. */ +static drb_t *find_drb_by_pdusession_id(seq_arr_t *seq, int pdusession_id) +{ + DevAssert(seq); + DevAssert(pdusession_id > 0 && pdusession_id <= NGAP_MAX_PDU_SESSION); + elm_arr_t elm = find_if(seq, &pdusession_id, eq_drb_pdu_session_id); + if (elm.found) + return (drb_t *)elm.it; + return NULL; +} + +/** @brief Removes a DRB from the list + * @param drbs The DRB list + * @param drb Pointer to the DRB to remove */ +static void nr_rrc_rm_drb(seq_arr_t *drbs, drb_t *drb) +{ + DevAssert(drbs); + DevAssert(drb); + LOG_I(NR_RRC, "Removing DRB ID %d (PDU Session ID=%d)\n", drb->drb_id, drb->pdusession_id); + seq_arr_erase_deep(drbs, drb, free_drb); +} + +/** @brief Removes a PDU Session from the list by ID + * Also removes all associated DRBs for this PDU session. + * @return true if successfully removed, false if not found */ +bool rm_pduSession(seq_arr_t *sessions, seq_arr_t *drbs, int pdusession_id) +{ + DevAssert(sessions); + DevAssert(drbs); + + rrc_pdu_session_param_t *session = find_pduSession(sessions, pdusession_id); + + if (session) { + LOG_I(NR_RRC, "Removing PDU Session %d from RRC setup list\n", pdusession_id); + // Remove all associated DRBs first + drb_t *drb; + while ((drb = find_drb_by_pdusession_id(drbs, pdusession_id))) { + nr_rrc_rm_drb(drbs, drb); + } + // Then remove the PDU session + seq_arr_erase_deep(sessions, session, free_pdusession); + return true; + } + + LOG_W(NR_RRC, "pdusession_id=%d not found to remove\n", pdusession_id); + return false; +} + /** @brief Add drb_t item in the UE context list for @param pdusession_id */ drb_t *nr_rrc_add_drb(seq_arr_t *drb_ptr, int pdusession_id, nr_pdcp_configuration_t *pdcp) { diff --git a/openair2/RRC/NR/rrc_gNB_radio_bearers.h b/openair2/RRC/NR/rrc_gNB_radio_bearers.h index f6821e314b..a1b09a5b02 100644 --- a/openair2/RRC/NR/rrc_gNB_radio_bearers.h +++ b/openair2/RRC/NR/rrc_gNB_radio_bearers.h @@ -39,6 +39,10 @@ rrc_pdu_session_param_t *add_pduSession(seq_arr_t *sessions_ptr, const pdusessio /// @brief get PDU session of UE ue through the DRB drb_id rrc_pdu_session_param_t *find_pduSession_from_drbId(gNB_RRC_UE_t *ue, int drb_id); +/// @brief Remove PDU Session from RRC list +/// Also removes all associated DRBs for this PDU session. +bool rm_pduSession(seq_arr_t *sessions, seq_arr_t *drbs, int pdusession_id); + /// @brief set PDCP configuration in E1 Bearer Context Management message bearer_context_pdcp_config_t set_bearer_context_pdcp_config(const nr_pdcp_configuration_t pdcp, bool um_on_default_drb, diff --git a/openair2/RRC/NR_UE/rrc_UE.c b/openair2/RRC/NR_UE/rrc_UE.c index 15c713cb26..24088749a5 100644 --- a/openair2/RRC/NR_UE/rrc_UE.c +++ b/openair2/RRC/NR_UE/rrc_UE.c @@ -747,12 +747,15 @@ static void nr_rrc_ue_process_masterCellGroup(NR_UE_RRC_INST_t *rrc, { AssertFatal(!fullConfig, "fullConfig not supported yet\n"); NR_CellGroupConfig_t *cellGroupConfig = NULL; - uper_decode(NULL, - &asn_DEF_NR_CellGroupConfig, //might be added prefix later - (void **)&cellGroupConfig, - (uint8_t *)masterCellGroup->buf, - masterCellGroup->size, 0, 0); - + asn_dec_rval_t dec_rval = uper_decode(NULL, + &asn_DEF_NR_CellGroupConfig, //might be added prefix later + (void **)&cellGroupConfig, + (uint8_t *)masterCellGroup->buf, + masterCellGroup->size, 0, 0); + if ((dec_rval.code != RC_OK) && (dec_rval.consumed == 0)) { + LOG_E(NR_RRC, "CellGroupConfig decode error\n"); + return; + } if (LOG_DEBUGFLAG(DEBUG_ASN1)) { xer_fprint(stdout, &asn_DEF_NR_CellGroupConfig, (const void *) cellGroupConfig); } @@ -823,28 +826,30 @@ static void nr_rrc_process_reconfiguration_v1530(NR_UE_RRC_INST_t *rrc, NR_RRCRe NR_RRCReconfiguration_v1540_IEs_t *rec_1540 = rec_1530->nonCriticalExtension; if (rec_1540) { NR_RRCReconfiguration_v1560_IEs_t *rec_1560 = rec_1540->nonCriticalExtension; - if (rec_1560->sk_Counter) { - // TODO perform AS security key update procedure as specified in 5.3.5.7 - LOG_E(NR_RRC, "RRCReconfiguration includes sk-Counter but this is not implemented yet\n"); - } - if (rec_1560->mrdc_SecondaryCellGroupConfig) { - // TODO perform handling of mrdc-SecondaryCellGroupConfig as specified in 5.3.5.3 - LOG_E(NR_RRC, "RRCReconfiguration includes mrdc-SecondaryCellGroupConfig but this is not handled yet\n"); - } - if (rec_1560->radioBearerConfig2) { - NR_RadioBearerConfig_t *RadioBearerConfig = NULL; - asn_dec_rval_t dec_rval = uper_decode(NULL, - &asn_DEF_NR_RadioBearerConfig, - (void **)&RadioBearerConfig, - (uint8_t *)rec_1560->radioBearerConfig2->buf, - rec_1560->radioBearerConfig2->size, - 0, - 0); - if ((dec_rval.code != RC_OK) && (dec_rval.consumed == 0)) { - LOG_E(NR_RRC, "radioBearerConfig2 decode error\n"); - SEQUENCE_free(&asn_DEF_NR_RadioBearerConfig, RadioBearerConfig, 1); - } else - nr_rrc_ue_process_RadioBearerConfig(rrc, RadioBearerConfig); + if (rec_1560) { + if (rec_1560->sk_Counter) { + // TODO perform AS security key update procedure as specified in 5.3.5.7 + LOG_E(NR_RRC, "RRCReconfiguration includes sk-Counter but this is not implemented yet\n"); + } + if (rec_1560->mrdc_SecondaryCellGroupConfig) { + // TODO perform handling of mrdc-SecondaryCellGroupConfig as specified in 5.3.5.3 + LOG_E(NR_RRC, "RRCReconfiguration includes mrdc-SecondaryCellGroupConfig but this is not handled yet\n"); + } + if (rec_1560->radioBearerConfig2) { + NR_RadioBearerConfig_t *RadioBearerConfig = NULL; + asn_dec_rval_t dec_rval = uper_decode(NULL, + &asn_DEF_NR_RadioBearerConfig, + (void **)&RadioBearerConfig, + (uint8_t *)rec_1560->radioBearerConfig2->buf, + rec_1560->radioBearerConfig2->size, + 0, + 0); + if ((dec_rval.code != RC_OK) && (dec_rval.consumed == 0)) { + LOG_E(NR_RRC, "radioBearerConfig2 decode error\n"); + SEQUENCE_free(&asn_DEF_NR_RadioBearerConfig, RadioBearerConfig, 1); + } else + nr_rrc_ue_process_RadioBearerConfig(rrc, RadioBearerConfig); + } } } } @@ -1158,20 +1163,19 @@ static void nr_rrc_ue_process_rrcReconfiguration(NR_UE_RRC_INST_t *rrc, int gNB_ LOG_E(NR_RRC, "\n"); // free the memory SEQUENCE_free(&asn_DEF_NR_CellGroupConfig, (void *)cellGroupConfig, 1); + } else { + if (LOG_DEBUGFLAG(DEBUG_ASN1)) + xer_fprint(stdout, &asn_DEF_NR_CellGroupConfig, (const void *) cellGroupConfig); + + nr_rrc_cellgroup_configuration(rrc, cellGroupConfig, gNB_index); + AssertFatal(!IS_SA_MODE(get_softmodem_params()), "secondaryCellGroup only used in NSA for now\n"); + nr_mac_rrc_message_t rrc_msg = {0}; + rrc_msg.payload_type = NR_MAC_RRC_CONFIG_CG; + nr_mac_rrc_config_cg_t *config_cg = &rrc_msg.payload.config_cg; + config_cg->cellGroupConfig = cellGroupConfig; + config_cg->UE_NR_Capability = rrc->UECap.UE_NR_Capability; + nr_rrc_send_msg_to_mac(rrc, &rrc_msg); } - - if (LOG_DEBUGFLAG(DEBUG_ASN1)) - xer_fprint(stdout, &asn_DEF_NR_CellGroupConfig, (const void *) cellGroupConfig); - - nr_rrc_cellgroup_configuration(rrc, cellGroupConfig, gNB_index); - - AssertFatal(!IS_SA_MODE(get_softmodem_params()), "secondaryCellGroup only used in NSA for now\n"); - nr_mac_rrc_message_t rrc_msg = {0}; - rrc_msg.payload_type = NR_MAC_RRC_CONFIG_CG; - nr_mac_rrc_config_cg_t *config_cg = &rrc_msg.payload.config_cg; - config_cg->cellGroupConfig = cellGroupConfig; - config_cg->UE_NR_Capability = rrc->UECap.UE_NR_Capability; - nr_rrc_send_msg_to_mac(rrc, &rrc_msg); } if (ie->measConfig) { LOG_I(NR_RRC, "RRCReconfiguration includes Measurement Configuration\n"); @@ -1651,13 +1655,29 @@ static void nr_rrc_signal_maxrtxindication(int ue_id) itti_send_msg_to_task(TASK_RRC_NRUE, ue_id, msg); } +/** @brief Release all active RLC entities for a UE and set to inactive. + * This is typically used when tearing down all DRBs at UE side, + * such as after a PDU session release or full reconfiguration. + * @param rrc Pointer to NR_UE_RRC_INST_t structure + * @param id Logical Channel ID (must be in range [0, NR_MAX_NUM_LCID-1]) */ +static void nr_rrc_release_rlc_entity(NR_UE_RRC_INST_t *rrc, int id) +{ + DevAssert(rrc); + DevAssert(id >= 0 && id < NR_MAX_NUM_LCID); + if (rrc->active_RLC_entity[id]) { + rrc->active_RLC_entity[id] = false; + nr_rlc_release_entity(rrc->ue_id, id); + LOG_I(RLC, "Released RLC entity: ue_id=%ld, lc_id=%d\n", rrc->ue_id, id); + } +} + static void nr_rrc_manage_rlc_bearers(NR_UE_RRC_INST_t *rrc, const NR_CellGroupConfig_t *cellGroupConfig) { if (cellGroupConfig->rlc_BearerToReleaseList != NULL) { for (int i = 0; i < cellGroupConfig->rlc_BearerToReleaseList->list.count; i++) { NR_LogicalChannelIdentity_t *lcid = cellGroupConfig->rlc_BearerToReleaseList->list.array[i]; AssertFatal(lcid, "LogicalChannelIdentity shouldn't be null here\n"); - nr_rlc_release_entity(rrc->ue_id, *lcid); + nr_rrc_release_rlc_entity(rrc, *lcid); } } @@ -1681,8 +1701,13 @@ static void nr_rrc_manage_rlc_bearers(NR_UE_RRC_INST_t *rrc, const NR_CellGroupC nr_rlc_set_rlf_handler(rrc->ue_id, nr_rrc_signal_maxrtxindication); } else { // DRB NR_DRB_Identity_t drb_id = rlc_bearer->servedRadioBearer->choice.drb_Identity; - nr_rlc_add_drb(rrc->ue_id, drb_id, rlc_bearer); - nr_rlc_set_rlf_handler(rrc->ue_id, nr_rrc_signal_maxrtxindication); + if (!rlc_bearer->rlc_Config) { + LOG_E(RLC, "RLC-Config not present but is mandatory for setup\n"); + rrc->active_RLC_entity[lcid] = false; + } else { + nr_rlc_add_drb(rrc->ue_id, drb_id, rlc_bearer); + nr_rlc_set_rlf_handler(rrc->ue_id, nr_rrc_signal_maxrtxindication); + } } } } @@ -1710,7 +1735,10 @@ static void nr_rrc_process_reconfigurationWithSync(NR_UE_RRC_INST_t *rrc, rrc->arfcn_ssb = *dcc->frequencyInfoDL->absoluteFrequencySSB; // consider the target SpCell to be one with a physical cell identity indicated by the physCellId - rrc->phyCellID = *reconfigurationWithSync->spCellConfigCommon->physCellId; + if (!reconfigurationWithSync->spCellConfigCommon->physCellId) + LOG_E(NR_RRC, "physCellId absent but should be mandatory present upon cell change and cell addition\n"); + else + rrc->phyCellID = *reconfigurationWithSync->spCellConfigCommon->physCellId; } NR_UE_Timers_Constants_t *tac = &rrc->timers_and_constants; @@ -1830,10 +1858,7 @@ static void nr_rrc_rrcsetup_fallback(NR_UE_RRC_INST_t *rrc) } } for (int i = 1; i < NR_MAX_NUM_LCID; i++) { - if (rrc->active_RLC_entity[i]) { - rrc->active_RLC_entity[i] = false; - nr_rlc_release_entity(rrc->ue_id, i); - } + nr_rrc_release_rlc_entity(rrc, i); } nr_sdap_delete_ue_entities(rrc->ue_id); @@ -2235,13 +2260,7 @@ static void nr_rrc_ue_process_ueCapabilityEnquiry(NR_UE_RRC_INST_t *rrc, NR_UECa AssertFatal (enc_rval.encoded > 0, "ASN1 message encoding failed (%s, %lu)!\n", enc_rval.failed_type->name, enc_rval.encoded); rrc->UECap.sdu_size = (enc_rval.encoded + 7) / 8; LOG_I(PHY, "[RRC]UE NR Capability encoded, %d bytes (%zd bits)\n", rrc->UECap.sdu_size, enc_rval.encoded + 7); - /* RAT Container */ - NR_UE_CapabilityRAT_Container_t *ue_CapabilityRAT_Container = CALLOC(1, sizeof(NR_UE_CapabilityRAT_Container_t)); - ue_CapabilityRAT_Container->rat_Type = NR_RAT_Type_nr; - OCTET_STRING_fromBuf(&ue_CapabilityRAT_Container->ue_CapabilityRAT_Container, (const char *)rrc->UECap.sdu, rrc->UECap.sdu_size); NR_UECapabilityEnquiry_IEs_t *ueCapabilityEnquiry_ie = UECapabilityEnquiry->criticalExtensions.choice.ueCapabilityEnquiry; - // ue_CapabilityRAT_Container.ueCapabilityRAT_Container.buf = UE_rrc_inst[ue_mod_idP].UECapability; - // ue_CapabilityRAT_Container.ueCapabilityRAT_Container.size = UE_rrc_inst[ue_mod_idP].UECapability_size; AssertFatal(UECapabilityEnquiry->criticalExtensions.present == NR_UECapabilityEnquiry__criticalExtensions_PR_ueCapabilityEnquiry, "UECapabilityEnquiry->criticalExtensions.present (%d) != UECapabilityEnquiry__criticalExtensions_PR_c1 (%d)\n", UECapabilityEnquiry->criticalExtensions.present,NR_UECapabilityEnquiry__criticalExtensions_PR_ueCapabilityEnquiry); @@ -2254,6 +2273,10 @@ static void nr_rrc_ue_process_ueCapabilityEnquiry(NR_UE_RRC_INST_t *rrc, NR_UECa for (int i = 0; i < ueCapabilityEnquiry_ie->ue_CapabilityRAT_RequestList.list.count; i++) { if (ueCapabilityEnquiry_ie->ue_CapabilityRAT_RequestList.list.array[i]->rat_Type == NR_RAT_Type_nr) { + /* RAT Container */ + NR_UE_CapabilityRAT_Container_t *ue_CapabilityRAT_Container = CALLOC(1, sizeof(NR_UE_CapabilityRAT_Container_t)); + ue_CapabilityRAT_Container->rat_Type = NR_RAT_Type_nr; + OCTET_STRING_fromBuf(&ue_CapabilityRAT_Container->ue_CapabilityRAT_Container, (const char *)rrc->UECap.sdu, rrc->UECap.sdu_size); asn1cSeqAdd(&UEcapList->list, ue_CapabilityRAT_Container); uint8_t buffer[500]; asn_enc_rval_t enc_rval = uper_encode_to_buffer(&asn_DEF_NR_UL_DCCH_Message, NULL, (void *)&ul_dcch_msg, buffer, 500); @@ -2267,8 +2290,7 @@ static void nr_rrc_ue_process_ueCapabilityEnquiry(NR_UE_RRC_INST_t *rrc, NR_UECa nr_pdcp_data_req_srb(rrc->ue_id, srb_id, 0, (enc_rval.encoded + 7) / 8, buffer, deliver_pdu_srb_rlc, NULL); } } - /* Free struct members after it's done - including locally allocated ue_CapabilityRAT_Container */ + /* Free struct members after it's done including locally allocated ue_CapabilityRAT_Container */ ASN_STRUCT_RESET(asn_DEF_NR_UL_DCCH_Message, &ul_dcch_msg); } @@ -2938,10 +2960,7 @@ void nr_rrc_going_to_IDLE(NR_UE_RRC_INST_t *rrc, } } for (int i = 0; i < NR_MAX_NUM_LCID; i++) { - if (rrc->active_RLC_entity[i]) { - rrc->active_RLC_entity[i] = false; - nr_rlc_release_entity(rrc->ue_id, i); - } + nr_rrc_release_rlc_entity(rrc, i); } for (int i = 0; i < NB_CNX_UE; i++) { diff --git a/openair2/SDAP/nr_sdap/nr_sdap_entity.c b/openair2/SDAP/nr_sdap/nr_sdap_entity.c index 389213986e..dc747e5a60 100644 --- a/openair2/SDAP/nr_sdap/nr_sdap_entity.c +++ b/openair2/SDAP/nr_sdap/nr_sdap_entity.c @@ -210,15 +210,20 @@ static void nr_sdap_rx_entity(nr_sdap_entity_t *entity, { /* The offset of the SDAP header, it might be 0 if has_sdap_rx is not true in the pdcp entity. */ int offset=0; - uint8_t qfi = buf[0] & 0x3F; // QFI is always the first 6 bits in the first octet - if (qfi >= SDAP_MAX_QFI) { - LOG_E(SDAP, "Invalid QFI %d received in SDAP header\n", qfi); - return; + bool sdap_ul_rx = false; + bool sdap_dl_rx = false; + /* If SDAP header is disabled for this entity, bypass header parsing */ + if (entity->enable_sdap) { + uint8_t qfi = buf[0] & 0x3F; // QFI is always the first 6 bits in the first octet + if (qfi >= SDAP_MAX_QFI) { + LOG_E(SDAP, "Invalid QFI %d received in SDAP header\n", qfi); + return; + } + // Fetch entity role from the qfi2drb_table + sdap_ul_rx = entity->qfi2drb_table[qfi].entity_role & SDAP_UL_RX; // gNB RX entity + sdap_dl_rx = entity->qfi2drb_table[qfi].entity_role & SDAP_DL_RX; // UE RX entity } - // Fetch entity role from the qfi2drb_table - bool sdap_ul_rx = entity->qfi2drb_table[qfi].entity_role & SDAP_UL_RX; // gNB RX entity - bool sdap_dl_rx = entity->qfi2drb_table[qfi].entity_role & SDAP_DL_RX; // UE RX entity if (is_gnb) { // gNB if (sdap_ul_rx) { // UL Data/Control PDU with SDAP header @@ -495,6 +500,7 @@ static void nr_sdap_add_entity(const int is_gnb, const ue_id_t ue_id, const sdap sdap_entity->ue_id = ue_id; sdap_entity->pdusession_id = sdap->pdusession_id; sdap_entity->is_gnb = is_gnb; + sdap_entity->enable_sdap = (sdap->role != NO_SDAP_HEADER); // rx/tx entities sdap_entity->tx_entity = nr_sdap_tx_entity; @@ -590,14 +596,13 @@ bool nr_sdap_delete_entity(ue_id_t ue_id, int pdusession_id) LOG_E(SDAP, "SDAP entities not established or Invalid range of pdusession_id [0, 256].\n"); return false; } - LOG_D(SDAP, "Deleting SDAP entity for UE %lx and PDU Session id %d\n", ue_id, entityPtr->pdusession_id); if (entityPtr->ue_id == ue_id && entityPtr->pdusession_id == pdusession_id) { sdap_info.sdap_entity_llist = sdap_info.sdap_entity_llist->next_entity; if (entityPtr->pdusession_sock != -1) remove_ip_if(entityPtr); free(entityPtr); - LOG_D(SDAP, "Successfully deleted Entity.\n"); + LOG_D(SDAP, "Successfully deleted SDAP entity for UE %lx and PDU Session id %d\n", ue_id, pdusession_id); return true; } else { while ((entityPtr->ue_id != ue_id || entityPtr->pdusession_id != pdusession_id) && entityPtr->next_entity != NULL @@ -613,7 +618,7 @@ bool nr_sdap_delete_entity(ue_id_t ue_id, int pdusession_id) remove_ip_if(entityPtr); } free(entityPtr); - LOG_D(SDAP, "Successfully deleted Entity.\n"); + LOG_D(SDAP, "Successfully deleted Entity for UE %lx and PDU Session id %d\n", ue_id, pdusession_id); return true; } } diff --git a/openair2/SDAP/nr_sdap/nr_sdap_entity.h b/openair2/SDAP/nr_sdap/nr_sdap_entity.h index e96836ac79..9f85ac21cf 100644 --- a/openair2/SDAP/nr_sdap/nr_sdap_entity.h +++ b/openair2/SDAP/nr_sdap/nr_sdap_entity.h @@ -99,6 +99,7 @@ typedef struct nr_sdap_entity_s { /// sdap_tun_read_thread needs to know if we are gNB/UE, so for noS1 mode, /// store which one we are bool is_gnb; + bool enable_sdap; int pdusession_id; int pdusession_sock; pthread_t pdusession_thread; diff --git a/openair3/NAS/NR_UE/nr_nas_msg.c b/openair3/NAS/NR_UE/nr_nas_msg.c index d0230e0a03..5a58af6b84 100644 --- a/openair3/NAS/NR_UE/nr_nas_msg.c +++ b/openair3/NAS/NR_UE/nr_nas_msg.c @@ -1772,7 +1772,7 @@ static void send_nas_5gmm_ind(instance_t instance, const Guti5GSMobileIdentity_t itti_send_msg_to_task(TASK_RRC_NRUE, instance, msg); } -static void request_pdusession(nr_ue_nas_t *nas, int pdusession_id) +void request_pdusession(nr_ue_nas_t *nas, int pdusession_id) { MessageDef *message_p = itti_alloc_new_message(TASK_NAS_NRUE, nas->UE_id, NAS_PDU_SESSION_REQ); NAS_PDU_SESSION_REQ(message_p).pdusession_id = pdusession_id; diff --git a/openair3/NAS/NR_UE/nr_nas_msg.h b/openair3/NAS/NR_UE/nr_nas_msg.h index 2d62c799ea..7a19997444 100644 --- a/openair3/NAS/NR_UE/nr_nas_msg.h +++ b/openair3/NAS/NR_UE/nr_nas_msg.h @@ -113,5 +113,6 @@ void *nas_nrue_task(void *args_p); void *nas_nrue(void *args_p); void nas_init_nrue(int num_ues); void nr_ue_create_ip_if(const char *ifnameprefix, const char *ipv4, const char *ipv6, int ue_id, int pdu_session_id); +void request_pdusession(nr_ue_nas_t *nas, int pdusession_id); #endif /* __NR_NAS_MSG_SIM_H__*/ diff --git a/openair3/NGAP/ngap_gNB_nnsf.c b/openair3/NGAP/ngap_gNB_nnsf.c index 5fbc3e4d11..e16e790d38 100644 --- a/openair3/NGAP/ngap_gNB_nnsf.c +++ b/openair3/NGAP/ngap_gNB_nnsf.c @@ -156,7 +156,7 @@ ngap_gNB_amf_data_t *ngap_gNB_nnsf_select_amf_by_plmn_id(ngap_gNB_instance_t *in ngap_gNB_amf_data_t *ngap_gNB_nnsf_select_amf_by_amf_setid(ngap_gNB_instance_t *instance_p, const ngap_rrc_establishment_cause_t cause, const plmn_id_t selected_plmn_identity, - uint8_t amf_setid) + uint16_t amf_setid) { struct ngap_gNB_amf_data_s *amf_data_p = NULL; diff --git a/openair3/NGAP/ngap_gNB_nnsf.h b/openair3/NGAP/ngap_gNB_nnsf.h index 8a87ecfce2..0b7c7059e3 100644 --- a/openair3/NGAP/ngap_gNB_nnsf.h +++ b/openair3/NGAP/ngap_gNB_nnsf.h @@ -43,7 +43,7 @@ ngap_gNB_amf_data_t *ngap_gNB_nnsf_select_amf_by_plmn_id(ngap_gNB_instance_t *in ngap_gNB_amf_data_t *ngap_gNB_nnsf_select_amf_by_amf_setid(ngap_gNB_instance_t *instance_p, const ngap_rrc_establishment_cause_t cause, const plmn_id_t selected_plmn_identity, - uint8_t amf_setid); + uint16_t amf_setid); ngap_gNB_amf_data_t *ngap_gNB_nnsf_select_amf_by_guami(ngap_gNB_instance_t *instance_p, const ngap_rrc_establishment_cause_t cause, diff --git a/openair3/ocp-gtpu/gtp_itf.cpp b/openair3/ocp-gtpu/gtp_itf.cpp index c524129098..ed15d48f80 100644 --- a/openair3/ocp-gtpu/gtp_itf.cpp +++ b/openair3/ocp-gtpu/gtp_itf.cpp @@ -292,7 +292,7 @@ static int gtpv1uCreateAndSendMsg(gtpv1u_bearer_t *bearer, DevAssert(bearer->ip.ss_family == AF_INET); struct sockaddr_in *to = (struct sockaddr_in *)&bearer->ip; LOG_D(GTPU, - "Peer IP:" IPV4_ADDR " port:%u outgoing teid:%x\n", + "Peer IP:" IPV4_ADDR " port:%u outgoing TEID:0x%x\n", IPV4_ADDR_FORMAT(to->sin_addr.s_addr), htons(to->sin_port), bearer->teid_outgoing); @@ -332,7 +332,7 @@ static void _gtpv1uSendDirect(instance_t instance, } LOG_D(GTPU, - "[%ld] sending a packet to UE:RAB:teid %lx/%x/%x, len %lu, oldseq %d, oldnum %d\n", + "[%ld] sending a packet to UE:RAB:TEID %lx/%d/0x%x, len %lu, oldseq %d, oldnum %d\n", instance, ue_id, bearer_id, @@ -492,7 +492,7 @@ static void gtpv1uEndTunnel(instance_t instance, gtpv1u_enb_end_marker_req_t *re } LOG_D(GTPU, - "[%ld] sending a end packet packet to UE:RAB:teid %lx/%x/%x\n", + "[%ld] sending a end packet packet to UE:RAB:TEID %lx/%d/0x%x\n", instance, ue_id, bearer_id, @@ -641,7 +641,7 @@ void GtpuUpdateTunnelOutgoingAddressAndTeid(instance_t instance, struct sockaddr_in *sa4 = (struct sockaddr_in *)sockaddr; struct sockaddr_in6 *sa6 = (struct sockaddr_in6 *)sockaddr; LOG_I(GTPU, - "[%ld] UE ID %ld: Update tunnel TEID incoming %x outgoing %x to remote IPv4 %s, IPv6 %s, port %d\n", + "[%ld] UE ID %ld: Update tunnel TEID incoming 0x%x outgoing 0x%x to remote IPv4 %s, IPv6 %s, port %d\n", instance, ue_id, ptr2->second.teid_incoming, @@ -676,7 +676,7 @@ teid_t newGtpuCreateTunnel(instance_t instance, teid_t incoming_teid = gtpv1uNewTeid(); while (globGtp.te2ue_mapping.find(incoming_teid) != globGtp.te2ue_mapping.end()) { - LOG_W(GTPU, "[%ld] generated a random Teid that exists, re-generating (%x)\n", instance, incoming_teid); + LOG_W(GTPU, "[%ld] generated a random TEID that exists, re-generating (0x%x)\n", instance, incoming_teid); incoming_teid = gtpv1uNewTeid(); }; @@ -721,7 +721,7 @@ teid_t newGtpuCreateTunnel(instance_t instance, char ip4[INET_ADDRSTRLEN]; char ip6[INET6_ADDRSTRLEN]; LOG_I(GTPU, - "[%ld] UE ID %ld: Create tunnel TEID incoming %x outgoing %x to remote IPv4 %s, IPv6 %s, port %d\n", + "[%ld] UE ID %ld: Create tunnel TEID incoming 0x%x outgoing 0x%x to remote IPv4 %s, IPv6 %s, port %d\n", instance, ue_id, bearer.teid_incoming, @@ -825,7 +825,7 @@ int gtpv1u_create_ngu_tunnel(const instance_t instance, gtpCallbackSDAP callBackSDAP) { LOG_D(GTPU, - "[%ld] Start create tunnels for ue id %lu, num_tunnels %d, sgw_S1u_teid %x\n", + "[%ld] Start create tunnels for ue id %lu, num_tunnels %d, TEID 0x%x\n", instance, create_tunnel_req->ue_id, create_tunnel_req->num_tunnels, @@ -905,17 +905,17 @@ int newGtpuDeleteOneTunnel(instance_t instance, ue_id_t ue_id, int rb_id) } map::iterator rb_it = ue_it->second.bearers.find(rb_id); if (rb_it == ue_it->second.bearers.end()) { - LOG_E(GTPU, "%s() UE %ld has no bearer %d, available\n", __func__, ue_id, rb_id); + LOG_E(GTPU, "%s() UE %ld has no tunnel for bearer %d\n", __func__, ue_id, rb_id); pthread_mutex_unlock(&globGtp.gtp_lock); return !GTPNOK; } - int teid = rb_it->second.teid_incoming; + teid_t teid = rb_it->second.teid_incoming; globGtp.te2ue_mapping.erase(teid); ue_it->second.bearers.erase(rb_id); pthread_mutex_unlock(&globGtp.gtp_lock); - LOG_I(GTPU, "Deleted tunnel TEID %d (RB %d) for ue id %ld, remaining bearers:\n", teid, rb_id, ue_id); + LOG_I(GTPU, "Deleted tunnel TEID 0x%x for bearer %d of UE %ld, remaining tunnels:\n", teid, rb_id, ue_id); for (auto b : ue_it->second.bearers) - LOG_I(GTPU, "bearer %ld\n", b.first); + LOG_I(GTPU, "Bearer %ld\n", b.first); return !GTPNOK; } @@ -982,45 +982,12 @@ int gtpv1u_delete_all_s1u_tunnel(const instance_t instance, const rnti_t rnti) return newGtpuDeleteAllTunnels(instance, rnti); } -int newGtpuDeleteTunnels(instance_t instance, ue_id_t ue_id, int nbTunnels, int *pdusession_id) -{ - LOG_D(GTPU, "[%ld] Start delete tunnels for ue id %lu\n", instance, ue_id); - pthread_mutex_lock(&globGtp.gtp_lock); - getInstRetInt(compatInst(instance)); - getUeRetInt(inst, ue_id); - int nb = 0; - - for (int i = 0; i < nbTunnels; i++) { - auto ptr2 = ptrUe->second.bearers.find(pdusession_id[i]); - - if (ptr2 == ptrUe->second.bearers.end()) { - LOG_E(GTPU, "[%ld] GTP-U instance: delete of not existing tunnel UE ID:RAB: %ld/%x\n", instance, ue_id, pdusession_id[i]); - } else { - globGtp.te2ue_mapping.erase(ptr2->second.teid_incoming); - nb++; - } - } - - if (ptrUe->second.bearers.size() == 0) - // no tunnels on this ue id, erase the ue entry - inst->ue2te_mapping.erase(ptrUe); - - pthread_mutex_unlock(&globGtp.gtp_lock); - LOG_I(GTPU, "[%ld] Deleted all tunnels for ue id %lu (%d tunnels deleted)\n", instance, ue_id, nb); - return !GTPNOK; -} - int gtpv1u_delete_x2u_tunnel(const instance_t instanceP, const gtpv1u_enb_delete_tunnel_req_t *const req_pP) { LOG_E(GTPU, "x2 tunnel not implemented\n"); return 0; } -int gtpv1u_delete_ngu_tunnel(const instance_t instance, gtpv1u_gnb_delete_tunnel_req_t *req) -{ - return newGtpuDeleteTunnels(instance, req->ue_id, req->num_pdusession, req->pdusession_id); -} - static gtpv1u_bearer_t create_bearer(int socket, const struct sockaddr_in *addr, uint32_t teid, uint16_t seq) { gtpv1u_bearer_t bearer = {.sock_fd = socket, .teid_outgoing = teid, .seqNum = seq}; @@ -1043,7 +1010,7 @@ static int Gtpv1uHandleEchoReq(int h, uint8_t *msgBuf, uint32_t msgBufLen, const } uint16_t seq = ntohs(*(uint16_t *)(msgHdr + 1)); - LOG_D(GTPU, "[%d] Received a echo request, TEID: %d, seq: %hu\n", h, msgHdr->teid, seq); + LOG_D(GTPU, "[%d] Received a echo request, TEID: 0x%x, seq: %hu\n", h, msgHdr->teid, seq); uint8_t recovery[2] = {14, 0}; gtpv1u_bearer_t bearer = create_bearer(h, addr, ntohl(msgHdr->teid), seq); return gtpv1uCreateAndSendMsg(&bearer, @@ -1061,10 +1028,11 @@ static int Gtpv1uHandleError(int h, uint8_t *msgBuf, uint32_t msgBufLen, const s if (msgBufLen < sizeof(Gtpv1uError)) LOG_E(GTPU, "Received GTP error indication with truncated size %u (mini size: %lu)\n", msgBufLen,sizeof(Gtpv1uError)+4); Gtpv1uError *msg = ( Gtpv1uError *)msgBuf; - LOG_E(GTPU, "Received GTP error indication: \n" - " TEID %u (must be 0 from TS 29.281)\n" - " TV id for TEID %u (must be 16)\n" - " TEID in error %u (should be a TEID we sent)\n" + LOG_E(GTPU, + "Received GTP error indication: \n" + " TEID 0x%x (must be 0 from TS 29.281)\n" + " TV id for TEID 0x%x (must be 16)\n" + " TEID in error 0x%x (should be a TEID we sent)\n" " TV id for GTP addr %u (should be 133)\n" " len for addr of UPF %u (should be IPv4 or IPv6 len)" " (TS 29.281 Sec 7.3.1 Error Handling not implemented)\n", @@ -1103,7 +1071,7 @@ static int Gtpv1uHandleEndMarker(int h, uint8_t *msgBuf, uint32_t msgBufLen, con auto tunnel = globGtp.te2ue_mapping.find(ntohl(msgHdr->teid)); if (tunnel == globGtp.te2ue_mapping.end()) { - LOG_E(GTPU, "[%d] Received a incoming packet on unknown teid (%x) Dropping!\n", h, msgHdr->teid); + LOG_E(GTPU, "[%d] Received a incoming packet on unknown TEID (0x%x) Dropping!\n", h, msgHdr->teid); pthread_mutex_unlock(&globGtp.gtp_lock); return GTPNOK; } @@ -1132,7 +1100,7 @@ static int Gtpv1uHandleEndMarker(int h, uint8_t *msgBuf, uint32_t msgBufLen, con if (!tunnel->second.callBack(&ctxt, srb_flag, rb_id, mui, confirm, 0, NULL, mode, &sourceL2Id, &destinationL2Id)) LOG_E(GTPU, "[%d] down layer refused incoming packet\n", h); - LOG_D(GTPU, "[%d] Received END marker packet for: teid:%x\n", h, ntohl(msgHdr->teid)); + LOG_D(GTPU, "[%d] Received END marker packet for: TEID:0x%x\n", h, ntohl(msgHdr->teid)); return !GTPNOK; } @@ -1149,7 +1117,7 @@ static int Gtpv1uHandleGpdu(int h, uint8_t *msgBuf, uint32_t msgBufLen, const st auto tunnel = globGtp.te2ue_mapping.find(ntohl(msgHdr->teid)); if (tunnel == globGtp.te2ue_mapping.end()) { - LOG_E(GTPU, "[%d] Received a incoming packet on unknown teid (%x) Dropping!\n", h, ntohl(msgHdr->teid)); + LOG_E(GTPU, "[%d] Received a incoming packet on unknown TEID (0x%x) Dropping!\n", h, ntohl(msgHdr->teid)); pthread_mutex_unlock(&globGtp.gtp_lock); return GTPNOK; } @@ -1282,7 +1250,7 @@ static int Gtpv1uHandleGpdu(int h, uint8_t *msgBuf, uint32_t msgBufLen, const st 1); } - LOG_D(GTPU, "[%d] Received a %d bytes packet for: teid:%x\n", h, msgBufLen - offset, ntohl(msgHdr->teid)); + LOG_D(GTPU, "[%d] Received a %d bytes packet for: TEID:0x%x\n", h, msgBufLen - offset, ntohl(msgHdr->teid)); return !GTPNOK; } diff --git a/openair3/ocp-gtpu/gtp_itf.h b/openair3/ocp-gtpu/gtp_itf.h index c31f8c935e..9274cd52f2 100644 --- a/openair3/ocp-gtpu/gtp_itf.h +++ b/openair3/ocp-gtpu/gtp_itf.h @@ -100,9 +100,6 @@ typedef struct gtpv1u_gnb_delete_tunnel_req_s gtpv1u_gnb_delete_tunnel_req_t; gtpCallback callBack, gtpCallbackSDAP callBackSDAP); - int gtpv1u_delete_ngu_tunnel( const instance_t instance, - gtpv1u_gnb_delete_tunnel_req_t *req); - int gtpv1u_update_ue_id(const instance_t instanceP, ue_id_t old_ue_id, ue_id_t new_ue_id); // New API @@ -124,7 +121,6 @@ typedef struct gtpv1u_gnb_delete_tunnel_req_s gtpv1u_gnb_delete_tunnel_req_t; int newGtpuDeleteOneTunnel(instance_t instance, ue_id_t ue_id, int rb_id); int newGtpuDeleteAllTunnels(instance_t instance, ue_id_t ue_id); - int newGtpuDeleteTunnels(instance_t instance, ue_id_t ue_id, int nbTunnels, int *pdusession_id); void gtpv1uSendDirect(instance_t instance, ue_id_t ue_id, int bearer_id, uint8_t *buf, size_t len, bool seqNumFlag, bool npduNumFlag); void gtpv1uSendDirectWithNRUSeqNum(instance_t instance, diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-pnf.band78.rfsim.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-pnf.band78.rfsim.conf index 887ff6eced..08691c3b62 100644 --- a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-pnf.band78.rfsim.conf +++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-pnf.band78.rfsim.conf @@ -22,6 +22,7 @@ RUs = ({ att_tx = 0 att_rx = 0; bands = [78]; + sl_ahead = 2; max_pdschReferenceSignalPower = -27; max_rxgain = 125; });