diff --git a/ci-scripts/cls_oai_html.py b/ci-scripts/cls_oai_html.py index 478cbd1860..c90b01a338 100644 --- a/ci-scripts/cls_oai_html.py +++ b/ci-scripts/cls_oai_html.py @@ -224,7 +224,6 @@ class HTMLManagement(): self.htmlFile.write(' \n') self.htmlFile.write(' \n') self.htmlFile.close() - time.sleep(1) if passStatus: cmd = "sed -i -e 's/__STATE_" + self.htmlTabNames[0] + "__//' test_results.html" subprocess.run(cmd, shell=True) diff --git a/ci-scripts/cls_oaicitest.py b/ci-scripts/cls_oaicitest.py index 4d7cf0a6fd..53bdacaacc 100644 --- a/ci-scripts/cls_oaicitest.py +++ b/ci-scripts/cls_oaicitest.py @@ -213,7 +213,7 @@ def Iperf_analyzeV2UDP(server_filename, iperf_bitrate_threshold, iperf_packetlos pal_msg += f' (too high! >{iperf_packetloss_threshold}%)' return (result, f'{req_msg}\n{bir_msg}\n{brl_msg}\n{jit_msg}\n{pal_msg}') -def Custom_Command(HTML, node, command, command_fail): +def Custom_Command(HTML, node, command): logging.info(f"Executing custom command on {node}") cmd = cls_cmd.getConnection(node) ret = cmd.run(command) @@ -221,26 +221,20 @@ def Custom_Command(HTML, node, command, command_fail): logging.debug(f"Custom_Command: {command} on node: {node} - {'OK, command succeeded' if ret.returncode == 0 else f'Error, return code: {ret.returncode}'}") status = 'OK' message = [] - if ret.returncode != 0 and not command_fail: - message = [ret.stdout] - logging.warning(f'Custom_Command output: {message}') - status = 'Warning' - if ret.returncode != 0 and command_fail: + if ret.returncode != 0: message = [ret.stdout] logging.error(f'Custom_Command failed: output: {message}') status = 'KO' HTML.CreateHtmlTestRowQueue(command, status, message) return status == 'OK' or status == 'Warning' -def Custom_Script(HTML, node, script, command_fail): +def Custom_Script(HTML, node, script): logging.info(f"Executing custom script on {node}") ret = cls_cmd.runScript(node, script, 90) logging.debug(f"Custom_Script: {script} on node: {node} - return code {ret.returncode}, output:\n{ret.stdout}") status = 'OK' message = [ret.stdout] - if ret.returncode != 0 and not command_fail: - status = 'Warning' - if ret.returncode != 0 and command_fail: + if ret.returncode != 0: status = 'KO' HTML.CreateHtmlTestRowQueue(script, status, message) return status == 'OK' or status == 'Warning' diff --git a/ci-scripts/conf_files/gnb.sa.band254.u0.25prb.rfsim.ntn.conf b/ci-scripts/conf_files/gnb.sa.band254.u0.25prb.rfsim.ntn.conf index 3e7dd08474..fa1bcc20c8 100644 --- a/ci-scripts/conf_files/gnb.sa.band254.u0.25prb.rfsim.ntn.conf +++ b/ci-scripts/conf_files/gnb.sa.band254.u0.25prb.rfsim.ntn.conf @@ -149,6 +149,8 @@ gNBs = #ext2 #ntn_Config_r17 + # This can be of values {s5, s10, s15, s20, s25, s30, s35, s40, s45, s50, s55, s60, s120, s180, s240, s900} + ntn-UlSyncValidityDuration-r17 = 240; cellSpecificKoffset_r17 = 478; ta-Common-r17 = 58629666; # 238.74 ms positionX-r17 = 0; diff --git a/ci-scripts/main.py b/ci-scripts/main.py index 333d515858..18956ae28f 100644 --- a/ci-scripts/main.py +++ b/ci-scripts/main.py @@ -376,14 +376,12 @@ def ExecuteActionWithParam(action): # Change all execution targets to localhost node = 'localhost' command = test.findtext('command') - command_fail = test.findtext('command_fail') in ['True', 'true', 'Yes', 'yes'] - success = cls_oaicitest.Custom_Command(HTML, node, command, command_fail) + success = cls_oaicitest.Custom_Command(HTML, node, command) elif action == 'Custom_Script': node = test.findtext('node') script = test.findtext('script') - command_fail = test.findtext('command_fail') in ['True', 'true', 'Yes', 'yes'] - success = cls_oaicitest.Custom_Script(HTML, node, script, command_fail) + success = cls_oaicitest.Custom_Script(HTML, node, script) elif action == 'Pull_Cluster_Image': tag_prefix = test.findtext('tag_prefix') or "" @@ -626,6 +624,7 @@ elif re.match('^TesteNB$', mode, re.IGNORECASE) or re.match('^TestUE$', mode, re HTML.testCase_id=CiTestObj.testCase_id CiTestObj.desc = test.findtext('desc') always_exec = test.findtext('always_exec') in ['True', 'true', 'Yes', 'yes'] + may_fail = test.findtext('may_fail') in ['True', 'true', 'Yes', 'yes'] HTML.desc=CiTestObj.desc action = test.findtext('class') if (CheckClassValidity(xml_class_list, action, id) == False): @@ -639,7 +638,9 @@ elif re.match('^TesteNB$', mode, re.IGNORECASE) or re.match('^TestUE$', mode, re break try: test_succeeded = ExecuteActionWithParam(action) - if not test_succeeded: + if not test_succeeded and may_fail: + logging.warning(f"test ID {test_case_id} action {action} may or may not fail, proceeding despite error") + elif not test_succeeded: logging.error(f"test ID {test_case_id} action {action} failed ({test_succeeded}), skipping next tests") task_set_succeeded = False except Exception as e: diff --git a/ci-scripts/ran.py b/ci-scripts/ran.py index 6f58478476..f0f790ba2c 100644 --- a/ci-scripts/ran.py +++ b/ci-scripts/ran.py @@ -95,7 +95,6 @@ class RANManagement(): self.cmd_prefix = '' # prefix before {lte,nr}-softmodem self.node = '' self.command = '' - self.command_fail = False #----------------------------------------------------------- diff --git a/ci-scripts/tests/test-runner/test.xml b/ci-scripts/tests/test-runner/test.xml index d5efacfdae..cb54989301 100644 --- a/ci-scripts/tests/test-runner/test.xml +++ b/ci-scripts/tests/test-runner/test.xml @@ -27,6 +27,8 @@ wrench 000001 + 000011 + 000012 000002 000003 000004 @@ -38,7 +40,21 @@ This should succeed localhost true - yes + + + + Custom_Command + This may fail + true + localhost + false + + + + Custom_Command + This is still executed + localhost + true @@ -46,7 +62,6 @@ This should fail localhost false - yes @@ -54,7 +69,6 @@ This should be skipped localhost true - yes @@ -63,6 +77,5 @@ true localhost true - yes diff --git a/ci-scripts/xml_files/container_5g_f1_rfsim.xml b/ci-scripts/xml_files/container_5g_f1_rfsim.xml index b27b0b5701..3b783a9215 100644 --- a/ci-scripts/xml_files/container_5g_f1_rfsim.xml +++ b/ci-scripts/xml_files/container_5g_f1_rfsim.xml @@ -134,7 +134,6 @@ Simulate a DL radio channel with noise (3 dB) cacofonix echo channelmod modify 0 noise_power_dB 3 | nc --send-only 192.168.71.181 8091 - yes @@ -166,7 +165,6 @@ Trigger Reestablishment cacofonix echo ci force_reestab | nc 192.168.71.171 9090 | grep -E 'Reset RLC counters of UE RNTI [0-9a-f]{4} to trigger reestablishment' - yes @@ -185,7 +183,6 @@ Verify Reestablishment cacofonix echo ci get_reestab_count | nc 192.168.71.150 9090 | grep -E 'UE RNTI [0-9a-f]{4} reestab 1' - yes @@ -193,7 +190,6 @@ Simulate a disruption of DL radio channel (ploss 55) cacofonix echo channelmod modify 0 ploss 55 | nc 192.168.71.181 8091 - yes @@ -201,7 +197,6 @@ Get UE sync state (UE ID 0) cacofonix echo ciUE sync_state 0 | nc 192.168.71.181 8091 | grep -E UE_NOT_SYNC - yes @@ -209,7 +204,6 @@ Restoration of the original DL channel conditions (ploss 20) cacofonix echo channelmod modify 0 ploss 20 | nc 192.168.71.181 8091 - yes @@ -217,7 +211,6 @@ Get UE sync state (UE ID 0) cacofonix echo ciUE sync_state 0 | nc 192.168.71.181 8091 | grep -E UE_CONNECTED - yes @@ -225,7 +218,6 @@ Trigger Handover cacofonix echo ci trigger_f1_ho | nc 192.168.71.150 9090 - yes @@ -233,7 +225,6 @@ UE (1) connected to DU-PCI 0? cacofonix echo ci fetch_du_by_ue_id 1 | nc 192.168.71.150 9090 | grep "3584" - yes @@ -241,7 +232,6 @@ UE (1) connected to DU-PCI 1? cacofonix echo ci fetch_du_by_ue_id 1 | nc 192.168.71.150 9090 | grep "3585" - yes diff --git a/ci-scripts/xml_files/container_5g_rfsim.xml b/ci-scripts/xml_files/container_5g_rfsim.xml index f20820629b..80e4d189ff 100644 --- a/ci-scripts/xml_files/container_5g_rfsim.xml +++ b/ci-scripts/xml_files/container_5g_rfsim.xml @@ -242,7 +242,7 @@ Detach_UE - Detach OAI UE 2 to 10 + Detach OAI UE 3 to 10 rfsim5g_ue3 rfsim5g_ue4 rfsim5g_ue5 rfsim5g_ue6 rfsim5g_ue7 rfsim5g_ue8 rfsim5g_ue9 rfsim5g_ue10 cacofonix cacofonix cacofonix cacofonix cacofonix cacofonix cacofonix cacofonix diff --git a/ci-scripts/xml_files/container_5g_rfsim_24prb.xml b/ci-scripts/xml_files/container_5g_rfsim_24prb.xml index 5a59880b2f..91275a5f10 100644 --- a/ci-scripts/xml_files/container_5g_rfsim_24prb.xml +++ b/ci-scripts/xml_files/container_5g_rfsim_24prb.xml @@ -151,7 +151,6 @@ Force Msg3 C-RNTI RA cacofonix echo ciUE force_crnti_ra | nc 192.168.71.150 8091 - yes @@ -159,7 +158,6 @@ Force RRC_IDLE (UE ID 0) cacofonix echo ciUE force_RRC_IDLE | nc 192.168.71.150 8091 - yes diff --git a/ci-scripts/xml_files/container_5g_rfsim_sidelink.xml b/ci-scripts/xml_files/container_5g_rfsim_sidelink.xml index 133d960c3a..ac7e28f003 100644 --- a/ci-scripts/xml_files/container_5g_rfsim_sidelink.xml +++ b/ci-scripts/xml_files/container_5g_rfsim_sidelink.xml @@ -79,7 +79,6 @@ Check that UE synched cacofonix docker logs rfsim5g-oai-nr-ue-2 | grep -m 1 "PSBCH RX:OK" - yes diff --git a/ci-scripts/xml_files/container_5g_rfsim_tdd_dora.xml b/ci-scripts/xml_files/container_5g_rfsim_tdd_dora.xml index bf71fc98ab..34d46cc87d 100644 --- a/ci-scripts/xml_files/container_5g_rfsim_tdd_dora.xml +++ b/ci-scripts/xml_files/container_5g_rfsim_tdd_dora.xml @@ -108,14 +108,6 @@ 0 - - Custom_Command - true - Clean-Up any residual volume - cacofonix - docker volume rm 5g_rfsimulator_tdd_dora_rrc.config - - Clean_Test_Server_Images true diff --git a/ci-scripts/xml_files/container_nsa_b200_quectel.xml b/ci-scripts/xml_files/container_nsa_b200_quectel.xml index 035163f3db..17c8a9b14f 100644 --- a/ci-scripts/xml_files/container_nsa_b200_quectel.xml +++ b/ci-scripts/xml_files/container_nsa_b200_quectel.xml @@ -70,9 +70,9 @@ Custom_Command - Reset USRP + Reset USRP on nepes nepes - sudo -S /usr/lib/uhd/utils/b2xx_fx3_utils --reset-device + sudo -S /usr/local/lib/uhd/utils/b2xx_fx3_utils --reset-device diff --git a/ci-scripts/xml_files/container_sa_aw2s_asue.xml b/ci-scripts/xml_files/container_sa_aw2s_asue.xml index 7eb6411827..88ab941e31 100644 --- a/ci-scripts/xml_files/container_sa_aw2s_asue.xml +++ b/ci-scripts/xml_files/container_sa_aw2s_asue.xml @@ -182,7 +182,7 @@ Iperf - iperf (DL/3Mbps/UDP)(30 sec)(multi-ue profile) + iperf (DL/3Mbps/UDP)(30 sec) -u -b 45M -t 30 -R amarisoft_ue_1 amarisoft_ue_2 amarisoft_ue_3 amarisoft_ue_4 amarisoft_ue_5 amarisoft_ue_6 amarisoft_ue_7 amarisoft_ue_8 amarisoft_ue_9 amarisoft_ue_10 amarisoft_ue_11 amarisoft_ue_12 amarisoft_ue_13 amarisoft_ue_14 amarisoft_ue_15 25 @@ -193,7 +193,7 @@ Iperf - iperf (DL/TCP)(30 sec)(multi-ue profile) + iperf (DL/TCP)(30 sec) -t 30 -R amarisoft_ue_1 amarisoft_ue_2 amarisoft_ue_3 amarisoft_ue_4 amarisoft_ue_5 amarisoft_ue_6 amarisoft_ue_7 amarisoft_ue_8 amarisoft_ue_9 amarisoft_ue_10 amarisoft_ue_11 amarisoft_ue_12 amarisoft_ue_13 amarisoft_ue_14 amarisoft_ue_15 2 @@ -202,7 +202,7 @@ Iperf - iperf (UL/1Mbps/UDP)(30 sec)(multi-ue profile) + iperf (UL/1Mbps/UDP)(30 sec) -u -b 15M -t 30 amarisoft_ue_1 amarisoft_ue_2 amarisoft_ue_3 amarisoft_ue_4 amarisoft_ue_5 amarisoft_ue_6 amarisoft_ue_7 amarisoft_ue_8 amarisoft_ue_9 amarisoft_ue_10 amarisoft_ue_11 amarisoft_ue_12 amarisoft_ue_13 amarisoft_ue_14 amarisoft_ue_15 25 @@ -213,7 +213,7 @@ Iperf - iperf (UL/TCP)(30 sec)(multi-ue profile) + iperf (UL/TCP)(30 sec) -t 30 oc-cn5g amarisoft_ue_1 amarisoft_ue_2 amarisoft_ue_3 amarisoft_ue_4 amarisoft_ue_5 amarisoft_ue_6 amarisoft_ue_7 amarisoft_ue_8 amarisoft_ue_9 amarisoft_ue_10 amarisoft_ue_11 amarisoft_ue_12 amarisoft_ue_13 amarisoft_ue_14 amarisoft_ue_15 diff --git a/ci-scripts/xml_files/container_sa_aw2s_asue_2x2.xml b/ci-scripts/xml_files/container_sa_aw2s_asue_2x2.xml index 739534be21..ed4a219f55 100644 --- a/ci-scripts/xml_files/container_sa_aw2s_asue_2x2.xml +++ b/ci-scripts/xml_files/container_sa_aw2s_asue_2x2.xml @@ -179,7 +179,7 @@ Iperf - iperf (DL/4Mbps/UDP)(30 sec)(multi-ue profile) + iperf (DL/4Mbps/UDP)(30 sec) -u -b 60M -t 30 -R amarisoft_ue_1 amarisoft_ue_2 amarisoft_ue_3 amarisoft_ue_4 amarisoft_ue_5 amarisoft_ue_6 amarisoft_ue_7 amarisoft_ue_8 amarisoft_ue_9 amarisoft_ue_10 amarisoft_ue_11 amarisoft_ue_12 amarisoft_ue_13 amarisoft_ue_14 amarisoft_ue_15 25 @@ -190,7 +190,7 @@ Iperf - iperf (DL/TCP)(30 sec)(multi-ue profile) + iperf (DL/TCP)(30 sec) -t 30 -R amarisoft_ue_1 amarisoft_ue_2 amarisoft_ue_3 amarisoft_ue_4 amarisoft_ue_5 amarisoft_ue_6 amarisoft_ue_7 amarisoft_ue_8 amarisoft_ue_9 amarisoft_ue_10 amarisoft_ue_11 amarisoft_ue_12 amarisoft_ue_13 amarisoft_ue_14 amarisoft_ue_15 3.9 @@ -199,7 +199,7 @@ Iperf - iperf (UL/1.5Mbps/UDP)(30 sec)(multi-ue profile) + iperf (UL/1.5Mbps/UDP)(30 sec) -u -b 22.5M -t 30 amarisoft_ue_1 amarisoft_ue_2 amarisoft_ue_3 amarisoft_ue_4 amarisoft_ue_5 amarisoft_ue_6 amarisoft_ue_7 amarisoft_ue_8 amarisoft_ue_9 amarisoft_ue_10 amarisoft_ue_11 amarisoft_ue_12 amarisoft_ue_13 amarisoft_ue_14 amarisoft_ue_15 25 @@ -210,7 +210,7 @@ Iperf - iperf (UL/TCP)(30 sec)(multi-ue profile) + iperf (UL/TCP)(30 sec) -t 30 oc-cn5g amarisoft_ue_1 amarisoft_ue_2 amarisoft_ue_3 amarisoft_ue_4 amarisoft_ue_5 amarisoft_ue_6 amarisoft_ue_7 amarisoft_ue_8 amarisoft_ue_9 amarisoft_ue_10 amarisoft_ue_11 amarisoft_ue_12 amarisoft_ue_13 amarisoft_ue_14 amarisoft_ue_15 diff --git a/ci-scripts/xml_files/container_sa_b200_quectel.xml b/ci-scripts/xml_files/container_sa_b200_quectel.xml index 9f3559aff1..dacee9692f 100644 --- a/ci-scripts/xml_files/container_sa_b200_quectel.xml +++ b/ci-scripts/xml_files/container_sa_b200_quectel.xml @@ -200,14 +200,12 @@ Trigger Reestablishment ofqot echo ci force_reestab | nc -N 127.0.0.1 9090 | grep -E 'Reset RLC counters of UE RNTI [0-9a-f]{4} to trigger reestablishment' - yes Custom_Command Verify Reestablishment ofqot echo ci get_reestab_count | nc -N 127.0.0.1 9090 | grep -E 'UE RNTI [0-9a-f]{4} reestab 1' - yes diff --git a/ci-scripts/xml_files/container_sa_e1_b200_quectel.xml b/ci-scripts/xml_files/container_sa_e1_b200_quectel.xml index dcbcb9a45f..b9535e6ea4 100644 --- a/ci-scripts/xml_files/container_sa_e1_b200_quectel.xml +++ b/ci-scripts/xml_files/container_sa_e1_b200_quectel.xml @@ -188,14 +188,12 @@ Trigger Reestablishment (on DU) ofqot echo ci force_reestab | nc -N 127.0.0.1 9091 | grep -E 'Reset RLC counters of UE RNTI [0-9a-f]{4} to trigger reestablishment' - yes Custom_Command Verify Reestablishment (on CU) ofqot echo ci get_reestab_count | nc -N 127.0.0.1 9090 | grep -E 'UE RNTI [0-9a-f]{4} reestab 1' - yes diff --git a/ci-scripts/xml_files/container_sa_f1_b200_quectel.xml b/ci-scripts/xml_files/container_sa_f1_b200_quectel.xml index 9622b2cf13..fd935be551 100644 --- a/ci-scripts/xml_files/container_sa_f1_b200_quectel.xml +++ b/ci-scripts/xml_files/container_sa_f1_b200_quectel.xml @@ -233,14 +233,12 @@ Trigger Reestablishment (on DU) ofqot echo ci force_reestab | nc -N 127.0.0.1 9091 | grep -E 'Reset RLC counters of UE RNTI [0-9a-f]{4} to trigger reestablishment' - yes Custom_Command Verify Reestablishment (on CU) ofqot echo ci get_reestab_count | nc -N 127.0.0.1 9090 | grep -E 'UE RNTI [0-9a-f]{4} reestab 1' - yes diff --git a/ci-scripts/xml_files/container_sa_fhi72_metanoia_up2_2x2.xml b/ci-scripts/xml_files/container_sa_fhi72_metanoia_up2_2x2.xml index e71ec3e37c..742b09e3d8 100644 --- a/ci-scripts/xml_files/container_sa_fhi72_metanoia_up2_2x2.xml +++ b/ci-scripts/xml_files/container_sa_fhi72_metanoia_up2_2x2.xml @@ -49,7 +49,6 @@ Setup sriov and network interfaces Metanoia cacofonix - yes @@ -92,7 +91,7 @@ Iperf - iperf (DL/570Mbps/UDP)(30 sec)(multi-ue profile) + iperf (DL/570Mbps/UDP)(30 sec) -u -b 570M -t 30 -R up2-fhi72 20 @@ -103,7 +102,7 @@ Iperf - iperf (DL/TCP)(30 sec)(multi-ue profile) + iperf (DL/TCP)(30 sec) -t 30 -R up2-fhi72 80 @@ -112,7 +111,7 @@ Iperf - iperf (UL/100Mbps/UDP)(30 sec)(multi-ue profile) + iperf (UL/100Mbps/UDP)(30 sec) -u -b 100M -t 30 up2-fhi72 20 @@ -123,7 +122,7 @@ Iperf - iperf (UL/TCP)(30 sec)(multi-ue profile) + iperf (UL/TCP)(30 sec) -t 30 up2-fhi72 80 @@ -166,7 +165,6 @@ Set CPU to idle state, set kernel parameters to default values cacofonix - yes diff --git a/ci-scripts/xml_files/container_sa_fhi72_vvdn_up2.xml b/ci-scripts/xml_files/container_sa_fhi72_vvdn_up2.xml index 4afe8f1b12..1d7cd323e4 100644 --- a/ci-scripts/xml_files/container_sa_fhi72_vvdn_up2.xml +++ b/ci-scripts/xml_files/container_sa_fhi72_vvdn_up2.xml @@ -36,6 +36,7 @@ 100020 100030 100040 + 100011 103000 100002 130000 @@ -49,7 +50,6 @@ Setup sriov and network interfaces VVDN cacofonix - yes @@ -90,7 +90,7 @@ Iperf - iperf (DL/600Mbps/UDP)(30 sec)(multi-ue profile) + iperf (DL/600Mbps/UDP)(30 sec) -u -b 600M -t 30 -R up2-fhi72 20 @@ -99,9 +99,20 @@ oc-cn5g-20897 + + Iperf + Optional iperf (DL/700Mbps/UDP)(30 sec) + true + -u -b 700M -t 30 -R + up2-fhi72 + 10 + 95 + oc-cn5g-20897 + + Iperf - iperf (DL/TCP)(30 sec)(multi-ue profile) + iperf (DL/TCP)(30 sec) -t 30 -R up2-fhi72 40 @@ -110,7 +121,7 @@ Iperf - iperf (UL/80Mbps/UDP)(30 sec)(multi-ue profile) + iperf (UL/80Mbps/UDP)(30 sec) -u -b 80M -t 30 up2-fhi72 20 @@ -121,7 +132,7 @@ Iperf - iperf (UL/TCP)(30 sec)(multi-ue profile) + iperf (UL/TCP)(30 sec) -t 30 up2-fhi72 10 @@ -164,7 +175,6 @@ Set CPU to idle state, set kernel parameters to default values cacofonix - yes diff --git a/ci-scripts/xml_files/container_sa_sc_b200_quectel.xml b/ci-scripts/xml_files/container_sa_sc_b200_quectel.xml index 69201ebcc8..f116e97e24 100644 --- a/ci-scripts/xml_files/container_sa_sc_b200_quectel.xml +++ b/ci-scripts/xml_files/container_sa_sc_b200_quectel.xml @@ -194,14 +194,12 @@ Trigger Reestablishment ofqot echo ci force_reestab | nc -N 127.0.0.1 9090 | grep -E 'Reset RLC counters of UE RNTI [0-9a-f]{4} to trigger reestablishment' - yes Custom_Command Verify Reestablishment ofqot echo ci get_reestab_count | nc -N 127.0.0.1 9090 | grep -E 'UE RNTI [0-9a-f]{4} reestab 1' - yes diff --git a/common/platform_types.h b/common/platform_types.h index 8cbd502fda..e345288061 100644 --- a/common/platform_types.h +++ b/common/platform_types.h @@ -207,6 +207,16 @@ typedef struct nsa_msg_t { uint8_t msg_buffer[MAX_MESSAGE_SIZE]; } nsa_msg_t; +typedef enum nr_lcid_rb_type { NR_LCID_NONE = 0, NR_LCID_SRB = 1, NR_LCID_DRB = 2 } nr_lcid_rb_type; + +typedef struct nr_lcid_rb_t { + nr_lcid_rb_type type; + union { + int srb_id; + int drb_id; + } choice; +} nr_lcid_rb_t; + typedef struct transport_layer_addr_s { /** * Transport Layer Address as a bitstring: diff --git a/doc/RUNMODEM.md b/doc/RUNMODEM.md index f2e71390c7..ba2d48be28 100644 --- a/doc/RUNMODEM.md +++ b/doc/RUNMODEM.md @@ -231,6 +231,9 @@ Or by providing this the the command line parameters: The main parameters to cope with the large NTN propagation delay are cellSpecificKoffset, ta-Common, ta-CommonDrift and the ephemeris data (satellite position and velocity vectors). +The parameter `ntn-UlSyncValidityDuration-r17` indicates the maximum time duration from epochtime during which the UE can apply assistance information without having acquired new assistance information. i.e this enables UE to re-read SIB19 before timer with value ulSyncValidityDuration expires. The unit of the field is in seconds. Example values for GEO: 240s, MEO: 20s, LEO: 5s. +As epochtime is not implemented yet, UE starts the timer from the TTI where SIB19 is received with ntn-UlSyncValidityDuration-r17 IE. + The parameter `cellSpecificKoffset_r17` is the scheduling offset used for the timing relationships that are modified for NTN (see TS 38.213). The unit of the field Koffset is number of slots for a given subcarrier spacing of 15 kHz. diff --git a/docker/Dockerfile.base.ubuntu22 b/docker/Dockerfile.base.ubuntu22 index 60e2aad8ab..ba8707d4db 100644 --- a/docker/Dockerfile.base.ubuntu22 +++ b/docker/Dockerfile.base.ubuntu22 @@ -40,6 +40,7 @@ RUN apt-get update && \ DEBIAN_FRONTEND=noninteractive apt-get install --yes \ #gcc needed for build_oai build-essential \ + ccache \ psmisc \ git \ #use gcc-12 to avoid problems of default gcc-11 in FlexRIC @@ -52,15 +53,15 @@ RUN apt-get update && \ flex \ m4 \ # python3-pip for conf template generation - python3-pip && \ + python3-pip \ + wget && \ update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-12 100 --slave /usr/bin/g++ g++ /usr/bin/g++-12 && \ pip3 install --ignore-installed pyyaml # Add "Tini - A tiny but valid init for containers", https://github.com/krallin/tini # it will be copied into target containers, to print exit numbers and handle signals properly ENV TINI_VERSION=v0.19.0 -ADD https://github.com/krallin/tini/releases/download/${TINI_VERSION}/tini-${TARGETARCH} /tini -RUN chmod +x /tini +RUN wget https://github.com/krallin/tini/releases/download/${TINI_VERSION}/tini-${TARGETARCH} -O /tini && chmod +x /tini # In some network environments, GIT proxy is required RUN /bin/bash -c "if [[ -v NEEDED_GIT_PROXY ]]; then git config --global http.proxy $NEEDED_GIT_PROXY; fi" diff --git a/docker/Dockerfile.build.ubuntu22 b/docker/Dockerfile.build.ubuntu22 index a3c2417b33..c11946ecdb 100644 --- a/docker/Dockerfile.build.ubuntu22 +++ b/docker/Dockerfile.build.ubuntu22 @@ -36,7 +36,12 @@ WORKDIR /oai-ran COPY . . # build all targets so final targets can be created afterwards -RUN /bin/sh oaienv && \ +RUN \ + # Mount CCache cache direrctory + --mount=type=cache,target=/root/.cache/ccache/ \ + # Mount CPM package cache + --mount=type=cache,target=/root/.cache/cpm/ \ + /bin/sh oaienv && \ cd cmake_targets && \ mkdir -p log && \ ./build_oai -c --ninja \ @@ -54,7 +59,10 @@ RUN /bin/sh oaienv && \ ldd ran_build/build/*.so ## Build FlexRIC for SM Models -RUN mkdir -p openair2/E2AP/flexric/build && \ +RUN \ + # Mount CCache cache direrctory + --mount=type=cache,target=/root/.cache/ccache/ \ + mkdir -p openair2/E2AP/flexric/build && \ cd openair2/E2AP/flexric/build && \ cmake -GNinja -DCMAKE_BUILD_TYPE=Release \ -DKPM_VERSION=$KPM_VERSION \ diff --git a/nfapi/open-nFAPI/fapi/inc/nr_fapi.h b/nfapi/open-nFAPI/fapi/inc/nr_fapi.h index e8e645b8cf..ee405792d2 100644 --- a/nfapi/open-nFAPI/fapi/inc/nr_fapi.h +++ b/nfapi/open-nFAPI/fapi/inc/nr_fapi.h @@ -35,6 +35,9 @@ #include "debug.h" #define INDENTED_PRINTF(format, ...) printf("%*s" format, depth * 2, "", ##__VA_ARGS__) +#define INDENTED_GENERIC_PRINT(string, format, ...) INDENTED_PRINTF(string " = " format "\n", ##__VA_ARGS__) +#define INDENTED_TLV_PRINT(tlv_name, tlv) INDENTED_GENERIC_PRINT("(0x%04x) " tlv_name, "0x%02x", tlv.tl.tag, tlv.value) +#define INDENTED_TLV_FORMAT_PRINT(tlv_name, format, tlv) INDENTED_GENERIC_PRINT("(0x%04x) " tlv_name, format, tlv.tl.tag, tlv.value) #define EQ_TLV(_tlv_a, _tlv_b) \ do { \ diff --git a/nfapi/open-nFAPI/fapi/src/nr_fapi_p5.c b/nfapi/open-nFAPI/fapi/src/nr_fapi_p5.c index 281043b6d3..6bf2ff37ea 100644 --- a/nfapi/open-nFAPI/fapi/src/nr_fapi_p5.c +++ b/nfapi/open-nFAPI/fapi/src/nr_fapi_p5.c @@ -724,6 +724,53 @@ uint8_t unpack_nr_param_response(uint8_t **ppReadPackedMsg, uint8_t *end, void * &pNfapiMsg->vendor_extension)); } +static uint8_t pack_dbt_table_tlv_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_nr_dbt_tlv_ve_t *dbt_ve = (nfapi_nr_dbt_tlv_ve_t *)tlv; + nfapi_nr_dbt_pdu_t *dbt_config = &dbt_ve->value; + if (!( push16(dbt_config->num_dig_beams, ppWritePackedMsg, end) && push16(dbt_config->num_txrus, ppWritePackedMsg, end) )) { + return 0; + } + for (int i = 0; i< dbt_config->num_dig_beams; i++) { + const nfapi_nr_dig_beam_t *dig_beam = &dbt_config->dig_beam_list[i]; + if (!(push16(dig_beam->beam_idx, ppWritePackedMsg, end))) { + return 0; + } + for (int k = 0; k< dbt_config->num_txrus; k++) { + const nfapi_nr_txru_t *tx_ru = &dig_beam->txru_list[k]; + if (!(push16(tx_ru->dig_beam_weight_Re, ppWritePackedMsg, end) && push16(tx_ru->dig_beam_weight_Im, ppWritePackedMsg, end))) { + return 0; + } + } + } + return 1; +} + +static uint8_t pack_pm_table_tlv_value(void *tlv, uint8_t **ppWritePackedMsg, uint8_t *end) +{ + nfapi_nr_pm_tlv_ve_t *pm_ve = (nfapi_nr_pm_tlv_ve_t *)tlv; + nfapi_nr_pm_list_t *pmi_list = &pm_ve->value; + if (!( push16(pmi_list->num_pm_idx, ppWritePackedMsg, end) )) { + return 0; + } + for (int i = 0; i< pmi_list->num_pm_idx; i++) { + const nfapi_nr_pm_pdu_t *pm_pdu = &pmi_list->pmi_pdu[i]; + if (!(push16(pm_pdu->pm_idx, ppWritePackedMsg, end) && push16(pm_pdu->numLayers, ppWritePackedMsg, end) + && push16(pm_pdu->num_ant_ports, ppWritePackedMsg, end))) { + return 0; + } + for (int k = 0; k < pm_pdu->numLayers; k++) { + for (int j = 0; j < pm_pdu->num_ant_ports; j++) { + const nfapi_nr_pm_weights_t *pm_weight = &pm_pdu->weights[k][j]; + if (!(push16(pm_weight->precoder_weight_Re, ppWritePackedMsg, end) && push16(pm_weight->precoder_weight_Im, ppWritePackedMsg, end))) { + return 0; + } + } + } + } + return 1; +} + uint8_t pack_nr_config_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t *config) { uint8_t *pNumTLVFields = (uint8_t *)*ppWritePackedMsg; @@ -1044,11 +1091,19 @@ uint8_t pack_nr_config_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *e // END Measurement Config // START Digital Beam Table (DBT) PDU - // Struct in nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface_scf.h nfapi_nr_dbt_pdu_t, currently unused + if (pNfapiMsg->dbt_config.num_dig_beams != 0) { + nfapi_nr_dbt_tlv_ve_t dbt_tlv = {.tl.tag = NFAPI_NR_CONFIG_BEAMFORMING_TABLE_TAG, .value = pNfapiMsg->dbt_config}; + pack_nr_tlv(NFAPI_NR_CONFIG_BEAMFORMING_TABLE_TAG, &dbt_tlv, ppWritePackedMsg, end, &pack_dbt_table_tlv_value); + numTLVs++; + } // END Digital Beam Table (DBT) PDU // START Precoding Matrix (PM) PDU - // Struct in nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface_scf.h nfapi_nr_pm_pdu_t, currently unused, tag to use for AERIAL + if (pNfapiMsg->pmi_list.num_pm_idx != 0) { + nfapi_nr_pm_tlv_ve_t pm_tlv = {.tl.tag = NFAPI_NR_CONFIG_PRECODING_TABLE_V6_TAG, .value = pNfapiMsg->pmi_list}; + pack_nr_tlv(NFAPI_NR_CONFIG_PRECODING_TABLE_V6_TAG, &pm_tlv, ppWritePackedMsg, end, &pack_pm_table_tlv_value); + numTLVs++; + } // is 0xA011 END Precoding Matrix (PM) PDU #ifndef ENABLE_AERIAL // START nFAPI TLVs included in CONFIG.request for IDLE and CONFIGURED states @@ -1156,6 +1211,62 @@ uint8_t pack_nr_config_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *e return retval; } +static uint8_t unpack_dbt_table_tlv_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_nr_dbt_pdu_t *dbt_config = (nfapi_nr_dbt_pdu_t *)tlv; + if (!(pull16(ppReadPackedMsg, &dbt_config->num_dig_beams, end) && pull16(ppReadPackedMsg, &dbt_config->num_txrus, end))) { + return 0; + } + if (dbt_config->num_dig_beams > 0) { + dbt_config->dig_beam_list = calloc(dbt_config->num_dig_beams, sizeof(*dbt_config->dig_beam_list)); + } + for (int i = 0; i < dbt_config->num_dig_beams; i++) { + nfapi_nr_dig_beam_t *dig_beam = &dbt_config->dig_beam_list[i]; + if (!(pull16(ppReadPackedMsg, &dig_beam->beam_idx, end))) { + return 0; + } + if (dbt_config->num_txrus > 0) { + dig_beam->txru_list = calloc(dbt_config->num_txrus, sizeof(*dig_beam->txru_list)); + } + for (int k = 0; k < dbt_config->num_txrus; k++) { + nfapi_nr_txru_t *tx_ru = &dig_beam->txru_list[k]; + if (!(pull16(ppReadPackedMsg, &tx_ru->dig_beam_weight_Re, end) && pull16(ppReadPackedMsg, &tx_ru->dig_beam_weight_Im, end))) { + return 0; + } + } + } + return 1; +} + +static uint8_t unpack_pm_table_tlv_value(void *tlv, uint8_t **ppReadPackedMsg, uint8_t *end) +{ + nfapi_nr_pm_list_t *pm_list = (nfapi_nr_pm_list_t *)tlv; + if (!(pull16(ppReadPackedMsg, &pm_list->num_pm_idx, end))) { + return 0; + } + if (pm_list->num_pm_idx > 0) { + pm_list->pmi_pdu = calloc(pm_list->num_pm_idx, sizeof(*pm_list->pmi_pdu)); + } + for (int i = 0; i < pm_list->num_pm_idx; i++) { + nfapi_nr_pm_pdu_t *pm_pdu = &pm_list->pmi_pdu[i]; + if (!(pull16(ppReadPackedMsg, &pm_pdu->pm_idx, end) && pull16(ppReadPackedMsg, &pm_pdu->numLayers, end) + && pull16(ppReadPackedMsg, &pm_pdu->num_ant_ports, end))) { + return 0; + } + AssertFatal(pm_pdu->numLayers <= 4 && pm_pdu->num_ant_ports <= 4, "Precoding matrix size limited to 4X4 for the time being\n"); + for (int k = 0; k < pm_pdu->numLayers; k++) { + for (int j = 0; j < pm_pdu->num_ant_ports; j++) { + nfapi_nr_pm_weights_t *pm_weight = &pm_pdu->weights[k][j]; + if (!(pulls16(ppReadPackedMsg, &pm_weight->precoder_weight_Re, end) + && pulls16(ppReadPackedMsg, &pm_weight->precoder_weight_Im, end))) { + return 0; + } + } + } + } + return 1; +} + uint8_t unpack_nr_config_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *msg, nfapi_p4_p5_codec_config_t *config) { // Helper vars for indexed TLVs @@ -1221,6 +1332,8 @@ uint8_t unpack_nr_config_request(uint8_t **ppReadPackedMsg, uint8_t *end, void * {NFAPI_NR_FAPI_TOTAL_NUM_BEAMS_VENDOR_EXTENSION_TAG, &(pNfapiMsg->analog_beamforming_ve.total_num_beams_vendor_ext), &unpack_uint8_tlv_value}, {NFAPI_NR_FAPI_ANALOG_BEAM_VENDOR_EXTENSION_TAG, NULL, &unpack_uint8_tlv_value}, {NFAPI_NR_CONFIG_RSSI_MEASUREMENT_TAG, &(pNfapiMsg->measurement_config.rssi_measurement), &unpack_uint8_tlv_value}, + {NFAPI_NR_CONFIG_BEAMFORMING_TABLE_TAG, NULL, &unpack_dbt_table_tlv_value}, + {NFAPI_NR_CONFIG_PRECODING_TABLE_V6_TAG, NULL, &unpack_pm_table_tlv_value}, {NFAPI_NR_NFAPI_P7_VNF_ADDRESS_IPV4_TAG, &(pNfapiMsg->nfapi_config.p7_vnf_address_ipv4), &unpack_ipv4_address_value}, {NFAPI_NR_NFAPI_P7_VNF_ADDRESS_IPV6_TAG, &(pNfapiMsg->nfapi_config.p7_vnf_address_ipv6), &unpack_ipv6_address_value}, {NFAPI_NR_NFAPI_P7_VNF_PORT_TAG, &(pNfapiMsg->nfapi_config.p7_vnf_port), &unpack_uint16_tlv_value}, @@ -1268,6 +1381,14 @@ uint8_t unpack_nr_config_request(uint8_t **ppReadPackedMsg, uint8_t *end, void * result = (*unpack_fns[idx].unpack_func)(&pNfapiMsg->analog_beamforming_ve.analog_beam_list[beam_ve_idx], ppReadPackedMsg, end); beam_ve_idx ++; break; + case NFAPI_NR_CONFIG_BEAMFORMING_TABLE_TAG: + unpack_fns[idx].tlv = &generic_tl; + result = (*unpack_fns[idx].unpack_func)(&pNfapiMsg->dbt_config, ppReadPackedMsg, end); + break; + case NFAPI_NR_CONFIG_PRECODING_TABLE_V6_TAG: + unpack_fns[idx].tlv = &generic_tl; + result = (*unpack_fns[idx].unpack_func)(&pNfapiMsg->pmi_list, ppReadPackedMsg, end); + break; case NFAPI_NR_CONFIG_NUM_PRACH_FD_OCCASIONS_TAG: pNfapiMsg->prach_config.num_prach_fd_occasions.tl.tag = generic_tl.tag; pNfapiMsg->prach_config.num_prach_fd_occasions.tl.length = generic_tl.length; diff --git a/nfapi/open-nFAPI/fapi/src/nr_fapi_p5_utils.c b/nfapi/open-nFAPI/fapi/src/nr_fapi_p5_utils.c index 1b5e3f0ad8..4c3f32ef27 100644 --- a/nfapi/open-nFAPI/fapi/src/nr_fapi_p5_utils.c +++ b/nfapi/open-nFAPI/fapi/src/nr_fapi_p5_utils.c @@ -259,6 +259,40 @@ bool eq_config_request(const nfapi_nr_config_request_scf_t *unpacked_req, const EQ_TLV(unpacked_req->measurement_config.rssi_measurement, req->measurement_config.rssi_measurement); + EQ(unpacked_req->dbt_config.num_dig_beams, req->dbt_config.num_dig_beams); + + EQ(unpacked_req->dbt_config.num_txrus, req->dbt_config.num_txrus); + + for (int i = 0; i < req->dbt_config.num_dig_beams; i++) { + const nfapi_nr_dig_beam_t *unpacked_dig_beam = &unpacked_req->dbt_config.dig_beam_list[i]; + const nfapi_nr_dig_beam_t *req_dig_beam = &req->dbt_config.dig_beam_list[i]; + EQ(unpacked_dig_beam->beam_idx, req_dig_beam->beam_idx); + for (int k = 0; k < req->dbt_config.num_txrus; ++k) { + const nfapi_nr_txru_t *unpacked_tx_ru = &unpacked_dig_beam->txru_list[k]; + const nfapi_nr_txru_t *req_tx_ru = &req_dig_beam->txru_list[k]; + EQ(unpacked_tx_ru->dig_beam_weight_Re, req_tx_ru->dig_beam_weight_Re); + EQ(unpacked_tx_ru->dig_beam_weight_Im, req_tx_ru->dig_beam_weight_Im); + } + } + + EQ(unpacked_req->pmi_list.num_pm_idx, req->pmi_list.num_pm_idx); + + for (int i = 0; i < req->pmi_list.num_pm_idx; i++) { + const nfapi_nr_pm_pdu_t *req_pmi_pdu = &req->pmi_list.pmi_pdu[i]; + const nfapi_nr_pm_pdu_t *unpacked_pmi_pdu = &unpacked_req->pmi_list.pmi_pdu[i]; + EQ(unpacked_pmi_pdu->pm_idx, req_pmi_pdu->pm_idx); + EQ(unpacked_pmi_pdu->numLayers, req_pmi_pdu->numLayers); + EQ(unpacked_pmi_pdu->num_ant_ports, req_pmi_pdu->num_ant_ports); + for (int j = 0; j < req_pmi_pdu->num_ant_ports; ++j) { + for (int k = 0; k < req_pmi_pdu->num_ant_ports; ++k) { + const nfapi_nr_pm_weights_t* req_pm_weight = &req_pmi_pdu->weights[j][k]; + const nfapi_nr_pm_weights_t* unpacked_pm_weight = &unpacked_pmi_pdu->weights[j][k]; + EQ(unpacked_pm_weight->precoder_weight_Re, req_pm_weight->precoder_weight_Re); + EQ(unpacked_pm_weight->precoder_weight_Im, req_pm_weight->precoder_weight_Im); + } + } + } + EQ(unpacked_req->nfapi_config.p7_vnf_address_ipv4.tl.tag, req->nfapi_config.p7_vnf_address_ipv4.tl.tag); for (int i = 0; i < NFAPI_IPV4_ADDRESS_LENGTH; ++i) { EQ(unpacked_req->nfapi_config.p7_vnf_address_ipv4.address[i], req->nfapi_config.p7_vnf_address_ipv4.address[i]); @@ -391,27 +425,20 @@ bool eq_error_indication(const nfapi_nr_error_indication_scf_t *unpacked_req, co void free_param_request(nfapi_nr_param_request_scf_t *msg) { - if (msg->vendor_extension) { - free(msg->vendor_extension); - } + free(msg->vendor_extension); } void free_param_response(nfapi_nr_param_response_scf_t *msg) { - if (msg->vendor_extension) { - free(msg->vendor_extension); - } + free(msg->vendor_extension); + + free(msg->cell_param.config_tlvs_to_report_list); - if (msg->cell_param.config_tlvs_to_report_list) { - free(msg->cell_param.config_tlvs_to_report_list); - } } void free_config_request(nfapi_nr_config_request_scf_t *msg) { - if (msg->vendor_extension) { - free(msg->vendor_extension); - } + free(msg->vendor_extension); if (msg->prach_config.num_prach_fd_occasions_list) { for (int i = 0; i < msg->prach_config.num_prach_fd_occasions.value; i++) { @@ -430,10 +457,14 @@ void free_config_request(nfapi_nr_config_request_scf_t *msg) free(msg->tdd_table.max_tdd_periodicity_list); } - if (msg->pmi_list.pmi_pdu) { - free(msg->pmi_list.pmi_pdu); + for (int i = 0; i < msg->dbt_config.num_dig_beams; i++) { + free(msg->dbt_config.dig_beam_list[i].txru_list); } + free(msg->dbt_config.dig_beam_list); + + free(msg->pmi_list.pmi_pdu); + if (msg->analog_beamforming_ve.analog_beam_list) { free(msg->analog_beamforming_ve.analog_beam_list); } @@ -441,60 +472,40 @@ void free_config_request(nfapi_nr_config_request_scf_t *msg) void free_config_response(nfapi_nr_config_response_scf_t *msg) { - if (msg->vendor_extension) { - free(msg->vendor_extension); - } + free(msg->vendor_extension); - if (msg->invalid_tlvs_list) { - free(msg->invalid_tlvs_list); - } + free(msg->invalid_tlvs_list); - if (msg->invalid_tlvs_configured_in_idle_list) { - free(msg->invalid_tlvs_configured_in_idle_list); - } + free(msg->invalid_tlvs_configured_in_idle_list); - if (msg->invalid_tlvs_configured_in_running_list) { - free(msg->invalid_tlvs_configured_in_running_list); - } + free(msg->invalid_tlvs_configured_in_running_list); - if (msg->missing_tlvs_list) { - free(msg->missing_tlvs_list); - } + free(msg->missing_tlvs_list); } void free_start_request(nfapi_nr_start_request_scf_t *msg) { - if (msg->vendor_extension) { - free(msg->vendor_extension); - } + free(msg->vendor_extension); } void free_start_response(nfapi_nr_start_response_scf_t *msg) { - if (msg->vendor_extension) { - free(msg->vendor_extension); - } + free(msg->vendor_extension); } void free_stop_request(nfapi_nr_stop_request_scf_t *msg) { - if (msg->vendor_extension) { - free(msg->vendor_extension); - } + free(msg->vendor_extension); } void free_stop_indication(nfapi_nr_stop_indication_scf_t *msg) { - if (msg->vendor_extension) { - free(msg->vendor_extension); - } + free(msg->vendor_extension); } void free_error_indication(nfapi_nr_error_indication_scf_t *msg) { - if (msg->vendor_extension) { - free(msg->vendor_extension); - } + free(msg->vendor_extension); } void copy_param_request(const nfapi_nr_param_request_scf_t *src, nfapi_nr_param_request_scf_t *dst) @@ -810,6 +821,42 @@ void copy_config_request(const nfapi_nr_config_request_scf_t *src, nfapi_nr_conf COPY_TLV(dst->measurement_config.rssi_measurement, src->measurement_config.rssi_measurement); + dst->dbt_config.num_dig_beams = src->dbt_config.num_dig_beams; + dst->dbt_config.num_txrus = src->dbt_config.num_txrus; + dst->dbt_config.dig_beam_list = calloc(dst->dbt_config.num_dig_beams, sizeof(*dst->dbt_config.dig_beam_list)); + for (int i = 0; i < dst->dbt_config.num_dig_beams; i++) { + nfapi_nr_dig_beam_t *dst_dig_beam = &dst->dbt_config.dig_beam_list[i]; + const nfapi_nr_dig_beam_t *src_dig_beam = &src->dbt_config.dig_beam_list[i]; + dst_dig_beam->beam_idx = src_dig_beam->beam_idx; + dst_dig_beam->txru_list = calloc(dst->dbt_config.num_txrus , sizeof(*dst_dig_beam->txru_list )); + for (int k = 0; k < dst->dbt_config.num_txrus; ++k) { + nfapi_nr_txru_t *dst_tx_ru = &dst_dig_beam->txru_list[k]; + const nfapi_nr_txru_t *src_tx_ru = &src_dig_beam->txru_list[k]; + dst_tx_ru->dig_beam_weight_Re = src_tx_ru->dig_beam_weight_Re; + dst_tx_ru->dig_beam_weight_Im = src_tx_ru->dig_beam_weight_Im; + } + } + + dst->pmi_list.num_pm_idx = src->pmi_list.num_pm_idx; + if (dst->pmi_list.num_pm_idx > 0) { + dst->pmi_list.pmi_pdu = calloc(dst->pmi_list.num_pm_idx , sizeof(*dst->pmi_list.pmi_pdu)); + for (int i = 0; i < dst->pmi_list.num_pm_idx; i++) { + nfapi_nr_pm_pdu_t * dst_pmi_pdu = &dst->pmi_list.pmi_pdu[i]; + const nfapi_nr_pm_pdu_t * src_pmi_pdu = &src->pmi_list.pmi_pdu[i]; + dst_pmi_pdu->pm_idx = src_pmi_pdu->pm_idx; + dst_pmi_pdu->numLayers = src_pmi_pdu->numLayers; + dst_pmi_pdu->num_ant_ports = src_pmi_pdu->num_ant_ports; + for (int j = 0; j < dst_pmi_pdu->numLayers; ++j) { + for (int k = 0; k < dst_pmi_pdu->num_ant_ports; ++k) { + nfapi_nr_pm_weights_t* dst_pm_weight = &dst_pmi_pdu->weights[j][k]; + const nfapi_nr_pm_weights_t* src_pm_weight = &src_pmi_pdu->weights[j][k]; + dst_pm_weight->precoder_weight_Re = src_pm_weight->precoder_weight_Re; + dst_pm_weight->precoder_weight_Im = src_pm_weight->precoder_weight_Im; + } + } + } + } + COPY_TL(dst->nfapi_config.p7_vnf_address_ipv4.tl, src->nfapi_config.p7_vnf_address_ipv4.tl); memcpy(dst->nfapi_config.p7_vnf_address_ipv4.address, src->nfapi_config.p7_vnf_address_ipv4.address, @@ -986,22 +1033,382 @@ void dump_param_request(const nfapi_nr_param_request_scf_t *msg) void dump_param_response(const nfapi_nr_param_response_scf_t *msg) { int depth = 0; - dump_p5_message_header(&msg->header,depth); + dump_p5_message_header(&msg->header, depth); depth++; INDENTED_PRINTF("Error Code = 0x%02x\n", msg->error_code); INDENTED_PRINTF("Number of TLVs = 0x%02x\n", msg->num_tlv); /* dump all TLVs from each table */ + /* Cell Param */ + const nfapi_nr_cell_param_t *cell_param = &msg->cell_param; + depth++; + INDENTED_TLV_PRINT("Release Capability", cell_param->release_capability); + INDENTED_TLV_PRINT("PHY State", cell_param->phy_state); + INDENTED_TLV_PRINT("Skip Blank Dl Config", cell_param->skip_blank_dl_config); + INDENTED_TLV_PRINT("Skip Blank UL Config", cell_param->skip_blank_ul_config); + INDENTED_TLV_PRINT("NumConfigTLVsToReport", cell_param->num_config_tlvs_to_report); + depth++; + for (int i = 0; i < cell_param->num_config_tlvs_to_report.value; i++) { + const nfapi_uint8_tlv_t *reportedTLV = &cell_param->config_tlvs_to_report_list[i]; + INDENTED_PRINTF("(0x%04x) Reported CONFIG TLV #%d = 0x%02x\n", reportedTLV->tl.tag, i + 1, reportedTLV->value); + } + depth--; + /* Carrier Param */ + const nfapi_nr_carrier_param_t *carrier_param = &msg->carrier_param; + INDENTED_TLV_PRINT("Cyclic Prefix", carrier_param->cyclic_prefix); + INDENTED_TLV_PRINT("Supported SCS DL", carrier_param->supported_subcarrier_spacings_dl); + INDENTED_TLV_PRINT("Supported BW DL", carrier_param->supported_bandwidth_dl); + INDENTED_TLV_PRINT("Supported SCS UL", carrier_param->supported_subcarrier_spacings_ul); + INDENTED_TLV_PRINT("Supported BW UL", carrier_param->supported_bandwidth_ul); + /* PDCCH Param */ + const nfapi_nr_pdcch_param_t *pdcch_param = &msg->pdcch_param; + INDENTED_TLV_PRINT("CCE Mapping Type", pdcch_param->cce_mapping_type); + INDENTED_TLV_PRINT("CSet Outside First 3 OFDM Symbols of Slot", pdcch_param->coreset_outside_first_3_of_ofdm_syms_of_slot); + INDENTED_TLV_PRINT("Precoder Granularity Coreset", pdcch_param->coreset_precoder_granularity_coreset); + INDENTED_TLV_PRINT("PDCCH Mu MIMO", pdcch_param->pdcch_mu_mimo); + INDENTED_TLV_PRINT("PDCCH Precoder Cycling", pdcch_param->pdcch_precoder_cycling); + INDENTED_TLV_PRINT("Max PDCCH per Slot", pdcch_param->max_pdcch_per_slot); + /* PUCHH Params */ + const nfapi_nr_pucch_param_t *pucch_param = &msg->pucch_param; + INDENTED_TLV_PRINT("PUCCH Formats", pucch_param->pucch_formats); + INDENTED_TLV_PRINT("Max PUCCH per Slot", pucch_param->max_pucchs_per_slot); + /* PDSCH Params */ + const nfapi_nr_pdsch_param_t *pdsch_param = &msg->pdsch_param; + INDENTED_TLV_PRINT("PDSCH Mapping Type", pdsch_param->pdsch_mapping_type); + INDENTED_TLV_PRINT("PDSCH Allocation Types", pdsch_param->pdsch_allocation_types); + INDENTED_TLV_PRINT("PDSCH VRB to PRB Mapping", pdsch_param->pdsch_vrb_to_prb_mapping); + INDENTED_TLV_PRINT("PDSCH CBG", pdsch_param->pdsch_cbg); + INDENTED_TLV_PRINT("PDSCH DMRS Config Types", pdsch_param->pdsch_dmrs_config_types); + INDENTED_TLV_PRINT("PDSCH DMRS Max Length", pdsch_param->pdsch_dmrs_max_length); + INDENTED_TLV_PRINT("PDSCH DMRS Additional Position", pdsch_param->pdsch_dmrs_additional_pos); + INDENTED_TLV_PRINT("Max PDSCH TBs per Slot", pdsch_param->max_pdsch_tbs_per_slot); + INDENTED_TLV_PRINT("Max number MIMO Layers PDSCH", pdsch_param->max_number_mimo_layers_pdsch); + INDENTED_TLV_PRINT("Supported Max Modulation Order DL", pdsch_param->supported_max_modulation_order_dl); + INDENTED_TLV_PRINT("Max Mu MIMO Users DL", pdsch_param->max_mu_mimo_users_dl); + INDENTED_TLV_PRINT("PDSCH Data in DMRS Symbols", pdsch_param->pdsch_data_in_dmrs_symbols); + INDENTED_TLV_PRINT("Preemption Support", pdsch_param->premption_support); + INDENTED_TLV_PRINT("PDSCH Non Slot Support", pdsch_param->pdsch_non_slot_support); + /* PUSCH Params */ + const nfapi_nr_pusch_param_t *pusch_param = &msg->pusch_param; + INDENTED_TLV_PRINT("UCI Mux ULSCH in PUSCH", pusch_param->uci_mux_ulsch_in_pusch); + INDENTED_TLV_PRINT("UCI Only PUSCH", pusch_param->uci_only_pusch); + INDENTED_TLV_PRINT("PUSCH Frequency Hopping", pusch_param->pusch_frequency_hopping); + INDENTED_TLV_PRINT("PUSCH DMRS Config Types", pusch_param->pusch_dmrs_config_types); + INDENTED_TLV_PRINT("PUSCH DMRS Max Len", pusch_param->pusch_dmrs_max_len); + INDENTED_TLV_PRINT("PUSCH DMRS Additional Pos", pusch_param->pusch_dmrs_additional_pos); + INDENTED_TLV_PRINT("PUSCH CBG", pusch_param->pusch_cbg); + INDENTED_TLV_PRINT("PUSCH Mapping Type", pusch_param->pusch_mapping_type); + INDENTED_TLV_PRINT("PUSCH Allocation Types", pusch_param->pusch_allocation_types); + INDENTED_TLV_PRINT("PUSCH VRB to PRB Mapping", pusch_param->pusch_vrb_to_prb_mapping); + INDENTED_TLV_PRINT("PUSCH Max PTRS Ports", pusch_param->pusch_max_ptrs_ports); + INDENTED_TLV_PRINT("Max PUSCH TBs per Slot", pusch_param->max_pduschs_tbs_per_slot); + INDENTED_TLV_PRINT("Max Number MIMO Layers non CB PUSCH", pusch_param->max_number_mimo_layers_non_cb_pusch); + INDENTED_TLV_PRINT("Supported Modulation Order UL", pusch_param->supported_modulation_order_ul); + INDENTED_TLV_PRINT("Max MU MIMO Users UL", pusch_param->max_mu_mimo_users_ul); + INDENTED_TLV_PRINT("DTFS OFDM Support", pusch_param->dfts_ofdm_support); + INDENTED_TLV_PRINT("PUSCH Aggregation Factor", pusch_param->pusch_aggregation_factor); + /* PRACH Params */ + const nfapi_nr_prach_param_t *prach_param = &msg->prach_param; + INDENTED_TLV_PRINT("PRACH Long Formats", prach_param->prach_long_formats); + INDENTED_TLV_PRINT("PRACH Short Formats", prach_param->prach_short_formats); + INDENTED_TLV_PRINT("PRACH Restricted Sets", prach_param->prach_restricted_sets); + INDENTED_TLV_PRINT("Max PRACH Occasions in a Slot", prach_param->max_prach_fd_occasions_in_a_slot); + /* Measurement Params */ + const nfapi_nr_measurement_param_t *measurement_param = &msg->measurement_param; + INDENTED_TLV_PRINT("RSSI Measurement Support", measurement_param->rssi_measurement_support); + /* nFAPI Config */ + const nfapi_nr_nfapi_t *nfapi_config = &msg->nfapi_config; + if (nfapi_config->p7_vnf_address_ipv4.tl.tag) { + char ip_str[INET_ADDRSTRLEN]; + INDENTED_GENERIC_PRINT("(0x%04x) P7 VNF Address IPv4", + "%s", + nfapi_config->p7_vnf_address_ipv4.tl.tag, + inet_ntop(AF_INET, nfapi_config->p7_vnf_address_ipv4.address, ip_str, sizeof(ip_str))); + } + if (nfapi_config->p7_vnf_address_ipv6.tl.tag) { + char addr6[INET6_ADDRSTRLEN]; + INDENTED_GENERIC_PRINT("(0x%04x) P7 VNF Address IPv6", + "%s", + nfapi_config->p7_vnf_address_ipv6.tl.tag, + inet_ntop(AF_INET6, nfapi_config->p7_vnf_address_ipv6.address, addr6, sizeof(addr6))); + } + INDENTED_TLV_FORMAT_PRINT("P7 VNF Port", "%d", nfapi_config->p7_vnf_port); + + if (nfapi_config->p7_pnf_address_ipv4.tl.tag) { + char ip_str[INET_ADDRSTRLEN]; + INDENTED_GENERIC_PRINT("(0x%04x) P7 PNF Address IPv4", + "%s", + nfapi_config->p7_pnf_address_ipv4.tl.tag, + inet_ntop(AF_INET, nfapi_config->p7_pnf_address_ipv4.address, ip_str, sizeof(ip_str))); + } + if (nfapi_config->p7_pnf_address_ipv6.tl.tag) { + char addr6[INET6_ADDRSTRLEN]; + INDENTED_GENERIC_PRINT("(0x%04x) P7 PNF Address IPv6", + "%s", + nfapi_config->p7_pnf_address_ipv6.tl.tag, + inet_ntop(AF_INET6, nfapi_config->p7_pnf_address_ipv6.address, addr6, sizeof(addr6))); + } + INDENTED_TLV_FORMAT_PRINT("P7 PNF Port", "%d", nfapi_config->p7_pnf_port); + INDENTED_TLV_FORMAT_PRINT("Timing Window", "%d", nfapi_config->timing_window); + INDENTED_TLV_FORMAT_PRINT("Timing Info Mode", "%d", nfapi_config->timing_info_mode); + INDENTED_TLV_FORMAT_PRINT("Timing Info Period", "%d", nfapi_config->timing_info_period); + INDENTED_TLV_FORMAT_PRINT("DL_TTI Timing Offset", "%d", nfapi_config->dl_tti_timing_offset); + INDENTED_TLV_FORMAT_PRINT("UL_TTI Timing Offset", "%d", nfapi_config->ul_tti_timing_offset); + INDENTED_TLV_FORMAT_PRINT("UL_DCI Timing Offset", "%d", nfapi_config->ul_dci_timing_offset); + INDENTED_TLV_FORMAT_PRINT("TX_DATA Timing Offset", "%d", nfapi_config->tx_data_timing_offset); depth--; } void dump_config_request(const nfapi_nr_config_request_scf_t *msg) { int depth = 0; - dump_p5_message_header(&msg->header,depth); + dump_p5_message_header(&msg->header, depth); depth++; INDENTED_PRINTF("Number of TLVs = 0x%02x\n", msg->num_tlv); /* dump all TLVs from each table */ + /* Carrier Config */ + const nfapi_nr_carrier_config_t *carrier_config = &msg->carrier_config; + INDENTED_TLV_PRINT("DL Bandwidth", carrier_config->dl_bandwidth); + INDENTED_TLV_PRINT("DL Frequency", carrier_config->dl_frequency); + INDENTED_PRINTF("(0x%04x) DL K0 = ", NFAPI_NR_CONFIG_DL_K0_TAG); + for (int i = 0; i < 5; i++) { + printf("%d ", carrier_config->dl_k0[i].value); + } + printf("\n"); + INDENTED_PRINTF("(0x%04x) DL Grid Size = ", NFAPI_NR_CONFIG_DL_GRID_SIZE_TAG); + for (int i = 0; i < 5; i++) { + printf("%d ", carrier_config->dl_grid_size[i].value); + } + printf("\n"); + INDENTED_TLV_PRINT("Num TX Antennas", carrier_config->num_tx_ant); + INDENTED_TLV_PRINT("UL Bandwidth", carrier_config->uplink_bandwidth); + INDENTED_TLV_PRINT("UL Frequency", carrier_config->uplink_frequency); + INDENTED_PRINTF("(0x%04x) UL K0 = ", NFAPI_NR_CONFIG_UL_K0_TAG); + for (int i = 0; i < 5; i++) { + printf("%d ", carrier_config->ul_k0[i].value); + } + printf("\n"); + INDENTED_PRINTF("(0x%04x) UL Grid Size = ", NFAPI_NR_CONFIG_UL_GRID_SIZE_TAG); + for (int i = 0; i < 5; i++) { + printf("%d ", carrier_config->ul_grid_size[i].value); + } + printf("\n"); + INDENTED_TLV_PRINT("Num RX Antennas", carrier_config->num_rx_ant); + INDENTED_TLV_PRINT("Frequency Shift 7p5KHz", carrier_config->frequency_shift_7p5khz); + /* Cell Config */ + const nfapi_nr_cell_config_t *cell_config = &msg->cell_config; + INDENTED_TLV_PRINT("Physical Cell ID", cell_config->phy_cell_id); + INDENTED_TLV_PRINT("Frame Duplex Type", cell_config->frame_duplex_type); + /* SSB Config */ + const nfapi_nr_ssb_config_t *ssb_config = &msg->ssb_config; + INDENTED_TLV_PRINT("SSB Block Power", ssb_config->ss_pbch_power); + INDENTED_TLV_PRINT("BCH Payload", ssb_config->bch_payload); + INDENTED_TLV_PRINT("SCS Common", ssb_config->scs_common); + /* PRACH Config */ + const nfapi_nr_prach_config_t *prach_config = &msg->prach_config; + INDENTED_TLV_PRINT("PRACH Sequence Length", prach_config->prach_sequence_length); + INDENTED_TLV_PRINT("PRACH Subcarrier Spacing", prach_config->prach_sub_c_spacing); + INDENTED_TLV_PRINT("Restricted Set Config", prach_config->restricted_set_config); + INDENTED_TLV_PRINT("Num PRACH FD Occasions", prach_config->num_prach_fd_occasions); + INDENTED_TLV_PRINT("PRACH Config Index", prach_config->prach_ConfigurationIndex); + depth++; + for (int i = 0; i < prach_config->num_prach_fd_occasions.value; i++) { + const nfapi_nr_num_prach_fd_occasions_t *prach_fd_occasion = &(prach_config->num_prach_fd_occasions_list[i]); + INDENTED_TLV_PRINT("PRACH Root Sequence Index", prach_fd_occasion->prach_root_sequence_index); + INDENTED_TLV_PRINT("Num Root Sequences", prach_fd_occasion->num_root_sequences); + INDENTED_TLV_PRINT("K1", prach_fd_occasion->k1); + INDENTED_TLV_PRINT("PRACH Zero CorrelationZone Config", prach_fd_occasion->prach_zero_corr_conf); + INDENTED_TLV_PRINT("Num Unused Root Sequences", prach_fd_occasion->num_unused_root_sequences); + depth++; + for (int k = 0; k < prach_fd_occasion->num_unused_root_sequences.value; k++) { + INDENTED_TLV_PRINT("Unused Root Sequence", prach_fd_occasion->unused_root_sequences_list[k]); + } + depth--; + } depth--; + INDENTED_TLV_PRINT("SSB Per RACH", prach_config->ssb_per_rach); + INDENTED_TLV_PRINT("PRACH Multiple Carriers in a Band", prach_config->prach_multiple_carriers_in_a_band); + /* SSB Table */ + const nfapi_nr_ssb_table_t *ssb_table = &msg->ssb_table; + INDENTED_TLV_PRINT("SSB Offset PointA", ssb_table->ssb_offset_point_a); + INDENTED_TLV_PRINT("Beta PSS", ssb_table->beta_pss); + INDENTED_TLV_PRINT("SSB Period", ssb_table->ssb_period); + INDENTED_TLV_PRINT("SSB Subcarrier Offset", ssb_table->ssb_subcarrier_offset); + INDENTED_TLV_PRINT("MIB", ssb_table->MIB); + + INDENTED_PRINTF("SSB Mask:\n"); + depth++; + for (int i = 0; i < 2; i++) { + INDENTED_TLV_PRINT("SSB Mask", ssb_table->ssb_mask_list[i].ssb_mask); + } + depth--; + INDENTED_PRINTF("Beam ID:\n"); + depth++; + for (int i = 0; i < 64; i++) { + INDENTED_TLV_PRINT("Beam ID", ssb_table->ssb_beam_id_list[i].beam_id); + } + depth--; + INDENTED_TLV_PRINT("ssPBCH Multiple Carriers in a Band", ssb_table->ss_pbch_multiple_carriers_in_a_band); + INDENTED_TLV_PRINT("Multiple Cells ssPBCH in a Carrier", ssb_table->multiple_cells_ss_pbch_in_a_carrier); + /* TDD Table */ + const nfapi_nr_tdd_table_t *tdd_table = &msg->tdd_table; + if (cell_config->frame_duplex_type.value == 1 /* TDD */) { + INDENTED_TLV_PRINT("TDD Period", tdd_table->tdd_period); + const uint8_t slotsperframe[5] = {10, 20, 40, 80, 160}; + // Assuming always CP_Normal, because Cyclic prefix is not included in CONFIG.request 10.02, but is present in 10.04 + uint8_t cyclicprefix = 1; + // 3GPP 38.211 Table 4.3.2.1 & Table 4.3.2.2 + uint8_t number_of_symbols_per_slot = cyclicprefix ? 14 : 12; + INDENTED_PRINTF("Slot Config:\n"); + depth++; + for (int i = 0; i < slotsperframe[ssb_config->scs_common.value]; i++) { + for (int k = 0; k < number_of_symbols_per_slot; k++) { + const uint8_t slot_type = tdd_table->max_tdd_periodicity_list[i].max_num_of_symbol_per_slot_list[k].slot_config.value; + const char *slot_dir = slot_type == 0 ? "DL" : slot_type == 1 ? "UL" : "S"; + INDENTED_GENERIC_PRINT("(0x%04x) Slot Config", + "%d (%s)", + tdd_table->max_tdd_periodicity_list[i].max_num_of_symbol_per_slot_list[k].slot_config.tl.tag, + slot_type, + slot_dir); + } + } + depth--; + } + /* Measurement Config */ + const nfapi_nr_measurement_config_t *measurement_config = &msg->measurement_config; + INDENTED_TLV_PRINT("RSSI Measurement", measurement_config->rssi_measurement); + /* Beamforming Table */ + const nfapi_nr_dbt_pdu_t *dbt_config = &msg->dbt_config; + INDENTED_PRINTF("Digital Beam Table\n"); + depth++; + INDENTED_GENERIC_PRINT("Num Digital Beams", "%d", dbt_config->num_dig_beams); + INDENTED_GENERIC_PRINT("Num TX RUs", "%d", dbt_config->num_txrus); + depth++; + for (int i = 0; i < dbt_config->num_dig_beams; i++) { + const nfapi_nr_dig_beam_t *dig_beam = &dbt_config->dig_beam_list[i]; + INDENTED_GENERIC_PRINT("Beam IDX", "%d", dig_beam->beam_idx); + depth++; + for (int k = 0; k < dbt_config->num_txrus; k++) { + const nfapi_nr_txru_t *tx_ru = &dig_beam->txru_list[k]; + INDENTED_GENERIC_PRINT("Dig Beam Weight Real", "0x%02x", tx_ru->dig_beam_weight_Re); + INDENTED_GENERIC_PRINT("Dig Beam Weight Imaginary", "0x%02x", tx_ru->dig_beam_weight_Im); + } + depth--; + } + depth--; + depth--; + + /* Precoding Table */ + const nfapi_nr_pm_list_t *pmi_list = &msg->pmi_list; + INDENTED_PRINTF("Precoding Matrix Table\n"); + depth++; + INDENTED_GENERIC_PRINT("Num Precoding Tables", "%d", pmi_list->num_pm_idx); + depth++; + for (int i = 0; i < pmi_list->num_pm_idx; i++) { + const nfapi_nr_pm_pdu_t *pm_pdu = &pmi_list->pmi_pdu[i]; + + INDENTED_GENERIC_PRINT("Precoding Matrix IDX", "0x%02x", pm_pdu->pm_idx); + INDENTED_GENERIC_PRINT("Number of Layers", "%d", pm_pdu->numLayers); + INDENTED_GENERIC_PRINT("Number of Antenna Ports", "%d", pm_pdu->num_ant_ports); + depth++; + for (int k = 0; k < pm_pdu->numLayers; k++) { + for (int l = 0; l < pm_pdu->num_ant_ports; l++) { + const nfapi_nr_pm_weights_t *pm_weights = &pm_pdu->weights[k][l]; + INDENTED_GENERIC_PRINT("Dig Beam Weight Real", "0x%02x", pm_weights->precoder_weight_Re); + INDENTED_GENERIC_PRINT("Dig Beam Weight Imaginary", "0x%02x", pm_weights->precoder_weight_Im); + } + } + depth--; + } + depth--; + depth--; + /* nFAPI Config */ + const nfapi_nr_nfapi_t *nfapi_config = &msg->nfapi_config; + if (nfapi_config->p7_vnf_address_ipv4.tl.tag) { + char ip_str[INET_ADDRSTRLEN]; + INDENTED_GENERIC_PRINT("(0x%04x) P7 VNF Address IPv4", + "%s", + nfapi_config->p7_vnf_address_ipv4.tl.tag, + inet_ntop(AF_INET, nfapi_config->p7_vnf_address_ipv4.address, ip_str, sizeof(ip_str))); + } + if (nfapi_config->p7_vnf_address_ipv6.tl.tag) { + char addr6[INET6_ADDRSTRLEN]; + INDENTED_GENERIC_PRINT("(0x%04x) P7 VNF Address IPv6", + "%s", + nfapi_config->p7_vnf_address_ipv6.tl.tag, + inet_ntop(AF_INET6, nfapi_config->p7_vnf_address_ipv6.address, addr6, sizeof(addr6))); + } + INDENTED_TLV_FORMAT_PRINT("P7 VNF Port", "%d", nfapi_config->p7_vnf_port); + + if (nfapi_config->p7_pnf_address_ipv4.tl.tag) { + char ip_str[INET_ADDRSTRLEN]; + INDENTED_GENERIC_PRINT("(0x%04x) P7 PNF Address IPv4", + "%s", + nfapi_config->p7_pnf_address_ipv4.tl.tag, + inet_ntop(AF_INET, nfapi_config->p7_pnf_address_ipv4.address, ip_str, sizeof(ip_str))); + } + if (nfapi_config->p7_pnf_address_ipv6.tl.tag) { + char addr6[INET6_ADDRSTRLEN]; + INDENTED_GENERIC_PRINT("(0x%04x) P7 PNF Address IPv6", + "%s", + nfapi_config->p7_pnf_address_ipv6.tl.tag, + inet_ntop(AF_INET6, nfapi_config->p7_pnf_address_ipv6.address, addr6, sizeof(addr6))); + } + INDENTED_TLV_FORMAT_PRINT("P7 PNF Port", "%d", nfapi_config->p7_pnf_port); + INDENTED_TLV_FORMAT_PRINT("Timing Window", "%d", nfapi_config->timing_window); + INDENTED_TLV_FORMAT_PRINT("Timing Info Mode", "%d", nfapi_config->timing_info_mode); + INDENTED_TLV_FORMAT_PRINT("Timing Info Period", "%d", nfapi_config->timing_info_period); + INDENTED_TLV_FORMAT_PRINT("DL_TTI Timing Offset", "%d", nfapi_config->dl_tti_timing_offset); + INDENTED_TLV_FORMAT_PRINT("UL_TTI Timing Offset", "%d", nfapi_config->ul_tti_timing_offset); + INDENTED_TLV_FORMAT_PRINT("UL_DCI Timing Offset", "%d", nfapi_config->ul_dci_timing_offset); + INDENTED_TLV_FORMAT_PRINT("TX_DATA Timing Offset", "%d", nfapi_config->tx_data_timing_offset); + /* Beamforming VE */ + const nfapi_nr_analog_beamforming_ve_t *analog_beamforming_ve = &msg->analog_beamforming_ve; + INDENTED_TLV_FORMAT_PRINT("Num Beams per Period", "%d", analog_beamforming_ve->num_beams_period_vendor_ext); + INDENTED_TLV_PRINT("Analog Beamforming VE", analog_beamforming_ve->analog_bf_vendor_ext); + /* Vendor Extension */ + if (msg->vendor_extension) { + const nfapi_tl_t *vendor_extension = (nfapi_tl_t *)&msg->vendor_extension; + switch (vendor_extension->tag) { + case VENDOR_EXT_TLV_1_TAG: { + vendor_ext_tlv_1 *ve = (vendor_ext_tlv_1 *)vendor_extension; + INDENTED_PRINTF("(0x%04x) Vendor extension = %d 0x%02x\n", ve->tl.tag, ve->tl.length, ve->dummy); + } break; + case VENDOR_EXT_TLV_2_TAG: { + vendor_ext_tlv_2 *ve = (vendor_ext_tlv_2 *)vendor_extension; + INDENTED_PRINTF("(0x%04x) Vendor extension = %d 0x%02x\n", ve->tl.tag, ve->tl.length, ve->dummy); + } break; + default: + break; + } + } + + depth--; +} + +static void dump_generic_tlv(const nfapi_nr_generic_tlv_scf_t* tlv, int depth) +{ + INDENTED_PRINTF("TLV tag 0x%02x , Length 0x%02x , Value ", tlv->tl.tag, tlv->tl.length); + switch (tlv->tl.length) { + case UINT_8: + printf("0x%x\n", tlv->value.u8); + break; + case UINT_16: + printf("0x%02x\n", tlv->value.u16); + break; + case UINT_32: + printf("0x%04x\n", tlv->value.u32); + break; + case ARRAY_UINT_16: + for (int i = 0; i< 5 ; i++) { + printf("0x%04x ", tlv->value.array_u16[i]); + } + printf("\n"); + break; + default: + printf("unknown length %d\n", tlv->tl.length); + DevAssert(1 == 0); + break; + } } void dump_config_response(const nfapi_nr_config_response_scf_t *msg) @@ -1016,6 +1423,25 @@ void dump_config_response(const nfapi_nr_config_response_scf_t *msg) msg->num_invalid_tlvs_configured_in_running); INDENTED_PRINTF("Number of Missing TLVs = 0x%02x\n", msg->num_missing_tlvs); /* dump all TLVs from each table */ + INDENTED_PRINTF("Invalid or Unsupported TLVs (%d) :\n",msg->num_invalid_tlvs); + for (int i = 0; i < msg->num_invalid_tlvs; ++i) { + dump_generic_tlv(&msg->invalid_tlvs_list[i], depth+1); + } + + INDENTED_PRINTF("TLVs that can only be configured in IDLE (%d):\n", msg->num_invalid_tlvs_configured_in_idle); + for (int i = 0; i < msg->num_invalid_tlvs; ++i) { + dump_generic_tlv(&msg->invalid_tlvs_list[i], depth+1); + } + + INDENTED_PRINTF("TLVs that can only be configured in RUNNING (%d):\n",msg->num_invalid_tlvs_configured_in_running); + for (int i = 0; i < msg->num_invalid_tlvs; ++i) { + dump_generic_tlv(&msg->invalid_tlvs_list[i], depth+1); + } + + INDENTED_PRINTF("Missing TLVs (%d):\n",msg->num_missing_tlvs); + for (int i = 0; i < msg->num_invalid_tlvs; ++i) { + dump_generic_tlv(&msg->invalid_tlvs_list[i], depth+1); + } depth--; } diff --git a/nfapi/open-nFAPI/fapi/src/nr_fapi_p7_utils.c b/nfapi/open-nFAPI/fapi/src/nr_fapi_p7_utils.c index 9939a6f535..fb645707ad 100644 --- a/nfapi/open-nFAPI/fapi/src/nr_fapi_p7_utils.c +++ b/nfapi/open-nFAPI/fapi/src/nr_fapi_p7_utils.c @@ -859,9 +859,7 @@ bool eq_rach_indication(const nfapi_nr_rach_indication_t *a, const nfapi_nr_rach void free_dl_tti_request(nfapi_nr_dl_tti_request_t *msg) { - if (msg->vendor_extension) { - free(msg->vendor_extension); - } + free(msg->vendor_extension); } void free_ul_tti_request(nfapi_nr_ul_tti_request_t *msg) @@ -907,9 +905,7 @@ void free_rx_data_indication(nfapi_nr_rx_data_indication_t *msg) if (msg->number_of_pdus > 0) { for (int pdu_idx = 0; pdu_idx < msg->number_of_pdus; ++pdu_idx) { nfapi_nr_rx_data_pdu_t *rx_pdu = &msg->pdu_list[pdu_idx]; - if (rx_pdu->pdu) { - free(rx_pdu->pdu); - } + free(rx_pdu->pdu); } free(msg->pdu_list); } @@ -917,99 +913,75 @@ void free_rx_data_indication(nfapi_nr_rx_data_indication_t *msg) void free_crc_indication(nfapi_nr_crc_indication_t *msg) { - if (msg->crc_list) { - for (int crc_idx = 0; crc_idx < msg->number_crcs; ++crc_idx) { - nfapi_nr_crc_t *crc = &msg->crc_list[crc_idx]; - if (crc->cb_crc_status) { - free(crc->cb_crc_status); - } - } - free(msg->crc_list); + for (int crc_idx = 0; crc_idx < msg->number_crcs; ++crc_idx) { + nfapi_nr_crc_t *crc = &msg->crc_list[crc_idx]; + free(crc->cb_crc_status); } + free(msg->crc_list); } void free_uci_indication(nfapi_nr_uci_indication_t *msg) { - if (msg->uci_list) { - for (int pdu_idx = 0; pdu_idx < msg->num_ucis; ++pdu_idx) { - nfapi_nr_uci_t *uci_pdu = &msg->uci_list[pdu_idx]; - switch (uci_pdu->pdu_type) { - case NFAPI_NR_UCI_PUSCH_PDU_TYPE: { - nfapi_nr_uci_pusch_pdu_t *pdu = &uci_pdu->pusch_pdu; - // Bit 0 not used in PUSCH PDU - // HARQ - if ((pdu->pduBitmap >> 1) & 0x01) { - if (pdu->harq.harq_payload) { - free(pdu->harq.harq_payload); - } - } - // CSI Part 1 - if ((pdu->pduBitmap >> 2) & 0x01) { - if (pdu->csi_part1.csi_part1_payload) { - free(pdu->csi_part1.csi_part1_payload); - } - } - // CSI Part 2 - if ((pdu->pduBitmap >> 3) & 0x01) { - if (pdu->csi_part2.csi_part2_payload) { - free(pdu->csi_part2.csi_part2_payload); - } - } - break; + for (int pdu_idx = 0; pdu_idx < msg->num_ucis; ++pdu_idx) { + nfapi_nr_uci_t *uci_pdu = &msg->uci_list[pdu_idx]; + switch (uci_pdu->pdu_type) { + case NFAPI_NR_UCI_PUSCH_PDU_TYPE: { + nfapi_nr_uci_pusch_pdu_t *pdu = &uci_pdu->pusch_pdu; + // Bit 0 not used in PUSCH PDU + // HARQ + if ((pdu->pduBitmap >> 1) & 0x01) { + free(pdu->harq.harq_payload); } - case NFAPI_NR_UCI_FORMAT_0_1_PDU_TYPE: { - // Nothing to free - break; + // CSI Part 1 + if ((pdu->pduBitmap >> 2) & 0x01) { + free(pdu->csi_part1.csi_part1_payload); } - case NFAPI_NR_UCI_FORMAT_2_3_4_PDU_TYPE: { - nfapi_nr_uci_pucch_pdu_format_2_3_4_t *pdu = &uci_pdu->pucch_pdu_format_2_3_4; - // SR - if (pdu->pduBitmap & 0x01) { - if (pdu->sr.sr_payload) { - free(pdu->sr.sr_payload); - } - } - // HARQ - if ((pdu->pduBitmap >> 1) & 0x01) { - if (pdu->harq.harq_payload) { - free(pdu->harq.harq_payload); - } - } - // CSI Part 1 - if ((pdu->pduBitmap >> 2) & 0x01) { - if (pdu->csi_part1.csi_part1_payload) { - free(pdu->csi_part1.csi_part1_payload); - } - } - // CSI Part 2 - if ((pdu->pduBitmap >> 3) & 0x01) { - if (pdu->csi_part2.csi_part2_payload) { - free(pdu->csi_part2.csi_part2_payload); - } - } - break; + // CSI Part 2 + if ((pdu->pduBitmap >> 3) & 0x01) { + free(pdu->csi_part2.csi_part2_payload); } - default: - AssertFatal(1 == 0, "Unknown UCI.indication PDU Type %d\n", uci_pdu->pdu_type); - break; + break; } + case NFAPI_NR_UCI_FORMAT_0_1_PDU_TYPE: { + // Nothing to free + break; + } + case NFAPI_NR_UCI_FORMAT_2_3_4_PDU_TYPE: { + nfapi_nr_uci_pucch_pdu_format_2_3_4_t *pdu = &uci_pdu->pucch_pdu_format_2_3_4; + // SR + if (pdu->pduBitmap & 0x01) { + free(pdu->sr.sr_payload); + } + // HARQ + if ((pdu->pduBitmap >> 1) & 0x01) { + free(pdu->harq.harq_payload); + } + // CSI Part 1 + if ((pdu->pduBitmap >> 2) & 0x01) { + free(pdu->csi_part1.csi_part1_payload); + } + // CSI Part 2 + if ((pdu->pduBitmap >> 3) & 0x01) { + free(pdu->csi_part2.csi_part2_payload); + } + break; + } + default: + AssertFatal(1 == 0, "Unknown UCI.indication PDU Type %d\n", uci_pdu->pdu_type); + break; } - free(msg->uci_list); } + free(msg->uci_list); } void free_srs_indication(nfapi_nr_srs_indication_t *msg) { - if (msg->pdu_list) { - free(msg->pdu_list); - } + free(msg->pdu_list); } void free_rach_indication(nfapi_nr_rach_indication_t *msg) { - if (msg->pdu_list) { - free(msg->pdu_list); - } + free(msg->pdu_list); } static void copy_dl_tti_beamforming(const nfapi_nr_tx_precoding_and_beamforming_t *src, @@ -2586,6 +2558,27 @@ void dump_ul_dci_request(const nfapi_nr_ul_dci_request_t *msg) } } +static void dump_tx_data_request_tlv(const nfapi_nr_tx_data_request_tlv_t *tlv, int depth) +{ + INDENTED_PRINTF("Tag = %d\n", tlv->tag); + INDENTED_PRINTF("Length = %d\n", tlv->length); + INDENTED_PRINTF("Value = "); + switch (tlv->tag) { + case 0: + for (int i = 0; i < tlv->length; i++) { + printf("0x%02x ", ((uint8_t*)tlv->value.direct)[i]); + } + break; + case 1: + printf("%p", tlv->value.ptr); + break; + default: + printf( " Unknown tag value %d",tlv->tag); + break; + } + printf("\n"); +} + void dump_tx_data_request(const nfapi_nr_tx_data_request_t *msg) { int depth = 0; @@ -2594,15 +2587,18 @@ void dump_tx_data_request(const nfapi_nr_tx_data_request_t *msg) INDENTED_PRINTF("SFN = %d\n", msg->SFN); INDENTED_PRINTF("Slot = %d\n", msg->Slot); INDENTED_PRINTF("Number of PDUs = %d\n", msg->Number_of_PDUs); + depth++; for (int i = 0; i < msg->Number_of_PDUs; i++) { - depth++; INDENTED_PRINTF("PDU #%d\n", i); const nfapi_nr_pdu_t *pdu = &msg->pdu_list[i]; INDENTED_PRINTF("PDU Length = 0x%02x\n", pdu->PDU_length); INDENTED_PRINTF("PDU Index = 0x%02x\n", pdu->PDU_index); INDENTED_PRINTF("numTLV = 0x%02x\n", pdu->num_TLV); + for (int tlv_idx = 0; tlv_idx < pdu->num_TLV; tlv_idx++) { + const nfapi_nr_tx_data_request_tlv_t *tlv = &pdu->TLVs[tlv_idx]; /* call to dump_tx_data_request_tlv */ - depth--; + dump_tx_data_request_tlv(tlv, depth + 1); + } } } @@ -2664,6 +2660,134 @@ void dump_crc_indication(const nfapi_nr_crc_indication_t *msg) } } +static void dump_harq_2_3_4(const nfapi_nr_harq_pdu_2_3_4_t *harq, int depth) +{ + INDENTED_PRINTF("HARQ CRC = %01x\n", harq->harq_crc); + INDENTED_PRINTF("HARQ Bit Length = %d\n", harq->harq_bit_len); + INDENTED_PRINTF("HARQ Payload = "); + for (int i = 0; i < harq->harq_bit_len / 8 + 1; i++) { + printf("%x ", harq->harq_payload[i]); + } + printf("\n"); +} + +static void dump_csi_part_1(const nfapi_nr_csi_part1_pdu_t *csi, int depth) +{ + INDENTED_PRINTF("CSI Part 1 CRC = %01x\n", csi->csi_part1_crc); + INDENTED_PRINTF("CSI Part 1 Bit Length = %d\n", csi->csi_part1_bit_len); + INDENTED_PRINTF("CSI Part 1 Payload = "); + for (int i = 0; i < csi->csi_part1_bit_len / 8 + 1; i++) { + printf("%x ", csi->csi_part1_payload[i]); + } + printf("\n"); +} + +static void dump_csi_part_2(const nfapi_nr_csi_part2_pdu_t *csi, int depth) +{ + INDENTED_PRINTF("CSI Part 1 CRC = %01x\n", csi->csi_part2_crc); + INDENTED_PRINTF("CSI Part 1 Bit Length = %d\n", csi->csi_part2_bit_len); + INDENTED_PRINTF("CSI Part 1 Payload = "); + for (int i = 0; i < csi->csi_part2_bit_len / 8 + 1; i++) { + printf("%x ", csi->csi_part2_payload[i]); + } + printf("\n"); +} + +static void dump_uci_PUSCH_PDU(const nfapi_nr_uci_pusch_pdu_t *pdu, int depth) +{ + INDENTED_PRINTF("PDU Bitmap = 0x%01x\n", pdu->pduBitmap); + INDENTED_PRINTF("Handle = 0x%04x\n", pdu->handle); + INDENTED_PRINTF("RNTI = 0x%02x\n", pdu->rnti); + INDENTED_PRINTF("UL_CQI = 0x%02x\n", pdu->ul_cqi); + INDENTED_PRINTF("Timing Advance = 0x%02x\n", pdu->timing_advance); + INDENTED_PRINTF("RSSI = 0x%02x\n", pdu->rssi); + // HARQ payload, CSI Part 1 and 2 are conditionally allocated + if ((pdu->pduBitmap >> 1) & 0x01) { + INDENTED_PRINTF("HARQ Information\n"); + dump_harq_2_3_4(&pdu->harq, depth + 1); + } + if ((pdu->pduBitmap >> 2) & 0x01) { + INDENTED_PRINTF("CSI Part 1\n"); + dump_csi_part_1(&pdu->csi_part1, depth + 1); + } + if ((pdu->pduBitmap >> 3) & 0x01) { + INDENTED_PRINTF("CSI Part 1\n"); + dump_csi_part_2(&pdu->csi_part2, depth + 1); + } +} + +static void dump_sr_0_1(const nfapi_nr_sr_pdu_0_1_t *sr, int depth) +{ + INDENTED_PRINTF("SR Indication = 0x%02x\n", sr->sr_indication); + INDENTED_PRINTF("SR Confidence Level = 0x%02x\n", sr->sr_confidence_level); +} + +static void dump_harq_0_1(const nfapi_nr_harq_pdu_0_1_t *harq, int depth) +{ + INDENTED_PRINTF("Num HARQ = 0x%02x\n", harq->num_harq); + INDENTED_PRINTF("HARQ Confidence Level = 0x%02x\n", harq->harq_confidence_level); + depth++; + for (int i = 0; i < harq->num_harq; i++) { + INDENTED_PRINTF("HARQ Value[%d] : 0x%02x \n", i, harq->harq_list[i].harq_value); + } +} + +static void dump_uci_PUCCH_0_1(const nfapi_nr_uci_pucch_pdu_format_0_1_t *pdu, int depth) +{ + INDENTED_PRINTF("PDU Bitmap = 0x%01x\n", pdu->pduBitmap); + INDENTED_PRINTF("Handle = 0x%04x\n", pdu->handle); + INDENTED_PRINTF("RNTI = 0x%02x\n", pdu->rnti); + INDENTED_PRINTF("PUCCH Format = 0x%02x\n", pdu->pucch_format); + INDENTED_PRINTF("UL_CQI = 0x%02x\n", pdu->ul_cqi); + INDENTED_PRINTF("Timing Advance = 0x%02x\n", pdu->timing_advance); + INDENTED_PRINTF("RSSI = 0x%02x\n", pdu->rssi); + if ((pdu->pduBitmap) & 0x01) { + INDENTED_PRINTF("SR Information\n"); + dump_sr_0_1(&pdu->sr, depth + 1); + } + if ((pdu->pduBitmap >> 1) & 0x01) { + INDENTED_PRINTF("HARQ Information\n"); + dump_harq_0_1(&pdu->harq, depth + 1); + } +} + +static void dump_sr_2_3_4(const nfapi_nr_sr_pdu_2_3_4_t *sr, int depth) +{ + INDENTED_PRINTF("SR Bit Length = %d\n", sr->sr_bit_len); + INDENTED_PRINTF("SR Payload "); + for (int i = 0; i < sr->sr_bit_len / 8 + 1; i++) { + printf("%x ", sr->sr_payload[i]); + } + printf("\n"); +} + +static void dump_uci_PUCCH_2_3_4(const nfapi_nr_uci_pucch_pdu_format_2_3_4_t *pdu, int depth) +{ + INDENTED_PRINTF("PDU Bitmap = 0x%01x\n", pdu->pduBitmap); + INDENTED_PRINTF("Handle = 0x%04x\n", pdu->handle); + INDENTED_PRINTF("RNTI = 0x%02x\n", pdu->rnti); + INDENTED_PRINTF("PUCCH Format = 0x%02x\n", pdu->pucch_format); + INDENTED_PRINTF("UL_CQI = 0x%02x\n", pdu->ul_cqi); + INDENTED_PRINTF("Timing Advance = 0x%02x\n", pdu->timing_advance); + INDENTED_PRINTF("RSSI = 0x%02x\n", pdu->rssi); + // SR + if (pdu->pduBitmap & 0x01) { + dump_sr_2_3_4(&pdu->sr, depth + 1); + } + // HARQ + if ((pdu->pduBitmap >> 1) & 0x01) { + dump_harq_2_3_4(&pdu->harq, depth + 1); + } + // CSI Part 1 + if ((pdu->pduBitmap >> 2) & 0x01) { + dump_csi_part_1(&pdu->csi_part1, depth + 1); + } + // CSI Part 2 + if ((pdu->pduBitmap >> 3) & 0x01) { + dump_csi_part_2(&pdu->csi_part2, depth + 1); + } +} + void dump_uci_indication(const nfapi_nr_uci_indication_t *msg) { int depth = 0; @@ -2680,6 +2804,20 @@ void dump_uci_indication(const nfapi_nr_uci_indication_t *msg) INDENTED_PRINTF("PDUType = 0x%02x\n", uci->pdu_type); INDENTED_PRINTF("PDUSize = 0x%02x\n", uci->pdu_size); /* call to dump_uci_indication__pdu */ + switch (uci->pdu_type) { + case NFAPI_NR_UCI_PUSCH_PDU_TYPE: + dump_uci_PUSCH_PDU(&uci->pusch_pdu, depth + 1); + break; + case NFAPI_NR_UCI_FORMAT_0_1_PDU_TYPE: + dump_uci_PUCCH_0_1(&uci->pucch_pdu_format_0_1, depth + 1); + break; + case NFAPI_NR_UCI_FORMAT_2_3_4_PDU_TYPE: + dump_uci_PUCCH_2_3_4(&uci->pucch_pdu_format_2_3_4, depth + 1); + break; + default: + INDENTED_PRINTF("Unknown PDU type 0x%02x\n", uci->pdu_type); + break; + } depth--; } } diff --git a/nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface.h b/nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface.h index b7e6577fa2..eb668f3e73 100644 --- a/nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface.h +++ b/nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface.h @@ -34,6 +34,7 @@ #define NFAPI_NR_FAPI_TOTAL_NUM_BEAMS_VENDOR_EXTENSION_TAG 0xA002 #define NFAPI_NR_FAPI_ANALOG_BEAM_VENDOR_EXTENSION_TAG 0xA003 + typedef struct { uint16_t phy_id; uint16_t message_id; diff --git a/nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface_scf.h b/nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface_scf.h index 0533a76c6d..f213868328 100644 --- a/nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface_scf.h +++ b/nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface_scf.h @@ -328,6 +328,8 @@ typedef struct #define NFAPI_NR_CONFIG_RSSI_MEASUREMENT_TAG 0x1028 #define NFAPI_NR_CONFIG_TDD_TABLE 0x1035 +#define NFAPI_NR_CONFIG_BEAMFORMING_TABLE_TAG 0x1043 // This tag was added in version 5 of the SCF222 standard ( Table 3-50 of SCF222.10.05 ) +#define NFAPI_NR_CONFIG_PRECODING_TABLE_V6_TAG 0x104B // This tag was added in version 6 of the SCF222 standard ( Table 3-52 of SCF222.10.06 ) //table 3-21 typedef struct @@ -473,6 +475,11 @@ typedef struct { nfapi_nr_dig_beam_t *dig_beam_list; } nfapi_nr_dbt_pdu_t; +typedef struct { + nfapi_tl_t tl; + nfapi_nr_dbt_pdu_t value; +} nfapi_nr_dbt_tlv_ve_t; + // Table 3–62 Precoding matrix (PM) PDU (v.222.10.04) typedef struct { int16_t precoder_weight_Re; @@ -491,7 +498,12 @@ typedef struct { typedef struct { uint16_t num_pm_idx; nfapi_nr_pm_pdu_t *pmi_pdu; -} nfapi_nr_pm_list_t; +} nfapi_nr_pm_list_t; // This corresponds to Table 3-69 of SCF222.10.06, which introduces the num_pm_idx parameter + +typedef struct { + nfapi_tl_t tl; + nfapi_nr_pm_list_t value; +} nfapi_nr_pm_tlv_ve_t; typedef struct { nfapi_uint8_tlv_t num_beams_period_vendor_ext; diff --git a/nfapi/tests/p5/nr_fapi_config_request_test.c b/nfapi/tests/p5/nr_fapi_config_request_test.c index 93ff5b5f3a..82ce60ca3b 100644 --- a/nfapi/tests/p5/nr_fapi_config_request_test.c +++ b/nfapi/tests/p5/nr_fapi_config_request_test.c @@ -206,6 +206,47 @@ static void fill_config_request_tlv_tdd_rand(nfapi_nr_config_request_scf_t *nfap FILL_TLV(nfapi_resp->measurement_config.rssi_measurement, NFAPI_NR_CONFIG_RSSI_MEASUREMENT_TAG, rand8()); nfapi_resp->num_tlv++; + uint16_t nb_beams = rand16_range(1, 15); + uint16_t nb_tx = rand16_range(1, 15); + nfapi_resp->dbt_config.num_dig_beams = nb_beams; + if (nfapi_resp->dbt_config.num_dig_beams > 0) { + nfapi_resp->dbt_config.num_txrus = nb_tx; + nfapi_resp->dbt_config.dig_beam_list = calloc(nb_beams , sizeof(*nfapi_resp->dbt_config.dig_beam_list)); + for (int i = 0; i < nb_beams; i++) { + nfapi_nr_dig_beam_t *beam = &nfapi_resp->dbt_config.dig_beam_list[i]; + beam->beam_idx = i; + beam->txru_list = calloc(nb_tx , sizeof(*beam->txru_list)); + for (int j = 0; j < nb_tx; j++) { + nfapi_nr_txru_t *txru = &beam->txru_list[j]; + txru->dig_beam_weight_Re = rand16_range(1, 0xffff); + txru->dig_beam_weight_Im = rand16_range(1, 0xffff); + } + } + nfapi_resp->num_tlv++; + } + + nfapi_nr_pm_list_t *pm_list = &nfapi_resp->pmi_list; + const uint16_t num_layers = rand16_range(1, 4); + const uint16_t num_ant_ports = rand16_range(1, 4); + pm_list->num_pm_idx = rand16_range(1, 4); + if (nfapi_resp->pmi_list.num_pm_idx > 0) { + pm_list->pmi_pdu = calloc(pm_list->num_pm_idx, sizeof(*pm_list->pmi_pdu)); + for (int i = 0; i < pm_list->num_pm_idx; i++) { + nfapi_nr_pm_pdu_t *pmi_pdu = &pm_list->pmi_pdu[i]; + pmi_pdu->pm_idx = i+1; + pmi_pdu->numLayers = num_layers; + pmi_pdu->num_ant_ports = num_ant_ports; + for (int j = 0; j < num_layers; j++) { + for (int k = 0; k < num_ant_ports; k++) { + nfapi_nr_pm_weights_t* pm_weight = &pmi_pdu->weights[j][k]; + pm_weight->precoder_weight_Re = (int16_t)rand16_range(1, 0xffff); + pm_weight->precoder_weight_Im = (int16_t)rand16_range(1, 0xffff); + } + } + } + nfapi_resp->num_tlv++; + } + nfapi_resp->nfapi_config.p7_vnf_address_ipv4.tl.tag = NFAPI_NR_NFAPI_P7_VNF_ADDRESS_IPV4_TAG; for (int i = 0; i < NFAPI_IPV4_ADDRESS_LENGTH; ++i) { nfapi_resp->nfapi_config.p7_vnf_address_ipv4.address[i] = rand8(); @@ -221,6 +262,21 @@ static void fill_config_request_tlv_tdd_rand(nfapi_nr_config_request_scf_t *nfap FILL_TLV(nfapi_resp->nfapi_config.p7_vnf_port, NFAPI_NR_NFAPI_P7_VNF_PORT_TAG, rand16()); nfapi_resp->num_tlv++; + nfapi_resp->nfapi_config.p7_pnf_address_ipv4.tl.tag = NFAPI_NR_NFAPI_P7_PNF_ADDRESS_IPV4_TAG; + for (int i = 0; i < NFAPI_IPV4_ADDRESS_LENGTH; ++i) { + nfapi_resp->nfapi_config.p7_pnf_address_ipv4.address[i] = rand8(); + } + nfapi_resp->num_tlv++; + + nfapi_resp->nfapi_config.p7_pnf_address_ipv6.tl.tag = NFAPI_NR_NFAPI_P7_PNF_ADDRESS_IPV6_TAG; + for (int i = 0; i < NFAPI_IPV6_ADDRESS_LENGTH; ++i) { + nfapi_resp->nfapi_config.p7_pnf_address_ipv6.address[i] = rand8(); + } + nfapi_resp->num_tlv++; + + FILL_TLV(nfapi_resp->nfapi_config.p7_pnf_port, NFAPI_NR_NFAPI_P7_PNF_PORT_TAG, rand16()); + nfapi_resp->num_tlv++; + FILL_TLV(nfapi_resp->nfapi_config.timing_window, NFAPI_NR_NFAPI_TIMING_WINDOW_TAG, rand8()); nfapi_resp->num_tlv++; diff --git a/openair2/COMMON/rrc_messages_def.h b/openair2/COMMON/rrc_messages_def.h index 67aadb2869..df295e2011 100644 --- a/openair2/COMMON/rrc_messages_def.h +++ b/openair2/COMMON/rrc_messages_def.h @@ -88,6 +88,7 @@ MESSAGE_DEF(NRRRC_FRAME_PROCESS, MESSAGE_PRIORITY_MED, NRRrcFramePr // UE: RRC -> MAC messages MESSAGE_DEF(NR_MAC_RRC_CONFIG_RESET, MESSAGE_PRIORITY_MED, nr_mac_rrc_config_reset_t, nr_mac_rrc_config_reset) MESSAGE_DEF(NR_MAC_RRC_CONFIG_CG, MESSAGE_PRIORITY_MED, nr_mac_rrc_config_cg_t, nr_mac_rrc_config_cg) +MESSAGE_DEF(NR_MAC_RRC_RESUME_RB, MESSAGE_PRIORITY_MED, nr_mac_rrc_resume_rb_t, nr_mac_rrc_resume_rb) MESSAGE_DEF(NR_MAC_RRC_CONFIG_MIB, MESSAGE_PRIORITY_MED, nr_mac_rrc_config_mib_t, nr_mac_rrc_config_mib) MESSAGE_DEF(NR_MAC_RRC_CONFIG_SIB1, MESSAGE_PRIORITY_MED, nr_mac_rrc_config_sib1_t, nr_mac_rrc_config_sib1) MESSAGE_DEF(NR_MAC_RRC_CONFIG_OTHER_SIB, MESSAGE_PRIORITY_MED, nr_mac_rrc_config_other_sib_t, nr_mac_rrc_config_other_sib) diff --git a/openair2/COMMON/rrc_messages_types.h b/openair2/COMMON/rrc_messages_types.h index a3db7ebba6..094fd0fa40 100644 --- a/openair2/COMMON/rrc_messages_types.h +++ b/openair2/COMMON/rrc_messages_types.h @@ -107,6 +107,7 @@ #define NAS_PDU_SESSION_REQ(mSGpTR) (mSGpTR)->ittiMsg.nas_pdu_session_req #define NR_MAC_RRC_CONFIG_RESET(mSGpTR) (mSGpTR)->ittiMsg.nr_mac_rrc_config_reset #define NR_MAC_RRC_CONFIG_CG(mSGpTR) (mSGpTR)->ittiMsg.nr_mac_rrc_config_cg +#define NR_MAC_RRC_RESUME_RB(mSGpTR) (mSGpTR)->ittiMsg.nr_mac_rrc_resume_rb #define NR_MAC_RRC_CONFIG_MIB(mSGpTR) (mSGpTR)->ittiMsg.nr_mac_rrc_config_mib #define NR_MAC_RRC_CONFIG_SIB1(mSGpTR) (mSGpTR)->ittiMsg.nr_mac_rrc_config_sib1 #define NR_MAC_RRC_CONFIG_OTHER_SIB(mSGpTR) (mSGpTR)->ittiMsg.nr_mac_rrc_config_other_sib @@ -470,6 +471,11 @@ typedef struct { int ue_id; } RlcMaxRtxIndication; +typedef struct { + bool is_srb; + int rb_id; +} nr_mac_rrc_resume_rb_t; + typedef struct { NR_ReestablishmentCause_t cause; } nr_mac_rrc_config_reset_t; diff --git a/openair2/GNB_APP/RRC_nr_paramsvalues.h b/openair2/GNB_APP/RRC_nr_paramsvalues.h index c7b74be8b0..44774342e5 100644 --- a/openair2/GNB_APP/RRC_nr_paramsvalues.h +++ b/openair2/GNB_APP/RRC_nr_paramsvalues.h @@ -124,6 +124,7 @@ #define GNB_CONFIG_STRING_NROFUPLINKSYMBOLS2 "nrofUplinkSymbols2" #define GNB_CONFIG_STRING_SSPBCHBLOCKPOWER "ssPBCH_BlockPower" +#define GNB_CONFIG_STRING_ULSYNCVALIDITYDURATION "ntn-UlSyncValidityDuration-r17" #define GNB_CONFIG_STRING_CELLSPECIFICKOFFSET "cellSpecificKoffset_r17" #define GNB_CONFIG_STRING_EPHEMERIS_POSITION_X "positionX-r17" #define GNB_CONFIG_STRING_EPHEMERIS_POSITION_Y "positionY-r17" @@ -250,6 +251,7 @@ {GNB_CONFIG_STRING_NROFUPLINKSLOTS,NULL,0,.i64ptr=&scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofUplinkSlots,.defint64val=2,TYPE_INT64,0},\ {GNB_CONFIG_STRING_NROFUPLINKSYMBOLS,NULL,0,.i64ptr=&scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofUplinkSymbols,.defint64val=4,TYPE_INT64,0},\ {GNB_CONFIG_STRING_SSPBCHBLOCKPOWER,NULL,0,.i64ptr=&scc->ss_PBCH_BlockPower,.defint64val=20,TYPE_INT64,0}, \ +{GNB_CONFIG_STRING_ULSYNCVALIDITYDURATION,NULL,0,.i64ptr=scc->ext2->ntn_Config_r17->ntn_UlSyncValidityDuration_r17,.defint64val=0,TYPE_INT64,0}, \ {GNB_CONFIG_STRING_CELLSPECIFICKOFFSET,NULL,0,.i64ptr=scc->ext2->ntn_Config_r17->cellSpecificKoffset_r17,.defint64val=0,TYPE_INT64,0}, \ {GNB_CONFIG_STRING_EPHEMERIS_POSITION_X,NULL,0,.i64ptr=&scc->ext2->ntn_Config_r17->ephemerisInfo_r17->choice.positionVelocity_r17->positionX_r17,.defint64val=LONG_MAX,TYPE_INT64,0}, \ {GNB_CONFIG_STRING_EPHEMERIS_POSITION_Y,NULL,0,.i64ptr=&scc->ext2->ntn_Config_r17->ephemerisInfo_r17->choice.positionVelocity_r17->positionY_r17,.defint64val=LONG_MAX,TYPE_INT64,0}, \ diff --git a/openair2/GNB_APP/gnb_config.c b/openair2/GNB_APP/gnb_config.c index 0ddd097ca6..36ac8b6b1f 100644 --- a/openair2/GNB_APP/gnb_config.c +++ b/openair2/GNB_APP/gnb_config.c @@ -216,6 +216,7 @@ void prepare_scc(NR_ServingCellConfigCommon_t *scc) scc->ext2 = calloc_or_fail(1, sizeof(*scc->ext2)); scc->ext2->ntn_Config_r17 = calloc_or_fail(1, sizeof(*scc->ext2->ntn_Config_r17)); + scc->ext2->ntn_Config_r17->ntn_UlSyncValidityDuration_r17 = calloc_or_fail(1, sizeof(long)); scc->ext2->ntn_Config_r17->cellSpecificKoffset_r17 = calloc_or_fail(1, sizeof(*scc->ext2->ntn_Config_r17->cellSpecificKoffset_r17)); scc->ext2->ntn_Config_r17->ephemerisInfo_r17 = calloc_or_fail(1, sizeof(*scc->ext2->ntn_Config_r17->ephemerisInfo_r17)); @@ -465,6 +466,40 @@ static void fix_tdd_pattern(NR_ServingCellConfigCommon_t *scc) } } +static int get_ulsyncvalidityduration_enum_value(int val) +{ + int retval = -1; + + switch (val) { + case 5: + case 10: + case 15: + case 20: + case 25: + case 30: + case 35: + case 40: + case 45: + case 50: + case 55: + retval = val / 5 - 1; + break; + case 60: + case 120: + case 180: + case 240: + retval = 10 + val / 60; + break; + case 900: + retval = 15; + break; + default: + AssertFatal(1 == 0, "ulsyncvalidityDuration in SIB19 set to invalid value in Conf file\n"); + break; + } + return retval; +} + void fix_scc(NR_ServingCellConfigCommon_t *scc, uint64_t ssbmap) { scc->ssb_PositionsInBurst->present = get_ssb_len(scc); @@ -572,6 +607,13 @@ void fix_scc(NR_ServingCellConfigCommon_t *scc, uint64_t ssbmap) AssertFatal(*scc->uplinkConfigCommon->initialUplinkBWP->pucch_ConfigCommon->choice.setup->pucch_ResourceCommon < 2, "pucch_ResourceConfig should be 0 or 1 for now\n"); + if (*scc->ext2->ntn_Config_r17->ntn_UlSyncValidityDuration_r17 == 0) { + free(scc->ext2->ntn_Config_r17->ntn_UlSyncValidityDuration_r17); + scc->ext2->ntn_Config_r17->ntn_UlSyncValidityDuration_r17 = NULL; + } else { + int val = get_ulsyncvalidityduration_enum_value(*scc->ext2->ntn_Config_r17->ntn_UlSyncValidityDuration_r17); + *scc->ext2->ntn_Config_r17->ntn_UlSyncValidityDuration_r17 = val; + } if (*scc->ext2->ntn_Config_r17->cellSpecificKoffset_r17 == 0) { free(scc->ext2->ntn_Config_r17->cellSpecificKoffset_r17); scc->ext2->ntn_Config_r17->cellSpecificKoffset_r17 = NULL; @@ -596,8 +638,10 @@ void fix_scc(NR_ServingCellConfigCommon_t *scc, uint64_t ssbmap) scc->ext2->ntn_Config_r17->ephemerisInfo_r17 = NULL; } - if (!scc->ext2->ntn_Config_r17->cellSpecificKoffset_r17 && !scc->ext2->ntn_Config_r17->ta_Info_r17 - && !scc->ext2->ntn_Config_r17->ephemerisInfo_r17) { + if (!scc->ext2->ntn_Config_r17->ntn_UlSyncValidityDuration_r17 && + !scc->ext2->ntn_Config_r17->cellSpecificKoffset_r17 && + !scc->ext2->ntn_Config_r17->ta_Info_r17 && + !scc->ext2->ntn_Config_r17->ephemerisInfo_r17) { free(scc->ext2->ntn_Config_r17); free(scc->ext2); scc->ext2 = NULL; diff --git a/openair2/LAYER2/NR_MAC_UE/config_ue.c b/openair2/LAYER2/NR_MAC_UE/config_ue.c index 3a5d5e5640..bfea78d540 100644 --- a/openair2/LAYER2/NR_MAC_UE/config_ue.c +++ b/openair2/LAYER2/NR_MAC_UE/config_ue.c @@ -811,7 +811,7 @@ static uint32_t get_lc_bucket_size(long prioritisedBitRate, long bucketSizeDurat } // default configuration as per 38.331 section 9.2.1 -static void set_default_logicalchannelconfig(nr_lcordered_info_t *lc_info, NR_SRB_Identity_t srb_id) +static void set_default_logicalchannelconfig(nr_lcordered_info_t *lc_info, int srb_id) { lc_info->lcid = srb_id; lc_info->priority = srb_id == 2 ? 3 : 1; @@ -822,12 +822,14 @@ static void set_default_logicalchannelconfig(nr_lcordered_info_t *lc_info, NR_SR static void nr_configure_lc_config(NR_UE_MAC_INST_t *mac, nr_lcordered_info_t *lc_info, NR_LogicalChannelConfig_t *mac_lc_config, - NR_SRB_Identity_t srb_id) + nr_lcid_rb_t rb) { NR_LC_SCHEDULING_INFO *lc_sched_info = get_scheduling_info_from_lcid(mac, lc_info->lcid); - if (srb_id > 0 && !mac_lc_config->ul_SpecificParameters) { + lc_info->rb = rb; + lc_info->rb_suspended = false; + if (rb.type == NR_LCID_SRB && !mac_lc_config->ul_SpecificParameters) { // release configuration and reset to default - set_default_logicalchannelconfig(lc_info, srb_id); + set_default_logicalchannelconfig(lc_info, rb.choice.srb_id); // invalid LCGID to signal it is absent in the configuration lc_sched_info->LCGID = NR_INVALID_LCGID; return; @@ -848,6 +850,25 @@ static void nr_configure_lc_config(NR_UE_MAC_INST_t *mac, nr_timer_start(bjt); } +static nr_lcid_rb_t configure_lcid_rb(NR_RLC_BearerConfig_t *rlc_bearer) +{ + nr_lcid_rb_t rb; + if (rlc_bearer->servedRadioBearer->present == NR_RLC_BearerConfig__servedRadioBearer_PR_srb_Identity) { + rb.type = NR_LCID_SRB; + rb.choice.srb_id = rlc_bearer->servedRadioBearer->choice.srb_Identity; + return rb; + } + + if (rlc_bearer->servedRadioBearer->present == NR_RLC_BearerConfig__servedRadioBearer_PR_drb_Identity) { + rb.type = NR_LCID_DRB; + rb.choice.drb_id = rlc_bearer->servedRadioBearer->choice.drb_Identity; + return rb; + } + LOG_E(NR_MAC, "Error. RLC should be linked to either DRB or SRB.\n"); + rb.type = NR_LCID_NONE; + return rb; +} + static void configure_logicalChannelBearer(NR_UE_MAC_INST_t *mac, struct NR_CellGroupConfig__rlc_BearerToAddModList *rlc_toadd_list, struct NR_CellGroupConfig__rlc_BearerToReleaseList *rlc_torelease_list) @@ -870,6 +891,9 @@ static void configure_logicalChannelBearer(NR_UE_MAC_INST_t *mac, if (rlc_toadd_list) { for (int i = 0; i < rlc_toadd_list->list.count; i++) { NR_RLC_BearerConfig_t *rlc_bearer = rlc_toadd_list->list.array[i]; + nr_lcid_rb_t rb = configure_lcid_rb(rlc_bearer); + if (rb.type == NR_LCID_NONE) + continue; int lc_identity = rlc_bearer->logicalChannelIdentity; NR_LogicalChannelConfig_t *mac_lc_config = rlc_bearer->mac_LogicalChannelConfig; int j; @@ -879,14 +903,9 @@ static void configure_logicalChannelBearer(NR_UE_MAC_INST_t *mac, } if (j < mac->lc_ordered_list.count) { LOG_D(NR_MAC, "Logical channel %d is already established, Reconfiguring now\n", lc_identity); - if (mac_lc_config != NULL) { - NR_SRB_Identity_t srb_id = 0; - if (rlc_bearer->servedRadioBearer->present == NR_RLC_BearerConfig__servedRadioBearer_PR_srb_Identity) - srb_id = rlc_bearer->servedRadioBearer->choice.srb_Identity; - nr_configure_lc_config(mac, mac->lc_ordered_list.array[j], mac_lc_config, srb_id); - } - } - else { + if (mac_lc_config != NULL) + nr_configure_lc_config(mac, mac->lc_ordered_list.array[j], mac_lc_config, rb); + } else { /* setup of new LCID*/ nr_lcordered_info_t *lc_info = calloc(1, sizeof(*lc_info)); lc_info->lcid = lc_identity; @@ -895,12 +914,12 @@ static void configure_logicalChannelBearer(NR_UE_MAC_INST_t *mac, if (rlc_bearer->servedRadioBearer->present == NR_RLC_BearerConfig__servedRadioBearer_PR_srb_Identity) { /* SRB */ NR_SRB_Identity_t srb_id = rlc_bearer->servedRadioBearer->choice.srb_Identity; if (mac_lc_config != NULL) - nr_configure_lc_config(mac, lc_info, mac_lc_config, srb_id); + nr_configure_lc_config(mac, lc_info, mac_lc_config, rb); else set_default_logicalchannelconfig(lc_info, srb_id); } else { /* DRB */ AssertFatal(mac_lc_config, "When establishing a DRB, LogicalChannelConfig should be mandatorily present\n"); - nr_configure_lc_config(mac, lc_info, mac_lc_config, 0); + nr_configure_lc_config(mac, lc_info, mac_lc_config, rb); } ASN_SEQUENCE_ADD(&mac->lc_ordered_list, lc_info); } @@ -1711,6 +1730,13 @@ void nr_rrc_mac_config_req_reset(module_id_t module_id, NR_UE_MAC_reset_cause_t nr_ue_mac_default_configs(mac); nr_ue_reset_sync_state(mac); release_mac_configuration(mac, cause); + // suspend all RBs except SRB0 + for (int j = 0; j < mac->lc_ordered_list.count; j++) { + nr_lcordered_info_t *lc = mac->lc_ordered_list.array[j]; + if (lc->rb.type == NR_LCID_SRB && lc->rb.choice.srb_id == 0) + continue; + lc->rb_suspended = true; + } // apply the timeAlignmentTimerCommon included in SIB1 configure_timeAlignmentTimer(&mac->time_alignment_timer, mac->timeAlignmentTimerCommon, mac->current_UL_BWP->scs); // new sync with old cell ID (re-establishment on the same cell) @@ -1718,6 +1744,15 @@ void nr_rrc_mac_config_req_reset(module_id_t module_id, NR_UE_MAC_reset_cause_t sync_req.ssb_bw_scan = false; nr_ue_send_synch_request(mac, module_id, 0, &sync_req); break; + case RRC_SETUP_REESTAB_RESUME: + release_mac_configuration(mac, cause); + nr_ue_mac_default_configs(mac); + break; + case UL_SYNC_LOST_T430_EXPIRED: + // TS 38.331 Section 5.2.2.6, TS 38.321 Section 5.2a + // Flush all HARQ buffers and Stop UL transmissions + handle_ulsync_loss(mac); + break; default: AssertFatal(false, "Invalid MAC reset cause %d\n", cause); } @@ -1725,6 +1760,29 @@ void nr_rrc_mac_config_req_reset(module_id_t module_id, NR_UE_MAC_reset_cause_t AssertFatal(!ret, "mutex failed %d\n", ret); } +bool is_lcid_suspended(NR_UE_MAC_INST_t *mac, int lcid) +{ + for (int j = 0; j < mac->lc_ordered_list.count; j++) { + nr_lcordered_info_t *lc = mac->lc_ordered_list.array[j]; + if (lc->lcid == lcid) + return lc->rb_suspended; + } + LOG_E(NR_MAC, "LCID %d not found in the MAC list\n", lcid); + return false; +} + +void nr_rrc_mac_resume_rb(module_id_t module_id, bool is_srb, int rb_id) +{ + NR_UE_MAC_INST_t *mac = get_mac_inst(module_id); + for (int j = 0; j < mac->lc_ordered_list.count; j++) { + nr_lcordered_info_t *lc = mac->lc_ordered_list.array[j]; + if (is_srb && lc->rb.type == NR_LCID_SRB && lc->rb.choice.srb_id == rb_id) + lc->rb_suspended = false; + if (!is_srb && lc->rb.type == NR_LCID_DRB && lc->rb.choice.drb_id == rb_id) + lc->rb_suspended = false; + } +} + static void configure_si_schedulingInfo(NR_UE_MAC_INST_t *mac, NR_SI_SchedulingInfo_t *si_SchedulingInfo, NR_SI_SchedulingInfo_v1700_t *si_SchedulingInfo_v1700) diff --git a/openair2/LAYER2/NR_MAC_UE/mac_defs.h b/openair2/LAYER2/NR_MAC_UE/mac_defs.h index b3ca280f86..dee2a30c08 100644 --- a/openair2/LAYER2/NR_MAC_UE/mac_defs.h +++ b/openair2/LAYER2/NR_MAC_UE/mac_defs.h @@ -196,7 +196,9 @@ typedef enum { GO_TO_IDLE, DETACH, T300_EXPIRY, - RE_ESTABLISHMENT + RE_ESTABLISHMENT, + RRC_SETUP_REESTAB_RESUME, + UL_SYNC_LOST_T430_EXPIRED, } NR_UE_MAC_reset_cause_t; typedef struct { @@ -450,6 +452,8 @@ typedef struct nr_lcordered_info_s { uint32_t bucket_size; bool sr_DelayTimerApplied; bool lc_SRMask; + nr_lcid_rb_t rb; + bool rb_suspended; } nr_lcordered_info_t; typedef struct { diff --git a/openair2/LAYER2/NR_MAC_UE/mac_proto.h b/openair2/LAYER2/NR_MAC_UE/mac_proto.h index b058f6e681..c8eab85462 100644 --- a/openair2/LAYER2/NR_MAC_UE/mac_proto.h +++ b/openair2/LAYER2/NR_MAC_UE/mac_proto.h @@ -67,13 +67,16 @@ void release_common_ss_cset(NR_BWP_PDCCH_t *pdcch); \param gNB_index gNB index \param sibs_mask sibs mask \param pduP pointer to pdu - \param pdu_length length of pdu */ + \param pdu_length length of pdu + \param frame,slot Received TTI*/ void nr_ue_decode_BCCH_DL_SCH(NR_UE_MAC_INST_t *mac, int cc_id, unsigned int gNB_index, uint8_t ack_nack, uint8_t *pduP, - uint32_t pdu_len); + uint32_t pdu_len, + int frame, + int slot); void release_dl_BWP(NR_UE_MAC_INST_t *mac, int index); void release_ul_BWP(NR_UE_MAC_INST_t *mac, int index); @@ -93,7 +96,7 @@ void nr_rrc_mac_config_req_sib1(module_id_t module_id, int cc_idP, NR_SIB1_t *si struct position; /* forward declaration */ void nr_rrc_mac_config_other_sib(module_id_t module_id, NR_SIB19_r17_t *sib19_r17, bool can_start_ra); - +void nr_rrc_mac_resume_rb(module_id_t module_id, bool is_srb, int rb_id); void nr_rrc_mac_config_req_reset(module_id_t module_id, NR_UE_MAC_reset_cause_t cause); /**\brief initialization NR UE MAC instance(s)*/ @@ -293,7 +296,7 @@ void configure_csi_resource_mapping(fapi_nr_dl_config_csirs_pdu_rel15_t *csirs_c uint32_t bwp_size, uint32_t bwp_start); - +bool is_lcid_suspended(NR_UE_MAC_INST_t *mac, int lcid); void nr_ra_contention_resolution_failed(NR_UE_MAC_INST_t *mac); void nr_ra_succeeded(NR_UE_MAC_INST_t *mac, const uint8_t gNB_index, const frame_t frame, const int slot); void nr_ra_backoff_setting(RA_config_t *ra); @@ -320,6 +323,7 @@ void nr_Msg3_transmitted(NR_UE_MAC_INST_t *mac, uint8_t CC_id, frame_t frameP, s void trigger_MAC_UE_RA(NR_UE_MAC_INST_t *mac, dci_pdu_rel15_t *pdcch_order); void nr_get_Msg3_MsgA_PUSCH_payload(NR_UE_MAC_INST_t *mac, uint8_t *buf, int TBS_max); void handle_time_alignment_timer_expired(NR_UE_MAC_INST_t *mac); +void handle_ulsync_loss(NR_UE_MAC_INST_t *mac); int8_t nr_ue_process_dci_freq_dom_resource_assignment(nfapi_nr_ue_pusch_pdu_t *pusch_config_pdu, fapi_nr_dl_config_dlsch_pdu_rel15_t *dlsch_config_pdu, NR_PDSCH_Config_t *pdsch_Config, diff --git a/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c b/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c index 6a6c7633bf..e189d7dcf9 100644 --- a/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c +++ b/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c @@ -271,7 +271,7 @@ void release_mac_configuration(NR_UE_MAC_INST_t *mac, NR_UE_MAC_reset_cause_t ca // in case of re-establishment we don't need to release initial BWP config common int first_bwp_rel = 0; // first BWP to release - if (cause == RE_ESTABLISHMENT) { + if (cause == RE_ESTABLISHMENT || cause == RRC_SETUP_REESTAB_RESUME) { first_bwp_rel = 1; // release dedicated BWP0 config NR_UE_DL_BWP_t *bwp = mac->dl_BWPs.array[0]; diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c index 5d3102c07d..8a892557b2 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c @@ -305,11 +305,13 @@ void nr_ue_decode_BCCH_DL_SCH(NR_UE_MAC_INST_t *mac, unsigned int gNB_index, uint8_t ack_nack, uint8_t *pduP, - uint32_t pdu_len) + uint32_t pdu_len, + int frame, + int slot) { if(ack_nack) { LOG_D(NR_MAC, "Decoding NR-BCCH-DL-SCH-Message (SIB1 or SI)\n"); - nr_mac_rrc_data_ind_ue(mac->ue_id, cc_id, gNB_index, 0, 0, 0, mac->physCellId, 0, NR_BCCH_DL_SCH, (uint8_t *) pduP, pdu_len); + nr_mac_rrc_data_ind_ue(mac->ue_id, cc_id, gNB_index, frame, slot, 0, mac->physCellId, 0, NR_BCCH_DL_SCH, (uint8_t *) pduP, pdu_len); if (mac->get_sib1) mac->get_sib1 = false; for (int i = 0; i < MAX_SI_GROUPS; i++) { @@ -325,7 +327,7 @@ void nr_ue_decode_BCCH_DL_SCH(NR_UE_MAC_INST_t *mac, } else { LOG_E(NR_MAC, "Got NACK on NR-BCCH-DL-SCH-Message (%s)\n", mac->get_sib1 ? "SIB1" : "other SI"); - nr_mac_rrc_data_ind_ue(mac->ue_id, cc_id, gNB_index, 0, 0, 0, mac->physCellId, 0, NR_BCCH_DL_SCH, NULL, 0); + nr_mac_rrc_data_ind_ue(mac->ue_id, cc_id, gNB_index, frame, slot, 0, mac->physCellId, 0, NR_BCCH_DL_SCH, NULL, 0); } } @@ -3734,7 +3736,7 @@ void nr_ue_process_mac_pdu(NR_UE_MAC_INST_t *mac, nr_downlink_indication_t *dl_i LOG_D(MAC, "[UE] LCID %d, PDU length %d\n", rx_lcid, pdu_len); bool ret; - switch(rx_lcid){ + switch (rx_lcid) { // MAC CE case DL_SCH_LCID_CCCH: // MSG4 RRC Setup 38.331 @@ -3871,6 +3873,11 @@ void nr_ue_process_mac_pdu(NR_UE_MAC_INST_t *mac, nr_downlink_indication_t *dl_i case 1 ... 32: if (!get_mac_len(pduP, pdu_len, &mac_len, &mac_subheader_len)) return; + // discard the received subPDU if RB is suspended + if (is_lcid_suspended(mac, rx_lcid)) { + LOG_W(NR_MAC, "Received PDU for a suspended RB, corresponding to LCID %d. Dropping it.\n", rx_lcid); + break; + } LOG_D(NR_MAC, "%4d.%2d : DLSCH -> LCID %d %d bytes\n", frameP, slot, rx_lcid, mac_len); nr_mac_rlc_data_ind(mac->ue_id, mac->ue_id, false, rx_lcid, (char *)(pduP + mac_subheader_len), mac_len); break; @@ -3878,8 +3885,8 @@ void nr_ue_process_mac_pdu(NR_UE_MAC_INST_t *mac, nr_downlink_indication_t *dl_i LOG_W(MAC, "unknown lcid %02x\n", rx_lcid); break; } - pduP += ( mac_subheader_len + mac_len ); - pdu_len -= ( mac_subheader_len + mac_len ); + pduP += (mac_subheader_len + mac_len); + pdu_len -= (mac_subheader_len + mac_len); if (pdu_len < 0) LOG_E(MAC, "[UE %d][%d.%d] nr_ue_process_mac_pdu, residual mac pdu length %d < 0!\n", mac->ue_id, frameP, slot, pdu_len); } diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c index b810bf8de6..2c37b21f5b 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c @@ -182,6 +182,27 @@ void handle_time_alignment_timer_expired(NR_UE_MAC_INST_t *mac) // TODO not sure what to do here } +void handle_ulsync_loss(NR_UE_MAC_INST_t *mac) +{ + // flush all HARQ buffers for all Serving Cells + for (int k = 0; k < NR_MAX_HARQ_PROCESSES; k++) { + memset(&mac->dl_harq_info[k], 0, sizeof(*mac->dl_harq_info)); + memset(&mac->ul_harq_info[k], 0, sizeof(*mac->ul_harq_info)); + mac->dl_harq_info[k].last_ndi = -1; // initialize to invalid value + mac->ul_harq_info[k].last_ndi = -1; // initialize to invalid value + } + // clear any configured downlink assignments and uplink grants; + if (mac->dl_config_request) + memset(mac->dl_config_request, 0, sizeof(*mac->dl_config_request)); + if (mac->ul_config_request) + clear_ul_config_request(mac); + + // Need to receive SIB19 again after loosing UL SYNC + mac->state = UE_RECEIVING_SIB; + // gNB needs to send PDCCH ORDER triggering RA after detecting ULSYNC LOSS + LOG_W(NR_MAC, "Wait for PDCCH ORDER, RACH needs to performed to obtain ULSYNC.\n"); +} + void update_mac_dl_timers(NR_UE_MAC_INST_t *mac) { bool ra_window_expired = nr_timer_tick(&mac->ra.response_window_timer); @@ -1266,10 +1287,11 @@ static void nr_update_rlc_buffers_status(NR_UE_MAC_INST_t *mac, frame_t frameP, { for (int i = 0; i < mac->lc_ordered_list.count; i++) { nr_lcordered_info_t *lc_info = mac->lc_ordered_list.array[i]; + if (lc_info->rb_suspended) + continue; int lcid = lc_info->lcid; NR_LC_SCHEDULING_INFO *lc_sched_info = get_scheduling_info_from_lcid(mac, lcid); mac_rlc_status_resp_t rlc_status = nr_mac_rlc_status_ind(mac->ue_id, frameP, lcid); - if (rlc_status.bytes_in_buffer > 0) { LOG_D(NR_MAC, "[UE %d] LCID %d has %d bytes to transmit at sfn %d.%d\n", @@ -2553,6 +2575,8 @@ static bool fill_mac_sdu(NR_UE_MAC_INST_t *mac, lcid_remain_buffer, lcid); + if (is_lcid_suspended(mac, lcid)) + return false; if (mac_ce_p->end_for_tailer - mac_ce_p->cur_ptr < sizeof(NR_MAC_SUBHEADER_LONG)) // We can't add one byte after the header return false; diff --git a/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.c b/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.c index 8dfa57f92b..88c8d5d377 100644 --- a/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.c +++ b/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.c @@ -77,10 +77,10 @@ static uint64_t get_nr_rlc_current_time(void) static void release_rlc_entity_from_lcid(nr_rlc_ue_t *ue, logical_chan_id_t channel_id) { AssertFatal(channel_id != 0, "LCID = 0 shouldn't be handled here\n"); - nr_rlc_rb_t *rb = &ue->lcid2rb[channel_id - 1]; - if (rb->type == NR_RLC_NONE) + nr_lcid_rb_t *rb = &ue->lcid2rb[channel_id - 1]; + if (rb->type == NR_LCID_NONE) return; - if (rb->type == NR_RLC_SRB) { + if (rb->type == NR_LCID_SRB) { int id = rb->choice.srb_id - 1; AssertFatal(id >= 0, "logic bug: impossible to have srb0 here\n"); if (ue->srb[id]) { @@ -91,7 +91,7 @@ static void release_rlc_entity_from_lcid(nr_rlc_ue_t *ue, logical_chan_id_t chan LOG_E(RLC, "Trying to release a non-established enity with LCID %d\n", channel_id); } else { - AssertFatal(rb->type == NR_RLC_DRB, + AssertFatal(rb->type == NR_LCID_DRB, "Invalid RB type\n"); int id = rb->choice.drb_id - 1; if (ue->drb[id]) { @@ -108,14 +108,14 @@ logical_chan_id_t nr_rlc_get_lcid_from_rb(int ue_id, bool is_srb, int rb_id) nr_rlc_manager_lock(nr_rlc_ue_manager); nr_rlc_ue_t *ue = nr_rlc_manager_get_ue(nr_rlc_ue_manager, ue_id); for (logical_chan_id_t id = 1; id <= 32; id++) { - nr_rlc_rb_t *rb = &ue->lcid2rb[id - 1]; + nr_lcid_rb_t *rb = &ue->lcid2rb[id - 1]; if (is_srb) { - if (rb->type == NR_RLC_SRB && rb->choice.srb_id == rb_id) { + if (rb->type == NR_LCID_SRB && rb->choice.srb_id == rb_id) { nr_rlc_manager_unlock(nr_rlc_ue_manager); return id; } } else { - if (rb->type == NR_RLC_DRB && rb->choice.drb_id == rb_id) { + if (rb->type == NR_LCID_DRB && rb->choice.drb_id == rb_id) { nr_rlc_manager_unlock(nr_rlc_ue_manager); return id; } @@ -130,14 +130,14 @@ static nr_rlc_entity_t *get_rlc_entity_from_lcid(nr_rlc_ue_t *ue, logical_chan_i { if (channel_id == 0) return ue->srb0; - nr_rlc_rb_t *rb = &ue->lcid2rb[channel_id - 1]; - if (rb->type == NR_RLC_NONE) + nr_lcid_rb_t *rb = &ue->lcid2rb[channel_id - 1]; + if (rb->type == NR_LCID_NONE) return NULL; - if (rb->type == NR_RLC_SRB) { + if (rb->type == NR_LCID_SRB) { AssertFatal(rb->choice.srb_id > 0, "logic bug: impossible to have srb0 here\n"); return ue->srb[rb->choice.srb_id - 1]; } else { - AssertFatal(rb->type == NR_RLC_DRB, + AssertFatal(rb->type == NR_LCID_DRB, "Invalid RB type\n"); return ue->drb[rb->choice.drb_id - 1]; } @@ -698,7 +698,7 @@ void nr_rlc_add_srb(int ue_id, int srb_id, const NR_RLC_BearerConfig_t *rlc_Bear NR_RLC_BearerConfig__servedRadioBearer_PR_srb_Identity), "servedRadioBearer for SRB mandatory present when setting up an SRB RLC entity\n"); int local_id = rlc_BearerConfig->logicalChannelIdentity - 1; // LCID 0 for SRB 0 not mapped - ue->lcid2rb[local_id].type = NR_RLC_SRB; + ue->lcid2rb[local_id].type = NR_LCID_SRB; ue->lcid2rb[local_id].choice.srb_id = rlc_BearerConfig->servedRadioBearer->choice.srb_Identity; if (ue->srb[srb_id-1] != NULL) { LOG_E(RLC, "SRB %d already exists for UE %d, do nothing\n", srb_id, ue_id); @@ -763,7 +763,7 @@ static void add_drb_am(int ue_id, int drb_id, const NR_RLC_BearerConfig_t *rlc_B NR_RLC_BearerConfig__servedRadioBearer_PR_drb_Identity), "servedRadioBearer for DRB mandatory present when setting up an SRB RLC entity\n"); int local_id = rlc_BearerConfig->logicalChannelIdentity - 1; // LCID 0 for SRB 0 not mapped - ue->lcid2rb[local_id].type = NR_RLC_DRB; + ue->lcid2rb[local_id].type = NR_LCID_DRB; ue->lcid2rb[local_id].choice.drb_id = rlc_BearerConfig->servedRadioBearer->choice.drb_Identity; if (ue->drb[drb_id-1] != NULL) { LOG_E(RLC, "DRB %d already exists for UE %d, do nothing\n", drb_id, ue_id); @@ -818,7 +818,7 @@ static void add_drb_um(int ue_id, int drb_id, const NR_RLC_BearerConfig_t *rlc_B NR_RLC_BearerConfig__servedRadioBearer_PR_drb_Identity), "servedRadioBearer for DRB mandatory present when setting up an SRB RLC entity\n"); int local_id = rlc_BearerConfig->logicalChannelIdentity - 1; // LCID 0 for SRB 0 not mapped - ue->lcid2rb[local_id].type = NR_RLC_DRB; + ue->lcid2rb[local_id].type = NR_LCID_DRB; ue->lcid2rb[local_id].choice.drb_id = rlc_BearerConfig->servedRadioBearer->choice.drb_Identity; if (ue->drb[drb_id-1] != NULL) { LOG_E(RLC, "DEBUG add_drb_um: warning DRB %d already exist for ue %d, do nothing\n", drb_id, ue_id); diff --git a/openair2/LAYER2/nr_rlc/nr_rlc_ue_manager.h b/openair2/LAYER2/nr_rlc/nr_rlc_ue_manager.h index 3dec237958..67484e7108 100644 --- a/openair2/LAYER2/nr_rlc/nr_rlc_ue_manager.h +++ b/openair2/LAYER2/nr_rlc/nr_rlc_ue_manager.h @@ -28,22 +28,12 @@ typedef void nr_rlc_ue_manager_t; -typedef enum nr_rlc_rb_type { NR_RLC_NONE = 0, NR_RLC_SRB = 1, NR_RLC_DRB = 2 } nr_rlc_rb_type; - typedef enum { NR_RLC_OP_MODE_SPLIT_GNB, NR_RLC_OP_MODE_MONO_GNB, NR_RLC_OP_MODE_UE, } nr_rlc_op_mode_t; -typedef struct nr_rlc_rb_t { - nr_rlc_rb_type type; - union { - int srb_id; - int drb_id; - } choice; -} nr_rlc_rb_t; - typedef void (*rlf_handler_t)(int rnti); typedef struct nr_rlc_ue_t { @@ -51,7 +41,7 @@ typedef struct nr_rlc_ue_t { nr_rlc_entity_t *srb0; nr_rlc_entity_t *srb[3]; nr_rlc_entity_t *drb[MAX_DRBS_PER_UE]; - nr_rlc_rb_t lcid2rb[32]; + nr_lcid_rb_t lcid2rb[32]; rlf_handler_t rlf_handler; } nr_rlc_ue_t; diff --git a/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c b/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c index 0d0829181e..e13ddac506 100644 --- a/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c +++ b/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c @@ -90,7 +90,14 @@ void print_ue_mac_stats(const module_id_t mod, const int frame_rx, const int slo if (nbdl < 1) nbdl = 1; - cur += snprintf(cur, end - cur, "UE %d stats sfn: %d.%d, cumulated bad DCI %d\n", mod, frame_rx, slot_rx, mac->stats.bad_dci); + cur += snprintf(cur, + end - cur, + "UE %d RNTI %04x stats sfn: %d.%d, cumulated bad DCI %d\n", + mod, + mac->crnti, + frame_rx, + slot_rx, + mac->stats.bad_dci); cur += snprintf(cur, end - cur, " DL harq: %lu", mac->stats.dl.rounds[0]); int nb; @@ -1106,9 +1113,11 @@ static int handle_bcch_dlsch(NR_UE_MAC_INST_t *mac, unsigned int gNB_index, uint8_t ack_nack, uint8_t *pduP, - uint32_t pdu_len) + uint32_t pdu_len, + int frame, + int slot) { - nr_ue_decode_BCCH_DL_SCH(mac, cc_id, gNB_index, ack_nack, pduP, pdu_len); + nr_ue_decode_BCCH_DL_SCH(mac, cc_id, gNB_index, ack_nack, pduP, pdu_len, frame, slot); return 0; } @@ -1290,10 +1299,13 @@ static uint32_t nr_ue_dl_processing(NR_UE_MAC_INST_t *mac, nr_downlink_indicatio break; case FAPI_NR_RX_PDU_TYPE_SIB: ret_mask |= (handle_bcch_dlsch(mac, - dl_info->cc_id, dl_info->gNB_index, + dl_info->cc_id, + dl_info->gNB_index, rx_indication_body.pdsch_pdu.ack_nack, rx_indication_body.pdsch_pdu.pdu, - rx_indication_body.pdsch_pdu.pdu_length)) << FAPI_NR_RX_PDU_TYPE_SIB; + rx_indication_body.pdsch_pdu.pdu_length, + dl_info->frame, + dl_info->slot)) << FAPI_NR_RX_PDU_TYPE_SIB; break; case FAPI_NR_RX_PDU_TYPE_DLSCH: ret_mask |= (handle_dlsch(mac, dl_info, i)) << FAPI_NR_RX_PDU_TYPE_DLSCH; diff --git a/openair2/RRC/NR/rrc_gNB.c b/openair2/RRC/NR/rrc_gNB.c index f69e03b810..2ef11ce605 100644 --- a/openair2/RRC/NR/rrc_gNB.c +++ b/openair2/RRC/NR/rrc_gNB.c @@ -2542,6 +2542,34 @@ void rrc_gNB_process_e1_bearer_context_release_cplt(const e1ap_bearer_release_cp LOG_I(RRC, "UE %d: received bearer release complete\n", cplt->gNB_cu_cp_ue_id); } +static void print_meas_result_quantity(FILE *f, const NR_MeasQuantityResults_t *mqr) +{ + fprintf(f, " resultSSB:"); + if (!mqr) { + fprintf(f, " NOT PROVIDED\n"); + return; + } + if (mqr->rsrp) { + const long rrsrp = *mqr->rsrp - 156; + fprintf(f, " RSRP %ld dBm", rrsrp); + } else { + fprintf(f, " RSRP not provided"); + } + if (mqr->rsrq) { + const float rrsrq = (float) (*mqr->rsrq - 87) / 2.0f; + fprintf(f, " RSRQ %.1f dB", rrsrq); + } else { + fprintf(f, " RSRQ not provided"); + } + if (mqr->sinr) { + const float rsinr = (float) (*mqr->sinr - 46) / 2.0f; + fprintf(f, " SINR %.1f dB", rsinr); + } else { + fprintf(f, " SINR not provided"); + } + fprintf(f, "\n"); +} + static void print_rrc_meas(FILE *f, const NR_MeasResults_t *measresults) { DevAssert(measresults->measResultServingMOList.list.count >= 1); @@ -2550,37 +2578,21 @@ static void print_rrc_meas(FILE *f, const NR_MeasResults_t *measresults) NR_MeasResultServMO_t *measresultservmo = measresults->measResultServingMOList.list.array[0]; NR_MeasResultNR_t *measresultnr = &measresultservmo->measResultServingCell; - NR_MeasQuantityResults_t *mqr = measresultnr->measResult.cellResults.resultsSSB_Cell; if (measresultnr->physCellId) fprintf(f, - " servingCellId %ld MeasResultNR for phyCellId %ld:\n resultSSB:", + " servingCellId %ld MeasResultNR for phyCellId %ld:\n", measresultservmo->servCellId, *measresultnr->physCellId); - if (mqr != NULL) { - const long rrsrp = *mqr->rsrp - 156; - const float rrsrq = (float) (*mqr->rsrq - 87) / 2.0f; - const float rsinr = (float) (*mqr->sinr - 46) / 2.0f; - fprintf(f, "RSRP %ld dBm RSRQ %.1f dB SINR %.1f dB\n", rrsrp, rrsrq, rsinr); - } else { - fprintf(f, "NOT PROVIDED\n"); - } + print_meas_result_quantity(f, measresultnr->measResult.cellResults.resultsSSB_Cell); if (measresults->measResultNeighCells && measresults->measResultNeighCells->present == NR_MeasResults__measResultNeighCells_PR_measResultListNR) { NR_MeasResultListNR_t *meas_neigh = measresults->measResultNeighCells->choice.measResultListNR; for (int i = 0; i < meas_neigh->list.count; ++i) { NR_MeasResultNR_t *measresultneigh = meas_neigh->list.array[i]; - NR_MeasQuantityResults_t *neigh_mqr = measresultneigh->measResult.cellResults.resultsSSB_Cell; if (measresultneigh->physCellId) - fprintf(f, " neighboring cell for phyCellId %ld:\n resultSSB:", *measresultneigh->physCellId); - if (mqr != NULL) { - const long rrsrp = *neigh_mqr->rsrp - 156; - const float rrsrq = (float)(*neigh_mqr->rsrq - 87) / 2.0f; - const float rsinr = (float)(*neigh_mqr->sinr - 46) / 2.0f; - fprintf(f, "RSRP %ld dBm RSRQ %.1f dB SINR %.1f dB\n", rrsrp, rrsrq, rsinr); - } else { - fprintf(f, "NOT PROVIDED\n"); - } + fprintf(f, " neighboring cell for phyCellId %ld:\n", *measresultneigh->physCellId); + print_meas_result_quantity(f, measresultneigh->measResult.cellResults.resultsSSB_Cell); } } } diff --git a/openair2/RRC/NR_UE/L2_interface_ue.c b/openair2/RRC/NR_UE/L2_interface_ue.c index 09bce459f2..fe2eb2cfed 100644 --- a/openair2/RRC/NR_UE/L2_interface_ue.c +++ b/openair2/RRC/NR_UE/L2_interface_ue.c @@ -146,6 +146,9 @@ void process_msg_rcc_to_mac(MessageDef *msg) bool can_start_ra = NR_MAC_RRC_CONFIG_OTHER_SIB(msg).can_start_ra; nr_rrc_mac_config_other_sib(ue_id, NR_MAC_RRC_CONFIG_OTHER_SIB(msg).sib19, can_start_ra); } break; + case NR_MAC_RRC_RESUME_RB: + nr_rrc_mac_resume_rb(ue_id, NR_MAC_RRC_RESUME_RB(msg).is_srb, NR_MAC_RRC_RESUME_RB(msg).rb_id); + break; default: LOG_E(NR_MAC, "Unexpected msg from RRC: %d\n", ITTI_MSG_ID(msg)); } diff --git a/openair2/RRC/NR_UE/rrc_UE.c b/openair2/RRC/NR_UE/rrc_UE.c index bb58191e24..90713ff50c 100644 --- a/openair2/RRC/NR_UE/rrc_UE.c +++ b/openair2/RRC/NR_UE/rrc_UE.c @@ -144,7 +144,8 @@ static void process_lte_nsa_msg(NR_UE_RRC_INST_t *rrc, nsa_msg_t *msg, int msg_l static void nr_rrc_ue_process_ueCapabilityEnquiry(NR_UE_RRC_INST_t *rrc, NR_UECapabilityEnquiry_t *UECapabilityEnquiry); static void nr_rrc_ue_process_masterCellGroup(NR_UE_RRC_INST_t *rrc, OCTET_STRING_t *masterCellGroup, - long *fullConfig); + long *fullConfig, + int gNB_index); static void nr_rrc_ue_process_measConfig(rrcPerNB_t *rrc, NR_MeasConfig_t *const measConfig, NR_UE_Timers_Constants_t *timers); @@ -165,7 +166,120 @@ static void set_DRB_status(NR_UE_RRC_INST_t *rrc, NR_DRB_Identity_t drb_id, NR_R rrc->status_DRBs[drb_id - 1] = status; } -static void nr_decode_SI(NR_UE_RRC_SI_INFO *SI_info, NR_SystemInformation_t *si, NR_UE_RRC_INST_t *rrc) +static int get_ulsyncvalidityduration_timer_value(NR_NTN_Config_r17_t *ntncfg) +{ + int retval = 0; + AssertFatal(ntncfg, "NTN-Config IE not present\n"); + + if (ntncfg->ntn_UlSyncValidityDuration_r17) { + const int values[] = {5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 120, 180, 240, 900}; + retval = values[*ntncfg->ntn_UlSyncValidityDuration_r17]; + } + + return retval; +} + +static void get_epochtime_from_sib19scheduling(NR_UE_RRC_SI_INFO *SI_info, int *frame, int *subframe) +{ + // TS 38.331 section 5.2.2.3.2 + // SI-window starts at the slot #a, where a = x mod N + // x = (si-WindowPosition -1) × w, where w is the si-WindowLength; + // N is the number of slots in a radio frame + int wl_slots = 5 << SI_info->si_windowlength; + int x = (SI_info->sib19_windowposition - 1) * wl_slots; + int slots_per_subframe = 1 << SI_info->scs; + int N = slots_per_subframe * 10; + int slot_end_sib19_window = (x % N) + wl_slots; + + *frame += (slot_end_sib19_window / N); + int slot = slot_end_sib19_window % N; + *subframe = ceil(slot / slots_per_subframe); + + LOG_D(NR_RRC, + "Get EPOCHTIME: x:%d, N:%d, slot_endw:%d, frame:%d, subframe:%d , slot:%d\n", + x, + N, + slot_end_sib19_window, + *frame, + *subframe, + slot); +} + +static int eval_epoch_time(NR_UE_RRC_SI_INFO *SI_info, NR_NTN_Config_r17_t *ntncfg, int frame) +{ + int epoch_frame = 0, epoch_subframe = 0; + int diff_frames = 0; + AssertFatal(frame >= 0, "Frame Incorrect, results in incorrect EPOCH time evaluation\n"); + if (ntncfg->epochTime_r17) { + epoch_frame = ntncfg->epochTime_r17->sfn_r17; + epoch_subframe = ntncfg->epochTime_r17->subFrameNR_r17; + } else { + // EPOCH time is optional in case of SIB19. This case happens only in case of SIB19 NTN config + // If no EPOCH time is sent, epochtime points to SIB19 window end slot in the current scheduling window + epoch_frame = frame; + epoch_subframe = 0; + get_epochtime_from_sib19scheduling(SI_info, &epoch_frame, &epoch_subframe); + // Adding epochTime IE in SIB19, later MAC will use it. + ntncfg->epochTime_r17 = CALLOC(1, sizeof(NR_EpochTime_r17_t)); + ntncfg->epochTime_r17->sfn_r17 = epoch_frame; + ntncfg->epochTime_r17->subFrameNR_r17 = epoch_subframe; + } + // For serving cell, the field sfn indicates the current SFN or the next upcoming SFN + // after the frame where the message indicating the epochTime is received + // i.e. Epochframe can be present or future SFN + diff_frames = (epoch_frame - frame + 1024) % 1024; // According to 38.331 Epochtime is defined for serving cell like this + LOG_D(NR_RRC, "Epoch frame %d, ahead by %d frames\n", epoch_frame, diff_frames); + return diff_frames; +} + +static int get_ntn_timervalues(NR_UE_RRC_SI_INFO *SI_info, NR_NTN_Config_r17_t *ntncfg, int diff_frames, int *val430_ms) +{ + int val430 = get_ulsyncvalidityduration_timer_value(ntncfg); + int sib19_periodicity_ms = (SI_info->sib19_periodicity + 1) * 10; + *val430_ms = val430 * 1000 + diff_frames * 10; // in ms + if (*val430_ms <= sib19_periodicity_ms) + LOG_E(NR_RRC, "Too small T430 value. Might result in frequent ULSYNC failure\n"); + + // Depending on ulsyncvalidity duration, SIB19 timer expires 15secs/2secs before T430 + // LArger values might be used for GEO and epoch time interval can be around 10 secs + // Lower values will be used for NGSO (LEO/MEO), epoch time interval can be between 2-3 secs. + // TODO remove the hardoded values and define a better strategy to determine the time of expiry + // with real GEO/LEO/MEO SATs. + int expire_before_ms = ((val430 >= 120) ? 10000 : 2000); + int diff = *val430_ms - expire_before_ms; + int sib19_timer_ms = (diff > 0) ? diff : ((*val430_ms - sib19_periodicity_ms) > 0) ? (*val430_ms - sib19_periodicity_ms) : 0; + LOG_D(NR_RRC, "val430:%d s, T430:%d ms, sib19_timer:%d ms\n", val430, *val430_ms, sib19_timer_ms); + return sib19_timer_ms; +} + +static void nr_rrc_process_ntnconfig(NR_UE_RRC_INST_t *rrc, NR_UE_RRC_SI_INFO *SI_info, NR_NTN_Config_r17_t *ntncfg, int frame) +{ + SI_info->SInfo_r17.sib19_validity = true; + // Check if Epochtime is sent or not + int diff_frames = eval_epoch_time(SI_info, ntncfg, frame); + + if (ntncfg->ntn_UlSyncValidityDuration_r17) { // ulsyncvalidity duration configured + int val430_ms = 0, sib19_timer_ms = 0; + sib19_timer_ms = get_ntn_timervalues(SI_info, ntncfg, diff_frames, &val430_ms); + // T430 should be started only in connected mode. + // Inorder to avoid starting T430 when entering connected mode, T430 is started as soon as + // SIB19 is received, and if UE enters connected mode T430 will be in running. + // T430 expiry in RRC idle or inactive states does nothing. + nr_timer_setup(&rrc->timers_and_constants.T430, val430_ms, 10); + nr_timer_start(&rrc->timers_and_constants.T430); + // SIB19 should be received before T430 expires + // SIB19 validity timer should expire before T430 expiry such that new SIB19 is read + if (sib19_timer_ms > 0) { + nr_timer_setup(&SI_info->SInfo_r17.sib19_timer, sib19_timer_ms, 10); + nr_timer_start(&SI_info->SInfo_r17.sib19_timer); + } else + // This makes sure that SIB19 is read again in the next window + SI_info->SInfo_r17.sib19_validity = false; + } else + nr_timer_start(&SI_info->SInfo_r17.sib19_timer); +} + +static void nr_decode_SI(NR_UE_RRC_SI_INFO *SI_info, NR_SystemInformation_t *si, NR_UE_RRC_INST_t *rrc, int frame) { instance_t ue_id = rrc->ue_id; VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_RRC_UE_DECODE_SI, VCD_FUNCTION_IN); @@ -240,11 +354,10 @@ static void nr_decode_SI(NR_UE_RRC_SI_INFO *SI_info, NR_SystemInformation_t *si, nr_timer_start(&SI_info->sib14_timer); break; case NR_SystemInformation_IEs__sib_TypeAndInfo__Member_PR_sib19_v1700: - SI_info->SInfo_r17.sib19_validity = true; - if (g_log->log_component[NR_RRC].level >= OAILOG_DEBUG) - xer_fprint(stdout, &asn_DEF_NR_SIB19_r17, (const void *)typeandinfo->choice.sib19_v1700); sib19 = typeandinfo->choice.sib19_v1700; - nr_timer_start(&SI_info->SInfo_r17.sib19_timer); + if (g_log->log_component[NR_RRC].level >= OAILOG_DEBUG) + xer_fprint(stdout, &asn_DEF_NR_SIB19_r17, (const void *)sib19); + nr_rrc_process_ntnconfig(rrc, SI_info, sib19->ntn_Config_r17, frame); break; default: break; @@ -335,6 +448,27 @@ static bool verify_NTN_access(const NR_UE_RRC_SI_INFO *SI_info, const NR_SIB1_v1 return ntn_access && sib19_present; } +static void get_sib19_schedinfo(NR_UE_RRC_SI_INFO *SI_info, NR_SI_SchedulingInfo_v1700_t *si_SchedInfo_v1700) +{ + // Find the SIB19 periodicity configured in the scheduling info + if (si_SchedInfo_v1700) { + int count_v17 = si_SchedInfo_v1700->schedulingInfoList2_r17.list.count; + for (int i = 0; i < count_v17; i++) { + struct NR_SchedulingInfo2_r17 *schedulingInfo2 = si_SchedInfo_v1700->schedulingInfoList2_r17.list.array[i]; + for (int j = 0; j < schedulingInfo2->sib_MappingInfo_r17.list.count; j++) { + struct NR_SIB_TypeInfo_v1700 *sib_TypeInfo_v1700 = schedulingInfo2->sib_MappingInfo_r17.list.array[j]; + if (sib_TypeInfo_v1700->sibType_r17.present == NR_SIB_TypeInfo_v1700__sibType_r17_PR_type1_r17) { + if (sib_TypeInfo_v1700->sibType_r17.choice.type1_r17 == NR_SIB_TypeInfo_v1700__sibType_r17__type1_r17_sibType19) { + SI_info->sib19_periodicity = 8 << schedulingInfo2->si_Periodicity_r17; + SI_info->sib19_windowposition = schedulingInfo2->si_WindowPosition_r17; + return; + } + } + } + } + } +} + static void nr_rrc_process_sib1(NR_UE_RRC_INST_t *rrc, NR_UE_RRC_SI_INFO *SI_info, NR_SIB1_t *sib1) { if(g_log->log_component[NR_RRC].level >= OAILOG_DEBUG) @@ -355,9 +489,14 @@ static void nr_rrc_process_sib1(NR_UE_RRC_INST_t *rrc, NR_UE_RRC_SI_INFO *SI_inf si_SchedInfo_v1700 = sib1_v1700->si_SchedulingInfo_v1700; } + AssertFatal(sib1->servingCellConfigCommon, "configuration issue in SIB1\n"); + SI_info->scs = sib1->servingCellConfigCommon->downlinkConfigCommon.initialDownlinkBWP.genericParameters.subcarrierSpacing; + SI_info->si_windowlength = (sib1->si_SchedulingInfo) ? sib1->si_SchedulingInfo->si_WindowLength : 0; // configure default SI nr_rrc_configure_default_SI(SI_info, sib1->si_SchedulingInfo, si_SchedInfo_v1700); rrc->is_NTN_UE = verify_NTN_access(SI_info, sib1_v1700); + if (rrc->is_NTN_UE) + get_sib19_schedinfo(SI_info, si_SchedInfo_v1700); // configure timers and constant nr_rrc_set_sib1_timers_and_constants(&rrc->timers_and_constants, sib1); @@ -376,7 +515,7 @@ static void nr_rrc_process_reconfiguration_v1530(NR_UE_RRC_INST_t *rrc, NR_RRCRe LOG_E(NR_RRC, "RRCReconfiguration includes fullConfig but this is not implemented yet\n"); } if (rec_1530->masterCellGroup) - nr_rrc_ue_process_masterCellGroup(rrc, rec_1530->masterCellGroup, rec_1530->fullConfig); + nr_rrc_ue_process_masterCellGroup(rrc, rec_1530->masterCellGroup, rec_1530->fullConfig, gNB_index); if (rec_1530->masterKeyUpdate) { // TODO perform AS security key update procedure as specified in 5.3.5.7 LOG_E(NR_RRC, "RRCReconfiguration includes masterKeyUpdate but this is not implemented yet\n"); @@ -426,7 +565,7 @@ static void nr_rrc_process_reconfiguration_v1530(NR_UE_RRC_INST_t *rrc, NR_RRCRe SEQUENCE_free(&asn_DEF_NR_SystemInformation, si, 1); } else { LOG_I(NR_RRC, "[UE %ld] Decoding dedicatedSystemInformationDelivery\n", rrc->ue_id); - nr_decode_SI(SI_info, si, rrc); + nr_decode_SI(SI_info, si, rrc, rrc->current_frame); } } if (rec_1530->otherConfig) { @@ -502,7 +641,7 @@ static void nr_rrc_ue_process_rrcReconfiguration(NR_UE_RRC_INST_t *rrc, int gNB_ if (LOG_DEBUGFLAG(DEBUG_ASN1)) xer_fprint(stdout, &asn_DEF_NR_CellGroupConfig, (const void *) cellGroupConfig); - nr_rrc_cellgroup_configuration(rrc, cellGroupConfig); + nr_rrc_cellgroup_configuration(rrc, cellGroupConfig, gNB_index); AssertFatal(!IS_SA_MODE(get_softmodem_params()), "secondaryCellGroup only used in NSA for now\n"); MessageDef *msg = itti_alloc_new_message(TASK_RRC_NRUE, 0, NR_MAC_RRC_CONFIG_CG); @@ -894,6 +1033,10 @@ static void nr_rrc_handle_msg3_indication(NR_UE_RRC_INST_t *rrc, rnti_t rnti) nr_rlc_reconfigure_entity(rrc->ue_id, lc_id, NULL); // resume SRB1 rrc->Srb[srb_id] = RB_ESTABLISHED; + MessageDef *msg = itti_alloc_new_message(TASK_RRC_NRUE, 0, NR_MAC_RRC_RESUME_RB); + NR_MAC_RRC_RESUME_RB(msg).is_srb = true; + NR_MAC_RRC_RESUME_RB(msg).rb_id = 1; + itti_send_msg_to_task(TASK_MAC_UE, rrc->ue_id, msg); break; case DURING_HANDOVER: AssertFatal(1==0, "ra_trigger not implemented yet!\n"); @@ -924,7 +1067,9 @@ static void nr_rrc_ue_decode_NR_BCCH_DL_SCH_Message(NR_UE_RRC_INST_t *rrc, uint8_t *const Sdu, const uint8_t Sdu_len, const uint8_t rsrq, - const uint8_t rsrp) + const uint8_t rsrp, + int frame, + int slot) { NR_UE_RRC_SI_INFO *SI_info = &rrc->perNB[gNB_index].SInfo; SI_info->sib_pending = false; @@ -960,9 +1105,9 @@ static void nr_rrc_ue_decode_NR_BCCH_DL_SCH_Message(NR_UE_RRC_INST_t *rrc, bcch_message->message.choice.c1->choice.systemInformationBlockType1 = NULL; break; case NR_BCCH_DL_SCH_MessageType__c1_PR_systemInformation: - LOG_I(NR_RRC, "[UE %ld] Decoding SI\n", rrc->ue_id); + LOG_I(NR_RRC, "[UE %ld] %d:%d Decoding SI\n", rrc->ue_id, frame, slot); NR_SystemInformation_t *si = bcch_message->message.choice.c1->choice.systemInformation; - nr_decode_SI(SI_info, si, rrc); + nr_decode_SI(SI_info, si, rrc, frame); break; case NR_BCCH_DL_SCH_MessageType__c1_PR_NOTHING: default: @@ -1019,7 +1164,9 @@ static void nr_rrc_manage_rlc_bearers(NR_UE_RRC_INST_t *rrc, } } -static void nr_rrc_process_reconfigurationWithSync(NR_UE_RRC_INST_t *rrc, NR_ReconfigurationWithSync_t *reconfigurationWithSync) +static void nr_rrc_process_reconfigurationWithSync(NR_UE_RRC_INST_t *rrc, + NR_ReconfigurationWithSync_t *reconfigurationWithSync, + int gNB_index) { // perform Reconfiguration with sync according to 5.3.5.5.2 if (!rrc->as_security_activated && !(get_softmodem_params()->phy_test || get_softmodem_params()->do_ra)) { @@ -1051,15 +1198,26 @@ static void nr_rrc_process_reconfigurationWithSync(NR_UE_RRC_INST_t *rrc, NR_Rec } rrc->rnti = reconfigurationWithSync->newUE_Identity; // reset the MAC entity of this cell group (done at MAC in handle_reconfiguration_with_sync) + + // 3GPP TS38.331 section 5.3.5.5.2 + nr_timer_stop(&tac->T430); + if (reconfigurationWithSync->spCellConfigCommon && + reconfigurationWithSync->spCellConfigCommon->ext2 && + reconfigurationWithSync->spCellConfigCommon->ext2->ntn_Config_r17) { + NR_NTN_Config_r17_t *ntncfg = reconfigurationWithSync->spCellConfigCommon->ext2->ntn_Config_r17; + // EPOCH time is always sent if NTN config is sent through DCCH + AssertFatal(ntncfg->epochTime_r17, "NTN-CONFIG sent in dedicated mode should have EPOCHTIME\n"); + nr_rrc_process_ntnconfig(rrc, &rrc->perNB[gNB_index].SInfo, ntncfg, rrc->current_frame); + } } -void nr_rrc_cellgroup_configuration(NR_UE_RRC_INST_t *rrc, NR_CellGroupConfig_t *cellGroupConfig) +void nr_rrc_cellgroup_configuration(NR_UE_RRC_INST_t *rrc, NR_CellGroupConfig_t *cellGroupConfig, int gNB_index) { NR_SpCellConfig_t *spCellConfig = cellGroupConfig->spCellConfig; if(spCellConfig) { if (spCellConfig->reconfigurationWithSync) { LOG_I(NR_RRC, "Processing reconfigurationWithSync\n"); - nr_rrc_process_reconfigurationWithSync(rrc, spCellConfig->reconfigurationWithSync); + nr_rrc_process_reconfigurationWithSync(rrc, spCellConfig->reconfigurationWithSync, gNB_index); } nr_rrc_handle_SetupRelease_RLF_TimersAndConstants(rrc, spCellConfig->rlf_TimersAndConstants); if (spCellConfig->spCellConfigDedicated) { @@ -1079,10 +1237,10 @@ void nr_rrc_cellgroup_configuration(NR_UE_RRC_INST_t *rrc, NR_CellGroupConfig_t AssertFatal(cellGroupConfig->sCellToAddModList == NULL, "Secondary serving cell addition not implemented\n"); } - static void nr_rrc_ue_process_masterCellGroup(NR_UE_RRC_INST_t *rrc, OCTET_STRING_t *masterCellGroup, - long *fullConfig) + long *fullConfig, + int gNB_index) { AssertFatal(!fullConfig, "fullConfig not supported yet\n"); NR_CellGroupConfig_t *cellGroupConfig = NULL; @@ -1096,7 +1254,7 @@ static void nr_rrc_ue_process_masterCellGroup(NR_UE_RRC_INST_t *rrc, xer_fprint(stdout, &asn_DEF_NR_CellGroupConfig, (const void *) cellGroupConfig); } - nr_rrc_cellgroup_configuration(rrc, cellGroupConfig); + nr_rrc_cellgroup_configuration(rrc, cellGroupConfig, gNB_index); LOG_D(RRC, "Sending CellGroupConfig to MAC the pointer will be managed by mac\n"); MessageDef *msg = itti_alloc_new_message(TASK_RRC_NRUE, 0, NR_MAC_RRC_CONFIG_CG); @@ -1143,21 +1301,67 @@ static void rrc_ue_generate_RRCSetupComplete(const NR_UE_RRC_INST_t *rrc, const nr_pdcp_data_req_srb(rrc->ue_id, srb_id, 0, size, buffer, deliver_pdu_srb_rlc, NULL); } +static void nr_rrc_rrcsetup_fallback(NR_UE_RRC_INST_t *rrc) +{ + LOG_W(NR_RRC, + "[UE %ld] Recived RRCSetup in response to %s request\n", + rrc->ue_id, rrc->ra_trigger == RRC_CONNECTION_REESTABLISHMENT ? "RRCReestablishment" : "RRCResume"); + + // discard any stored UE Inactive AS context and suspendConfig + // TODO + + // discard any current AS security context including + // K_RRCenc key, the K_RRCint key, the K_UPint key and the K_UPenc key + // TODO only kgnb is stored + memset(rrc->kgnb, 0, sizeof(rrc->kgnb)); + rrc->as_security_activated = false; + + // release radio resources for all established RBs except SRB0, + // including release of the RLC entities, of the associated PDCP entities and of SDAP + for (int i = 1; i <= MAX_DRBS_PER_UE; i++) { + if (get_DRB_status(rrc, i) != RB_NOT_PRESENT) { + set_DRB_status(rrc, i, RB_NOT_PRESENT); + nr_pdcp_release_drb(rrc->ue_id, i); + } + } + for (int i = 1; i < NR_NUM_SRB; i++) { + if (rrc->Srb[i] != RB_NOT_PRESENT) { + rrc->Srb[i] = RB_NOT_PRESENT; + nr_pdcp_release_srb(rrc->ue_id, i); + } + } + 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_sdap_delete_ue_entities(rrc->ue_id); + + // release the RRC configuration except for the default L1 parameter values, + // default MAC Cell Group configuration and CCCH configuration + // TODO to be completed + NR_UE_MAC_reset_cause_t cause = RRC_SETUP_REESTAB_RESUME; + MessageDef *msg = itti_alloc_new_message(TASK_RRC_NRUE, 0, NR_MAC_RRC_CONFIG_RESET); + NR_MAC_RRC_CONFIG_RESET(msg).cause = cause; + itti_send_msg_to_task(TASK_MAC_UE, rrc->ue_id, msg); + + // indicate to upper layers fallback of the RRC connection + // TODO + + // stop timer T380, if running + // TODO not implemented yet +} + static void nr_rrc_process_rrcsetup(NR_UE_RRC_INST_t *rrc, const NR_RRCSetup_t *rrcSetup) { // if the RRCSetup is received in response to an RRCReestablishmentRequest // or RRCResumeRequest or RRCResumeRequest1 - // TODO none of the procedures implemented yet - if (rrc->ra_trigger == RRC_CONNECTION_REESTABLISHMENT) { - LOG_E(NR_RRC, "Handling of RRCSetup in response of RRCReestablishment not implemented yet. Going back to IDLE.\n"); - nr_rrc_going_to_IDLE(rrc, OTHER, NULL); - return; - } + if (rrc->ra_trigger == RRC_CONNECTION_REESTABLISHMENT || rrc->ra_trigger == RRC_RESUME_REQUEST) + nr_rrc_rrcsetup_fallback(rrc); // perform the cell group configuration procedure in accordance with the received masterCellGroup - nr_rrc_ue_process_masterCellGroup(rrc, - &rrcSetup->criticalExtensions.choice.rrcSetup->masterCellGroup, - NULL); + nr_rrc_ue_process_masterCellGroup(rrc, &rrcSetup->criticalExtensions.choice.rrcSetup->masterCellGroup, NULL, 0); // perform the radio bearer configuration procedure in accordance with the received radioBearerConfig nr_rrc_ue_process_RadioBearerConfig(rrc, &rrcSetup->criticalExtensions.choice.rrcSetup->radioBearerConfig); @@ -1182,6 +1386,9 @@ static void nr_rrc_process_rrcsetup(NR_UE_RRC_INST_t *rrc, const NR_RRCSetup_t * MessageDef *msg_p = itti_alloc_new_message(TASK_RRC_NRUE, 0, NR_NAS_CONN_ESTABLISH_IND); itti_send_msg_to_task(TASK_NAS_NRUE, rrc->ue_id, msg_p); + // resetting the RA trigger state after receiving MSG4 with RRCSetup + rrc->ra_trigger = RA_NOT_RUNNING; + // set the content of RRCSetupComplete message // TODO procedues described in 5.3.3.4 seems more complex than what we actualy do rrc_ue_generate_RRCSetupComplete(rrc, rrcSetup->rrc_TransactionIdentifier); @@ -1868,11 +2075,21 @@ static int nr_rrc_ue_decode_dcch(NR_UE_RRC_INST_t *rrc, if (rrc->reconfig_after_reestab) { // if this is the first RRCReconfiguration message after successful completion of the RRC re-establishment procedure // resume SRB2 and DRBs that are suspended - if (rrc->Srb[2] == RB_SUSPENDED) + if (rrc->Srb[2] == RB_SUSPENDED) { rrc->Srb[2] = RB_ESTABLISHED; + MessageDef *msg = itti_alloc_new_message(TASK_RRC_NRUE, 0, NR_MAC_RRC_RESUME_RB); + NR_MAC_RRC_RESUME_RB(msg).is_srb = true; + NR_MAC_RRC_RESUME_RB(msg).rb_id = 2; + itti_send_msg_to_task(TASK_MAC_UE, rrc->ue_id, msg); + } for (int i = 1; i <= MAX_DRBS_PER_UE; i++) { - if (get_DRB_status(rrc, i) == RB_SUSPENDED) + if (get_DRB_status(rrc, i) == RB_SUSPENDED) { set_DRB_status(rrc, i, RB_ESTABLISHED); + MessageDef *msg = itti_alloc_new_message(TASK_RRC_NRUE, 0, NR_MAC_RRC_RESUME_RB); + NR_MAC_RRC_RESUME_RB(msg).is_srb = false; + NR_MAC_RRC_RESUME_RB(msg).rb_id = i; + itti_send_msg_to_task(TASK_MAC_UE, rrc->ue_id, msg); + } } rrc->reconfig_after_reestab = false; } @@ -1907,22 +2124,22 @@ static int nr_rrc_ue_decode_dcch(NR_UE_RRC_INST_t *rrc, break; case NR_DL_DCCH_MessageType__c1_PR_dlInformationTransfer: { - NR_DLInformationTransfer_t *dlInformationTransfer = c1->choice.dlInformationTransfer; + NR_DLInformationTransfer_t *dlInfo = c1->choice.dlInformationTransfer; - if (dlInformationTransfer->criticalExtensions.present - == NR_DLInformationTransfer__criticalExtensions_PR_dlInformationTransfer) { + if (dlInfo->criticalExtensions.present == NR_DLInformationTransfer__criticalExtensions_PR_dlInformationTransfer) { + NR_DLInformationTransfer_IEs_t *dlInfo_IE = dlInfo->criticalExtensions.choice.dlInformationTransfer; /* This message hold a dedicated info NAS payload, forward it to NAS */ - NR_DedicatedNAS_Message_t *dedicatedNAS_Message = - dlInformationTransfer->criticalExtensions.choice.dlInformationTransfer->dedicatedNAS_Message; - - MessageDef *ittiMsg = itti_alloc_new_message(TASK_RRC_NRUE, rrc->ue_id, NAS_DOWNLINK_DATA_IND); - dl_info_transfer_ind_t *msg = &NAS_DOWNLINK_DATA_IND(ittiMsg); - msg->UEid = rrc->ue_id; - msg->nasMsg.length = dedicatedNAS_Message->size; - msg->nasMsg.nas_data = malloc(msg->nasMsg.length); - memcpy(msg->nasMsg.nas_data, dedicatedNAS_Message->buf, msg->nasMsg.length); - itti_send_msg_to_task(TASK_NAS_NRUE, rrc->ue_id, ittiMsg); - dedicatedNAS_Message->buf = NULL; // to keep the buffer, up to NAS to free it + NR_DedicatedNAS_Message_t *dedicatedNAS_Message = dlInfo_IE->dedicatedNAS_Message; + if (dedicatedNAS_Message) { + MessageDef *ittiMsg = itti_alloc_new_message(TASK_RRC_NRUE, rrc->ue_id, NAS_DOWNLINK_DATA_IND); + dl_info_transfer_ind_t *msg = &NAS_DOWNLINK_DATA_IND(ittiMsg); + msg->UEid = rrc->ue_id; + msg->nasMsg.length = dedicatedNAS_Message->size; + msg->nasMsg.nas_data = malloc(msg->nasMsg.length); + memcpy(msg->nasMsg.nas_data, dedicatedNAS_Message->buf, msg->nasMsg.length); + itti_send_msg_to_task(TASK_NAS_NRUE, rrc->ue_id, ittiMsg); + dedicatedNAS_Message->buf = NULL; // to keep the buffer, up to NAS to free it + } } } break; case NR_DL_DCCH_MessageType__c1_PR_mobilityFromNRCommand: @@ -2004,7 +2221,8 @@ void *rrc_nrue(void *notUsed) } break; case NRRRC_FRAME_PROCESS: - LOG_D(NR_RRC, "Received %s: frame %d\n", ITTI_MSG_NAME(msg_p), NRRRC_FRAME_PROCESS(msg_p).frame); + rrc->current_frame = NRRRC_FRAME_PROCESS(msg_p).frame; + LOG_D(NR_RRC, "Received %s: frame %d\n", ITTI_MSG_NAME(msg_p), rrc->current_frame); // increase the timers every 10ms (every new frame) nr_rrc_handle_timers(rrc); NR_UE_RRC_SI_INFO *SInfo = &rrc->perNB[NRRRC_FRAME_PROCESS(msg_p).gnb_id].SInfo; @@ -2048,7 +2266,14 @@ void *rrc_nrue(void *notUsed) if (bcch->is_bch) nr_rrc_ue_decode_NR_BCCH_BCH_Message(rrc, bcch->gnb_index, bcch->phycellid, bcch->ssb_arfcn, bcch->sdu, bcch->sdu_size); else - nr_rrc_ue_decode_NR_BCCH_DL_SCH_Message(rrc, bcch->gnb_index, bcch->sdu, bcch->sdu_size, bcch->rsrq, bcch->rsrp); + nr_rrc_ue_decode_NR_BCCH_DL_SCH_Message(rrc, + bcch->gnb_index, + bcch->sdu, + bcch->sdu_size, + bcch->rsrq, + bcch->rsrp, + bcch->frame, + bcch->slot); break; case NR_RRC_MAC_SBCCH_DATA_IND: @@ -2649,6 +2874,22 @@ void handle_t300_expiry(NR_UE_RRC_INST_t *rrc) // TODO inform upper layers about the failure to establish the RRC connection } +void handle_t430_expiry(NR_UE_RRC_INST_t *rrc) +{ + // SPEC 38.331 section 5.2.2.6 + // Reacquire SIB19 after T430 expiry + for (int i = 0; i < NB_CNX_UE; i++) { + rrcPerNB_t *nb = &rrc->perNB[i]; + NR_UE_RRC_SI_INFO *SI_info = &nb->SInfo; + SI_info->SInfo_r17.sib19_validity = false; + } + // Indicate MAC that UL SYNC is LOST + NR_UE_MAC_reset_cause_t cause = UL_SYNC_LOST_T430_EXPIRED; + MessageDef *msg = itti_alloc_new_message(TASK_RRC_NRUE, 0, NR_MAC_RRC_CONFIG_RESET); + NR_MAC_RRC_CONFIG_RESET(msg).cause = cause; + itti_send_msg_to_task(TASK_MAC_UE, rrc->ue_id, msg); +} + //This calls the sidelink preconf message after RRC, MAC instances are created. void start_sidelink(int instance) { diff --git a/openair2/RRC/NR_UE/rrc_defs.h b/openair2/RRC/NR_UE/rrc_defs.h index e428c4c160..960dc1aaa0 100644 --- a/openair2/RRC/NR_UE/rrc_defs.h +++ b/openair2/RRC/NR_UE/rrc_defs.h @@ -94,6 +94,7 @@ typedef enum RA_trigger_e { RA_NOT_RUNNING, RRC_CONNECTION_SETUP, RRC_CONNECTION_REESTABLISHMENT, + RRC_RESUME_REQUEST, DURING_HANDOVER, NON_SYNCHRONISED, TRANSITION_FROM_RRC_INACTIVE, @@ -151,6 +152,11 @@ typedef struct UE_RRC_SI_INFO_NR_s { bool sib14_validity; NR_timer_t sib14_timer; NR_UE_RRC_SI_INFO_r17 SInfo_r17; + // Extracted from SIB1 + int scs; + int sib19_periodicity; + int sib19_windowposition; + int si_windowlength; } NR_UE_RRC_SI_INFO; typedef struct NR_UE_Timers_Constants_s { @@ -167,6 +173,8 @@ typedef struct NR_UE_Timers_Constants_s { NR_timer_t T325; NR_timer_t T380; NR_timer_t T390; + // NTN timer T430 which guards UL SYNC + NR_timer_t T430; // counters uint32_t N310_cnt; uint32_t N311_cnt; @@ -233,6 +241,8 @@ typedef struct NR_UE_RRC_INST_s { bool reconfig_after_reestab; // 5G-S-TMSI uint64_t fiveG_S_TMSI; + // Frame timing received from MAC + int current_frame; //Sidelink params NR_SL_PreconfigurationNR_r16_t *sl_preconfig; diff --git a/openair2/RRC/NR_UE/rrc_proto.h b/openair2/RRC/NR_UE/rrc_proto.h index f4728f0f58..7c5f749fa0 100644 --- a/openair2/RRC/NR_UE/rrc_proto.h +++ b/openair2/RRC/NR_UE/rrc_proto.h @@ -47,7 +47,7 @@ void init_nsa_message (NR_UE_RRC_INST_t *rrc, char* reconfig_file, char* rbconfi void process_nsa_message(NR_UE_RRC_INST_t *rrc, nsa_message_t nsa_message_type, void *message, int msg_len); -void nr_rrc_cellgroup_configuration(NR_UE_RRC_INST_t *rrc, NR_CellGroupConfig_t *cellGroupConfig); +void nr_rrc_cellgroup_configuration(NR_UE_RRC_INST_t *rrc, NR_CellGroupConfig_t *cellGroupConfig, int gNB_index); void nr_rrc_going_to_IDLE(NR_UE_RRC_INST_t *rrc, NR_Release_Cause_t release_cause, @@ -80,6 +80,7 @@ void init_SI_timers(NR_UE_RRC_SI_INFO *SInfo); void nr_ue_rrc_timer_trigger(int module_id, int frame, int gnb_id); void handle_t300_expiry(NR_UE_RRC_INST_t *rrc); +void handle_t430_expiry(NR_UE_RRC_INST_t *rrc); void reset_rlf_timers_and_constants(NR_UE_Timers_Constants_t *tac); void set_default_timers_and_constants(NR_UE_Timers_Constants_t *tac); diff --git a/openair2/RRC/NR_UE/rrc_timers_and_constants.c b/openair2/RRC/NR_UE/rrc_timers_and_constants.c index 6629055b3a..9286494f0b 100644 --- a/openair2/RRC/NR_UE/rrc_timers_and_constants.c +++ b/openair2/RRC/NR_UE/rrc_timers_and_constants.c @@ -169,6 +169,14 @@ void nr_rrc_handle_timers(NR_UE_RRC_INST_t *rrc) // with release cause 'RRC connection failure' nr_rrc_going_to_IDLE(rrc, RRC_CONNECTION_FAILURE, NULL); } + + bool t430_expired = nr_timer_tick(&rrc->timers_and_constants.T430); + if (t430_expired && rrc->nrRrcState == RRC_STATE_CONNECTED_NR && rrc->is_NTN_UE) { + LOG_W(NR_RRC, "Timer T430 expired! Indicate UL SYNC LOSS to MAC\n"); + // Upon T430 expiry, the UE shall reacquire SIB19 and re-obtain UL-SYNC + // Spec 38.331 Section 5.2.2.6 + handle_t430_expiry(rrc); + } } int nr_rrc_get_T304(long t304) diff --git a/openair3/NAS/NR_UE/nr_nas_msg.c b/openair3/NAS/NR_UE/nr_nas_msg.c index 5709d482c6..d7fb313fa8 100644 --- a/openair3/NAS/NR_UE/nr_nas_msg.c +++ b/openair3/NAS/NR_UE/nr_nas_msg.c @@ -32,6 +32,7 @@ #include "nr_nas_msg.h" #include #include "NR_NAS_defs.h" +#include #include #include #include @@ -1495,6 +1496,10 @@ static void handle_pdu_session_accept(uint8_t *pdu_buffer, uint32_t msg_length, */ void handleDownlinkNASTransport(uint8_t * pdu_buffer, int pdu_length, int instance) { + if (pdu_length < 17) { + LOG_E(NAS, "Received DL NAS Transport message too short (%d)\n", pdu_length); + return; + } uint8_t msg_type = *(pdu_buffer + 16); if (msg_type == FGS_PDU_SESSION_ESTABLISHMENT_ACC) { LOG_A(NAS, "Received PDU Session Establishment Accept in DL NAS Transport\n"); @@ -2079,10 +2084,23 @@ void *nas_nrue(void *args_p) case FGS_PDU_SESSION_ESTABLISHMENT_REJ: LOG_E(NAS, "Received PDU Session Establishment reject\n"); break; - case FGS_REGISTRATION_REJECT: - LOG_E(NAS, "Received Registration reject cause: %s\n", cause_text_info[pdu_buffer[17]].text); + case FGS_REGISTRATION_REJECT: { + + if (pdu_length < 18) { + LOG_E(NAS, "Received Registration reject message too short\n"); + break; + } + + uint8_t cause = pdu_buffer[17]; + if (cause >= sizeof(cause_text_info) / sizeof(cause_text_info[0])) { + LOG_E(NAS, "Received Registration reject cause %d unknown\n", cause); + break; + } + + LOG_E(NAS, "Received Registration reject cause: %s\n", cause_text_info[cause].text); exit(1); break; + } case FGS_SERVICE_ACCEPT: { handle_service_accept(nas, &buffer); break; diff --git a/radio/USRP/usrp_lib.cpp b/radio/USRP/usrp_lib.cpp index 8fbb561149..6dde70b2eb 100644 --- a/radio/USRP/usrp_lib.cpp +++ b/radio/USRP/usrp_lib.cpp @@ -1202,9 +1202,9 @@ extern "C" { } } else { - if (openair0_cfg[0].clock_source != unset) { - LOG_W(HW,"Time source set in both usrp_args and in time_source, ingnoring the latter!\n"); - } + if (openair0_cfg[0].time_source != unset) { + LOG_W(HW, "Time source set in both usrp_args and in openair0_cfg[0].time_source, ignoring the latter!\n"); + } }