diff --git a/ci-scripts/as_ue/aw2s-multi-20897-2x2.cfg b/ci-scripts/as_ue/aw2s-multi-00102-2x2.cfg similarity index 92% rename from ci-scripts/as_ue/aw2s-multi-20897-2x2.cfg rename to ci-scripts/as_ue/aw2s-multi-00102-2x2.cfg index b9707b801e..04d2bb9ffd 100644 --- a/ci-scripts/as_ue/aw2s-multi-20897-2x2.cfg +++ b/ci-scripts/as_ue/aw2s-multi-00102-2x2.cfg @@ -25,8 +25,8 @@ allow dynamic UE creation from remote API */ rf_port: 0, bandwidth: 20, band: 78, - dl_nr_arfcn:627360, - ssb_nr_arfcn:627360, + dl_nr_arfcn:630048, + ssb_nr_arfcn:630048, subcarrier_spacing: 30, n_antenna_dl: N_ANTENNA_DL, n_antenna_ul: N_ANTENNA_UL, @@ -39,7 +39,7 @@ allow dynamic UE creation from remote API */ ue_list: [ { "ue_id" : 1, - "imsi": "208970000000111", + "imsi": "001020000000001", "K": "fec86ba6eb707ed08905757b1bb44b8f", "sim_algo":"milenage", "op": "1006020f0a478bf6b699f15c062e42b3", @@ -54,7 +54,7 @@ allow dynamic UE creation from remote API */ }, { "ue_id" : 2, - "imsi": "208970000000112", + "imsi": "001020000000002", "K": "fec86ba6eb707ed08905757b1bb44b8f", "sim_algo":"milenage", "op": "1006020f0a478bf6b699f15c062e42b3", @@ -69,7 +69,7 @@ allow dynamic UE creation from remote API */ }, { "ue_id" : 3, - "imsi": "208970000000113", + "imsi": "001020000000003", "K": "fec86ba6eb707ed08905757b1bb44b8f", "sim_algo":"milenage", "op": "1006020f0a478bf6b699f15c062e42b3", @@ -84,7 +84,7 @@ allow dynamic UE creation from remote API */ }, { "ue_id" : 4, - "imsi": "208970000000114", + "imsi": "001020000000004", "K": "fec86ba6eb707ed08905757b1bb44b8f", "sim_algo":"milenage", "op": "1006020f0a478bf6b699f15c062e42b3", @@ -99,7 +99,7 @@ allow dynamic UE creation from remote API */ }, { "ue_id" : 5, - "imsi": "208970000000115", + "imsi": "001020000000005", "K": "fec86ba6eb707ed08905757b1bb44b8f", "sim_algo":"milenage", "op": "1006020f0a478bf6b699f15c062e42b3", @@ -114,7 +114,7 @@ allow dynamic UE creation from remote API */ }, { "ue_id" : 6, - "imsi": "208970000000116", + "imsi": "001020000000006", "K": "fec86ba6eb707ed08905757b1bb44b8f", "sim_algo":"milenage", "op": "1006020f0a478bf6b699f15c062e42b3", @@ -129,7 +129,7 @@ allow dynamic UE creation from remote API */ }, { "ue_id" : 7, - "imsi": "208970000000100", + "imsi": "001020000000007", "K": "fec86ba6eb707ed08905757b1bb44b8f", "sim_algo":"milenage", "op": "1006020f0a478bf6b699f15c062e42b3", @@ -144,7 +144,7 @@ allow dynamic UE creation from remote API */ }, { "ue_id" : 8, - "imsi": "208970000000102", + "imsi": "001020000000008", "K": "fec86ba6eb707ed08905757b1bb44b8f", "sim_algo":"milenage", "op": "1006020f0a478bf6b699f15c062e42b3", @@ -159,7 +159,7 @@ allow dynamic UE creation from remote API */ }, { "ue_id" : 9, - "imsi": "208970000000103", + "imsi": "001020000000009", "K": "fec86ba6eb707ed08905757b1bb44b8f", "sim_algo":"milenage", "op": "1006020f0a478bf6b699f15c062e42b3", @@ -174,7 +174,7 @@ allow dynamic UE creation from remote API */ }, { "ue_id" : 10, - "imsi": "208970000000104", + "imsi": "001020000000010", "K": "fec86ba6eb707ed08905757b1bb44b8f", "sim_algo":"milenage", "op": "1006020f0a478bf6b699f15c062e42b3", @@ -189,7 +189,7 @@ allow dynamic UE creation from remote API */ }, { "ue_id" : 11, - "imsi": "208970000000110", + "imsi": "001020000000011", "K": "fec86ba6eb707ed08905757b1bb44b8f", "sim_algo":"milenage", "op": "1006020f0a478bf6b699f15c062e42b3", @@ -204,7 +204,7 @@ allow dynamic UE creation from remote API */ }, { "ue_id" : 12, - "imsi": "208970000000105", + "imsi": "001020000000012", "K": "fec86ba6eb707ed08905757b1bb44b8f", "sim_algo":"milenage", "op": "1006020f0a478bf6b699f15c062e42b3", @@ -219,7 +219,7 @@ allow dynamic UE creation from remote API */ }, { "ue_id" : 13, - "imsi": "208970000000106", + "imsi": "001020000000013", "K": "fec86ba6eb707ed08905757b1bb44b8f", "sim_algo":"milenage", "op": "1006020f0a478bf6b699f15c062e42b3", @@ -234,7 +234,7 @@ allow dynamic UE creation from remote API */ }, { "ue_id" : 14, - "imsi": "208970000000107", + "imsi": "001020000000014", "K": "fec86ba6eb707ed08905757b1bb44b8f", "sim_algo":"milenage", "op": "1006020f0a478bf6b699f15c062e42b3", @@ -249,7 +249,7 @@ allow dynamic UE creation from remote API */ }, { "ue_id" : 15, - "imsi": "208970000000108", + "imsi": "001020000000015", "K": "fec86ba6eb707ed08905757b1bb44b8f", "sim_algo":"milenage", "op": "1006020f0a478bf6b699f15c062e42b3", @@ -264,7 +264,7 @@ allow dynamic UE creation from remote API */ }, { "ue_id" : 16, - "imsi": "208970000000109", + "imsi": "001020000000016", "K": "fec86ba6eb707ed08905757b1bb44b8f", "sim_algo":"milenage", "op": "1006020f0a478bf6b699f15c062e42b3", diff --git a/ci-scripts/as_ue/aw2s-multi-20897.cfg b/ci-scripts/as_ue/aw2s-multi-20897.cfg deleted file mode 100644 index f4b2371cb8..0000000000 --- a/ci-scripts/as_ue/aw2s-multi-20897.cfg +++ /dev/null @@ -1,280 +0,0 @@ -/* UE simulator configuration file version 2021-06-17 - * LTE / 5G Non StandAlone - * Copyright (C) 2019-2021 Amarisoft - */ -{ -#define N_ANTENNA_DL 2 -#define TDD 1 - -log_options: "all.level=warn,all.max_size=0,nas.level=debug,nas.max_size=1,rrc.level=debug,rrc.max_size=1", -log_filename: "/tmp/ue.log", - -/* Enable remote API and Web interface */ -com_addr: "0.0.0.0:9002", - -include "rf_driver/1chan.cfg", - -/* If true, allow the simulation of several UEs at the same time and -allow dynamic UE creation from remote API */ - - cell_groups: [{ - group_type: "nr", - multi_ue: true, - cells: [{ - rf_port: 0, - bandwidth: 20, - band: 78, - dl_nr_arfcn:627360, - ssb_nr_arfcn:627360, - subcarrier_spacing: 30, - n_antenna_dl: N_ANTENNA_DL, - n_antenna_ul: 1, - rx_to_tx_latency:2, - }], - }], - - /* UE capabilities */ - /* USIM data */ - ue_list: [ - { - "ue_id" : 1, - "imsi": "208970000000111", - "K": "fec86ba6eb707ed08905757b1bb44b8f", - "sim_algo":"milenage", - "op": "1006020f0a478bf6b699f15c062e42b3", - - as_release: 15, - ue_category: "nr", - apn:"oai", - attach_pdn_type:"ipv4", - default_nssai: [ { sst: 1, }, ], - default_pdu_session_snssai: { sst: 1, }, - tun_setup_script: "ue-ifup", - }, - { - "ue_id" : 2, - "imsi": "208970000000112", - "K": "fec86ba6eb707ed08905757b1bb44b8f", - "sim_algo":"milenage", - "op": "1006020f0a478bf6b699f15c062e42b3", - - as_release: 15, - ue_category: "nr", - apn:"oai", - attach_pdn_type:"ipv4", - default_nssai: [ { sst: 1, }, ], - default_pdu_session_snssai: { sst: 1, }, - tun_setup_script: "ue-ifup", - }, - { - "ue_id" : 3, - "imsi": "208970000000113", - "K": "fec86ba6eb707ed08905757b1bb44b8f", - "sim_algo":"milenage", - "op": "1006020f0a478bf6b699f15c062e42b3", - - as_release: 15, - ue_category: "nr", - apn:"oai", - attach_pdn_type:"ipv4", - default_nssai: [ { sst: 1, }, ], - default_pdu_session_snssai: { sst: 1, }, - tun_setup_script: "ue-ifup", - }, - { - "ue_id" : 4, - "imsi": "208970000000114", - "K": "fec86ba6eb707ed08905757b1bb44b8f", - "sim_algo":"milenage", - "op": "1006020f0a478bf6b699f15c062e42b3", - - as_release: 15, - ue_category: "nr", - apn:"oai", - attach_pdn_type:"ipv4", - default_nssai: [ { sst: 1, }, ], - default_pdu_session_snssai: { sst: 1, }, - tun_setup_script: "ue-ifup", - }, - { - "ue_id" : 5, - "imsi": "208970000000115", - "K": "fec86ba6eb707ed08905757b1bb44b8f", - "sim_algo":"milenage", - "op": "1006020f0a478bf6b699f15c062e42b3", - - as_release: 15, - ue_category: "nr", - apn:"oai", - attach_pdn_type:"ipv4", - default_nssai: [ { sst: 1, }, ], - default_pdu_session_snssai: { sst: 1, }, - tun_setup_script: "ue-ifup", - }, - { - "ue_id" : 6, - "imsi": "208970000000116", - "K": "fec86ba6eb707ed08905757b1bb44b8f", - "sim_algo":"milenage", - "op": "1006020f0a478bf6b699f15c062e42b3", - - as_release: 15, - ue_category: "nr", - apn:"oai", - attach_pdn_type:"ipv4", - default_nssai: [ { sst: 1, }, ], - default_pdu_session_snssai: { sst: 1, }, - tun_setup_script: "ue-ifup", - }, - { - "ue_id" : 7, - "imsi": "208970000000117", - "K": "fec86ba6eb707ed08905757b1bb44b8f", - "sim_algo":"milenage", - "op": "1006020f0a478bf6b699f15c062e42b3", - - as_release: 15, - ue_category: "nr", - apn:"oai", - attach_pdn_type:"ipv4", - default_nssai: [ { sst: 1, }, ], - default_pdu_session_snssai: { sst: 1, }, - tun_setup_script: "ue-ifup", - }, - { - "ue_id" : 8, - "imsi": "208970000000118", - "K": "fec86ba6eb707ed08905757b1bb44b8f", - "sim_algo":"milenage", - "op": "1006020f0a478bf6b699f15c062e42b3", - - as_release: 15, - ue_category: "nr", - apn:"oai", - attach_pdn_type:"ipv4", - default_nssai: [ { sst: 1, }, ], - default_pdu_session_snssai: { sst: 1, }, - tun_setup_script: "ue-ifup", - }, - { - "ue_id" : 9, - "imsi": "208970000000119", - "K": "fec86ba6eb707ed08905757b1bb44b8f", - "sim_algo":"milenage", - "op": "1006020f0a478bf6b699f15c062e42b3", - - as_release: 15, - ue_category: "nr", - apn:"oai", - attach_pdn_type:"ipv4", - default_nssai: [ { sst: 1, }, ], - default_pdu_session_snssai: { sst: 1, }, - tun_setup_script: "ue-ifup", - }, - { - "ue_id" : 10, - "imsi": "208970000000120", - "K": "fec86ba6eb707ed08905757b1bb44b8f", - "sim_algo":"milenage", - "op": "1006020f0a478bf6b699f15c062e42b3", - - as_release: 15, - ue_category: "nr", - apn:"oai", - attach_pdn_type:"ipv4", - default_nssai: [ { sst: 1, }, ], - default_pdu_session_snssai: { sst: 1, }, - tun_setup_script: "ue-ifup", - }, - { - "ue_id" : 11, - "imsi": "208970000000121", - "K": "fec86ba6eb707ed08905757b1bb44b8f", - "sim_algo":"milenage", - "op": "1006020f0a478bf6b699f15c062e42b3", - - as_release: 15, - ue_category: "nr", - apn:"oai", - attach_pdn_type:"ipv4", - default_nssai: [ { sst: 1, }, ], - default_pdu_session_snssai: { sst: 1, }, - tun_setup_script: "ue-ifup", - }, - { - "ue_id" : 12, - "imsi": "208970000000122", - "K": "fec86ba6eb707ed08905757b1bb44b8f", - "sim_algo":"milenage", - "op": "1006020f0a478bf6b699f15c062e42b3", - - as_release: 15, - ue_category: "nr", - apn:"oai", - attach_pdn_type:"ipv4", - default_nssai: [ { sst: 1, }, ], - default_pdu_session_snssai: { sst: 1, }, - tun_setup_script: "ue-ifup", - }, - { - "ue_id" : 13, - "imsi": "208970000000123", - "K": "fec86ba6eb707ed08905757b1bb44b8f", - "sim_algo":"milenage", - "op": "1006020f0a478bf6b699f15c062e42b3", - - as_release: 15, - ue_category: "nr", - apn:"oai", - attach_pdn_type:"ipv4", - default_nssai: [ { sst: 1, }, ], - default_pdu_session_snssai: { sst: 1, }, - tun_setup_script: "ue-ifup", - }, - { - "ue_id" : 14, - "imsi": "208970000000124", - "K": "fec86ba6eb707ed08905757b1bb44b8f", - "sim_algo":"milenage", - "op": "1006020f0a478bf6b699f15c062e42b3", - - as_release: 15, - ue_category: "nr", - apn:"oai", - attach_pdn_type:"ipv4", - default_nssai: [ { sst: 1, }, ], - default_pdu_session_snssai: { sst: 1, }, - tun_setup_script: "ue-ifup", - }, - { - "ue_id" : 15, - "imsi": "208970000000125", - "K": "fec86ba6eb707ed08905757b1bb44b8f", - "sim_algo":"milenage", - "op": "1006020f0a478bf6b699f15c062e42b3", - - as_release: 15, - ue_category: "nr", - apn:"oai", - attach_pdn_type:"ipv4", - default_nssai: [ { sst: 1, }, ], - default_pdu_session_snssai: { sst: 1, }, - tun_setup_script: "ue-ifup", - }, - { - "ue_id" : 16, - "imsi": "208970000000126", - "K": "fec86ba6eb707ed08905757b1bb44b8f", - "sim_algo":"milenage", - "op": "1006020f0a478bf6b699f15c062e42b3", - - as_release: 15, - ue_category: "nr", - apn:"oai", - attach_pdn_type:"ipv4", - default_nssai: [ { sst: 1, }, ], - default_pdu_session_snssai: { sst: 1, }, - tun_setup_script: "ue-ifup", - }, - ], -} diff --git a/ci-scripts/ci_infra.yaml b/ci-scripts/ci_infra.yaml index 400b80e2e0..8cbb5936e2 100644 --- a/ci-scripts/ci_infra.yaml +++ b/ci-scripts/ci_infra.yaml @@ -97,7 +97,7 @@ ltebox-nepes: amarisoft_ue: Host: amariue - InitScript: /root/lteue-linux-2023-10-27/ue/lteue /root/oaicicd/ran_sa_aw2s_asue_2x2/aw2s-multi-20897-2x2.cfg & + InitScript: /root/lteue-linux-2023-10-27/ue/lteue /root/oaicicd/ran_sa_aw2s_asue_2x2/aw2s-multi-00102-2x2.cfg & TermScript: /root/2023-10-27/libs/ws.js -t 10 127.0.0.1:9002 '{"message":"quit"}' || killall -KILL lteue-avx2 amarisoft_ue_1: Host: amariue diff --git a/ci-scripts/cls_cluster.py b/ci-scripts/cls_cluster.py index c8b0ce818b..d35b73890b 100644 --- a/ci-scripts/cls_cluster.py +++ b/ci-scripts/cls_cluster.py @@ -44,6 +44,9 @@ OCUrl = "https://api.oai.cs.eurecom.fr:6443" OCRegistry = "default-route-openshift-image-registry.apps.oai.cs.eurecom.fr/" CI_OC_RAN_NAMESPACE = "oaicicd-ran" CI_OC_CORE_NAMESPACE = "oaicicd-core-for-ci-ran" +CN_IMAGES = ["mysql", "oai-nrf", "oai-amf", "oai-smf", "oai-upf", "oai-ausf", "oai-udm", "oai-udr", "oai-traffic-server"] +CN_CONTAINERS = ["", "-c nrf", "-c amf", "-c smf", "-c upf", "-c ausf", "-c udm", "-c udr", ""] + def OC_login(cmd, ocUserName, ocPassword, ocProjectName): if ocUserName == '' or ocPassword == '' or ocProjectName == '': @@ -65,6 +68,51 @@ def OC_login(cmd, ocUserName, ocPassword, ocProjectName): def OC_logout(cmd): cmd.run(f'oc logout') +def OC_deploy_CN(cmd, ocUserName, ocPassword): + logging.debug('OC OAI CN5G: Deploying OAI CN5G on Openshift Cluster') + path = "/opt/oai-cn5g-fed-develop-2024-april-00102" + succeeded = OC_login(cmd, ocUserName, ocPassword, CI_OC_CORE_NAMESPACE) + if not succeeded: + return False, CONST.OC_LOGIN_FAIL + cmd.run('helm uninstall oai5gcn --wait --timeout 60s') + ret = cmd.run(f'helm install --wait --timeout 60s oai5gcn {path}/ci-scripts/charts/oai-5g-basic/.') + if ret.returncode != 0: + logging.error('OC OAI CN5G: Deployment failed') + OC_logout(cmd) + return False, CONST.OC_PROJECT_FAIL + report = cmd.run('oc get pods') + OC_logout(cmd) + return True, report + +def OC_undeploy_CN(cmd, ocUserName, ocPassword): + logging.debug('OC OAI CN5G: Terminating CN on Openshift Cluster') + path = "/opt/oai-cn5g-fed-develop-2024-april-00102" + succeeded = OC_login(cmd, ocUserName, ocPassword, CI_OC_CORE_NAMESPACE) + if not succeeded: + return False, CONST.OC_LOGIN_FAIL + cmd.run(f'rm -Rf {path}/logs') + cmd.run(f'mkdir -p {path}/logs') + logging.debug('OC OAI CN5G: Collecting log files to workspace') + cmd.run(f'oc describe pod &> {path}/logs/describe-pods-post-test.log') + cmd.run(f'oc get pods.metrics.k8s &> {path}/logs/nf-resource-consumption.log') + for ii, ci in zip(CN_IMAGES, CN_CONTAINERS): + podName = cmd.run(f"oc get pods | grep {ii} | awk \'{{print $1}}\'").stdout.strip() + if not podName: + logging.debug(f'{ii} pod not found!') + else: + cmd.run(f'oc logs -f {podName} {ci} &> {path}/logs/{ii}.log &') + cmd.run(f'cd {path}/logs && zip -r -qq test_logs_CN.zip *.log') + cmd.copyin(f'{path}/logs/test_logs_CN.zip','test_logs_CN.zip') + ret = cmd.run('helm uninstall --wait --timeout 60s oai5gcn') + if ret.returncode != 0: + logging.error('OC OAI CN5G: Undeployment failed') + cmd.run('helm uninstall --wait --timeout 60s oai5gcn') + OC_logout(cmd) + return False, CONST.OC_PROJECT_FAIL + report = cmd.run('oc get pods') + OC_logout(cmd) + return True, report + class Cluster: def __init__(self): self.eNBIPAddress = "" diff --git a/ci-scripts/cls_oaicitest.py b/ci-scripts/cls_oaicitest.py index 0facb2f51a..928e6bbfbd 100644 --- a/ci-scripts/cls_oaicitest.py +++ b/ci-scripts/cls_oaicitest.py @@ -129,10 +129,10 @@ def Iperf_analyzeV3BIDIRJson(filename): with open(filename) as file: filename = json.load(file) try: - sender_bitrate_dl = round(filename['end']['streams'][0]['sender']['bits_per_second']/1000000,2) - receiver_bitrate_dl = round(filename['end']['streams'][0]['receiver']['bits_per_second']/1000000,2) - sender_bitrate_ul = round(filename['end']['streams'][1]['sender']['bits_per_second']/1000000,2) - receiver_bitrate_ul = round(filename['end']['streams'][1]['receiver']['bits_per_second']/1000000,2) + sender_bitrate_ul = round(filename['end']['streams'][0]['sender']['bits_per_second']/1000000,2) + receiver_bitrate_ul = round(filename['end']['streams'][0]['receiver']['bits_per_second']/1000000,2) + sender_bitrate_dl = round(filename['end']['streams'][1]['sender']['bits_per_second']/1000000,2) + receiver_bitrate_dl = round(filename['end']['streams'][1]['receiver']['bits_per_second']/1000000,2) except Exception as e: return (False, 'Could not compute BIDIR bitrate!') diff --git a/ci-scripts/conf_files/enb.band38.lte_2x2.100prb.usrpn310.conf b/ci-scripts/conf_files/enb.band38.lte_2x2.100prb.usrpn310.conf index 183b91407c..cd3842ed5b 100644 --- a/ci-scripts/conf_files/enb.band38.lte_2x2.100prb.usrpn310.conf +++ b/ci-scripts/conf_files/enb.band38.lte_2x2.100prb.usrpn310.conf @@ -204,8 +204,8 @@ MACRLCs = ( bler_target_upper = 20.0; bler_target_lower = 10.0; max_ul_rb_index = 27; - puSch10xSnr = 190; - puCch10xSnr = 160; + puSch10xSnr = 250; + puCch10xSnr = 230; } ); @@ -224,8 +224,8 @@ RUs = ( local_rf = "yes" nb_tx = 2 nb_rx = 2 - att_tx = 10 - att_rx = 5; + att_tx = 12 + att_rx = 0; bands = [38]; max_pdschReferenceSignalPower = -27; max_rxgain = 75; diff --git a/ci-scripts/conf_files/enb.band38.lte_2x2_tm2.100prb.usrpn310.conf b/ci-scripts/conf_files/enb.band38.lte_2x2_tm2.100prb.usrpn310.conf index 21fc241994..a2dfde11c3 100644 --- a/ci-scripts/conf_files/enb.band38.lte_2x2_tm2.100prb.usrpn310.conf +++ b/ci-scripts/conf_files/enb.band38.lte_2x2_tm2.100prb.usrpn310.conf @@ -204,8 +204,8 @@ MACRLCs = ( bler_target_upper = 20.0; bler_target_lower = 10.0; max_ul_rb_index = 27; - puSch10xSnr = 190; - puCch10xSnr = 160; + puSch10xSnr = 280; + puCch10xSnr = 250; } ); @@ -224,8 +224,8 @@ RUs = ( local_rf = "yes" nb_tx = 2 nb_rx = 2 - att_tx = 10 - att_rx = 5; + att_tx = 18 + att_rx = 0; bands = [38]; max_pdschReferenceSignalPower = -27; max_rxgain = 75; diff --git a/ci-scripts/conf_files/gnb.sa.band77.162prb.usrpn310.2x2.conf b/ci-scripts/conf_files/gnb.sa.band77.162prb.usrpn310.2x2.conf index fb19d44985..2ad639f727 100644 --- a/ci-scripts/conf_files/gnb.sa.band77.162prb.usrpn310.2x2.conf +++ b/ci-scripts/conf_files/gnb.sa.band77.162prb.usrpn310.2x2.conf @@ -167,19 +167,12 @@ gNBs = ////////// AMF parameters: - amf_ip_address = ( { ipv4 = "192.168.61.132"; - ipv6 = "192:168:30::17"; - active = "yes"; - preference = "ipv4"; - } - ); + amf_ip_address = ({ ipv4 = "192.168.61.132"; }); NETWORK_INTERFACES : { - GNB_INTERFACE_NAME_FOR_NG_AMF = "demo-oai"; GNB_IPV4_ADDRESS_FOR_NG_AMF = "192.168.61.129/26"; - GNB_INTERFACE_NAME_FOR_NGU = "demo-oai"; GNB_IPV4_ADDRESS_FOR_NGU = "192.168.61.129/26"; GNB_PORT_FOR_S1U = 2152; # Spec 2152 }; diff --git a/ci-scripts/conf_files/gnb.sa.band77.273prb.usrpn310.2x2.conf b/ci-scripts/conf_files/gnb.sa.band77.273prb.usrpn310.2x2.conf index efe4bbcec8..c8a578a738 100644 --- a/ci-scripts/conf_files/gnb.sa.band77.273prb.usrpn310.2x2.conf +++ b/ci-scripts/conf_files/gnb.sa.band77.273prb.usrpn310.2x2.conf @@ -164,20 +164,11 @@ gNBs = ( ////////// AMF parameters: - amf_ip_address = ( - { - ipv4 = "192.168.61.132"; - ipv6 = "192:168:30::17"; - active = "yes"; - preference = "ipv4"; - } - ); + amf_ip_address = ({ ipv4 = "192.168.61.132"; }); NETWORK_INTERFACES : { - GNB_INTERFACE_NAME_FOR_NG_AMF = "demo-oai"; GNB_IPV4_ADDRESS_FOR_NG_AMF = "192.168.61.129/24"; - GNB_INTERFACE_NAME_FOR_NGU = "demo-oai"; GNB_IPV4_ADDRESS_FOR_NGU = "192.168.61.129/24"; GNB_PORT_FOR_S1U = 2152; # Spec 2152 } diff --git a/ci-scripts/conf_files/gnb.sa.band78.106prb.n310.7ds2u.conf b/ci-scripts/conf_files/gnb.sa.band78.106prb.n310.7ds2u.conf index d43d2ed8e9..540774e2d1 100644 --- a/ci-scripts/conf_files/gnb.sa.band78.106prb.n310.7ds2u.conf +++ b/ci-scripts/conf_files/gnb.sa.band78.106prb.n310.7ds2u.conf @@ -13,7 +13,7 @@ gNBs = // Tracking area code, 0x0000 and 0xfffe are reserved values tracking_area_code = 1; - plmn_list = ({ mcc = 208; mnc = 97; mnc_length = 2; snssaiList = ({sst = 1;}); }); + plmn_list = ({ mcc = 001; mnc = 02; mnc_length = 2; snssaiList = ({sst = 1;}); }); nr_cellid = 12345678L diff --git a/ci-scripts/conf_files/gnb.sa.band78.51prb.aw2s.ddsuu.conf b/ci-scripts/conf_files/gnb.sa.band78.51prb.aw2s.ddsuu.conf index 34201a96b1..c41faa0841 100644 --- a/ci-scripts/conf_files/gnb.sa.band78.51prb.aw2s.ddsuu.conf +++ b/ci-scripts/conf_files/gnb.sa.band78.51prb.aw2s.ddsuu.conf @@ -16,7 +16,7 @@ gNBs = // Tracking area code, 0x0000 and 0xfffe are reserved values tracking_area_code = 0x1; - plmn_list = ({ mcc = 208; mnc = 97; mnc_length = 2; snssaiList = ({ sst =0x1; }) }); + plmn_list = ({ mcc = 001; mnc = 02; mnc_length = 2; snssaiList = ({ sst =0x1; }) }); nr_cellid = 12345678L @@ -35,10 +35,10 @@ gNBs = # downlinkConfigCommon #frequencyInfoDL # this is 3410.4 MHz => 301 REs from PointA 25 PRBs + 1 RE - absoluteFrequencySSB = 627360; + absoluteFrequencySSB = 630048; dl_frequencyBand = 78; # this is 3410.4 - (51*12*30e-3/2) = 3401.22 MHz - dl_absoluteFrequencyPointA = 626748; + dl_absoluteFrequencyPointA = 629436; #scs-SpecificCarrierList dl_offstToCarrier = 0; # subcarrierSpacing diff --git a/ci-scripts/epc.py b/ci-scripts/epc.py index c5a35c59a3..fb5aa8cde6 100644 --- a/ci-scripts/epc.py +++ b/ci-scripts/epc.py @@ -298,39 +298,18 @@ class EPCManagement(): html_cell += '(' + res4.group('date') + ')' html_cell += '\n' elif re.match('OC-OAI-CN5G', self.Type, re.IGNORECASE): - self.testCase_id = HTML.testCase_id - imageNames = ["oai-nrf", "oai-amf", "oai-smf", "oai-spgwu-tiny", "oai-ausf", "oai-udm", "oai-udr", "mysql","oai-traffic-server"] - logging.debug('Deploying OAI CN5G on Openshift Cluster') - lIpAddr = self.IPAddress - lSourcePath = "/opt/oai-cn5g-fed-develop-2023-04-28-20897" - succeeded = OC.OC_login(mySSH, self.OCUserName, self.OCPassword, OC.CI_OC_CORE_NAMESPACE) + succeeded, report = OC.OC_deploy_CN(mySSH, self.OCUserName, self.OCPassword) if not succeeded: - logging.error('\u001B[1m OC Cluster Login Failed\u001B[0m') - HTML.CreateHtmlTestRow('N/A', 'KO', CONST.OC_LOGIN_FAIL) - return False - for ii in imageNames: - mySSH.run(f'helm uninstall {ii}', reportNonZero=False) - mySSH.run(f'helm spray {lSourcePath}/ci-scripts/charts/oai-5g-basic/.') - ret = mySSH.run(f'oc get pods', silent=True) - if ret.stdout.count('Running') != 9: - logging.error('\u001B[1m Deploying 5GCN Failed using helm chart on OC Cluster\u001B[0m') - for ii in imageNames: - mySSH.run('helm uninstall '+ ii) - ret = mySSH.run(f'oc get pods') - if re.search('No resources found', ret.stdout): - logging.debug('All pods uninstalled') - OC.OC_logout(mySSH) - mySSH.close() - HTML.CreateHtmlTestRow('N/A', 'KO', CONST.OC_PROJECT_FAIL) - return False - ret = mySSH.run(f'oc get pods', silent=True) - for line in ret.stdout.split('\n')[1:]: + HTML.CreateHtmlTestRow('N/A', 'KO', report) + HTML.CreateHtmlTabFooter(False) + mySSH.close() + sys.exit("OC OAI CN5G: CN deployment failed!") + for line in report.stdout.split('\n')[1:]: columns = line.strip().split() name = columns[0] status = columns[2] html_cell += status + ' ' + name html_cell += '\n' - OC.OC_logout(mySSH) else: logging.error('This option should not occur!') mySSH.close() @@ -562,8 +541,6 @@ class EPCManagement(): HTML.CreateHtmlTestRow('N/A', 'OK', CONST.ALL_PROCESSES_OK) def Terminate5GCN(self, HTML): - imageNames = ["mysql", "oai-nrf", "oai-amf", "oai-smf", "oai-spgwu-tiny", "oai-ausf", "oai-udm", "oai-udr", "oai-traffic-server"] - containerInPods = ["", "-c nrf", "-c amf", "-c smf", "-c spgwu", "-c ausf", "-c udm", "-c udr", ""] mySSH = cls_cmd.getConnection(self.IPAddress) message = '' if re.match('ltebox', self.Type, re.IGNORECASE): @@ -598,36 +575,13 @@ class EPCManagement(): mySSH.copyin(f'{self.SourceCodePath}/logs/test_logs_CN.zip','test_logs_CN.zip') logging.debug(message) elif re.match('OC-OAI-CN5G', self.Type, re.IGNORECASE): - logging.debug('Terminating OAI CN5G on Openshift Cluster') - lIpAddr = self.IPAddress - lSourcePath = self.SourceCodePath - mySSH.run(f'rm -Rf {lSourcePath}/logs') - mySSH.run(f'mkdir -p {lSourcePath}/logs') - logging.debug('OC OAI CN5G - Collecting Log files to workspace') - succeeded = OC.OC_login(mySSH, self.OCUserName, self.OCPassword, OC.CI_OC_CORE_NAMESPACE) + succeeded, report = OC.OC_undeploy_CN(mySSH, self.OCUserName, self.OCPassword) if not succeeded: - logging.error('\u001B[1m OC Cluster Login Failed\u001B[0m') - HTML.CreateHtmlTestRow('N/A', 'KO', CONST.OC_LOGIN_FAIL) - return False - mySSH.run(f'oc describe pod &> {lSourcePath}/logs/describe-pods-post-test.log') - mySSH.run(f'oc get pods.metrics.k8s &> {lSourcePath}/logs/nf-resource-consumption.log') - for ii, ci in zip(imageNames, containerInPods): - podName = mySSH.run(f"oc get pods | grep {ii} | awk \'{{print $1}}\'").stdout.strip() - if not podName: - logging.debug(f'{ii} pod not found!') - HTML.CreateHtmlTestRow(self.Type, 'KO', CONST.INVALID_PARAMETER) - HTML.CreateHtmlTabFooter(False) - mySSH.run(f'oc logs -f {podName} {ci} &> {lSourcePath}/logs/{ii}.log &') - mySSH.run(f'helm uninstall {ii}') - podName = '' - mySSH.run(f'cd {lSourcePath}/logs && zip -r -qq test_logs_CN.zip *.log') - mySSH.copyin(f'{lSourcePath}/logs/test_logs_CN.zip','test_logs_CN.zip') - ret = mySSH.run(f'oc get pods', silent=True) - res = re.search(f'No resources found in {OC.CI_OC_CORE_NAMESPACE} namespace.', ret.stdout) - if res is not None: - logging.debug('OC OAI CN5G components uninstalled') - message = 'OC OAI CN5G components uninstalled' - OC.OC_logout(mySSH) + HTML.CreateHtmlTestRow('N/A', 'KO', report) + HTML.CreateHtmlTabFooter(False) + sys.exit("OC OAI CN5G: CN undeployment failed!") + else: + message = report.stdout else: logging.error('This should not happen!') mySSH.close() diff --git a/ci-scripts/xml_files/container_lte_n3xx_tdd_2x2_tm2.xml b/ci-scripts/xml_files/container_lte_n3xx_tdd_2x2_tm2.xml index bee8c9eba5..b518f98bdb 100644 --- a/ci-scripts/xml_files/container_lte_n3xx_tdd_2x2_tm2.xml +++ b/ci-scripts/xml_files/container_lte_n3xx_tdd_2x2_tm2.xml @@ -31,15 +31,15 @@ 111111 100000 010010 -030101 +031101 010001 000001 -050000 -050001 -070000 -070001 +051000 +051001 +071000 +071001 010010 -030201 +031201 @@ -65,7 +65,7 @@ sudo cpupower idle-set -E - + Deploy_Object Deploy eNB (TDD/Band38/2.6Ghz/N3XX) in a container ci-scripts/yaml_files/lte_n3xx_tdd_2x2_tm2 @@ -85,7 +85,7 @@ up2 - + Ping Ping: 20 pings up2 @@ -94,7 +94,7 @@ 60 - + Ping Ping: 100 pings, size 1024 up2 @@ -103,7 +103,7 @@ 60 - + Iperf iperf (DL/26Mbps/UDP)(60 sec)(single-ue profile) -u -b 1M -t 60 -R @@ -113,7 +113,7 @@ 95 - + Iperf iperf (UL/7Mbps/UDP)(60 sec)(single-ue profile) -u -b 7M -t 60 @@ -129,7 +129,7 @@ up2 - + Undeploy_Object Undeploy gNB ci-scripts/yaml_files/lte_n3xx_tdd_2x2_tm2 diff --git a/ci-scripts/xml_files/container_sa_aw2s_asue.xml b/ci-scripts/xml_files/container_sa_aw2s_asue.xml index 3885fbdd8e..820e414ffb 100644 --- a/ci-scripts/xml_files/container_sa_aw2s_asue.xml +++ b/ci-scripts/xml_files/container_sa_aw2s_asue.xml @@ -48,9 +48,9 @@ 000100 000010 000020 - 002016 000030 000040 + 002016 000200 003000 004000 diff --git a/ci-scripts/xml_files/container_sa_b200_quectel.xml b/ci-scripts/xml_files/container_sa_b200_quectel.xml index 7d139f46fe..3eff9cddfd 100644 --- a/ci-scripts/xml_files/container_sa_b200_quectel.xml +++ b/ci-scripts/xml_files/container_sa_b200_quectel.xml @@ -165,7 +165,7 @@ Iperf - iperf (DL/TCP)(30 sec)(multi-ue profile) + iperf (DL/TCP)(30 sec)(single-ue profile) -t 30 -R idefix sabox-nepes @@ -174,7 +174,7 @@ Iperf - iperf (UL/TCP)(30 sec)(multi-ue profile) + iperf (UL/TCP)(30 sec)(single-ue profile) -t 30 idefix sabox-nepes 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 af550ad4b6..b888cdb855 100644 --- a/ci-scripts/xml_files/container_sa_e1_b200_quectel.xml +++ b/ci-scripts/xml_files/container_sa_e1_b200_quectel.xml @@ -157,7 +157,7 @@ Iperf - iperf (DL/TCP)(30 sec)(multi-ue profile) + iperf (DL/TCP)(30 sec)(single-ue profile) -t 30 -R idefix sabox-nepes @@ -166,7 +166,7 @@ Iperf - iperf (UL/TCP)(30 sec)(multi-ue profile) + iperf (UL/TCP)(30 sec)(single-ue profile) -t 30 idefix sabox-nepes 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 9d9ff62012..df69f4c32c 100644 --- a/ci-scripts/xml_files/container_sa_f1_b200_quectel.xml +++ b/ci-scripts/xml_files/container_sa_f1_b200_quectel.xml @@ -189,7 +189,7 @@ Iperf - iperf (DL/TCP)(30 sec)(multi-ue profile) + iperf (DL/TCP)(30 sec)(single-ue profile) -t 30 -R idefix sabox-nepes @@ -198,7 +198,7 @@ Iperf - iperf (UL/TCP)(30 sec)(multi-ue profile) + iperf (UL/TCP)(30 sec)(single-ue profile) -t 30 idefix sabox-nepes 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 e1fb0f5318..4c1e2ab506 100644 --- a/ci-scripts/xml_files/container_sa_sc_b200_quectel.xml +++ b/ci-scripts/xml_files/container_sa_sc_b200_quectel.xml @@ -159,7 +159,7 @@ Iperf - iperf (DL/TCP)(30 sec)(multi-ue profile) + iperf (DL/TCP)(30 sec)(single-ue profile) -t 30 -R idefix sabox-nepes @@ -168,7 +168,7 @@ Iperf - iperf (UL/TCP)(30 sec)(multi-ue profile) + iperf (UL/TCP)(30 sec)(single-ue profile) -t 30 idefix sabox-nepes diff --git a/ci-scripts/yaml_files/5g_sa_n310_nrue/docker-compose.yml b/ci-scripts/yaml_files/5g_sa_n310_nrue/docker-compose.yml index 20c6f81b1b..a1815eba92 100644 --- a/ci-scripts/yaml_files/5g_sa_n310_nrue/docker-compose.yml +++ b/ci-scripts/yaml_files/5g_sa_n310_nrue/docker-compose.yml @@ -10,7 +10,7 @@ services: #entrypoint: /bin/bash -c "sleep infinity" environment: TZ: Europe/Paris - USE_ADDITIONAL_OPTIONS: --usrp-args type=n3xx,name=ni-n3xx-31641B9,addr=192.168.10.2 -r 106 --numerology 1 --band 78 -C 3511200000 --sa --ue-fo-compensation --ue-rxgain 65 --tune-offset 20000000 -A 45 --log_config.global_log_options level,nocolor,time --uicc0.imsi 208970000000111 --uicc0.nssai_sd 16777215 + USE_ADDITIONAL_OPTIONS: --usrp-args type=n3xx,name=ni-n3xx-31641B9,addr=192.168.10.2 -r 106 --numerology 1 --band 78 -C 3511200000 --sa --ue-fo-compensation --ue-rxgain 65 --tune-offset 20000000 -A 45 --log_config.global_log_options level,nocolor,time --uicc0.imsi 001020000000111 --uicc0.nssai_sd 16777215 volumes: - ../../conf_files/ue.sa.conf:/opt/oai-nr-ue/etc/nr-ue.conf healthcheck: diff --git a/ci-scripts/yaml_files/sa_f1_b200_gnb/docker-compose.yml b/ci-scripts/yaml_files/sa_f1_b200_gnb/docker-compose.yml index f7a6138d2b..d62bbc098f 100644 --- a/ci-scripts/yaml_files/sa_f1_b200_gnb/docker-compose.yml +++ b/ci-scripts/yaml_files/sa_f1_b200_gnb/docker-compose.yml @@ -30,7 +30,7 @@ services: core: -1 # for core dumps environment: USE_B2XX: 'yes' - USE_ADDITIONAL_OPTIONS: --sa --RUs.[0].sdr_addrs serial=30C51D4 --telnetsrv --telnetsrv.shrmod ci --log_config.global_log_options level,nocolor,time,line_num,function --gNBs.[0].min_rxtxtime 2 --gNBs.[0].do_CSIRS 1 --gNBs.[0].do_SRS 0 --L1s.[0].max_ldpc_iterations 20 + USE_ADDITIONAL_OPTIONS: --sa --RUs.[0].sdr_addrs serial=30C51D4 --continuous-tx --telnetsrv --telnetsrv.shrmod ci --log_config.global_log_options level,nocolor,time,line_num,function --gNBs.[0].min_rxtxtime 2 --gNBs.[0].do_CSIRS 1 --gNBs.[0].do_SRS 0 --L1s.[0].max_ldpc_iterations 20 volumes: - ../../conf_files/gnb-du.sa.band1.52prb.usrpb210.conf:/opt/oai-gnb/etc/gnb.conf - /dev:/dev diff --git a/cmake_targets/tools/build_helper b/cmake_targets/tools/build_helper index 8ff0dcfa8c..7df0fee3f8 100755 --- a/cmake_targets/tools/build_helper +++ b/cmake_targets/tools/build_helper @@ -128,6 +128,7 @@ check_supported_distribution() { "rhel9.1") return 0 ;; "rhel9.2") return 0 ;; "rhel9.3") return 0 ;; + "rhel9.4") return 0 ;; "centos7") return 0 ;; "centos8") return 0 ;; "rocky8.7") return 0 ;; diff --git a/common/utils/nr/nr_common.c b/common/utils/nr/nr_common.c index 9867c879d1..64aabab0a4 100644 --- a/common/utils/nr/nr_common.c +++ b/common/utils/nr/nr_common.c @@ -105,7 +105,6 @@ int get_supported_band_index(int scs, frequency_range_t freq_range, int n_rbs) return (-1); // not found } - // Table 5.2-1 NR operating bands in FR1 & FR2 (3GPP TS 38.101) // Table 5.4.2.3-1 Applicable NR-ARFCN per operating band in FR1 & FR2 (3GPP TS 38.101) // Notes: @@ -179,8 +178,9 @@ const nr_bandentry_t nr_bandtable[] = { {261,27500040,28350000,27500040,28350000, 2,2070833, 120} }; -int get_supported_bw_mhz(frequency_range_t frequency_range, int bw_index) +int get_supported_bw_mhz(frequency_range_t frequency_range, int scs, int nb_rb) { + int bw_index = get_supported_band_index(scs, frequency_range, nb_rb); if (frequency_range == FR1) { switch (bw_index) { case 0 : @@ -232,8 +232,8 @@ bool compare_relative_ul_channel_bw(int nr_band, int scs, int nb_ul, frame_type_ // 38.101-1 section 6.2.2 // Relative channel bandwidth <= 4% for TDD bands and <= 3% for FDD bands int index = get_nr_table_idx(nr_band, scs); - int bw_index = get_supported_band_index(scs, nr_band > 256 ? FR2 : FR1, nb_ul); - int band_size_khz = get_supported_bw_mhz(nr_band > 256 ? FR2 : FR1, bw_index) * 1000; + + int band_size_khz = get_supported_bw_mhz(nr_band > 256 ? FR2 : FR1, scs, nb_ul) * 1000; float limit = frame_type == TDD ? 0.04 : 0.03; float rel_bw = (float) (2 * band_size_khz) / (float) (nr_bandtable[index].ul_max + nr_bandtable[index].ul_min); return rel_bw <= limit; diff --git a/common/utils/nr/nr_common.h b/common/utils/nr/nr_common.h index fb3abd1247..9efd8bd84f 100644 --- a/common/utils/nr/nr_common.h +++ b/common/utils/nr/nr_common.h @@ -79,11 +79,6 @@ static inline const char *rnti_types(nr_rnti_type_t rr) #define NR_MAX_NB_LAYERS 4 // 8 -typedef enum { - nr_FR1 = 0, - nr_FR2 -} nr_frequency_range_e; - typedef struct nr_bandentry_s { int16_t band; uint64_t ul_min; @@ -176,7 +171,16 @@ static inline int get_num_dmrs(uint16_t dmrs_mask ) return(num_dmrs); } -static __attribute__((always_inline)) inline int count_bits_set(uint64_t v) +static inline int count_bits(uint8_t *arr, int sz) +{ + AssertFatal(sz % sizeof(int) == 0, "to implement if needed\n"); + int ret = 0; + for (uint *ptr = (uint *)arr; (uint8_t *)ptr < arr + sz; ptr++) + ret += __builtin_popcount(*ptr); + return ret; +} + +static __attribute__((always_inline)) inline int count_bits64(uint64_t v) { return __builtin_popcountll(v); } @@ -206,7 +210,7 @@ uint16_t SL_to_bitmap(int startSymbolIndex, int nrOfSymbols); int get_nb_periods_per_frame(uint8_t tdd_period); long rrc_get_max_nr_csrs(const int max_rbs, long b_SRS); bool compare_relative_ul_channel_bw(int nr_band, int scs, int nb_ul, frame_type_t frame_type); -int get_supported_bw_mhz(frequency_range_t frequency_range, int bw_index); +int get_supported_bw_mhz(frequency_range_t frequency_range, int scs, int nb_rb); int get_supported_band_index(int scs, frequency_range_t freq_range, int n_rbs); void get_samplerate_and_bw(int mu, int n_rb, diff --git a/doc/TESTBenches.md b/doc/TESTBenches.md index 433e696e79..9ea8534faa 100644 --- a/doc/TESTBenches.md +++ b/doc/TESTBenches.md @@ -9,10 +9,10 @@ | asterix | 172.21.16.127 | CI-Asterix-Usage | *unused* | 172.21.19.14 | | obelix | 172.21.16.128 | CI-Obelix-Usage | eNB (n40, n78), nrUE | 172.21.19.13, X300 (192.168.60.2) | | porcepix | 172.21.16.136 | CI-Porcepix | Executor, EPC, 5GC | -- | -| nrmodule2 | 172.21.16.139 | CI-NrModule2 | Quectel | Quectel module | +| up2 | 172.21.19.68 | CI-UP2-Usage | COTS UE | Quectel RM520N | | nepes | 172.21.16.137 | CI-Nepes | gNB (n78), EPC/5GC | B200mini (30C51EB) | | ofqot | 172.21.16.109 | CI-Ofqot | gNB (n78) | B200mini (30C51D4) | -| idefix | 172.21.16.135 | CI-Idefix | Quectel | Quectel module | +| idefix | 172.21.16.135 | CI-Idefix | COTS UE | Quectel RM500Q | | caracal | 172.21.16.132 | CI-Caracal | gNB/phytest | N300 (192.168.10.2) | | amariue | 172.21.16.144 | CI-Amarisoft-UE-Usage | nrUE | Amarisoft UE simulator | | nano | 172.21.18.48 | CI-Nano-Legacy-EPC | Executor, EPC, adb | 2x COTS (adb) | @@ -23,7 +23,8 @@ | avra | 172.21.16.124 | CI-Avra-Usage | gNB (n78) | AW2S Jaguar (192.168.80.239) | | orion | 172.21.16.134 | CI-Orion-Build-Sanity-Check-Deploy-Test, CI-Orion-DsTester-Deploy-Test | Build | | | aerial2 | 172.21.16.131 | CI-Aerial2-Usage | gNB (PNF/Nvidia CUBB + VNF) | Foxconn RU, _Nvidia Aerial SDK integrated_ | -| sphex | 172.21.17.54 | CI-Sphex-Usage | Quectel | Quectel module | +| sphex | 172.21.17.54 | CI-Sphex-Usage | COTS UE | Quectel RM500Q | +| matix | 172.21.19.58 | CI-Matix-Usage | gNB (n77) | N310 | Note: The available resources, and their current usage, is indicated here: - [Lockable resources of jenkins-oai](https://jenkins-oai.eurecom.fr/lockable-resources/): @@ -154,7 +155,7 @@ information on how the images are built. - tests OAI 4G for 10 MHz/TM1; known to be unstable - [RAN-LTE-TDD-2x2-Container](https://jenkins-oai.eurecom.fr/view/RAN/job/RAN-LTE-TDD-2x2-Container/) ~4G-LTE - - obelix + N310, porcepix, nrmodule2 + Quectel + - obelix + N310, porcepix, up2 + Quectel - TM1 and TM2 test, IF4p5 fronthaul - [RAN-LTE-TDD-LTEBOX-Container](https://jenkins-oai.eurecom.fr/job/RAN-LTE-TDD-LTEBOX-Container/) ~4G-LTE @@ -191,8 +192,12 @@ information on how the images are built. - OpenShift cluster for CN deployment and container images for gNB and UE deployment - [RAN-SA-AERIAL-CN5G](https://jenkins-oai.eurecom.fr/job/RAN-SA-AERIAL-CN5G/) ~5G-NR - - 5G-NR SA test setup: OAI VNF + PNF/NVIDIA CUBB on Aerial2 (U22) + Foxconn RU, COTS UE (Quctel RM500Q), OAI CN5G + - 5G-NR SA test setup: OAI VNF + PNF/NVIDIA CUBB on Aerial2 (U22) + Foxconn RU, sphex + COTS UE (Quectel RM500Q), OAI CN5G - container images for gNB deployment +- [RAN-SA-2x2-Module-CN5G](https://jenkins-oai.eurecom.fr/view/RAN/job/RAN-SA-2x2-Module-CN5G/) + ~5G-NR + - matix + N310 (gNB), up2 + COTS UE (Quectel RM520N), OAI 5GC deployed in docker on matix + - NR performance tests: 2x2 configuration, 60 MHz and 100 MHz bandwidth ### RAN-CI-NSA-Trigger @@ -201,9 +206,6 @@ information on how the images are built. - [RAN-NSA-2x2-Module-OAIEPC](https://jenkins-oai.eurecom.fr/job/RAN-NSA-2x2-Module-OAIEPC/) - obelix + N310 (eNB), asterix + N310 (gNB), nrmodule2 + Quectel, porcepix w/ Magma EPC - LTE 2x2 and NR 2x2 (non-standalone) -- [RAN-SA-Module-CN5G](https://jenkins-oai.eurecom.fr/view/RAN/job/RAN-SA-Module-CN5G/) - - asterix + N310 (gNB), nrmodule2 + Quectel, porcepix w/ OAI 5GC - - NR 2x2 (standalone) ## How to reproduce CI results diff --git a/doc/testbenches_doc_resources/5g-ota-bench.pdf b/doc/testbenches_doc_resources/5g-ota-bench.pdf index 4199a44166..3dc2e39e80 100644 Binary files a/doc/testbenches_doc_resources/5g-ota-bench.pdf and b/doc/testbenches_doc_resources/5g-ota-bench.pdf differ diff --git a/doc/testbenches_doc_resources/5g-ota-bench.png b/doc/testbenches_doc_resources/5g-ota-bench.png index 30309bf9f4..1a84e4dd20 100644 Binary files a/doc/testbenches_doc_resources/5g-ota-bench.png and b/doc/testbenches_doc_resources/5g-ota-bench.png differ diff --git a/doc/testbenches_doc_resources/5g-ota-bench.tex b/doc/testbenches_doc_resources/5g-ota-bench.tex index b7413af7db..0ffd01fa63 100644 --- a/doc/testbenches_doc_resources/5g-ota-bench.tex +++ b/doc/testbenches_doc_resources/5g-ota-bench.tex @@ -16,16 +16,16 @@ \node[label=above:porcepix] (porcepix) {\includegraphics[width=1.2cm]{server}}; - \node[above right=-0.4cm and 2cm of porcepix, label=above:asterix] (asterix) + \node[above right=-0.4cm and 2cm of porcepix, label=above:matix] (matix) {\includegraphics[width=1.2cm]{server}} edge (porcepix); - \node[right=0.3cm of asterix, label=above:N310] (n310a) - {\includegraphics[width=1.5cm]{n310}} edge (asterix); - \node[right=.2cm of n310a, duplexer] (b78o) {n78} edge (n310a); - \node[below right=-0.1cm and 0.35cm of b78o.east] (anto1) - {\includegraphics[width=0.3cm]{antenna}} edge (b78o); - \node[above right=-0.1cm and 0.35cm of b78o.east] (anto2) - {\includegraphics[width=0.3cm]{antenna}} edge (b78o); + \node[right=0.3cm of matix, label=above:N310] (n310a) + {\includegraphics[width=1.5cm]{n310}} edge (matix); + \node[right=.2cm of n310a, duplexer] (b77o) {n77} edge (n310a); + \node[below right=-0.1cm and 0.35cm of b77o.east] (anto1) + {\includegraphics[width=0.3cm]{antenna}} edge (b77o); + \node[above right=-0.1cm and 0.35cm of b77o.east] (anto2) + {\includegraphics[width=0.3cm]{antenna}} edge (b77o); \node[below right=-0.4cm and 2cm of porcepix, label=above:obelix] (obelix) {\includegraphics[width=1.2cm]{server}} @@ -45,7 +45,7 @@ \node[above right=-0.1cm and 0.35cm of b78o.east] (anto2) {\includegraphics[width=0.3cm]{antenna}} edge (b78o); - \node[above right=-0.5cm and 5.0cm of n310o.east, label=above:RM500Q-GL] (quectel) + \node[above right=-0.5cm and 5.0cm of n310o.east, label=above:RM520N-GL] (quectel) {\includegraphics[height=1.2cm]{quectel}}; \node[above left=-0.1cm and 0.8cm of quectel.west] (aq2) {\includegraphics[width=0.3cm]{antenna}} edge (quectel); @@ -55,7 +55,7 @@ {\includegraphics[width=0.3cm]{antenna}} edge (quectel); \node[below=-0.2cm of aq3] {\includegraphics[width=0.3cm]{antenna}} edge (quectel); - \node[right=1cm of quectel, label=above:nrmodule2] (nrmodule2) + \node[right=1cm of quectel, label=above:up2] (up2) {\includegraphics[width=1.2cm]{server}} edge (quectel); diff --git a/executables/nr-gnb.c b/executables/nr-gnb.c index 1fa3478d75..9df218fe1b 100644 --- a/executables/nr-gnb.c +++ b/executables/nr-gnb.c @@ -115,10 +115,10 @@ static void tx_func(void *param) int slot_tx = info->slot; int frame_rx = info->frame_rx; int slot_rx = info->slot_rx; - int absslot_tx = info->timestamp_tx / info->gNB->frame_parms.get_samples_per_slot(slot_tx, &info->gNB->frame_parms); - int absslot_rx = absslot_tx - info->gNB->RU_list[0]->sl_ahead; + int64_t absslot_tx = info->timestamp_tx / info->gNB->frame_parms.get_samples_per_slot(slot_tx, &info->gNB->frame_parms); + int64_t absslot_rx = absslot_tx - info->gNB->RU_list[0]->sl_ahead; if (absslot_rx < 0) { - LOG_W(NR_PHY, "Slot ahead %d is larger than absslot_tx %d. Cannot start TX yet.\n", info->gNB->RU_list[0]->sl_ahead, absslot_tx); + LOG_W(NR_PHY, "Slot ahead %d is larger than absslot_tx %ld. Cannot start TX yet.\n", info->gNB->RU_list[0]->sl_ahead, absslot_tx); return; } LOG_D(NR_PHY, "%d.%d running tx_func\n", frame_tx, slot_tx); @@ -218,8 +218,8 @@ void rx_func(void *param) for (; i < gNB->frame_parms.slots_per_subframe / 2; i++) cumul_samples += gNB->frame_parms.get_samples_per_slot(i, &gNB->frame_parms); int samples = cumul_samples / i; - int absslot_tx = info->timestamp_tx / samples; - int absslot_rx = absslot_tx - gNB->RU_list[0]->sl_ahead; + int64_t absslot_tx = info->timestamp_tx / samples; + int64_t absslot_rx = absslot_tx - gNB->RU_list[0]->sl_ahead; int rt_prof_idx = absslot_rx % RT_PROF_DEPTH; clock_gettime(CLOCK_MONOTONIC,&info->gNB->rt_L1_profiling.start_L1_RX[rt_prof_idx]); start_meas(&softmodem_stats_rxtx_sf); diff --git a/executables/nr-ru.c b/executables/nr-ru.c index 96c9e55e75..41adc59bf6 100644 --- a/executables/nr-ru.c +++ b/executables/nr-ru.c @@ -841,7 +841,7 @@ void tx_rf(RU_t *ru,int frame,int slot, uint64_t timestamp) { flags_burst = proc->first_tx == 1 ? TX_BURST_START : TX_BURST_MIDDLE; } - if (fp->freq_range == nr_FR2) + if (fp->freq_range == FR2) flags_gpio = get_gpio_flags(ru, slot); const int flags = flags_burst | (flags_gpio << 4); @@ -1108,8 +1108,8 @@ void ru_tx_func(void *param) { for (; i < fp->slots_per_subframe / 2; i++) cumul_samples += fp->get_samples_per_slot(i, fp); int samples = cumul_samples / i; - int absslot_tx = info->timestamp_tx / samples; - int absslot_rx = absslot_tx - ru->sl_ahead; + int64_t absslot_tx = info->timestamp_tx / samples; + int64_t absslot_rx = absslot_tx - ru->sl_ahead; int rt_prof_idx = absslot_rx % RT_PROF_DEPTH; clock_gettime(CLOCK_MONOTONIC,&ru->rt_ru_profiling.start_RU_TX[rt_prof_idx]); // do TX front-end processing if needed (precoding and/or IDFTs) @@ -1335,7 +1335,7 @@ void *ru_thread( void *param ) { proc->timestamp_tx += fp->get_samples_per_slot(i % fp->slots_per_frame, fp); proc->tti_tx = (proc->tti_rx + ru->sl_ahead) % fp->slots_per_frame; proc->frame_tx = proc->tti_rx > proc->tti_tx ? (proc->frame_rx + 1) & 1023 : proc->frame_rx; - int absslot_rx = proc->timestamp_rx/fp->get_samples_per_slot(proc->tti_rx,fp); + int64_t absslot_rx = proc->timestamp_rx/fp->get_samples_per_slot(proc->tti_rx,fp); int rt_prof_idx = absslot_rx % RT_PROF_DEPTH; clock_gettime(CLOCK_MONOTONIC,&ru->rt_ru_profiling.return_RU_south_in[rt_prof_idx]); LOG_D(PHY,"AFTER fh_south_in - SFN/SL:%d%d RU->proc[RX:%d.%d TX:%d.%d] RC.gNB[0]:[RX:%d%d TX(SFN):%d]\n", diff --git a/executables/rt_profiling.h b/executables/rt_profiling.h index 03dcf94517..9b72a7091f 100644 --- a/executables/rt_profiling.h +++ b/executables/rt_profiling.h @@ -40,7 +40,7 @@ extern "C" // depth of trace in slots #define RT_PROF_DEPTH 100 typedef struct { - int absslot_rx[RT_PROF_DEPTH]; + int64_t absslot_rx[RT_PROF_DEPTH]; struct timespec return_RU_south_in[RT_PROF_DEPTH]; struct timespec return_RU_feprx[RT_PROF_DEPTH]; struct timespec return_RU_prachrx[RT_PROF_DEPTH]; @@ -50,7 +50,7 @@ typedef struct { } rt_ru_profiling_t; typedef struct { - int absslot_ux[RT_PROF_DEPTH]; + int64_t absslot_ux[RT_PROF_DEPTH]; struct timespec start_L1_RX[RT_PROF_DEPTH]; struct timespec return_L1_RX[RT_PROF_DEPTH]; struct timespec start_L1_TX[RT_PROF_DEPTH]; diff --git a/openair1/PHY/INIT/nr_init.c b/openair1/PHY/INIT/nr_init.c index c688b20e21..0470abcf49 100644 --- a/openair1/PHY/INIT/nr_init.c +++ b/openair1/PHY/INIT/nr_init.c @@ -515,8 +515,7 @@ void nr_phy_config_request_sim(PHY_VARS_gNB *gNB, } fp->threequarter_fs = 0; - int bw_index = get_supported_band_index(mu, fp->nr_band > 256 ? FR2 : FR1, N_RB_DL); - gNB_config->carrier_config.dl_bandwidth.value = get_supported_bw_mhz(fp->nr_band > 256 ? FR2 : FR1, bw_index); + gNB_config->carrier_config.dl_bandwidth.value = get_supported_bw_mhz(fp->nr_band > 256 ? FR2 : FR1, mu, N_RB_DL); nr_init_frame_parms(gNB_config, fp); diff --git a/openair1/PHY/INIT/nr_parms.c b/openair1/PHY/INIT/nr_parms.c index dc516d7f24..c96754fe74 100644 --- a/openair1/PHY/INIT/nr_parms.c +++ b/openair1/PHY/INIT/nr_parms.c @@ -252,7 +252,7 @@ void nr_init_frame_parms(nfapi_nr_config_request_scf_t* cfg, NR_DL_FRAME_PARMS * fp->get_samples_slot_timestamp = &get_samples_slot_timestamp; fp->get_slot_from_timestamp = &get_slot_from_timestamp; fp->samples_per_frame = 10 * fp->samples_per_subframe; - fp->freq_range = (fp->dl_CarrierFreq < 6e9)? nr_FR1 : nr_FR2; + fp->freq_range = (fp->dl_CarrierFreq < 6e9)? FR1 : FR2; fp->Ncp = Ncp; @@ -341,12 +341,12 @@ int nr_init_frame_parms_ue(NR_DL_FRAME_PARMS *fp, fp->get_samples_per_slot = &get_samples_per_slot; fp->get_samples_slot_timestamp = &get_samples_slot_timestamp; fp->samples_per_frame = 10 * fp->samples_per_subframe; - fp->freq_range = (fp->dl_CarrierFreq < 6e9)? nr_FR1 : nr_FR2; + fp->freq_range = (fp->dl_CarrierFreq < 6e9)? FR1 : FR2; uint8_t sco = 0; - if (((fp->freq_range == nr_FR1) && (config->ssb_table.ssb_subcarrier_offset < 24)) || - ((fp->freq_range == nr_FR2) && (config->ssb_table.ssb_subcarrier_offset < 12))) { - if (fp->freq_range == nr_FR1) + if (((fp->freq_range == FR1) && (config->ssb_table.ssb_subcarrier_offset < 24)) || + ((fp->freq_range == FR2) && (config->ssb_table.ssb_subcarrier_offset < 12))) { + if (fp->freq_range == FR1) sco = config->ssb_table.ssb_subcarrier_offset>>config->ssb_config.scs_common; else sco = config->ssb_table.ssb_subcarrier_offset; @@ -379,7 +379,7 @@ void nr_init_frame_parms_ue_sa(NR_DL_FRAME_PARMS *frame_parms, uint64_t downlink frame_parms->numerology_index = mu; frame_parms->dl_CarrierFreq = downlink_frequency; frame_parms->ul_CarrierFreq = downlink_frequency + delta_duplex; - frame_parms->freq_range = (frame_parms->dl_CarrierFreq < 6e9)? nr_FR1 : nr_FR2; + frame_parms->freq_range = (frame_parms->dl_CarrierFreq < 6e9)? FR1 : FR2; frame_parms->N_RB_UL = frame_parms->N_RB_DL; frame_parms->nr_band = nr_band; diff --git a/openair1/PHY/NR_TRANSPORT/nr_prach.c b/openair1/PHY/NR_TRANSPORT/nr_prach.c index 95c2c8040b..d103505357 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_prach.c +++ b/openair1/PHY/NR_TRANSPORT/nr_prach.c @@ -350,6 +350,12 @@ void rx_nr_prach_ru(RU_t *ru, dftlen = dftlen*6; break; + case 245760: + // 200 MHz @ 245.76 Ms/s + Ncp <<= 3; + dftlen <<= 3; + break; + default: AssertFatal(1==0,"sample rate %f MHz not supported for numerology %d\n", fp->samples_per_subframe / 1000.0, mu); } diff --git a/openair1/PHY/NR_UE_ESTIMATION/nr_adjust_synch_ue.c b/openair1/PHY/NR_UE_ESTIMATION/nr_adjust_synch_ue.c index bcac18a60b..61c12d145a 100644 --- a/openair1/PHY/NR_UE_ESTIMATION/nr_adjust_synch_ue.c +++ b/openair1/PHY/NR_UE_ESTIMATION/nr_adjust_synch_ue.c @@ -71,7 +71,7 @@ int nr_adjust_synch_ue(NR_DL_FRAME_PARMS *frame_parms, int diff = ue->max_pos_avg >> 15; - if (frame_parms->freq_range==nr_FR2) + if (frame_parms->freq_range == FR2) sync_offset = 2; else sync_offset = 0; diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_prach.c b/openair1/PHY/NR_UE_TRANSPORT/nr_prach.c index 3ba71ed3ea..ea24f0a45c 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_prach.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_prach.c @@ -366,6 +366,12 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, int frame, uint8_t dftlen = dftlen*6; break; + case 245760: + // 200 MHz @ 245.76 Ms/s + Ncp <<= 3; + dftlen <<= 3; + break; + default: AssertFatal(1==0,"sample rate %f MHz not supported for numerology %d\n", fp->samples_per_subframe / 1000.0, mu); } diff --git a/openair1/PHY/defs_nr_common.h b/openair1/PHY/defs_nr_common.h index 121ef0d3c1..3d0f2efa88 100644 --- a/openair1/PHY/defs_nr_common.h +++ b/openair1/PHY/defs_nr_common.h @@ -139,7 +139,7 @@ typedef uint32_t (*get_samples_slot_timestamp_t)(int slot, const NR_DL_FRAME_PAR struct NR_DL_FRAME_PARMS { /// frequency range - nr_frequency_range_e freq_range; + frequency_range_t freq_range; // /// Placeholder to replace overlapping fields below // nfapi_nr_rf_config_t rf_config; /// Placeholder to replace SSB overlapping fields below diff --git a/openair1/SCHED_NR/phy_procedures_nr_gNB.c b/openair1/SCHED_NR/phy_procedures_nr_gNB.c index 291e063aa4..886482bc5d 100644 --- a/openair1/SCHED_NR/phy_procedures_nr_gNB.c +++ b/openair1/SCHED_NR/phy_procedures_nr_gNB.c @@ -71,10 +71,10 @@ void nr_common_signal_procedures(PHY_VARS_gNB *gNB,int frame,int slot, nfapi_nr_ // for FR2 offsetToPointA is expressed in terms of 60 kHz SCS and k_SSB expressed in terms of the subcarrier spacing provided // by the higher-layer parameter subCarrierSpacingCommon const int scs = cfg->ssb_config.scs_common.value; - const int prb_offset = (fp->freq_range == nr_FR1) ? ssb_pdu.ssb_pdu_rel15.ssbOffsetPointA >> scs - : ssb_pdu.ssb_pdu_rel15.ssbOffsetPointA >> (scs - 2); + const int prb_offset = (fp->freq_range == FR1) ? ssb_pdu.ssb_pdu_rel15.ssbOffsetPointA >> scs + : ssb_pdu.ssb_pdu_rel15.ssbOffsetPointA >> (scs - 2); const int sc_offset = - (fp->freq_range == nr_FR1) ? ssb_pdu.ssb_pdu_rel15.SsbSubcarrierOffset >> scs : ssb_pdu.ssb_pdu_rel15.SsbSubcarrierOffset; + (fp->freq_range == FR1) ? ssb_pdu.ssb_pdu_rel15.SsbSubcarrierOffset >> scs : ssb_pdu.ssb_pdu_rel15.SsbSubcarrierOffset; fp->ssb_start_subcarrier = (12 * prb_offset + sc_offset); if (fp->print_ue_help_cmdline_log && get_softmodem_params()->sa) { @@ -134,7 +134,7 @@ void nr_common_signal_procedures(PHY_VARS_gNB *gNB,int frame,int slot, nfapi_nr_ #endif // Beam_id is currently used only for FR2 - if (fp->freq_range==nr_FR2){ + if (fp->freq_range == FR2){ LOG_D(PHY,"slot %d, ssb_index %d, beam %d\n",slot,ssb_index,cfg->ssb_table.ssb_beam_id_list[ssb_index].beam_id.value); for (int j=0;jsymbols_per_slot;j++) gNB->common_vars.beam_id[0][slot*fp->symbols_per_slot+j] = cfg->ssb_table.ssb_beam_id_list[ssb_index].beam_id.value; diff --git a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c index da734cc84d..eb84c1e470 100644 --- a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c +++ b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c @@ -494,19 +494,25 @@ static int nr_ue_pdsch_procedures(PHY_VARS_NR_UE *ue, // We handle only one CW now if (!(NR_MAX_NB_LAYERS>4)) { NR_UE_DLSCH_t *dlsch0 = &dlsch[0]; - int harq_pid = dlsch0->dlsch_config.harq_process_nbr; + fapi_nr_dl_config_dlsch_pdu_rel15_t *dlschCfg = &dlsch0->dlsch_config; + int harq_pid = dlschCfg->harq_process_nbr; + // dlsch0_harq contains the previous transmissions data for this harq pid NR_DL_UE_HARQ_t *dlsch0_harq = &ue->dl_harq_processes[0][harq_pid]; - uint16_t BWPStart = dlsch0->dlsch_config.BWPStart; - uint16_t pdsch_start_rb = dlsch0->dlsch_config.start_rb; - uint16_t pdsch_nb_rb = dlsch0->dlsch_config.number_rbs; - uint16_t s0 = dlsch0->dlsch_config.start_symbol; - uint16_t s1 = dlsch0->dlsch_config.number_symbols; - AssertFatal(dlsch0->dlsch_config.resource_alloc == 1, - "DLSCH resource allocation type0 not supported at PHY\n"); - - LOG_D(PHY,"[UE %d] nr_slot_rx %d, harq_pid %d (%d), BWP start %d, rb_start %d, nb_rb %d, symbol_start %d, nb_symbols %d, DMRS mask %x, Nl %d\n", - ue->Mod_id,nr_slot_rx,harq_pid,dlsch0_harq->status,BWPStart,pdsch_start_rb,pdsch_nb_rb,s0,s1,dlsch0->dlsch_config.dlDmrsSymbPos, dlsch0->Nl); + LOG_D(PHY, + "[UE %d] nr_slot_rx %d, harq_pid %d (%d), BWP start %d, rb_start %d, nb_rb %d, symbol_start %d, nb_symbols %d, DMRS mask " + "%x, Nl %d\n", + ue->Mod_id, + nr_slot_rx, + harq_pid, + dlsch0_harq->status, + dlschCfg->BWPStart, + dlschCfg->start_rb, + dlschCfg->number_rbs, + dlschCfg->start_symbol, + dlschCfg->number_symbols, + dlschCfg->dlDmrsSymbPos, + dlsch0->Nl); const uint32_t pdsch_est_size = ((ue->frame_parms.symbols_per_slot * ue->frame_parms.ofdm_symbol_size + 15) / 16) * 16; __attribute__((aligned(32))) int32_t pdsch_dl_ch_estimates[ue->frame_parms.nb_antennas_rx * dlsch0->Nl][pdsch_est_size]; @@ -522,25 +528,26 @@ static int nr_ue_pdsch_procedures(PHY_VARS_NR_UE *ue, __attribute__((aligned(32))) int32_t rxdataF_comp[dlsch[0].Nl][ue->frame_parms.nb_antennas_rx][rx_size_symbol * NR_SYMBOLS_PER_SLOT]; memset(rxdataF_comp, 0, sizeof(rxdataF_comp)); - for (int m = s0; m < (s0 +s1); m++) { - if (dlsch0->dlsch_config.dlDmrsSymbPos & (1 << m)) { + for (int m = dlschCfg->start_symbol; m < (dlschCfg->start_symbol + dlschCfg->number_symbols); m++) { + if (dlschCfg->dlDmrsSymbPos & (1 << m)) { for (int nl = 0; nl < dlsch0->Nl; nl++) { //for MIMO Config: it shall loop over no_layers LOG_D(PHY,"PDSCH Channel estimation layer %d, slot %d, symbol %d\n", nl, nr_slot_rx, m); nr_pdsch_channel_estimation(ue, proc, nl, - get_dmrs_port(nl,dlsch0->dlsch_config.dmrs_ports), + get_dmrs_port(nl, dlschCfg->dmrs_ports), m, - dlsch0->dlsch_config.nscid, - dlsch0->dlsch_config.dlDmrsScramblingId, - BWPStart, - dlsch0->dlsch_config.dmrsConfigType, - dlsch0->dlsch_config.rb_offset, - ue->frame_parms.first_carrier_offset+(BWPStart + pdsch_start_rb)*12, - pdsch_nb_rb, + dlschCfg->nscid, + dlschCfg->dlDmrsScramblingId, + dlschCfg->BWPStart, + dlschCfg->dmrsConfigType, + dlschCfg->rb_offset, + ue->frame_parms.first_carrier_offset + (dlschCfg->BWPStart + dlschCfg->start_rb) * 12, + dlschCfg->number_rbs, pdsch_est_size, pdsch_dl_ch_estimates, - ue->frame_parms.samples_per_slot_wCP, rxdataF); + ue->frame_parms.samples_per_slot_wCP, + rxdataF); #if 0 ///LOG_M: the channel estimation int nr_frame_rx = proc->frame_rx; @@ -558,22 +565,22 @@ static int nr_ue_pdsch_procedures(PHY_VARS_NR_UE *ue, if (ue->chest_time == 1) { // averaging time domain channel estimates nr_chest_time_domain_avg(&ue->frame_parms, - (int32_t **) pdsch_dl_ch_estimates, - dlsch0->dlsch_config.number_symbols, - dlsch0->dlsch_config.start_symbol, - dlsch0->dlsch_config.dlDmrsSymbPos, - pdsch_nb_rb); + (int32_t **)pdsch_dl_ch_estimates, + dlschCfg->number_symbols, + dlschCfg->start_symbol, + dlschCfg->dlDmrsSymbPos, + dlschCfg->number_rbs); } - uint16_t first_symbol_with_data = s0; + uint16_t first_symbol_with_data = dlschCfg->start_symbol; uint32_t dmrs_data_re; - if (dlsch0->dlsch_config.dmrsConfigType == NFAPI_NR_DMRS_TYPE1) - dmrs_data_re = 12 - 6 * dlsch0->dlsch_config.n_dmrs_cdm_groups; + if (dlschCfg->dmrsConfigType == NFAPI_NR_DMRS_TYPE1) + dmrs_data_re = 12 - 6 * dlschCfg->n_dmrs_cdm_groups; else - dmrs_data_re = 12 - 4 * dlsch0->dlsch_config.n_dmrs_cdm_groups; + dmrs_data_re = 12 - 4 * dlschCfg->n_dmrs_cdm_groups; - while ((dmrs_data_re == 0) && (dlsch0->dlsch_config.dlDmrsSymbPos & (1 << first_symbol_with_data))) { + while ((dmrs_data_re == 0) && (dlschCfg->dlDmrsSymbPos & (1 << first_symbol_with_data))) { first_symbol_with_data++; } @@ -582,7 +589,7 @@ static int nr_ue_pdsch_procedures(PHY_VARS_NR_UE *ue, int32_t log2_maxh = 0; start_meas(&ue->rx_pdsch_stats); - for (int m = s0; m < (s1 + s0); m++) { + for (int m = dlschCfg->start_symbol; m < (dlschCfg->number_symbols + dlschCfg->start_symbol); m++) { bool first_symbol_flag = false; if (m == first_symbol_with_data) first_symbol_flag = true; diff --git a/openair1/SIMULATION/NR_PHY/pbchsim.c b/openair1/SIMULATION/NR_PHY/pbchsim.c index acfa696b24..408fe64d28 100644 --- a/openair1/SIMULATION/NR_PHY/pbchsim.c +++ b/openair1/SIMULATION/NR_PHY/pbchsim.c @@ -162,8 +162,7 @@ void nr_phy_config_request_sim_pbchsim(PHY_VARS_gNB *gNB, else fp->nr_band = 78; fp->threequarter_fs= 0; - int bw_index = get_supported_band_index(mu, fp->nr_band > 256 ? FR2 : FR1, N_RB_DL); - gNB_config->carrier_config.dl_bandwidth.value = get_supported_bw_mhz(fp->nr_band > 256 ? FR2 : FR1, bw_index); + gNB_config->carrier_config.dl_bandwidth.value = get_supported_bw_mhz(fp->nr_band > 256 ? FR2 : FR1, mu, N_RB_DL); fp->ofdm_offset_divisor = UINT_MAX; nr_init_frame_parms(gNB_config, fp); @@ -487,7 +486,7 @@ int main(int argc, char **argv) frame_parms->N_RB_DL = N_RB_DL; frame_parms->Nid_cell = Nid_cell; frame_parms->ssb_type = nr_ssb_type_C; - frame_parms->freq_range = mu<2 ? nr_FR1 : nr_FR2; + frame_parms->freq_range = mu<2 ? FR1 : FR2; nr_phy_config_request_sim_pbchsim(gNB,N_RB_DL,N_RB_DL,mu,Nid_cell,SSB_positions); gNB->gNB_config.tdd_table.tdd_period.value = 6; @@ -620,8 +619,8 @@ int main(int argc, char **argv) for (i=0; iLmax; i++) { if((SSB_positions >> i) & 0x01) { - const int sc_offset = frame_parms->freq_range == nr_FR1 ? ssb_subcarrier_offset<freq_range == nr_FR1 ? gNB->gNB_config.ssb_table.ssb_offset_point_a.value<gNB_config.ssb_table.ssb_offset_point_a.value << (mu - 2); + const int sc_offset = frame_parms->freq_range == FR1 ? ssb_subcarrier_offset<freq_range == FR1 ? gNB->gNB_config.ssb_table.ssb_offset_point_a.value<gNB_config.ssb_table.ssb_offset_point_a.value << (mu - 2); msgDataTx.ssb[i].ssb_pdu.ssb_pdu_rel15.bchPayload = 0x55dd33; msgDataTx.ssb[i].ssb_pdu.ssb_pdu_rel15.SsbBlockIndex = i; msgDataTx.ssb[i].ssb_pdu.ssb_pdu_rel15.SsbSubcarrierOffset = sc_offset; diff --git a/openair1/SIMULATION/NR_PHY/prachsim.c b/openair1/SIMULATION/NR_PHY/prachsim.c index 71f92aebd3..9586cf2d64 100644 --- a/openair1/SIMULATION/NR_PHY/prachsim.c +++ b/openair1/SIMULATION/NR_PHY/prachsim.c @@ -422,7 +422,7 @@ int main(int argc, char **argv){ frame_parms->N_RB_UL = N_RB_UL; frame_parms->threequarter_fs = threequarter_fs; frame_parms->frame_type = TDD; - frame_parms->freq_range = (mu != 3 ? nr_FR1 : nr_FR2); + frame_parms->freq_range = (mu != 3 ? FR1 : FR2); frame_parms->numerology_index = mu; nr_phy_config_request_sim(gNB, N_RB_UL, N_RB_UL, mu, Nid_cell, SSB_positions); @@ -447,7 +447,7 @@ int main(int argc, char **argv){ frame_parms->Ncp, frame_parms->samples_per_subframe, frame_parms->frame_type == FDD ? "FDD" : "TDD", - frame_parms->freq_range == nr_FR1 ? "FR1" : "FR2"); + frame_parms->freq_range == FR1 ? "FR1" : "FR2"); ru->nr_frame_parms = frame_parms; ru->if_south = LOCAL_RF; diff --git a/openair2/COMMON/e1ap_messages_types.h b/openair2/COMMON/e1ap_messages_types.h index 5b727a3818..cc48a6f9e9 100644 --- a/openair2/COMMON/e1ap_messages_types.h +++ b/openair2/COMMON/e1ap_messages_types.h @@ -55,6 +55,12 @@ typedef net_ip_address_t e1ap_net_ip_address_t; +typedef enum BEARER_CONTEXT_STATUS_e { + BEARER_ACTIVE = 0, + BEARER_SUSPEND, + BEARER_RESUME, +} BEARER_CONTEXT_STATUS_t; + typedef struct PLMN_ID_s { int mcc; int mnc; @@ -240,6 +246,7 @@ typedef struct e1ap_bearer_setup_req_s { char integrityProtectionKey[128]; long ueDlAggMaxBitRate; PLMN_ID_t servingPLMNid; + BEARER_CONTEXT_STATUS_t bearerContextStatus; long activityNotificationLevel; int numPDUSessions; pdu_session_to_setup_t pduSession[E1AP_MAX_NUM_PDU_SESSIONS]; diff --git a/openair2/E1AP/e1ap.c b/openair2/E1AP/e1ap.c index 07baf5757c..fda507ef4e 100644 --- a/openair2/E1AP/e1ap.c +++ b/openair2/E1AP/e1ap.c @@ -1192,7 +1192,7 @@ static int fill_BEARER_CONTEXT_MODIFICATION_REQUEST(e1ap_bearer_setup_req_t *con ieC2->value.present = E1AP_BearerContextModificationRequestIEs__value_PR_GNB_CU_UP_UE_E1AP_ID; ieC2->value.choice.GNB_CU_UP_UE_E1AP_ID = bearerCxt->gNB_cu_up_ue_id; /* optional */ - /* */ + /* c3. E1AP_ProtocolIE_ID_id_System_BearerContextModificationRequest */ asn1cSequenceAdd(out->protocolIEs.list, E1AP_BearerContextModificationRequestIEs_t, ieC3); ieC3->id = E1AP_ProtocolIE_ID_id_System_BearerContextModificationRequest; ieC3->criticality = E1AP_Criticality_reject; @@ -1230,6 +1230,15 @@ static int fill_BEARER_CONTEXT_MODIFICATION_REQUEST(e1ap_bearer_setup_req_t *con } } } + /* c4. E1AP_ProtocolIE_ID_id_BearerContextStatusChange */ + if (bearerCxt->bearerContextStatus == BEARER_SUSPEND) { + asn1cSequenceAdd(out->protocolIEs.list, E1AP_BearerContextModificationRequestIEs_t, ieC4); + ieC4->id = E1AP_ProtocolIE_ID_id_BearerContextStatusChange; + ieC4->criticality = E1AP_Criticality_reject; + ieC4->value.present = E1AP_BearerContextModificationRequestIEs__value_PR_BearerContextStatusChange; + /* Bearer Context Status Change */ + ieC4->value.choice.BearerContextStatusChange = E1AP_BearerContextStatusChange_suspend; + } return 0; } @@ -1390,6 +1399,13 @@ static void extract_BEARER_CONTEXT_MODIFICATION_REQUEST(const E1AP_E1AP_PDU_t *p } break; + case E1AP_ProtocolIE_ID_id_BearerContextStatusChange: + /* Bearer Context Status Change */ + DevAssert(ie->criticality == E1AP_Criticality_reject); + DevAssert(ie->value.present == E1AP_BearerContextModificationRequestIEs__value_PR_BearerContextStatusChange); + bearerCxt->bearerContextStatus = (ie->value.choice.BearerContextStatusChange == E1AP_BearerContextStatusChange_suspend) ? BEARER_SUSPEND : BEARER_ACTIVE; + break; + default: LOG_E(E1AP, "Handle for this IE is not implemented (or) invalid IE detected\n"); break; diff --git a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c index c5f3daf88f..1ef7a9e2ce 100644 --- a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c +++ b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c @@ -1694,7 +1694,7 @@ int get_nr_prach_occasion_info_from_index(uint8_t index, if (pointa > 2016666) { //FR2 x = table_6_3_3_2_4_prachConfig_Index[index][2]; s_map = table_6_3_3_2_4_prachConfig_Index[index][5]; - *N_RA_sfn += count_bits_set(s_map); + *N_RA_sfn += count_bits64(s_map); *N_RA_slot = table_6_3_3_2_4_prachConfig_Index[index][7]; // Number of RACH slots within a subframe *max_association_period = 160/(x * 10); if (start_symbol != NULL && N_t_slot != NULL && N_dur != NULL && format != NULL){ @@ -1721,7 +1721,7 @@ int get_nr_prach_occasion_info_from_index(uint8_t index, if (unpaired) { x = table_6_3_3_2_3_prachConfig_Index[index][2]; s_map = table_6_3_3_2_3_prachConfig_Index[index][4]; - *N_RA_sfn += count_bits_set(s_map); + *N_RA_sfn += count_bits64(s_map); *N_RA_slot = table_6_3_3_2_3_prachConfig_Index[index][6]; // Number of RACH slots within a subframe *max_association_period = 160/(x * 10); if (start_symbol != NULL && N_t_slot != NULL && N_dur != NULL && format != NULL){ @@ -1746,7 +1746,7 @@ int get_nr_prach_occasion_info_from_index(uint8_t index, else { // FDD x = table_6_3_3_2_2_prachConfig_Index[index][2]; s_map = table_6_3_3_2_2_prachConfig_Index[index][4]; - *N_RA_sfn += count_bits_set(s_map); + *N_RA_sfn += count_bits64(s_map); *N_RA_slot = table_6_3_3_2_2_prachConfig_Index[index][6]; if (start_symbol != NULL && N_t_slot != NULL && N_dur != NULL && format != NULL){ *start_symbol = table_6_3_3_2_2_prachConfig_Index[index][5]; @@ -5158,6 +5158,59 @@ uint16_t nr_get_csi_bitlen(nr_csi_report_t *csi_report_template, uint8_t csi_rep return csi_bitlen; } +bool supported_bw_comparison(int bw_mhz, NR_SupportedBandwidth_t *supported_BW, long *support_90mhz) +{ + if (bw_mhz == 90) + return support_90mhz ? true : false; + switch (supported_BW->present) { + case NR_SupportedBandwidth_PR_fr1 : + switch (supported_BW->choice.fr1) { + case NR_SupportedBandwidth__fr1_mhz5 : + return bw_mhz == 5; + case NR_SupportedBandwidth__fr1_mhz10 : + return bw_mhz == 10; + case NR_SupportedBandwidth__fr1_mhz15 : + return bw_mhz == 15; + case NR_SupportedBandwidth__fr1_mhz20 : + return bw_mhz == 20; + case NR_SupportedBandwidth__fr1_mhz25 : + return bw_mhz == 25; + case NR_SupportedBandwidth__fr1_mhz30 : + return bw_mhz == 30; + case NR_SupportedBandwidth__fr1_mhz40 : + return bw_mhz == 40; + case NR_SupportedBandwidth__fr1_mhz50 : + return bw_mhz == 50; + case NR_SupportedBandwidth__fr1_mhz60 : + return bw_mhz == 60; + case NR_SupportedBandwidth__fr1_mhz80 : + return bw_mhz == 80; + case NR_SupportedBandwidth__fr1_mhz100 : + return bw_mhz == 100; + default : + AssertFatal(false, "Invalid FR1 supported band\n"); + } + break; + case NR_SupportedBandwidth_PR_fr2 : + switch (supported_BW->choice.fr2) { + case NR_SupportedBandwidth__fr2_mhz50 : + return bw_mhz == 50; + case NR_SupportedBandwidth__fr2_mhz100 : + return bw_mhz == 100; + case NR_SupportedBandwidth__fr2_mhz200 : + return bw_mhz == 200; + case NR_SupportedBandwidth__fr2_mhz400 : + return bw_mhz == 400; + default : + AssertFatal(false, "Invalid FR2 supported band\n"); + } + break; + default : + AssertFatal(false, "Invalid BW type\n"); + } + return false; +} + uint16_t compute_PDU_length(uint32_t num_TLV, uint16_t total_length) { uint8_t pdu_length = 8; // 2 bytes PDU_Length + 2 bytes PDU_Index + 4 bytes num_TLV diff --git a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h index 60af5706ae..8fce9ee559 100644 --- a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h +++ b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h @@ -33,6 +33,7 @@ #include "NR_MIB.h" #include "NR_CellGroupConfig.h" +#include "NR_UE-NR-Capability.h" #include "nr_mac.h" #include "common/utils/nr/nr_common.h" @@ -316,4 +317,6 @@ uint16_t compute_PDU_length(uint32_t num_TLV, uint16_t total_length); rnti_t nr_get_ra_rnti(uint8_t s_id, uint8_t t_id, uint8_t f_id, uint8_t ul_carrier_id); +bool supported_bw_comparison(int bw_mhz, NR_SupportedBandwidth_t *supported_BW, long *support_90mhz); + #endif diff --git a/openair2/LAYER2/NR_MAC_UE/config_ue.c b/openair2/LAYER2/NR_MAC_UE/config_ue.c index 0511573be9..d15611f847 100644 --- a/openair2/LAYER2/NR_MAC_UE/config_ue.c +++ b/openair2/LAYER2/NR_MAC_UE/config_ue.c @@ -118,10 +118,9 @@ static void config_common_ue_sa(NR_UE_MAC_INST_t *mac, NR_FrequencyInfoDL_SIB_t *frequencyInfoDL = &scc->downlinkConfigCommon.frequencyInfoDL; AssertFatal(frequencyInfoDL->frequencyBandList.list.array[0]->freqBandIndicatorNR, "Field mandatory present for DL in SIB1\n"); mac->nr_band = *frequencyInfoDL->frequencyBandList.list.array[0]->freqBandIndicatorNR; - int bw_index = get_supported_band_index(frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing, - mac->nr_band > 256 ? FR2 : FR1, - frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->carrierBandwidth); - cfg->carrier_config.dl_bandwidth = get_supported_bw_mhz(mac->frequency_range, bw_index); + cfg->carrier_config.dl_bandwidth = get_supported_bw_mhz(mac->frequency_range, + frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing, + frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->carrierBandwidth); uint64_t dl_bw_khz = (12 * frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->carrierBandwidth) * (15 << frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing); @@ -140,10 +139,9 @@ static void config_common_ue_sa(NR_UE_MAC_INST_t *mac, NR_FrequencyInfoUL_SIB_t *frequencyInfoUL = &scc->uplinkConfigCommon->frequencyInfoUL; mac->p_Max = frequencyInfoUL->p_Max ? *frequencyInfoUL->p_Max : INT_MIN; - bw_index = get_supported_band_index(frequencyInfoUL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing, - mac->nr_band > 256 ? FR2 : FR1, - frequencyInfoUL->scs_SpecificCarrierList.list.array[0]->carrierBandwidth); - cfg->carrier_config.uplink_bandwidth = get_supported_bw_mhz(mac->frequency_range, bw_index); + cfg->carrier_config.uplink_bandwidth = get_supported_bw_mhz(mac->frequency_range, + frequencyInfoUL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing, + frequencyInfoUL->scs_SpecificCarrierList.list.array[0]->carrierBandwidth); if (frequencyInfoUL->absoluteFrequencyPointA == NULL) cfg->carrier_config.uplink_frequency = cfg->carrier_config.dl_frequency; @@ -262,10 +260,9 @@ static void config_common_ue(NR_UE_MAC_INST_t *mac, mac->frame_type = get_frame_type(mac->nr_band, get_softmodem_params()->numerology); mac->frequency_range = mac->nr_band < 256 ? FR1 : FR2; - int bw_index = get_supported_band_index(frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing, - mac->nr_band > 256 ? FR2 : FR1, - frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->carrierBandwidth); - cfg->carrier_config.dl_bandwidth = get_supported_bw_mhz(mac->frequency_range, bw_index); + cfg->carrier_config.dl_bandwidth = get_supported_bw_mhz(mac->frequency_range, + frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing, + frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->carrierBandwidth); cfg->carrier_config.dl_frequency = from_nrarfcn(mac->nr_band, *scc->ssbSubcarrierSpacing, @@ -287,10 +284,9 @@ static void config_common_ue(NR_UE_MAC_INST_t *mac, NR_FrequencyInfoUL_t *frequencyInfoUL = scc->uplinkConfigCommon->frequencyInfoUL; mac->p_Max = frequencyInfoUL->p_Max ? *frequencyInfoUL->p_Max : INT_MIN; - int bw_index = get_supported_band_index(frequencyInfoUL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing, - *frequencyInfoUL->frequencyBandList->list.array[0] > 256 ? FR2 : FR1, - frequencyInfoUL->scs_SpecificCarrierList.list.array[0]->carrierBandwidth); - cfg->carrier_config.uplink_bandwidth = get_supported_bw_mhz(mac->frequency_range, bw_index); + cfg->carrier_config.uplink_bandwidth = get_supported_bw_mhz(mac->frequency_range, + frequencyInfoUL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing, + frequencyInfoUL->scs_SpecificCarrierList.list.array[0]->carrierBandwidth); long *UL_pointA = NULL; if (frequencyInfoUL->absoluteFrequencyPointA) @@ -1426,7 +1422,7 @@ void nr_rrc_mac_config_req_reset(module_id_t module_id, NR_UE_MAC_INST_t *mac = get_mac_inst(module_id); switch (cause) { case GO_TO_IDLE: - reset_ra(mac, cause); + reset_ra(mac, true); release_mac_configuration(mac, cause); nr_ue_init_mac(mac); nr_ue_mac_default_configs(mac); @@ -1435,14 +1431,14 @@ void nr_rrc_mac_config_req_reset(module_id_t module_id, break; case DETACH: LOG_A(NR_MAC, "Received detach indication\n"); - reset_ra(mac, cause); + reset_ra(mac, true); reset_mac_inst(mac); nr_ue_reset_sync_state(mac); release_mac_configuration(mac, cause); mac->state = UE_DETACHING; break; case T300_EXPIRY: - reset_ra(mac, cause); + reset_ra(mac, false); reset_mac_inst(mac); mac->state = UE_SYNC; // still in sync but need to restart RA break; @@ -2045,6 +2041,47 @@ static void configure_servingcell_info(NR_UE_ServingCell_Info_t *sc_info, NR_Ser } } +/// This function implements 38.331 Section 5.3.12: UE actions upon PUCCH/SRS release request +void release_PUCCH_SRS(NR_UE_MAC_INST_t *mac) +{ + // release PUCCH-CSI-Resources configured in CSI-ReportConfig + NR_UE_ServingCell_Info_t *sc_info = &mac->sc_info; + NR_CSI_MeasConfig_t *meas_config = sc_info->csi_MeasConfig; + if (meas_config && meas_config->csi_ReportConfigToAddModList) { + for (int i = 0; i < meas_config->csi_ReportConfigToAddModList->list.count; i++) { + struct NR_CSI_ReportConfig__reportConfigType *type = &meas_config->csi_ReportConfigToAddModList->list.array[i]->reportConfigType; + switch (type->present) { + case NR_CSI_ReportConfig__reportConfigType_PR_periodic : + for (int j = type->choice.periodic->pucch_CSI_ResourceList.list.count; j > 0 ; j--) + asn_sequence_del(&type->choice.periodic->pucch_CSI_ResourceList.list, j - 1, 1); + break; + case NR_CSI_ReportConfig__reportConfigType_PR_semiPersistentOnPUCCH : + for (int j = type->choice.semiPersistentOnPUCCH->pucch_CSI_ResourceList.list.count; j > 0 ; j--) + asn_sequence_del(&type->choice.semiPersistentOnPUCCH->pucch_CSI_ResourceList.list, j - 1, 1); + break; + case NR_CSI_ReportConfig__reportConfigType_PR_semiPersistentOnPUSCH : + case NR_CSI_ReportConfig__reportConfigType_PR_aperiodic : + // no PUCCH config to release + break; + default : + AssertFatal(false, "Invalid CSI report type\n"); + } + } + } + + for (int bwp = 0; bwp < mac->ul_BWPs.count; bwp++) { + // release SchedulingRequestResourceConfig instances configured in PUCCH-Config + NR_PUCCH_Config_t *pucch_Config = mac->ul_BWPs.array[bwp]->pucch_Config; + for (int j = pucch_Config->schedulingRequestResourceToAddModList->list.count; j > 0 ; j--) + asn_sequence_del(&pucch_Config->schedulingRequestResourceToAddModList->list, j - 1, 1); + // release SRS-Resource instances configured in SRS-Config + // TODO not clear if only SRS-Resources or also the ResourceSet should be released + NR_SRS_Config_t *srs_Config = mac->ul_BWPs.array[bwp]->srs_Config; + for (int j = srs_Config->srs_ResourceToAddModList->list.count; j > 0 ; j--) + asn_sequence_del(&srs_Config->srs_ResourceToAddModList->list, j - 1, 1); + } +} + void release_dl_BWP(NR_UE_MAC_INST_t *mac, int index) { NR_UE_DL_BWP_t *bwp = mac->dl_BWPs.array[index]; @@ -2139,18 +2176,8 @@ static void handle_mac_uecap_info(NR_UE_MAC_INST_t *mac, NR_UE_NR_Capability_t * NR_FeatureSetDownlinkPerCC_t *fs_dl_cc = fs_dlcc_list->list.array[i]; if (mac->current_DL_BWP->scs != fs_dl_cc->supportedSubcarrierSpacingDL) continue; - int uecap_bw_index; - if (fs_dl_cc->supportedBandwidthDL.present == NR_SupportedBandwidth_PR_fr1) { - uecap_bw_index = fs_dl_cc->supportedBandwidthDL.choice.fr1; - // 90 MHz option is indicated by a separate pointer in case indicated supported BW is 100MHz - // so we need to increase the index by 1 unit to point to 100 MHz if not 90MHz - if (uecap_bw_index == NR_SupportedBandwidth__fr1_mhz100 && !fs_dl_cc->channelBW_90mhz) - uecap_bw_index++; - } - else - uecap_bw_index = fs_dl_cc->supportedBandwidthDL.choice.fr2; int dl_bw_mhz = mac->phy_config.config_req.carrier_config.dl_bandwidth; - if (dl_bw_mhz != get_supported_bw_mhz(mac->frequency_range, uecap_bw_index)) + if (!supported_bw_comparison(dl_bw_mhz, &fs_dl_cc->supportedBandwidthDL, fs_dl_cc->channelBW_90mhz)) continue; if (fs_dl_cc->maxNumberMIMO_LayersPDSCH) mac->uecap_maxMIMO_PDSCH_layers = 2 << *fs_dl_cc->maxNumberMIMO_LayersPDSCH; @@ -2162,18 +2189,8 @@ static void handle_mac_uecap_info(NR_UE_MAC_INST_t *mac, NR_UE_NR_Capability_t * NR_FeatureSetUplinkPerCC_t *fs_ul_cc = fs_ulcc_list->list.array[i]; if (mac->current_UL_BWP->scs != fs_ul_cc->supportedSubcarrierSpacingUL) continue; - int uecap_bw_index; - if (fs_ul_cc->supportedBandwidthUL.present == NR_SupportedBandwidth_PR_fr1) { - uecap_bw_index = fs_ul_cc->supportedBandwidthUL.choice.fr1; - // 90 MHz option is indicated by a separate pointer in case indicated supported BW is 100MHz - // so we need to increase the index by 1 unit to point to 100 MHz if not 90MHz - if (uecap_bw_index == NR_SupportedBandwidth__fr1_mhz100 && !fs_ul_cc->channelBW_90mhz) - uecap_bw_index++; - } - else - uecap_bw_index = fs_ul_cc->supportedBandwidthUL.choice.fr2; int ul_bw_mhz = mac->phy_config.config_req.carrier_config.uplink_bandwidth; - if (ul_bw_mhz != get_supported_bw_mhz(mac->frequency_range, uecap_bw_index)) + if (!supported_bw_comparison(ul_bw_mhz, &fs_ul_cc->supportedBandwidthUL, fs_ul_cc->channelBW_90mhz)) continue; if (fs_ul_cc->maxNumberMIMO_LayersNonCB_PUSCH) mac->uecap_maxMIMO_PUSCH_layers_nocb = 1 << *fs_ul_cc->maxNumberMIMO_LayersNonCB_PUSCH; diff --git a/openair2/LAYER2/NR_MAC_UE/config_ue_sl.c b/openair2/LAYER2/NR_MAC_UE/config_ue_sl.c index 73fb6782ae..044ad3b255 100644 --- a/openair2/LAYER2/NR_MAC_UE/config_ue_sl.c +++ b/openair2/LAYER2/NR_MAC_UE/config_ue_sl.c @@ -140,10 +140,7 @@ static void sl_prepare_phy_config(int module_id, AssertFatal(carriercfg, "SCS_SpecificCarrier cannot be NULL"); - int bw_index = get_supported_band_index(carriercfg->subcarrierSpacing, - sl_band > 256 ? FR2 : FR1, - carriercfg->carrierBandwidth); - phycfg->sl_carrier_config.sl_bandwidth = get_supported_bw_mhz(FR1, bw_index); + phycfg->sl_carrier_config.sl_bandwidth = get_supported_bw_mhz(FR1, carriercfg->subcarrierSpacing, carriercfg->carrierBandwidth); phycfg->sl_carrier_config.sl_frequency = from_nrarfcn(sl_band,carriercfg->subcarrierSpacing,pointA_ARFCN); // freq in kHz diff --git a/openair2/LAYER2/NR_MAC_UE/mac_defs.h b/openair2/LAYER2/NR_MAC_UE/mac_defs.h index fa58cf4676..2cda190f23 100644 --- a/openair2/LAYER2/NR_MAC_UE/mac_defs.h +++ b/openair2/LAYER2/NR_MAC_UE/mac_defs.h @@ -308,7 +308,7 @@ typedef struct { /// number of attempt for rach uint8_t RA_attempt_number; /// Random-access procedure flag - uint8_t RA_active; + bool RA_active; /// Random-access preamble index int ra_PreambleIndex; // When multiple SSBs per RO is configured, this indicates which one is selected in this RO -> this is used to properly compute the PRACH preamble @@ -341,6 +341,8 @@ typedef struct { /// Msg3 buffer uint8_t *Msg3_buffer; + bool msg3_C_RNTI; + /// Random-access Contention Resolution Timer NR_timer_t contention_resolution_timer; /// Transmitted UE Contention Resolution Identifier diff --git a/openair2/LAYER2/NR_MAC_UE/mac_proto.h b/openair2/LAYER2/NR_MAC_UE/mac_proto.h index b13c2a9865..ea30052058 100644 --- a/openair2/LAYER2/NR_MAC_UE/mac_proto.h +++ b/openair2/LAYER2/NR_MAC_UE/mac_proto.h @@ -100,7 +100,7 @@ NR_UE_MAC_INST_t * nr_l2_init_ue(int nb_inst); NR_UE_MAC_INST_t *get_mac_inst(module_id_t module_id); void reset_mac_inst(NR_UE_MAC_INST_t *nr_mac); -void reset_ra(NR_UE_MAC_INST_t *nr_mac, NR_UE_MAC_reset_cause_t cause); +void reset_ra(NR_UE_MAC_INST_t *nr_mac, bool free_prach); void release_mac_configuration(NR_UE_MAC_INST_t *mac, NR_UE_MAC_reset_cause_t cause); @@ -293,7 +293,7 @@ void nr_get_prach_resources(NR_UE_MAC_INST_t *mac, void prepare_msg4_feedback(NR_UE_MAC_INST_t *mac, int pid, int ack_nack); void configure_initial_pucch(PUCCH_sched_t *pucch, int res_ind); - +void release_PUCCH_SRS(NR_UE_MAC_INST_t *mac); void nr_ue_reset_sync_state(NR_UE_MAC_INST_t *mac); void nr_ue_send_synch_request(NR_UE_MAC_INST_t *mac, module_id_t module_id, int cc_id, int cell_id); @@ -312,6 +312,7 @@ void init_RA(NR_UE_MAC_INST_t *mac, int16_t get_prach_tx_power(NR_UE_MAC_INST_t *mac); void free_rach_structures(NR_UE_MAC_INST_t *nr_mac, int bwp_id); +void schedule_RA_after_SR_failure(NR_UE_MAC_INST_t *mac); void nr_Msg1_transmitted(NR_UE_MAC_INST_t *mac); void nr_Msg3_transmitted(NR_UE_MAC_INST_t *mac, uint8_t CC_id, frame_t frameP, slot_t slotP, uint8_t gNB_id); void nr_get_msg3_payload(NR_UE_MAC_INST_t *mac, uint8_t *buf, int TBS_max); @@ -335,7 +336,7 @@ void remove_ul_config_last_item(fapi_nr_ul_config_request_pdu_t *pdu); fapi_nr_ul_config_request_pdu_t *fapiLockIterator(fapi_nr_ul_config_request_t *ul_config, frame_t frame_tx, int slot_tx); void release_ul_config(fapi_nr_ul_config_request_pdu_t *pdu, bool clearIt); - +void clear_ul_config_request(NR_UE_MAC_INST_t *mac, int scs); int16_t compute_nr_SSB_PL(NR_UE_MAC_INST_t *mac, short ssb_rsrp_dBm); // PUSCH scheduler: diff --git a/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c b/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c index 8d13ddfb68..79086da5a9 100644 --- a/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c +++ b/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c @@ -299,14 +299,14 @@ void free_rach_structures(NR_UE_MAC_INST_t *nr_mac, int bwp_id) free(nr_mac->ssb_list[bwp_id].tx_ssb); } -void reset_ra(NR_UE_MAC_INST_t *nr_mac, NR_UE_MAC_reset_cause_t cause) +void reset_ra(NR_UE_MAC_INST_t *nr_mac, bool free_prach) { RA_config_t *ra = &nr_mac->ra; if(ra->rach_ConfigDedicated) asn1cFreeStruc(asn_DEF_NR_RACH_ConfigDedicated, ra->rach_ConfigDedicated); memset(ra, 0, sizeof(RA_config_t)); - if (cause == T300_EXPIRY) + if (!free_prach) return; for (int i = 0; i < MAX_NUM_BWP_UE; i++) diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c index e89e68f317..3cdcbf769d 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c @@ -61,7 +61,7 @@ void init_RA(NR_UE_MAC_INST_t *mac, { mac->state = UE_PERFORMING_RA; RA_config_t *ra = &mac->ra; - ra->RA_active = 1; + ra->RA_active = true; ra->ra_PreambleIndex = -1; ra->RA_usedGroupA = 1; ra->RA_RAPID_found = 0; @@ -582,17 +582,25 @@ void nr_Msg3_transmitted(NR_UE_MAC_INST_t *mac, uint8_t CC_id, frame_t frameP, s ra->ra_state = nrRA_WAIT_CONTENTION_RESOLUTION; } -void nr_get_msg3_payload(NR_UE_MAC_INST_t *mac, uint8_t *buf, int TBS_max) +static uint8_t *fill_msg3_crnti_pdu(RA_config_t *ra, uint8_t *pdu, uint16_t crnti) +{ + // RA triggered by UE MAC with C-RNTI in MAC CE + LOG_D(NR_MAC, "Generating MAC CE with C-RNTI for MSG3 %x\n", crnti); + *(NR_MAC_SUBHEADER_FIXED *)pdu = (NR_MAC_SUBHEADER_FIXED){.LCID = UL_SCH_LCID_C_RNTI, .R = 0}; + pdu += sizeof(NR_MAC_SUBHEADER_FIXED); + + // C-RNTI MAC CE (2 octets) + uint16_t rnti_pdu = ((crnti & 0xFF) << 8) | ((crnti >> 8) & 0xFF); + memcpy(pdu, &rnti_pdu, sizeof(rnti_pdu)); + pdu += sizeof(rnti_pdu); + ra->t_crnti = crnti; + return pdu; +} + +static uint8_t *fill_msg3_pdu_from_rlc(NR_UE_MAC_INST_t *mac, uint8_t *pdu, int TBS_max) { RA_config_t *ra = &mac->ra; - - // we already stored MSG3 in the buffer, we can use that - if (ra->Msg3_buffer) { - buf = ra->Msg3_buffer; - return; - } - - uint8_t *pdu = buf; + // regular MSG3 with PDU coming from higher layers *(NR_MAC_SUBHEADER_FIXED *)pdu = (NR_MAC_SUBHEADER_FIXED){.LCID = UL_SCH_LCID_CCCH}; pdu += sizeof(NR_MAC_SUBHEADER_FIXED); tbs_size_t len = mac_rlc_data_req(mac->ue_id, @@ -613,6 +621,25 @@ void nr_get_msg3_payload(NR_UE_MAC_INST_t *mac, uint8_t *buf, int TBS_max) // We copy from persisted memory to another persisted memory memcpy(ra->cont_res_id, pdu, sizeof(uint8_t) * 6); pdu += len; + return pdu; +} + +void nr_get_msg3_payload(NR_UE_MAC_INST_t *mac, uint8_t *buf, int TBS_max) +{ + RA_config_t *ra = &mac->ra; + + // we already stored MSG3 in the buffer, we can use that + if (ra->Msg3_buffer) { + memcpy(buf, ra->Msg3_buffer, sizeof(uint8_t) * TBS_max); + return; + } + + uint8_t *pdu = buf; + if (ra->msg3_C_RNTI) + pdu = fill_msg3_crnti_pdu(ra, pdu, mac->crnti); + else + pdu = fill_msg3_pdu_from_rlc(mac, pdu, TBS_max); + AssertFatal(TBS_max >= pdu - buf, "Allocated resources are not enough for Msg3!\n"); // Padding: fill remainder with 0 LOG_D(NR_MAC, "Remaining %ld bytes, filling with padding\n", pdu - buf); @@ -657,7 +684,7 @@ void nr_ue_get_rach(NR_UE_MAC_INST_t *mac, int CC_id, frame_t frame, uint8_t gNB LOG_D(NR_MAC, "[UE %d][%d.%d]: ra_state %d, RA_active %d\n", mac->ue_id, frame, nr_slot_tx, ra->ra_state, ra->RA_active); if (ra->ra_state > nrRA_UE_IDLE && ra->ra_state < nrRA_SUCCEEDED) { - if (ra->RA_active == 0) { + if (!ra->RA_active) { NR_RACH_ConfigCommon_t *setup = mac->current_UL_BWP->rach_ConfigCommon; NR_RACH_ConfigGeneric_t *rach_ConfigGeneric = &setup->rach_ConfigGeneric; init_RA(mac, &ra->prach_resources, setup, rach_ConfigGeneric, ra->rach_ConfigDedicated); @@ -825,7 +852,8 @@ void nr_ra_succeeded(NR_UE_MAC_INST_t *mac, const uint8_t gNB_index, const frame } LOG_D(MAC, "[UE %d] clearing RA_active flag...\n", mac->ue_id); - ra->RA_active = 0; + ra->RA_active = false; + ra->msg3_C_RNTI = false; ra->ra_state = nrRA_SUCCEEDED; mac->state = UE_CONNECTED; free_and_zero(ra->Msg3_buffer); @@ -875,6 +903,25 @@ void nr_ra_failed(NR_UE_MAC_INST_t *mac, uint8_t CC_id, NR_PRACH_RESOURCES_t *pr } } +void schedule_RA_after_SR_failure(NR_UE_MAC_INST_t *mac) +{ + LOG_W(NR_MAC, "Triggering new RA procedure for UE with RNTI %x\n", mac->crnti); + mac->state = UE_SYNC; + reset_ra(mac, false); + mac->ra.msg3_C_RNTI = true; + // release PUCCH for all Serving Cells; + // release SRS for all Serving Cells; + release_PUCCH_SRS(mac); + // clear any configured downlink assignments and uplink grants; + int scs = mac->current_UL_BWP->scs; + 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, scs); + // clear any PUSCH resources for semi-persistent CSI reporting + // TODO we don't have semi-persistent CSI reporting +} + void prepare_msg4_feedback(NR_UE_MAC_INST_t *mac, int pid, int ack_nack) { NR_UE_HARQ_STATUS_t *current_harq = &mac->dl_harq_info[pid]; diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_dci_configuration.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_dci_configuration.c index 6b0318ab6b..27219bed1f 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_dci_configuration.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_dci_configuration.c @@ -43,7 +43,7 @@ void fill_dci_search_candidates(const NR_SearchSpace_t *ss, fapi_nr_dl_config_dci_dl_pdu_rel15_t *rel15, const uint32_t Y) { - LOG_D(NR_MAC_DCI, "Filling search candidates for DCI\n"); + LOG_T(NR_MAC_DCI, "Filling search candidates for DCI\n"); int i = 0; for (int maxL = 16; maxL > 0; maxL >>= 1) { @@ -54,7 +54,7 @@ void fill_dci_search_candidates(const NR_SearchSpace_t *ss, maxL); if (max_number_of_candidates == 0) continue; - LOG_D(NR_MAC_DCI, "L %d, max number of candidates %d, aggregation %d\n", maxL, max_number_of_candidates, aggregation); + LOG_T(NR_MAC_DCI, "L %d, max number of candidates %d, aggregation %d\n", maxL, max_number_of_candidates, aggregation); int N_cce_sym = 0; // nb of rbs of coreset per symbol for (int f = 0; f < 6; f++) { for (int t = 0; t < 8; t++) { @@ -66,7 +66,7 @@ void fill_dci_search_candidates(const NR_SearchSpace_t *ss, continue; for (int j = 0; j < max_number_of_candidates; j++) { int first_cce = aggregation * ((Y + ((j * N_cces) / (aggregation * max_number_of_candidates)) + 0) % (N_cces / aggregation)); - LOG_D(NR_MAC_DCI, + LOG_T(NR_MAC_DCI, "Candidate %d of %d first_cce %d (L %d N_cces %d Y %d)\n", j, max_number_of_candidates, @@ -79,7 +79,7 @@ void fill_dci_search_candidates(const NR_SearchSpace_t *ss, for (int k = 0; k < i; k++) { if (rel15->CCE[k] == first_cce && rel15->L[k] == aggregation) { duplicated = true; - LOG_D(NR_MAC_DCI, "Candidate %d of %d is duplicated\n", j, max_number_of_candidates); + LOG_T(NR_MAC_DCI, "Candidate %d of %d is duplicated\n", j, max_number_of_candidates); } } if (!duplicated) { @@ -315,7 +315,7 @@ void config_dci_pdu(NR_UE_MAC_INST_t *mac, #ifdef DEBUG_DCI for (int i = 0; i < rel15->num_dci_options; i++) { - LOG_D(NR_MAC_DCI, + LOG_T(NR_MAC_DCI, "[DCI_CONFIG] Configure DCI PDU: rnti_type %d BWPSize %d BWPStart %d rel15->SubcarrierSpacing %d rel15->dci_format %d " "rel15->dci_length %d sps %d monitoringSymbolsWithinSlot %d \n", rnti_type, diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c index 5f0bc51e9a..490235445f 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c @@ -293,6 +293,7 @@ int8_t nr_ue_process_dci_freq_dom_resource_assignment(nfapi_nr_ue_pusch_pdu_t *p pdsch_Config->resourceAllocation == NR_PDSCH_Config__resourceAllocation_resourceAllocationType0) { // TS 38.214 subclause 5.1.2.2.1 Downlink resource allocation type 0 dlsch_config_pdu->resource_alloc = 0; + memset(dlsch_config_pdu->rb_bitmap, 0, sizeof(dlsch_config_pdu->rb_bitmap)); int P = getRBGSize(n_RB_DLBWP, pdsch_Config->rbg_Size); int n_RBG = frequency_domain_assignment.nbits; int index = 0; @@ -312,6 +313,23 @@ int8_t nr_ue_process_dci_freq_dom_resource_assignment(nfapi_nr_ue_pusch_pdu_t *p dlsch_config_pdu->rb_bitmap[j / 8] |= bit_rbg << (j % 8); index += size_RBG; } + dlsch_config_pdu->number_rbs = count_bits(dlsch_config_pdu->rb_bitmap, sizeofArray(dlsch_config_pdu->rb_bitmap)); + // Temporary code to process type0 as type1 when the RB allocation is contiguous + int state = 0; + for (int i = 0; i < sizeof(dlsch_config_pdu->rb_bitmap) * 8; i++) { + int allocated = dlsch_config_pdu->rb_bitmap[i / 8] & (1 << (i % 8)); + if (allocated) { + if (state == 0) { + dlsch_config_pdu->start_rb = i; + state = 1; + } else + AssertFatal(state == 1, "non-contiguous RB allocation in RB allocation type 0 not implemented"); + } else { + if (state == 1) { + state = 2; + } + } + } } else if (pdsch_Config && pdsch_Config->resourceAllocation == NR_PDSCH_Config__resourceAllocation_dynamicSwitch) @@ -2434,7 +2452,7 @@ bool trigger_periodic_scheduling_request(NR_UE_MAC_INST_t *mac, PUCCH_sched_t *p if(!pucch_Config || !pucch_Config->schedulingRequestResourceToAddModList || - pucch_Config->schedulingRequestResourceToAddModList->list.count==0) + pucch_Config->schedulingRequestResourceToAddModList->list.count == 0) return false; // SR not configured int sr_count = 0; @@ -2458,7 +2476,12 @@ bool trigger_periodic_scheduling_request(NR_UE_MAC_INST_t *mac, PUCCH_sched_t *p pucch->pucch_resource = sr_pucch; pucch->n_sr = 1; /* sr_payload = 1 means that this is a positive SR, sr_payload = 0 means that it is a negative SR */ - pucch->sr_payload = nr_ue_get_SR(mac, frame, slot, sr_Config->schedulingRequestID); + int ret = nr_ue_get_SR(mac, frame, slot, sr_Config->schedulingRequestID); + if (ret < 0) { + memset(pucch, 0, sizeof(*pucch)); + return false; + } + pucch->sr_payload = ret; sr_count++; AssertFatal(sr_count < 2, "Cannot handle more than 1 SR per slot yet\n"); } @@ -2500,18 +2523,18 @@ int8_t nr_ue_get_SR(NR_UE_MAC_INST_t *mac, frame_t frame, slot_t slot, NR_Schedu return 1; } - // TODO - // notify RRC to release PUCCH for all Serving Cells; - // notify RRC to release SRS for all Serving Cells; - // clear any configured downlink assignments and uplink grants; - // clear any PUSCH resources for semi-persistent CSI reporting; + LOG_W(NR_MAC, + "[UE %d] SR not served! SR counter %d reached sr_MaxTransmissions %d\n", + mac->ue_id, + sr_info->counter, + sr_info->maxTransmissions); + // initiate a Random Access procedure (see clause 5.1) on the SpCell and cancel all pending SRs. - LOG_E(NR_MAC, "[UE %d] SR not served. Triggering of new RA procedure not implemented yet.\n", mac->ue_id); sr_info->pending = false; sr_info->counter = 0; nr_timer_stop(&sr_info->prohibitTimer); - - return 0; + schedule_RA_after_SR_failure(mac); + return -1; } // section 5.2.5 of 38.214 @@ -3511,7 +3534,7 @@ void nr_ue_process_mac_pdu(NR_UE_MAC_INST_t *mac, nr_downlink_indication_t *dl_i mac_len = 6; if (ra->ra_state == nrRA_WAIT_CONTENTION_RESOLUTION) { - LOG_I(MAC, "[UE %d][RAPROC] Frame %d : received contention resolution identity: 0x%02x%02x%02x%02x%02x%02x Terminating RA procedure\n", + LOG_I(MAC, "[UE %d]Frame %d Contention resolution identity: 0x%02x%02x%02x%02x%02x%02x Terminating RA procedure\n", mac->ue_id, frameP, pduP[1], @@ -3523,21 +3546,21 @@ void nr_ue_process_mac_pdu(NR_UE_MAC_INST_t *mac, nr_downlink_indication_t *dl_i bool ra_success = true; if (!IS_SOFTMODEM_IQPLAYER) { // Control is bypassed when replaying IQs (BMC) - for(int i = 0; icont_res_id[i] != pduP[i+1]) { + for(int i = 0; i < mac_len; i++) { + if(ra->cont_res_id[i] != pduP[i + 1]) { ra_success = false; break; } } } - if ( (ra->RA_active == 1) && ra_success) { + if (ra->RA_active && ra_success) { nr_ra_succeeded(mac, gNB_index, frameP, slot); - } else if (!ra_success){ + } else if (!ra_success) { // TODO: Handle failure of RA procedure @ MAC layer // nr_ra_failed(module_idP, CC_id, prach_resources, frameP, slot); // prach_resources is a PHY structure ra->ra_state = nrRA_UE_IDLE; - ra->RA_active = 0; + ra->RA_active = false; } } break; @@ -3978,7 +4001,8 @@ static void nr_ue_process_rar(NR_UE_MAC_INST_t *mac, nr_downlink_indication_t *d if (!ra->cfra) { ra->t_crnti = rar->TCRNTI_2 + (rar->TCRNTI_1 << 8); rnti = ra->t_crnti; - nr_mac_rrc_msg3_ind(mac->ue_id, rnti, dl_info->gNB_index); + if (!ra->msg3_C_RNTI) + nr_mac_rrc_msg3_ind(mac->ue_id, rnti, dl_info->gNB_index); } fapi_nr_ul_config_request_pdu_t *pdu = lockGet_ul_config(mac, frame_tx, slot_tx, FAPI_NR_UL_CONFIG_TYPE_PUSCH); if (!pdu) diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c index 8c9062d8ec..d04fe1a295 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c @@ -60,6 +60,17 @@ static void nr_ue_prach_scheduler(NR_UE_MAC_INST_t *mac, frame_t frameP, sub_frame_t slotP); static void schedule_ta_command(fapi_nr_dl_config_request_t *dl_config, NR_UL_TIME_ALIGNMENT_t *ul_time_alignment); +void clear_ul_config_request(NR_UE_MAC_INST_t *mac, int scs) +{ + int slots = nr_slots_per_frame[scs]; + for (int i = 0; i < slots ; i++) { + fapi_nr_ul_config_request_t *ul_config = mac->ul_config_request + i; + pthread_mutex_lock(&ul_config->mutex_ul_config); + ul_config->number_pdus = 0; + pthread_mutex_unlock(&ul_config->mutex_ul_config); + } +} + fapi_nr_ul_config_request_pdu_t *lockGet_ul_config(NR_UE_MAC_INST_t *mac, frame_t frame_tx, int slot_tx, uint8_t pdu_type) { NR_TDD_UL_DL_ConfigCommon_t *tdd_config = mac->tdd_UL_DL_ConfigurationCommon; @@ -689,7 +700,7 @@ int nr_config_pusch_pdu(NR_UE_MAC_INST_t *mac, pusch_config_pdu->dfts_ofdm.low_papr_group_number); } else { - if (pusch_config_pdu->scid == 0 && NR_DMRS_ulconfig && + if (pusch_config_pdu->scid == 0 && NR_DMRS_ulconfig && NR_DMRS_ulconfig->transformPrecodingDisabled && NR_DMRS_ulconfig->transformPrecodingDisabled->scramblingID0) pusch_config_pdu->ul_dmrs_scrambling_id = *NR_DMRS_ulconfig->transformPrecodingDisabled->scramblingID0; if (pusch_config_pdu->scid == 1 && NR_DMRS_ulconfig && @@ -1111,6 +1122,19 @@ void nr_ue_dl_scheduler(NR_UE_MAC_INST_t *mac, nr_downlink_indication_t *dl_info LOG_E(NR_MAC, "Internal error, no scheduled_response function\n"); } +static bool check_pucchres_for_pending_SR(NR_PUCCH_Config_t *pucch_Config, int target_sr_id) +{ + for (int id = 0; id < pucch_Config->schedulingRequestResourceToAddModList->list.count; id++) { + NR_SchedulingRequestResourceConfig_t *sr_Config = pucch_Config->schedulingRequestResourceToAddModList->list.array[id]; + if (sr_Config->schedulingRequestID == target_sr_id) { + if (sr_Config->resource) { + return true; + } + } + } + return false; +} + static void nr_update_sr(NR_UE_MAC_INST_t *mac) { NR_UE_SCHEDULING_INFO *sched_info = &mac->scheduling_info; @@ -1153,17 +1177,27 @@ static void nr_update_sr(NR_UE_MAC_INST_t *mac) // if the UL-SCH resources available for a new transmission do not meet the LCP mapping restrictions // TODO not implemented - // trigger SR if (lc_info->sr_id < 0 || lc_info->sr_id >= NR_MAX_SR_ID) LOG_E(NR_MAC, "No SR corresponding to this LCID\n"); // TODO not sure what to do here else { nr_sr_info_t *sr = &sched_info->sr_info[lc_info->sr_id]; if (!sr->pending) { - LOG_D(NR_MAC, "Triggering SR for ID %d\n", lc_info->sr_id); - sr->pending = true; - sr->counter = 0; - // TODO initiate a Random Access procedure on the SpCell and cancel the pending SR - // if the MAC entity has no valid PUCCH resource configured for the pending SR + NR_UE_UL_BWP_t *current_UL_BWP = mac->current_UL_BWP; + NR_PUCCH_Config_t *pucch_Config = current_UL_BWP ? current_UL_BWP->pucch_Config : NULL; + if (check_pucchres_for_pending_SR(pucch_Config, lc_info->sr_id)) { + // trigger SR + LOG_D(NR_MAC, "Triggering SR for ID %d\n", lc_info->sr_id); + sr->pending = true; + sr->counter = 0; + } + else { + // initiate a Random Access procedure on the SpCell and cancel the pending SR + // if the MAC entity has no valid PUCCH resource configured for the pending SR + sr->pending = false; + sr->counter = 0; + nr_timer_stop(&sr->prohibitTimer); + schedule_RA_after_SR_failure(mac); + } } } } diff --git a/openair2/LAYER2/NR_MAC_gNB/config.c b/openair2/LAYER2/NR_MAC_gNB/config.c index 17fb37edba..5d3985b2d3 100644 --- a/openair2/LAYER2/NR_MAC_gNB/config.c +++ b/openair2/LAYER2/NR_MAC_gNB/config.c @@ -340,11 +340,9 @@ static void config_common(gNB_MAC_INST *nrmac, nr_pdsch_AntennaPorts_t pdsch_Ant // Carrier configuration struct NR_FrequencyInfoDL *frequencyInfoDL = scc->downlinkConfigCommon->frequencyInfoDL; - int bw_index = get_supported_band_index(frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing, - *frequencyInfoDL->frequencyBandList.list.array[0] > 256 ? FR2 : FR1, - frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->carrierBandwidth); - cfg->carrier_config.dl_bandwidth.value = - get_supported_bw_mhz(*frequencyInfoDL->frequencyBandList.list.array[0] > 256 ? FR2 : FR1, bw_index); + cfg->carrier_config.dl_bandwidth.value = get_supported_bw_mhz(*frequencyInfoDL->frequencyBandList.list.array[0] > 256 ? FR2 : FR1, + frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing, + frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->carrierBandwidth); cfg->carrier_config.dl_bandwidth.tl.tag = NFAPI_NR_CONFIG_DL_BANDWIDTH_TAG; // temporary cfg->num_tlv++; LOG_I(NR_MAC, "DL_Bandwidth:%d\n", cfg->carrier_config.dl_bandwidth.value); @@ -370,11 +368,9 @@ static void config_common(gNB_MAC_INST *nrmac, nr_pdsch_AntennaPorts_t pdsch_Ant } } struct NR_FrequencyInfoUL *frequencyInfoUL = scc->uplinkConfigCommon->frequencyInfoUL; - bw_index = get_supported_band_index(frequencyInfoUL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing, - *frequencyInfoUL->frequencyBandList->list.array[0] > 256 ? FR2 : FR1, - frequencyInfoUL->scs_SpecificCarrierList.list.array[0]->carrierBandwidth); - cfg->carrier_config.uplink_bandwidth.value = - get_supported_bw_mhz(*frequencyInfoUL->frequencyBandList->list.array[0] > 256 ? FR2 : FR1, bw_index); + cfg->carrier_config.uplink_bandwidth.value = get_supported_bw_mhz(*frequencyInfoUL->frequencyBandList->list.array[0] > 256 ? FR2 : FR1, + frequencyInfoUL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing, + frequencyInfoUL->scs_SpecificCarrierList.list.array[0]->carrierBandwidth); cfg->carrier_config.uplink_bandwidth.tl.tag = NFAPI_NR_CONFIG_UPLINK_BANDWIDTH_TAG; // temporary cfg->num_tlv++; LOG_I(NR_MAC, "DL_Bandwidth:%d\n", cfg->carrier_config.uplink_bandwidth.value); diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c index e617184edd..422ae13d89 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c @@ -132,9 +132,14 @@ int nr_write_ce_dlsch_pdu(module_id_t module_idP, // contention resolution identity MAC ce has a fixed 48 bit size // this contains the UL CCCH SDU. If UL CCCH SDU is longer than 48 bits, // it contains the first 48 bits of the UL CCCH SDU - LOG_T(NR_MAC, "[gNB ][RAPROC] Generate contention resolution msg: %x.%x.%x.%x.%x.%x\n", - ue_cont_res_id[0], ue_cont_res_id[1], ue_cont_res_id[2], - ue_cont_res_id[3], ue_cont_res_id[4], ue_cont_res_id[5]); + LOG_D(NR_MAC, + "[gNB ][RAPROC] Generate contention resolution msg: %x.%x.%x.%x.%x.%x\n", + ue_cont_res_id[0], + ue_cont_res_id[1], + ue_cont_res_id[2], + ue_cont_res_id[3], + ue_cont_res_id[4], + ue_cont_res_id[5]); // Copying bytes (6 octects) to CEs pointer mac_ce_size = 6; memcpy(ce_ptr, ue_cont_res_id, mac_ce_size); diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c index 2f1a05370e..5b99631d73 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c +++ b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c @@ -687,6 +687,12 @@ void dl_rrc_message_transfer(const f1ap_dl_rrc_message_t *dl_rrc) nr_mac_enable_ue_rrc_processing_timer(mac, UE, /* apply_cellGroup = */ true); NR_SCHED_UNLOCK(&mac->sched_lock); UE->expect_reconfiguration = false; + /* Re-establish RLC for all remaining bearers */ + if (UE->reestablish_rlc) { + for (int i = 1; i < UE->UE_sched_ctrl.dl_lc_num; ++i) + nr_rlc_reestablish_entity(dl_rrc->gNB_DU_ue_id, UE->UE_sched_ctrl.dl_lc_ids[i]); + UE->reestablish_rlc = false; + } } if (dl_rrc->old_gNB_DU_ue_id != NULL) { @@ -716,6 +722,11 @@ void dl_rrc_message_transfer(const f1ap_dl_rrc_message_t *dl_rrc) pthread_mutex_unlock(&mac->sched_lock); nr_rlc_remove_ue(dl_rrc->gNB_DU_ue_id); nr_rlc_update_id(*dl_rrc->old_gNB_DU_ue_id, dl_rrc->gNB_DU_ue_id); + /* Set flag to trigger RLC re-establishment + * for remaining RBs in next RRCReconfiguration */ + UE->reestablish_rlc = true; + /* 38.331 clause 5.3.7.4: apply the specified configuration defined in 9.2.1 for SRB1 */ + nr_rlc_reconfigure_entity(dl_rrc->gNB_DU_ue_id, 1, NULL); instance_t f1inst = get_f1_gtp_instance(); if (f1inst >= 0) // we actually use F1-U gtpv1u_update_ue_id(f1inst, *dl_rrc->old_gNB_DU_ue_id, dl_rrc->gNB_DU_ue_id); diff --git a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h index 398372e85b..02b5f54a56 100644 --- a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h +++ b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h @@ -683,6 +683,8 @@ typedef struct { NR_CellGroupConfig_t *CellGroup; /// CellGroupConfig that is to be activated after the next reconfiguration bool expect_reconfiguration; + /// reestablishRLC has to be signaled in RRCreconfiguration + bool reestablish_rlc; NR_CellGroupConfig_t *reconfigCellGroup; bool apply_cellgroup; NR_UE_NR_Capability_t *capability; diff --git a/openair2/LAYER2/PDCP_v10.1.0/pdcp.c b/openair2/LAYER2/PDCP_v10.1.0/pdcp.c index 99081a5ffc..28cd37f3af 100644 --- a/openair2/LAYER2/PDCP_v10.1.0/pdcp.c +++ b/openair2/LAYER2/PDCP_v10.1.0/pdcp.c @@ -2124,9 +2124,12 @@ pdcp_config_set_security( pdcp_pP->cipheringAlgorithm, pdcp_pP->integrityProtAlgorithm); - kRRCenc != NULL ? memcpy(pdcp_pP->kRRCenc, kRRCenc, 32) : memset(pdcp_pP->kRRCenc, 0, 32); - kRRCint != NULL ? memcpy(pdcp_pP->kRRCint, kRRCint, 32) : memset(pdcp_pP->kRRCint, 0, 32); - kUPenc != NULL ? memcpy(pdcp_pP->kUPenc, kUPenc, 32) : memset(pdcp_pP->kUPenc, 0, 32); + kRRCenc != NULL ? memcpy(pdcp_pP->kRRCenc, kRRCenc+16, 16) : memset(pdcp_pP->kRRCenc, 0, 16); + kRRCint != NULL ? memcpy(pdcp_pP->kRRCint, kRRCint+16, 16) : memset(pdcp_pP->kRRCint, 0, 16); + kUPenc != NULL ? memcpy(pdcp_pP->kUPenc, kUPenc+16, 16) : memset(pdcp_pP->kUPenc, 0, 16); + + pdcp_pP->security_container_rrc = stream_security_container_init(pdcp_pP->cipheringAlgorithm, pdcp_pP->integrityProtAlgorithm, pdcp_pP->kRRCenc, pdcp_pP->kRRCint); + pdcp_pP->security_container_up = stream_security_container_init(pdcp_pP->cipheringAlgorithm, 0, pdcp_pP->kUPenc, NULL); /* Activate security */ pdcp_pP->security_activated = 1; @@ -2196,6 +2199,8 @@ void rrc_pdcp_config_req ( pdcp_p->last_submitted_pdcp_rx_sn = 4095; pdcp_p->seq_num_size = 0; pdcp_p->first_missing_pdu = -1; + stream_security_container_delete(pdcp_p->security_container_rrc); + stream_security_container_delete(pdcp_p->security_container_up); pdcp_p->security_activated = 0; h_rc = hashtable_remove(pdcp_coll_p, key); break; diff --git a/openair2/LAYER2/PDCP_v10.1.0/pdcp.h b/openair2/LAYER2/PDCP_v10.1.0/pdcp.h index 6b0e2499fe..4a7f71b315 100644 --- a/openair2/LAYER2/PDCP_v10.1.0/pdcp.h +++ b/openair2/LAYER2/PDCP_v10.1.0/pdcp.h @@ -181,9 +181,12 @@ typedef struct pdcp_s { * Control-Plane RRC integrity key * These keys are configured by RRC layer */ - uint8_t kUPenc[32]; - uint8_t kRRCint[32]; - uint8_t kRRCenc[32]; + uint8_t kUPenc[16]; + uint8_t kRRCint[16]; + uint8_t kRRCenc[16]; + + stream_security_container_t *security_container_rrc; + stream_security_container_t *security_container_up; uint8_t security_activated; diff --git a/openair2/LAYER2/PDCP_v10.1.0/pdcp_security.c b/openair2/LAYER2/PDCP_v10.1.0/pdcp_security.c index a88d4028ae..e969467231 100644 --- a/openair2/LAYER2/PDCP_v10.1.0/pdcp_security.c +++ b/openair2/LAYER2/PDCP_v10.1.0/pdcp_security.c @@ -112,6 +112,7 @@ pdcp_apply_security( { uint8_t *buffer_encrypted = NULL; nas_stream_cipher_t encrypt_params = {0}; + stream_security_container_t *container; DevAssert(pdcp_pP != NULL); DevAssert(pdcp_pdu_buffer != NULL); @@ -122,7 +123,11 @@ pdcp_apply_security( encrypt_params.direction = (pdcp_pP->is_ue == 1) ? SECU_DIRECTION_UPLINK : SECU_DIRECTION_DOWNLINK; encrypt_params.bearer = rb_id - 1; encrypt_params.count = pdcp_get_next_count_tx(pdcp_pP, srb_flagP, current_sn); - encrypt_params.key_length = 16; + + if (srb_flagP) + container = pdcp_pP->security_container_rrc; + else + container = pdcp_pP->security_container_up; if (srb_flagP) { /* SRBs */ @@ -133,7 +138,7 @@ pdcp_apply_security( encrypt_params.message = pdcp_pdu_buffer; encrypt_params.blength = (pdcp_header_len + sdu_buffer_size) << 3; - encrypt_params.key = pdcp_pP->kRRCint + 16; // + 128; + encrypt_params.context = container->integrity_context; mac_i = &pdcp_pdu_buffer[pdcp_header_len + sdu_buffer_size]; @@ -142,15 +147,13 @@ pdcp_apply_security( stream_compute_integrity(pdcp_pP->integrityProtAlgorithm, &encrypt_params, mac_i); - - encrypt_params.key = pdcp_pP->kRRCenc; // + 128 // bit key } else { LOG_D(PDCP, "[OSA][RB %ld] %s Applying user-plane security\n", rb_id, (pdcp_pP->is_ue != 0) ? "UE -> eNB" : "eNB -> UE"); - - encrypt_params.key = pdcp_pP->kUPenc;// + 128; } + encrypt_params.context = container->ciphering_context; + encrypt_params.message = &pdcp_pdu_buffer[pdcp_header_len]; encrypt_params.blength = sdu_buffer_size << 3; @@ -180,6 +183,7 @@ pdcp_validate_security( { uint8_t *buffer_decrypted = NULL; nas_stream_cipher_t decrypt_params = {0}; + stream_security_container_t *container; DevAssert(pdcp_pP != NULL); @@ -195,17 +199,17 @@ pdcp_validate_security( decrypt_params.count = pdcp_get_next_count_rx(pdcp_pP, srb_flagP, hfn, sn); decrypt_params.message = &pdcp_pdu_buffer[pdcp_header_len]; decrypt_params.blength = (sdu_buffer_size - pdcp_header_len) << 3; - decrypt_params.key_length = 16; if (srb_flagP) { LOG_D(PDCP, "[OSA][RB %ld] %s Validating control-plane security\n", rb_id, (pdcp_pP->is_ue != 0) ? "eNB -> UE" : "UE -> eNB"); - decrypt_params.key = pdcp_pP->kRRCenc;// + 128; + container = pdcp_pP->security_container_rrc; } else { LOG_D(PDCP, "[OSA][RB %ld] %s Validating user-plane security\n", rb_id, (pdcp_pP->is_ue != 0) ? "eNB -> UE" : "UE -> eNB"); - decrypt_params.key = pdcp_pP->kUPenc;// + 128; + container = pdcp_pP->security_container_up; } /* Uncipher the block */ + decrypt_params.context = container->ciphering_context; stream_compute_encrypt(pdcp_pP->cipheringAlgorithm, &decrypt_params, buffer_decrypted); if (!IS_SOFTMODEM_IQPLAYER) { @@ -213,7 +217,7 @@ pdcp_validate_security( /* Now check the integrity of the complete PDU */ decrypt_params.message = pdcp_pdu_buffer; decrypt_params.blength = sdu_buffer_size << 3; - decrypt_params.key = pdcp_pP->kRRCint + 16;// 128; + decrypt_params.context = container->integrity_context; if (pdcp_pP->integrityProtAlgorithm != EIA0_ALG_ID) { uint8_t result[4] = {0}; @@ -221,10 +225,9 @@ pdcp_validate_security( if (memcmp(result, &pdcp_pdu_buffer[sdu_buffer_size], 4) != 0) { LOG_E(PDCP, - "[OSA][RB %ld] %s failed to validate MAC-I (key %llx) of incoming PDU\n", + "[OSA][RB %ld] %s failed to validate MAC-I of incoming PDU\n", rb_id, - (pdcp_pP->is_ue != 0) ? "UE" : "eNB", - ((long long unsigned int *)decrypt_params.key)[0]); + (pdcp_pP->is_ue != 0) ? "UE" : "eNB"); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_VALIDATE_SECURITY, VCD_FUNCTION_OUT); return -1; } diff --git a/openair2/LAYER2/nr_pdcp/cucp_cuup_handler.c b/openair2/LAYER2/nr_pdcp/cucp_cuup_handler.c index cc10a9d7c3..2f7f4afa59 100644 --- a/openair2/LAYER2/nr_pdcp/cucp_cuup_handler.c +++ b/openair2/LAYER2/nr_pdcp/cucp_cuup_handler.c @@ -261,10 +261,12 @@ void e1_bearer_context_modif(const e1ap_bearer_mod_req_t *req) if (f1inst < 0) // no F1-U? continue; // nothing to do - in_addr_t addr = {0}; - memcpy(&addr, &to_modif->DlUpParamList[0].tlAddress, sizeof(in_addr_t)); - - GtpuUpdateTunnelOutgoingAddressAndTeid(f1inst, req->gNB_cu_cp_ue_id, to_modif->id, addr, to_modif->DlUpParamList[0].teId); + /* Loop through DL UP Transport Layer params list + * and update GTP tunnel outgoing addr and TEID */ + for (int k = 0; k < to_modif->numDlUpParam; k++) { + in_addr_t addr = to_modif->DlUpParamList[k].tlAddress; + GtpuUpdateTunnelOutgoingAddressAndTeid(f1inst, req->gNB_cu_cp_ue_id, to_modif->id, addr, to_modif->DlUpParamList[k].teId); + } } } diff --git a/openair2/LAYER2/nr_pdcp/nr_pdcp_entity.c b/openair2/LAYER2/nr_pdcp/nr_pdcp_entity.c index 98162d003c..712bbf6b0c 100644 --- a/openair2/LAYER2/nr_pdcp/nr_pdcp_entity.c +++ b/openair2/LAYER2/nr_pdcp/nr_pdcp_entity.c @@ -57,7 +57,10 @@ static void nr_pdcp_entity_recv_pdu(nr_pdcp_entity_t *entity, uint32_t rx_deliv_hfn; if (entity->entity_suspended) { - LOG_W(PDCP, "PDCP entity %d is suspended. Quit RX procedure.\n", entity->rb_id); + LOG_W(PDCP, + "PDCP entity (%s) %d is suspended. Quit RX procedure.\n", + entity->type > NR_PDCP_DRB_UM ? "SRB" : "DRB", + entity->rb_id); return; } @@ -190,6 +193,13 @@ static void nr_pdcp_entity_recv_pdu(nr_pdcp_entity_t *entity, count++; } entity->rx_deliv = count; + LOG_D(PDCP, + "%s: entity (%s) %d - rx_deliv = %d, rcvd_sn = %d \n", + __func__, + entity->type == NR_PDCP_DRB_AM ? "DRB" : "SRB", + entity->rb_id, + entity->rx_deliv, + rcvd_sn); } if (entity->t_reordering_start != 0 && entity->rx_deliv >= entity->rx_reord) { @@ -220,7 +230,10 @@ static int nr_pdcp_entity_process_sdu(nr_pdcp_entity_t *entity, int dc_bit; if (entity->entity_suspended) { - LOG_W(PDCP, "PDCP entity %d is suspended. Quit SDU processing.\n", entity->rb_id); + LOG_W(PDCP, + "PDCP entity (%s) %d is suspended. Quit SDU processing.\n", + entity->type > NR_PDCP_DRB_UM ? "SRB" : "DRB", + entity->rb_id); return -1; } @@ -387,6 +400,14 @@ static void check_t_reordering(nr_pdcp_entity_t *entity) if (entity->t_reordering_start == 0 || entity->t_current <= entity->t_reordering_start + entity->t_reordering) return; + LOG_D(PDCP, + "%s: entity (%s) %d: t_reordering_start = %ld, t_current = %ld, t_reordering = %d \n", + __func__, + entity->type > NR_PDCP_DRB_UM ? "SRB" : "DRB", + entity->rb_id, + entity->t_reordering_start, + entity->t_current, + entity->t_reordering); /* stop timer */ entity->t_reordering_start = 0; @@ -450,15 +471,29 @@ static void deliver_all_sdus(nr_pdcp_entity_t *entity) } } +/** + * @brief PDCP Entity Suspend according to 5.1.4 of 3GPP TS 38.323 + * Transmitting PDCP entity shall: + * - set TX_NEXT to the initial value; + * - discard all stored PDCP PDUs (NOTE: PDUs are stored in RLC) + * Receiving PDCP entity shall: + * - if t-Reordering is running: + * a) stop and reset t-Reordering; + * b) deliver all stored PDCP SDUs + * - set RX_NEXT and RX_DELIV to the initial value. + */ static void nr_pdcp_entity_suspend(nr_pdcp_entity_t *entity) { + /* Transmitting PDCP entity */ entity->tx_next = 0; + /* Receiving PDCP entity */ if (entity->t_reordering_start != 0) { entity->t_reordering_start = 0; deliver_all_sdus(entity); } entity->rx_next = 0; entity->rx_deliv = 0; + /* Flag to keep track of PDCP entity status */ entity->entity_suspended = true; } diff --git a/openair2/LAYER2/nr_pdcp/nr_pdcp_entity.h b/openair2/LAYER2/nr_pdcp/nr_pdcp_entity.h index 5d2fd56f70..d26ce83b82 100644 --- a/openair2/LAYER2/nr_pdcp/nr_pdcp_entity.h +++ b/openair2/LAYER2/nr_pdcp/nr_pdcp_entity.h @@ -28,6 +28,7 @@ #include "nr_pdcp_sdu.h" #include "openair2/RRC/NR/rrc_gNB_radio_bearers.h" +#include "openair3/SECU/secu_defs.h" /* PDCP Formats according to clause 6.2 of 3GPP TS 38.323 */ /* SN Size applicable to SRBs, UM DRBs and AM DRBs */ @@ -151,16 +152,17 @@ typedef struct nr_pdcp_entity_t { int integrity_algorithm; unsigned char ciphering_key[16]; unsigned char integrity_key[16]; - void *security_context; - void (*cipher)(void *security_context, + stream_security_context_t *security_context; + void (*cipher)(stream_security_context_t *security_context, unsigned char *buffer, int length, int bearer, int count, int direction); - void (*free_security)(void *security_context); - void *integrity_context; - void (*integrity)(void *integrity_context, unsigned char *out, + void (*free_security)(stream_security_context_t *security_context); + stream_security_context_t *integrity_context; + void (*integrity)(stream_security_context_t *integrity_context, + unsigned char *out, unsigned char *buffer, int length, int bearer, int count, int direction); - void (*free_integrity)(void *integrity_context); + void (*free_integrity)(stream_security_context_t *integrity_context); /* security/integrity algorithms need to know uplink/downlink information * which is reverse for gnb and ue, so we need to know if this * pdcp entity is for a gnb or an ue diff --git a/openair2/LAYER2/nr_pdcp/nr_pdcp_integrity_nia1.c b/openair2/LAYER2/nr_pdcp/nr_pdcp_integrity_nia1.c index 3dbf15136b..d21c98610e 100644 --- a/openair2/LAYER2/nr_pdcp/nr_pdcp_integrity_nia1.c +++ b/openair2/LAYER2/nr_pdcp/nr_pdcp_integrity_nia1.c @@ -28,24 +28,23 @@ #include "openair3/SECU/secu_defs.h" #include "openair3/SECU/key_nas_deriver.h" -void *nr_pdcp_integrity_nia1_init(unsigned char *integrity_key) +stream_security_context_t *nr_pdcp_integrity_nia1_init(unsigned char *integrity_key) { nas_stream_cipher_t *ret; ret = calloc(1, sizeof(*ret)); if (ret == NULL) abort(); - ret->key = malloc(16); if (ret->key == NULL) abort(); - memcpy(ret->key, integrity_key, 16); - ret->key_length = 16; /* unused */ + ret->context = malloc(16); if (ret->context == NULL) abort(); + memcpy(ret->context, integrity_key, 16); - return ret; + return (stream_security_context_t *)ret; } -void nr_pdcp_integrity_nia1_integrity(void *integrity_context, +void nr_pdcp_integrity_nia1_integrity(stream_security_context_t *integrity_context, unsigned char *out, unsigned char *buffer, int length, int bearer, int count, int direction) { - nas_stream_cipher_t *ctx = integrity_context; + nas_stream_cipher_t *ctx = (nas_stream_cipher_t *)integrity_context; ctx->message = buffer; ctx->count = count; @@ -56,9 +55,9 @@ void nr_pdcp_integrity_nia1_integrity(void *integrity_context, stream_compute_integrity(EIA1_128_ALG_ID, ctx, out); } -void nr_pdcp_integrity_nia1_free_integrity(void *integrity_context) +void nr_pdcp_integrity_nia1_free_integrity(stream_security_context_t *integrity_context) { - nas_stream_cipher_t *ctx = integrity_context; - free(ctx->key); + nas_stream_cipher_t *ctx = (nas_stream_cipher_t *)integrity_context; + free(ctx->context); free(ctx); } diff --git a/openair2/LAYER2/nr_pdcp/nr_pdcp_integrity_nia1.h b/openair2/LAYER2/nr_pdcp/nr_pdcp_integrity_nia1.h index 5c44bad4a7..89f6d9156a 100644 --- a/openair2/LAYER2/nr_pdcp/nr_pdcp_integrity_nia1.h +++ b/openair2/LAYER2/nr_pdcp/nr_pdcp_integrity_nia1.h @@ -22,13 +22,15 @@ #ifndef _NR_PDCP_INTEGRITY_NIA1_H_ #define _NR_PDCP_INTEGRITY_NIA1_H_ -void *nr_pdcp_integrity_nia1_init(unsigned char *integrity_key); +#include "openair3/SECU/secu_defs.h" -void nr_pdcp_integrity_nia1_integrity(void *integrity_context, +stream_security_context_t *nr_pdcp_integrity_nia1_init(unsigned char *integrity_key); + +void nr_pdcp_integrity_nia1_integrity(stream_security_context_t *integrity_context, unsigned char *out, unsigned char *buffer, int length, int bearer, int count, int direction); -void nr_pdcp_integrity_nia1_free_integrity(void *integrity_context); +void nr_pdcp_integrity_nia1_free_integrity(stream_security_context_t *integrity_context); #endif /* _NR_PDCP_INTEGRITY_NIA1_H_ */ diff --git a/openair2/LAYER2/nr_pdcp/nr_pdcp_integrity_nia2.c b/openair2/LAYER2/nr_pdcp/nr_pdcp_integrity_nia2.c index 497ed154d5..f6db1b10a6 100644 --- a/openair2/LAYER2/nr_pdcp/nr_pdcp_integrity_nia2.c +++ b/openair2/LAYER2/nr_pdcp/nr_pdcp_integrity_nia2.c @@ -30,29 +30,25 @@ #include "openair3/SECU/aes_128.h" #include "openair3/SECU/aes_128_cbc_cmac.h" -void *nr_pdcp_integrity_nia2_init(uint8_t integrity_key[16]) +stream_security_context_t *nr_pdcp_integrity_nia2_init(uint8_t integrity_key[16]) { - // This is a hack. Reduce the 3 functions to just cipher? - // No. The overhead is x8 times more. Don't change before measuring - // return integrity_key; cbc_cmac_ctx_t* ctx = calloc(1, sizeof(cbc_cmac_ctx_t)); AssertFatal(ctx, "Memory exhausted"); *ctx = init_aes_128_cbc_cmac(integrity_key); - return ctx; + return (stream_security_context_t *)ctx; } -void nr_pdcp_integrity_nia2_integrity(void *integrity_context, unsigned char *out, unsigned char *buffer, int length, int bearer, int count, int direction) +void nr_pdcp_integrity_nia2_integrity(stream_security_context_t *integrity_context, unsigned char *out, unsigned char *buffer, int length, int bearer, int count, int direction) { DevAssert(integrity_context != NULL); DevAssert(out != NULL); DevAssert(buffer != NULL); DevAssert(length > -1); - // Strange range: [1-32] instead of [0-31] DevAssert(bearer > 0 && bearer < 33); DevAssert(count > -1); - cbc_cmac_ctx_t* ctx = (cbc_cmac_ctx_t*)integrity_context; + cbc_cmac_ctx_t *ctx = (cbc_cmac_ctx_t *)integrity_context; aes_128_t k_iv = {0}; memcpy(&k_iv.key, ctx->key, sizeof(k_iv.key)); @@ -64,18 +60,13 @@ void nr_pdcp_integrity_nia2_integrity(void *integrity_context, unsigned char *ou uint8_t result[16] = {0}; byte_array_t msg = {.buf = buffer, .len = length}; - cipher_aes_128_cbc_cmac((cbc_cmac_ctx_t*)integrity_context, &k_iv, msg, sizeof(result), result); - //aes_128_cbc_cmac(&k_iv, msg, sizeof(result), result); + cipher_aes_128_cbc_cmac(ctx, &k_iv, msg, sizeof(result), result); - // AES CMAC (RFC 4493) outputs 128 bits but NR PDCP PDUs have a MAC-I of - // 32 bits (see 38.323 6.2). RFC 4493 2.1 says to truncate most significant - // bit first (so seems to say 33.401 B.2.3) - // Precondition: out should have enough space... memcpy(out, result, 4); } -void nr_pdcp_integrity_nia2_free_integrity(void *integrity_context) +void nr_pdcp_integrity_nia2_free_integrity(stream_security_context_t *integrity_context) { - free( ( cbc_cmac_ctx_t*) integrity_context); + free_aes_128_cbc_cmac((cbc_cmac_ctx_t *)integrity_context); + free(integrity_context); } - diff --git a/openair2/LAYER2/nr_pdcp/nr_pdcp_integrity_nia2.h b/openair2/LAYER2/nr_pdcp/nr_pdcp_integrity_nia2.h index 53f117aafb..c9bd6cd881 100644 --- a/openair2/LAYER2/nr_pdcp/nr_pdcp_integrity_nia2.h +++ b/openair2/LAYER2/nr_pdcp/nr_pdcp_integrity_nia2.h @@ -24,13 +24,15 @@ #include -void *nr_pdcp_integrity_nia2_init(uint8_t integrity_key[16]); +#include "openair3/SECU/secu_defs.h" -void nr_pdcp_integrity_nia2_integrity(void *integrity_context, +stream_security_context_t *nr_pdcp_integrity_nia2_init(uint8_t integrity_key[16]); + +void nr_pdcp_integrity_nia2_integrity(stream_security_context_t *integrity_context, unsigned char *out, unsigned char *buffer, int length, int bearer, int count, int direction); -void nr_pdcp_integrity_nia2_free_integrity(void *integrity_context); +void nr_pdcp_integrity_nia2_free_integrity(stream_security_context_t *integrity_context); #endif /* _NR_PDCP_INTEGRITY_NIA2_H_ */ diff --git a/openair2/LAYER2/nr_pdcp/nr_pdcp_security_nea2.c b/openair2/LAYER2/nr_pdcp/nr_pdcp_security_nea2.c index e54b854125..617d5c3372 100644 --- a/openair2/LAYER2/nr_pdcp/nr_pdcp_security_nea2.c +++ b/openair2/LAYER2/nr_pdcp/nr_pdcp_security_nea2.c @@ -29,14 +29,14 @@ #include #include -void *nr_pdcp_security_nea2_init(unsigned char *ciphering_key) +stream_security_context_t *nr_pdcp_security_nea2_init(unsigned char *ciphering_key) { // This is a hack, IMO init, cipher and free functions should be reduced to cipher. // Test show a ~10% more processing time - return ciphering_key; + return (stream_security_context_t *)ciphering_key; } -void nr_pdcp_security_nea2_cipher(void *security_context, unsigned char *buffer, int length, int bearer, int count, int direction) +void nr_pdcp_security_nea2_cipher(stream_security_context_t *security_context, unsigned char *buffer, int length, int bearer, int count, int direction) { DevAssert(security_context != NULL); DevAssert(buffer != NULL); @@ -62,7 +62,7 @@ void nr_pdcp_security_nea2_cipher(void *security_context, unsigned char *buffer, memcpy(buffer, out, length); } -void nr_pdcp_security_nea2_free_security(void *security_context) +void nr_pdcp_security_nea2_free_security(stream_security_context_t *security_context) { (void)security_context; } diff --git a/openair2/LAYER2/nr_pdcp/nr_pdcp_security_nea2.h b/openair2/LAYER2/nr_pdcp/nr_pdcp_security_nea2.h index c3667c93d4..4550e7290d 100644 --- a/openair2/LAYER2/nr_pdcp/nr_pdcp_security_nea2.h +++ b/openair2/LAYER2/nr_pdcp/nr_pdcp_security_nea2.h @@ -22,12 +22,14 @@ #ifndef _NR_PDCP_SECURITY_NEA2_H_ #define _NR_PDCP_SECURITY_NEA2_H_ -void *nr_pdcp_security_nea2_init(unsigned char *ciphering_key); +#include "openair3/SECU/secu_defs.h" -void nr_pdcp_security_nea2_cipher(void *security_context, +stream_security_context_t *nr_pdcp_security_nea2_init(unsigned char *ciphering_key); + +void nr_pdcp_security_nea2_cipher(stream_security_context_t *security_context, unsigned char *buffer, int length, int bearer, int count, int direction); -void nr_pdcp_security_nea2_free_security(void *security_context); +void nr_pdcp_security_nea2_free_security(stream_security_context_t *security_context); #endif /* _NR_PDCP_SECURITY_NEA2_H_ */ diff --git a/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.c b/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.c index 55d245dd38..5178ebc1d9 100644 --- a/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.c +++ b/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.c @@ -650,7 +650,7 @@ void nr_rlc_reestablish_entity(int ue_id, int lc_id) nr_rlc_entity_t *rb = get_rlc_entity_from_lcid(ue, lc_id); if (rb != NULL) { - LOG_D(RLC, "RB found! (channel ID %d) \n", lc_id); + LOG_D(RLC, "RB found! (channel ID %d), re-establish RLC\n", lc_id); rb->reestablishment(rb); } else { LOG_E(RLC, "no RLC entity found (channel ID %d) for reestablishment\n", lc_id); @@ -1065,12 +1065,11 @@ bool nr_rlc_update_id(int from_id, int to_id) } ue->ue_id = to_id; LOG_I(RLC, "Update old UE ID %d context to ID %d\n", from_id, to_id); - for (int i = 0; i < sizeof(ue->srb) / sizeof(ue->srb[0]); ++i) - if (ue->srb[i]) - ue->srb[i]->reestablishment(ue->srb[i]); - for (int i = 0; i < sizeof(ue->drb) / sizeof(ue->drb[0]); ++i) - if (ue->drb[i]) - ue->drb[i]->reestablishment(ue->drb[i]); + /* re-establish RLC for SRB1: according to 5.3.7.4 of TS 38.331 */ + if (ue->srb[0]) { + LOG_I(RLC, "Re-establish RLC for SRB 1\n"); + ue->srb[0]->reestablishment(ue->srb[0]); + } nr_rlc_manager_unlock(nr_rlc_ue_manager); return true; } diff --git a/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c b/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c index 38e57eda66..16f35f6c92 100644 --- a/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c +++ b/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c @@ -1059,8 +1059,18 @@ static int handle_bcch_dlsch(NR_UE_MAC_INST_t *mac, } // L2 Abstraction Layer -static nr_dci_format_t handle_dci(NR_UE_MAC_INST_t *mac, frame_t frame, int slot, fapi_nr_dci_indication_pdu_t *dci) +static nr_dci_format_t handle_dci(NR_UE_MAC_INST_t *mac, + unsigned int gNB_index, + frame_t frame, + int slot, + fapi_nr_dci_indication_pdu_t *dci) { + // if notification of a reception of a PDCCH transmission of the SpCell is received from lower layers + // if the C-RNTI MAC CE was included in Msg3 + // consider this Contention Resolution successful + if (mac->ra.msg3_C_RNTI && mac->ra.ra_state == nrRA_WAIT_CONTENTION_RESOLUTION) + nr_ra_succeeded(mac, gNB_index, frame, slot); + return nr_ue_process_dci_indication_pdu(mac, frame, slot, dci); } @@ -1156,7 +1166,11 @@ static uint32_t nr_ue_dl_processing(nr_downlink_indication_t *dl_info) LOG_T(MAC, "[L2][IF MODULE][DL INDICATION][DCI_IND]\n"); for (int i = 0; i < dl_info->dci_ind->number_of_dcis; i++) { LOG_T(MAC, ">>>NR_IF_Module i=%d, dl_info->dci_ind->number_of_dcis=%d\n", i, dl_info->dci_ind->number_of_dcis); - nr_dci_format_t dci_format = handle_dci(mac, dl_info->frame, dl_info->slot, dl_info->dci_ind->dci_list + i); + nr_dci_format_t dci_format = handle_dci(mac, + dl_info->gNB_index, + dl_info->frame, + dl_info->slot, + dl_info->dci_ind->dci_list + i); /* The check below filters out UL_DCIs which are being processed as DL_DCIs. */ if (dci_format != NR_DL_DCI_FORMAT_1_0 && dci_format != NR_DL_DCI_FORMAT_1_1) { diff --git a/openair2/RRC/NR/nr_rrc_config.c b/openair2/RRC/NR/nr_rrc_config.c index f631563044..b6a5d45ff9 100644 --- a/openair2/RRC/NR/nr_rrc_config.c +++ b/openair2/RRC/NR/nr_rrc_config.c @@ -526,18 +526,12 @@ void set_dl_maxmimolayers(NR_PDSCH_ServingCellConfig_t *pdsch_servingcellconfig, NR_FeatureSets_t *fs = uecap ? uecap->featureSets : NULL; if (fs) { - const int bw_index = get_supported_band_index(scs, freq_range, bw_size); - AssertFatal(bw_index >= 0, "BW corresponding to %d PRBs not found\n", bw_size); + const int bw_mhz = get_supported_bw_mhz(freq_range, scs, bw_size); // go through UL feature sets and look for one with current SCS for (int i = 0; i < fs->featureSetsDownlinkPerCC->list.count; i++) { NR_FeatureSetDownlinkPerCC_t *dl_fs = fs->featureSetsDownlinkPerCC->list.array[i]; - long supported_bw; - if (freq_range == FR1) - supported_bw = dl_fs->supportedBandwidthDL.choice.fr1; - else - supported_bw = dl_fs->supportedBandwidthDL.choice.fr2; if (scs == dl_fs->supportedSubcarrierSpacingDL && - bw_index == supported_bw && + supported_bw_comparison(bw_mhz, &dl_fs->supportedBandwidthDL, dl_fs->channelBW_90mhz) && dl_fs->maxNumberMIMO_LayersPDSCH) { long ue_supported_layers = (2 << *dl_fs->maxNumberMIMO_LayersPDSCH); *pdsch_servingcellconfig->ext1->maxMIMO_Layers = NR_MAX_SUPPORTED_DL_LAYERS < ue_supported_layers ? NR_MAX_SUPPORTED_DL_LAYERS : ue_supported_layers; @@ -776,38 +770,42 @@ void prepare_sim_uecap(NR_UE_NR_Capability_t *cap, int numerology, int rbsize, int mcs_table_dl, - int mcs_table_ul) { - + int mcs_table_ul) +{ NR_Phy_Parameters_t *phy_Parameters = &cap->phy_Parameters; int band = *scc->downlinkConfigCommon->frequencyInfoDL->frequencyBandList.list.array[0]; - NR_BandNR_t *nr_bandnr = CALLOC(1,sizeof(NR_BandNR_t)); + NR_BandNR_t *nr_bandnr = calloc(1, sizeof(NR_BandNR_t)); nr_bandnr->bandNR = band; asn1cSeqAdd(&cap->rf_Parameters.supportedBandListNR.list, nr_bandnr); NR_BandNR_t *bandNRinfo = cap->rf_Parameters.supportedBandListNR.list.array[0]; if (mcs_table_ul == 1) { - bandNRinfo->pusch_256QAM = CALLOC(1,sizeof(*bandNRinfo->pusch_256QAM)); + bandNRinfo->pusch_256QAM = calloc(1,sizeof(*bandNRinfo->pusch_256QAM)); *bandNRinfo->pusch_256QAM = NR_BandNR__pusch_256QAM_supported; } if (mcs_table_dl == 1) { const frequency_range_t freq_range = band < 257 ? FR1 : FR2; - int bw = get_supported_band_index(numerology, freq_range, rbsize); if (freq_range == FR2) { - bandNRinfo->pdsch_256QAM_FR2 = CALLOC(1,sizeof(*bandNRinfo->pdsch_256QAM_FR2)); + bandNRinfo->pdsch_256QAM_FR2 = calloc(1, sizeof(*bandNRinfo->pdsch_256QAM_FR2)); *bandNRinfo->pdsch_256QAM_FR2 = NR_BandNR__pdsch_256QAM_FR2_supported; } else{ - phy_Parameters->phy_ParametersFR1 = CALLOC(1,sizeof(*phy_Parameters->phy_ParametersFR1)); + phy_Parameters->phy_ParametersFR1 = calloc(1, sizeof(*phy_Parameters->phy_ParametersFR1)); NR_Phy_ParametersFR1_t *phy_fr1 = phy_Parameters->phy_ParametersFR1; - phy_fr1->pdsch_256QAM_FR1 = CALLOC(1,sizeof(*phy_fr1->pdsch_256QAM_FR1)); + phy_fr1->pdsch_256QAM_FR1 = calloc(1, sizeof(*phy_fr1->pdsch_256QAM_FR1)); *phy_fr1->pdsch_256QAM_FR1 = NR_Phy_ParametersFR1__pdsch_256QAM_FR1_supported; } - cap->featureSets = CALLOC(1,sizeof(*cap->featureSets)); + cap->featureSets = calloc(1, sizeof(*cap->featureSets)); NR_FeatureSets_t *fs=cap->featureSets; - fs->featureSetsDownlinkPerCC = CALLOC(1,sizeof(*fs->featureSetsDownlinkPerCC)); - NR_FeatureSetDownlinkPerCC_t *fs_cc = CALLOC(1,sizeof(NR_FeatureSetDownlinkPerCC_t)); + fs->featureSetsDownlinkPerCC = calloc(1, sizeof(*fs->featureSetsDownlinkPerCC)); + NR_FeatureSetDownlinkPerCC_t *fs_cc = calloc(1, sizeof(*fs_cc)); fs_cc->supportedSubcarrierSpacingDL = numerology; + int bw = get_supported_band_index(numerology, freq_range, rbsize); + if (bw == 10) // 90MHz + fs_cc->channelBW_90mhz = calloc(1, sizeof(*fs_cc->channelBW_90mhz)); + if (bw == 11) // 100MHz + bw--; if(freq_range == FR2) { fs_cc->supportedBandwidthDL.present = NR_SupportedBandwidth_PR_fr2; fs_cc->supportedBandwidthDL.choice.fr2 = bw; @@ -816,12 +814,12 @@ void prepare_sim_uecap(NR_UE_NR_Capability_t *cap, fs_cc->supportedBandwidthDL.present = NR_SupportedBandwidth_PR_fr1; fs_cc->supportedBandwidthDL.choice.fr1 = bw; } - fs_cc->supportedModulationOrderDL = CALLOC(1,sizeof(*fs_cc->supportedModulationOrderDL)); + fs_cc->supportedModulationOrderDL = calloc(1, sizeof(*fs_cc->supportedModulationOrderDL)); *fs_cc->supportedModulationOrderDL = NR_ModulationOrder_qam256; asn1cSeqAdd(&fs->featureSetsDownlinkPerCC->list, fs_cc); } - phy_Parameters->phy_ParametersFRX_Diff = CALLOC(1,sizeof(*phy_Parameters->phy_ParametersFRX_Diff)); + phy_Parameters->phy_ParametersFRX_Diff = calloc(1, sizeof(*phy_Parameters->phy_ParametersFRX_Diff)); phy_Parameters->phy_ParametersFRX_Diff->pucch_F0_2WithoutFH = NULL; } diff --git a/openair2/RRC/NR/rrc_gNB.c b/openair2/RRC/NR/rrc_gNB.c index 0d745fb798..d0d9735426 100644 --- a/openair2/RRC/NR/rrc_gNB.c +++ b/openair2/RRC/NR/rrc_gNB.c @@ -227,8 +227,7 @@ static int get_ssb_arfcn(const f1ap_served_cell_info_t *cell_info, const NR_MIB_ else AssertFatal(false, "Invalid absoluteFrequencyPointA: %u\n", dl_arfcn); - int bw_index = get_supported_band_index(scs, band > 256 ? FR2 : FR1, get_dl_bw(cell_info)); - int band_size_hz = get_supported_bw_mhz(band > 256 ? FR2 : FR1, bw_index) * 1000 * 1000; + int band_size_hz = get_supported_bw_mhz(band > 256 ? FR2 : FR1, scs, get_dl_bw(cell_info)) * 1000 * 1000; uint32_t ssb_arfcn = to_nrarfcn(band, freqssb, scs, band_size_hz); LOG_D(NR_RRC, @@ -370,6 +369,9 @@ unsigned int rrc_gNB_get_next_transaction_identifier(module_id_t gnb_mod_idP) return tmp; } +/** + * @brief Create srb-ToAddModList for RRCSetup and RRCReconfiguration messages +*/ static NR_SRB_ToAddModList_t *createSRBlist(gNB_RRC_UE_t *ue, bool reestablish) { if (!ue->Srb[1].Active) { @@ -381,6 +383,7 @@ static NR_SRB_ToAddModList_t *createSRBlist(gNB_RRC_UE_t *ue, bool reestablish) if (ue->Srb[i].Active) { asn1cSequenceAdd(list->list, NR_SRB_ToAddMod_t, srb); srb->srb_Identity = i; + /* Set reestablishPDCP only for SRB2 */ if (reestablish && i == 2) { asn1cCallocOne(srb->reestablishPDCP, NR_SRB_ToAddMod__reestablishPDCP_true); } @@ -1018,13 +1021,11 @@ static void rrc_gNB_generate_RRCReestablishment(rrc_gNB_ue_context_t *ue_context /* SRBs */ for (int srb_id = 1; srb_id < NR_NUM_SRB; srb_id++) { - if (ue_p->Srb[srb_id].Active) { + if (ue_p->Srb[srb_id].Active) nr_pdcp_config_set_security(ue_p->rrc_ue_id, srb_id, security_mode, kRRCenc, kRRCint, kUPenc); - nr_pdcp_reestablishment(ue_p->rrc_ue_id, srb_id, true); - } } - /* PDCP Reestablishment over E1 */ - cuup_notify_reestablishment(rrc, ue_p); + /* Re-establish PDCP for SRB1, according to 5.3.7.4 of 3GPP TS 38.331 */ + nr_pdcp_reestablishment(ue_p->rrc_ue_id, 1, true); /* F1AP DL RRC Message Transfer */ f1_ue_data_t ue_data = cu_get_f1_ue_data(ue_p->rrc_ue_id); RETURN_IF_INVALID_ASSOC_ID(ue_data); @@ -1075,12 +1076,28 @@ static void rrc_gNB_process_RRCReestablishmentComplete(const protocol_ctxt_t *co for (i = 1; i < ue_p->masterCellGroup->rlc_BearerToAddModList->list.count; ++i) asn1cSeqAdd(&cellGroupConfig->rlc_BearerToAddModList->list, ue_p->masterCellGroup->rlc_BearerToAddModList->list.array[i]); + /* + * At this stage, PDCP entity are re-established and reestablishRLC is flagged + * with RRCReconfiguration to complete RLC re-establishment of remaining bearers + */ for (i = 0; i < cellGroupConfig->rlc_BearerToAddModList->list.count; i++) { asn1cCallocOne(cellGroupConfig->rlc_BearerToAddModList->list.array[i]->reestablishRLC, NR_RLC_BearerConfig__reestablishRLC_true); } + /* Re-establish SRB2 according to clause 5.3.5.6.3 of 3GPP TS 38.331 + * (SRB1 is re-established with RRCReestablishment message) + */ + int srb_id = 2; + if (ue_p->Srb[srb_id].Active) { + nr_pdcp_reestablishment(ue_p->rrc_ue_id, srb_id, true); + } + /* PDCP Reestablishment of DRBs according to 5.3.5.6.5 of 3GPP TS 38.331 (over E1) */ + cuup_notify_reestablishment(rrc, ue_p); + + /* Create srb-ToAddModList */ NR_SRB_ToAddModList_t *SRBs = createSRBlist(ue_p, true); + /* Create drb-ToAddModList */ NR_DRB_ToAddModList_t *DRBs = createDRBlist(ue_p, true); uint8_t new_xid = rrc_gNB_get_next_transaction_identifier(ctxt_pP->module_id); diff --git a/openair2/RRC/NR_UE/rrc_UE.c b/openair2/RRC/NR_UE/rrc_UE.c index 6442594eef..d5379c1769 100644 --- a/openair2/RRC/NR_UE/rrc_UE.c +++ b/openair2/RRC/NR_UE/rrc_UE.c @@ -1623,15 +1623,14 @@ static int nr_rrc_ue_decode_dcch(NR_UE_RRC_INST_t *rrc, } break; case NR_DL_DCCH_MessageType__c1_PR_rrcResume: - LOG_I(NR_RRC, "Received rrcResume on DL-DCCH-Message\n"); + LOG_E(NR_RRC, "Received rrcResume on DL-DCCH-Message -> Not handled\n"); break; case NR_DL_DCCH_MessageType__c1_PR_rrcRelease: LOG_I(NR_RRC, "[UE %ld] Received RRC Release (gNB %d)\n", rrc->ue_id, gNB_indexP); - // TODO properly implement procedures in 5.3.8.3 of 38.331 - NR_Release_Cause_t cause = OTHER; - if (rrc->detach_after_release) - rrc->nrRrcState = RRC_STATE_DETACH_NR; - nr_rrc_going_to_IDLE(rrc, cause, dl_dcch_msg->message.choice.c1->choice.rrcRelease); + // delay the actions 60 ms from the moment the RRCRelease message was received + UPDATE_IE(rrc->RRCRelease, dl_dcch_msg->message.choice.c1->choice.rrcRelease, NR_RRCRelease_t); + nr_timer_setup(&rrc->release_timer, 60, 10); // 10ms step + nr_timer_start(&rrc->release_timer); break; case NR_DL_DCCH_MessageType__c1_PR_ueCapabilityEnquiry: @@ -1930,13 +1929,11 @@ void nr_rrc_initiate_rrcReestablishment(NR_UE_RRC_INST_t *rrc, for (int i = 1; i < 4; i++) { if (rrc->Srb[i] == RB_ESTABLISHED) { rrc->Srb[i] = RB_SUSPENDED; - nr_pdcp_suspend_srb(rrc->ue_id, i); } } for (int i = 1; i <= MAX_DRBS_PER_UE; i++) { if (get_DRB_status(rrc, i) == RB_ESTABLISHED) { set_DRB_status(rrc, i, RB_SUSPENDED); - nr_pdcp_suspend_drb(rrc->ue_id, i); } } // release the MCG SCell(s), if configured @@ -2136,6 +2133,46 @@ static void process_lte_nsa_msg(NR_UE_RRC_INST_t *rrc, nsa_msg_t *msg, int msg_l } } +void handle_RRCRelease(NR_UE_RRC_INST_t *rrc) +{ + NR_UE_Timers_Constants_t *tac = &rrc->timers_and_constants; + // stop timer T380, if running + nr_timer_stop(&tac->T380); + // stop timer T320, if running + nr_timer_stop(&tac->T320); + if (rrc->detach_after_release) + rrc->nrRrcState = RRC_STATE_DETACH_NR; + const struct NR_RRCRelease_IEs *rrcReleaseIEs = rrc->RRCRelease ? rrc->RRCRelease->criticalExtensions.choice.rrcRelease : NULL; + if (!rrc->as_security_activated) { + // ignore any field included in RRCRelease message except waitTime + // perform the actions upon going to RRC_IDLE as specified in 5.3.11 with the release cause 'other' + // upon which the procedure ends + NR_Release_Cause_t cause = OTHER; + nr_rrc_going_to_IDLE(rrc, cause, rrc->RRCRelease); + asn1cFreeStruc(asn_DEF_NR_RRCRelease, rrc->RRCRelease); + return; + } + bool suspend = false; + if (rrcReleaseIEs) { + if (rrcReleaseIEs->redirectedCarrierInfo) + LOG_E(NR_RRC, "redirectedCarrierInfo in RRCRelease not handled\n"); + if (rrcReleaseIEs->cellReselectionPriorities) + LOG_E(NR_RRC, "cellReselectionPriorities in RRCRelease not handled\n"); + if (rrcReleaseIEs->deprioritisationReq) + LOG_E(NR_RRC, "deprioritisationReq in RRCRelease not handled\n"); + if (rrcReleaseIEs->suspendConfig) { + suspend = true; + // procedures to go in INACTIVE state + AssertFatal(false, "Inactive State not supported\n"); + } + } + if (!suspend) { + NR_Release_Cause_t cause = OTHER; + nr_rrc_going_to_IDLE(rrc, cause, rrc->RRCRelease); + } + asn1cFreeStruc(asn_DEF_NR_RRCRelease, rrc->RRCRelease); +} + void nr_rrc_going_to_IDLE(NR_UE_RRC_INST_t *rrc, NR_Release_Cause_t release_cause, NR_RRCRelease_t *RRCRelease) diff --git a/openair2/RRC/NR_UE/rrc_defs.h b/openair2/RRC/NR_UE/rrc_defs.h index 533b3870f5..c22132767e 100644 --- a/openair2/RRC/NR_UE/rrc_defs.h +++ b/openair2/RRC/NR_UE/rrc_defs.h @@ -159,6 +159,7 @@ typedef struct NR_UE_Timers_Constants_s { NR_timer_t T320; NR_timer_t T321; NR_timer_t T325; + NR_timer_t T380; NR_timer_t T390; // counters uint32_t N310_cnt; @@ -217,10 +218,10 @@ typedef struct NR_UE_RRC_INST_s { long keyToUse; bool as_security_activated; bool detach_after_release; - - long selected_plmn_identity; - Rrc_State_NR_t nrRrcState; - as_nas_info_t initialNasMsg; + NR_timer_t release_timer; + NR_RRCRelease_t *RRCRelease; + long selected_plmn_identity; + Rrc_State_NR_t nrRrcState; //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 556898c304..1de5c19122 100644 --- a/openair2/RRC/NR_UE/rrc_proto.h +++ b/openair2/RRC/NR_UE/rrc_proto.h @@ -86,7 +86,7 @@ void nr_mac_rrc_sync_ind(const module_id_t module_id, void nr_rrc_going_to_IDLE(NR_UE_RRC_INST_t *rrc, NR_Release_Cause_t release_cause, NR_RRCRelease_t *RRCRelease); - +void handle_RRCRelease(NR_UE_RRC_INST_t *rrc); void nr_mac_rrc_ra_ind(const module_id_t mod_id, int frame, bool success); void nr_mac_rrc_msg3_ind(const module_id_t mod_id, const int rnti, int gnb_id); void set_rlf_sib1_timers_and_constants(NR_UE_Timers_Constants_t *tac, NR_SIB1_t *sib1); diff --git a/openair2/RRC/NR_UE/rrc_timers_and_constants.c b/openair2/RRC/NR_UE/rrc_timers_and_constants.c index 10f50dbf9b..70a467691b 100644 --- a/openair2/RRC/NR_UE/rrc_timers_and_constants.c +++ b/openair2/RRC/NR_UE/rrc_timers_and_constants.c @@ -119,6 +119,10 @@ void nr_rrc_handle_timers(NR_UE_RRC_INST_t *rrc) { NR_UE_Timers_Constants_t *timers = &rrc->timers_and_constants; + bool release_timer_expired = nr_timer_tick(&rrc->release_timer); + if (release_timer_expired) + handle_RRCRelease(rrc); + bool t300_expired = nr_timer_tick(&timers->T300); if(t300_expired) { LOG_W(NR_RRC, "Timer T300 expired! No timely response to RRCSetupRequest\n"); diff --git a/openair3/NAS/COMMON/API/NETWORK/nas_message.c b/openair3/NAS/COMMON/API/NETWORK/nas_message.c index c5a304b84b..32454a13e3 100644 --- a/openair3/NAS/COMMON/API/NETWORK/nas_message.c +++ b/openair3/NAS/COMMON/API/NETWORK/nas_message.c @@ -1009,8 +1009,7 @@ static int _nas_message_decrypt( (direction == SECU_DIRECTION_UPLINK) ? "UPLINK":"DOWNLINK", (direction == SECU_DIRECTION_UPLINK) ? emm_security_context->ul_count.seq_num:emm_security_context->dl_count.seq_num, count); - stream_cipher.key = emm_security_context->knas_enc.value; - stream_cipher.key_length = AUTH_KNAS_ENC_SIZE; + stream_cipher.context = emm_security_context->security_container->ciphering_context; stream_cipher.count = count; stream_cipher.bearer = 0x00; //33.401 section 8.1.1 stream_cipher.direction = direction; @@ -1045,15 +1044,14 @@ static int _nas_message_decrypt( (direction == SECU_DIRECTION_UPLINK) ? "UPLINK":"DOWNLINK", (direction == SECU_DIRECTION_UPLINK) ? emm_security_context->ul_count.seq_num:emm_security_context->dl_count.seq_num, count); - stream_cipher.key = emm_security_context->knas_enc.value; - stream_cipher.key_length = AUTH_KNAS_ENC_SIZE; + stream_cipher.context = emm_security_context->security_container->ciphering_context; stream_cipher.count = count; stream_cipher.bearer = 0x00; //33.401 section 8.1.1 stream_cipher.direction = direction; stream_cipher.message = (unsigned char *)src; /* length in bits */ stream_cipher.blength = length << 3; - stream_compute_encrypt(EEA1_128_ALG_ID, &stream_cipher, (unsigned char *)dest); + stream_compute_encrypt(EEA2_128_ALG_ID, &stream_cipher, (unsigned char *)dest); /* Decode the first octet (security header type or EPS bearer identity, * and protocol discriminator) */ @@ -1178,8 +1176,7 @@ static int _nas_message_encrypt( (direction == SECU_DIRECTION_UPLINK) ? "UPLINK":"DOWNLINK", (direction == SECU_DIRECTION_UPLINK) ? emm_security_context->ul_count.seq_num:emm_security_context->dl_count.seq_num, count); - stream_cipher.key = emm_security_context->knas_enc.value; - stream_cipher.key_length = AUTH_KNAS_ENC_SIZE; + stream_cipher.context = emm_security_context->security_container->ciphering_context; stream_cipher.count = count; stream_cipher.bearer = 0x00; //33.401 section 8.1.1 stream_cipher.direction = direction; @@ -1208,8 +1205,7 @@ static int _nas_message_encrypt( (direction == SECU_DIRECTION_UPLINK) ? "UPLINK":"DOWNLINK", (direction == SECU_DIRECTION_UPLINK) ? emm_security_context->ul_count.seq_num:emm_security_context->dl_count.seq_num, count); - stream_cipher.key = emm_security_context->knas_enc.value; - stream_cipher.key_length = AUTH_KNAS_ENC_SIZE; + stream_cipher.context = emm_security_context->security_container->ciphering_context; stream_cipher.count = count; stream_cipher.bearer = 0x00; //33.401 section 8.1.1 stream_cipher.direction = direction; @@ -1347,8 +1343,7 @@ static uint32_t _nas_message_get_mac( fflush(stderr); #endif - stream_cipher.key = emm_security_context->knas_int.value; - stream_cipher.key_length = AUTH_KNAS_INT_SIZE; + stream_cipher.context = emm_security_context->security_container->integrity_context; stream_cipher.count = count; stream_cipher.bearer = 0x00; //33.401 section 8.1.1 stream_cipher.direction = direction; @@ -1391,8 +1386,7 @@ static uint32_t _nas_message_get_mac( (direction == SECU_DIRECTION_UPLINK) ? emm_security_context->ul_count.seq_num:emm_security_context->dl_count.seq_num, count); - stream_cipher.key = emm_security_context->knas_int.value; - stream_cipher.key_length = AUTH_KNAS_INT_SIZE; + stream_cipher.context = emm_security_context->security_container->integrity_context; stream_cipher.count = count; stream_cipher.bearer = 0x00; //33.401 section 8.1.1 stream_cipher.direction = direction; diff --git a/openair3/NAS/NR_UE/nr_nas_msg_sim.c b/openair3/NAS/NR_UE/nr_nas_msg_sim.c index 57c3e1df58..97f9ca1aef 100644 --- a/openair3/NAS/NR_UE/nr_nas_msg_sim.c +++ b/openair3/NAS/NR_UE/nr_nas_msg_sim.c @@ -515,6 +515,10 @@ void generateIdentityResponse(as_nas_info_t *initialNasMsg, uint8_t identitytype static void generateAuthenticationResp(nr_ue_nas_t *nas, as_nas_info_t *initialNasMsg, uint8_t *buf) { derive_ue_keys(buf, nas); + /* todo: as of now, nia2 is hardcoded in derive_ue_keys(), remove this hardcoding, use NAS signalling for getting proper algorithm */ + /* todo: deal with ciphering for this stream_security_container_init() (handle ciphering in general) */ + /* todo: stream_security_container_delete() is not called anywhere, deal with that */ + nas->security_container = stream_security_container_init(0, 2 /* hardcoded: nia2 */, NULL, nas->security.knas_int); OctetString res; res.length = 16; res.value = calloc(1,16); @@ -598,8 +602,7 @@ static void generateSecurityModeComplete(nr_ue_nas_t *nas, as_nas_info_t *initia initialNasMsg->length = security_header_len + mm_msg_encode(mm_msg, (uint8_t*)(initialNasMsg->data+security_header_len), size-security_header_len); - stream_cipher.key = nas->security.knas_int; - stream_cipher.key_length = 16; + stream_cipher.context = nas->security_container->integrity_context; stream_cipher.count = nas->security.mm_counter++; stream_cipher.bearer = 1; stream_cipher.direction = 0; @@ -642,8 +645,6 @@ static void decodeRegistrationAccept(const uint8_t *buf, int len, nr_ue_nas_t *n static void generateRegistrationComplete(nr_ue_nas_t *nas, as_nas_info_t *initialNasMsg, SORTransparentContainer *sortransparentcontainer) { - //wait send RRCReconfigurationComplete and InitialContextSetupResponse - sleep(1); int length = 0; int size = 0; fgs_nas_message_t nas_msg; @@ -701,8 +702,7 @@ static void generateRegistrationComplete(nr_ue_nas_t *nas, as_nas_info_t *initia } initialNasMsg->length = length; - stream_cipher.key = nas->security.knas_int; - stream_cipher.key_length = 16; + stream_cipher.context = nas->security_container->integrity_context; stream_cipher.count = nas->security.mm_counter++; stream_cipher.bearer = 1; stream_cipher.direction = 0; @@ -764,8 +764,7 @@ static void generateDeregistrationRequest(nr_ue_nas_t *nas, as_nas_info_t *initi initialNasMsg->length = security_header_len + mm_msg_encode(&sp_msg->plain.mm_msg, (uint8_t *)(initialNasMsg->data + security_header_len), size - security_header_len); nas_stream_cipher_t stream_cipher = { - .key = nas->security.knas_int, - .key_length = 16, + .context = nas->security_container->integrity_context, .count = nas->security.mm_counter++, .bearer = 1, .direction = 0, @@ -781,8 +780,6 @@ static void generateDeregistrationRequest(nr_ue_nas_t *nas, as_nas_info_t *initi static void generatePduSessionEstablishRequest(nr_ue_nas_t *nas, as_nas_info_t *initialNasMsg, nas_pdu_session_req_t *pdu_req) { - //wait send RegistrationComplete - usleep(100*150); int size = 0; fgs_nas_message_t nas_msg={0}; @@ -857,8 +854,7 @@ static void generatePduSessionEstablishRequest(nr_ue_nas_t *nas, as_nas_info_t * initialNasMsg->length = security_header_len + mm_msg_encode(mm_msg, (uint8_t*)(initialNasMsg->data+security_header_len), size-security_header_len); - stream_cipher.key = nas->security.knas_int; - stream_cipher.key_length = 16; + stream_cipher.context = nas->security_container->integrity_context; stream_cipher.count = nas->security.mm_counter++; stream_cipher.bearer = 1; stream_cipher.direction = 0; diff --git a/openair3/NAS/NR_UE/nr_nas_msg_sim.h b/openair3/NAS/NR_UE/nr_nas_msg_sim.h index a892bf1b4b..0d2d8f5cc9 100644 --- a/openair3/NAS/NR_UE/nr_nas_msg_sim.h +++ b/openair3/NAS/NR_UE/nr_nas_msg_sim.h @@ -41,6 +41,7 @@ #include "as_message.h" #include "FGSUplinkNasTransport.h" #include +#include "secu_defs.h" #define PLAIN_5GS_MSG 0b0000 #define INTEGRITY_PROTECTED 0b0001 @@ -98,6 +99,7 @@ typedef struct { typedef struct { uicc_t *uicc; ue_sa_security_key_t security; + stream_security_container_t *security_container; Guti5GSMobileIdentity_t *guti; bool termination_procedure; } nr_ue_nas_t; diff --git a/openair3/NAS/UE/EMM/SecurityModeControl.c b/openair3/NAS/UE/EMM/SecurityModeControl.c index 3386499663..2a18763f50 100644 --- a/openair3/NAS/UE/EMM/SecurityModeControl.c +++ b/openair3/NAS/UE/EMM/SecurityModeControl.c @@ -258,6 +258,7 @@ int emm_proc_security_mode_command(nas_user_t *user, int native_ksi, int ksi, LOG_TRACE(INFO, "EMM-PROC - Update Current security context"); /* Release non-current security context */ + stream_security_container_delete(user->emm_data->security->security_container); _security_release(user->emm_data->security); user->emm_data->security = user->emm_data->non_current; /* Reset the uplink NAS COUNT counter */ @@ -265,6 +266,12 @@ int emm_proc_security_mode_command(nas_user_t *user, int native_ksi, int ksi, user->emm_data->security->ul_count.seq_num = 0; /* Set new security context indicator */ security_context_is_new = true; + /* create contexts */ + user->emm_data->security->security_container = stream_security_container_init( + seea, + seia, + user->emm_data->non_current->knas_enc.value, + user->emm_data->non_current->knas_int.value); } } diff --git a/openair3/NAS/UE/EMM/emmData.h b/openair3/NAS/UE/EMM/emmData.h index 50219b7883..d90820edf9 100644 --- a/openair3/NAS/UE/EMM/emmData.h +++ b/openair3/NAS/UE/EMM/emmData.h @@ -42,6 +42,7 @@ Description Defines internal private data handled by EPS Mobility #include "commonDef.h" #include "networkDef.h" #include "securityDef.h" +#include "openair3/SECU/secu_defs.h" #include "OctetString.h" #include "nas_timer.h" @@ -138,6 +139,7 @@ typedef struct emm_security_context_s { //OctetString ksgsn; /* SGSN security key (mapped context) */ OctetString knas_enc; /* NAS cyphering key */ OctetString knas_int; /* NAS integrity key */ + stream_security_container_t *security_container; /* container for NAS security */ struct count_s{ uint32_t spare:8; uint32_t overflow:16; diff --git a/openair3/SECU/aes_128_cbc_cmac.c b/openair3/SECU/aes_128_cbc_cmac.c index da925f6d1e..3f4ca96e50 100644 --- a/openair3/SECU/aes_128_cbc_cmac.c +++ b/openair3/SECU/aes_128_cbc_cmac.c @@ -31,101 +31,56 @@ // code for version 3.0 or greater #include -static -const char *propq = NULL; - -void aes_128_cbc_cmac(const aes_128_t* k_iv, byte_array_t msg, size_t len_out, uint8_t out[len_out]) -{ - OSSL_LIB_CTX* library_context = OSSL_LIB_CTX_new(); - DevAssert(library_context != NULL); - - /* Fetch the CMAC implementation */ - EVP_MAC* mac = EVP_MAC_fetch(library_context, "CMAC", propq); - DevAssert(mac != NULL); - - /* Create a context for the CMAC operation */ - EVP_MAC_CTX* mctx = EVP_MAC_CTX_new(mac); - DevAssert(mctx != NULL); - - // The underlying cipher to be used - char cipher_name[] = "aes128"; - - OSSL_PARAM params[2] = {0}; - params[0] = OSSL_PARAM_construct_utf8_string(OSSL_MAC_PARAM_CIPHER, cipher_name, - sizeof(cipher_name)); - params[1] = OSSL_PARAM_construct_end(); - - /* Initialise the CMAC operation */ - int rc = EVP_MAC_init(mctx, k_iv->key, sizeof(k_iv->key), params); - DevAssert(rc != 0); - - size_t sz_iv = 0; - uint8_t* iv = NULL; - if(k_iv->type == AES_INITIALIZATION_VECTOR_8){ - sz_iv = 8; - iv = (uint8_t*)k_iv->iv8.iv; - } else if(k_iv->type == AES_INITIALIZATION_VECTOR_16) { - sz_iv = 16; - iv = (uint8_t*)k_iv->iv16.iv; - } else { - DevAssert(0!=0 && "Unknwon Initialization vector"); - } - - /* Make one or more calls to process the data to be authenticated */ - rc = EVP_MAC_update(mctx, iv, sz_iv); - DevAssert(rc != 0); - - /* Make one or more calls to process the data to be authenticated */ - rc = EVP_MAC_update(mctx, msg.buf, msg.len); - DevAssert(rc != 0); - - /* Make a call to the final with a NULL buffer to get the length of the MAC */ - size_t out_len = 0; - rc = EVP_MAC_final(mctx, out, &out_len, len_out); - DevAssert(rc != 0); - - EVP_MAC_CTX_free(mctx); - EVP_MAC_free(mac); - OSSL_LIB_CTX_free(library_context); -} - -cbc_cmac_ctx_t init_aes_128_cbc_cmac(uint8_t key[16]) +cbc_cmac_ctx_t init_aes_128_cbc_cmac(const uint8_t key[16]) { DevAssert(key != NULL); - OSSL_LIB_CTX* library_context = OSSL_LIB_CTX_new(); - DevAssert(library_context != NULL); - /* Fetch the CMAC implementation */ - EVP_MAC* mac = EVP_MAC_fetch(library_context, "CMAC", propq); - DevAssert(mac != NULL); + EVP_MAC *mac_implementation = EVP_MAC_fetch(NULL, "CMAC", NULL); + DevAssert(mac_implementation != NULL); - cbc_cmac_ctx_t ctx = {.lib_ctx = library_context, .mac = mac }; + /* Create a context for the CMAC operation */ + EVP_MAC_CTX* mac_context = EVP_MAC_CTX_new(mac_implementation); + DevAssert(mac_context != NULL); - assert(16 == sizeof(ctx.key)); + cbc_cmac_ctx_t ctx = { .mac_implementation = mac_implementation, .mac_context = mac_context }; memcpy(ctx.key, key, 16); - return ctx; + // The underlying cipher to be used + char cipher_name[] = "aes128"; + + OSSL_PARAM params[2] = {0}; + params[0] = OSSL_PARAM_construct_utf8_string(OSSL_MAC_PARAM_CIPHER, cipher_name, + sizeof(cipher_name)); + params[1] = OSSL_PARAM_construct_end(); + + /* Initialise the CMAC operation */ + int rc = EVP_MAC_init(mac_context, key, 16, params); + DevAssert(rc != 0); + + return ctx; } void cipher_aes_128_cbc_cmac(cbc_cmac_ctx_t const* ctx, const aes_128_t* k_iv, byte_array_t msg, size_t len_out, uint8_t out[len_out]) { DevAssert(ctx != NULL); DevAssert(k_iv != NULL); - /* Create a context for the CMAC operation */ - EVP_MAC_CTX* mctx = EVP_MAC_CTX_new(ctx->mac); - DevAssert(mctx != NULL); - // The underlying cipher to be used - char cipher_name[] = "aes128"; - - OSSL_PARAM params[2] = {0}; - params[0] = OSSL_PARAM_construct_utf8_string(OSSL_MAC_PARAM_CIPHER, cipher_name, - sizeof(cipher_name)); - params[1] = OSSL_PARAM_construct_end(); - - /* Initialise the CMAC operation */ - int rc = EVP_MAC_init(mctx, k_iv->key, sizeof(k_iv->key), params); + /* reset the CMAC */ + /* There is a bug with version <= 3.0.2 of OpenSSL for which we must + * pass the key to reset. (Some Ubuntu version provide this version.) + * Passing the key has some impact on performance. + * todo: drop support for old versions of openssl. + */ +#if OPENSSL_VERSION_NUMBER <= 0x30000020 + /* todo: when/if we remove this code, don't forget to check use of k_iv->key + * somewhere else in the codebase. + * If not used, remove from aes_128_t* + */ + int rc = EVP_MAC_init(ctx->mac_context, k_iv->key, 16, NULL); +#else + int rc = EVP_MAC_init(ctx->mac_context, NULL, 0, NULL); +#endif DevAssert(rc != 0); size_t sz_iv = 0; @@ -141,74 +96,41 @@ void cipher_aes_128_cbc_cmac(cbc_cmac_ctx_t const* ctx, const aes_128_t* k_iv, b } /* Make one or more calls to process the data to be authenticated */ - rc = EVP_MAC_update(mctx, iv, sz_iv); + rc = EVP_MAC_update(ctx->mac_context, iv, sz_iv); DevAssert(rc != 0); /* Make one or more calls to process the data to be authenticated */ - rc = EVP_MAC_update(mctx, msg.buf, msg.len); + rc = EVP_MAC_update(ctx->mac_context, msg.buf, msg.len); DevAssert(rc != 0); /* Make a call to the final with a NULL buffer to get the length of the MAC */ size_t out_len = 0; - rc = EVP_MAC_final(mctx, out, &out_len, len_out); + rc = EVP_MAC_final(ctx->mac_context, out, &out_len, len_out); DevAssert(rc != 0); - - EVP_MAC_CTX_free(mctx); } void free_aes_128_cbc_cmac(cbc_cmac_ctx_t const* ctx) { DevAssert(ctx != NULL); - EVP_MAC_free(ctx->mac); - OSSL_LIB_CTX_free(ctx->lib_ctx); + EVP_MAC_CTX_free(ctx->mac_context); + EVP_MAC_free(ctx->mac_implementation); } #else // code for 1.1.x or lower -void aes_128_cbc_cmac(const aes_128_t* k_iv, byte_array_t msg, size_t len_out, uint8_t out[len_out]) -{ - DevAssert(k_iv != NULL); - - CMAC_CTX *ctx = CMAC_CTX_new(); - DevAssert(ctx != NULL); - - CMAC_Init(ctx, k_iv->key, sizeof(k_iv->key), EVP_aes_128_cbc(), NULL); - - size_t sz_iv = 0; - uint8_t* iv = NULL; - if(k_iv->type == AES_INITIALIZATION_VECTOR_8){ - sz_iv = 8; - iv = (uint8_t*)k_iv->iv8.iv; - } else if(k_iv->type == AES_INITIALIZATION_VECTOR_16) { - sz_iv = 16; - iv = (uint8_t*)k_iv->iv16.iv; - } else { - AssertFatal(0 != 0, "Unknwon Initialization vector"); - } - - CMAC_Update(ctx, iv, sz_iv); - - CMAC_Update(ctx, msg.buf, msg.len); - size_t len_res = 0; - CMAC_Final(ctx, out, &len_res); - DevAssert(len_res <= len_out); - - CMAC_CTX_free(ctx); -} - -cbc_cmac_ctx_t init_aes_128_cbc_cmac(uint8_t key[16]) +cbc_cmac_ctx_t init_aes_128_cbc_cmac(const uint8_t key[16]) { DevAssert(key != NULL); - cbc_cmac_ctx_t ctx = {.lib_ctx = NULL, .mac = NULL }; + cbc_cmac_ctx_t ctx = {.mac_implementation = NULL, .mac_context = NULL }; - ctx.mac = CMAC_CTX_new(); - DevAssert(ctx.mac != NULL); + ctx.mac_context = CMAC_CTX_new(); + DevAssert(ctx.mac_context != NULL); //assert(16 == sizeof(ctx.key)); memcpy(ctx.key, key, 16); //sizeof(ctx.key)); - CMAC_Init(ctx.mac, ctx.key, 16, EVP_aes_128_cbc(), NULL); + CMAC_Init(ctx.mac_context, ctx.key, 16, EVP_aes_128_cbc(), NULL); return ctx; } @@ -218,11 +140,11 @@ void cipher_aes_128_cbc_cmac(cbc_cmac_ctx_t const* ctx, const aes_128_t* k_iv, b DevAssert(k_iv != NULL); //From https://man.openbsd.org/CMAC_Init.3 - //If ctx is already initialized, CMAC_Init() can be called again with key, - //cipher, and impl all set to NULL and key_len set to 0. In that case, any - //data already processed is discarded and ctx is re-initialized to start + //If ctx is already initialized, CMAC_Init() can be called again with key, + //cipher, and impl all set to NULL and key_len set to 0. In that case, any + //data already processed is discarded and ctx is re-initialized to start //reading data anew. - CMAC_Init(ctx->mac, NULL, 0, NULL, NULL); + CMAC_Init(ctx->mac_context, NULL, 0, NULL, NULL); size_t sz_iv = 0; uint8_t* iv = NULL; @@ -236,19 +158,18 @@ void cipher_aes_128_cbc_cmac(cbc_cmac_ctx_t const* ctx, const aes_128_t* k_iv, b AssertFatal(0 != 0, "Unknwon Initialization vector"); } - CMAC_Update(ctx->mac, iv, sz_iv); + CMAC_Update(ctx->mac_context, iv, sz_iv); - CMAC_Update(ctx->mac, msg.buf, msg.len); + CMAC_Update(ctx->mac_context, msg.buf, msg.len); size_t len_res = 0; - CMAC_Final(ctx->mac, out, &len_res); + CMAC_Final(ctx->mac_context, out, &len_res); DevAssert(len_res <= len_out); } void free_aes_128_cbc_cmac(cbc_cmac_ctx_t const* ctx) { DevAssert(ctx != NULL); - CMAC_CTX_free(ctx->mac); + CMAC_CTX_free(ctx->mac_context); } #endif - diff --git a/openair3/SECU/aes_128_cbc_cmac.h b/openair3/SECU/aes_128_cbc_cmac.h index b5118118c3..b906ddf5f3 100644 --- a/openair3/SECU/aes_128_cbc_cmac.h +++ b/openair3/SECU/aes_128_cbc_cmac.h @@ -31,17 +31,13 @@ #include typedef struct { - void* lib_ctx; - void* mac; + void *mac_implementation; + void *mac_context; uint8_t key[16]; } cbc_cmac_ctx_t ; -void aes_128_cbc_cmac(const aes_128_t* k_iv, byte_array_t msg, size_t len_out, uint8_t out[len_out]); - -cbc_cmac_ctx_t init_aes_128_cbc_cmac(uint8_t key[16]); - +cbc_cmac_ctx_t init_aes_128_cbc_cmac(const uint8_t key[16]); void cipher_aes_128_cbc_cmac(cbc_cmac_ctx_t const* ctx, const aes_128_t* k_iv, byte_array_t msg, size_t len_out, uint8_t out[len_out]); - void free_aes_128_cbc_cmac(cbc_cmac_ctx_t const* ctx); #endif diff --git a/openair3/SECU/nas_stream_eea1.c b/openair3/SECU/nas_stream_eea1.c index a4e4b84ca4..027205353b 100644 --- a/openair3/SECU/nas_stream_eea1.c +++ b/openair3/SECU/nas_stream_eea1.c @@ -38,10 +38,9 @@ void nas_stream_encrypt_eea1(nas_stream_cipher_t const *stream_cipher, uint8_t * //uint32_t byte_length; uint32_t *KS; uint32_t K[4],IV[4]; + uint8_t *key = (uint8_t *)stream_cipher->context; DevAssert(stream_cipher != NULL); - DevAssert(stream_cipher->key != NULL); - DevAssert(stream_cipher->key_length == 16); DevAssert(out != NULL); n = ( stream_cipher->blength + 31 ) / 32; @@ -50,22 +49,20 @@ void nas_stream_encrypt_eea1(nas_stream_cipher_t const *stream_cipher, uint8_t * memset(&snow_3g_context, 0, sizeof(snow_3g_context)); /*Initialisation*/ - /* Load the confidentiality key for SNOW 3G initialization as in section - 3.4. */ - memcpy(K+3,stream_cipher->key+0,4); /*K[3] = key[0]; we assume + /* Load the confidentiality key for SNOW 3G initialization as in section 3.4. */ + memcpy(K+3,key+0,4); /*K[3] = key[0]; we assume K[3]=key[0]||key[1]||...||key[31] , with key[0] the * most important bit of key*/ - memcpy(K+2,stream_cipher->key+4,4); /*K[2] = key[1];*/ - memcpy(K+1,stream_cipher->key+8,4); /*K[1] = key[2];*/ - memcpy(K+0,stream_cipher->key+12,4); /*K[0] = key[3]; we assume - K[0]=key[96]||key[97]||...||key[127] , with key[127] the - * least important bit of key*/ + memcpy(K+2,key+4,4); /*K[2] = key[1];*/ + memcpy(K+1,key+8,4); /*K[1] = key[2];*/ + memcpy(K+0,key+12,4); /*K[0] = key[3]; we assume + * K[0]=key[96]||key[97]||...||key[127] , with key[127] the + * least important bit of key*/ K[3] = hton_int32(K[3]); K[2] = hton_int32(K[2]); K[1] = hton_int32(K[1]); K[0] = hton_int32(K[0]); - /* Prepare the initialization vector (IV) for SNOW 3G initialization as in - section 3.4. */ + /* Prepare the initialization vector (IV) for SNOW 3G initialization as in section 3.4. */ IV[3] = stream_cipher->count; IV[2] = ((((uint32_t)stream_cipher->bearer) << 3) | ((((uint32_t)stream_cipher->direction) & 0x1) << 2)) << 24; IV[1] = IV[3]; @@ -104,3 +101,16 @@ void nas_stream_encrypt_eea1(nas_stream_cipher_t const *stream_cipher, uint8_t * out[ceil_index - 1] = stream_cipher->message[ceil_index - 1]; } } + +stream_security_context_t *stream_ciphering_init_eea1(const uint8_t *ciphering_key) +{ + void *ret = calloc(1, 16); + AssertFatal(ret != NULL, "out of memory\n"); + memcpy(ret, ciphering_key, 16); + return (stream_security_context_t *)ret; +} + +void stream_ciphering_free_eea1(stream_security_context_t *ciphering_context) +{ + free(ciphering_context); +} diff --git a/openair3/SECU/nas_stream_eea1.h b/openair3/SECU/nas_stream_eea1.h index d713dc60d3..ebddd7af35 100644 --- a/openair3/SECU/nas_stream_eea1.h +++ b/openair3/SECU/nas_stream_eea1.h @@ -29,4 +29,7 @@ void nas_stream_encrypt_eea1(nas_stream_cipher_t const *stream_cipher, uint8_t *out); +stream_security_context_t *stream_ciphering_init_eea1(const uint8_t *ciphering_key); +void stream_ciphering_free_eea1(stream_security_context_t *ciphering_context); + #endif diff --git a/openair3/SECU/nas_stream_eea2.c b/openair3/SECU/nas_stream_eea2.c index dbdc040883..6600afaace 100644 --- a/openair3/SECU/nas_stream_eea2.c +++ b/openair3/SECU/nas_stream_eea2.c @@ -33,15 +33,13 @@ void nas_stream_encrypt_eea2(nas_stream_cipher_t const *stream_cipher, uint8_t *out) { DevAssert(stream_cipher != NULL); - DevAssert(stream_cipher->key != NULL); - DevAssert(stream_cipher->key_length == 32); DevAssert(stream_cipher->bearer < 32); DevAssert(stream_cipher->direction < 2); DevAssert(stream_cipher->message != NULL); DevAssert(stream_cipher->blength > 7); aes_128_t p = {0}; - memcpy(p.key, stream_cipher->key, stream_cipher->key_length); + memcpy(p.key, stream_cipher->context, 16); p.type = AES_INITIALIZATION_VECTOR_16; p.iv16.d.count = htonl(stream_cipher->count); p.iv16.d.bearer = stream_cipher->bearer; @@ -54,3 +52,16 @@ void nas_stream_encrypt_eea2(nas_stream_cipher_t const *stream_cipher, uint8_t * byte_array_t msg = {.buf = stream_cipher->message, .len = byte_lenght}; aes_128_ctr(&p, msg, len_out, out); } + +stream_security_context_t *stream_ciphering_init_eea2(const uint8_t *ciphering_key) +{ + void *ret = calloc(1, 16); + AssertFatal(ret != NULL, "out of memory\n"); + memcpy(ret, ciphering_key, 16); + return (stream_security_context_t *)ret; +} + +void stream_ciphering_free_eea2(stream_security_context_t *ciphering_context) +{ + free(ciphering_context); +} diff --git a/openair3/SECU/nas_stream_eea2.h b/openair3/SECU/nas_stream_eea2.h index c6133c987d..f64fff6c4d 100644 --- a/openair3/SECU/nas_stream_eea2.h +++ b/openair3/SECU/nas_stream_eea2.h @@ -26,40 +26,9 @@ #include "secu_defs.h" #include -/* Rijndael S-box OSA_SR */ - -static const uint8_t OSA_SR[256] = { - 0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5, 0x30, 0x01, 0x67, 0x2B, 0xFE, 0xD7, 0xAB, 0x76, 0xCA, 0x82, 0xC9, 0x7D, - 0xFA, 0x59, 0x47, 0xF0, 0xAD, 0xD4, 0xA2, 0xAF, 0x9C, 0xA4, 0x72, 0xC0, 0xB7, 0xFD, 0x93, 0x26, 0x36, 0x3F, 0xF7, 0xCC, - 0x34, 0xA5, 0xE5, 0xF1, 0x71, 0xD8, 0x31, 0x15, 0x04, 0xC7, 0x23, 0xC3, 0x18, 0x96, 0x05, 0x9A, 0x07, 0x12, 0x80, 0xE2, - 0xEB, 0x27, 0xB2, 0x75, 0x09, 0x83, 0x2C, 0x1A, 0x1B, 0x6E, 0x5A, 0xA0, 0x52, 0x3B, 0xD6, 0xB3, 0x29, 0xE3, 0x2F, 0x84, - 0x53, 0xD1, 0x00, 0xED, 0x20, 0xFC, 0xB1, 0x5B, 0x6A, 0xCB, 0xBE, 0x39, 0x4A, 0x4C, 0x58, 0xCF, 0xD0, 0xEF, 0xAA, 0xFB, - 0x43, 0x4D, 0x33, 0x85, 0x45, 0xF9, 0x02, 0x7F, 0x50, 0x3C, 0x9F, 0xA8, 0x51, 0xA3, 0x40, 0x8F, 0x92, 0x9D, 0x38, 0xF5, - 0xBC, 0xB6, 0xDA, 0x21, 0x10, 0xFF, 0xF3, 0xD2, 0xCD, 0x0C, 0x13, 0xEC, 0x5F, 0x97, 0x44, 0x17, 0xC4, 0xA7, 0x7E, 0x3D, - 0x64, 0x5D, 0x19, 0x73, 0x60, 0x81, 0x4F, 0xDC, 0x22, 0x2A, 0x90, 0x88, 0x46, 0xEE, 0xB8, 0x14, 0xDE, 0x5E, 0x0B, 0xDB, - 0xE0, 0x32, 0x3A, 0x0A, 0x49, 0x06, 0x24, 0x5C, 0xC2, 0xD3, 0xAC, 0x62, 0x91, 0x95, 0xE4, 0x79, 0xE7, 0xC8, 0x37, 0x6D, - 0x8D, 0xD5, 0x4E, 0xA9, 0x6C, 0x56, 0xF4, 0xEA, 0x65, 0x7A, 0xAE, 0x08, 0xBA, 0x78, 0x25, 0x2E, 0x1C, 0xA6, 0xB4, 0xC6, - 0xE8, 0xDD, 0x74, 0x1F, 0x4B, 0xBD, 0x8B, 0x8A, 0x70, 0x3E, 0xB5, 0x66, 0x48, 0x03, 0xF6, 0x0E, 0x61, 0x35, 0x57, 0xB9, - 0x86, 0xC1, 0x1D, 0x9E, 0xE1, 0xF8, 0x98, 0x11, 0x69, 0xD9, 0x8E, 0x94, 0x9B, 0x1E, 0x87, 0xE9, 0xCE, 0x55, 0x28, 0xDF, - 0x8C, 0xA1, 0x89, 0x0D, 0xBF, 0xE6, 0x42, 0x68, 0x41, 0x99, 0x2D, 0x0F, 0xB0, 0x54, 0xBB, 0x16}; - -/* S-box OSA_SQ */ - -static const uint8_t OSA_SQ[256] = { - 0x25, 0x24, 0x73, 0x67, 0xD7, 0xAE, 0x5C, 0x30, 0xA4, 0xEE, 0x6E, 0xCB, 0x7D, 0xB5, 0x82, 0xDB, 0xE4, 0x8E, 0x48, 0x49, - 0x4F, 0x5D, 0x6A, 0x78, 0x70, 0x88, 0xE8, 0x5F, 0x5E, 0x84, 0x65, 0xE2, 0xD8, 0xE9, 0xCC, 0xED, 0x40, 0x2F, 0x11, 0x28, - 0x57, 0xD2, 0xAC, 0xE3, 0x4A, 0x15, 0x1B, 0xB9, 0xB2, 0x80, 0x85, 0xA6, 0x2E, 0x02, 0x47, 0x29, 0x07, 0x4B, 0x0E, 0xC1, - 0x51, 0xAA, 0x89, 0xD4, 0xCA, 0x01, 0x46, 0xB3, 0xEF, 0xDD, 0x44, 0x7B, 0xC2, 0x7F, 0xBE, 0xC3, 0x9F, 0x20, 0x4C, 0x64, - 0x83, 0xA2, 0x68, 0x42, 0x13, 0xB4, 0x41, 0xCD, 0xBA, 0xC6, 0xBB, 0x6D, 0x4D, 0x71, 0x21, 0xF4, 0x8D, 0xB0, 0xE5, 0x93, - 0xFE, 0x8F, 0xE6, 0xCF, 0x43, 0x45, 0x31, 0x22, 0x37, 0x36, 0x96, 0xFA, 0xBC, 0x0F, 0x08, 0x52, 0x1D, 0x55, 0x1A, 0xC5, - 0x4E, 0x23, 0x69, 0x7A, 0x92, 0xFF, 0x5B, 0x5A, 0xEB, 0x9A, 0x1C, 0xA9, 0xD1, 0x7E, 0x0D, 0xFC, 0x50, 0x8A, 0xB6, 0x62, - 0xF5, 0x0A, 0xF8, 0xDC, 0x03, 0x3C, 0x0C, 0x39, 0xF1, 0xB8, 0xF3, 0x3D, 0xF2, 0xD5, 0x97, 0x66, 0x81, 0x32, 0xA0, 0x00, - 0x06, 0xCE, 0xF6, 0xEA, 0xB7, 0x17, 0xF7, 0x8C, 0x79, 0xD6, 0xA7, 0xBF, 0x8B, 0x3F, 0x1F, 0x53, 0x63, 0x75, 0x35, 0x2C, - 0x60, 0xFD, 0x27, 0xD3, 0x94, 0xA5, 0x7C, 0xA1, 0x05, 0x58, 0x2D, 0xBD, 0xD9, 0xC7, 0xAF, 0x6B, 0x54, 0x0B, 0xE0, 0x38, - 0x04, 0xC8, 0x9D, 0xE7, 0x14, 0xB1, 0x87, 0x9C, 0xDF, 0x6F, 0xF9, 0xDA, 0x2A, 0xC4, 0x59, 0x16, 0x74, 0x91, 0xAB, 0x26, - 0x61, 0x76, 0x34, 0x2B, 0xAD, 0x99, 0xFB, 0x72, 0xEC, 0x33, 0x12, 0xDE, 0x98, 0x3B, 0xC0, 0x9B, 0x3E, 0x18, 0x10, 0x3A, - 0x56, 0xE1, 0x77, 0xC9, 0x1E, 0x9E, 0x95, 0xA3, 0x90, 0x19, 0xA8, 0x6C, 0x09, 0xD0, 0xF0, 0x86}; - void nas_stream_encrypt_eea2(nas_stream_cipher_t const *stream_cipher, uint8_t *out); +stream_security_context_t *stream_ciphering_init_eea2(const uint8_t *ciphering_key); +void stream_ciphering_free_eea2(stream_security_context_t *ciphering_context); + #endif diff --git a/openair3/SECU/nas_stream_eia1.c b/openair3/SECU/nas_stream_eia1.c index f080db7aac..c648ee585f 100644 --- a/openair3/SECU/nas_stream_eia1.c +++ b/openair3/SECU/nas_stream_eia1.c @@ -126,16 +126,17 @@ void nas_stream_encrypt_eia1(nas_stream_cipher_t const *stream_cipher, uint8_t o uint64_t M_D_2; int rem_bits; uint32_t mask = 0; - uint32_t *message; + uint32_t *message; + uint8_t *key = (uint8_t *)stream_cipher->context; message = (uint32_t*)stream_cipher->message; /* To operate 32 bit message internally. */ /* Load the Integrity Key for SNOW3G initialization as in section 4.4. */ - memcpy(K+3,stream_cipher->key+0,4); /*K[3] = key[0]; we assume + memcpy(K+3,key+0,4); /*K[3] = key[0]; we assume K[3]=key[0]||key[1]||...||key[31] , with key[0] the * most important bit of key*/ - memcpy(K+2,stream_cipher->key+4,4); /*K[2] = key[1];*/ - memcpy(K+1,stream_cipher->key+8,4); /*K[1] = key[2];*/ - memcpy(K+0,stream_cipher->key+12,4); /*K[0] = key[3]; we assume + memcpy(K+2,key+4,4); /*K[2] = key[1];*/ + memcpy(K+1,key+8,4); /*K[1] = key[2];*/ + memcpy(K+0,key+12,4); /*K[0] = key[3]; we assume K[0]=key[96]||key[97]||...||key[127] , with key[127] the * least important bit of key*/ K[3] = hton_int32(K[3]); @@ -213,3 +214,16 @@ void nas_stream_encrypt_eia1(nas_stream_cipher_t const *stream_cipher, uint8_t o MAC_I = hton_int32(MAC_I); memcpy(out, &MAC_I, 4); } + +stream_security_context_t *stream_integrity_init_eia1(const uint8_t *integrity_key) +{ + void *ret = calloc(1, 16); + AssertFatal(ret != NULL, "out of memory\n"); + memcpy(ret, integrity_key, 16); + return (stream_security_context_t *)ret; +} + +void stream_integrity_free_eia1(stream_security_context_t *integrity_context) +{ + free(integrity_context); +} diff --git a/openair3/SECU/nas_stream_eia1.h b/openair3/SECU/nas_stream_eia1.h index 58a7f8be99..a385781035 100644 --- a/openair3/SECU/nas_stream_eia1.h +++ b/openair3/SECU/nas_stream_eia1.h @@ -26,4 +26,7 @@ void nas_stream_encrypt_eia1(nas_stream_cipher_t const* stream_cipher, uint8_t out[4]); +stream_security_context_t *stream_integrity_init_eia1(const uint8_t *integrity_key); +void stream_integrity_free_eia1(stream_security_context_t *integrity_context); + #endif diff --git a/openair3/SECU/nas_stream_eia2.c b/openair3/SECU/nas_stream_eia2.c index 2655c8ad81..ee19a8f603 100644 --- a/openair3/SECU/nas_stream_eia2.c +++ b/openair3/SECU/nas_stream_eia2.c @@ -45,11 +45,11 @@ void nas_stream_encrypt_eia2(nas_stream_cipher_t const *stream_cipher, uint8_t o DevAssert(stream_cipher != NULL); DevAssert(stream_cipher->message != NULL); DevAssert(stream_cipher->bearer < 32); - DevAssert(stream_cipher->key_length == 16); DevAssert((stream_cipher->blength & 0x7) == 0); + cbc_cmac_ctx_t *ctx = (cbc_cmac_ctx_t *)stream_cipher->context; aes_128_t k_iv = {0}; - memcpy(k_iv.key, stream_cipher->key, sizeof(k_iv.key)); + memcpy(&k_iv.key, ctx->key, 16); k_iv.type = AES_INITIALIZATION_VECTOR_8; k_iv.iv8.d.bearer = stream_cipher->bearer; k_iv.iv8.d.direction = stream_cipher->direction; @@ -58,8 +58,21 @@ void nas_stream_encrypt_eia2(nas_stream_cipher_t const *stream_cipher, uint8_t o size_t const m_length = stream_cipher->blength >> 3; uint8_t result[16] = {0}; byte_array_t msg = {.buf = stream_cipher->message, .len = m_length }; - aes_128_cbc_cmac(&k_iv, msg, sizeof(result), result); + cipher_aes_128_cbc_cmac(ctx, &k_iv, msg, sizeof(result), result); memcpy(out, result, 4); } +stream_security_context_t *stream_integrity_init_eia2(const uint8_t *integrity_key) +{ + cbc_cmac_ctx_t *ret = calloc(1, sizeof(cbc_cmac_ctx_t)); + AssertFatal(ret != NULL, "out of memory\n"); + *ret = init_aes_128_cbc_cmac(integrity_key); + return (stream_security_context_t *)ret; +} + +void stream_integrity_free_eia2(stream_security_context_t *integrity_context) +{ + free_aes_128_cbc_cmac((cbc_cmac_ctx_t *)integrity_context); + free(integrity_context); +} diff --git a/openair3/SECU/nas_stream_eia2.h b/openair3/SECU/nas_stream_eia2.h index 1349408fb7..b3da1d14a4 100644 --- a/openair3/SECU/nas_stream_eia2.h +++ b/openair3/SECU/nas_stream_eia2.h @@ -26,4 +26,7 @@ void nas_stream_encrypt_eia2(nas_stream_cipher_t const* stream_cipher, uint8_t out[4]); +stream_security_context_t *stream_integrity_init_eia2(const uint8_t *integrity_key); +void stream_integrity_free_eia2(stream_security_context_t *integrity_context); + #endif diff --git a/openair3/SECU/secu_defs.c b/openair3/SECU/secu_defs.c index 58a8754bad..17e3ca96ec 100644 --- a/openair3/SECU/secu_defs.c +++ b/openair3/SECU/secu_defs.c @@ -64,3 +64,70 @@ void stream_compute_encrypt(eea_alg_id_e alg, nas_stream_cipher_t const* stream_ } } +stream_security_context_t *stream_integrity_init(int integrity_algorithm, const uint8_t *integrity_key) +{ + switch (integrity_algorithm) { + case EEA0_ALG_ID: return NULL; + case EEA1_128_ALG_ID: return stream_integrity_init_eia1(integrity_key); + case EEA2_128_ALG_ID: return stream_integrity_init_eia2(integrity_key); + default: AssertFatal(0, "unsupported integrity algorithm\n"); + } +} + +void stream_integrity_free(int integrity_algorithm, stream_security_context_t *integrity_context) +{ + switch (integrity_algorithm) { + case EEA0_ALG_ID: return; + case EEA1_128_ALG_ID: return stream_integrity_free_eia1(integrity_context); + case EEA2_128_ALG_ID: return stream_integrity_free_eia2(integrity_context); + default: AssertFatal(0, "unsupported integrity algorithm\n"); + } +} + +stream_security_context_t *stream_ciphering_init(int ciphering_algorithm, const uint8_t *ciphering_key) +{ + switch (ciphering_algorithm) { + case EEA0_ALG_ID: return NULL; + case EEA1_128_ALG_ID: return stream_ciphering_init_eea1(ciphering_key); + case EEA2_128_ALG_ID: return stream_ciphering_init_eea2(ciphering_key); + default: AssertFatal(0, "unsupported ciphering algorithm\n"); + } +} + +void stream_ciphering_free(int ciphering_algorithm, stream_security_context_t *ciphering_context) +{ + switch (ciphering_algorithm) { + case EEA0_ALG_ID: return; + case EEA1_128_ALG_ID: return stream_ciphering_free_eea1(ciphering_context); + case EEA2_128_ALG_ID: return stream_ciphering_free_eea2(ciphering_context); + default: AssertFatal(0, "unsupported ciphering algorithm\n"); + } +} + +stream_security_container_t *stream_security_container_init(int ciphering_algorithm, + int integrity_algorithm, + const uint8_t *ciphering_key, + const uint8_t *integrity_key) +{ + stream_security_container_t *container = calloc(1, sizeof(*container)); + AssertFatal(container != NULL, "out of memory\n"); + + container->integrity_algorithm = integrity_algorithm; + container->ciphering_algorithm = ciphering_algorithm; + + container->integrity_context = stream_integrity_init(integrity_algorithm, integrity_key); + container->ciphering_context = stream_ciphering_init(ciphering_algorithm, ciphering_key); + + return container; +} + +void stream_security_container_delete(stream_security_container_t *container) +{ + /* passing NULL is accepted */ + if (container == NULL) + return; + + stream_integrity_free(container->integrity_algorithm, container->integrity_context); + stream_ciphering_free(container->ciphering_algorithm, container->ciphering_context); + free(container); +} diff --git a/openair3/SECU/secu_defs.h b/openair3/SECU/secu_defs.h index 7b96544bd5..bfd3a943ce 100644 --- a/openair3/SECU/secu_defs.h +++ b/openair3/SECU/secu_defs.h @@ -28,17 +28,46 @@ #define SECU_DIRECTION_UPLINK 0 #define SECU_DIRECTION_DOWNLINK 1 +/* stream_security_context_t is an opaque structure. + * It is different for each integrity and ciphering algorithm in use. + * Defined as a struct to have compilation time type checking + * (the "context" field is never actually used). + */ typedef struct { - uint8_t *key; - uint32_t key_length; + void *context; +} stream_security_context_t; + +/* stream_security_container_t contains the current configuration + * of integrity and ciphering. It is used by PDCP and NAS. + */ +typedef struct { + int integrity_algorithm; + int ciphering_algorithm; + stream_security_context_t *ciphering_context; + stream_security_context_t *integrity_context; +} stream_security_container_t; + +typedef struct { + stream_security_context_t *context; uint32_t count; uint8_t bearer; uint8_t direction; uint8_t *message; /* length in bits */ - uint32_t blength; + uint32_t blength; } nas_stream_cipher_t; +stream_security_context_t *stream_integrity_init(int integrity_algorithm, const uint8_t *integrity_key); +stream_security_context_t *stream_ciphering_init(int ciphering_algorithm, const uint8_t *ciphering_key); +void stream_integrity_free(int integrity_algorithm, stream_security_context_t *integrity_context); +void stream_ciphering_free(int ciphering_algorithm, stream_security_context_t *ciphering_context); + +stream_security_container_t *stream_security_container_init(int ciphering_algorithm, + int integrity_algorithm, + const uint8_t *ciphering_key, + const uint8_t *integrity_key); +void stream_security_container_delete(stream_security_container_t *container); + /*! * @brief Encrypt/Decrypt a block of data based on the provided algorithm * @param[in] algorithm Algorithm used to encrypt the data diff --git a/radio/USRP/usrp_lib.cpp b/radio/USRP/usrp_lib.cpp index 4218ae7748..ad0404f13d 100644 --- a/radio/USRP/usrp_lib.cpp +++ b/radio/USRP/usrp_lib.cpp @@ -1220,12 +1220,20 @@ extern "C" { LOG_I(HW,"%s() sample_rate:%u\n", __FUNCTION__, (int)openair0_cfg[0].sample_rate); switch ((int)openair0_cfg[0].sample_rate) { + case 245760000: + // from usrp_time_offset + // openair0_cfg[0].samples_per_packet = 2048; + openair0_cfg[0].tx_sample_advance = 15; // to be checked + openair0_cfg[0].tx_bw = 200e6; + openair0_cfg[0].rx_bw = 200e6; + break; + case 184320000: // from usrp_time_offset - //openair0_cfg[0].samples_per_packet = 2048; - openair0_cfg[0].tx_sample_advance = 15; //to be checked - openair0_cfg[0].tx_bw = 100e6; - openair0_cfg[0].rx_bw = 100e6; + // openair0_cfg[0].samples_per_packet = 2048; + openair0_cfg[0].tx_sample_advance = 15; // to be checked + openair0_cfg[0].tx_bw = 100e6; + openair0_cfg[0].rx_bw = 100e6; break; case 122880000: