Merge branch 'integration_2023_w21' into 'develop'

integration_2023_w21

See merge request oai/openairinterface5g!2128

* !2097 Fix: NR UE timing adjust
* !2100 CI: AW2S pipeline - iperf test added, modifs in OC projects usage
* !2119 Set kernel parameters for X4x0
* !2121 Fix regression pdu session release
* !2124 handle --disable-stats in rrc gNB
* !2125 Tutorials: minor updates on NR SA Tutorial
* !2126 bugfix for PRACH format C2 at UE
* !1964 Merge secu osa into openair3/SECU
* !2101 Use F1 internally: UE Context Release
* !2120 Use F1 internally: UE Context Modification
* !2129 Adding a check to avoid having more logical antenna ports than physical in config file
This commit is contained in:
Robert Schmidt
2023-05-28 13:07:13 +00:00
112 changed files with 1785 additions and 2803 deletions
+18 -27
View File
@@ -773,33 +773,25 @@ add_library(UTIL
${OPENAIR_DIR}/common/utils/time_stat.c
)
set(SECU_OSA_SRC
${OPENAIR2_DIR}/UTIL/OSA/osa_key_deriver.c
${OPENAIR2_DIR}/UTIL/OSA/osa_snow3g.c
${OPENAIR2_DIR}/UTIL/OSA/osa_stream_eea.c
${OPENAIR2_DIR}/UTIL/OSA/osa_stream_eia.c
)
add_library(SECU_OSA ${SECU_OSA_SRC} $<TARGET_OBJECTS:ds> )
target_include_directories(SECU_OSA PRIVATE ${OPENAIR_DIR}/common/utils/ds/)
set(SECU_CN_SRC
set(SECURITY_SRC
${OPENAIR3_DIR}/SECU/secu_defs.c
${OPENAIR3_DIR}/SECU/kdf.c
${OPENAIR3_DIR}/SECU/aes_128_ctr.c
${OPENAIR3_DIR}/SECU/aes_128_cbc_cmac.c
${OPENAIR3_DIR}/SECU/aes_128_ecb.c
${OPENAIR3_DIR}/SECU/sha_256_hmac.c
${OPENAIR3_DIR}/SECU/rijndael.c
${OPENAIR3_DIR}/SECU/snow3g.c
${OPENAIR3_DIR}/SECU/key_nas_deriver.c
${OPENAIR3_DIR}/SECU/nas_stream_eea0.c
${OPENAIR3_DIR}/SECU/nas_stream_eea1.c
${OPENAIR3_DIR}/SECU/nas_stream_eia1.c
${OPENAIR3_DIR}/SECU/nas_stream_eea2.c
${OPENAIR3_DIR}/SECU/nas_stream_eia2.c
)
add_library(SECU_CN ${SECU_CN_SRC} $<TARGET_OBJECTS:ds>)
target_include_directories(SECU_CN PRIVATE ${OPENAIR_DIR}/common/utils/ds/)
add_library(SECURITY ${SECURITY_SRC} $<TARGET_OBJECTS:ds>)
target_include_directories(SECURITY PRIVATE ${OPENAIR_DIR}/common/utils/ds/)
# Physical Channel Procedures Scheduling
################################"
@@ -1350,8 +1342,8 @@ set(NR_PDCP_SRC
#these files should not be here, will be removed at some point when the
#computation is done directly inside nr_pdcp_integrity_nia1.c instead
#of reusing code of osa_stream_eia.c
${OPENAIR2_DIR}/UTIL/OSA/osa_stream_eia.c
${OPENAIR2_DIR}/UTIL/OSA/osa_snow3g.c
#${OPENAIR2_DIR}/UTIL/OSA/osa_stream_eia.c
#${OPENAIR2_DIR}/UTIL/OSA/osa_snow3g.c
)
set(NR_SDAP_SRC
@@ -1993,7 +1985,7 @@ add_library(LIB_5GNAS_GNB
)
target_include_directories(LIB_5GNAS_GNB PRIVATE ${OPENAIR_DIR}/common/utils/ds/)
target_link_libraries(LIB_5GNAS_GNB PRIVATE SECU_CN ${CRYPTO_LIBRARIES})
target_link_libraries(LIB_5GNAS_GNB PRIVATE SECURITY ${CRYPTO_LIBRARIES})
target_link_libraries(LIB_5GNAS_GNB PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs)
# Simulation library
@@ -2156,7 +2148,7 @@ add_dependencies(lte-softmodem oai_iqplayer)
target_link_libraries(lte-softmodem PRIVATE
-Wl,--start-group
lte_rrc nr_rrc s1ap m2ap x2ap m3ap GTPV1U SECU_CN SECU_OSA UTIL HASHTABLE SCTP_CLIENT MME_APP SCHED_LIB SCHED_RU_LIB
lte_rrc nr_rrc s1ap m2ap x2ap m3ap GTPV1U SECURITY UTIL HASHTABLE SCTP_CLIENT MME_APP SCHED_LIB SCHED_RU_LIB
PHY_COMMON PHY PHY_RU L2 L2_LTE NFAPI_COMMON_LIB NFAPI_LIB NFAPI_VNF_LIB NFAPI_PNF_LIB NFAPI_USER_LIB MISC_NFAPI_LTE_LIB
${NAS_UE_LIB} ITTI SIMU SIMU_ETH
-Wl,--end-group z dl)
@@ -2165,7 +2157,6 @@ target_link_libraries(lte-softmodem PRIVATE pthread m CONFIG_LIB rt crypt ${CRYP
target_link_libraries(lte-softmodem PRIVATE ${T_LIB})
target_link_libraries(lte-softmodem PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs)
add_executable(oairu
${OPENAIR_DIR}/executables/lte-ru.c
${OPENAIR_DIR}/executables/ru_control.c
@@ -2218,7 +2209,7 @@ endif()
target_link_libraries(lte-uesoftmodem PRIVATE
-Wl,--start-group
lte_rrc nr_rrc s1ap x2ap m2ap m3ap
SECU_CN SECU_OSA UTIL HASHTABLE SCTP_CLIENT MME_APP SCHED_RU_LIB SCHED_UE_LIB PHY_COMMON
SECURITY UTIL HASHTABLE SCTP_CLIENT MME_APP SCHED_RU_LIB SCHED_UE_LIB PHY_COMMON
PHY_UE PHY_RU L2_UE L2_LTE SIMU SIMU_ETH NFAPI_COMMON_LIB NFAPI_LIB NFAPI_PNF_LIB NFAPI_USER_LIB MISC_NFAPI_LTE_LIB
${NAS_UE_LIB} ITTI ${ATLAS_LIBRARIES}
-Wl,--end-group z dl)
@@ -2258,7 +2249,7 @@ add_executable(nr-softmodem
target_link_libraries(nr-softmodem PRIVATE
-Wl,--start-group
UTIL HASHTABLE SCTP_CLIENT SCHED_LIB SCHED_RU_LIB SCHED_NR_LIB PHY_NR PHY PHY_COMMON PHY_NR_COMMON PHY_RU GTPV1U SECU_CN SECU_OSA
UTIL HASHTABLE SCTP_CLIENT SCHED_LIB SCHED_RU_LIB SCHED_NR_LIB PHY_NR PHY PHY_COMMON PHY_NR_COMMON PHY_RU GTPV1U SECURITY
ITTI ${NAS_UE_LIB} lte_rrc nr_rrc
ngap s1ap L2_LTE_NR L2_NR MAC_NR_COMMON NFAPI_COMMON_LIB NFAPI_LIB NFAPI_VNF_LIB NFAPI_PNF_LIB NFAPI_USER_LIB SIMU SIMU_ETH
x2ap f1ap m2ap m3ap e1ap
@@ -2293,9 +2284,9 @@ add_executable(nr-cuup
target_link_libraries(nr-cuup PRIVATE
CONFIG_LIB ITTI SCTP_CLIENT
GTPV1U e1ap e1_pdcp_if f1ap SIMU_ETH
SECU_OSA SECU_CN ${OPENSSL_LIBRARIES} crypt z sctp dl pthread)
SECURITY ${OPENSSL_LIBRARIES} crypt z sctp dl pthread)
target_link_libraries(nr-cuup PRIVATE asn1_lte_rrc_hdrs asn1_nr_rrc_hdrs)
# nr-uesoftmodem is UE implementation
#######################################
@@ -2320,7 +2311,7 @@ add_executable(nr-uesoftmodem
target_link_libraries(nr-uesoftmodem PRIVATE
-Wl,--start-group
nr_rrc SECU_CN SECU_OSA UTIL HASHTABLE SCHED_RU_LIB SCHED_NR_UE_LIB
nr_rrc SECURITY UTIL HASHTABLE SCHED_RU_LIB SCHED_NR_UE_LIB
PHY_COMMON PHY_NR_COMMON PHY_NR_UE NR_L2_UE L2_UE_LTE_NR MAC_NR_COMMON NFAPI_COMMON_LIB NFAPI_LIB NFAPI_PNF_LIB
NFAPI_USER_LIB MISC_NFAPI_NR_LIB
ITTI ${ATLAS_LIBRARIES} LIB_5GNAS_GNB LIB_NAS_SIMUE ${NAS_SIM_LIB} SIMU SIMU_ETH
@@ -2464,7 +2455,7 @@ add_executable(nr_dlsim
${SHLIB_LOADER_SOURCES}
)
target_link_libraries(nr_dlsim PRIVATE
-Wl,--start-group UTIL SIMU SIMU_ETH PHY_COMMON PHY_NR_COMMON PHY_NR PHY_NR_UE SCHED_NR_LIB SCHED_NR_UE_LIB MAC_NR MAC_UE_NR MAC_NR_COMMON nr_rrc CONFIG_LIB L2_NR HASHTABLE x2ap SECU_CN ngap -lz -Wl,--end-group
-Wl,--start-group UTIL SIMU SIMU_ETH PHY_COMMON PHY_NR_COMMON PHY_NR PHY_NR_UE SCHED_NR_LIB SCHED_NR_UE_LIB MAC_NR MAC_UE_NR MAC_NR_COMMON nr_rrc CONFIG_LIB L2_NR HASHTABLE x2ap SECURITY ngap -lz -Wl,--end-group
m pthread ${ATLAS_LIBRARIES} ${T_LIB} ITTI ${OPENSSL_LIBRARIES} dl
)
target_link_libraries(nr_dlsim PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs)
@@ -2513,7 +2504,7 @@ if (ENABLE_LDPC_T1)
endif()
target_link_libraries(nr_ulsim PRIVATE
-Wl,--start-group UTIL SIMU SIMU_ETH PHY_COMMON PHY_NR_COMMON PHY_NR PHY_NR_UE SCHED_NR_LIB SCHED_NR_UE_LIB MAC_NR MAC_UE_NR MAC_NR_COMMON nr_rrc CONFIG_LIB L2_NR HASHTABLE x2ap SECU_CN ngap -lz -Wl,--end-group
-Wl,--start-group UTIL SIMU SIMU_ETH PHY_COMMON PHY_NR_COMMON PHY_NR PHY_NR_UE SCHED_NR_LIB SCHED_NR_UE_LIB MAC_NR MAC_UE_NR MAC_NR_COMMON nr_rrc CONFIG_LIB L2_NR HASHTABLE x2ap SECURITY ngap -lz -Wl,--end-group
m pthread ${ATLAS_LIBRARIES} ${T_LIB} ITTI ${OPENSSL_LIBRARIES} dl
)
target_link_libraries(nr_ulsim PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs)
@@ -2552,7 +2543,7 @@ foreach(myExe s1ap
${OPENAIR3_DIR}/TEST/test_${myExe}.c
)
target_link_libraries (test_${myExe}
-Wl,--start-group SECU_CN UTIL -Wl,--end-group m rt crypt ${CRYPTO_LIBRARIES} ${OPENSSL_LIBRARIES} CONFIG_LIB
-Wl,--start-group SECURITY UTIL -Wl,--end-group m rt crypt ${CRYPTO_LIBRARIES} ${OPENSSL_LIBRARIES} CONFIG_LIB
)
endforeach(myExe)
@@ -2573,7 +2564,7 @@ if (${T_TRACER})
ITTI lte_rrc nr_rrc s1ap x2ap m2ap m3ap f1ap
params_libconfig oai_usrpdevif oai_bladerfdevif oai_lmssdrdevif oai_iqplayer
oai_eth_transpro oai_mobipass coding HASHTABLE UTIL OMG_SUMO
SECU_OSA SECU_CN SCHED_LIB SCHED_NR_LIB SCHED_RU_LIB SCHED_UE_LIB SCHED_NR_UE_LIB default_sched remote_sched RAL
SECURITY SCHED_LIB SCHED_NR_LIB SCHED_RU_LIB SCHED_UE_LIB SCHED_NR_UE_LIB default_sched remote_sched RAL
NFAPI_COMMON_LIB NFAPI_LIB NFAPI_PNF_LIB NFAPI_VNF_LIB NFAPI_USER_LIB
PHY_COMMON PHY PHY_UE PHY_NR PHY_NR_COMMON PHY_NR_UE PHY_RU PHY_MEX
L2 L2_LTE L2_NR L2_LTE_NR L2_UE NR_L2_UE L2_UE_LTE_NR MAC_NR_COMMON MAC_NR MAC_UE_NR ngap
+1 -1
View File
@@ -49,7 +49,7 @@ adb_ue_2:
amarisoft_ue:
Host: amariue
InitScript: /root/NV18-06-2022/lteue-linux-2023-03-17/lteue /root/oaicicd/ran_sa_aw2s_asue/aw2s-multi-20897.cfg &
InitScript: /root/NV18-06-2022/lteue-linux-2023-03-17/lteue /root/oaicicd/ran_sa_aw2s_asue/aw2s-multi-20897-2x2.cfg &
TermScript: /root/NV18-06-2022/lteue-linux-2023-03-17/doc/ws.js 127.0.0.1:9002 '{"message":"quit"}'
amarisoft_ue_1:
Host: amariue
+6 -6
View File
@@ -42,7 +42,8 @@ IMAGE_REGISTRY_SERVICE_NAME = "image-registry.openshift-image-registry.svc"
NAMESPACE = "oaicicd-ran"
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"
def OC_login(cmd, ocUserName, ocPassword, ocProjectName):
if ocUserName == '' or ocPassword == '' or ocProjectName == '':
@@ -198,23 +199,22 @@ class Cluster:
HELP.GenericHelp(CONST.Version)
HELP.EPCSrvHelp(self.imageToPull)
sys.exit('Insufficient eNB Parameters')
lIpAddr = self.eNBIPAddress
self.testCase_id = HTML.testCase_id
cmd = cls_cmd.getConnection(lIpAddr)
succeeded = OC_login(cmd, self.OCUserName, self.OCPassword, self.OCProjectName)
cmd = cls_cmd.getConnection(self.eNBIPAddress)
succeeded = OC_login(cmd, self.OCUserName, self.OCPassword, CI_OC_RAN_NAMESPACE)
if not succeeded:
logging.error('\u001B[1m OC Cluster Login Failed\u001B[0m')
HTML.CreateHtmlTestRow('N/A', 'KO', CONST.OC_LOGIN_FAIL)
return False
ret = cmd.run(f'oc whoami -t | docker login -u oaicicd --password-stdin {self.OCRegistry}')
if ret.returncode != 0:
logging.error(f'\u001B[1m Unable to access OC project {ocProjectName}\u001B[0m')
logging.error(f'\u001B[1m Unable to access OC project {CI_OC_RAN_NAMESPACE}\u001B[0m')
OC_logout(cmd)
cmd.close()
HTML.CreateHtmlTestRow('N/A', 'KO', CONST.OC_LOGIN_FAIL)
return False
for image in self.imageToPull:
imagePrefix = f'{self.OCRegistry}{self.OCProjectName}'
imagePrefix = f'{self.OCRegistry}{CI_OC_RAN_NAMESPACE}'
imageTag = cls_containerize.ImageTagToUse(image, self.ranCommitID, self.ranBranch, self.ranAllowMerge)
ret = cmd.run(f'docker pull {imagePrefix}/{imageTag}')
if ret.returncode != 0:
+1 -1
View File
@@ -800,7 +800,7 @@ class Containerize():
logging.debug('Removing test images locally')
myCmd = cls_cmd.LocalCmd()
imageNames = ['oai-enb', 'oai-gnb', 'oai-lte-ue', 'oai-nr-ue', 'oai-lte-ru', 'oai-nr-cuup']
imageNames = ['oai-enb', 'oai-gnb', 'oai-lte-ue', 'oai-nr-ue', 'oai-lte-ru', 'oai-nr-cuup', 'oai-gnb-aw2s']
for image in imageNames:
imageTag = ImageTagToUse(image, self.ranCommitID, self.ranBranch, self.ranAllowMerge)
cmd = f'docker rmi oai-ci/{imageTag}'
+18 -3
View File
@@ -49,6 +49,7 @@ import concurrent.futures
#import our libs
import helpreadme as HELP
import constants as CONST
import cls_cluster as OC
import sshconnection
import cls_module_ue
@@ -231,7 +232,6 @@ class OaiCiTest():
[f.result() for f in futures]
HTML.CreateHtmlTestRowQueue('N/A', 'OK', messages)
def InitializeOAIUE(self,HTML,RAN,EPC,CONTAINERS):
if self.UEIPAddress == '' or self.UEUserName == '' or self.UEPassword == '' or self.UESourceCodePath == '':
HELP.GenericHelp(CONST.Version)
@@ -995,7 +995,9 @@ class OaiCiTest():
cn_target_ip = result.group('trf_ip_addr')
SSH.close()
cn_iperf_prefix = "docker exec prod-trf-gen" # -w /iperf-2.0.13 necessary?
else: # ltebox, sabox
if (re.match('OC-OAI-CN5G', EPC.Type, re.IGNORECASE)):
cn_target_ip = "172.21.6.102"
else: # lteboix, sabox
cn_target_ip = "192.172.0.1"
cn_iperf_prefix = ""
@@ -1077,6 +1079,20 @@ class OaiCiTest():
self.Iperf_analyzeV2BIDIR(lock, ue.getHost(), ue.getName(), statusQueue, server_filename, client_filename)
elif self.iperf_direction == "IPERF3":
cmd = cls_cmd.getConnection(ue.getHost())
cmd.run(f'rm /tmp/{server_filename}', reportNonZero=False)
port = f'{5002+idx}'
cmd.run(f'{ue.getCmdPrefix()} iperf3 -c {cn_target_ip} -p {port} {iperf_opt} --get-server-output &> /tmp/{server_filename}', timeout=iperf_time*1.5)
cmd.copyin(f'/tmp/{server_filename}', server_filename)
cmd.close()
if udpIperf:
self.Iperf_analyzeV2Server(lock, ue.getIP(), ue.getName(), statusQueue, iperf_opt, server_filename, 1)
else:
cmd = cls_cmd.getConnection(EPC.IPAddress)
self.Iperf_analyzeV2TCPOutput(lock, ue.getIP(), ue.getName(), statusQueue, iperf_opt, EPC, cmd, f'/tmp/{server_filename}')
cmd.close()
else :
raise Exception("Incorrect or missing IPERF direction in XML")
@@ -1216,7 +1232,6 @@ class OaiCiTest():
#result = re.search('iperf version 2.0.10', str(iperfStdout.strip()))
#if result is not None:
# dummyIperfVersion = '2.0.10'
multi_jobs = []
ue_num = len(ues)
i = 0
@@ -200,7 +200,7 @@ MACRLCs = (
pusch_TargetSNRx10 = 200;
pucch_TargetSNRx10 = 200;
ulsch_max_frame_inactivity = 10;
ul_max_mcs = 15;
ul_max_mcs = 28;
}
);
+6 -7
View File
@@ -75,7 +75,6 @@ class EPCManagement():
self.OCRegistry = "default-route-openshift-image-registry.apps.oai.cs.eurecom.fr/"
self.OCUserName = ''
self.OCPassword = ''
self.OCProjectName = ''
self.imageToPull = ''
self.eNBSourceCodePath = ''
@@ -240,9 +239,9 @@ class EPCManagement():
HTML.CreateHtmlTestRow(self.Type, 'OK', CONST.ALL_PROCESSES_OK)
def Initialize5GCN(self, HTML):
if self.IPAddress == '' or self.UserName == '' or self.Password == '' or self.SourceCodePath == '' or self.Type == '':
if self.IPAddress == '' or self.UserName == '' or self.Password == '' or self.Type == '':
HELP.GenericHelp(CONST.Version)
HELP.EPCSrvHelp(self.IPAddress, self.UserName, self.Password, self.SourceCodePath, self.Type)
HELP.EPCSrvHelp(self.IPAddress, self.UserName, self.Password, self.Type)
sys.exit('Insufficient EPC Parameters')
mySSH = cls_cmd.getConnection(self.IPAddress)
html_cell = ''
@@ -299,8 +298,8 @@ class EPCManagement():
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 = self.SourceCodePath
succeeded = OC.OC_login(mySSH, self.OCUserName, self.OCPassword, self.OCProjectName)
lSourcePath = "/opt/oai-cn5g-fed-develop-2023-04-28-20897"
succeeded = OC.OC_login(mySSH, self.OCUserName, self.OCPassword, OC.CI_OC_CORE_NAMESPACE)
if not succeeded:
logging.error('\u001B[1m OC Cluster Login Failed\u001B[0m')
HTML.CreateHtmlTestRow('N/A', 'KO', CONST.OC_LOGIN_FAIL)
@@ -599,7 +598,7 @@ class EPCManagement():
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, self.OCProjectName)
succeeded = OC.OC_login(mySSH, self.OCUserName, self.OCPassword, OC.CI_OC_CORE_NAMESPACE)
if not succeeded:
logging.error('\u001B[1m OC Cluster Login Failed\u001B[0m')
HTML.CreateHtmlTestRow('N/A', 'KO', CONST.OC_LOGIN_FAIL)
@@ -618,7 +617,7 @@ class EPCManagement():
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('No resources found in oaicicd-ran namespace.', ret.stdout)
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'
@@ -30,8 +30,14 @@
001000
020000
002000
002001
002002
002003
002004
002005
000100
000010
000020
000200
003000
004000
@@ -43,6 +49,7 @@
<testCase id="010000">
<class>Pull_Cluster_Image</class>
<desc>Pull Images from Cluster</desc>
<oc_project>oaicicd-ran</oc_project>
<images_to_pull>oai-gnb-aw2s</images_to_pull>
</testCase>
@@ -60,7 +67,7 @@
<id>amarisoft_ue</id>
</testCase>
<testCase id="002000">
<testCase id="002001">
<class>Attach_UE</class>
<desc>Attach UE</desc>
<id>amarisoft_ue_1</id>
@@ -72,28 +79,68 @@
<id>amarisoft_ue_2</id>
</testCase>
<testCase id="002003">
<class>Attach_UE</class>
<desc>Attach UE</desc>
<id>amarisoft_ue_3</id>
</testCase>
<testCase id="002004">
<class>Attach_UE</class>
<desc>Attach UE</desc>
<id>amarisoft_ue_4</id>
</testCase>
<testCase id="002005">
<class>Attach_UE</class>
<desc>Attach UE</desc>
<id>amarisoft_ue_5</id>
</testCase>
<testCase id="000010">
<class>Iperf</class>
<desc>iperf (DL/20Mbps/UDP)(30 sec)(multi-ue profile)</desc>
<iperf_args>-u -b 60M -t 30 -i 1 -R</iperf_args>
<direction>IPERF3</direction>
<id>amarisoft_ue_1 amarisoft_ue_2 amarisoft_ue_3</id>
<iperf_packetloss_threshold>25</iperf_packetloss_threshold>
<iperf_bitrate_threshold>80</iperf_bitrate_threshold>
<iperf_profile>balanced</iperf_profile>
</testCase>
<testCase id="000020">
<class>Iperf</class>
<desc>iperf (UL/5Mbps/UDP)(30 sec)(multi-ue profile)</desc>
<iperf_args>-u -b 15M -t 30 -i 1 </iperf_args>
<direction>IPERF3</direction>
<id>amarisoft_ue_1 amarisoft_ue_2 amarisoft_ue_3</id>
<iperf_packetloss_threshold>25</iperf_packetloss_threshold>
<iperf_bitrate_threshold>80</iperf_bitrate_threshold>
<iperf_profile>balanced</iperf_profile>
</testCase>
<testCase id="000100">
<class>Ping</class>
<desc>Ping: 20pings in 20sec</desc>
<id>amarisoft_ue_1 amarisoft_ue_2</id>
<desc>Ping: 20pings in 20sec, multi-ue</desc>
<id>amarisoft_ue_1 amarisoft_ue_2 amarisoft_ue_3 amarisoft_ue_4 amarisoft_ue_5</id>
<ping_args>-c 20</ping_args>
<ping_packetloss_threshold>1</ping_packetloss_threshold>
<ping_rttavg_threshold>15</ping_rttavg_threshold>
<ping_rttavg_threshold>25</ping_rttavg_threshold>
</testCase>
<testCase id="000200">
<class>Ping</class>
<desc>Ping: 100pings in 20sec</desc>
<id>amarisoft_ue_1 amarisoft_ue_2</id>
<desc>Ping: 100pings in 20sec, multi-ue</desc>
<id>amarisoft_ue_1 amarisoft_ue_2 amarisoft_ue_3 amarisoft_ue_4 amarisoft_ue_5</id>
<ping_args>-c 100 -i 0.2</ping_args>
<ping_packetloss_threshold>1</ping_packetloss_threshold>
<ping_rttavg_threshold>15</ping_rttavg_threshold>
<ping_rttavg_threshold>30</ping_rttavg_threshold>
</testCase>
<testCase id="003000">
<class>Detach_UE</class>
<desc>Detach UE</desc>
<id>amarisoft_ue_1 amarisoft_ue_2</id>
<id>amarisoft_ue_1 amarisoft_ue_2 amarisoft_ue_3 amarisoft_ue_4 amarisoft_ue_5</id>
</testCase>
<testCase id="004000">
@@ -119,4 +166,3 @@
</testCase>
</testCaseList>
@@ -0,0 +1,46 @@
<!--
Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The OpenAirInterface Software Alliance licenses this file to You under
the OAI Public License, Version 1.1 (the "License"); you may not use this file
except in compliance with the License.
You may obtain a copy of the License at
http://www.openairinterface.org/?page_id=698
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
For more information about the OpenAirInterface (OAI) Software Alliance:
contact@openairinterface.org
-->
<testCaseList>
<htmlTabRef>test-aw2s-cleanup</htmlTabRef>
<htmlTabName>CleanUp AW2S ASUE</htmlTabName>
<htmlTabIcon>trash</htmlTabIcon>
<TestCaseRequestedList>
111111
222222
</TestCaseRequestedList>
<TestCaseExclusionList></TestCaseExclusionList>
<testCase id="111111">
<class>Clean_Test_Server_Images</class>
<desc>Clean Test Images on Test Server</desc>
<test_svr_id>0</test_svr_id>
</testCase>
<testCase id="222222">
<class>Terminate_UE</class>
<desc>Terminate UE</desc>
<id>amarisoft_ue</id>
</testCase>
</testCaseList>
+2 -2
View File
@@ -21,14 +21,14 @@ In this tutorial we describe how to configure and run a 5G end-to-end setup with
Minimum hardware requirements:
- Laptop/Desktop/Server for OAI CN5G and OAI gNB
- Operating System: [Ubuntu 22.04 LTS](https://releases.ubuntu.com/22.04/ubuntu-22.04.1-desktop-amd64.iso)
- Operating System: [Ubuntu 22.04 LTS](https://releases.ubuntu.com/22.04/ubuntu-22.04.2-desktop-amd64.iso)
- CPU: 8 cores x86_64 @ 3.5 GHz
- RAM: 32 GB
- Laptop for UE
- Operating System: Microsoft Windows 10 x64
- CPU: 4 cores x86_64
- RAM: 8 GB
- Windows driver for Quectel MUST be equal or higher than version **2.2.4**
- Windows driver for Quectel MUST be equal or higher than version **2.4.6**
- [USRP B210](https://www.ettus.com/all-products/ub210-kit/), [USRP N300](https://www.ettus.com/all-products/USRP-N300/) or [USRP X300](https://www.ettus.com/all-products/x300-kit/)
- Please identify the network interface(s) on which the USRP is connected and update the gNB configuration file
- Quectel RM500Q
+1 -1
View File
@@ -21,7 +21,7 @@ In this tutorial we describe how to configure and run a 5G end-to-end setup with
Minimum hardware requirements:
- Laptop/Desktop/Server for OAI CN5G and OAI gNB
- Operating System: [Ubuntu 22.04 LTS](https://releases.ubuntu.com/22.04/ubuntu-22.04.1-desktop-amd64.iso)
- Operating System: [Ubuntu 22.04 LTS](https://releases.ubuntu.com/22.04/ubuntu-22.04.2-desktop-amd64.iso)
- CPU: 8 cores x86_64 @ 3.5 GHz
- RAM: 32 GB
+4 -4
View File
@@ -21,11 +21,11 @@ In this tutorial we describe how to configure and run a 5G end-to-end setup with
Minimum hardware requirements:
- Laptop/Desktop/Server for OAI CN5G and OAI gNB
- Operating System: [Ubuntu 22.04 LTS](https://releases.ubuntu.com/22.04/ubuntu-22.04.1-desktop-amd64.iso)
- Operating System: [Ubuntu 22.04 LTS](https://releases.ubuntu.com/22.04/ubuntu-22.04.2-desktop-amd64.iso)
- CPU: 8 cores x86_64 @ 3.5 GHz
- RAM: 32 GB
- Laptop for UE
- Operating System: [Ubuntu 22.04 LTS](https://releases.ubuntu.com/22.04/ubuntu-22.04.1-desktop-amd64.iso)
- Operating System: [Ubuntu 22.04 LTS](https://releases.ubuntu.com/22.04/ubuntu-22.04.2-desktop-amd64.iso)
- CPU: 8 cores x86_64 @ 3.5 GHz
- RAM: 8 GB
- [USRP B210](https://www.ettus.com/all-products/ub210-kit/), [USRP N300](https://www.ettus.com/all-products/USRP-N300/) or [USRP X300](https://www.ettus.com/all-products/x300-kit/)
@@ -155,7 +155,7 @@ Run OAI nrUE
cd ~/openairinterface5g
source oaienv
cd cmake_targets/ran_build/build
sudo ./nr-uesoftmodem -r 106 --numerology 1 --band 78 -C 3619200000 --nokrnmod --ue-fo-compensation --sa -E --uicc0.imsi 001010000000001
sudo ./nr-uesoftmodem -r 106 --numerology 1 --band 78 -C 3619200000 --ue-fo-compensation --sa -E --uicc0.imsi 001010000000001
```
## 5.2 Testing OAI nrUE with RFsimulator
@@ -168,7 +168,7 @@ Run OAI nrUE with RFsimulator
cd ~/openairinterface5g
source oaienv
cd cmake_targets/ran_build/build
sudo RFSIMULATOR=127.0.0.1 ./nr-uesoftmodem -r 106 --numerology 1 --band 78 -C 3619200000 --nokrnmod --rfsim --sa --uicc0.imsi 001010000000001
sudo RFSIMULATOR=127.0.0.1 ./nr-uesoftmodem -r 106 --numerology 1 --band 78 -C 3619200000 --rfsim --sa --uicc0.imsi 001010000000001
```
### 5.2.1 Ping test
-1
View File
@@ -36,7 +36,6 @@ There is some general information in the [OpenAirInterface Gitlab Wiki](https://
* (5G) Using SDAP and custom DRBs
* IF setups and arbitrary frequencies
* MIMO
- [How to run a 5G-SA setup](./TESTING_5GSA_setup.md)
- [How to run a 5G-NSA setup](./TESTING_GNB_W_COTS_UE.md)
- [How to run a 4G setup using L1 simulator](./L1SIM.md) _Note: we recommend the RFsimulator_
- [How to use the L2 simulator](./L2NFAPI.md)
-1
View File
@@ -31,7 +31,6 @@ rx_func_implem[rx_func]
--> handle_nr_ulsch
subgraph gNB_dlsch_ulsch_scheduler
run_pdcp
--> nr_rrc_trigger
--> schedule_xxxx
end
handle_nr_ulsch --> gNB_dlsch_ulsch_scheduler
-230
View File
@@ -1,230 +0,0 @@
<table style="border-collapse: collapse; border: none;">
<tr style="border-collapse: collapse; border: none;">
<td style="border-collapse: collapse; border: none;">
<a href="http://www.openairinterface.org/">
<img src="./images/oai_final_logo.png" alt="" border=3 height=50 width=150>
</img>
</a>
</td>
<td style="border-collapse: collapse; border: none; vertical-align: center;">
<b><font size = "5">OAI 5G SA tutorial</font></b>
</td>
</tr>
</table>
**Table of Contents**
[[_TOC_]]
In the following tutorial we describe how to deploy configure and test the two SA OAI setups:
- SA setup with OAI gNB and COTS UE
- SA setup with OAI gNB and OAI UE
The operating system and hardware requirements to support OAI 5G NR are described [here](https://gitlab.eurecom.fr/oai/openairinterface5g/-/wikis/5g-nr-development-and-setup).
# 1. SA setup with COTS UE
At the moment of writing this document interoperability with the following COTS UE devices is being tested:
- [Quectel RM500Q-GL](https://www.quectel.com/product/5g-rm500q-gl/)
- [Simcom SIMCOM8200EA](https://www.simcom.com/product/SIM8200EA_M2.html)
- Huawei Mate 30 Pro
- Oneplus 8
- Google Pixel 5
End-to-end control plane signaling to achieve a 5G SA connection, UE registration and PDU session establishment with the CN, as well as some basic user-plane traffic tests have been validated so far using SIMCOM/Quectel modules and Huawei Mate 30 pro. In terms of interoperability with different 5G Core Networks, so far this setup has been tested with:
- [OAI CN](https://openairinterface.org/oai-5g-core-network-project/)
- Nokia SA Box
- [Free CN](https://www.free5gc.org/)
## 1.1 gNB build and configuration
To get the code and build the gNB executable:
### Build gNB
```bash
git clone https://gitlab.eurecom.fr/oai/openairinterface5g.git
git checkout develop
cd openairinterface5g/
source oaienv
cd cmake_targets/
./build_oai -I -w USRP #For OAI first time installation only to install software dependencies
./build_oai --gNB -w USRP
```
A reference configuration file for the **monolithic** gNB is provided [here](https://gitlab.eurecom.fr/oai/openairinterface5g/-/blob/develop/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.usrpb210.conf).
In the following, we highlight the fields of the file that have to be configured according to the configuration and interfaces of the Core Network. First, the PLMN section has to be filled with the proper values that match the configuration of the AMF and the UE USIM.
```bash
// Tracking area code, 0x0000 and 0xfffe are reserved values
tracking_area_code = 1;
plmn_list = ({ mcc = 208; mnc = 99; mnc_length = 2; snssaiList = ({ sst = 1 }) });
```
Then, the source and destination IP interfaces for the communication with
the Core Network also need to be set as shown below.
```bash
////////// AMF parameters:
amf_ip_address = ( { ipv4 = "192.168.70.132";
ipv6 = "192:168:30::17";
active = "yes";
preference = "ipv4";
}
);
NETWORK_INTERFACES :
{
GNB_INTERFACE_NAME_FOR_NG_AMF = "demo-oai";
GNB_IPV4_ADDRESS_FOR_NG_AMF = "192.168.70.129/24";
GNB_INTERFACE_NAME_FOR_NGU = "demo-oai";
GNB_IPV4_ADDRESS_FOR_NGU = "192.168.70.129/24";
GNB_PORT_FOR_S1U = 2152; # Spec 2152
};
```
In the first part (*amf_ip_address*) we specify the IP of the AMF and in the second part (*NETWORK_INTERFACES*) we specify the gNB local interface with AMF (N2 interface) and the UPF (N3 interface).
**CAUTION:** the `192.168.70.132` AMF IF address is the OAI-CN5G `AMF` Container IP address. You certainly will need to do some networking manipulations for the `gNB` server to be able to see this AMF container.
Please read [CN5G tutorial for more details](https://gitlab.eurecom.fr/oai/cn5g/oai-cn5g-fed/-/blob/master/README.md).
### gNB configuration in F1 (CU/DU split mode)
For the configuration of the gNB in CU and DU blocks, the following sample configuration files are provided for the [CU](https://gitlab.eurecom.fr/oai/openairinterface5g/-/blob/develop/targets/PROJECTS/GENERIC-NR-5GC/CONF/cu_gnb.conf) and the [DU](https://gitlab.eurecom.fr/oai/openairinterface5g/-/blob/develop/targets/PROJECTS/GENERIC-NR-5GC/CONF/du_gnb.conf) entities respectively. These configuration files have to be updated with the IP addresses of the CU and the DU over the F1 interface. For example, in the following section from the DU configuration file, *local_n_address* corresponds to the DU address and *remote_n_address* corresponds to the CU address:
```bash
MACRLCs = (
{
num_cc = 1;
tr_s_preference = "local_L1";
tr_n_preference = "f1";
local_n_if_name = "lo";
local_n_address = "127.0.0.3";
remote_n_address = "127.0.0.4";
local_n_portc = 601;
local_n_portd = 2152;
remote_n_portc = 600;
remote_n_portd = 2152;
}
);
```
At the point of writing this document the control-plane exchanges between the CU and the DU over *F1-C* interface, as well as some IP traffic tests over *F1-U* have been validated using the OAI gNB/nrUE in RFSIMULATOR mode.
### gNB configuration with F1 and E1
Please refer to [E1-design](E1-design) for more information.
## 1.2 OAI 5G Core Network installation and configuration
The instructions for the installation of OAI CN components (AMF, SMF, NRF, UPF) using `docker-compose` can be found [here](https://gitlab.eurecom.fr/oai/cn5g/oai-cn5g-fed/-/blob/master/README.md).
## 1.3 Execution of SA scenario
After having configured the gNB, we can start the individual components in the following sequence:
- Launch 5G Core Network
- Launch gNB
- Launch COTS UE (disable airplane mode)
The execution command to start the gNB (in monolithic mode) is the following:
```bash
cd cmake_targets/ran_build/build
sudo ./nr-softmodem -E --sa -O ../../../targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.usrpb210.conf
```
# 2. SA Setup with OAI NR UE Softmodem
The SA setup with OAI UE has been validated with **RFSIMULATOR**. Both control plane and user plane for the successful UE registration and PDU Session establishment has been verified with OAI and Nokia SA Box CNs.
In the following, we provide the instructions on how to build, configure and execute this SA setup.
As another option, if you do not want to build anything and instead deploy the OAI RAN (RFSIMULATOR) and Core Network components directly using docker images and docker-compose, please have a look at [this tutorial](https://gitlab.eurecom.fr/oai/openairinterface5g/-/blob/develop/ci-scripts/yaml_files/5g_rfsimulator/README.md).
### NAS configuration for the OAI UE
The NAS configuration parameters of the OAI UE can be set as input parameters, configuration file or can be hardcoded. More specifically:
- SUCI (*Subscription Concealed Identifier*)
- USIM_API_K and OPc keys
- NSSAI (*Network Slice Assistance Information*)
- DNN (*Data Network Name*)
Below is a sample configuration file that can be parsed through the execution command ([section 2.3](#23-execution-of-sa-scenario)).
```bash
uicc0 = {
imsi = "208990000007487";
key = "fec86ba6eb707ed08905757b1bb44b8f";
opc= "C42449363BBAD02B66D16BC975D77CC1";
dnn= "oai";
nssai_sst=1;
nssai_sd=1;
}
```
For interoperability with OAI or other CNs, it should be ensured that the configuration of the aforementioned parameters match the configuration of the corresponding subscribed user at the core network.
## 2.1 Build and configuration
To build the gNB and OAI UE executables:
```bash
cd cmake_targets
# Note: For OAI first time installation please install software dependencies as described in 1.1.
./build_oai --gNB --nrUE -w SIMU
```
The gNB configuration can be performed according to what is described in [section 1.1](#11--gnb-build-and-configuration), using the same reference configuration file as with the RF scenario.
## 2.2 OAI 5G Core Network installation and configuration
The instructions for the installation of OAI CN components (AMF, SMF, NRF, UPF) using `docker-compose` can be found [here](https://gitlab.eurecom.fr/oai/cn5g/oai-cn5g-fed/-/blob/master/README.md).
## 2.3 Execution of SA scenario
The order of starting the different components should be the same as the one described in [section 1.3](#13--execution-of-sa-scenario).
the gNB can be launched in 2 modes:
- To launch the gNB in `monolithic` mode:
```bash
sudo RFSIMULATOR=server ./nr-softmodem --rfsim --sa \
-O ../../../targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.usrpb210.conf
```
- To launch the gNB in `CU/DU split` mode:
1. Launch the CU component:
```bash
sudo RFSIMULATOR=server ./nr-softmodem --rfsim --sa \
-O ../../../ci-scripts/conf_files/gNB_SA_CU.conf
```
2. Launch the DU component:
```bash
sudo RFSIMULATOR=server ./nr-softmodem --rfsim --sa \
-O ../../../ci-scripts/conf_files/gNB_SA_DU.conf
```
- To launch the OAI UE (valid in `monolithic` gNB and `CU/DU split` gNB):
```bash
sudo RFSIMULATOR=127.0.0.1 ./nr-uesoftmodem -r 106 --numerology 1 --band 78 -C 3619200000 \
--rfsim --sa -O <PATH_TO_UE_CONF_FILE>
```
If you get the following error:
```bash
Assertion (k2 >= ((5))) failed!
In get_k2() /home/mir/workspace/openairinterface5g/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c:147
Slot offset K2 (2) cannot be less than DURATION_RX_TO_TX (5). K2 set according to min_rxtxtime in config file.
```
Add the following parameter (i.e., min_rxtxtime) in the gNB configuration file, just after nr_cellid.
```bash
nr_cellid = 12345678L;
min_rxtxtime=6;
```
or --gNBs.[0].min_rxtxtime 6 to the gNB command line
The IP address at the execution command of the OAI UE corresponds to the target IP of the gNB host that the RFSIMULATOR at the UE will connect to. In the above example, we assume that the gNB and UE are running on the same host so the specified address (127.0.0.1) is the one of the loopback interface.
+1 -1
View File
@@ -84,7 +84,7 @@ int nr_rlc_get_available_tx_space(const rnti_t rntiP, const logical_chan_id_t ch
return 0;
}
void rrc_gNB_generate_dedicatedRRCReconfiguration(const protocol_ctxt_t *const ctxt_pP, rrc_gNB_ue_context_t *ue_context_pP, NR_CellGroupConfig_t *cell_groupConfig_from_DU)
void rrc_gNB_generate_dedicatedRRCReconfiguration(const protocol_ctxt_t *const ctxt_pP, rrc_gNB_ue_context_t *ue_context_pP)
{
abort();
}
+31 -14
View File
@@ -1829,18 +1829,30 @@ void stop_RU(int nb_ru) {
/* --------------------------------------------------------*/
/* from here function to use configuration module */
static void NRRCconfig_RU(void) {
int i = 0, j = 0;
static void NRRCconfig_RU(void)
{
paramdef_t RUParams[] = RUPARAMS_DESC;
paramlist_def_t RUParamList = {CONFIG_STRING_RU_LIST,NULL,0};
config_getlist( &RUParamList, RUParams, sizeof(RUParams)/sizeof(paramdef_t), NULL);
config_getlist(&RUParamList, RUParams, sizeof(RUParams)/sizeof(paramdef_t), NULL);
if ( RUParamList.numelt > 0) {
paramdef_t GNBSParams[] = GNBSPARAMS_DESC;
paramdef_t GNBParams[] = GNBPARAMS_DESC;
paramlist_def_t GNBParamList = {GNB_CONFIG_STRING_GNB_LIST, NULL, 0};
config_get(GNBSParams, sizeof(GNBSParams) / sizeof(paramdef_t), NULL);
int num_gnbs = GNBSParams[GNB_ACTIVE_GNBS_IDX].numelt;
AssertFatal(num_gnbs > 0, "Failed to parse config file no gnbs %s \n", GNB_CONFIG_STRING_ACTIVE_GNBS);
config_getlist(&GNBParamList, GNBParams, sizeof(GNBParams) / sizeof(paramdef_t), NULL);
int N1 = *GNBParamList.paramarray[0][GNB_PDSCH_ANTENNAPORTS_N1_IDX].iptr;
int N2 = *GNBParamList.paramarray[0][GNB_PDSCH_ANTENNAPORTS_N2_IDX].iptr;
int XP = *GNBParamList.paramarray[0][GNB_PDSCH_ANTENNAPORTS_XP_IDX].iptr;
int num_logical_antennas = N1 * N2 * XP;
if (RUParamList.numelt > 0) {
RC.ru = (RU_t **)malloc(RC.nb_RU*sizeof(RU_t *));
RC.ru_mask=(1<<NB_RU) - 1;
RC.ru_mask = (1 << NB_RU) - 1;
printf("Set RU mask to %lx\n",RC.ru_mask);
for (j = 0; j < RC.nb_RU; j++) {
for (int j = 0; j < RC.nb_RU; j++) {
RC.ru[j] = (RU_t *)malloc(sizeof(RU_t));
memset((void *)RC.ru[j],0,sizeof(RU_t));
RC.ru[j]->idx = j;
@@ -1849,12 +1861,13 @@ static void NRRCconfig_RU(void) {
printf("Creating RC.ru[%d]:%p\n", j, RC.ru[j]);
RC.ru[j]->if_timing = synch_to_ext_device;
if (RC.nb_nr_L1_inst >0)
if (RC.nb_nr_L1_inst > 0)
RC.ru[j]->num_gNB = RUParamList.paramarray[j][RU_ENB_LIST_IDX].numelt;
else
RC.ru[j]->num_gNB = 0;
for (i=0; i<RC.ru[j]->num_gNB; i++) RC.ru[j]->gNB_list[i] = RC.gNB[RUParamList.paramarray[j][RU_ENB_LIST_IDX].iptr[i]];
for (int i = 0; i < RC.ru[j]->num_gNB; i++)
RC.ru[j]->gNB_list[i] = RC.gNB[RUParamList.paramarray[j][RU_ENB_LIST_IDX].iptr[i]];
if (config_isparamset(RUParamList.paramarray[j], RU_SDR_ADDRS)) {
RC.ru[j]->openair0_cfg.sdr_addrs = strdup(*(RUParamList.paramarray[j][RU_SDR_ADDRS].strptr));
@@ -1909,7 +1922,7 @@ static void NRRCconfig_RU(void) {
RC.ru[j]->openair0_cfg.tune_offset = get_softmodem_params()->tune_offset;
if (strcmp(*(RUParamList.paramarray[j][RU_LOCAL_RF_IDX].strptr), "yes") == 0) {
if ( !(config_isparamset(RUParamList.paramarray[j],RU_LOCAL_IF_NAME_IDX)) ) {
if (!(config_isparamset(RUParamList.paramarray[j],RU_LOCAL_IF_NAME_IDX))) {
RC.ru[j]->if_south = LOCAL_RF;
RC.ru[j]->function = gNodeB_3GPP;
printf("Setting function for RU %d to gNodeB_3GPP\n",j);
@@ -1983,6 +1996,8 @@ static void NRRCconfig_RU(void) {
} /* strcmp(local_rf, "yes") != 0 */
RC.ru[j]->nb_tx = *(RUParamList.paramarray[j][RU_NB_TX_IDX].uptr);
AssertFatal(RC.ru[j]->nb_tx >= num_logical_antennas,
"Number of logical antenna ports (set in config file with pdsch_AntennaPorts) cannot be larger than physical antennas (nb_tx)\n");
RC.ru[j]->nb_rx = *(RUParamList.paramarray[j][RU_NB_RX_IDX].uptr);
RC.ru[j]->att_tx = *(RUParamList.paramarray[j][RU_ATT_TX_IDX].uptr);
RC.ru[j]->att_rx = *(RUParamList.paramarray[j][RU_ATT_RX_IDX].uptr);
@@ -1991,7 +2006,8 @@ static void NRRCconfig_RU(void) {
RC.ru[j]->do_precoding = *(RUParamList.paramarray[j][RU_DO_PRECODING].iptr);
RC.ru[j]->sl_ahead = *(RUParamList.paramarray[j][RU_SL_AHEAD].iptr);
RC.ru[j]->num_bands = RUParamList.paramarray[j][RU_BAND_LIST_IDX].numelt;
for (i=0; i<RC.ru[j]->num_bands; i++) RC.ru[j]->band[i] = RUParamList.paramarray[j][RU_BAND_LIST_IDX].iptr[i];
for (int i = 0; i < RC.ru[j]->num_bands; i++)
RC.ru[j]->band[i] = RUParamList.paramarray[j][RU_BAND_LIST_IDX].iptr[i];
RC.ru[j]->openair0_cfg.nr_flag = *(RUParamList.paramarray[j][RU_NR_FLAG].iptr);
RC.ru[j]->openair0_cfg.nr_band = RC.ru[j]->band[0];
RC.ru[j]->openair0_cfg.nr_scs_for_raster = *(RUParamList.paramarray[j][RU_NR_SCS_FOR_RASTER].iptr);
@@ -2003,14 +2019,15 @@ static void NRRCconfig_RU(void) {
RC.ru[j]->ru_thread_core = *(RUParamList.paramarray[j][RU_RU_THREAD_CORE].iptr);
printf("[RU %d] Setting half-slot parallelization to %d\n",j,RC.ru[j]->half_slot_parallelization);
AssertFatal(RC.ru[j]->num_tpcores <= RUParamList.paramarray[j][RU_TP_CORES].numelt, "Number of TP cores should be <=16\n");
for (i=0; i<RC.ru[j]->num_tpcores; i++) RC.ru[j]->tpcores[i] = RUParamList.paramarray[j][RU_TP_CORES].iptr[i];
for (int i = 0; i < RC.ru[j]->num_tpcores; i++)
RC.ru[j]->tpcores[i] = RUParamList.paramarray[j][RU_TP_CORES].iptr[i];
if (config_isparamset(RUParamList.paramarray[j], RU_BF_WEIGHTS_LIST_IDX)) {
RC.ru[j]->nb_bfw = RUParamList.paramarray[j][RU_BF_WEIGHTS_LIST_IDX].numelt;
for (i=0; i<RC.ru[j]->num_gNB; i++) {
for (int i = 0; i < RC.ru[j]->num_gNB; i++) {
RC.ru[j]->bw_list[i] = (int32_t *)malloc16_clear((RC.ru[j]->nb_bfw)*sizeof(int32_t));
for (int b=0; b<RC.ru[j]->nb_bfw; b++) RC.ru[j]->bw_list[i][b] = RUParamList.paramarray[j][RU_BF_WEIGHTS_LIST_IDX].iptr[b];
for (int b = 0; b < RC.ru[j]->nb_bfw; b++)
RC.ru[j]->bw_list[i][b] = RUParamList.paramarray[j][RU_BF_WEIGHTS_LIST_IDX].iptr[b];
}
}
}// j=0..num_rus
+7 -18
View File
@@ -734,16 +734,6 @@ void syncInFrame(PHY_VARS_NR_UE *UE, openair0_timestamp *timestamp) {
}
}
int computeSamplesShift(PHY_VARS_NR_UE *UE) {
int samples_shift = -(UE->rx_offset>>1);
if (samples_shift != 0) {
LOG_I(NR_PHY,"Adjusting frame in time by %i samples\n", samples_shift);
UE->rx_offset = 0; // reset so that it is not applied falsely in case of SSB being only in every second frame
UE->max_pos_fil += samples_shift << 15; // reset IIR filter when sample shift is applied
}
return samples_shift;
}
static inline int get_firstSymSamp(uint16_t slot, NR_DL_FRAME_PARMS *fp) {
if (fp->numerology_index == 0)
return fp->nb_prefix_samples0 + fp->ofdm_symbol_size;
@@ -904,14 +894,13 @@ void *UE_thread(void *arg) {
int readBlockSize, writeBlockSize;
if (slot_nr<(nb_slot_frame - 1)) {
readBlockSize=get_readBlockSize(slot_nr, &UE->frame_parms);
writeBlockSize=UE->frame_parms.get_samples_per_slot((slot_nr + DURATION_RX_TO_TX) % nb_slot_frame, &UE->frame_parms);
} else {
UE->rx_offset_diff = computeSamplesShift(UE);
readBlockSize=get_readBlockSize(slot_nr, &UE->frame_parms) -
UE->rx_offset_diff;
writeBlockSize=UE->frame_parms.get_samples_per_slot((slot_nr + DURATION_RX_TO_TX) % nb_slot_frame, &UE->frame_parms)- UE->rx_offset_diff;
readBlockSize=get_readBlockSize(slot_nr, &UE->frame_parms);
writeBlockSize=UE->frame_parms.get_samples_per_slot((slot_nr + DURATION_RX_TO_TX) % nb_slot_frame, &UE->frame_parms);
if (UE->apply_timing_offset && (slot_nr == nb_slot_frame-1)) {
const int sampShift = -(UE->rx_offset>>1);
readBlockSize -= sampShift;
writeBlockSize -= sampShift;
UE->apply_timing_offset = false;
}
AssertFatal(readBlockSize ==
@@ -94,6 +94,10 @@ void nr_adjust_synch_ue(NR_DL_FRAME_PARMS *frame_parms,
else
ue->rx_offset = diff;
const int sample_shift = -(ue->rx_offset>>1);
// reset IIR filter for next offset calculation
ue->max_pos_fil += sample_shift << 15;
if(abs(diff)<5)
count_max_pos_ok ++;
else
@@ -284,7 +284,7 @@ void nr_processDLSegment(void* arg) {
if (no_iteration_ldpc > dlsch->max_ldpc_iterations)
no_iteration_ldpc = dlsch->max_ldpc_iterations;
} else {
LOG_I(PHY,"%d.%d CRC NOT OK\n",rdata->proc->frame_rx,rdata->proc->nr_slot_rx);
LOG_D(PHY,"%d.%d CRC NOT OK\n",rdata->proc->frame_rx,rdata->proc->nr_slot_rx);
no_iteration_ldpc = dlsch->max_ldpc_iterations + 1;
}
+1 -1
View File
@@ -450,7 +450,7 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, int frame, uint8_t
memcpy(prach, prach+(dftlen<<1), (Ncp<<2));
// here we have | Prefix | Prach | Prach |
prach_len = (dftlen*2)+Ncp;
} else if (prach_fmt_id == 5) { // 4xdftlen
} else if (prach_fmt_id == 5 || prach_fmt_id == 10) { // 4xdftlen
// here we have | empty | Prach | empty | empty | empty |
memcpy(prach2+(dftlen<<1), prach2, (dftlen<<2));
// here we have | empty | Prach | Prach | empty | empty |
+1
View File
@@ -516,6 +516,7 @@ typedef struct {
int rx_offset; /// Timing offset
int rx_offset_diff; /// Timing adjustment for ofdm symbol0 on HW USRP
int max_pos_fil; /// Timing offset IIR filter
bool apply_timing_offset; /// Do time sync for current frame
int time_sync_cell;
/// Timing Advance updates variables
+10 -8
View File
@@ -352,12 +352,12 @@ void nr_ue_measurement_procedures(uint16_t l,
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_MEASUREMENT_PROCEDURES, VCD_FUNCTION_OUT);
}
static void nr_ue_pbch_procedures(PHY_VARS_NR_UE *ue,
UE_nr_rxtx_proc_t *proc,
int estimateSz,
struct complex16 dl_ch_estimates[][estimateSz],
nr_phy_data_t *phy_data,
c16_t rxdataF[][ue->frame_parms.samples_per_slot_wCP]) {
static int nr_ue_pbch_procedures(PHY_VARS_NR_UE *ue,
UE_nr_rxtx_proc_t *proc,
int estimateSz,
struct complex16 dl_ch_estimates[][estimateSz],
nr_phy_data_t *phy_data,
c16_t rxdataF[][ue->frame_parms.samples_per_slot_wCP]) {
int ret = 0;
DevAssert(ue);
@@ -420,6 +420,7 @@ static void nr_ue_pbch_procedures(PHY_VARS_NR_UE *ue,
}
return ret;
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_PBCH_PROCEDURES, VCD_FUNCTION_OUT);
}
@@ -929,9 +930,9 @@ void pbch_pdcch_processing(PHY_VARS_NR_UE *ue,
if(ssb_index == fp->ssb_index) {
LOG_D(PHY," ------ Decode MIB: frame.slot %d.%d ------ \n", frame_rx%1024, nr_slot_rx);
nr_ue_pbch_procedures(ue, proc, estimateSz, dl_ch_estimates, phy_data, rxdataF);
const int pbchSuccess = nr_ue_pbch_procedures(ue, proc, estimateSz, dl_ch_estimates, phy_data, rxdataF);
if (ue->no_timing_correction==0) {
if (ue->no_timing_correction==0 && pbchSuccess == 0) {
LOG_D(PHY,"start adjust sync slot = %d no timing %d\n", nr_slot_rx, ue->no_timing_correction);
nr_adjust_synch_ue(fp,
ue,
@@ -943,6 +944,7 @@ void pbch_pdcch_processing(PHY_VARS_NR_UE *ue,
0,
16384);
}
ue->apply_timing_offset = true;
}
LOG_D(PHY, "Doing N0 measurements in %s\n", __FUNCTION__);
nr_ue_rrc_measurements(ue, proc, rxdataF);
+3 -5
View File
@@ -98,9 +98,8 @@ nfapi_ue_release_request_body_t release_rntis;
instance_t DUuniqInstance=0;
instance_t CUuniqInstance=0;
int nr_derive_key_ng_ran_star(uint16_t pci, uint64_t nr_arfcn_dl, const uint8_t key[32], uint8_t *key_ng_ran_star)
void nr_derive_key_ng_ran_star(uint16_t pci, uint64_t nr_arfcn_dl, const uint8_t key[32], uint8_t *key_ng_ran_star)
{
return 0;
}
int dummy_nr_ue_ul_indication(nr_uplink_indication_t *ul_info) { return(0); }
@@ -124,10 +123,9 @@ int8_t nr_rrc_RA_succeeded(const module_id_t mod_id, const uint8_t gNB_index) {
return 0;
}
int nr_derive_key(int alg_type, uint8_t alg_id,
const uint8_t key[32], uint8_t **out)
void nr_derive_key(int alg_type, uint8_t alg_id, const uint8_t key[32], uint8_t out[16])
{
return 0;
(void)alg_type;
}
void processSlotTX(void *arg) {}
+3 -5
View File
@@ -96,9 +96,8 @@ void deref_sched_response(int _)
exit(1);
}
int nr_derive_key_ng_ran_star(uint16_t pci, uint64_t nr_arfcn_dl, const uint8_t key[32], uint8_t *key_ng_ran_star)
void nr_derive_key_ng_ran_star(uint16_t pci, uint64_t nr_arfcn_dl, const uint8_t key[32], uint8_t *key_ng_ran_star)
{
return 0;
}
void nr_rrc_ue_generate_RRCSetupRequest(module_id_t module_id, const uint8_t gNB_index)
@@ -120,10 +119,9 @@ int8_t nr_rrc_RA_succeeded(const module_id_t mod_id, const uint8_t gNB_index) {
return 0;
}
int nr_derive_key(int alg_type, uint8_t alg_id,
const uint8_t key[32], uint8_t **out)
void nr_derive_key(int alg_type, uint8_t alg_id, const uint8_t key[32], uint8_t out[16])
{
return 0;
(void)alg_type;
}
nrUE_params_t nrUE_params;
+3 -5
View File
@@ -94,9 +94,8 @@ nfapi_ue_release_request_body_t release_rntis;
instance_t DUuniqInstance=0;
instance_t CUuniqInstance=0;
int nr_derive_key_ng_ran_star(uint16_t pci, uint64_t nr_arfcn_dl, const uint8_t key[32], uint8_t *key_ng_ran_star)
void nr_derive_key_ng_ran_star(uint16_t pci, uint64_t nr_arfcn_dl, const uint8_t key[32], uint8_t *key_ng_ran_star)
{
return 0;
}
extern void fix_scd(NR_ServingCellConfig_t *scd);// forward declaration
@@ -133,10 +132,9 @@ int DU_send_INITIAL_UL_RRC_MESSAGE_TRANSFER(module_id_t module_idP,
nr_bler_struct nr_bler_data[NR_NUM_MCS];
int nr_derive_key(int alg_type, uint8_t alg_id,
const uint8_t key[32], uint8_t **out)
void nr_derive_key(int alg_type, uint8_t alg_id, const uint8_t key[32], uint8_t out[16])
{
return 0;
(void)alg_type;
}
void processSlotTX(void *arg) {}
+3 -2
View File
@@ -39,14 +39,15 @@ MESSAGE_DEF(F1AP_UL_RRC_MESSAGE , MESSAGE_PRIORITY_MED, f1ap_ul_r
//MESSAGE_DEF(F1AP_INITIAL_CONTEXT_SETUP_FAILURE, MESSAGE_PRIORITY_MED, f1ap_initial_context_setup_failure_t, f1ap_initial_context_setup_failure)
MESSAGE_DEF(F1AP_UE_CONTEXT_RELEASE_REQ, MESSAGE_PRIORITY_MED, f1ap_ue_context_release_req_t, f1ap_ue_context_release_req)
MESSAGE_DEF(F1AP_UE_CONTEXT_RELEASE_CMD, MESSAGE_PRIORITY_MED, f1ap_ue_context_release_cmd_t, f1ap_ue_context_release_cmd)
MESSAGE_DEF(F1AP_UE_CONTEXT_RELEASE_COMPLETE, MESSAGE_PRIORITY_MED, f1ap_ue_context_release_complete_t, f1ap_ue_context_release_complete)
/* RRC -> F1AP messages */
MESSAGE_DEF(F1AP_DL_RRC_MESSAGE , MESSAGE_PRIORITY_MED, f1ap_dl_rrc_message_t , f1ap_dl_rrc_message )
//MESSAGE_DEF(F1AP_INITIAL_CONTEXT_SETUP_REQ , MESSAGE_PRIORITY_MED, f1ap_initial_context_setup_req_t , f1ap_initial_context_setup_req )
MESSAGE_DEF(F1AP_UE_CONTEXT_SETUP_REQ, MESSAGE_PRIORITY_MED, f1ap_ue_context_setup_t, f1ap_ue_context_setup_req)
MESSAGE_DEF(F1AP_UE_CONTEXT_SETUP_RESP, MESSAGE_PRIORITY_MED, f1ap_ue_context_setup_t, f1ap_ue_context_setup_resp)
MESSAGE_DEF(F1AP_UE_CONTEXT_MODIFICATION_REQ, MESSAGE_PRIORITY_MED, f1ap_ue_context_setup_t, f1ap_ue_context_modification_req)
MESSAGE_DEF(F1AP_UE_CONTEXT_MODIFICATION_RESP, MESSAGE_PRIORITY_MED, f1ap_ue_context_setup_t, f1ap_ue_context_modification_resp)
MESSAGE_DEF(F1AP_UE_CONTEXT_MODIFICATION_REQ, MESSAGE_PRIORITY_MED, f1ap_ue_context_modif_req_t, f1ap_ue_context_modification_req)
MESSAGE_DEF(F1AP_UE_CONTEXT_MODIFICATION_RESP, MESSAGE_PRIORITY_MED, f1ap_ue_context_modif_resp_t, f1ap_ue_context_modification_resp)
/* CU -> DU*/
MESSAGE_DEF(F1AP_PAGING_IND, MESSAGE_PRIORITY_MED, f1ap_paging_ind_t, f1ap_paging_ind)
+5 -6
View File
@@ -41,14 +41,14 @@
#define F1AP_UL_RRC_MESSAGE(mSGpTR) (mSGpTR)->ittiMsg.f1ap_ul_rrc_message
#define F1AP_UE_CONTEXT_SETUP_REQ(mSGpTR) (mSGpTR)->ittiMsg.f1ap_ue_context_setup_req
#define F1AP_UE_CONTEXT_SETUP_RESP(mSGpTR) (mSGpTR)->ittiMsg.f1ap_ue_context_setup_resp
#define F1AP_UE_CONTEXT_RELEASE_RESP(mSGpTR) (mSGpTR)->ittiMsg.f1ap_ue_context_release_resp
#define F1AP_UE_CONTEXT_MODIFICATION_REQ(mSGpTR) (mSGpTR)->ittiMsg.f1ap_ue_context_modification_req
#define F1AP_UE_CONTEXT_MODIFICATION_RESP(mSGpTR) (mSGpTR)->ittiMsg.f1ap_ue_context_modification_resp
#define F1AP_UE_CONTEXT_MODIFICATION_FAIL(mSGpTR) (mSGpTR)->ittiMsg.f1ap_ue_context_modification_fail
#define F1AP_DL_RRC_MESSAGE(mSGpTR) (mSGpTR)->ittiMsg.f1ap_dl_rrc_message
#define F1AP_UE_CONTEXT_RELEASE_REQ(mSGpTR) (mSGpTR)->ittiMsg.f1ap_ue_context_release_req
#define F1AP_UE_CONTEXT_RELEASE_CMD(mSGpTR) (mSGpTR)->ittiMsg.f1ap_ue_context_release_req
#define F1AP_UE_CONTEXT_RELEASE_CMD(mSGpTR) (mSGpTR)->ittiMsg.f1ap_ue_context_release_cmd
#define F1AP_UE_CONTEXT_RELEASE_COMPLETE(mSGpTR) (mSGpTR)->ittiMsg.f1ap_ue_context_release_complete
#define F1AP_PAGING_IND(mSGpTR) (mSGpTR)->ittiMsg.f1ap_paging_ind
@@ -341,7 +341,6 @@ typedef struct f1ap_drb_to_be_setup_s {
typedef struct f1ap_srb_to_be_setup_s {
long srb_id;
rlc_mode_t rlc_mode;
uint8_t lcid;
} f1ap_srb_to_be_setup_t;
@@ -409,7 +408,7 @@ typedef struct f1ap_ue_context_setup_s {
ReconfigurationCompl_t ReconfigComplOutcome;
uint8_t *rrc_container;
int rrc_container_length;
} f1ap_ue_context_setup_t;
} f1ap_ue_context_setup_t, f1ap_ue_context_modif_req_t, f1ap_ue_context_modif_resp_t;
typedef enum F1ap_Cause_e {
F1AP_CAUSE_NOTHING, /* No components present */
@@ -425,8 +424,8 @@ typedef struct f1ap_ue_context_release_s {
long cause_value;
uint8_t *rrc_container;
int rrc_container_length;
} f1ap_ue_context_release_req_t, f1ap_ue_context_release_cmd_t,
f1ap_ue_context_release_cplt_t;
int srb_id;
} f1ap_ue_context_release_req_t, f1ap_ue_context_release_cmd_t, f1ap_ue_context_release_complete_t;
typedef struct f1ap_paging_ind_s {
uint16_t ueidentityindexvalue;
+6 -5
View File
@@ -23,11 +23,12 @@
#include <arpa/inet.h>
#include "e1ap_api.h"
#include "UTIL/OSA/osa_defs.h"
#include "nr_pdcp/nr_pdcp_entity.h"
#include "openair2/LAYER2/nr_pdcp/nr_pdcp_e1_api.h"
#include "openair2/RRC/NR/cucp_cuup_if.h"
#include "openair2/RRC/LTE/MESSAGES/asn1_msg.h"
#include "openair3/SECU/key_nas_deriver.h"
#include "openair3/ocp-gtpu/gtp_itf.h"
#include "e1ap_asnc.h"
#include "e1ap_common.h"
@@ -120,12 +121,12 @@ static int drb_config_N3gtpu_create(e1ap_bearer_setup_req_t * const req,
}
// Configure DRBs
uint8_t *kUPenc = NULL;
uint8_t *kUPint = NULL;
uint8_t kUPenc[16] = {0};
uint8_t kUPint[16] = {0};
nr_derive_key(UP_ENC_ALG, req->cipheringAlgorithm, (uint8_t *)req->encryptionKey, &kUPenc);
nr_derive_key(UP_ENC_ALG, req->cipheringAlgorithm, (uint8_t *)req->encryptionKey, kUPenc);
nr_derive_key(UP_INT_ALG, req->integrityProtectionAlgorithm, (uint8_t *)req->integrityProtectionKey, &kUPint);
nr_derive_key(UP_INT_ALG, req->integrityProtectionAlgorithm, (uint8_t *)req->integrityProtectionKey, kUPint);
nr_pdcp_e1_add_drbs(true, // set this to notify PDCP that his not UE
create_tunnel_req.ue_id,
+1 -1
View File
@@ -180,7 +180,7 @@ int f1ap_du_add_cu_ue_id(instance_t instanceP,
return -1;
f1_inst->f1ap_ue[f1ap_uid].cu_ue_f1ap_id = cu_ue_f1ap_id;
LOG_I(F1AP, "Adding cu_ue_f1ap_id %ld for UE with RNTI %x\n", cu_ue_f1ap_id, f1_inst->f1ap_ue[f1ap_uid].rnti);
LOG_D(F1AP, "Adding cu_ue_f1ap_id %ld for UE with RNTI %x\n", cu_ue_f1ap_id, f1_inst->f1ap_ue[f1ap_uid].rnti);
return 0;
}
+1 -1
View File
@@ -171,7 +171,7 @@ void *F1AP_CU_task(void *arg) {
case F1AP_UE_CONTEXT_MODIFICATION_REQ:
CU_send_UE_CONTEXT_MODIFICATION_REQUEST(ITTI_MSG_DESTINATION_INSTANCE(received_msg),
&F1AP_UE_CONTEXT_SETUP_REQ(received_msg));
&F1AP_UE_CONTEXT_MODIFICATION_REQ(received_msg));
break;
case F1AP_UE_CONTEXT_RELEASE_CMD: // from rrc
+34 -17
View File
@@ -776,10 +776,10 @@ int CU_handle_UE_CONTEXT_SETUP_FAILURE(instance_t instance,
AssertFatal(1==0,"Not implemented yet\n");
}
int CU_handle_UE_CONTEXT_RELEASE_REQUEST(instance_t instance,
uint32_t assoc_id,
uint32_t stream,
F1AP_F1AP_PDU_t *pdu) {
int CU_handle_UE_CONTEXT_RELEASE_REQUEST(instance_t instance, uint32_t assoc_id, uint32_t stream, F1AP_F1AP_PDU_t *pdu)
{
MessageDef *msg = itti_alloc_new_message(TASK_CU_F1, 0, F1AP_UE_CONTEXT_RELEASE_REQ);
f1ap_ue_context_release_req_t *req = &F1AP_UE_CONTEXT_RELEASE_REQ(msg);
F1AP_UEContextReleaseRequest_t *container;
F1AP_UEContextReleaseRequestIEs_t *ie;
DevAssert(pdu);
@@ -789,6 +789,8 @@ int CU_handle_UE_CONTEXT_RELEASE_REQUEST(instance_t instance,
F1AP_ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID, true);
const rnti_t rnti = f1ap_get_rnti_by_cu_id(true, instance,
ie->value.choice.GNB_CU_UE_F1AP_ID);
req->rnti = rnti;
/* GNB_DU_UE_F1AP_ID */
F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextReleaseRequestIEs_t, ie, container,
F1AP_ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID, true);
@@ -796,35 +798,42 @@ int CU_handle_UE_CONTEXT_RELEASE_REQUEST(instance_t instance,
ie->value.choice.GNB_DU_UE_F1AP_ID);
AssertFatal(rnti == rnti2, "RNTI obtained through DU ID (%x) is different from CU ID (%x)\n",
rnti2, rnti);
/* Cause */
/* We don't care for the moment
F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextReleaseRequestIEs_t, ie, container,
F1AP_ProtocolIE_ID_id_Cause, true);
switch(ie->value.choice.Cause.present)
{
case F1AP_Cause_PR_radioNetwork:
//ie->value.choice.Cause.choice.radioNetwork
req->cause = F1AP_CAUSE_RADIO_NETWORK;
req->cause_value = ie->value.choice.Cause.choice.radioNetwork;
break;
case F1AP_Cause_PR_transport:
//ie->value.choice.Cause.choice.transport
req->cause = F1AP_CAUSE_TRANSPORT;
req->cause_value = ie->value.choice.Cause.choice.transport;
break;
case F1AP_Cause_PR_protocol:
//ie->value.choice.Cause.choice.protocol
req->cause = F1AP_CAUSE_PROTOCOL;
req->cause_value = ie->value.choice.Cause.choice.protocol;
break;
case F1AP_Cause_PR_misc:
//ie->value.choice.Cause.choice.misc
req->cause = F1AP_CAUSE_MISC;
req->cause_value = ie->value.choice.Cause.choice.misc;
break;
case F1AP_Cause_PR_NOTHING:
default:
req->cause = F1AP_CAUSE_NOTHING;
break;
}
*/
LOG_I(F1AP, "Received UE CONTEXT RELEASE REQUEST: Trigger RRC for RNTI %x\n", rnti);
if (f1ap_req(true, instance)->cell_type==CELL_MACRO_GNB) {
AssertFatal(false,"must be devlopped\n");
}
F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextReleaseRequestIEs_t, ie, container, F1AP_ProtocolIE_ID_id_targetCellsToCancel, false);
if (ie != NULL) {
LOG_W(F1AP, "ignoring list of target cells to cancel in UE Context Release Request: implementation missing\n");
}
itti_send_msg_to_task(TASK_RRC_GNB, instance, msg);
return 0;
}
@@ -900,6 +909,13 @@ int CU_send_UE_CONTEXT_RELEASE_COMMAND(instance_t instance,
ie4->value.present = F1AP_UEContextReleaseCommandIEs__value_PR_RRCContainer;
OCTET_STRING_fromBuf(&ie4->value.choice.RRCContainer, (const char *)cmd->rrc_container,
cmd->rrc_container_length);
// conditionally have SRBID if RRC Container
asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextReleaseCommandIEs_t, ie5);
ie5->id = F1AP_ProtocolIE_ID_id_SRBID;
ie5->criticality = F1AP_Criticality_ignore;
ie5->value.present = F1AP_UEContextReleaseCommandIEs__value_PR_SRBID;
ie5->value.choice.SRBID = cmd->srb_id;
}
/* encode */
@@ -965,7 +981,8 @@ int CU_handle_UE_CONTEXT_RELEASE_COMPLETE(instance_t instance,
return 0;
}
int CU_send_UE_CONTEXT_MODIFICATION_REQUEST(instance_t instance, f1ap_ue_context_setup_t *f1ap_ue_context_modification_req) {
int CU_send_UE_CONTEXT_MODIFICATION_REQUEST(instance_t instance, f1ap_ue_context_modif_req_t *f1ap_ue_context_modification_req)
{
F1AP_F1AP_PDU_t pdu= {0};
F1AP_UEContextModificationRequest_t *out;
uint8_t *buffer=NULL;
@@ -1584,7 +1601,7 @@ int CU_handle_UE_CONTEXT_MODIFICATION_RESPONSE(instance_t instance,
F1AP_UEContextModificationResponseIEs_t *ie;
DevAssert(pdu);
msg_p = itti_alloc_new_message(TASK_DU_F1, 0, F1AP_UE_CONTEXT_MODIFICATION_RESP);
f1ap_ue_context_setup_t *f1ap_ue_context_modification_resp = &F1AP_UE_CONTEXT_MODIFICATION_RESP(msg_p);
f1ap_ue_context_modif_resp_t *f1ap_ue_context_modification_resp = &F1AP_UE_CONTEXT_MODIFICATION_RESP(msg_p);
container = &pdu->choice.successfulOutcome->value.choice.UEContextModificationResponse;
int i;
@@ -1593,7 +1610,7 @@ int CU_handle_UE_CONTEXT_MODIFICATION_RESPONSE(instance_t instance,
F1AP_ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID, true);
f1ap_ue_context_modification_resp->gNB_CU_ue_id = ie->value.choice.GNB_CU_UE_F1AP_ID;
LOG_D(F1AP, "f1ap_ue_context_setup_resp->gNB_CU_ue_id is: %d \n", f1ap_ue_context_modification_resp->gNB_CU_ue_id);
LOG_D(F1AP, "f1ap_ue_context_modif_resp->gNB_CU_ue_id is: %d \n", f1ap_ue_context_modification_resp->gNB_CU_ue_id);
/* GNB_DU_UE_F1AP_ID */
F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextModificationResponseIEs_t, ie, container,
@@ -72,8 +72,7 @@ int CU_handle_UE_CONTEXT_RELEASE_COMPLETE(instance_t instance,
/*
* UE Context Modification (gNB-CU initiated)
*/
int CU_send_UE_CONTEXT_MODIFICATION_REQUEST(instance_t instance,
f1ap_ue_context_setup_t *f1ap_ue_context_modification_req);
int CU_send_UE_CONTEXT_MODIFICATION_REQUEST(instance_t instance, f1ap_ue_context_modif_req_t *f1ap_ue_context_modification_req);
int CU_handle_UE_CONTEXT_MODIFICATION_RESPONSE(instance_t instance,
uint32_t assoc_id,
uint32_t stream,
+4
View File
@@ -165,6 +165,10 @@ void *F1AP_DU_task(void *arg) {
&F1AP_UE_CONTEXT_RELEASE_REQ(msg));
break;
case F1AP_UE_CONTEXT_RELEASE_COMPLETE:
DU_send_UE_CONTEXT_RELEASE_COMPLETE(myInstance, &F1AP_UE_CONTEXT_RELEASE_COMPLETE(msg));
break;
case TERMINATE_MESSAGE:
LOG_W(F1AP, " *** Exiting F1AP thread\n");
itti_exit_task();
+58 -54
View File
@@ -37,29 +37,24 @@
#include "f1ap_du_ue_context_management.h"
#include "openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.h"
#include "rrc_extern.h"
#include "openair2/RRC/NR/rrc_gNB_UE_context.h"
#include "openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h"
#include <openair3/ocp-gtpu/gtp_itf.h>
bool lteDURecvCb(protocol_ctxt_t *ctxt_pP,
const srb_flag_t srb_flagP,
const rb_id_t rb_idP,
const mui_t muiP,
const confirm_t confirmP,
const sdu_size_t sdu_buffer_sizeP,
unsigned char *const sdu_buffer_pP,
const pdcp_transmission_mode_t modeP,
const uint32_t *sourceL2Id,
const uint32_t *destinationL2Id) {
bool DURecvCb(protocol_ctxt_t *ctxt_pP,
const srb_flag_t srb_flagP,
const rb_id_t rb_idP,
const mui_t muiP,
const confirm_t confirmP,
const sdu_size_t sdu_buffer_sizeP,
unsigned char *const sdu_buffer_pP,
const pdcp_transmission_mode_t modeP,
const uint32_t *sourceL2Id,
const uint32_t *destinationL2Id)
{
// The buffer comes from the stack in gtp-u thread, we have a make a separate buffer to enqueue in a inter-thread message queue
mem_block_t *sdu=get_free_mem_block(sdu_buffer_sizeP, __func__);
memcpy(sdu->data, sdu_buffer_pP, sdu_buffer_sizeP);
// weird rb id management in 4G, not fully understand (looks bad design)
// overcomplex: if i understand, on the interface DRB start at 4 because there can be SRB 0..3
// but it would be much simpler to use absolute numbering
// instead of this "srb flag" associated to these +/-4
du_rlc_data_req(ctxt_pP,srb_flagP, false, rb_idP-4,muiP, confirmP, sdu_buffer_sizeP, sdu);
du_rlc_data_req(ctxt_pP, srb_flagP, false, rb_idP, muiP, confirmP, sdu_buffer_sizeP, sdu);
return true;
}
@@ -98,8 +93,6 @@ int DU_handle_UE_CONTEXT_SETUP_REQUEST(instance_t instance,
if(f1ap_ue_context_setup_req->rnti<0)
LOG_E(F1AP, "Could not retrieve UE rnti based on the CU/DU UE id \n");
else
LOG_I(F1AP, "Retrieved rnti is: %d \n", f1ap_ue_context_setup_req->rnti);
/* SpCell_ID */
F1AP_UEContextSetupRequestIEs_t *ieNet;
@@ -140,7 +133,7 @@ int DU_handle_UE_CONTEXT_SETUP_REQUEST(instance_t instance,
f1ap_ue_context_setup_req->cu_to_du_rrc_information->uE_CapabilityRAT_ContainerList = (uint8_t *)calloc(1,ieCuRrcInfo->value.choice.CUtoDURRCInformation.uE_CapabilityRAT_ContainerList->size);
memcpy(f1ap_ue_context_setup_req->cu_to_du_rrc_information->uE_CapabilityRAT_ContainerList, ieCuRrcInfo->value.choice.CUtoDURRCInformation.uE_CapabilityRAT_ContainerList->buf, ieCuRrcInfo->value.choice.CUtoDURRCInformation.uE_CapabilityRAT_ContainerList->size);
f1ap_ue_context_setup_req->cu_to_du_rrc_information->uE_CapabilityRAT_ContainerList_length = ieCuRrcInfo->value.choice.CUtoDURRCInformation.uE_CapabilityRAT_ContainerList->size;
LOG_I(F1AP, "Size f1ap_ue_context_setup_req->cu_to_du_rrc_information->uE_CapabilityRAT_ContainerList_length: %d \n", f1ap_ue_context_setup_req->cu_to_du_rrc_information->uE_CapabilityRAT_ContainerList_length);
LOG_D(F1AP, "Size f1ap_ue_context_setup_req->cu_to_du_rrc_information->uE_CapabilityRAT_ContainerList_length: %d \n", f1ap_ue_context_setup_req->cu_to_du_rrc_information->uE_CapabilityRAT_ContainerList_length);
}
}
@@ -649,18 +642,13 @@ int DU_send_UE_CONTEXT_RELEASE_REQUEST(instance_t instance,
return 0;
}
int DU_handle_UE_CONTEXT_RELEASE_COMMAND(instance_t instance,
uint32_t assoc_id,
uint32_t stream,
F1AP_F1AP_PDU_t *pdu) {
int DU_handle_UE_CONTEXT_RELEASE_COMMAND(instance_t instance, uint32_t assoc_id, uint32_t stream, F1AP_F1AP_PDU_t *pdu)
{
F1AP_UEContextReleaseCommand_t *container;
F1AP_UEContextReleaseCommandIEs_t *ie;
/* ITTI message to NR-RRC for the case of gNB-DU */
MessageDef *msg_p; // message to NR-RRC
msg_p = itti_alloc_new_message(TASK_DU_F1, 0, F1AP_UE_CONTEXT_RELEASE_CMD);
f1ap_ue_context_release_req_t *f1ap_ue_context_release_cmd = &F1AP_UE_CONTEXT_RELEASE_CMD(msg_p);
f1ap_ue_context_release_req_t ue_context_release = {0};
f1ap_ue_context_release_req_t *f1ap_ue_context_release_cmd = &ue_context_release;
DevAssert(pdu);
container = &pdu->choice.initiatingMessage->value.choice.UEContextReleaseCommand;
@@ -680,26 +668,30 @@ int DU_handle_UE_CONTEXT_RELEASE_COMMAND(instance_t instance,
F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextReleaseCommandIEs_t, ie, container,
F1AP_ProtocolIE_ID_id_RRCContainer, false);
f1ap_ue_context_release_cmd->rrc_container = malloc(ie->value.choice.RRCContainer.size);
memcpy(f1ap_ue_context_release_cmd->rrc_container, ie->value.choice.RRCContainer.buf, ie->value.choice.RRCContainer.size);
if (ie != NULL) {
f1ap_ue_context_release_cmd->rrc_container = malloc(ie->value.choice.RRCContainer.size);
AssertFatal(f1ap_ue_context_release_cmd->rrc_container != NULL, "out of memory\n");
memcpy(f1ap_ue_context_release_cmd->rrc_container, ie->value.choice.RRCContainer.buf, ie->value.choice.RRCContainer.size);
f1ap_ue_context_release_cmd->rrc_container_length = ie->value.choice.RRCContainer.size;
// conditionally have SRB ID if there is RRC container
F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextReleaseCommandIEs_t, ie, container, F1AP_ProtocolIE_ID_id_SRBID, true);
f1ap_ue_context_release_cmd->srb_id = ie->value.choice.SRBID;
}
F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextReleaseCommandIEs_t, ie, container,
F1AP_ProtocolIE_ID_id_Cause, true);
switch (ie->value.choice.Cause.present){
case F1AP_Cause_PR_radioNetwork:
LOG_W (F1AP, "UE context release command cause is due to radioNetwork with specific code: %ld\n",ie->value.choice.Cause.choice.radioNetwork);
f1ap_ue_context_release_cmd->cause = F1AP_CAUSE_RADIO_NETWORK;
break;
case F1AP_Cause_PR_transport:
LOG_W (F1AP, "UE context release command cause is due to transport with specific code: %ld\n",ie->value.choice.Cause.choice.transport);
f1ap_ue_context_release_cmd->cause = F1AP_CAUSE_TRANSPORT;
break;
case F1AP_Cause_PR_protocol:
LOG_W (F1AP, "UE context release command cause is due to protocol with specific code: %ld\n",ie->value.choice.Cause.choice.protocol);
f1ap_ue_context_release_cmd->cause = F1AP_CAUSE_PROTOCOL;
break;
case F1AP_Cause_PR_misc:
LOG_W (F1AP, "UE context release command cause is misc with specific code: %ld \n",ie->value.choice.Cause.choice.misc);
f1ap_ue_context_release_cmd->cause = F1AP_CAUSE_MISC;
break;
default:
@@ -707,12 +699,13 @@ int DU_handle_UE_CONTEXT_RELEASE_COMMAND(instance_t instance,
break;
}
itti_send_msg_to_task(TASK_RRC_GNB, instance, msg_p);
ue_context_release_command(f1ap_ue_context_release_cmd);
return 0;
}
int DU_send_UE_CONTEXT_RELEASE_COMPLETE(instance_t instance,
f1ap_ue_context_release_cplt_t *cplt) {
int DU_send_UE_CONTEXT_RELEASE_COMPLETE(instance_t instance, f1ap_ue_context_release_complete_t *complete)
{
F1AP_F1AP_PDU_t pdu= {0};
F1AP_UEContextReleaseComplete_t *out;
/* Create */
@@ -729,14 +722,14 @@ int DU_send_UE_CONTEXT_RELEASE_COMPLETE(instance_t instance,
ie1->id = F1AP_ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID;
ie1->criticality = F1AP_Criticality_reject;
ie1->value.present = F1AP_UEContextReleaseCompleteIEs__value_PR_GNB_CU_UE_F1AP_ID;
ie1->value.choice.GNB_CU_UE_F1AP_ID = f1ap_get_cu_ue_f1ap_id(DUtype, instance, cplt->rnti);
ie1->value.choice.GNB_CU_UE_F1AP_ID = f1ap_get_cu_ue_f1ap_id(DUtype, instance, complete->rnti);
/* mandatory */
/* c2. GNB_DU_UE_F1AP_ID */
asn1cSequenceAdd(out->protocolIEs.list,F1AP_UEContextReleaseCompleteIEs_t, ie2);
ie2->id = F1AP_ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID;
ie2->criticality = F1AP_Criticality_reject;
ie2->value.present = F1AP_UEContextReleaseCompleteIEs__value_PR_GNB_DU_UE_F1AP_ID;
ie2->value.choice.GNB_DU_UE_F1AP_ID = f1ap_get_du_ue_f1ap_id(DUtype, instance, cplt->rnti);
ie2->value.choice.GNB_DU_UE_F1AP_ID = f1ap_get_du_ue_f1ap_id(DUtype, instance, complete->rnti);
/* optional -> currently not used */
/* c3. CriticalityDiagnostics */
//if (0) {
@@ -798,7 +791,7 @@ int DU_send_UE_CONTEXT_RELEASE_COMPLETE(instance_t instance,
buffer,
len,
getCxt(false, instance)->default_sctp_stream_id);
f1ap_remove_ue(DUtype, instance, cplt->rnti);
f1ap_remove_ue(DUtype, instance, complete->rnti);
return 0;
}
@@ -812,17 +805,12 @@ static instance_t du_create_gtpu_instance_to_cu(char *CUaddr, uint16_t CUport, c
return gtpv1Init(tmp);
}
int DU_handle_UE_CONTEXT_MODIFICATION_REQUEST(instance_t instance,
uint32_t assoc_id,
uint32_t stream,
F1AP_F1AP_PDU_t *pdu) {
MessageDef *msg_p; // message to RRC
int DU_handle_UE_CONTEXT_MODIFICATION_REQUEST(instance_t instance, uint32_t assoc_id, uint32_t stream, F1AP_F1AP_PDU_t *pdu)
{
F1AP_UEContextModificationRequest_t *container;
int i;
DevAssert(pdu);
msg_p = itti_alloc_new_message(TASK_DU_F1, 0, F1AP_UE_CONTEXT_MODIFICATION_REQ);
f1ap_ue_context_setup_t *f1ap_ue_context_modification_req = &F1AP_UE_CONTEXT_MODIFICATION_REQ(msg_p);
f1ap_ue_context_modif_req_t ue_context_modification = {0};
f1ap_ue_context_modif_req_t *f1ap_ue_context_modification_req = &ue_context_modification;
container = &pdu->choice.initiatingMessage->value.choice.UEContextModificationRequest;
/* mandatory */
@@ -843,7 +831,7 @@ int DU_handle_UE_CONTEXT_MODIFICATION_REQUEST(instance_t instance,
if(f1ap_ue_context_modification_req->rnti<0)
LOG_E(F1AP, "Could not retrieve UE rnti based on the DU UE id \n");
else
LOG_I(F1AP, "Retrieved rnti is: %d \n", f1ap_ue_context_modification_req->rnti);
LOG_D(F1AP, "Retrieved rnti is: %d \n", f1ap_ue_context_modification_req->rnti);
/* SRB */
F1AP_UEContextModificationRequestIEs_t *ieSrb;
@@ -969,15 +957,16 @@ int DU_handle_UE_CONTEXT_MODIFICATION_REQUEST(instance_t instance,
LOG_E(F1AP, " RRCContainer in UEContextModificationRequestIEs size id 0\n");
}
} else {
LOG_W(F1AP, "can't find RRCContainer in UEContextModificationRequestIEs by id %ld \n", F1AP_ProtocolIE_ID_id_RRCContainer);
LOG_D(F1AP, "can't find RRCContainer in UEContextModificationRequestIEs by id %ld \n", F1AP_ProtocolIE_ID_id_RRCContainer);
}
itti_send_msg_to_task(TASK_RRC_GNB, instance, msg_p);
ue_context_modification_request(f1ap_ue_context_modification_req);
return 0;
}
//void DU_send_UE_CONTEXT_MODIFICATION_RESPONSE(F1AP_UEContextModificationResponse_t *UEContextModificationResponse) {
int DU_send_UE_CONTEXT_MODIFICATION_RESPONSE(instance_t instance, f1ap_ue_context_setup_t *resp) {
int DU_send_UE_CONTEXT_MODIFICATION_RESPONSE(instance_t instance, f1ap_ue_context_modif_resp_t *resp)
{
F1AP_F1AP_PDU_t pdu= {0};
F1AP_UEContextModificationResponse_t *out;
uint8_t *buffer=NULL;
@@ -1064,6 +1053,21 @@ int DU_send_UE_CONTEXT_MODIFICATION_RESPONSE(instance_t instance, f1ap_ue_contex
drbs_setupmod_item->dRBID = resp->drbs_to_be_setup[i].drb_id;
for (int j=0; j<resp->drbs_to_be_setup[i].up_dl_tnl_length; j++) {
f1ap_drb_to_be_setup_t *drb = &resp->drbs_to_be_setup[i];
transport_layer_addr_t tl_addr = {0};
memcpy(tl_addr.buffer, &drb->up_ul_tnl[0].tl_address, sizeof(drb->up_ul_tnl[0].tl_address));
tl_addr.length = sizeof(drb->up_ul_tnl[0].tl_address) * 8;
drb->up_dl_tnl[j].teid = newGtpuCreateTunnel(getCxt(false, instance)->gtpInst,
resp->rnti,
drb->drb_id,
drb->drb_id,
drb->up_ul_tnl[j].teid,
-1, // no qfi
tl_addr,
drb->up_ul_tnl[0].port,
DURecvCb,
NULL);
/* ADD */
asn1cSequenceAdd(drbs_setupmod_item->dLUPTNLInformation_ToBeSetup_List.list,
F1AP_DLUPTNLInformation_ToBeSetup_Item_t, dLUPTNLInformation_ToBeSetup_Item);
@@ -63,9 +63,7 @@ int DU_handle_UE_CONTEXT_RELEASE_COMMAND(instance_t instance,
/*
* UE Context Release Complete (gNB-DU initiated)
*/
int DU_send_UE_CONTEXT_RELEASE_COMPLETE(instance_t instance,
f1ap_ue_context_release_cplt_t *cplt);
int DU_send_UE_CONTEXT_RELEASE_COMPLETE(instance_t instance, f1ap_ue_context_release_complete_t *complete);
/*
* UE Context Modification (gNB-CU initiated)
@@ -74,7 +72,7 @@ int DU_handle_UE_CONTEXT_MODIFICATION_REQUEST(instance_t instance,
uint32_t assoc_id,
uint32_t stream,
F1AP_F1AP_PDU_t *pdu);
int DU_send_UE_CONTEXT_MODIFICATION_RESPONSE(instance_t instance, f1ap_ue_context_setup_t *resp);
int DU_send_UE_CONTEXT_MODIFICATION_RESPONSE(instance_t instance, f1ap_ue_context_modif_resp_t *resp);
int DU_send_UE_CONTEXT_MODIFICATION_FAILURE(instance_t instance);
@@ -271,17 +271,6 @@ bool set_ul_ptrs_values(NR_PTRS_UplinkConfig_t *ul_ptrs_config,
@returns transformPrecoding value */
long get_transformPrecoding(const NR_UE_UL_BWP_t *current_UL_BWP, nr_dci_format_t dci_format, uint8_t configuredGrant);
void nr_mac_gNB_rrc_ul_failure(const module_id_t Mod_instP,
const int CC_idP,
const frame_t frameP,
const sub_frame_t subframeP,
const rnti_t rntiP);
void nr_mac_gNB_rrc_ul_failure_reset(const module_id_t Mod_instP,
const frame_t frameP,
const sub_frame_t subframeP,
const rnti_t rntiP);
uint8_t number_of_bits_set(uint8_t buf);
void compute_rsrp_bitlen(struct NR_CSI_ReportConfig *csi_reportconfig,
+3 -2
View File
@@ -40,7 +40,7 @@
#include "common/utils/LOG/vcd_signal_dumper.h"
#include "UTIL/OPT/opt.h"
#include "RRC/NR/nr_rrc_extern.h"
#include "openair2/X2AP/x2ap_eNB.h"
#include "nr_pdcp/nr_pdcp_oai_api.h"
@@ -174,7 +174,8 @@ void gNB_dlsch_ulsch_scheduler(module_id_t module_idP, frame_t frame, sub_frame_
void nr_pdcp_tick(int frame, int subframe);
nr_rlc_tick(frame, slot >> *scc->ssbSubcarrierSpacing);
nr_pdcp_tick(frame, slot >> *scc->ssbSubcarrierSpacing);
nr_rrc_trigger(&ctxt, 0 /*CC_id*/, frame, slot >> *scc->ssbSubcarrierSpacing);
if (is_x2ap_enabled())
x2ap_trigger();
}
for (int CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) {
@@ -1796,8 +1796,7 @@ static void nr_generate_Msg3_dcch_dtch_response(module_id_t module_idP,
configure_UE_BWP(nr_mac, scc, sched_ctrl, NULL, UE, 0, 0);
// Reset uplink failure flags/counters/timers at MAC so gNB will resume again scheduling resources for this UE
sched_ctrl->pusch_consecutive_dtx_cnt = 0;
sched_ctrl->ul_failure = 0;
nr_mac_reset_ul_failure(sched_ctrl);
}
static void nr_generate_Msg4(module_id_t module_idP,
@@ -577,7 +577,7 @@ static void pf_dl(module_id_t module_id,
NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl;
NR_UE_DL_BWP_t *current_BWP = &UE->current_DL_BWP;
if (sched_ctrl->ul_failure==1)
if (sched_ctrl->ul_failure)
continue;
const NR_mac_dir_stats_t *stats = &UE->mac_stats.dl;
@@ -898,7 +898,8 @@ void nr_schedule_ue_spec(module_id_t module_id,
NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl;
NR_UE_DL_BWP_t *current_BWP = &UE->current_DL_BWP;
if (sched_ctrl->ul_failure==1 && get_softmodem_params()->phy_test==0) continue;
if (sched_ctrl->ul_failure && !get_softmodem_params()->phy_test)
continue;
NR_sched_pdsch_t *sched_pdsch = &sched_ctrl->sched_pdsch;
UE->mac_stats.dl.current_bytes = 0;
@@ -44,10 +44,6 @@
#include "openair2/LAYER2/nr_rlc/nr_rlc_oai_api.h"
/* TODO REMOVE_DU_RRC: the RRC in the DU is a hack and should be taken out in the future */
#include "RRC/NR/nr_rrc_extern.h"
#include "RRC/NR/rrc_gNB_UE_context.h"
#include "RRC/L2_INTERFACE/openair_rrc_L2_interface.h"
#include "RRC/NR/MESSAGES/asn1_msg.h"
#include "intertask_interface.h"
@@ -2785,6 +2781,19 @@ void nr_mac_update_timers(module_id_t module_id,
NR_UEs_t *UE_info = &RC.nrmac[module_id]->UE_info;
UE_iterator(UE_info->list, UE) {
NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl;
if (nr_mac_check_release(sched_ctrl, UE->rnti)) {
nr_rlc_remove_ue(UE->rnti);
mac_remove_nr_ue(RC.nrmac[module_id], UE->rnti);
// go back to examine the next UE, which is at the position the
// current UE was
UE--;
continue;
}
/* check if UL failure and trigger release request if necessary */
nr_mac_check_ul_failure(RC.nrmac[module_id], UE->rnti, sched_ctrl);
if (sched_ctrl->rrc_processing_timer > 0) {
sched_ctrl->rrc_processing_timer--;
if (sched_ctrl->rrc_processing_timer == 0) {
@@ -2931,12 +2940,6 @@ void prepare_initial_ul_rrc_message(gNB_MAC_INST *mac, NR_UE_info_t *UE)
UE->CellGroup = cellGroupConfig;
nr_mac_update_cellgroup(mac, UE->rnti, cellGroupConfig);
/* TODO REMOVE_DU_RRC: the RRC in the DU is a hack and should be taken out in the future */
if (NODE_IS_DU(rrc->node_type)) {
rrc_gNB_ue_context_t *ue = rrc_gNB_create_ue_context(UE->rnti, rrc, UE->rnti);
ue->ue_context.masterCellGroup = cellGroupConfig;
}
/* activate SRB0 */
nr_rlc_activate_srb0(UE->rnti, mac, UE, send_initial_ul_rrc_message);
@@ -2946,3 +2949,53 @@ void prepare_initial_ul_rrc_message(gNB_MAC_INST *mac, NR_UE_info_t *UE)
DevAssert(bearer->servedRadioBearer->choice.srb_Identity == 1);
nr_rlc_add_srb(UE->rnti, DCCH, bearer);
}
void nr_mac_trigger_release_timer(NR_UE_sched_ctrl_t *sched_ctrl, NR_SubcarrierSpacing_t subcarrier_spacing)
{
// trigger 60ms
sched_ctrl->release_timer = 60 << subcarrier_spacing;
}
bool nr_mac_check_release(NR_UE_sched_ctrl_t *sched_ctrl, int rnti)
{
if (sched_ctrl->release_timer == 0)
return false;
sched_ctrl->release_timer--;
return sched_ctrl->release_timer == 0;
}
void nr_mac_trigger_ul_failure(NR_UE_sched_ctrl_t *sched_ctrl, NR_SubcarrierSpacing_t subcarrier_spacing)
{
if (sched_ctrl->ul_failure) {
/* already running */
return;
}
sched_ctrl->ul_failure = true;
// 30 seconds till triggering release request
sched_ctrl->ul_failure_timer = 30000 << subcarrier_spacing;
}
void nr_mac_reset_ul_failure(NR_UE_sched_ctrl_t *sched_ctrl)
{
sched_ctrl->ul_failure = false;
sched_ctrl->ul_failure_timer = 0;
sched_ctrl->pusch_consecutive_dtx_cnt = 0;
}
void nr_mac_check_ul_failure(const gNB_MAC_INST *nrmac, int rnti, NR_UE_sched_ctrl_t *sched_ctrl)
{
if (!sched_ctrl->ul_failure)
return;
if (sched_ctrl->ul_failure_timer > 0)
sched_ctrl->ul_failure_timer--;
/* to trigger only once: trigger when ul_failure_timer == 1, but timer will
* stop at 0 and we wait for a UE release command from upper layers */
if (sched_ctrl->ul_failure_timer == 1) {
f1ap_ue_context_release_complete_t complete = {
.rnti = rnti,
.cause = F1AP_CAUSE_RADIO_NETWORK,
.cause_value = 12, // F1AP_CauseRadioNetwork_rl_failure_others
};
nrmac->mac_rrc.ue_context_release_request(&complete);
}
}
@@ -260,8 +260,7 @@ void nr_schedule_srs(int module_id, frame_t frame, int slot)
sched_ctrl->sched_srs.srs_scheduled = false;
}
if((sched_ctrl->ul_failure == 1 && get_softmodem_params()->phy_test==0) ||
sched_ctrl->rrc_processing_timer > 0) {
if ((sched_ctrl->ul_failure && !get_softmodem_params()->phy_test) || sched_ctrl->rrc_processing_timer > 0) {
continue;
}
@@ -209,7 +209,7 @@ void nr_csi_meas_reporting(int Mod_idP,
NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl;
NR_UE_UL_BWP_t *ul_bwp = &UE->current_UL_BWP;
const int n_slots_frame = nr_slots_per_frame[ul_bwp->scs];
if ((sched_ctrl->rrc_processing_timer > 0) || (sched_ctrl->ul_failure==1 && get_softmodem_params()->phy_test==0)) {
if ((sched_ctrl->rrc_processing_timer > 0) || (sched_ctrl->ul_failure && !get_softmodem_params()->phy_test)) {
continue;
}
const NR_CSI_MeasConfig_t *csi_measconfig = ul_bwp->csi_MeasConfig;
@@ -1216,7 +1216,8 @@ void nr_sr_reporting(gNB_MAC_INST *nrmac, frame_t SFN, sub_frame_t slot)
NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl;
NR_UE_UL_BWP_t *ul_bwp = &UE->current_UL_BWP;
const int n_slots_frame = nr_slots_per_frame[ul_bwp->scs];
if (sched_ctrl->ul_failure==1 || sched_ctrl->rrc_processing_timer>0) continue;
if (sched_ctrl->ul_failure || sched_ctrl->rrc_processing_timer > 0)
continue;
NR_PUCCH_Config_t *pucch_Config = ul_bwp->pucch_Config;
if (!pucch_Config || !pucch_Config->schedulingRequestResourceToAddModList)
@@ -671,9 +671,7 @@ static void _nr_rx_sdu(const module_id_t gnb_mod_idP,
if (!get_softmodem_params()->phy_test && UE->UE_sched_ctrl.pusch_consecutive_dtx_cnt >= pusch_failure_thres) {
LOG_W(NR_MAC,"Detected UL Failure on PUSCH after %d PUSCH DTX, stopping scheduling\n",
UE->UE_sched_ctrl.pusch_consecutive_dtx_cnt);
UE->UE_sched_ctrl.ul_failure = 1;
nr_mac_gNB_rrc_ul_failure(gnb_mod_idP,CC_idP,frameP,slotP,rntiP);
nr_mac_trigger_ul_failure(&UE->UE_sched_ctrl, UE->current_UL_BWP.scs);
}
}
} else if(sduP) {
@@ -757,11 +755,9 @@ static void _nr_rx_sdu(const module_id_t gnb_mod_idP,
LOG_D(NR_MAC, "[UE %04x] PUSCH TPC %d and TA %d\n", UE_msg3_stage->rnti, UE_scheduling_control->tpc0, UE_scheduling_control->ta_update);
if (ra->cfra) {
LOG_A(NR_MAC, "(rnti 0x%04x) CFRA procedure succeeded!\n", ra->rnti);
nr_mac_gNB_rrc_ul_failure_reset(gnb_mod_idP, frameP, slotP, ra->rnti);
nr_mac_reset_ul_failure(UE_scheduling_control);
reset_dl_harq_list(UE_scheduling_control);
reset_ul_harq_list(UE_scheduling_control);
UE_scheduling_control->pusch_consecutive_dtx_cnt = 0;
UE_scheduling_control->ul_failure = 0;
UE_msg3_stage->ra_timer = 0;
nr_clear_ra_proc(gnb_mod_idP, CC_idP, frameP, ra);
process_CellGroup(ra->CellGroup, UE_scheduling_control);
@@ -793,8 +789,7 @@ static void _nr_rx_sdu(const module_id_t gnb_mod_idP,
return;
} else {
// The UE identified by C-RNTI still exists at the gNB
// Reset uplink failure flags/counters/timers at RRC
nr_mac_gNB_rrc_ul_failure_reset(gnb_mod_idP, frameP, slotP, ra->crnti);
nr_mac_reset_ul_failure(&UE_C->UE_sched_ctrl);
// Reset HARQ processes
reset_dl_harq_list(&UE_C->UE_sched_ctrl);
@@ -1638,7 +1633,7 @@ static void pf_ul(module_id_t module_id,
UE_iterator(UE_list, UE) {
NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl;
if (UE->Msg4_ACKed != true || sched_ctrl->ul_failure == 1)
if (UE->Msg4_ACKed != true || sched_ctrl->ul_failure)
continue;
LOG_D(NR_MAC,"pf_ul: preparing UL scheduling for UE %04x\n",UE->rnti);
@@ -2067,7 +2062,8 @@ void nr_schedule_ulsch(module_id_t module_id, frame_t frame, sub_frame_t slot, n
const NR_SIB1_t *sib1 = nr_mac->common_channels[0].sib1 ? nr_mac->common_channels[0].sib1->message.choice.c1->choice.systemInformationBlockType1 : NULL;
UE_iterator( UE_info->list, UE) {
NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl;
if (sched_ctrl->ul_failure == 1 && get_softmodem_params()->phy_test==0) continue;
if (sched_ctrl->ul_failure && !get_softmodem_params()->phy_test)
continue;
NR_CellGroupConfig_t *cg = UE->CellGroup;
NR_UE_UL_BWP_t *current_BWP = &UE->current_UL_BWP;
+7
View File
@@ -440,4 +440,11 @@ void send_initial_ul_rrc_message(gNB_MAC_INST *mac, int rnti, const uint8_t *sdu
void abort_nr_dl_harq(NR_UE_info_t* UE, int8_t harq_pid);
void nr_mac_trigger_release_timer(NR_UE_sched_ctrl_t *sched_ctrl, NR_SubcarrierSpacing_t subcarrier_spacing);
bool nr_mac_check_release(NR_UE_sched_ctrl_t *sched_ctrl, int rnti);
void nr_mac_trigger_ul_failure(NR_UE_sched_ctrl_t *sched_ctrl, NR_SubcarrierSpacing_t subcarrier_spacing);
void nr_mac_reset_ul_failure(NR_UE_sched_ctrl_t *sched_ctrl);
void nr_mac_check_ul_failure(const gNB_MAC_INST *nrmac, int rnti, NR_UE_sched_ctrl_t *sched_ctrl);
#endif /*__LAYER2_NR_MAC_PROTO_H__*/
+147 -26
View File
@@ -33,25 +33,27 @@ static NR_RLC_BearerConfig_t *get_bearerconfig_from_srb(const f1ap_srb_to_be_set
return get_SRB_RLC_BearerConfig(srb->srb_id, priority, bucket);
}
static void handle_ue_context_srbs_setup(const f1ap_ue_context_setup_t *req,
f1ap_ue_context_setup_t *resp,
NR_CellGroupConfig_t *cellGroupConfig)
static int handle_ue_context_srbs_setup(int rnti,
int srbs_len,
const f1ap_srb_to_be_setup_t *req_srbs,
f1ap_srb_to_be_setup_t **resp_srbs,
NR_CellGroupConfig_t *cellGroupConfig)
{
DevAssert(req != NULL && resp != NULL && cellGroupConfig != NULL);
DevAssert(req_srbs != NULL && resp_srbs != NULL && cellGroupConfig != NULL);
resp->srbs_to_be_setup_length = req->srbs_to_be_setup_length;
resp->srbs_to_be_setup = calloc(req->srbs_to_be_setup_length, sizeof(*resp->srbs_to_be_setup));
AssertFatal(resp->srbs_to_be_setup != NULL, "out of memory\n");
for (int i = 0; i < req->srbs_to_be_setup_length; i++) {
f1ap_srb_to_be_setup_t *srb = &req->srbs_to_be_setup[i];
*resp_srbs = calloc(srbs_len, sizeof(**resp_srbs));
AssertFatal(*resp_srbs != NULL, "out of memory\n");
for (int i = 0; i < srbs_len; i++) {
const f1ap_srb_to_be_setup_t *srb = &req_srbs[i];
NR_RLC_BearerConfig_t *rlc_BearerConfig = get_bearerconfig_from_srb(srb);
nr_rlc_add_srb(req->rnti, srb->srb_id, rlc_BearerConfig);
nr_rlc_add_srb(rnti, srb->srb_id, rlc_BearerConfig);
resp->srbs_to_be_setup[i] = *srb;
(*resp_srbs)[i] = *srb;
int ret = ASN_SEQUENCE_ADD(&cellGroupConfig->rlc_BearerToAddModList->list, rlc_BearerConfig);
DevAssert(ret == 0);
}
return srbs_len;
}
static NR_RLC_BearerConfig_t *get_bearerconfig_from_drb(const f1ap_drb_to_be_setup_t *drb)
@@ -61,27 +63,31 @@ static NR_RLC_BearerConfig_t *get_bearerconfig_from_drb(const f1ap_drb_to_be_set
return get_DRB_RLC_BearerConfig(3 + drb->drb_id, drb->drb_id, rlc_conf, priority);
}
static void handle_ue_context_drbs_setup(const f1ap_ue_context_setup_t *req,
f1ap_ue_context_setup_t *resp,
NR_CellGroupConfig_t *cellGroupConfig)
static int handle_ue_context_drbs_setup(int rnti,
int drbs_len,
const f1ap_drb_to_be_setup_t *req_drbs,
f1ap_drb_to_be_setup_t **resp_drbs,
NR_CellGroupConfig_t *cellGroupConfig)
{
DevAssert(req != NULL && resp != NULL && cellGroupConfig != NULL);
DevAssert(req_drbs != NULL && resp_drbs != NULL && cellGroupConfig != NULL);
/* Note: the actual GTP tunnels are created in the F1AP breanch of
* ue_context_*_response() */
resp->drbs_to_be_setup_length = req->drbs_to_be_setup_length;
resp->drbs_to_be_setup = calloc(req->drbs_to_be_setup_length, sizeof(*resp->drbs_to_be_setup));
AssertFatal(resp->drbs_to_be_setup != NULL, "out of memory\n");
for (int i = 0; i < req->drbs_to_be_setup_length; i++) {
f1ap_drb_to_be_setup_t *drb = &req->drbs_to_be_setup[i];
*resp_drbs = calloc(drbs_len, sizeof(**resp_drbs));
AssertFatal(*resp_drbs != NULL, "out of memory\n");
for (int i = 0; i < drbs_len; i++) {
const f1ap_drb_to_be_setup_t *drb = &req_drbs[i];
NR_RLC_BearerConfig_t *rlc_BearerConfig = get_bearerconfig_from_drb(drb);
nr_rlc_add_drb(req->rnti, drb->drb_id, rlc_BearerConfig);
nr_rlc_add_drb(rnti, drb->drb_id, rlc_BearerConfig);
resp->drbs_to_be_setup[i] = *drb;
(*resp_drbs)[i] = *drb;
// just put same number of tunnels in DL as in UL
(*resp_drbs)[i].up_dl_tnl_length = drb->up_ul_tnl_length;
int ret = ASN_SEQUENCE_ADD(&cellGroupConfig->rlc_BearerToAddModList->list, rlc_BearerConfig);
DevAssert(ret == 0);
}
return drbs_len;
}
void ue_context_setup_request(const f1ap_ue_context_setup_t *req)
@@ -105,11 +111,20 @@ void ue_context_setup_request(const f1ap_ue_context_setup_t *req)
NR_UE_info_t *UE = find_nr_UE(&RC.nrmac[0]->UE_info, req->rnti);
AssertFatal(UE != NULL, "did not find UE with RNTI %04x, but UE Context Setup Failed not implemented\n", req->rnti);
if (req->srbs_to_be_setup_length > 0)
handle_ue_context_srbs_setup(req, &resp, UE->CellGroup);
if (req->srbs_to_be_setup_length > 0) {
resp.srbs_to_be_setup_length = handle_ue_context_srbs_setup(req->rnti,
req->srbs_to_be_setup_length,
req->srbs_to_be_setup,
&resp.srbs_to_be_setup,
UE->CellGroup);
}
if (req->drbs_to_be_setup_length > 0) {
handle_ue_context_drbs_setup(req, &resp, NULL);
resp.drbs_to_be_setup_length = handle_ue_context_drbs_setup(req->rnti,
req->drbs_to_be_setup_length,
req->drbs_to_be_setup,
&resp.drbs_to_be_setup,
UE->CellGroup);
}
if (req->rrc_container != NULL)
@@ -147,9 +162,115 @@ void ue_context_setup_request(const f1ap_ue_context_setup_t *req)
free(resp.du_to_cu_rrc_information);
}
void ue_context_modification_request(const f1ap_ue_context_modif_req_t *req)
{
gNB_MAC_INST *mac = RC.nrmac[0];
f1ap_ue_context_modif_resp_t resp = {
.gNB_CU_ue_id = req->gNB_CU_ue_id,
.gNB_DU_ue_id = req->gNB_DU_ue_id,
.rnti = req->rnti,
};
if (req->cu_to_du_rrc_information != NULL) {
AssertFatal(req->cu_to_du_rrc_information->cG_ConfigInfo == NULL, "CG-ConfigInfo not handled\n");
AssertFatal(req->cu_to_du_rrc_information->uE_CapabilityRAT_ContainerList == NULL, "UE capabilities not handled yet\n");
AssertFatal(req->cu_to_du_rrc_information->measConfig == NULL, "MeasConfig not handled\n");
}
NR_SCHED_LOCK(&mac->sched_lock);
NR_UE_info_t *UE = find_nr_UE(&RC.nrmac[0]->UE_info, req->rnti);
if (req->srbs_to_be_setup_length > 0) {
resp.srbs_to_be_setup_length = handle_ue_context_srbs_setup(req->rnti,
req->srbs_to_be_setup_length,
req->srbs_to_be_setup,
&resp.srbs_to_be_setup,
UE->CellGroup);
}
if (req->drbs_to_be_setup_length > 0) {
resp.drbs_to_be_setup_length = handle_ue_context_drbs_setup(req->rnti,
req->drbs_to_be_setup_length,
req->drbs_to_be_setup,
&resp.drbs_to_be_setup,
UE->CellGroup);
}
if (req->rrc_container != NULL)
nr_rlc_srb_recv_sdu(req->rnti, DCCH, req->rrc_container, req->rrc_container_length);
if (req->ReconfigComplOutcome != RRCreconf_info_not_present && req->ReconfigComplOutcome != RRCreconf_success) {
LOG_E(NR_MAC,
"RRC reconfiguration outcome unsuccessful, but no rollback mechanism implemented to come back to old configuration\n");
}
if (req->srbs_to_be_setup_length > 0 || req->drbs_to_be_setup_length > 0) {
/* TODO: if we change e.g. BWP or MCS table, need to automatically call
* configure_UE_BWP() (form nr_mac_update_timers()) after some time? */
resp.du_to_cu_rrc_information = calloc(1, sizeof(du_to_cu_rrc_information_t));
AssertFatal(resp.du_to_cu_rrc_information != NULL, "out of memory\n");
resp.du_to_cu_rrc_information->cellGroupConfig = calloc(1, 1024);
AssertFatal(resp.du_to_cu_rrc_information->cellGroupConfig != NULL, "out of memory\n");
asn_enc_rval_t enc_rval = uper_encode_to_buffer(&asn_DEF_NR_CellGroupConfig,
NULL,
UE->CellGroup,
resp.du_to_cu_rrc_information->cellGroupConfig,
1024);
AssertFatal(enc_rval.encoded > 0, "Could not encode CellGroup, failed element %s\n", enc_rval.failed_type->name);
resp.du_to_cu_rrc_information->cellGroupConfig_length = (enc_rval.encoded + 7) >> 3;
/* works? */
nr_mac_update_cellgroup(RC.nrmac[0], req->rnti, UE->CellGroup);
}
NR_SCHED_UNLOCK(&mac->sched_lock);
/* some sanity checks, since we use the same type for request and response */
DevAssert(resp.cu_to_du_rrc_information == NULL);
// resp.du_to_cu_rrc_information can be either NULL or not
DevAssert(resp.rrc_container == NULL && resp.rrc_container_length == 0);
mac->mac_rrc.ue_context_modification_response(req, &resp);
/* free the memory we allocated above */
free(resp.srbs_to_be_setup);
free(resp.drbs_to_be_setup);
if (resp.du_to_cu_rrc_information != NULL) {
free(resp.du_to_cu_rrc_information->cellGroupConfig);
free(resp.du_to_cu_rrc_information);
}
}
void ue_context_release_command(const f1ap_ue_context_release_cmd_t *cmd)
{
/* mark UE as to be deleted after PUSCH failure */
gNB_MAC_INST *mac = RC.nrmac[0];
pthread_mutex_lock(&mac->sched_lock);
NR_UE_info_t *UE = find_nr_UE(&mac->UE_info, cmd->rnti);
if (UE->UE_sched_ctrl.ul_failure || cmd->rrc_container_length == 0) {
/* The UE is already not connected anymore or we have nothing to forward*/
nr_rlc_remove_ue(cmd->rnti);
mac_remove_nr_ue(mac, cmd->rnti);
} else {
/* UE is in sync: forward release message and mark to be deleted
* after UL failure */
nr_rlc_srb_recv_sdu(cmd->rnti, cmd->srb_id, cmd->rrc_container, cmd->rrc_container_length);
nr_mac_trigger_release_timer(&UE->UE_sched_ctrl, UE->current_UL_BWP.scs);
}
pthread_mutex_unlock(&mac->sched_lock);
f1ap_ue_context_release_complete_t complete = {
.rnti = cmd->rnti,
};
mac->mac_rrc.ue_context_release_complete(&complete);
if (cmd->rrc_container)
free(cmd->rrc_container);
}
int dl_rrc_message(module_id_t module_id, const f1ap_dl_rrc_message_t *dl_rrc)
{
LOG_I(NR_MAC, "DL RRC Message Transfer with %d bytes for RNTI %04x SRB %d\n", dl_rrc->rrc_container_length, dl_rrc->rnti, dl_rrc->srb_id);
LOG_D(NR_MAC, "DL RRC Message Transfer with %d bytes for RNTI %04x SRB %d\n", dl_rrc->rrc_container_length, dl_rrc->rnti, dl_rrc->srb_id);
nr_rlc_srb_recv_sdu(dl_rrc->rnti, dl_rrc->srb_id, dl_rrc->rrc_container, dl_rrc->rrc_container_length);
return 0;
@@ -26,6 +26,8 @@
#include "f1ap_messages_types.h"
void ue_context_setup_request(const f1ap_ue_context_setup_t *req);
void ue_context_modification_request(const f1ap_ue_context_modif_req_t *req);
void ue_context_release_command(const f1ap_ue_context_release_cmd_t *cmd);
int dl_rrc_message(module_id_t module_id, const f1ap_dl_rrc_message_t *dl_rrc);
+4
View File
@@ -26,6 +26,10 @@
#include "f1ap_messages_types.h"
typedef void (*ue_context_setup_response_func_t)(const f1ap_ue_context_setup_t* req, const f1ap_ue_context_setup_t *resp);
typedef void (*ue_context_modification_response_func_t)(const f1ap_ue_context_modif_req_t *req,
const f1ap_ue_context_modif_resp_t *resp);
typedef void (*ue_context_release_request_func_t)(const f1ap_ue_context_release_req_t* req);
typedef void (*ue_context_release_complete_func_t)(const f1ap_ue_context_release_complete_t *complete);
typedef void (*initial_ul_rrc_message_transfer_func_t)(module_id_t module_id, const f1ap_initial_ul_rrc_message_t *ul_rrc);
@@ -55,6 +55,79 @@ static void ue_context_setup_response_direct(const f1ap_ue_context_setup_t *req,
itti_send_msg_to_task(TASK_RRC_GNB, 0, msg);
}
static void ue_context_modification_response_direct(const f1ap_ue_context_modif_req_t *req,
const f1ap_ue_context_modif_resp_t *resp)
{
(void)req; /* we don't need the request -- it is to set up GTP in F1 case */
MessageDef *msg = itti_alloc_new_message(TASK_MAC_GNB, 0, F1AP_UE_CONTEXT_MODIFICATION_RESP);
f1ap_ue_context_modif_resp_t *f1ap_msg = &F1AP_UE_CONTEXT_MODIFICATION_RESP(msg);
f1ap_msg->gNB_CU_ue_id = resp->gNB_CU_ue_id;
f1ap_msg->gNB_DU_ue_id = resp->gNB_DU_ue_id;
f1ap_msg->rnti = resp->rnti;
f1ap_msg->mcc = resp->mcc;
f1ap_msg->mnc = resp->mnc;
f1ap_msg->mnc_digit_length = resp->mnc_digit_length;
f1ap_msg->nr_cellid = resp->nr_cellid;
f1ap_msg->servCellIndex = resp->servCellIndex;
AssertFatal(resp->cellULConfigured == NULL, "not handled\n");
f1ap_msg->servCellId = resp->servCellId;
DevAssert(resp->cu_to_du_rrc_information == NULL && resp->cu_to_du_rrc_information_length == 0);
if (resp->du_to_cu_rrc_information) {
f1ap_msg->du_to_cu_rrc_information = malloc(sizeof(*resp->du_to_cu_rrc_information));
AssertFatal(f1ap_msg->du_to_cu_rrc_information != NULL, "out of memory\n");
f1ap_msg->du_to_cu_rrc_information_length = resp->du_to_cu_rrc_information_length;
du_to_cu_rrc_information_t *du2cu = f1ap_msg->du_to_cu_rrc_information;
du2cu->cellGroupConfig_length = resp->du_to_cu_rrc_information->cellGroupConfig_length;
du2cu->cellGroupConfig = calloc(du2cu->cellGroupConfig_length, sizeof(*du2cu->cellGroupConfig));
AssertFatal(du2cu->cellGroupConfig != NULL, "out of memory\n");
memcpy(du2cu->cellGroupConfig, resp->du_to_cu_rrc_information->cellGroupConfig, du2cu->cellGroupConfig_length);
}
if (resp->drbs_to_be_setup_length > 0) {
DevAssert(resp->drbs_to_be_setup != NULL);
f1ap_msg->drbs_to_be_setup_length = resp->drbs_to_be_setup_length;
f1ap_msg->drbs_to_be_setup = calloc(f1ap_msg->drbs_to_be_setup_length, sizeof(*f1ap_msg->drbs_to_be_setup));
for (int i = 0; i < f1ap_msg->drbs_to_be_setup_length; ++i)
f1ap_msg->drbs_to_be_setup[i] = resp->drbs_to_be_setup[i];
}
DevAssert(resp->drbs_to_be_modified == NULL && resp->drbs_to_be_modified_length == 0);
f1ap_msg->QoS_information_type = resp->QoS_information_type;
AssertFatal(resp->drbs_failed_to_be_setup_length == 0 && resp->drbs_failed_to_be_setup == NULL, "not implemented yet\n");
if (resp->srbs_to_be_setup_length > 0) {
DevAssert(resp->srbs_to_be_setup != NULL);
f1ap_msg->srbs_to_be_setup_length = resp->srbs_to_be_setup_length;
f1ap_msg->srbs_to_be_setup = calloc(f1ap_msg->srbs_to_be_setup_length, sizeof(*f1ap_msg->srbs_to_be_setup));
for (int i = 0; i < f1ap_msg->srbs_to_be_setup_length; ++i)
f1ap_msg->srbs_to_be_setup[i] = resp->srbs_to_be_setup[i];
}
AssertFatal(resp->srbs_failed_to_be_setup_length == 0 && resp->srbs_failed_to_be_setup == NULL, "not implemented yet\n");
DevAssert(resp->rrc_container == NULL && resp->rrc_container_length == 0);
itti_send_msg_to_task(TASK_RRC_GNB, 0, msg);
}
static void ue_context_release_request_direct(const f1ap_ue_context_release_req_t* req)
{
MessageDef *msg = itti_alloc_new_message(TASK_MAC_GNB, 0, F1AP_UE_CONTEXT_RELEASE_REQ);
f1ap_ue_context_release_req_t *f1ap_msg = &F1AP_UE_CONTEXT_RELEASE_REQ(msg);
*f1ap_msg = *req;
itti_send_msg_to_task(TASK_RRC_GNB, 0, msg);
}
static void ue_context_release_complete_direct(const f1ap_ue_context_release_complete_t *complete)
{
MessageDef *msg = itti_alloc_new_message(TASK_MAC_GNB, 0, F1AP_UE_CONTEXT_RELEASE_COMPLETE);
f1ap_ue_context_release_complete_t *f1ap_msg = &F1AP_UE_CONTEXT_RELEASE_COMPLETE(msg);
*f1ap_msg = *complete;
itti_send_msg_to_task(TASK_RRC_GNB, 0, msg);
}
static void initial_ul_rrc_message_transfer_direct(module_id_t module_id, const f1ap_initial_ul_rrc_message_t *ul_rrc)
{
MessageDef *msg = itti_alloc_new_message(TASK_MAC_GNB, 0, F1AP_INITIAL_UL_RRC_MESSAGE);
@@ -78,5 +151,8 @@ static void initial_ul_rrc_message_transfer_direct(module_id_t module_id, const
void mac_rrc_ul_direct_init(struct nr_mac_rrc_ul_if_s *mac_rrc)
{
mac_rrc->ue_context_setup_response = ue_context_setup_response_direct;
mac_rrc->ue_context_modification_response = ue_context_modification_response_direct;
mac_rrc->ue_context_release_request = ue_context_release_request_direct;
mac_rrc->ue_context_release_complete = ue_context_release_complete_direct;
mac_rrc->initial_ul_rrc_message_transfer = initial_ul_rrc_message_transfer_direct;
}
@@ -60,6 +60,60 @@ static void ue_context_setup_response_f1ap(const f1ap_ue_context_setup_t *req, c
itti_send_msg_to_task(TASK_DU_F1, 0, msg);
}
static void ue_context_modification_response_f1ap(const f1ap_ue_context_modif_req_t *req, const f1ap_ue_context_modif_resp_t *resp)
{
MessageDef *msg = itti_alloc_new_message(TASK_MAC_GNB, 0, F1AP_UE_CONTEXT_MODIFICATION_RESP);
f1ap_ue_context_modif_resp_t *f1ap_msg = &F1AP_UE_CONTEXT_MODIFICATION_RESP(msg);
/* copy all fields, but reallocate rrc_containers! */
*f1ap_msg = *resp;
if (resp->srbs_to_be_setup_length > 0) {
DevAssert(resp->srbs_to_be_setup != NULL);
f1ap_msg->srbs_to_be_setup_length = resp->srbs_to_be_setup_length;
f1ap_msg->srbs_to_be_setup = calloc(f1ap_msg->srbs_to_be_setup_length, sizeof(*f1ap_msg->srbs_to_be_setup));
for (int i = 0; i < f1ap_msg->srbs_to_be_setup_length; ++i)
f1ap_msg->srbs_to_be_setup[i] = resp->srbs_to_be_setup[i];
}
if (resp->drbs_to_be_setup_length > 0) {
DevAssert(resp->drbs_to_be_setup != NULL);
f1ap_msg->drbs_to_be_setup_length = resp->drbs_to_be_setup_length;
f1ap_msg->drbs_to_be_setup = calloc(f1ap_msg->drbs_to_be_setup_length, sizeof(*f1ap_msg->drbs_to_be_setup));
for (int i = 0; i < f1ap_msg->drbs_to_be_setup_length; ++i)
f1ap_msg->drbs_to_be_setup[i] = resp->drbs_to_be_setup[i];
}
if (resp->du_to_cu_rrc_information != NULL) {
f1ap_msg->du_to_cu_rrc_information = calloc(1, sizeof(*resp->du_to_cu_rrc_information));
AssertFatal(f1ap_msg->du_to_cu_rrc_information != NULL, "out of memory\n");
f1ap_msg->du_to_cu_rrc_information_length = resp->du_to_cu_rrc_information_length;
du_to_cu_rrc_information_t *du2cu = f1ap_msg->du_to_cu_rrc_information;
du2cu->cellGroupConfig_length = resp->du_to_cu_rrc_information->cellGroupConfig_length;
du2cu->cellGroupConfig = calloc(du2cu->cellGroupConfig_length, sizeof(*du2cu->cellGroupConfig));
AssertFatal(du2cu->cellGroupConfig != NULL, "out of memory\n");
memcpy(du2cu->cellGroupConfig, resp->du_to_cu_rrc_information->cellGroupConfig, du2cu->cellGroupConfig_length);
}
itti_send_msg_to_task(TASK_DU_F1, 0, msg);
}
static void ue_context_release_request_f1ap(const f1ap_ue_context_release_req_t* req)
{
MessageDef *msg = itti_alloc_new_message(TASK_MAC_GNB, 0, F1AP_UE_CONTEXT_RELEASE_REQ);
f1ap_ue_context_release_req_t *f1ap_msg = &F1AP_UE_CONTEXT_RELEASE_REQ(msg);
*f1ap_msg = *req;
itti_send_msg_to_task(TASK_DU_F1, 0, msg);
}
static void ue_context_release_complete_f1ap(const f1ap_ue_context_release_complete_t *complete)
{
newGtpuDeleteAllTunnels(0, complete->rnti);
MessageDef *msg = itti_alloc_new_message(TASK_MAC_GNB, 0, F1AP_UE_CONTEXT_RELEASE_COMPLETE);
f1ap_ue_context_release_complete_t *f1ap_msg = &F1AP_UE_CONTEXT_RELEASE_COMPLETE(msg);
*f1ap_msg = *complete;
itti_send_msg_to_task(TASK_DU_F1, 0, msg);
}
static void initial_ul_rrc_message_transfer_f1ap(module_id_t module_id, const f1ap_initial_ul_rrc_message_t *ul_rrc)
{
MessageDef *msg = itti_alloc_new_message(TASK_MAC_GNB, 0, F1AP_INITIAL_UL_RRC_MESSAGE);
@@ -83,6 +137,9 @@ static void initial_ul_rrc_message_transfer_f1ap(module_id_t module_id, const f1
void mac_rrc_ul_f1ap_init(struct nr_mac_rrc_ul_if_s *mac_rrc)
{
mac_rrc->ue_context_setup_response = ue_context_setup_response_f1ap;
mac_rrc->ue_context_modification_response = ue_context_modification_response_f1ap;
mac_rrc->ue_context_release_request = ue_context_release_request_f1ap;
mac_rrc->ue_context_release_complete = ue_context_release_complete_f1ap;
mac_rrc->initial_ul_rrc_message_transfer = initial_ul_rrc_message_transfer_f1ap;
}
+6 -2
View File
@@ -591,7 +591,9 @@ typedef struct {
uint8_t current_harq_pid;
int pusch_consecutive_dtx_cnt;
int pucch_consecutive_dtx_cnt;
int ul_failure;
bool ul_failure;
int ul_failure_timer;
int release_timer;
struct CSI_Report CSI_report;
bool SR;
/// information about every HARQ process
@@ -659,8 +661,10 @@ typedef struct NR_bler_options {
} NR_bler_options_t;
typedef struct nr_mac_rrc_ul_if_s {
/* TODO add other message types as necessary */
ue_context_setup_response_func_t ue_context_setup_response;
ue_context_modification_response_func_t ue_context_modification_response;
ue_context_release_request_func_t ue_context_release_request;
ue_context_release_complete_func_t ue_context_release_complete;
initial_ul_rrc_message_transfer_func_t initial_ul_rrc_message_transfer;
} nr_mac_rrc_ul_if_t;
+6 -30
View File
@@ -50,14 +50,13 @@
#include "common/openairinterface5g_limits.h"
#include "executables/lte-softmodem.h"
#include "SIMULATION/ETH_TRANSPORT/proto.h"
#include "UTIL/OSA/osa_defs.h"
#include "openair2/RRC/NAS/nas_config.h"
#include "intertask_interface.h"
#include "openair3/S1AP/s1ap_eNB.h"
#include <pthread.h>
#include "pdcp.h"
# include "openair3/ocp-gtpu/gtp_itf.h"
#include "openair3/ocp-gtpu/gtp_itf.h"
#include <openair3/ocp-gtpu/gtp_itf.h>
#include "ENB_APP/enb_config.h"
@@ -2028,19 +2027,6 @@ pdcp_config_req_asn1(const protocol_ctxt_t *const ctxt_pP,
// pdcp_remove_UE(ctxt_pP);
}
/* Security keys */
if (pdcp_pP->kUPenc != NULL) {
free(pdcp_pP->kUPenc);
}
if (pdcp_pP->kRRCint != NULL) {
free(pdcp_pP->kRRCint);
}
if (pdcp_pP->kRRCenc != NULL) {
free(pdcp_pP->kRRCenc);
}
memset(pdcp_pP, 0, sizeof(pdcp_t));
break;
@@ -2105,9 +2091,11 @@ pdcp_config_set_security(
PROTOCOL_PDCP_CTXT_ARGS(ctxt_pP,pdcp_pP),
pdcp_pP->cipheringAlgorithm,
pdcp_pP->integrityProtAlgorithm);
pdcp_pP->kRRCenc = kRRCenc;
pdcp_pP->kRRCint = kRRCint;
pdcp_pP->kUPenc = kUPenc;
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);
/* Activate security */
pdcp_pP->security_activated = 1;
}
@@ -2328,18 +2316,6 @@ pdcp_free (
pdcp_t *pdcp_p = (pdcp_t *)pdcp_pP;
if (pdcp_p != NULL) {
if (pdcp_p->kUPenc != NULL) {
free(pdcp_p->kUPenc);
}
if (pdcp_p->kRRCint != NULL) {
free(pdcp_p->kRRCint);
}
if (pdcp_p->kRRCenc != NULL) {
free(pdcp_p->kRRCenc);
}
memset(pdcp_pP, 0, sizeof(pdcp_t));
free(pdcp_pP);
}
+6 -5
View File
@@ -45,6 +45,7 @@
#include "LTE_MBMS-SessionInfoList-r9.h"
#include "LTE_PMCH-InfoList-r9.h"
#include "openair3/SECU/secu_defs.h"
typedef rlc_op_status_t (*send_rlc_data_req_func_t)(const protocol_ctxt_t *const,
const srb_flag_t, const MBMS_flag_t,
@@ -161,17 +162,17 @@ typedef struct pdcp_s {
bool is_srb;
/* Configured security algorithms */
uint8_t cipheringAlgorithm;
uint8_t integrityProtAlgorithm;
eea_alg_id_e cipheringAlgorithm;
eia_alg_id_e integrityProtAlgorithm;
/* User-Plane encryption key
* Control-Plane RRC encryption key
* Control-Plane RRC integrity key
* These keys are configured by RRC layer
*/
uint8_t *kUPenc;
uint8_t *kRRCint;
uint8_t *kRRCenc;
uint8_t kUPenc[32];
uint8_t kRRCint[32];
uint8_t kRRCenc[32];
uint8_t security_activated;
+23 -21
View File
@@ -30,7 +30,6 @@
#include "assertions.h"
#include "common/utils/LOG/log.h"
#include "UTIL/OSA/osa_defs.h"
#include "common/utils/LOG/vcd_signal_dumper.h"
#include "executables/softmodem-common.h"
@@ -39,6 +38,8 @@
#include "pdcp.h"
#include "pdcp_primitives.h"
#include "openair3/SECU/secu_defs.h"
//-----------------------------------------------------------------------------
static
uint32_t pdcp_get_next_count_tx(
@@ -110,7 +111,7 @@ pdcp_apply_security(
)
{
uint8_t *buffer_encrypted = NULL;
stream_cipher_t encrypt_params;
nas_stream_cipher_t encrypt_params = {0};
DevAssert(pdcp_pP != NULL);
DevAssert(pdcp_pdu_buffer != NULL);
@@ -156,9 +157,7 @@ pdcp_apply_security(
buffer_encrypted = &pdcp_pdu_buffer[pdcp_header_len];
/* Apply ciphering if any requested */
stream_encrypt(pdcp_pP->cipheringAlgorithm,
&encrypt_params,
&buffer_encrypted);
stream_compute_encrypt(pdcp_pP->cipheringAlgorithm, &encrypt_params, buffer_encrypted);
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_APPLY_SECURITY, VCD_FUNCTION_OUT);
@@ -180,7 +179,7 @@ pdcp_validate_security(
)
{
uint8_t *buffer_decrypted = NULL;
stream_cipher_t decrypt_params;
nas_stream_cipher_t decrypt_params = {0};
DevAssert(pdcp_pP != NULL);
@@ -199,33 +198,36 @@ pdcp_validate_security(
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");
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;
} else {
LOG_D(PDCP, "[OSA][RB %ld] %s Validating user-plane security\n",
rb_id, (pdcp_pP->is_ue != 0) ? "eNB -> UE" : "UE -> eNB");
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;
}
/* Uncipher the block */
stream_decrypt(pdcp_pP->cipheringAlgorithm,
&decrypt_params,
&buffer_decrypted);
stream_compute_encrypt(pdcp_pP->cipheringAlgorithm, &decrypt_params, buffer_decrypted);
if (!IS_SOFTMODEM_IQPLAYER) {
if (srb_flagP) {
/* Now check the integrity of the complete PDU */
/* 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;
if (stream_check_integrity(pdcp_pP->integrityProtAlgorithm,
&decrypt_params,
&pdcp_pdu_buffer[sdu_buffer_size]) != 0) {
LOG_E(PDCP, "[OSA][RB %ld] %s failed to validate MAC-I (key %llx) of incoming PDU\n",
rb_id, (pdcp_pP->is_ue != 0) ? "UE" : "eNB",((long long unsigned int*)decrypt_params.key)[0]);
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_VALIDATE_SECURITY, VCD_FUNCTION_OUT);
return -1;
if (pdcp_pP->integrityProtAlgorithm != EIA0_ALG_ID) {
uint8_t result[4] = {0};
stream_compute_integrity(pdcp_pP->integrityProtAlgorithm, &decrypt_params, result);
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",
rb_id,
(pdcp_pP->is_ue != 0) ? "UE" : "eNB",
((long long unsigned int *)decrypt_params.key)[0]);
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_VALIDATE_SECURITY, VCD_FUNCTION_OUT);
return -1;
}
}
}
} /* !IQPLAYER */
-4
View File
@@ -52,8 +52,4 @@ void nr_pdcp_e1_add_drbs(eNB_flag_t enb_flag,
}
} else
LOG_W(PDCP, "%s with void list\n", __FUNCTION__);
if (kUPenc)
free(kUPenc);
if (kUPint)
free(kUPint);
}
@@ -26,13 +26,12 @@
#include <stdint.h>
#include <openssl/cmac.h>
#include "UTIL/OSA/osa_defs.h"
int stream_compute_integrity_eia1(stream_cipher_t *stream_cipher, uint8_t out[4]);
#include "openair3/SECU/secu_defs.h"
#include "openair3/SECU/key_nas_deriver.h"
void *nr_pdcp_integrity_nia1_init(unsigned char *integrity_key)
{
stream_cipher_t *ret;
nas_stream_cipher_t *ret;
ret = calloc(1, sizeof(*ret)); if (ret == NULL) abort();
ret->key = malloc(16); if (ret->key == NULL) abort();
@@ -47,7 +46,7 @@ void nr_pdcp_integrity_nia1_integrity(void *integrity_context,
unsigned char *buffer, int length,
int bearer, int count, int direction)
{
stream_cipher_t *ctx = integrity_context;
nas_stream_cipher_t *ctx = integrity_context;
ctx->message = buffer;
ctx->count = count;
@@ -55,12 +54,12 @@ void nr_pdcp_integrity_nia1_integrity(void *integrity_context,
ctx->direction = direction;
ctx->blength = length * 8;
stream_compute_integrity_eia1(ctx, out);
stream_compute_integrity(EIA1_128_ALG_ID, ctx, out);
}
void nr_pdcp_integrity_nia1_free_integrity(void *integrity_context)
{
stream_cipher_t *ctx = integrity_context;
nas_stream_cipher_t *ctx = integrity_context;
free(ctx->key);
free(ctx);
}
+1 -10
View File
@@ -675,8 +675,7 @@ static void deliver_pdu_drb(void *deliver_pdu_data, ue_id_t ue_id, int rb_id,
req->offset = GTPU_HEADER_OVERHEAD_MAX;
req->ue_id = ue_id;
req->bearer_id = rb_id;
LOG_I(PDCP, "%s() (drb %d) sending message to gtp size %d\n",
__func__, rb_id, size);
LOG_D(PDCP, "%s() (drb %d) sending message to gtp size %d\n", __func__, rb_id, size);
extern instance_t CUuniqInstance;
itti_send_msg_to_task(TASK_GTPV1_U, CUuniqInstance, message_p);
} else {
@@ -920,10 +919,6 @@ void nr_pdcp_add_srbs(eNB_flag_t enb_flag, ue_id_t rntiMaybeUEid, NR_SRB_ToAddMo
}
} else
LOG_W(PDCP, "nr_pdcp_add_srbs() with void list\n");
if (kRRCenc)
free(kRRCenc);
if (kRRCint)
free(kRRCint);
}
void nr_pdcp_add_drbs(eNB_flag_t enb_flag,
@@ -941,10 +936,6 @@ void nr_pdcp_add_drbs(eNB_flag_t enb_flag,
}
} else
LOG_W(PDCP, "nr_pdcp_add_drbs() with void list\n");
if (kUPenc)
free(kUPenc);
if (kUPint)
free(kUPint);
}
/* Dummy function due to dependency from LTE libraries */
+1 -1
View File
@@ -104,7 +104,7 @@
#include "common/ran_context.h"
#include "secu_defs.h"
#include "key_nas_deriver.h"
#if !defined (msg)
#define msg printf
+16 -19
View File
@@ -73,7 +73,7 @@
#include "rrc_UE_ral.h"
#endif
#include "UTIL/OSA/osa_defs.h"
#include "openair3/SECU/key_nas_deriver.h"
#include "pdcp.h"
#include "plmn_data.h"
@@ -1246,12 +1246,11 @@ rrc_ue_process_radioResourceConfigDedicated(
// Establish SRBs if present
// loop through SRBToAddModList
if (radioResourceConfigDedicated->srb_ToAddModList) {
uint8_t *kRRCenc = NULL;
uint8_t *kRRCint = NULL;
derive_key_rrc_enc(UE_rrc_inst[ctxt_pP->module_id].ciphering_algorithm,
UE_rrc_inst[ctxt_pP->module_id].kenb, &kRRCenc);
derive_key_rrc_int(UE_rrc_inst[ctxt_pP->module_id].integrity_algorithm,
UE_rrc_inst[ctxt_pP->module_id].kenb, &kRRCint);
uint8_t kRRCenc[32] = {0};
uint8_t kRRCint[32] = {0};
derive_key_nas(RRC_ENC_ALG, UE_rrc_inst[ctxt_pP->module_id].ciphering_algorithm, UE_rrc_inst[ctxt_pP->module_id].kenb, kRRCenc);
derive_key_nas(RRC_INT_ALG, UE_rrc_inst[ctxt_pP->module_id].integrity_algorithm, UE_rrc_inst[ctxt_pP->module_id].kenb, kRRCint);
// Refresh SRBs
rrc_pdcp_config_asn1_req(ctxt_pP,
radioResourceConfigDedicated->srb_ToAddModList,
@@ -1397,9 +1396,9 @@ rrc_ue_process_radioResourceConfigDedicated(
LOG_I(RRC,"[UE %d] default DRB = %ld\n",ctxt_pP->module_id, *UE_rrc_inst[ctxt_pP->module_id].defaultDRB);
}
uint8_t *kUPenc = NULL;
derive_key_up_enc(UE_rrc_inst[ctxt_pP->module_id].integrity_algorithm,
UE_rrc_inst[ctxt_pP->module_id].kenb, &kUPenc);
uint8_t kUPenc[32] = {0};
derive_key_nas(UP_ENC_ALG, UE_rrc_inst[ctxt_pP->module_id].integrity_algorithm, UE_rrc_inst[ctxt_pP->module_id].kenb, kUPenc);
// Refresh DRBs
rrc_pdcp_config_asn1_req(ctxt_pP,
(LTE_SRB_ToAddModList_t *)NULL,
@@ -1549,9 +1548,9 @@ rrc_ue_process_securityModeCommand(
ul_dcch_msg.message.choice.c1.present = LTE_UL_DCCH_MessageType__c1_PR_securityModeFailure;
}
uint8_t *kRRCenc = NULL;
uint8_t *kUPenc = NULL;
uint8_t *kRRCint = NULL;
uint8_t kRRCenc[32] = {0};
uint8_t kUPenc[32] = {0};
uint8_t kRRCint[32] = {0};
pdcp_t *pdcp_p = NULL;
hash_key_t key = HASHTABLE_NOT_A_KEY_VALUE;
hashtable_rc_t h_rc;
@@ -1577,12 +1576,10 @@ rrc_ue_process_securityModeCommand(
UE_rrc_inst[ctxt_pP->module_id].kenb[20], UE_rrc_inst[ctxt_pP->module_id].kenb[21], UE_rrc_inst[ctxt_pP->module_id].kenb[22], UE_rrc_inst[ctxt_pP->module_id].kenb[23],
UE_rrc_inst[ctxt_pP->module_id].kenb[24], UE_rrc_inst[ctxt_pP->module_id].kenb[25], UE_rrc_inst[ctxt_pP->module_id].kenb[26], UE_rrc_inst[ctxt_pP->module_id].kenb[27],
UE_rrc_inst[ctxt_pP->module_id].kenb[28], UE_rrc_inst[ctxt_pP->module_id].kenb[29], UE_rrc_inst[ctxt_pP->module_id].kenb[30], UE_rrc_inst[ctxt_pP->module_id].kenb[31]);
derive_key_rrc_enc(UE_rrc_inst[ctxt_pP->module_id].ciphering_algorithm,
UE_rrc_inst[ctxt_pP->module_id].kenb, &kRRCenc);
derive_key_rrc_int(UE_rrc_inst[ctxt_pP->module_id].integrity_algorithm,
UE_rrc_inst[ctxt_pP->module_id].kenb, &kRRCint);
derive_key_up_enc(UE_rrc_inst[ctxt_pP->module_id].ciphering_algorithm,
UE_rrc_inst[ctxt_pP->module_id].kenb, &kUPenc);
derive_key_nas(RRC_ENC_ALG, UE_rrc_inst[ctxt_pP->module_id].ciphering_algorithm, UE_rrc_inst[ctxt_pP->module_id].kenb, kRRCenc);
derive_key_nas(RRC_INT_ALG, UE_rrc_inst[ctxt_pP->module_id].integrity_algorithm, UE_rrc_inst[ctxt_pP->module_id].kenb, kRRCint);
derive_key_nas(UP_ENC_ALG, UE_rrc_inst[ctxt_pP->module_id].ciphering_algorithm, UE_rrc_inst[ctxt_pP->module_id].kenb, kUPenc);
if (securityMode != 0xff) {
pdcp_config_set_security(ctxt_pP, pdcp_p, 0, 0,
+11 -18
View File
@@ -44,7 +44,6 @@
#include "RRC/LTE/MESSAGES/asn1_msg.h"
#include "LTE_RRCConnectionRequest.h"
#include "LTE_RRCConnectionReestablishmentRequest.h"
//#include "ReestablishmentCause.h"
#include "LTE_BCCH-BCH-Message.h"
#include "LTE_UL-CCCH-Message.h"
#include "LTE_DL-CCCH-Message.h"
@@ -81,15 +80,14 @@
#include "RRC/NAS/nas_config.h"
#include "RRC/NAS/rb_config.h"
#include "UTIL/OSA/osa_defs.h"
#include "rrc_eNB_S1AP.h"
#include "rrc_eNB_GTPV1U.h"
#include "rrc_eNB_M2AP.h"
#include "pdcp.h"
#include "openair3/SECU/key_nas_deriver.h"
#include "openair3/SECU/secu_defs.h"
#include "openair3/ocp-gtpu/gtp_itf.h"
#include <openair3/ocp-gtpu/gtp_itf.h>
#include "intertask_interface.h"
#include "softmodem-common.h"
@@ -114,8 +112,9 @@ mui_t rrc_eNB_mui = 0;
extern uint32_t to_earfcn_DL(int eutra_bandP, uint32_t dl_CarrierFreq, uint32_t bw);
extern int rrc_eNB_process_security(const protocol_ctxt_t *const ctxt_pP, rrc_eNB_ue_context_t *const ue_context_pP, security_capabilities_t *security_capabilities_pP);
extern void process_eNB_security_key (const protocol_ctxt_t *const ctxt_pP, rrc_eNB_ue_context_t *const ue_context_pP, uint8_t *security_key_pP);
extern int derive_keNB_star(const uint8_t *kenb_32, const uint16_t pci, const uint32_t earfcn_dl, const bool is_rel8_only, uint8_t *kenb_star);
extern void process_eNB_security_key(const protocol_ctxt_t *const ctxt_pP,
rrc_eNB_ue_context_t *const ue_context_pP,
uint8_t *security_key_pP);
extern int rrc_eNB_generate_RRCConnectionReconfiguration_endc(protocol_ctxt_t *ctxt, rrc_eNB_ue_context_t *ue_context, unsigned char *buffer, int buffer_size, OCTET_STRING_t *scg_group_config,
OCTET_STRING_t *scg_RB_config);
extern struct rrc_eNB_ue_context_s *get_first_ue_context(eNB_RRC_INST *rrc_instance_pP);
@@ -5145,9 +5144,9 @@ rrc_eNB_process_RRCConnectionReconfigurationComplete(
int drb_id;
int oip_ifup = 0;
int dest_ip_offset = 0;
uint8_t *kRRCenc = NULL;
uint8_t *kRRCint = NULL;
uint8_t *kUPenc = NULL;
uint8_t kRRCenc[32] = {0};
uint8_t kRRCint[32] = {0};
uint8_t kUPenc[32] = {0};
LTE_DRB_ToAddModList_t *DRB_configList = ue_context_pP->ue_context.DRB_configList2[xid];
LTE_SRB_ToAddModList_t *SRB_configList = ue_context_pP->ue_context.SRB_configList2[xid];
LTE_DRB_ToReleaseList_t *DRB_Release_configList2 = ue_context_pP->ue_context.DRB_Release_configList2[xid];
@@ -5178,17 +5177,11 @@ rrc_eNB_process_RRCConnectionReconfigurationComplete(
/* Derive the keys from kenb */
if (DRB_configList != NULL) {
derive_key_up_enc(ue_context_pP->ue_context.ciphering_algorithm,
ue_context_pP->ue_context.kenb,
&kUPenc);
derive_key_nas(UP_ENC_ALG, ue_context_pP->ue_context.ciphering_algorithm, ue_context_pP->ue_context.kenb, kUPenc);
}
derive_key_rrc_enc(ue_context_pP->ue_context.ciphering_algorithm,
ue_context_pP->ue_context.kenb,
&kRRCenc);
derive_key_rrc_int(ue_context_pP->ue_context.integrity_algorithm,
ue_context_pP->ue_context.kenb,
&kRRCint);
derive_key_nas(RRC_ENC_ALG, ue_context_pP->ue_context.ciphering_algorithm, ue_context_pP->ue_context.kenb, kRRCenc);
derive_key_nas(RRC_INT_ALG, ue_context_pP->ue_context.integrity_algorithm, ue_context_pP->ue_context.kenb, kRRCint);
/* Refresh SRBs/DRBs */
rrc_pdcp_config_asn1_req(ctxt_pP,
SRB_configList, // NULL,
+13 -16
View File
@@ -46,12 +46,14 @@
#include "pdcp.h"
#include "pdcp_primitives.h"
#include "UTIL/OSA/osa_defs.h"
#include "LTE_UERadioAccessCapabilityInformation.h"
#include "openair3/ocp-gtpu/gtp_itf.h"
#include <openair3/ocp-gtpu/gtp_itf.h>
#include "openair3/SECU/secu_defs.h"
#include "openair3/SECU/key_nas_deriver.h"
#include "RRC/LTE/rrc_eNB_GTPV1U.h"
#include "TLVDecoder.h"
@@ -485,9 +487,9 @@ rrc_pdcp_config_security(
//------------------------------------------------------------------------------
{
LTE_SRB_ToAddModList_t *SRB_configList = ue_context_pP->ue_context.SRB_configList;
uint8_t *kRRCenc = NULL;
uint8_t *kRRCint = NULL;
uint8_t *kUPenc = NULL;
uint8_t kRRCenc[32] = {0};
uint8_t kRRCint[32] = {0};
uint8_t kUPenc[32] = {0};
pdcp_t *pdcp_p = NULL;
static int print_keys= 1;
hashtable_rc_t h_rc;
@@ -495,19 +497,13 @@ rrc_pdcp_config_security(
/* Derive the keys from kenb */
if (SRB_configList != NULL) {
derive_key_up_enc(ue_context_pP->ue_context.ciphering_algorithm,
ue_context_pP->ue_context.kenb,
&kUPenc);
derive_key_nas(UP_ENC_ALG, ue_context_pP->ue_context.ciphering_algorithm, ue_context_pP->ue_context.kenb, kUPenc);
}
derive_key_rrc_enc(ue_context_pP->ue_context.ciphering_algorithm,
ue_context_pP->ue_context.kenb,
&kRRCenc);
derive_key_rrc_int(ue_context_pP->ue_context.integrity_algorithm,
ue_context_pP->ue_context.kenb,
&kRRCint);
if (!IS_SOFTMODEM_IQPLAYER) {
SET_LOG_DUMP(DEBUG_SECURITY) ;
derive_key_nas(RRC_ENC_ALG, ue_context_pP->ue_context.ciphering_algorithm, ue_context_pP->ue_context.kenb, kRRCenc);
derive_key_nas(RRC_INT_ALG, ue_context_pP->ue_context.integrity_algorithm, ue_context_pP->ue_context.kenb, kRRCint);
if (!IS_SOFTMODEM_IQPLAYER) {
SET_LOG_DUMP(DEBUG_SECURITY);
}
@@ -953,6 +949,7 @@ int rrc_eNB_process_S1AP_INITIAL_CONTEXT_SETUP_REQ(MessageDef *msg_p, const char
&ctxt,
ue_context_p,
S1AP_INITIAL_CONTEXT_SETUP_REQ(msg_p).security_key);
{
uint8_t send_security_mode_command = true;
rrc_pdcp_config_security(
-29
View File
@@ -118,32 +118,3 @@ int8_t nr_mac_rrc_bwp_switch_req(const module_id_t module_idP,
return 0;
}
void nr_mac_gNB_rrc_ul_failure(const module_id_t Mod_instP,
const int CC_idP,
const frame_t frameP,
const sub_frame_t subframeP,
const rnti_t rntiP) {
rrc_gNB_ue_context_t *ue_context_p = rrc_gNB_get_ue_context_by_rnti(RC.nrrrc[Mod_instP], rntiP);
if (ue_context_p != NULL) {
LOG_D(RRC,"Frame %d, Subframe %d: UE %x UL failure, activating timer\n",frameP,subframeP,rntiP);
if(ue_context_p->ue_context.ul_failure_timer == 0)
ue_context_p->ue_context.ul_failure_timer=1;
} else {
LOG_D(RRC,"Frame %d, Subframe %d: UL failure: UE %x unknown \n",frameP,subframeP,rntiP);
}
}
void nr_mac_gNB_rrc_ul_failure_reset(const module_id_t Mod_instP,
const frame_t frameP,
const sub_frame_t subframeP,
const rnti_t rntiP) {
rrc_gNB_ue_context_t *ue_context_p = rrc_gNB_get_ue_context_by_rnti(RC.nrrrc[Mod_instP], rntiP);
if (ue_context_p != NULL) {
LOG_W(RRC,"Frame %d, Subframe %d: UE %x UL failure reset, deactivating timer\n",frameP,subframeP,rntiP);
ue_context_p->ue_context.ul_failure_timer=0;
} else {
LOG_W(RRC,"Frame %d, Subframe %d: UL failure reset: UE %x unknown \n",frameP,subframeP,rntiP);
}
}
+3 -1
View File
@@ -46,7 +46,9 @@
#include "LAYER2/nr_rlc/nr_rlc_oai_api.h"
#include "asn1_msg.h"
#include "../nr_rrc_proto.h"
#include "UTIL/OSA/osa_defs.h"
#include "openair3/SECU/key_nas_deriver.h"
#include "RRC/NR/nr_rrc_extern.h"
#include "NR_DL-CCCH-Message.h"
#include "NR_UL-CCCH-Message.h"
+34 -13
View File
@@ -29,7 +29,8 @@
#include "nr_rrc_proto.h"
#include "nr_rrc_extern.h"
#include "openair2/COMMON/e1ap_messages_types.h"
#include "UTIL/OSA/osa_defs.h"
#include "openair3/SECU/key_nas_deriver.h"
#include "nr_pdcp/nr_pdcp_entity.h"
#include "openair2/LAYER2/nr_pdcp/nr_pdcp_e1_api.h"
#include <openair2/RRC/NR/rrc_gNB_UE_context.h>
@@ -38,6 +39,7 @@
#include "common/ran_context.h"
#include "openair2/F1AP/f1ap_common.h"
#include "openair2/E1AP/e1ap_common.h"
extern RAN_CONTEXT_t RC;
void fill_e1ap_bearer_setup_resp(e1ap_bearer_setup_resp_t *resp,
@@ -134,18 +136,19 @@ static int drb_config_gtpu_create(const protocol_ctxt_t *const ctxt_p,
nr_rrc_gNB_process_GTPV1U_CREATE_TUNNEL_RESP(ctxt_p, &create_tunnel_resp, 0);
uint8_t *kRRCenc = NULL;
uint8_t *kRRCint = NULL;
uint8_t *kUPenc = NULL;
uint8_t *kUPint = NULL;
uint8_t kRRCenc[16] = {0};
uint8_t kRRCint[16] = {0};
uint8_t kUPenc[16] = {0};
uint8_t kUPint[16] = {0};
/* Derive the keys from kgnb */
if (DRB_configList != NULL) {
nr_derive_key_up_enc(UE->ciphering_algorithm, UE->kgnb, &kUPenc);
nr_derive_key_up_int(UE->integrity_algorithm, UE->kgnb, &kUPint);
nr_derive_key(UP_ENC_ALG, UE->ciphering_algorithm, UE->kgnb, kUPenc);
nr_derive_key(UP_INT_ALG, UE->integrity_algorithm, UE->kgnb, kUPint);
}
nr_derive_key_rrc_enc(UE->ciphering_algorithm, UE->kgnb, &kRRCenc);
nr_derive_key_rrc_int(UE->integrity_algorithm, UE->kgnb, &kRRCint);
nr_derive_key(RRC_ENC_ALG, UE->ciphering_algorithm, UE->kgnb, kRRCenc);
nr_derive_key(RRC_INT_ALG, UE->integrity_algorithm, UE->kgnb, kRRCint);
/* Refresh SRBs/DRBs */
LOG_D(NR_RRC, "Configuring PDCP DRBs/SRBs for UE %x\n", UE->rnti);
@@ -187,6 +190,19 @@ static void cucp_cuup_bearer_context_setup_direct(e1ap_bearer_setup_req_t *const
PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, 0, GNB_FLAG_YES, UE->rnti, 0, 0, 0);
fill_DRB_configList(&ctxt, ue_context_p, xid);
e1ap_bearer_setup_resp_t resp = {0};
resp.numPDUSessions = req->numPDUSessions;
for (int i = 0; i < resp.numPDUSessions; ++i) {
resp.pduSession[i].numDRBSetup = req->pduSession[i].numDRB2Setup;
for (int j = 0; j < req->pduSession[i].numDRB2Setup; j++) {
DRB_nGRAN_to_setup_t *req_drb = req->pduSession[i].DRBnGRanList + j;
DRB_nGRAN_setup_t *resp_drb = resp.pduSession[i].DRBnGRanList + j;
resp_drb->id = req_drb->id;
resp_drb->numQosFlowSetup = req_drb->numQosFlow2Setup;
for (int k = 0; k < resp_drb->numQosFlowSetup; k++)
resp_drb->qosFlows[k].id = req_drb->qosFlows[k].id;
}
}
gNB_RRC_INST *rrc = RC.nrrrc[ctxt.module_id];
// Fixme: xid not random, but almost!
@@ -195,21 +211,26 @@ static void cucp_cuup_bearer_context_setup_direct(e1ap_bearer_setup_req_t *const
int ret = drb_config_gtpu_create(&ctxt, ue_context_p, req, UE->DRB_configList, *SRB_configList2, rrc->e1_inst);
if (ret < 0) AssertFatal(false, "Unable to configure DRB or to create GTP Tunnel\n");
// Used to store teids: if monolithic, will simply be NULL
if(!NODE_IS_CU(RC.nrrrc[ctxt.module_id]->node_type)) {
rrc_gNB_generate_dedicatedRRCReconfiguration(&ctxt, ue_context_p, NULL);
// intentionally empty
} else {
e1ap_bearer_setup_resp_t resp; // Used to store teids
int remote_port = RC.nrrrc[ctxt.module_id]->eth_params_s.remote_portd;
in_addr_t my_addr = inet_addr(RC.nrrrc[ctxt.module_id]->eth_params_s.my_addr);
instance_t gtpInst = getCxt(CUtype, instance)->gtpInst;
// GTP tunnel for DL
fill_e1ap_bearer_setup_resp(&resp, req, gtpInst, UE->rnti, remote_port, my_addr);
prepare_and_send_ue_context_modification_f1(ue_context_p, &resp);
}
// actually, we should receive the corresponding context setup response
// message at the RRC and always react to this one. So in the following, we
// just call the corresponding message handler
prepare_and_send_ue_context_modification_f1(ue_context_p, &resp);
}
static void cucp_cuup_bearer_context_mod_direct(e1ap_bearer_setup_req_t *const req, instance_t instance, uint8_t xid) {
// only update GTP tunnels if it is really a CU
if (!NODE_IS_CU(RC.nrrrc[0]->node_type))
return;
instance_t gtpInst = getCxt(CUtype, instance)->gtpInst;
CU_update_UP_DL_tunnel(req, gtpInst, req->rnti);
}
+2 -1
View File
@@ -29,7 +29,8 @@
#include "nr_rrc_extern.h"
#include "cucp_cuup_if.h"
#include "openair2/COMMON/e1ap_messages_types.h"
#include "UTIL/OSA/osa_defs.h"
#include "openair3/SECU/secu_defs.h"
#include <openair2/RRC/NR/rrc_gNB_UE_context.h>
#include "common/ran_context.h"
+2
View File
@@ -26,6 +26,8 @@
#include "f1ap_messages_types.h"
typedef void (*ue_context_setup_request_func_t)(const f1ap_ue_context_setup_t *req);
typedef void (*ue_context_modification_request_func_t)(const f1ap_ue_context_modif_req_t *req);
typedef void (*ue_context_release_command_func_t)(const f1ap_ue_context_release_cmd_t *cmd);
typedef void (*dl_rrc_message_transfer_func_t)(module_id_t module_id, const f1ap_dl_rrc_message_t *dl_rrc);
+2
View File
@@ -34,5 +34,7 @@ static void dl_rrc_message_transfer_direct(module_id_t module_id, const f1ap_dl_
void mac_rrc_dl_direct_init(nr_mac_rrc_dl_if_t *mac_rrc)
{
mac_rrc->ue_context_setup_request = ue_context_setup_request;
mac_rrc->ue_context_modification_request = ue_context_modification_request;
mac_rrc->ue_context_release_command = ue_context_release_command;
mac_rrc->dl_rrc_message_transfer = dl_rrc_message_transfer_direct;
}
+42
View File
@@ -30,6 +30,8 @@ static void ue_context_setup_request_f1ap(const f1ap_ue_context_setup_t *req)
f1ap_ue_context_setup_t *f1ap_msg = &F1AP_UE_CONTEXT_SETUP_REQ(msg);
*f1ap_msg = *req;
AssertFatal(req->cu_to_du_rrc_information == NULL, "cu_to_du_rrc_information not supported yet\n");
AssertFatal(req->drbs_to_be_setup == NULL, "drbs_to_be_setup not supported yet\n");
AssertFatal(req->srbs_to_be_setup == NULL, "drbs_to_be_setup not supported yet\n");
if (req->rrc_container_length > 0) {
f1ap_msg->rrc_container = calloc(req->rrc_container_length, sizeof(*f1ap_msg->rrc_container));
AssertFatal(f1ap_msg->rrc_container != NULL, "out of memory\n");
@@ -39,6 +41,44 @@ static void ue_context_setup_request_f1ap(const f1ap_ue_context_setup_t *req)
itti_send_msg_to_task(TASK_CU_F1, 0, msg);
}
static void ue_context_modification_request_f1ap(const f1ap_ue_context_modif_req_t *req)
{
MessageDef *msg = itti_alloc_new_message(TASK_RRC_GNB, 0, F1AP_UE_CONTEXT_MODIFICATION_REQ);
f1ap_ue_context_modif_req_t *f1ap_msg = &F1AP_UE_CONTEXT_MODIFICATION_REQ(msg);
*f1ap_msg = *req;
AssertFatal(req->cu_to_du_rrc_information == NULL, "cu_to_du_rrc_information not supported yet\n");
AssertFatal(req->drbs_to_be_modified_length == 0, "drbs_to_be_modified not supported yet\n");
if (req->drbs_to_be_setup_length > 0) {
int n = req->drbs_to_be_setup_length;
f1ap_msg->drbs_to_be_setup_length = n;
f1ap_msg->drbs_to_be_setup = calloc(n, sizeof(*f1ap_msg->drbs_to_be_setup));
AssertFatal(f1ap_msg->drbs_to_be_setup != NULL, "out of memory\n");
memcpy(f1ap_msg->drbs_to_be_setup, req->drbs_to_be_setup, n * sizeof(*f1ap_msg->drbs_to_be_setup));
}
if (req->srbs_to_be_setup_length > 0) {
int n = req->srbs_to_be_setup_length;
f1ap_msg->srbs_to_be_setup_length = n;
f1ap_msg->srbs_to_be_setup = calloc(n, sizeof(*f1ap_msg->srbs_to_be_setup));
AssertFatal(f1ap_msg->srbs_to_be_setup != NULL, "out of memory\n");
memcpy(f1ap_msg->srbs_to_be_setup, req->srbs_to_be_setup, n * sizeof(*f1ap_msg->srbs_to_be_setup));
}
if (req->rrc_container_length > 0) {
f1ap_msg->rrc_container = calloc(req->rrc_container_length, sizeof(*f1ap_msg->rrc_container));
AssertFatal(f1ap_msg->rrc_container != NULL, "out of memory\n");
f1ap_msg->rrc_container_length = req->rrc_container_length;
memcpy(f1ap_msg->rrc_container, req->rrc_container, req->rrc_container_length);
}
itti_send_msg_to_task(TASK_CU_F1, 0, msg);
}
static void ue_context_release_command_f1ap(const f1ap_ue_context_release_cmd_t *cmd)
{
MessageDef *message_p = itti_alloc_new_message (TASK_RRC_GNB, 0, F1AP_UE_CONTEXT_RELEASE_CMD);
f1ap_ue_context_release_cmd_t *msg = &F1AP_UE_CONTEXT_RELEASE_CMD(message_p);
*msg = *cmd;
itti_send_msg_to_task (TASK_CU_F1, 0, message_p);
}
static void dl_rrc_message_transfer_f1ap(module_id_t module_id, const f1ap_dl_rrc_message_t *dl_rrc)
{
/* TODO call F1AP function directly? no real-time constraint here */
@@ -58,5 +98,7 @@ static void dl_rrc_message_transfer_f1ap(module_id_t module_id, const f1ap_dl_rr
void mac_rrc_dl_f1ap_init(nr_mac_rrc_dl_if_t *mac_rrc)
{
mac_rrc->ue_context_setup_request = ue_context_setup_request_f1ap;
mac_rrc->ue_context_modification_request = ue_context_modification_request_f1ap;
mac_rrc->ue_context_release_command = ue_context_release_command_f1ap;
mac_rrc->dl_rrc_message_transfer = dl_rrc_message_transfer_f1ap;
}
+2 -12
View File
@@ -313,17 +313,6 @@ typedef struct gNB_RRC_UE_s {
int nb_of_pdusessions;
rrc_pdu_session_param_t pduSession[NGAP_MAX_PDU_SESSION];
rrc_action_t xids[NR_RRC_TRANSACTION_IDENTIFIER_NUMBER];
uint32_t ul_failure_timer;
uint32_t ue_release_timer;
uint32_t ue_release_timer_thres;
uint32_t ue_release_timer_s1;
uint32_t ue_release_timer_thres_s1;
uint32_t ue_release_timer_ng;
uint32_t ue_release_timer_thres_ng;
uint32_t ue_release_timer_rrc;
uint32_t ue_release_timer_thres_rrc;
uint32_t ue_reestablishment_timer;
uint32_t ue_reestablishment_timer_thres;
uint8_t e_rab_release_command_flag;
uint32_t ue_rrc_inactivity_timer;
uint32_t ue_reestablishment_counter;
@@ -389,8 +378,9 @@ typedef struct {
} nr_security_configuration_t;
typedef struct nr_mac_rrc_dl_if_s {
/* TODO add other message types as necessary */
ue_context_setup_request_func_t ue_context_setup_request;
ue_context_modification_request_func_t ue_context_modification_request;
ue_context_release_command_func_t ue_context_release_command;
dl_rrc_message_transfer_func_t dl_rrc_message_transfer;
} nr_mac_rrc_dl_if_t;
+1 -8
View File
@@ -111,9 +111,6 @@ rrc_gNB_generate_RRCRelease(
\param void *args_p Pointer on arguments to start the task. */
void *rrc_gnb_task(void *args_p);
/* Trigger RRC periodic processing. To be called once per ms. */
void nr_rrc_trigger(protocol_ctxt_t *ctxt, int CC_id, int frame, int subframe);
/**\ Function to set or overwrite PTRS DL RRC parameters.
\ *bwp Pointer to dedicated RC config structure
\ *ptrsNrb Pointer to K_ptrs N_RB related parameters
@@ -145,11 +142,7 @@ rrc_gNB_generate_dedicatedRRCReconfiguration_release(
uint32_t nas_length,
uint8_t *nas_buffer);
void
rrc_gNB_generate_dedicatedRRCReconfiguration(
const protocol_ctxt_t *const ctxt_pP,
rrc_gNB_ue_context_t *ue_context_pP,
NR_CellGroupConfig_t *cell_groupConfig_from_DU);
void rrc_gNB_generate_dedicatedRRCReconfiguration(const protocol_ctxt_t *const ctxt_pP, rrc_gNB_ue_context_t *ue_context_pP);
void bearer_context_setup_direct(e1ap_bearer_setup_req_t *req,
instance_t instance);
+186 -510
View File
@@ -75,7 +75,7 @@
#include "RRC/NAS/nas_config.h"
#include "RRC/NAS/rb_config.h"
#include "UTIL/OSA/osa_defs.h"
#include "openair3/SECU/secu_defs.h"
#include "rrc_gNB_NGAP.h"
@@ -90,6 +90,7 @@
#include "executables/softmodem-common.h"
#include <openair2/RRC/NR/rrc_gNB_UE_context.h>
#include <openair2/X2AP/x2ap_eNB.h>
#include <openair3/SECU/key_nas_deriver.h>
#include <openair3/ocp-gtpu/gtp_itf.h>
#include <openair2/RRC/NR/nr_rrc_proto.h>
#include "openair2/LAYER2/nr_pdcp/nr_pdcp_e1_api.h"
@@ -111,23 +112,6 @@ mui_t rrc_gNB_mui = 0;
///---------------------------------------------------------------------------------------------------------------///
///---------------------------------------------------------------------------------------------------------------///
bool DURecvCb(protocol_ctxt_t *ctxt_pP,
const srb_flag_t srb_flagP,
const rb_id_t rb_idP,
const mui_t muiP,
const confirm_t confirmP,
const sdu_size_t sdu_buffer_sizeP,
unsigned char *const sdu_buffer_pP,
const pdcp_transmission_mode_t modeP,
const uint32_t *sourceL2Id,
const uint32_t *destinationL2Id) {
// The buffer comes from the stack in gtp-u thread, we have a make a separate buffer to enqueue in a inter-thread message queue
mem_block_t *sdu=get_free_mem_block(sdu_buffer_sizeP, __func__);
memcpy(sdu->data, sdu_buffer_pP, sdu_buffer_sizeP);
du_rlc_data_req(ctxt_pP,srb_flagP, false, rb_idP,muiP, confirmP, sdu_buffer_sizeP, sdu);
return true;
}
static void nr_rrc_addmod_srbs(int rnti,
const NR_SRB_ToAddModList_t *srb_list,
const struct NR_CellGroupConfig__rlc_BearerToAddModList *bearer_list)
@@ -359,11 +343,6 @@ static void rrc_gNB_generate_RRCSetup(instance_t instance,
size,
"[MSG] RRC Setup\n");
// activate release timer, if RRCSetupComplete not received after 100 frames, remove UE
ue_context_pP->ue_context.ue_release_timer = 1;
// remove UE after 10 frames after RRCConnectionRelease is triggered
ue_context_pP->ue_context.ue_release_timer_thres = 1000;
nr_pdcp_add_srbs(true, rnti, ue_context_pP->ue_context.SRB_configList, 0, NULL, NULL);
f1ap_dl_rrc_message_t dl_rrc = {
@@ -414,20 +393,11 @@ static int rrc_gNB_generate_RRCSetup_for_RRCReestablishmentRequest(module_id_t m
nr_mac_config_sib1(RC.nrmac[rrc_instance_p->module_id], rrc_instance_p->carrier.siblock1);
LOG_I(NR_RRC, " [RAPROC] rnti: %04x Logical Channel DL-CCCH, Generating RRCSetup (bytes %d)\n", rnti, size);
// activate release timer, if RRCSetupComplete not received after 100 frames, remove UE
ue_context_pP->ue_context.ue_release_timer = 1;
// remove UE after 10 frames after RRCConnectionRelease is triggered
ue_context_pP->ue_context.ue_release_timer_thres = 1000;
// configure MAC
protocol_ctxt_t ctxt = {0};
PROTOCOL_CTXT_SET_BY_INSTANCE(&ctxt, 0, GNB_FLAG_YES, rnti, 0, 0);
apply_macrlc_config(rrc_instance_p, ue_context_pP, &ctxt);
//nr_pdcp_add_srbs(ctxt_pP->enb_flag, ctxt_pP->rntiMaybeUEid, ue_context_pP->ue_context.SRB_configList, 0, NULL, NULL);
//apply_pdcp_config(ue_context_pP,ctxt_pP);
/* init timers */
// ue_context_pP->ue_context.ue_rrc_inactivity_timer = 0;
f1ap_dl_rrc_message_t dl_rrc = {
.old_gNB_DU_ue_id = 0xFFFFFF,
.rrc_container = buf,
@@ -655,17 +625,10 @@ void fill_DRB_configList(const protocol_ctxt_t *const ctxt_pP, rrc_gNB_ue_contex
}
//-----------------------------------------------------------------------------
void
rrc_gNB_generate_dedicatedRRCReconfiguration(
const protocol_ctxt_t *const ctxt_pP,
rrc_gNB_ue_context_t *ue_context_pP,
NR_CellGroupConfig_t *cell_groupConfig_from_DU
)
void rrc_gNB_generate_dedicatedRRCReconfiguration(const protocol_ctxt_t *const ctxt_pP, rrc_gNB_ue_context_t *ue_context_pP)
//-----------------------------------------------------------------------------
{
gNB_RRC_INST *rrc = RC.nrrrc[ctxt_pP->module_id];
long drb_priority[NGAP_MAX_DRBS_PER_UE];
NR_CellGroupConfig_t *cellGroupConfig = NULL;
int xid = -1;
int drb_id_to_setup_start = 1;
@@ -696,7 +659,6 @@ rrc_gNB_generate_dedicatedRRCReconfiguration(
}
xid = ue_p->pduSession[j].xid;
drb_priority[DRB_config->drb_Identity - 1] = 13; // For now, we assume only one drb per pdu sessions with a default preiority (will be dynamique in future)
}
/* If list is empty free the list and reset the address */
@@ -705,20 +667,7 @@ rrc_gNB_generate_dedicatedRRCReconfiguration(
dedicatedNAS_MessageList = NULL;
}
if(cell_groupConfig_from_DU == NULL){
cellGroupConfig = calloc(1, sizeof(NR_CellGroupConfig_t));
// FIXME: fill_mastercellGroupConfig() won't fill the right priorities
fill_mastercellGroupConfig(cellGroupConfig,
ue_p->masterCellGroup,
rrc->um_on_default_drb,
(drb_id_to_setup_start < 2) ? 1 : 0,
DRB_configList,
drb_priority);
}
else{
LOG_I(NR_RRC, "Master cell group originating from the DU \n");
cellGroupConfig = cell_groupConfig_from_DU;
}
NR_CellGroupConfig_t *cellGroupConfig = ue_p->masterCellGroup;
AssertFatal(xid > -1, "Invalid xid %d. No PDU sessions setup to configure.\n", xid);
NR_SRB_ToAddModList_t *SRB_configList2 = NULL;
@@ -1035,31 +984,28 @@ rrc_gNB_generate_dedicatedRRCReconfiguration_release(
static void rrc_gNB_process_RRCReconfigurationComplete(const protocol_ctxt_t *const ctxt_pP, rrc_gNB_ue_context_t *ue_context_pP, const uint8_t xid)
{
int drb_id;
uint8_t *kRRCenc = NULL;
uint8_t *kRRCint = NULL;
uint8_t *kUPenc = NULL;
uint8_t *kUPint = NULL;
gNB_RRC_UE_t *ue_p = &ue_context_pP->ue_context;
NR_DRB_ToAddModList_t *DRB_configList = ue_p->DRB_configList2[xid];
NR_SRB_ToAddModList_t *SRB_configList = ue_p->SRB_configList2[xid];
NR_DRB_ToReleaseList_t *DRB_Release_configList2 = ue_p->DRB_Release_configList2[xid];
uint8_t kRRCenc[16] = {0};
uint8_t kRRCint[16] = {0};
uint8_t kUPenc[16] = {0};
uint8_t kUPint[16] = {0};
NR_DRB_ToAddModList_t *DRB_configList = ue_context_pP->ue_context.DRB_configList2[xid];
NR_SRB_ToAddModList_t *SRB_configList = ue_context_pP->ue_context.SRB_configList2[xid];
NR_DRB_ToReleaseList_t *DRB_Release_configList2 = ue_context_pP->ue_context.DRB_Release_configList2[xid];
NR_DRB_Identity_t *drb_id_p = NULL;
// uint8_t nr_DRB2LCHAN[8];
ue_p->ue_reestablishment_timer = 0;
gNB_RRC_UE_t *ue_p = &ue_context_pP->ue_context;
/* Derive the keys from kgnb */
if (DRB_configList != NULL) {
nr_derive_key_up_enc(ue_p->ciphering_algorithm, ue_p->kgnb, &kUPenc);
nr_derive_key_up_int(ue_p->integrity_algorithm, ue_p->kgnb, &kUPint);
nr_derive_key(UP_ENC_ALG, ue_p->ciphering_algorithm, ue_p->kgnb, kUPenc);
nr_derive_key(UP_INT_ALG, ue_p->integrity_algorithm, ue_p->kgnb, kUPint);
}
nr_derive_key_rrc_enc(ue_p->ciphering_algorithm, ue_p->kgnb, &kRRCenc);
nr_derive_key_rrc_int(ue_p->integrity_algorithm, ue_p->kgnb, &kRRCint);
nr_derive_key(RRC_ENC_ALG, ue_p->ciphering_algorithm, ue_p->kgnb, kRRCenc);
nr_derive_key(RRC_INT_ALG, ue_p->integrity_algorithm, ue_p->kgnb, kRRCint);
/* Refresh SRBs/DRBs */
LOG_D(NR_RRC, "Configuring PDCP DRBs/SRBs for UE %04x\n", ue_p->rnti);
ue_id_t reestablish_ue_id = 0;
if (DRB_configList && DRB_configList->list.array[0]->reestablishPDCP && *DRB_configList->list.array[0]->reestablishPDCP == NR_DRB_ToAddMod__reestablishPDCP_true) {
for (int i = 0; i < MAX_MOBILES_PER_GNB; i++) {
@@ -1226,16 +1172,16 @@ void rrc_gNB_generate_RRCReestablishment(const protocol_ctxt_t *ctxt_pP,
LOG_I(NR_RRC, "[RAPROC] UE %04x Logical Channel DL-DCCH, Generating NR_RRCReestablishment (bytes %d)\n", ue_p->rnti, size);
uint8_t *kRRCenc = NULL;
uint8_t *kRRCint = NULL;
uint8_t *kUPenc = NULL;
uint8_t kRRCenc[16] = {0};
uint8_t kRRCint[16] = {0};
uint8_t kUPenc[16] = {0};
/* Derive the keys from kgnb */
if (SRB_configList != NULL) {
nr_derive_key_up_enc(ue_p->ciphering_algorithm, ue_p->kgnb, &kUPenc);
nr_derive_key(UP_ENC_ALG, ue_p->ciphering_algorithm, ue_p->kgnb, kUPenc);
}
nr_derive_key_rrc_enc(ue_p->ciphering_algorithm, ue_p->kgnb, &kRRCenc);
nr_derive_key_rrc_int(ue_p->integrity_algorithm, ue_p->kgnb, &kRRCint);
nr_derive_key(RRC_ENC_ALG, ue_p->ciphering_algorithm, ue_p->kgnb, kRRCenc);
nr_derive_key(RRC_INT_ALG, ue_p->integrity_algorithm, ue_p->kgnb, kRRCint);
/* Configure SRB1 for UE */
if (*SRB_configList != NULL) {
@@ -1406,12 +1352,7 @@ void RRCReestablishmentComplete_update_ngu_tunnel(const protocol_ctxt_t *const c
if (ret != 0) {
LOG_E(NR_RRC, "RRC Reestablishment - gtpv1u_update_ngu_tunnel failed,start to release UE %x\n", reestablish_rnti);
ue_p->ue_release_timer_s1 = 1;
ue_p->ue_release_timer_thres_s1 = 100;
ue_p->ue_release_timer = 0;
ue_p->ue_reestablishment_timer = 0;
ue_p->ul_failure_timer = 20000; // set ul_failure to 20000 for triggering rrc_eNB_send_S1AP_UE_CONTEXT_RELEASE_REQ
ue_p->ul_failure_timer = 0;
AssertFatal(false, "not implemented\n");
return;
}
}
@@ -1470,7 +1411,6 @@ void rrc_gNB_process_RRCReestablishmentComplete(const protocol_ctxt_t *const ctx
uint8_t new_xid = rrc_gNB_get_next_transaction_identifier(ctxt_pP->module_id);
ue_p->xids[new_xid] = RRC_REESTABLISH_COMPLETE;
ue_p->StatusRrc = NR_RRC_CONNECTED;
ue_p->ue_rrc_inactivity_timer = 1; // set rrc inactivity when UE goes into RRC_CONNECTED
RRCReestablishmentComplete_fill_SRB2_configList(ctxt_pP, ue_context_pP, xid, new_xid);
RRCReestablishmentComplete_fill_DRB_configList(ctxt_pP, ue_context_pP, new_xid);
RRCReestablishmentComplete_update_ngu_tunnel(ctxt_pP, ue_context_pP, reestablish_rnti);
@@ -1665,9 +1605,8 @@ static int nr_rrc_gNB_decode_ccch(module_id_t module_id, rnti_t rnti, const uint
* the current one must be removed from MAC/PHY (zombie UE)
*/
if ((ue_context_p = rrc_gNB_ue_context_random_exist(gnb_rrc_inst, random_value))) {
gNB_RRC_UE_t *UE = &ue_context_p->ue_context;
LOG_W(NR_RRC, "new UE rnti (coming with random value) is already there, removing UE %x from MAC/PHY\n", rnti);
UE->ul_failure_timer = 20000;
AssertFatal(false, "not implemented\n");
}
ue_context_p = rrc_gNB_create_ue_context(rnti, gnb_rrc_inst, random_value);
@@ -1693,16 +1632,12 @@ static int nr_rrc_gNB_decode_ccch(module_id_t module_id, rnti_t rnti, const uint
// TODO: MAC structures should not be accessed directly from the RRC! An implementation using the F1 interface should be developed.
if (!NODE_IS_CU(RC.nrrrc[0]->node_type)) {
nr_rrc_mac_remove_ue(ue_context_p->ue_context.rnti);
} else {
AssertFatal(false, "not implemented: need to switch RNTI in MAC via DL RRC Message Transfer\n");
}
/* replace rnti in the context */
UE->rnti = rnti;
/* reset timers */
UE->ul_failure_timer = 0;
UE->ue_release_timer = 0;
UE->ue_reestablishment_timer = 0;
UE->ue_release_timer_s1 = 0;
UE->ue_release_timer_rrc = 0;
} else {
LOG_I(NR_RRC, "UE %04x 5G-S-TMSI-Part1 doesn't exist, setting ng_5G_S_TMSI_Part1 => %ld\n", rnti, s_tmsi_part1);
@@ -1793,28 +1728,9 @@ static int nr_rrc_gNB_decode_ccch(module_id_t module_id, rnti_t rnti, const uint
break;
}
if (UE->ue_reestablishment_timer > 0) {
LOG_E(NR_RRC, "RRRCReconfigurationComplete(Previous) don't receive, delete the Previous UE,\nprevious Status %d, new Status NR_RRC_RECONFIGURED\n", UE->StatusRrc);
UE->StatusRrc = NR_RRC_RECONFIGURED;
protocol_ctxt_t ctxt_old_p;
PROTOCOL_CTXT_SET_BY_INSTANCE(&ctxt_old_p, module_id, GNB_FLAG_YES, c_rnti, 0, 0);
rrc_gNB_process_RRCReconfigurationComplete(&ctxt_old_p, ue_context_p, xid);
/* TODO: start timer in ITTI and drop UE if it does not come back */
(void) xid; /* xid currently not used */
for (uint8_t pdusessionid = 0; pdusessionid < UE->nb_of_pdusessions; pdusessionid++) {
if (UE->pduSession[pdusessionid].status == PDU_SESSION_STATUS_DONE) {
UE->pduSession[pdusessionid].status = PDU_SESSION_STATUS_ESTABLISHED;
} else {
UE->pduSession[pdusessionid].status = PDU_SESSION_STATUS_FAILED;
}
}
}
/* reset timers */
UE->ul_failure_timer = 0;
UE->ue_release_timer = 0;
UE->ue_reestablishment_timer = 0;
// UE->ue_release_timer_s1 = 0;
UE->ue_release_timer_rrc = 0;
// Insert C-RNTI to map
for (int i = 0; i < MAX_MOBILES_PER_GNB; i++) {
nr_reestablish_rnti_map_t *nr_reestablish_rnti_map = &gnb_rrc_inst->nr_reestablish_rnti_map[i];
@@ -1942,11 +1858,6 @@ static int handle_rrcReestablishmentComplete(const protocol_ctxt_t *const ctxt_p
nr_rrc_mac_remove_ue(reestablish_rnti);
UE->ue_reestablishment_counter++;
// UE->ue_release_timer = 0;
UE->ue_reestablishment_timer = 1;
// remove UE after 100 frames after NR_RRCReestablishmentRelease is triggered
UE->ue_reestablishment_timer_thres = 1000;
return 0;
}
@@ -2104,8 +2015,6 @@ static int handle_rrcSetupComplete(const protocol_ctxt_t *const ctxt_pP,
rrc_gNB_process_RRCSetupComplete(ctxt_pP, ue_context_p, setup_complete->criticalExtensions.choice.rrcSetupComplete);
LOG_I(NR_RRC, PROTOCOL_NR_RRC_CTXT_UE_FMT " UE State = NR_RRC_CONNECTED \n", PROTOCOL_NR_RRC_CTXT_UE_ARGS(ctxt_pP));
UE->ue_release_timer = 0;
return 0;
}
@@ -2120,6 +2029,7 @@ static void handle_rrcReconfigurationComplete(const protocol_ctxt_t *const ctxt_
uint8_t xid = reconfig_complete->rrc_TransactionIdentifier;
rrc_gNB_process_RRCReconfigurationComplete(ctxt_pP, ue_context_p, xid);
bool successful_reconfig = true;
if (get_softmodem_params()->sa) {
switch (UE->xids[xid]) {
case RRC_PDUSESSION_RELEASE: {
@@ -2138,10 +2048,29 @@ static void handle_rrcReconfigurationComplete(const protocol_ctxt_t *const ctxt_
case RRC_FIRST_RECONF:
rrc_gNB_send_NGAP_INITIAL_CONTEXT_SETUP_RESP(ctxt_pP, ue_context_p);
break;
case RRC_DEFAULT_RECONF:
/* nothing to do */
break;
default:
LOG_E(RRC, "Received unexpected xid: %d\n", xid);
successful_reconfig = false;
break;
}
}
gNB_RRC_INST *rrc = RC.nrrrc[0];
f1ap_ue_context_modif_req_t ue_context_modif_req = {
.gNB_CU_ue_id = 0xffffffff, /* filled by F1 for the moment */
.gNB_DU_ue_id = 0xffffffff, /* filled by F1 for the moment */
.rnti = UE->rnti,
.mcc = rrc->configuration.mcc[0],
.mnc = rrc->configuration.mnc[0],
.mnc_digit_length = rrc->configuration.mnc_digit_length[0],
.nr_cellid = rrc->nr_cellid,
.servCellId = 0, /* TODO: correct value? */
.ReconfigComplOutcome = successful_reconfig ? RRCreconf_success : RRCreconf_failure,
};
rrc->mac_rrc.ue_context_modification_request(&ue_context_modif_req);
}
//-----------------------------------------------------------------------------
int rrc_gNB_decode_dcch(const protocol_ctxt_t *const ctxt_pP,
@@ -2205,9 +2134,9 @@ int rrc_gNB_decode_dcch(const protocol_ctxt_t *const ctxt_pP,
break;
case NR_UL_DCCH_MessageType__c1_PR_ulInformationTransfer:
LOG_I(NR_RRC, "Recived RRC GNB UL Information Transfer \n");
LOG_D(NR_RRC, "Recived RRC GNB UL Information Transfer \n");
if (!ue_context_p) {
LOG_I(NR_RRC, "Processing ulInformationTransfer UE %lx, ue_context_p is NULL\n", ctxt_pP->rntiMaybeUEid);
LOG_W(NR_RRC, "Processing ulInformationTransfer UE %lx, ue_context_p is NULL\n", ctxt_pP->rntiMaybeUEid);
break;
}
@@ -2410,158 +2339,9 @@ void rrc_gNB_process_dc_overall_timeout(const module_id_t gnb_mod_idP, x2ap_ENDC
rrc_remove_nsa_user(rrc, m->rnti);
}
static void rrc_DU_process_ue_context_modification_request(MessageDef *msg_p, instance_t instance)
{
f1ap_ue_context_setup_t * req=&F1AP_UE_CONTEXT_MODIFICATION_REQ(msg_p);
protocol_ctxt_t ctxt = {.rntiMaybeUEid = req->rnti, .module_id = instance, .instance = instance, .enb_flag = 1, .eNB_index = instance};
gNB_RRC_INST *rrc = RC.nrrrc[ctxt.module_id];
gNB_MAC_INST *mac = RC.nrmac[ctxt.module_id];
rrc_gNB_ue_context_t *ue_context_p = rrc_gNB_get_ue_context_by_rnti(rrc, req->rnti);
gNB_RRC_UE_t *UE = &ue_context_p->ue_context;
MessageDef *message_p;
message_p = itti_alloc_new_message (TASK_RRC_GNB, 0, F1AP_UE_CONTEXT_MODIFICATION_RESP);
f1ap_ue_context_setup_t * resp=&F1AP_UE_CONTEXT_MODIFICATION_RESP(message_p);
uint32_t incoming_teid = 0;
NR_CellGroupConfig_t *cellGroupConfig = NULL;
/* Configure SRB2 */
NR_SRB_ToAddMod_t *SRB2_config = NULL;
NR_SRB_ToAddModList_t *SRB_configList = NULL;
uint8_t SRBs_before_new_addition = 0;
if(req->srbs_to_be_setup_length>0){
if (UE->SRB_configList == NULL) {
LOG_W(NR_RRC, "The SRB list of the UE context is empty before the addition of new SRB at the DU \n");
UE->SRB_configList = CALLOC(1, sizeof(*UE->SRB_configList));
}
SRB_configList = UE->SRB_configList;
SRBs_before_new_addition = SRB_configList->list.count;
for (int i=0; i<req->srbs_to_be_setup_length; i++){
SRB2_config = CALLOC(1, sizeof(*SRB2_config));
SRB2_config->srb_Identity = req->srbs_to_be_setup[i].srb_id;
asn1cSeqAdd(&SRB_configList->list, SRB2_config);
}
}
/* Configure DRB */
NR_DRB_ToAddMod_t *DRB_config = NULL;
NR_DRB_ToAddModList_t *DRB_configList = NULL;
int drb_id_to_setup_start = 0;
long drb_priority[NGAP_MAX_DRBS_PER_UE];
if(req->drbs_to_be_setup_length>0){
if (UE->DRB_configList == NULL) {
UE->DRB_configList = CALLOC(1, sizeof(*UE->DRB_configList));
}
DRB_configList = UE->DRB_configList;
for (int i=0; i<req->drbs_to_be_setup_length; i++){
DRB_config = CALLOC(1, sizeof(*DRB_config));
DRB_config->drb_Identity = req->drbs_to_be_setup[i].drb_id;
if (drb_id_to_setup_start == 0) drb_id_to_setup_start = DRB_config->drb_Identity;
asn1cSeqAdd(&DRB_configList->list, DRB_config);
f1ap_drb_to_be_setup_t drb_p = req->drbs_to_be_setup[i];
transport_layer_addr_t addr;
memcpy(addr.buffer, &drb_p.up_ul_tnl[0].tl_address, sizeof(drb_p.up_ul_tnl[0].tl_address));
addr.length=sizeof(drb_p.up_ul_tnl[0].tl_address)*8;
extern instance_t DUuniqInstance;
if (!drb_id_to_setup_start) drb_id_to_setup_start = drb_p.drb_id;
incoming_teid = newGtpuCreateTunnel(DUuniqInstance,
req->rnti,
drb_p.drb_id,
drb_p.drb_id,
drb_p.up_ul_tnl[0].teid,
-1, // no qfi
addr,
drb_p.up_ul_tnl[0].port,
DURecvCb,
NULL);
/* TODO: hardcoded to 13 for the time being, to be changed? */
drb_priority[DRB_config->drb_Identity-1] = 13;
}
}
if(req->srbs_to_be_setup_length>0 || req->drbs_to_be_setup_length>0){
cellGroupConfig = calloc(1, sizeof(NR_CellGroupConfig_t));
fill_mastercellGroupConfig(cellGroupConfig,
UE->masterCellGroup,
rrc->um_on_default_drb,
drb_id_to_setup_start < 2 ? 1 : 0,
DRB_configList,
drb_priority);
apply_macrlc_config(rrc, ue_context_p, &ctxt);
}
if(req->ReconfigComplOutcome == RRCreconf_failure){
LOG_W(NR_RRC, "CU reporting RRC Reconfiguration failure \n");
}
else if(req->ReconfigComplOutcome == RRCreconf_success){
LOG_I(NR_RRC, "CU reporting RRC Reconfiguration success \n");
if (UE->DRB_configList != NULL) {
LOG_I(NR_RRC, "Send first DDD buffer status reporting towards the CU through an ITTI message to gtp-u \n");
uint8_t drb_id = UE->DRB_configList->list.array[0]->drb_Identity;
rnti_t rnti = UE->rnti;
int rlc_tx_buffer_space = nr_rlc_get_available_tx_space(rnti, drb_id + 3);
LOG_I(NR_RRC, "Reported in DDD drb_id:%d, rnti:%d\n", drb_id, rnti);
MessageDef *msg = itti_alloc_new_message_sized(TASK_RRC_GNB, 0, GTPV1U_DU_BUFFER_REPORT_REQ,
sizeof(gtpv1u_tunnel_data_req_t));
gtpv1u_DU_buffer_report_req_t *req=&GTPV1U_DU_BUFFER_REPORT_REQ(msg);
req->pdusession_id = drb_id;
req->ue_id = rnti;
req->buffer_availability = rlc_tx_buffer_space; //10000000; //Hardcoding to be removed and read the actual RLC buffer availability instead
extern instance_t DUuniqInstance;
itti_send_msg_to_task(TASK_GTPV1_U, DUuniqInstance, msg);
}
}
/* Fill the UE context setup response ITTI message to send to F1AP */
resp->gNB_CU_ue_id = req->gNB_CU_ue_id;
resp->rnti = ctxt.rntiMaybeUEid;
if(DRB_configList){
if(DRB_configList->list.count > 0){
resp->drbs_to_be_setup = calloc(1,DRB_configList->list.count*sizeof(f1ap_drb_to_be_setup_t));
resp->drbs_to_be_setup_length = DRB_configList->list.count;
for (int i=0; i<DRB_configList->list.count; i++){
resp->drbs_to_be_setup[i].drb_id = DRB_configList->list.array[i]->drb_Identity;
resp->drbs_to_be_setup[i].rlc_mode = RLC_MODE_AM;
resp->drbs_to_be_setup[i].up_dl_tnl[0].teid = incoming_teid;
resp->drbs_to_be_setup[i].up_dl_tnl[0].tl_address = inet_addr(mac->eth_params_n.my_addr);
resp->drbs_to_be_setup[i].up_dl_tnl_length = 1;
}
}
else{
LOG_W(NR_RRC, "No DRB added upon reception of F1 UE context modification request with a DRB to setup list\n");
}
}
if(SRB_configList){
if(SRB_configList->list.count >0 && SRBs_before_new_addition < SRB_configList->list.count){
resp->srbs_to_be_setup = calloc(1,req->srbs_to_be_setup_length*sizeof(f1ap_srb_to_be_setup_t));
resp->srbs_to_be_setup_length = req->srbs_to_be_setup_length;
for (int i=SRBs_before_new_addition; i<SRB_configList->list.count; i++){
resp->srbs_to_be_setup[i-SRBs_before_new_addition].srb_id = SRB_configList->list.array[i]->srb_Identity;
}
}
else{
LOG_W(NR_RRC, "No SRB added upon reception of F1 UE Context modification request at the DU\n");
}
}
else{
LOG_W(NR_RRC, "No SRB added upon reception of F1 UE Context modification request at the DU\n");
}
//if(cellGroupConfig != NULL) {
resp->du_to_cu_rrc_information = calloc(1,sizeof(du_to_cu_rrc_information_t));
resp->du_to_cu_rrc_information->cellGroupConfig = calloc(1,1024);
asn_enc_rval_t enc_rval = uper_encode_to_buffer(&asn_DEF_NR_CellGroupConfig,
NULL,
UE->masterCellGroup, //(void *)cellGroupConfig,
resp->du_to_cu_rrc_information->cellGroupConfig,
1024);
resp->du_to_cu_rrc_information->cellGroupConfig_length = (enc_rval.encoded+7)>>3;
//}
itti_send_msg_to_task (TASK_DU_F1, ctxt.module_id, message_p);
}
static void rrc_CU_process_ue_context_setup_response(MessageDef *msg_p, instance_t instance)
{
f1ap_ue_context_setup_t * resp=&F1AP_UE_CONTEXT_SETUP_RESP(msg_p);
f1ap_ue_context_setup_t *resp = &F1AP_UE_CONTEXT_SETUP_RESP(msg_p);
gNB_RRC_INST *rrc = RC.nrrrc[instance];
rrc_gNB_ue_context_t *ue_context_p = rrc_gNB_get_ue_context_by_rnti(rrc, resp->rnti);
gNB_RRC_UE_t *UE = &ue_context_p->ue_context;
@@ -2587,77 +2367,84 @@ static void rrc_CU_process_ue_context_setup_response(MessageDef *msg_p, instance
* messages (UE capability, to be specific) */
}
static void rrc_CU_process_ue_context_release_request(MessageDef *msg_p)
{
const int instance = 0;
f1ap_ue_context_release_req_t *req = &F1AP_UE_CONTEXT_RELEASE_REQ(msg_p);
gNB_RRC_INST *rrc = RC.nrrrc[instance];
rrc_gNB_ue_context_t *ue_context_p = rrc_gNB_get_ue_context_by_rnti(rrc, req->rnti);
/* TODO: marshall types correctly */
LOG_I(NR_RRC, "received UE Context Release Request for UE %04x, forwarding to AMF\n", req->rnti);
rrc_gNB_send_NGAP_UE_CONTEXT_RELEASE_REQ(instance,
ue_context_p,
NGAP_CAUSE_RADIO_NETWORK,
NGAP_CAUSE_RADIO_NETWORK_RADIO_CONNECTION_WITH_UE_LOST);
}
static void rrc_CU_process_ue_context_release_complete(MessageDef *msg_p)
{
const int instance = 0;
f1ap_ue_context_release_complete_t *complete = &F1AP_UE_CONTEXT_RELEASE_COMPLETE(msg_p);
gNB_RRC_INST *rrc = RC.nrrrc[instance];
rrc_gNB_ue_context_t *ue_context_p = rrc_gNB_get_ue_context_by_rnti(rrc, complete->rnti);
gNB_RRC_UE_t *UE = &ue_context_p->ue_context;
nr_pdcp_remove_UE(UE->rnti);
newGtpuDeleteAllTunnels(instance, UE->rnti);
rrc_gNB_send_NGAP_UE_CONTEXT_RELEASE_COMPLETE(instance, UE->gNB_ue_ngap_id);
LOG_I(NR_RRC, "removed UE %04x \n", UE->rnti);
rrc_gNB_remove_ue_context(rrc, ue_context_p);
}
static void rrc_CU_process_ue_context_modification_response(MessageDef *msg_p, instance_t instance)
{
f1ap_ue_context_setup_t *resp=&F1AP_UE_CONTEXT_SETUP_RESP(msg_p);
f1ap_ue_context_modif_resp_t *resp = &F1AP_UE_CONTEXT_MODIFICATION_RESP(msg_p);
protocol_ctxt_t ctxt = {.rntiMaybeUEid = resp->rnti, .module_id = instance, .instance = instance, .enb_flag = 1, .eNB_index = instance};
gNB_RRC_INST *rrc = RC.nrrrc[ctxt.module_id];
rrc_gNB_ue_context_t *ue_context_p = rrc_gNB_get_ue_context_by_rnti(rrc, resp->rnti);
gNB_RRC_UE_t *UE = &ue_context_p->ue_context;
e1ap_bearer_setup_req_t req = {0};
req.numPDUSessionsMod = UE->nb_of_pdusessions;
req.gNB_cu_cp_ue_id = UE->gNB_ue_ngap_id;
req.rnti = UE->rnti;
for (int i=0; i < req.numPDUSessionsMod; i++) {
req.pduSessionMod[i].numDRB2Modify = resp->drbs_to_be_setup_length;
for (int j=0; j < resp->drbs_to_be_setup_length; j++) {
f1ap_drb_to_be_setup_t *drb_f1 = resp->drbs_to_be_setup + j;
DRB_nGRAN_to_setup_t *drb_e1 = req.pduSessionMod[i].DRBnGRanModList + j;
if (resp->drbs_to_be_setup_length > 0) {
e1ap_bearer_setup_req_t req = {0};
req.numPDUSessionsMod = UE->nb_of_pdusessions;
req.gNB_cu_cp_ue_id = UE->gNB_ue_ngap_id;
req.rnti = UE->rnti;
for (int i = 0; i < req.numPDUSessionsMod; i++) {
req.pduSessionMod[i].numDRB2Modify = resp->drbs_to_be_setup_length;
for (int j = 0; j < resp->drbs_to_be_setup_length; j++) {
f1ap_drb_to_be_setup_t *drb_f1 = resp->drbs_to_be_setup + j;
DRB_nGRAN_to_setup_t *drb_e1 = req.pduSessionMod[i].DRBnGRanModList + j;
drb_e1->id = drb_f1->drb_id;
drb_e1->numDlUpParam = drb_f1->up_dl_tnl_length;
drb_e1->DlUpParamList[0].tlAddress = drb_f1->up_dl_tnl[0].tl_address;
drb_e1->DlUpParamList[0].teId = drb_f1->up_dl_tnl[0].teid;
}
}
// send the F1 response message up to update F1-U tunnel info
// it seems the rrc transaction id (xid) is not needed here
rrc->cucp_cuup.bearer_context_mod(&req, instance, 0);
NR_CellGroupConfig_t *cellGroupConfig = NULL;
if(resp->du_to_cu_rrc_information->cellGroupConfig!=NULL){
asn_dec_rval_t dec_rval = uper_decode_complete( NULL,
&asn_DEF_NR_CellGroupConfig,
(void **)&cellGroupConfig,
(uint8_t *)resp->du_to_cu_rrc_information->cellGroupConfig,
(int) resp->du_to_cu_rrc_information->cellGroupConfig_length);
if((dec_rval.code != RC_OK) && (dec_rval.consumed == 0)) {
AssertFatal(1==0,"Cell group config decode error\n");
// free the memory
SEQUENCE_free( &asn_DEF_NR_CellGroupConfig, cellGroupConfig, 1 );
return;
}
//xer_fprint(stdout,&asn_DEF_NR_CellGroupConfig, cellGroupConfig);
if (UE->masterCellGroup == NULL) {
UE->masterCellGroup = calloc(1, sizeof(NR_CellGroupConfig_t));
}
if(cellGroupConfig->rlc_BearerToAddModList!=NULL){
if (UE->masterCellGroup->rlc_BearerToAddModList != NULL) {
int ue_ctxt_rlc_Bearers = UE->masterCellGroup->rlc_BearerToAddModList->list.count;
for(int i=ue_ctxt_rlc_Bearers; i<ue_ctxt_rlc_Bearers + cellGroupConfig->rlc_BearerToAddModList->list.count; i++){
asn1cSeqAdd(&UE->masterCellGroup->rlc_BearerToAddModList->list, cellGroupConfig->rlc_BearerToAddModList->list.array[i - ue_ctxt_rlc_Bearers]);
}
} else {
LOG_W(NR_RRC, "Empty rlc_BearerToAddModList at ue_context of the CU before filling the updates from UE context setup response \n");
UE->masterCellGroup->rlc_BearerToAddModList = calloc(1, sizeof(*cellGroupConfig->rlc_BearerToAddModList));
memcpy(UE->masterCellGroup->rlc_BearerToAddModList, cellGroupConfig->rlc_BearerToAddModList, sizeof(*cellGroupConfig->rlc_BearerToAddModList));
drb_e1->id = drb_f1->drb_id;
drb_e1->numDlUpParam = drb_f1->up_dl_tnl_length;
drb_e1->DlUpParamList[0].tlAddress = drb_f1->up_dl_tnl[0].tl_address;
drb_e1->DlUpParamList[0].teId = drb_f1->up_dl_tnl[0].teid;
}
}
LOG_I(NR_RRC, "Updated master cell group configuration stored at the UE context of the CU:\n");
if (LOG_DEBUGFLAG(DEBUG_ASN1)) {
xer_fprint(stdout, &asn_DEF_NR_CellGroupConfig, UE->masterCellGroup);
// send the F1 response message up to update F1-U tunnel info
// it seems the rrc transaction id (xid) is not needed here
rrc->cucp_cuup.bearer_context_mod(&req, instance, 0);
}
if (resp->du_to_cu_rrc_information != NULL && resp->du_to_cu_rrc_information->cellGroupConfig != NULL) {
LOG_W(RRC, "UE context modification response contains new CellGroupConfig for UE %04x, triggering reconfiguration\n", UE->rnti);
NR_CellGroupConfig_t *cellGroupConfig = NULL;
asn_dec_rval_t dec_rval = uper_decode_complete(NULL,
&asn_DEF_NR_CellGroupConfig,
(void **)&cellGroupConfig,
(uint8_t *)resp->du_to_cu_rrc_information->cellGroupConfig,
resp->du_to_cu_rrc_information->cellGroupConfig_length);
AssertFatal(dec_rval.code == RC_OK && dec_rval.consumed > 0, "Cell group config decode error\n");
if (UE->masterCellGroup) {
ASN_STRUCT_FREE(asn_DEF_NR_CellGroupConfig, UE->masterCellGroup);
LOG_I(RRC, "UE %04x replacing existing CellGroupConfig with new one received from DU\n", UE->rnti);
}
UE->masterCellGroup = cellGroupConfig;
rrc_gNB_generate_dedicatedRRCReconfiguration(&ctxt, ue_context_p, cellGroupConfig);
free(cellGroupConfig->rlc_BearerToAddModList);
free(cellGroupConfig);
rrc_gNB_generate_dedicatedRRCReconfiguration(&ctxt, ue_context_p);
}
}
@@ -2817,90 +2604,6 @@ static int get_dl_mimo_layers(const gNB_RRC_INST *rrc, const NR_UE_NR_Capability
return(1);
}
void nr_rrc_subframe_process(protocol_ctxt_t *const ctxt_pP, const int CC_id) {
MessageDef *msg;
gNB_RRC_INST *rrc = RC.nrrrc[ctxt_pP->module_id];
rrc_gNB_ue_context_t *ue_context_p = NULL;
RB_FOREACH(ue_context_p, rrc_nr_ue_tree_s, &rrc->rrc_ue_head)
{
gNB_RRC_UE_t *UE = &ue_context_p->ue_context;
ctxt_pP->rntiMaybeUEid = UE->rnti;
if (UE->ul_failure_timer > 0) {
UE->ul_failure_timer++;
if (UE->ul_failure_timer >= 20000) {
// remove UE after 20 seconds after MAC (or else) has indicated UL failure
LOG_I(RRC, "Removing UE %x instance, because of uplink failure timer timeout\n", UE->rnti);
if (UE->StatusRrc >= NR_RRC_CONNECTED) {
rrc_gNB_send_NGAP_UE_CONTEXT_RELEASE_REQ(
ctxt_pP->module_id,
ue_context_p,
NGAP_CAUSE_RADIO_NETWORK,
NGAP_CAUSE_RADIO_NETWORK_RADIO_CONNECTION_WITH_UE_LOST);
}
// Remove here the MAC and RRC context when RRC is not connected
if (UE->StatusRrc < NR_RRC_CONNECTED) {
if (!NODE_IS_CU(rrc->node_type)) {
nr_rrc_mac_remove_ue(ctxt_pP->rntiMaybeUEid);
rrc_rlc_remove_ue(ctxt_pP);
nr_pdcp_remove_UE(ctxt_pP->rntiMaybeUEid);
/* remove RRC UE Context */
ue_context_p = rrc_gNB_get_ue_context_by_rnti(rrc, UE->rnti);
if (ue_context_p) {
LOG_I(NR_RRC, "remove UE %04x \n", UE->rnti);
rrc_gNB_remove_ue_context(rrc, ue_context_p);
break; // We must not access this UE context
}
}
// In case of CU trigger UE context release command towards the DU
else {
MessageDef *message_p;
message_p = itti_alloc_new_message (TASK_RRC_GNB, 0, F1AP_UE_CONTEXT_RELEASE_CMD);
f1ap_ue_context_release_cmd_t *rel_cmd=&F1AP_UE_CONTEXT_RELEASE_CMD (message_p);
rel_cmd->rnti = UE->rnti;
rel_cmd->cause = F1AP_CAUSE_RADIO_NETWORK;
rel_cmd->cause_value = 10; // 10 = F1AP_CauseRadioNetwork_normal_release
itti_send_msg_to_task(TASK_CU_F1, ctxt_pP->module_id, message_p);
}
}
break; // break RB_FOREACH
}
}
if (UE->ue_release_timer_rrc > 0) {
UE->ue_release_timer_rrc++;
if (UE->ue_release_timer_rrc >= UE->ue_release_timer_thres_rrc) {
LOG_I(NR_RRC, "Removing UE %x instance after UE_CONTEXT_RELEASE_Complete (ue_release_timer_rrc timeout)\n", UE->rnti);
UE->ue_release_timer_rrc = 0;
if (!NODE_IS_CU(RC.nrrrc[0]->node_type)) {
nr_rrc_mac_remove_ue(ctxt_pP->rntiMaybeUEid);
}
rrc_rlc_remove_ue(ctxt_pP);
nr_pdcp_remove_UE(ctxt_pP->rntiMaybeUEid);
newGtpuDeleteAllTunnels(ctxt_pP->instance, UE->rnti);
/* remove RRC UE Context */
LOG_I(NR_RRC, "remove UE %04x \n", UE->rnti);
rrc_gNB_remove_ue_context(rrc, ue_context_p);
break; // break RB_FOREACH
}
}
}
/* send a tick to x2ap */
if (is_x2ap_enabled()){
msg = itti_alloc_new_message(TASK_RRC_ENB, 0, X2AP_SUBFRAME_PROCESS);
itti_send_msg_to_task(TASK_X2AP, ctxt_pP->module_id, msg);
}
}
int rrc_gNB_process_e1_setup_req(e1ap_setup_req_t *req, instance_t instance) {
AssertFatal(req->supported_plmns <= PLMN_LIST_MAX_SIZE, "Supported PLMNs is more than PLMN_LIST_MAX_SIZE\n");
@@ -2924,46 +2627,48 @@ int rrc_gNB_process_e1_setup_req(e1ap_setup_req_t *req, instance_t instance) {
return 0;
}
void prepare_and_send_ue_context_modification_f1(rrc_gNB_ue_context_t *ue_context_p,
e1ap_bearer_setup_resp_t *e1ap_resp) {
void prepare_and_send_ue_context_modification_f1(rrc_gNB_ue_context_t *ue_context_p, e1ap_bearer_setup_resp_t *e1ap_resp)
{
/* Generate a UE context modification request message towards the DU to
* instruct the DU for SRB2 and DRB configuration and get the updates on
* master cell group config from the DU*/
/*Generate a UE context modification request message towards the DU to instruct the DU
*for SRB2 and DRB configuration and get the updates on master cell group config from the DU*/
gNB_RRC_INST *rrc = RC.nrrrc[0];
gNB_RRC_UE_t *UE = &ue_context_p->ue_context;
protocol_ctxt_t ctxt = {0};
PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, 0, GNB_FLAG_YES, UE->rnti, 0, 0, 0);
// TODO: So many hard codings
MessageDef *message_p;
message_p = itti_alloc_new_message (TASK_RRC_GNB, 0, F1AP_UE_CONTEXT_MODIFICATION_REQ);
f1ap_ue_context_setup_t *req=&F1AP_UE_CONTEXT_MODIFICATION_REQ(message_p);
req->rnti = UE->rnti;
req->mcc = RC.nrrrc[ctxt.module_id]->configuration.mcc[0];
req->mnc = RC.nrrrc[ctxt.module_id]->configuration.mnc[0];
req->mnc_digit_length = RC.nrrrc[ctxt.module_id]->configuration.mnc_digit_length[0];
req->nr_cellid = RC.nrrrc[ctxt.module_id]->nr_cellid;
/*Instruction towards the DU for SRB2 configuration*/
req->srbs_to_be_setup = malloc(1*sizeof(f1ap_srb_to_be_setup_t));
req->srbs_to_be_setup_length = 1;
f1ap_srb_to_be_setup_t *SRBs=req->srbs_to_be_setup;
SRBs[0].srb_id = 2;
SRBs[0].lcid = 2;
/*Instruction towards the DU for DRB configuration and tunnel creation*/
req->drbs_to_be_setup_length = e1ap_resp->pduSession[0].numDRBSetup;
req->drbs_to_be_setup = malloc(1*sizeof(f1ap_drb_to_be_setup_t)*req->drbs_to_be_setup_length);
for (int i=0; i < e1ap_resp->pduSession[0].numDRBSetup; i++) {
f1ap_drb_to_be_setup_t *DRBs = req->drbs_to_be_setup + i;
DRBs[i].drb_id = e1ap_resp->pduSession[0].DRBnGRanList[i].id;
DRBs[i].rlc_mode = RLC_MODE_AM;
DRBs[i].up_ul_tnl[0].tl_address = e1ap_resp->pduSession[0].DRBnGRanList[i].UpParamList[0].tlAddress;
DRBs[i].up_ul_tnl[0].port = RC.nrrrc[ctxt.module_id]->eth_params_s.my_portd;
DRBs[i].up_ul_tnl[0].teid = e1ap_resp->pduSession[0].DRBnGRanList[i].UpParamList[0].teId;
DRBs[i].up_ul_tnl_length = 1;
/* Instruction towards the DU for DRB configuration and tunnel creation */
int nb_drb = e1ap_resp->pduSession[0].numDRBSetup;
f1ap_drb_to_be_setup_t drbs[nb_drb];
for (int i = 0; i < nb_drb; i++) {
drbs[i].drb_id = e1ap_resp->pduSession[0].DRBnGRanList[i].id;
drbs[i].rlc_mode = rrc->um_on_default_drb ? RLC_MODE_UM : RLC_MODE_AM;
drbs[i].up_ul_tnl[0].tl_address = e1ap_resp->pduSession[0].DRBnGRanList[i].UpParamList[0].tlAddress;
drbs[i].up_ul_tnl[0].port = rrc->eth_params_s.my_portd;
drbs[i].up_ul_tnl[0].teid = e1ap_resp->pduSession[0].DRBnGRanList[i].UpParamList[0].teId;
drbs[i].up_ul_tnl_length = 1;
}
itti_send_msg_to_task (TASK_CU_F1, ctxt.module_id, message_p);
/* Instruction towards the DU for SRB2 configuration */
int nb_srb = 1;
f1ap_srb_to_be_setup_t srbs[nb_srb];
srbs[0].srb_id = 2;
srbs[0].lcid = 2;
f1ap_ue_context_modif_req_t ue_context_modif_req = {
.gNB_CU_ue_id = 0xffffffff, /* filled by F1 for the moment */
.gNB_DU_ue_id = 0xffffffff, /* filled by F1 for the moment */
.rnti = UE->rnti,
.mcc = rrc->configuration.mcc[0],
.mnc = rrc->configuration.mnc[0],
.mnc_digit_length = rrc->configuration.mnc_digit_length[0],
.nr_cellid = rrc->nr_cellid,
.servCellId = 0, /* TODO: correct value? */
.srbs_to_be_setup_length = nb_srb,
.srbs_to_be_setup = srbs,
.drbs_to_be_setup_length = nb_drb,
.drbs_to_be_setup = drbs,
};
rrc->mac_rrc.ue_context_modification_request(&ue_context_modif_req);
}
void rrc_gNB_process_e1_bearer_context_setup_resp(e1ap_bearer_setup_resp_t *resp, instance_t instance) {
@@ -3031,9 +2736,9 @@ static void write_rrc_stats(const gNB_RRC_INST *rrc)
fprintf(f, "NR RRC UE rnti %04x:", rnti);
if (ue_ctxt->Initialue_identity_5g_s_TMSI.presence)
fprintf(f, " S-TMSI %x\n", ue_ctxt->Initialue_identity_5g_s_TMSI.fiveg_tmsi);
fprintf(f, " S-TMSI %x", ue_ctxt->Initialue_identity_5g_s_TMSI.fiveg_tmsi);
fprintf(f, " failure timer %d/8\n", ue_ctxt->ul_failure_timer);
fprintf(f, "\n");
if (ue_ctxt->UE_Capability_nr) {
fprintf(f,
@@ -3060,10 +2765,12 @@ void *rrc_gnb_task(void *args_p) {
int result;
protocol_ctxt_t ctxt = {.module_id = 0, .enb_flag = 1, .instance = 0, .rntiMaybeUEid = 0, .frame = -1, .subframe = -1, .eNB_index = 0, .brOption = false};
/* timer to write stats to file */
long stats_timer_id = 1;
timer_setup(1, 0, TASK_RRC_GNB, 0, TIMER_PERIODIC, NULL, &stats_timer_id);
if (!IS_SOFTMODEM_NOSTATS_BIT) {
/* timer to write stats to file */
timer_setup(1, 0, TASK_RRC_GNB, 0, TIMER_PERIODIC, NULL, &stats_timer_id);
}
itti_mark_task_ready(TASK_RRC_GNB);
LOG_I(NR_RRC,"Entering main loop of NR_RRC message task\n");
@@ -3089,10 +2796,6 @@ void *rrc_gnb_task(void *args_p) {
write_rrc_stats(RC.nrrrc[0]);
break;
case RRC_SUBFRAME_PROCESS:
nr_rrc_subframe_process(&RRC_SUBFRAME_PROCESS(msg_p).ctxt, RRC_SUBFRAME_PROCESS(msg_p).CC_id);
break;
case F1AP_INITIAL_UL_RRC_MESSAGE:
AssertFatal(NODE_IS_CU(RC.nrrrc[instance]->node_type) || NODE_IS_MONOLITHIC(RC.nrrrc[instance]->node_type),
"should not receive F1AP_INITIAL_UL_RRC_MESSAGE, need call by CU!\n");
@@ -3156,13 +2859,12 @@ void *rrc_gnb_task(void *args_p) {
rrc_CU_process_ue_context_modification_response(msg_p, instance);
break;
case F1AP_UE_CONTEXT_MODIFICATION_REQ:
rrc_DU_process_ue_context_modification_request(msg_p, instance);
case F1AP_UE_CONTEXT_RELEASE_REQ:
rrc_CU_process_ue_context_release_request(msg_p);
break;
case F1AP_UE_CONTEXT_RELEASE_CMD:
LOG_W(NR_RRC, "Received F1AP_UE_CONTEXT_RELEASE_CMD for processing at the RRC layer of the DU. Processing function "
"implementation is pending\n");
case F1AP_UE_CONTEXT_RELEASE_COMPLETE:
rrc_CU_process_ue_context_release_complete(msg_p);
break;
/* Messages from X2AP */
@@ -3290,6 +2992,24 @@ rrc_gNB_generate_UECapabilityEnquiry(
nr_pdcp_data_req_srb(ctxt_pP->rntiMaybeUEid, DCCH, rrc_gNB_mui++, size, buffer, deliver_pdu_srb_f1, rrc);
}
static void rrc_deliver_ue_ctxt_release_cmd(void *deliver_pdu_data, ue_id_t ue_id, int srb_id, char *buf, int size, int sdu_id)
{
DevAssert(deliver_pdu_data != NULL);
gNB_RRC_INST *rrc = deliver_pdu_data;
uint8_t *rrc_container = malloc(size);
AssertFatal(rrc_container != NULL, "out of memory\n");
memcpy(rrc_container, buf, size);
f1ap_ue_context_release_cmd_t ue_context_release_cmd = {
.rnti = ue_id, /* TODO: proper IDs! */
.cause = F1AP_CAUSE_RADIO_NETWORK,
.cause_value = 10, // 10 = F1AP_CauseRadioNetwork_normal_release
.srb_id = srb_id,
.rrc_container = rrc_container,
.rrc_container_length = size,
};
rrc->mac_rrc.ue_context_release_command(&ue_context_release_cmd);
}
//-----------------------------------------------------------------------------
/*
* Generate the RRC Connection Release to UE.
@@ -3304,49 +3024,16 @@ rrc_gNB_generate_RRCRelease(
{
uint8_t buffer[RRC_BUF_SIZE] = {0};
int size = do_NR_RRCRelease(buffer, RRC_BUF_SIZE, rrc_gNB_get_next_transaction_identifier(ctxt_pP->module_id));
gNB_RRC_UE_t *ue_p = &ue_context_pP->ue_context;
ue_p->ue_reestablishment_timer = 0;
ue_p->ue_release_timer = 0;
ue_p->ul_failure_timer = 0;
ue_p->ue_release_timer_rrc = 0;
LOG_I(NR_RRC,
PROTOCOL_NR_RRC_CTXT_UE_FMT" Logical Channel DL-DCCH, Generate RRCRelease (bytes %d)\n",
PROTOCOL_NR_RRC_CTXT_UE_ARGS(ctxt_pP),
size);
LOG_D(NR_RRC,
PROTOCOL_NR_RRC_CTXT_UE_FMT" --- PDCP_DATA_REQ/%d Bytes (rrcRelease MUI %d) --->[PDCP][RB %u]\n",
PROTOCOL_NR_RRC_CTXT_UE_ARGS(ctxt_pP),
size,
rrc_gNB_mui,
DCCH);
gNB_RRC_INST *rrc = RC.nrrrc[ctxt_pP->module_id];
nr_pdcp_data_req_srb(ctxt_pP->rntiMaybeUEid, DCCH, rrc_gNB_mui++, size, buffer, deliver_pdu_srb_f1, rrc);
nr_pdcp_data_req_srb(ctxt_pP->rntiMaybeUEid, DCCH, rrc_gNB_mui++, size, buffer, rrc_deliver_ue_ctxt_release_cmd, rrc);
rrc_gNB_send_NGAP_UE_CONTEXT_RELEASE_COMPLETE(ctxt_pP->instance, ue_context_pP->ue_context.gNB_ue_ngap_id);
ue_context_pP->ue_context.ue_release_timer_rrc = 1;
/* TODO: 38.331 says for RRC Release that the UE should release everything
* after 60ms or if lower layers acked receipt of release. Hence, from the
* gNB POV, we can free the UE's RRC context as soon as we sent the msg.
* Currently, without the F1 interface, the ue_release timer expiration also
* triggers MAC, so we give it some time. If we send an F1 UE Context release
* message, we can free it immediately. The MAC should release it after these
* 60ms, or the ack of the DLSCH transmission. */
ue_context_pP->ue_context.ue_release_timer_thres_rrc = 5;
LOG_I(RRC, "delaying UE %ld context removal by 5ms\n", ctxt_pP->rntiMaybeUEid);
if (NODE_IS_CU(rrc->node_type)) {
uint8_t *message_buffer = itti_malloc (TASK_RRC_GNB, TASK_CU_F1, size);
memcpy (message_buffer, buffer, size);
MessageDef *m = itti_alloc_new_message(TASK_RRC_GNB, 0, F1AP_UE_CONTEXT_RELEASE_CMD);
F1AP_UE_CONTEXT_RELEASE_CMD(m).rnti = ctxt_pP->rntiMaybeUEid;
F1AP_UE_CONTEXT_RELEASE_CMD(m).cause = F1AP_CAUSE_RADIO_NETWORK;
F1AP_UE_CONTEXT_RELEASE_CMD(m).cause_value = 10; // 10 = F1AP_CauseRadioNetwork_normal_release
F1AP_UE_CONTEXT_RELEASE_CMD(m).rrc_container = message_buffer;
F1AP_UE_CONTEXT_RELEASE_CMD(m).rrc_container_length = size;
itti_send_msg_to_task(TASK_CU_F1, ctxt_pP->module_id, m);
}
/* UE will be freed after UE context release complete */
}
int rrc_gNB_generate_pcch_msg(uint32_t tmsi, uint8_t paging_drx, instance_t instance, uint8_t CC_id){
@@ -3471,14 +3158,3 @@ int rrc_gNB_generate_pcch_msg(uint32_t tmsi, uint8_t paging_drx, instance_t inst
return 0;
}
void nr_rrc_trigger(protocol_ctxt_t *ctxt, int CC_id, int frame, int subframe)
{
MessageDef *message_p;
message_p = itti_alloc_new_message(TASK_RRC_GNB, 0, RRC_SUBFRAME_PROCESS);
RRC_SUBFRAME_PROCESS(message_p).ctxt = *ctxt;
RRC_SUBFRAME_PROCESS(message_p).CC_id = CC_id;
LOG_D(NR_RRC, "Time in RRC: %u/ %u \n", frame, subframe);
itti_send_msg_to_task(TASK_RRC_GNB, ctxt->module_id, message_p);
}
+11 -16
View File
@@ -47,7 +47,8 @@
#include "S1AP_NAS-PDU.h"
#include "executables/softmodem-common.h"
#include "UTIL/OSA/osa_defs.h"
#include "openair3/SECU/key_nas_deriver.h"
#include "ngap_gNB_defs.h"
#include "ngap_gNB_ue_context.h"
#include "ngap_gNB_management_procedures.h"
@@ -126,20 +127,21 @@ nr_rrc_pdcp_config_security(
{
NR_SRB_ToAddModList_t *SRB_configList = ue_context_pP->ue_context.SRB_configList;
(void)SRB_configList;
uint8_t *kRRCenc = NULL;
uint8_t *kRRCint = NULL;
uint8_t *kUPenc = NULL;
uint8_t kRRCenc[16] = {0};
uint8_t kRRCint[16] = {0};
uint8_t kUPenc[16] = {0};
//uint8_t *k_kdf = NULL;
static int print_keys= 1;
gNB_RRC_UE_t *UE = &ue_context_pP->ue_context;
/* Derive the keys from kgnb */
if (UE->Srb[1].Active || UE->Srb[2].Active) {
nr_derive_key_up_enc(UE->ciphering_algorithm, UE->kgnb, &kUPenc);
nr_derive_key(UP_ENC_ALG, UE->ciphering_algorithm, UE->kgnb, kUPenc);
}
nr_derive_key_rrc_enc(UE->ciphering_algorithm, UE->kgnb, &kRRCenc);
nr_derive_key_rrc_int(UE->integrity_algorithm, UE->kgnb, &kRRCint);
nr_derive_key(RRC_ENC_ALG, UE->ciphering_algorithm, UE->kgnb, kRRCenc);
nr_derive_key(RRC_INT_ALG, UE->integrity_algorithm, UE->kgnb, kRRCint);
if (!IS_SOFTMODEM_IQPLAYER) {
SET_LOG_DUMP(DEBUG_SECURITY) ;
}
@@ -396,12 +398,7 @@ int rrc_gNB_process_NGAP_INITIAL_CONTEXT_SETUP_REQ(MessageDef *msg_p, instance_t
int ret = gtpv1u_create_ngu_tunnel(instance, &create_tunnel_req, &create_tunnel_resp, nr_pdcp_data_req_drb, sdap_data_req);
if (ret != 0) {
LOG_E(NR_RRC, "rrc_gNB_process_NGAP_INITIAL_CONTEXT_SETUP_REQ : gtpv1u_create_ngu_tunnel failed,start to release UE %x\n", UE->rnti);
UE->ue_release_timer_ng = 1;
UE->ue_release_timer_thres_ng = 100;
UE->ue_release_timer = 0;
UE->ue_reestablishment_timer = 0;
UE->ul_failure_timer = 20000;
UE->ul_failure_timer = 0;
AssertFatal(false, "release timer not implemented\n");
return (0);
}
@@ -653,7 +650,7 @@ rrc_gNB_send_NGAP_UPLINK_NAS(
// NGAP_UPLINK_NAS (msg_p).nas_pdu.length,
// ue_context_pP);
itti_send_msg_to_task (TASK_NGAP, ctxt_pP->instance, msg_p);
LOG_I(NR_RRC,"Send RRC GNB UL Information Transfer \n");
LOG_D(NR_RRC,"Send RRC GNB UL Information Transfer \n");
}
}
@@ -1157,8 +1154,6 @@ int rrc_gNB_process_NGAP_UE_CONTEXT_RELEASE_COMMAND(MessageDef *msg_p, instance_
}
gNB_RRC_UE_t *UE = &ue_context_p->ue_context;
UE->ue_release_timer_ng = 0;
UE->ue_release_timer_thres_rrc = 1000;
PROTOCOL_CTXT_SET_BY_INSTANCE(&ctxt, instance, GNB_FLAG_YES, UE->rnti, 0, 0);
ctxt.eNB_index = 0;
rrc_gNB_generate_RRCRelease(&ctxt, ue_context_p);
+7 -5
View File
@@ -43,7 +43,9 @@
#include "executables/nr-softmodem.h"
#include <openair2/RRC/NR/rrc_gNB_UE_context.h>
#include <openair3/ocp-gtpu/gtp_itf.h>
#include "UTIL/OSA/osa_defs.h"
#include "openair3/SECU/secu_defs.h"
#include "openair3/SECU/key_nas_deriver.h"
#include <openair2/RRC/NR/nr_rrc_proto.h>
#include "nr_pdcp/nr_pdcp_oai_api.h"
#include "MESSAGES/asn1_msg.h"
@@ -121,8 +123,8 @@ void rrc_add_nsa_user(gNB_RRC_INST *rrc, rrc_gNB_ue_context_t *ue_context_p, x2a
gtpv1u_enb_create_tunnel_req_t create_tunnel_req;
gtpv1u_enb_create_tunnel_resp_t create_tunnel_resp;
protocol_ctxt_t ctxt={0};
unsigned char *kUPenc = NULL;
unsigned char *kUPint = NULL;
uint8_t kUPenc[16] = {0};
uint8_t kUPint[16] = {0};
int i;
gNB_RRC_UE_t *UE = &ue_context_p->ue_context;
@@ -212,8 +214,8 @@ void rrc_add_nsa_user(gNB_RRC_INST *rrc, rrc_gNB_ue_context_t *ue_context_p, x2a
LOG_I(RRC, "selecting integrity algorithm %d\n", UE->integrity_algorithm);
/* derive UP security key */
nr_derive_key_up_enc(UE->ciphering_algorithm, UE->kgnb, &kUPenc);
nr_derive_key_up_int(UE->integrity_algorithm, UE->kgnb, &kUPint);
nr_derive_key(UP_ENC_ALG, UE->ciphering_algorithm, UE->kgnb, kUPenc);
nr_derive_key(UP_INT_ALG, UE->integrity_algorithm, UE->kgnb, kUPint);
e_NR_CipheringAlgorithm cipher_algo;
switch (UE->ciphering_algorithm) {
+6 -4
View File
@@ -28,10 +28,12 @@ rrc_pdu_session_param_t *find_pduSession(gNB_RRC_UE_t *ue, int id, bool create)
for (j = 0; j < ue->nb_of_pdusessions; j++)
if (id == ue->pduSession[j].param.pdusession_id)
break;
if (j == ue->nb_of_pdusessions && create)
ue->nb_of_pdusessions++;
else
return NULL;
if (j == ue->nb_of_pdusessions) {
if (create)
ue->nb_of_pdusessions++;
else
return NULL;
}
return ue->pduSession + j;
}
+39 -23
View File
@@ -57,7 +57,9 @@
#include "nr-uesoftmodem.h"
#include "plmn_data.h"
#include "nr_pdcp/nr_pdcp_oai_api.h"
#include "UTIL/OSA/osa_defs.h"
#include "openair3/SECU/secu_defs.h"
#include "openair3/SECU/key_nas_deriver.h"
#include "common/utils/LOG/log.h"
#include "common/utils/LOG/vcd_signal_dumper.h"
@@ -1522,18 +1524,22 @@ int8_t nr_rrc_ue_decode_ccch( const protocol_ctxt_t *const ctxt_pP, const NR_SRB
ul_dcch_msg.message.choice.c1->present = NR_UL_DCCH_MessageType__c1_PR_securityModeComplete;
}
uint8_t *kRRCenc = NULL;
uint8_t *kUPenc = NULL;
uint8_t *kRRCint = NULL;
nr_derive_key_up_enc(NR_UE_rrc_inst[ctxt_pP->module_id].cipheringAlgorithm,
NR_UE_rrc_inst[ctxt_pP->module_id].kgnb,
&kUPenc);
nr_derive_key_rrc_enc(NR_UE_rrc_inst[ctxt_pP->module_id].cipheringAlgorithm,
NR_UE_rrc_inst[ctxt_pP->module_id].kgnb,
&kRRCenc);
nr_derive_key_rrc_int(NR_UE_rrc_inst[ctxt_pP->module_id].integrityProtAlgorithm,
NR_UE_rrc_inst[ctxt_pP->module_id].kgnb,
&kRRCint);
uint8_t kRRCenc[16] = {0};
uint8_t kUPenc[16] = {0};
uint8_t kRRCint[16] = {0};
nr_derive_key(UP_ENC_ALG,
NR_UE_rrc_inst[ctxt_pP->module_id].cipheringAlgorithm,
NR_UE_rrc_inst[ctxt_pP->module_id].kgnb,
kUPenc);
nr_derive_key(RRC_ENC_ALG,
NR_UE_rrc_inst[ctxt_pP->module_id].cipheringAlgorithm,
NR_UE_rrc_inst[ctxt_pP->module_id].kgnb,
kRRCenc);
nr_derive_key(RRC_INT_ALG,
NR_UE_rrc_inst[ctxt_pP->module_id].integrityProtAlgorithm,
NR_UE_rrc_inst[ctxt_pP->module_id].kgnb,
kRRCint);
LOG_I(NR_RRC, "driving kRRCenc, kRRCint and kUPenc from KgNB="
"%02x%02x%02x%02x"
"%02x%02x%02x%02x"
@@ -1868,10 +1874,16 @@ nr_rrc_ue_establish_srb2(
}
}
uint8_t *kRRCenc = NULL;
uint8_t *kRRCint = NULL;
nr_derive_key_rrc_enc(ue_rrc->cipheringAlgorithm, ue_rrc->kgnb, &kRRCenc);
nr_derive_key_rrc_int(ue_rrc->integrityProtAlgorithm, ue_rrc->kgnb, &kRRCint);
uint8_t kRRCenc[16] = {0};
uint8_t kRRCint[16] = {0};
nr_derive_key(RRC_ENC_ALG,
NR_UE_rrc_inst[ctxt_pP->module_id].cipheringAlgorithm,
NR_UE_rrc_inst[ctxt_pP->module_id].kgnb,
kRRCenc);
nr_derive_key(RRC_INT_ALG,
NR_UE_rrc_inst[ctxt_pP->module_id].integrityProtAlgorithm,
NR_UE_rrc_inst[ctxt_pP->module_id].kgnb,
kRRCint);
// Refresh SRBs
nr_pdcp_add_srbs(ctxt_pP->enb_flag,
@@ -1959,12 +1971,16 @@ nr_rrc_ue_establish_srb2(
}
}
uint8_t *kUPenc = NULL;
uint8_t *kUPint = NULL;
NR_UE_RRC_INST_t *ue_rrc = &NR_UE_rrc_inst[ctxt_pP->module_id];
nr_derive_key_up_enc(ue_rrc->cipheringAlgorithm, ue_rrc->kgnb, &kUPenc);
nr_derive_key_up_int(ue_rrc->integrityProtAlgorithm, ue_rrc->kgnb, &kUPint);
uint8_t kUPenc[16] = {0};
uint8_t kUPint[16] = {0};
nr_derive_key(UP_ENC_ALG,
NR_UE_rrc_inst[ctxt_pP->module_id].cipheringAlgorithm,
NR_UE_rrc_inst[ctxt_pP->module_id].kgnb,
kUPenc);
nr_derive_key(UP_INT_ALG,
NR_UE_rrc_inst[ctxt_pP->module_id].integrityProtAlgorithm,
NR_UE_rrc_inst[ctxt_pP->module_id].kgnb,
kUPint);
// Refresh DRBs
nr_pdcp_add_drbs(ctxt_pP->enb_flag,
-18
View File
@@ -1,18 +0,0 @@
OAISIM Security Algorithms v0.1
Dependencies:
- openssl >= 1.0.1
Compilation:
When compiling oaisim, add SECU=1 to enable security features. The makefile will
check for required dependencies and disable this feature if not all dependencies
are met.
OSA is based on 3GPP TS 33.401.
Note that only EEA2 and EIA2 algorithms are supported, SNOW-3G is not implemented.
Currently the kenb used to derive kRRCint, kRRCenc and kUPenc is composed of the
UE_id. In the future this parameter can be either obtained by deriving KASME received
from core epc (in the S1AP initial context setup request)
or configurable via command line or XML file.
-138
View File
@@ -1,138 +0,0 @@
/*
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenAirInterface Software Alliance licenses this file to You under
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
* except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.openairinterface.org/?page_id=698
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*-------------------------------------------------------------------------------
* For more information about the OpenAirInterface (OAI) Software Alliance:
* contact@openairinterface.org
*/
/*!
* \file secu_defs.h
* \brief Openair security algorithms functions implementing 3GPP TS 33.401
* \note HMAC computations are done by openssl library
* \author Sebastien ROUX
* \date 2013
* \version 0.1
* @ingroup security
*/
#ifndef __UTIL_OSA_OSA_DEFS__H__
#define __UTIL_OSA_OSA_DEFS__H__
#define EIA0_ALG_ID 0x00
#define EIA1_128_ALG_ID 0x01
#define EIA2_128_ALG_ID 0x02
#define EEA0_ALG_ID EIA0_ALG_ID
#define EEA1_128_ALG_ID EIA1_128_ALG_ID
#define EEA2_128_ALG_ID EIA2_128_ALG_ID
#define SECU_DIRECTION_UPLINK 0
#define SECU_DIRECTION_DOWNLINK 1
typedef enum {
NAS_ENC_ALG = 0x01,
NAS_INT_ALG = 0x02,
RRC_ENC_ALG = 0x03,
RRC_INT_ALG = 0x04,
UP_ENC_ALG = 0x05,
UP_INT_ALG = 0x06
} algorithm_type_dist_t;
//int derive_keNB(const uint8_t kasme[32], const uint32_t nas_count, uint8_t **keNB);
int derive_skgNB(const uint8_t *keNB, const uint16_t sk_counter, uint8_t *skgNB);
int derive_key(algorithm_type_dist_t nas_alg_type, uint8_t nas_enc_alg_id,
const uint8_t key[32], uint8_t **out);
int nr_derive_key(algorithm_type_dist_t alg_type, uint8_t alg_id,
const uint8_t key[32], uint8_t **out);
int nr_derive_key_ng_ran_star(uint16_t pci, uint64_t nr_arfcn_dl, const uint8_t key[32], uint8_t *key_ng_ran_star);
//#define derive_key_nas_enc(aLGiD, kEY, kNAS) derive_key(NAS_ENC_ALG, aLGiD, kEY, kNAS)
//#define derive_key_nas_int(aLGiD, kEY, kNAS) derive_key(NAS_INT_ALG, aLGiD, kEY, kNAS)
#define derive_key_rrc_enc(aLGiD, kEY, kNAS) \
derive_key(RRC_ENC_ALG, aLGiD, kEY, kNAS)
#define derive_key_rrc_int(aLGiD, kEY, kNAS) \
derive_key(RRC_INT_ALG, aLGiD, kEY, kNAS)
#define derive_key_up_enc(aLGiD, kEY, kNAS) \
derive_key(UP_ENC_ALG, aLGiD, kEY, kNAS)
#define derive_key_up_int(aLGiD, kEY, kNAS) \
derive_key(UP_INT_ALG, aLGiD, kEY, kNAS)
// 5G SA
#define nr_derive_key_rrc_enc(aLGiD, kEY, kRRC) \
nr_derive_key(RRC_ENC_ALG, aLGiD, kEY, kRRC)
#define nr_derive_key_rrc_int(aLGiD, kEY, kRRC) \
nr_derive_key(RRC_INT_ALG, aLGiD, kEY, kRRC)
#define nr_derive_key_up_enc(aLGiD, kEY, kUP) \
nr_derive_key(UP_ENC_ALG, aLGiD, kEY, kUP)
#define nr_derive_key_up_int(aLGiD, kEY, kUP) \
nr_derive_key(UP_INT_ALG, aLGiD, kEY, kUP)
typedef struct {
uint8_t *key;
uint32_t key_length;
uint32_t count;
uint8_t bearer;
uint8_t direction;
uint8_t *message;
/* length in bits */
uint32_t blength;
} stream_cipher_t;
/*!
* @brief Encrypt/Decrypt a block of data based on the provided algorithm
* @param[in] algorithm Algorithm used to encrypt the data
* Possible values are:
* - EIA0_ALG_ID for NULL encryption
* - EIA1_128_ALG_ID for SNOW-3G encryption (not avalaible right now)
* - EIA2_128_ALG_ID for 128 bits AES LTE encryption
* @param[in] stream_cipher All parameters used to compute the encrypted block of data
* @param[out] out The encrypted block of data dynamically allocated
* @return 0 if everything OK, -1 if something failed
*/
int stream_encrypt(uint8_t algorithm, stream_cipher_t *stream_cipher, uint8_t **out);
#define stream_decrypt stream_encrypt
int stream_compute_integrity(uint8_t algorithm, stream_cipher_t *stream_cipher, uint8_t out[4]);
/*!
* @brief Decrypt a block of data based on the provided algorithm
* @param[in] algorithm Algorithm used to encrypt the data
* Possible values are:
* - EIA0_ALG_ID for NULL encryption
* - EIA1_128_ALG_ID for SNOW-3G encryption (not avalaible right now)
* - EIA2_128_ALG_ID for 128 bits AES LTE encryption
* @param[in] stream_cipher All parameters used to compute the decrypted block of data
* @param[out] out The decrypted block of data dynamically allocated
* @return 0 if everything OK, -1 if something failed
*/
int stream_decrypt(uint8_t algorithm, stream_cipher_t *stream_cipher, uint8_t **out);
int stream_check_integrity(uint8_t algorithm, stream_cipher_t *stream_cipher, uint8_t *expected);
#undef SECU_DEBUG
#endif /* __UTIL_OSA_OSA_DEFS__H__ */
-175
View File
@@ -1,175 +0,0 @@
/*
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenAirInterface Software Alliance licenses this file to You under
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
* except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.openairinterface.org/?page_id=698
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*-------------------------------------------------------------------------------
* For more information about the OpenAirInterface (OAI) Software Alliance:
* contact@openairinterface.org
*/
#include "../../../openair3/SECU/kdf.h"
#include <stdint.h>
#include <string.h>
#include "osa_defs.h"
#include "osa_internal.h"
#include "common/utils/LOG/log.h"
/*!
* @brief Derive the keys from key and perform truncate on the generated key to
* reduce his size to 128 bits. Definition of the derivation function can
* be found in 3GPP TS.33401 #A.7
* @param[in] alg_type Algorithm distinguisher
* @param[in] alg_id Algorithm identifier.
* Possible values are:
* - 0 for EIA0 algorithm (Null Integrity Protection algorithm)
* - 1 for 128-EIA1 SNOW 3G
* - 2 for 128-EIA2 AES
* @param[in] key The top key used to derive other subkeys
* @param[out] out Pointer to reference where output of KDF will be stored.
* NOTE: knas is dynamically allocated by the KDF function
*/
int derive_key(algorithm_type_dist_t alg_type, uint8_t alg_id, const uint8_t key[32], uint8_t **out)
{
uint8_t string[7] = {0};
/* FC */
string[0] = FC_ALG_KEY_DER;
/* P0 = algorithm type distinguisher */
string[1] = (uint8_t)(alg_type & 0xFF);
/* L0 = length(P0) = 1 */
string[2] = 0x00;
string[3] = 0x01;
/* P1 */
string[4] = alg_id;
/* L1 = length(P1) = 1 */
string[5] = 0x00;
string[6] = 0x01;
#if defined(SECU_DEBUG)
{
int i;
char payload[6 * sizeof(string) + 1];
int index = 0;
for (i = 0; i < sizeof(string); i++)
index += sprintf(&payload[index], "0x%02x ", string[i]);
LOG_D(OSA, "Key deriver input string: %s\n", payload);
}
#endif
byte_array_t data = {.buf = string, .len = 7};
if (*out == NULL) {
*out = malloc(sizeof(uint8_t) * 32);
DevAssert(*out != NULL && "Memory exhausted");
}
kdf(key, data, 32, *out);
return 0;
}
int nr_derive_key(algorithm_type_dist_t alg_type, uint8_t alg_id, const uint8_t key[32], uint8_t **out)
{
uint8_t string[7];
/* FC */
string[0] = NR_FC_ALG_KEY_DER;
/* P0 = algorithm type distinguisher */
string[1] = (uint8_t)(alg_type & 0xFF);
/* L0 = length(P0) = 1 */
string[2] = 0x00;
string[3] = 0x01;
/* P1 */
string[4] = alg_id;
/* L1 = length(P1) = 1 */
string[5] = 0x00;
string[6] = 0x01;
byte_array_t data = {.buf = string, .len = 7};
if (*out == NULL) {
*out = malloc(sizeof(uint8_t) * 32);
DevAssert(*out != NULL && "Memory exhausted");
}
kdf(key, data, 32, *out);
// in NR, we use the last 16 bytes, ignoring the first 16 ones
memcpy(*out, *out + 16, 16);
return 0;
}
int nr_derive_key_ng_ran_star(uint16_t pci, uint64_t nr_arfcn_dl, const uint8_t key[32], uint8_t *key_ng_ran_star)
{
uint8_t s[10] = {0};
/* FC */
s[0] = NR_FC_ALG_KEY_NG_RAN_STAR_DER;
/* P0 = PCI */
s[1] = (pci & 0x0000ff00) >> 8;
s[2] = (pci & 0x000000ff);
/* L0 = length(P0) = 2 */
s[3] = 0x00;
s[4] = 0x02;
/* P1 = NR ARFCN */
s[5] = (nr_arfcn_dl & 0x00ff0000) >> 16;
s[6] = (nr_arfcn_dl & 0x0000ff00) >> 8;
s[7] = (nr_arfcn_dl & 0x000000ff);
/* L1 = length(P1) = 3 */
s[8] = 0x00;
s[9] = 0x03;
byte_array_t data = {.buf = s, .len = 10};
const uint32_t len_key = 32;
kdf(key, data, len_key, key_ng_ran_star);
return 0;
}
int derive_skgNB(const uint8_t *keNB, const uint16_t sk_counter, uint8_t *skgNB)
{
uint8_t s[5] = {0};
/* FC is 0x1c (see 3gpp 33.401 annex A.15) */
s[0] = 0x1c;
/* put sk_counter */
s[1] = (sk_counter >> 8) & 0xff;
s[2] = sk_counter & 0xff;
/* put length of sk_counter (2) */
s[3] = 0x00;
s[4] = 0x02;
byte_array_t data = {.buf = s, .len = 5};
kdf(keNB, data, 32, skgNB);
return 0;
}
-344
View File
@@ -1,344 +0,0 @@
/*
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenAirInterface Software Alliance licenses this file to You under
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
* except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.openairinterface.org/?page_id=698
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*-------------------------------------------------------------------------------
* For more information about the OpenAirInterface (OAI) Software Alliance:
* contact@openairinterface.org
*/
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include "osa_rijndael.h"
#include "osa_snow3g.h"
static uint8_t OSA_MULx(uint8_t V, uint8_t c);
static uint8_t OSA_MULxPOW(uint8_t V, uint8_t i, uint8_t c);
static uint32_t OSA_MULalpha(uint8_t c);
static uint32_t OSA_DIValpha(uint8_t c);
static uint32_t OSA_S1(uint32_t w);
static uint32_t OSA_S2(uint32_t w);
static void osa_snow3g_clock_LFSR_initialization_mode(uint32_t F, osa_snow_3g_context_t *s3g_ctx_pP);
static void osa_snow3g_clock_LFSR_key_stream_mode(osa_snow_3g_context_t *snow_3g_context_pP);
static uint32_t osa_snow3g_clock_fsm(osa_snow_3g_context_t *snow_3g_context_pP);
void osa_snow3g_initialize(uint32_t k[4], uint32_t IV[4], osa_snow_3g_context_t *snow_3g_context_pP);
void osa_snow3g_generate_key_stream(uint32_t n, uint32_t *ks, osa_snow_3g_context_t *snow_3g_context_pP);
/* OSA_MULx.
* Input V: an 8-bit input.
* Input c: an 8-bit input.
* Output : an 8-bit input.
* MULx maps 16 bits to 8 bits
*/
static uint8_t OSA_MULx(uint8_t V, uint8_t c)
{
//If the leftmost (i.e. the most significant) bit of V equals 1
if ( V & 0x80 )
return ( (V << 1) ^ c);
else
return ( V << 1);
}
/* OSA_MULxPOW.
* Input V: an 8-bit input.
* Input i: a positive integer.
* Input c: an 8-bit input.
* Output : an 8-bit output.
* MULxPOW maps 16 bits and a positive integer i to 8 bit.
*/
static uint8_t OSA_MULxPOW(uint8_t V, uint8_t i, uint8_t c)
{
if ( i == 0)
return V;
else
return OSA_MULx( OSA_MULxPOW( V, i-1, c ), c);
}
/* The function OSA_MULalpha.
* Input c: 8-bit input.
* Output : 32-bit output.
* maps 8 bits to 32 bits.
*/
static uint32_t OSA_MULalpha(uint8_t c)
{
return ( ( ((uint32_t)OSA_MULxPOW(c,23, 0xa9)) << 24 ) |
( ((uint32_t)OSA_MULxPOW(c, 245, 0xa9)) << 16 ) |
( ((uint32_t)OSA_MULxPOW(c, 48, 0xa9)) << 8 ) |
( ((uint32_t)OSA_MULxPOW(c, 239, 0xa9)) ) ) ;
}
/* The function DIV alpha.
* Input c: 8-bit input.
* Output : 32-bit output.
* maps 8 bits to 32 bit.
*/
static uint32_t OSA_DIValpha(uint8_t c)
{
return ( ( ((uint32_t)OSA_MULxPOW(c, 16, 0xa9)) << 24 ) |
( ((uint32_t)OSA_MULxPOW(c, 39, 0xa9)) << 16 ) |
( ((uint32_t)OSA_MULxPOW(c, 6, 0xa9)) << 8 ) |
( ((uint32_t)OSA_MULxPOW(c, 64, 0xa9)) ) ) ;
}
/* The 32x32-bit S-Box S1
* Input: a 32-bit input.
* Output: a 32-bit output of S1 box.
* The S-Box S1 maps a 32-bit input to a 32-bit output.
* w = w0 || w1 || w2 || w3 the 32-bit input with w0 the most and w3 the least significant byte.
* S1(w)= r0 || r1 || r2 || r3 with r0 the most and r3 the least significant byte.
*/
static uint32_t OSA_S1(uint32_t w)
{
uint8_t r0=0, r1=0, r2=0, r3=0;
uint8_t srw0 = OSA_SR[ (uint8_t)((w >> 24) & 0xff) ];
uint8_t srw1 = OSA_SR[ (uint8_t)((w >> 16) & 0xff) ];
uint8_t srw2 = OSA_SR[ (uint8_t)((w >> 8) & 0xff) ];
uint8_t srw3 = OSA_SR[ (uint8_t)((w) & 0xff) ];
r0 = ( ( OSA_MULx( srw0 , 0x1b) ) ^
( srw1 ) ^
( srw2 ) ^
( (OSA_MULx( srw3, 0x1b)) ^ srw3 )
);
r1 = ( ( ( OSA_MULx( srw0 , 0x1b) ) ^ srw0 ) ^
( OSA_MULx(srw1, 0x1b) ) ^
( srw2 ) ^
( srw3 )
);
r2 = ( ( srw0 ) ^
( ( OSA_MULx( srw1 , 0x1b) ) ^ srw1 ) ^
( OSA_MULx(srw2, 0x1b) ) ^
( srw3 )
);
r3 = ( ( srw0 ) ^
( srw1 ) ^
( ( OSA_MULx( srw2 , 0x1b) ) ^ srw2 ) ^
( OSA_MULx( srw3, 0x1b) )
);
return ( ( ((uint32_t)r0) << 24 ) | ( ((uint32_t)r1) << 16 ) | ( ((uint32_t)r2) << 8 ) | ( ((uint32_t)r3) ) );
}
/* The 32x32-bit S-Box S2
* Input: a 32-bit input.
* Output: a 32-bit output of S2 box.
* The S-Box S2 maps a 32-bit input to a 32-bit output.
* Let w = w0 || w1 || w2 || w3 the 32-bit input with w0 the most and w3 the least significant byte.
* Let S2(w)= r0 || r1 || r2 || r3 with r0 the most and r3 the least significant byte.
*/
static uint32_t OSA_S2(uint32_t w)
{
uint8_t r0=0, r1=0, r2=0, r3=0;
uint8_t sqw0 = OSA_SQ[ (uint8_t)((w >> 24) & 0xff) ];
uint8_t sqw1 = OSA_SQ[ (uint8_t)((w >> 16) & 0xff) ];
uint8_t sqw2 = OSA_SQ[ (uint8_t)((w >> 8) & 0xff) ];
uint8_t sqw3 = OSA_SQ[ (uint8_t)((w) & 0xff) ];
r0 = ( ( OSA_MULx( sqw0 , 0x69) ) ^
( sqw1 ) ^
( sqw2 ) ^
( (OSA_MULx( sqw3, 0x69)) ^ sqw3 )
);
r1 = ( ( ( OSA_MULx( sqw0 , 0x69) ) ^ sqw0 ) ^
( OSA_MULx(sqw1, 0x69) ) ^
( sqw2 ) ^
( sqw3 )
);
r2 = ( ( sqw0 ) ^
( ( OSA_MULx( sqw1 , 0x69) ) ^ sqw1 ) ^
( OSA_MULx(sqw2, 0x69) ) ^
( sqw3 )
);
r3 = ( ( sqw0 ) ^
( sqw1 ) ^
( ( OSA_MULx( sqw2 , 0x69) ) ^ sqw2 ) ^
( OSA_MULx( sqw3, 0x69) )
);
return ( ( ((uint32_t)r0) << 24 ) | ( ((uint32_t)r1) << 16 ) | ( ((uint32_t)r2) << 8 ) | ( ((uint32_t)r3) ) );
}
/* Clocking LFSR in initialization mode.
* LFSR Registers S0 to S15 are updated as the LFSR receives a single clock.
* Input F: a 32-bit word comes from output of FSM.
* See section 3.4.4.
*/
static void osa_snow3g_clock_LFSR_initialization_mode(uint32_t F, osa_snow_3g_context_t *s3g_ctx_pP)
{
uint32_t v = ( ( (s3g_ctx_pP->LFSR_S0 << 8) & 0xffffff00 ) ^
( OSA_MULalpha( (uint8_t)((s3g_ctx_pP->LFSR_S0>>24) & 0xff) ) ) ^
( s3g_ctx_pP->LFSR_S2 ) ^
( (s3g_ctx_pP->LFSR_S11 >> 8) & 0x00ffffff ) ^
( OSA_DIValpha( (uint8_t)( ( s3g_ctx_pP->LFSR_S11) & 0xff ) ) ) ^
( F )
);
s3g_ctx_pP->LFSR_S0 = s3g_ctx_pP->LFSR_S1;
s3g_ctx_pP->LFSR_S1 = s3g_ctx_pP->LFSR_S2;
s3g_ctx_pP->LFSR_S2 = s3g_ctx_pP->LFSR_S3;
s3g_ctx_pP->LFSR_S3 = s3g_ctx_pP->LFSR_S4;
s3g_ctx_pP->LFSR_S4 = s3g_ctx_pP->LFSR_S5;
s3g_ctx_pP->LFSR_S5 = s3g_ctx_pP->LFSR_S6;
s3g_ctx_pP->LFSR_S6 = s3g_ctx_pP->LFSR_S7;
s3g_ctx_pP->LFSR_S7 = s3g_ctx_pP->LFSR_S8;
s3g_ctx_pP->LFSR_S8 = s3g_ctx_pP->LFSR_S9;
s3g_ctx_pP->LFSR_S9 = s3g_ctx_pP->LFSR_S10;
s3g_ctx_pP->LFSR_S10 = s3g_ctx_pP->LFSR_S11;
s3g_ctx_pP->LFSR_S11 = s3g_ctx_pP->LFSR_S12;
s3g_ctx_pP->LFSR_S12 = s3g_ctx_pP->LFSR_S13;
s3g_ctx_pP->LFSR_S13 = s3g_ctx_pP->LFSR_S14;
s3g_ctx_pP->LFSR_S14 = s3g_ctx_pP->LFSR_S15;
s3g_ctx_pP->LFSR_S15 = v;
}
/* Clocking LFSR in keystream mode.
* LFSR Registers S0 to S15 are updated as the LFSR receives a single clock.
* See section 3.4.5.
*/
static void osa_snow3g_clock_LFSR_key_stream_mode(osa_snow_3g_context_t *snow_3g_context_pP)
{
uint32_t v = ( ( (snow_3g_context_pP->LFSR_S0 << 8) & 0xffffff00 ) ^
( OSA_MULalpha( (uint8_t)((snow_3g_context_pP->LFSR_S0>>24) & 0xff) ) ) ^
( snow_3g_context_pP->LFSR_S2 ) ^
( (snow_3g_context_pP->LFSR_S11 >> 8) & 0x00ffffff ) ^
( OSA_DIValpha( (uint8_t)( ( snow_3g_context_pP->LFSR_S11) & 0xff ) ) )
);
snow_3g_context_pP->LFSR_S0 = snow_3g_context_pP->LFSR_S1;
snow_3g_context_pP->LFSR_S1 = snow_3g_context_pP->LFSR_S2;
snow_3g_context_pP->LFSR_S2 = snow_3g_context_pP->LFSR_S3;
snow_3g_context_pP->LFSR_S3 = snow_3g_context_pP->LFSR_S4;
snow_3g_context_pP->LFSR_S4 = snow_3g_context_pP->LFSR_S5;
snow_3g_context_pP->LFSR_S5 = snow_3g_context_pP->LFSR_S6;
snow_3g_context_pP->LFSR_S6 = snow_3g_context_pP->LFSR_S7;
snow_3g_context_pP->LFSR_S7 = snow_3g_context_pP->LFSR_S8;
snow_3g_context_pP->LFSR_S8 = snow_3g_context_pP->LFSR_S9;
snow_3g_context_pP->LFSR_S9 = snow_3g_context_pP->LFSR_S10;
snow_3g_context_pP->LFSR_S10 = snow_3g_context_pP->LFSR_S11;
snow_3g_context_pP->LFSR_S11 = snow_3g_context_pP->LFSR_S12;
snow_3g_context_pP->LFSR_S12 = snow_3g_context_pP->LFSR_S13;
snow_3g_context_pP->LFSR_S13 = snow_3g_context_pP->LFSR_S14;
snow_3g_context_pP->LFSR_S14 = snow_3g_context_pP->LFSR_S15;
snow_3g_context_pP->LFSR_S15 = v;
}
/* Clocking FSM.
* Produces a 32-bit word F.
* Updates FSM registers R1, R2, R3.
* See Section 3.4.6.
*/
static uint32_t osa_snow3g_clock_fsm(osa_snow_3g_context_t *snow_3g_context_pP)
{
uint32_t F = ( ( snow_3g_context_pP->LFSR_S15 + snow_3g_context_pP->FSM_R1 ) & 0xffffffff ) ^ snow_3g_context_pP->FSM_R2 ;
uint32_t r = ( snow_3g_context_pP->FSM_R2 + ( snow_3g_context_pP->FSM_R3 ^ snow_3g_context_pP->LFSR_S5 ) ) & 0xffffffff ;
snow_3g_context_pP->FSM_R3 = OSA_S2(snow_3g_context_pP->FSM_R2);
snow_3g_context_pP->FSM_R2 = OSA_S1(snow_3g_context_pP->FSM_R1);
snow_3g_context_pP->FSM_R1 = r;
return F;
}
/* Initialization.
* Input k[4]: Four 32-bit words making up 128-bit key.
* Input IV[4]: Four 32-bit words making 128-bit initialization variable.
* Output: All the LFSRs and FSM are initialized for key generation.
* See Section 4.1.
*/
void osa_snow3g_initialize(uint32_t k[4], uint32_t IV[4], osa_snow_3g_context_t *snow_3g_context_pP)
{
uint8_t i = 0;
uint32_t F = 0x0;
snow_3g_context_pP->LFSR_S15 = k[3] ^ IV[0];
snow_3g_context_pP->LFSR_S14 = k[2];
snow_3g_context_pP->LFSR_S13 = k[1];
snow_3g_context_pP->LFSR_S12 = k[0] ^ IV[1];
snow_3g_context_pP->LFSR_S11 = k[3] ^ 0xffffffff;
snow_3g_context_pP->LFSR_S10 = k[2] ^ 0xffffffff ^ IV[2];
snow_3g_context_pP->LFSR_S9 = k[1] ^ 0xffffffff ^ IV[3];
snow_3g_context_pP->LFSR_S8 = k[0] ^ 0xffffffff;
snow_3g_context_pP->LFSR_S7 = k[3];
snow_3g_context_pP->LFSR_S6 = k[2];
snow_3g_context_pP->LFSR_S5 = k[1];
snow_3g_context_pP->LFSR_S4 = k[0];
snow_3g_context_pP->LFSR_S3 = k[3] ^ 0xffffffff;
snow_3g_context_pP->LFSR_S2 = k[2] ^ 0xffffffff;
snow_3g_context_pP->LFSR_S1 = k[1] ^ 0xffffffff;
snow_3g_context_pP->LFSR_S0 = k[0] ^ 0xffffffff;
snow_3g_context_pP->FSM_R1 = 0x0;
snow_3g_context_pP->FSM_R2 = 0x0;
snow_3g_context_pP->FSM_R3 = 0x0;
for(i=0; i<32; i++) {
F = osa_snow3g_clock_fsm(snow_3g_context_pP);
osa_snow3g_clock_LFSR_initialization_mode(F, snow_3g_context_pP);
}
}
/* Generation of Keystream.
* input n: number of 32-bit words of keystream.
* input z: space for the generated keystream, assumes
* memory is allocated already.
* output: generated keystream which is filled in z
* See section 4.2.
*/
void osa_snow3g_generate_key_stream(uint32_t n, uint32_t *ks, osa_snow_3g_context_t *snow_3g_context_pP)
{
uint32_t t = 0;
uint32_t F = 0x0;
osa_snow3g_clock_fsm(snow_3g_context_pP); /* Clock FSM once. Discard the output. */
osa_snow3g_clock_LFSR_key_stream_mode(snow_3g_context_pP); /* Clock LFSR in keystream mode once. */
for ( t=0; t<n; t++) {
F = osa_snow3g_clock_fsm(snow_3g_context_pP); /* STEP 1 */
ks[t] = F ^ snow_3g_context_pP->LFSR_S0; /* STEP 2 */
/* Note that ks[t] corresponds to z_{t+1} in section 4.2*/
osa_snow3g_clock_LFSR_key_stream_mode(snow_3g_context_pP); /* STEP 3 */
}
}
-77
View File
@@ -1,77 +0,0 @@
/*
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenAirInterface Software Alliance licenses this file to You under
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
* except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.openairinterface.org/?page_id=698
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*-------------------------------------------------------------------------------
* For more information about the OpenAirInterface (OAI) Software Alliance:
* contact@openairinterface.org
*/
/*! \file snow3g.h
* \brief
* \author Open source Adapted from Specification of the 3GPP Confidentiality and
* Integrity Algorithms UEA2 & UIA2. Document 2: SNOW 3G Specification
* \integrators Kharbach Othmane, GAUTHIER Lionel.
* \date 2014
* \version
* \note
* \bug
* \warning
*/
#ifndef OSA_SNOW3G_H_
#define OSA_SNOW3G_H_
typedef struct osa_snow_3g_context_s {
uint32_t LFSR_S0;
uint32_t LFSR_S1;
uint32_t LFSR_S2;
uint32_t LFSR_S3;
uint32_t LFSR_S4;
uint32_t LFSR_S5;
uint32_t LFSR_S6;
uint32_t LFSR_S7;
uint32_t LFSR_S8;
uint32_t LFSR_S9;
uint32_t LFSR_S10;
uint32_t LFSR_S11;
uint32_t LFSR_S12;
uint32_t LFSR_S13;
uint32_t LFSR_S14;
uint32_t LFSR_S15;
/* FSM : The Finite State Machine has three 32-bit registers R1, R2 and R3.
*/
uint32_t FSM_R1;
uint32_t FSM_R2;
uint32_t FSM_R3;
} osa_snow_3g_context_t;
/* Initialization.
* Input k[4]: Four 32-bit words making up 128-bit key.
* Input IV[4]: Four 32-bit words making 128-bit initialization variable.
* Output: All the LFSRs and FSM are initialized for key generation.
*/
void osa_snow3g_initialize(uint32_t k[4], uint32_t IV[4], osa_snow_3g_context_t *snow_3g_context_pP);
/* Generation of Keystream.
* input n: number of 32-bit words of keystream.
* input z: space for the generated keystream, assumes
* memory is allocated already.
* output: generated keystream which is filled in z
*/
void osa_snow3g_generate_key_stream(uint32_t n, uint32_t *z, osa_snow_3g_context_t *snow_3g_context_pP);
#endif
-181
View File
@@ -1,181 +0,0 @@
/*
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenAirInterface Software Alliance licenses this file to You under
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
* except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.openairinterface.org/?page_id=698
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*-------------------------------------------------------------------------------
* For more information about the OpenAirInterface (OAI) Software Alliance:
* contact@openairinterface.org
*/
#include <arpa/inet.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include "common/utils/LOG/log.h"
#include "byte_array.h"
#include "openair3//SECU//aes_128_ctr.h"
#include "assertions.h"
#include "osa_defs.h"
#include "osa_snow3g.h"
#include "osa_internal.h"
int stream_encrypt_eea0(stream_cipher_t *stream_cipher, uint8_t **out)
{
uint8_t *data = NULL;
uint32_t byte_length;
DevAssert(stream_cipher != NULL);
DevAssert(out != NULL);
LOG_D(OSA,
"Entering stream_encrypt_eea0, bits length %u, bearer %u, "
"count %u, direction %s\n",
stream_cipher->blength,
stream_cipher->bearer,
stream_cipher->count,
stream_cipher->direction == SECU_DIRECTION_DOWNLINK ? "Downlink" : "Uplink");
byte_length = (stream_cipher->blength + 7) >> 3;
if (*out == NULL) {
/* User did not provide output buffer */
data = malloc(byte_length);
*out = data;
} else {
data = *out;
}
memcpy(data, stream_cipher->message, byte_length);
return 0;
}
int stream_encrypt_eea1(stream_cipher_t *stream_cipher, uint8_t **out)
{
osa_snow_3g_context_t snow_3g_context;
int n;
int i = 0;
uint32_t zero_bit = 0;
uint32_t *KS;
uint32_t K[4], IV[4];
DevAssert(stream_cipher != NULL);
DevAssert(stream_cipher->key != NULL);
DevAssert(stream_cipher->key_length == 16);
DevAssert(out != NULL);
n = (stream_cipher->blength + 31) / 32;
zero_bit = stream_cipher->blength & 0x7;
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
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*/
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. */
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];
IV[0] = IV[2];
/* Run SNOW 3G algorithm to generate sequence of key stream bits KS*/
osa_snow3g_initialize(K, IV, &snow_3g_context);
KS = (uint32_t *)malloc(4 * n);
osa_snow3g_generate_key_stream(n, (uint32_t *)KS, &snow_3g_context);
if (zero_bit > 0) {
KS[n - 1] = KS[n - 1] & (uint32_t)(0xFFFFFFFF << (8 - zero_bit));
}
for (i = 0; i < n; i++) {
KS[i] = hton_int32(KS[i]);
}
/* Exclusive-OR the input data with keystream to generate the output bit
stream */
for (i = 0; i < n * 4; i++) {
stream_cipher->message[i] ^= *(((uint8_t *)KS) + i);
}
if (zero_bit > 0) {
int ceil_index = (stream_cipher->blength + 7) >> 3;
stream_cipher->message[ceil_index - 1] = stream_cipher->message[ceil_index - 1] & (uint8_t)(0xFF << (8 - zero_bit));
}
free(KS);
*out = stream_cipher->message;
return 0;
}
int stream_encrypt_eea2(stream_cipher_t *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);
if (*out == NULL) {
*out = calloc(1, (stream_cipher->blength >> 3) + 1);
DevAssert(*out != NULL && "Memory exhausted");
}
aes_128_t p = {0};
memcpy(p.key, stream_cipher->key, stream_cipher->key_length);
p.type = AES_INITIALIZATION_VECTOR_16;
p.iv16.d.count = htonl(stream_cipher->count);
p.iv16.d.bearer = stream_cipher->bearer;
p.iv16.d.direction = stream_cipher->direction;
DevAssert((stream_cipher->blength & 0x07) == 0 && "Cipher length must be multiple of one octet");
const uint32_t byte_lenght = stream_cipher->blength >> 3;
// Precondition: out must have enough space, at least as much as the input
const size_t len_out = byte_lenght;
byte_array_t msg = {.buf = stream_cipher->message, .len =byte_lenght};
aes_128_ctr(&p, msg, len_out, *out);
return 0;
}
int stream_encrypt(uint8_t algorithm, stream_cipher_t *stream_cipher, uint8_t **out)
{
if (algorithm == EEA0_ALG_ID) {
return stream_encrypt_eea0(stream_cipher, out);
} else if (algorithm == EEA1_128_ALG_ID) {
return stream_encrypt_eea1(stream_cipher, out);
} else if (algorithm == EEA2_128_ALG_ID) {
return stream_encrypt_eea2(stream_cipher, out);
}
LOG_E(OSA, "Provided encryption algorithm is currently not supported = %u\n", algorithm);
return -1;
}
-287
View File
@@ -1,287 +0,0 @@
/*
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenAirInterface Software Alliance licenses this file to You under
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
* except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.openairinterface.org/?page_id=698
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*-------------------------------------------------------------------------------
* For more information about the OpenAirInterface (OAI) Software Alliance:
* contact@openairinterface.org
*/
#include <arpa/inet.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <math.h>
#include "assertions.h"
#include "common/utils/LOG/log.h"
#include "openair3/SECU/aes_128_cbc_cmac.h"
#include "osa_defs.h"
#include "osa_snow3g.h"
#include "osa_internal.h"
// see spec 3GPP Confidentiality and Integrity Algorithms UEA2&UIA2. Document 1: UEA2 and UIA2 Specification. Version 1.1
/* OSA_MUL64x.
* Input V: a 64-bit input.
* Input c: a 64-bit input.
* Output : a 64-bit output.
* A 64-bit memory is allocated which is to be freed by the calling
* function.
* See section 4.3.2 for details.
*/
uint64_t OSA_MUL64x(uint64_t V, uint64_t c)
{
if (V & 0x8000000000000000)
return (V << 1) ^ c;
else
return V << 1;
}
/* OSA_MUL64xPOW.
* Input V: a 64-bit input.
* Input i: a positive integer.
* Input c: a 64-bit input.
* Output : a 64-bit output.
* A 64-bit memory is allocated which is to be freed by the calling
function.
* See section 4.3.3 for details.
*/
uint64_t OSA_MUL64xPOW(uint64_t V, uint32_t i, uint64_t c)
{
if (i == 0)
return V;
else
return OSA_MUL64x(OSA_MUL64xPOW(V, i - 1, c), c);
}
/* OSA_MUL64.
* Input V: a 64-bit input.
* Input P: a 64-bit input.
* Input c: a 64-bit input.
* Output : a 64-bit output.
* A 64-bit memory is allocated which is to be freed by the calling
* function.
* See section 4.3.4 for details.
*/
uint64_t OSA_MUL64(uint64_t V, uint64_t P, uint64_t c)
{
uint64_t result = 0;
int i = 0;
for (i = 0; i < 64; i++) {
if ((P >> i) & 0x1)
result ^= OSA_MUL64xPOW(V, i, c);
}
return result;
}
/* osa_mask32bit.
* Input n: an integer in 1-32.
* Output : a 32 bit mask.
* Prepares a 32 bit mask with required number of 1 bits on the MSB side.
*/
uint32_t osa_mask32bit(int n)
{
uint32_t mask = 0x0;
if (n % 32 == 0)
return 0xffffffff;
while (n--)
mask = (mask >> 1) ^ 0x80000000;
return mask;
}
/*!
* @brief Create integrity cmac t for a given message.
* @param[in] stream_cipher Structure containing various variables to setup encoding
* @param[out] out For EIA2 the output string is 32 bits long
*/
int stream_compute_integrity_eia1(stream_cipher_t *stream_cipher, uint8_t out[4])
{
osa_snow_3g_context_t snow_3g_context;
uint32_t K[4], IV[4], z[5];
int i = 0, D;
uint32_t MAC_I = 0;
uint64_t EVAL;
uint64_t V;
uint64_t P;
uint64_t Q;
uint64_t c;
uint64_t M_D_2;
int rem_bits;
uint32_t mask = 0;
uint32_t *message;
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
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*/
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 SNOW3G initialization as in
section 4.4. */
IV[3] = (uint32_t)stream_cipher->count;
IV[2] = ((((uint32_t)stream_cipher->bearer) & 0x0000001F) << 27);
IV[1] = (uint32_t)(stream_cipher->count) ^ ((uint32_t)(stream_cipher->direction) << 31);
IV[0] = ((((uint32_t)stream_cipher->bearer) & 0x0000001F) << 27) ^ ((uint32_t)(stream_cipher->direction & 0x00000001) << 15);
// printf ("K:\n");
// hexprint(K, 16);
// printf ("K[0]:%08X\n",K[0]);
// printf ("K[1]:%08X\n",K[1]);
// printf ("K[2]:%08X\n",K[2]);
// printf ("K[3]:%08X\n",K[3]);
// printf ("IV:\n");
// hexprint(IV, 16);
// printf ("IV[0]:%08X\n",IV[0]);
// printf ("IV[1]:%08X\n",IV[1]);
// printf ("IV[2]:%08X\n",IV[2]);
// printf ("IV[3]:%08X\n",IV[3]);
z[0] = z[1] = z[2] = z[3] = z[4] = 0;
/* Run SNOW 3G to produce 5 keystream words z_1, z_2, z_3, z_4 and z_5. */
osa_snow3g_initialize(K, IV, &snow_3g_context);
osa_snow3g_generate_key_stream(5, z, &snow_3g_context);
// printf ("z[0]:%08X\n",z[0]);
// printf ("z[1]:%08X\n",z[1]);
// printf ("z[2]:%08X\n",z[2]);
// printf ("z[3]:%08X\n",z[3]);
// printf ("z[4]:%08X\n",z[4]);
P = ((uint64_t)z[0] << 32) | (uint64_t)z[1];
Q = ((uint64_t)z[2] << 32) | (uint64_t)z[3];
// printf ("P:%16lX\n",P);
// printf ("Q:%16lX\n",Q);
/* Calculation */
D = ceil(stream_cipher->blength / 64.0) + 1;
// printf ("D:%d\n",D);
EVAL = 0;
c = 0x1b;
/* for 0 <= i <= D-3 */
for (i = 0; i < D - 2; i++) {
V = EVAL ^ ((uint64_t)hton_int32(message[2 * i]) << 32 | (uint64_t)hton_int32(message[2 * i + 1]));
EVAL = OSA_MUL64(V, P, c);
// printf ("Mi: %16X %16X\tEVAL: %16lX\n",hton_int32(message[2*i]),hton_int32(message[2*i+1]), EVAL);
}
/* for D-2 */
rem_bits = stream_cipher->blength % 64;
if (rem_bits == 0)
rem_bits = 64;
mask = osa_mask32bit(rem_bits % 32);
if (rem_bits > 32) {
M_D_2 = ((uint64_t)hton_int32(message[2 * (D - 2)]) << 32) | (uint64_t)(hton_int32(message[2 * (D - 2) + 1]) & mask);
} else {
M_D_2 = ((uint64_t)hton_int32(message[2 * (D - 2)]) & mask) << 32;
}
V = EVAL ^ M_D_2;
EVAL = OSA_MUL64(V, P, c);
/* for D-1 */
EVAL ^= stream_cipher->blength;
/* Multiply by Q */
EVAL = OSA_MUL64(EVAL, Q, c);
MAC_I = (uint32_t)(EVAL >> 32) ^ z[4];
// printf ("MAC_I:%16X\n",MAC_I);
MAC_I = hton_int32(MAC_I);
memcpy(out, &MAC_I, 4);
return 0;
}
int stream_compute_integrity_eia2(stream_cipher_t *stream_cipher, uint8_t out[4])
{
DevAssert(stream_cipher != NULL);
;
DevAssert((stream_cipher->blength & 0x7) == 0);
DevAssert(stream_cipher->key_length == 16 && "k_iv.key and stream_cipher mismatch");
DevAssert(stream_cipher->bearer < 32);
DevAssert(stream_cipher->direction < 2);
aes_128_t k_iv = {0};
memcpy(k_iv.key, stream_cipher->key, sizeof(k_iv.key));
k_iv.type = AES_INITIALIZATION_VECTOR_8;
k_iv.iv8.d.bearer = stream_cipher->bearer;
k_iv.iv8.d.direction = stream_cipher->direction;
k_iv.iv8.d.count = htonl(stream_cipher->count);
const size_t m_length = stream_cipher->blength >> 3;
uint8_t result[16] = {0};
byte_array_t msg = {.len = m_length, .buf = stream_cipher->message };
aes_128_cbc_cmac(&k_iv, msg, sizeof(result), result);
memcpy(out, result, 4);
return 0;
}
int stream_compute_integrity(uint8_t algorithm, stream_cipher_t *stream_cipher, uint8_t out[4])
{
if (algorithm == EIA1_128_ALG_ID) {
LOG_D(OSA, "EIA1 algorithm applied for integrity\n");
return stream_compute_integrity_eia1(stream_cipher, out);
} else if (algorithm == EIA2_128_ALG_ID) {
LOG_D(OSA, "EIA2 algorithm applied for integrity\n");
return stream_compute_integrity_eia2(stream_cipher, out);
}
LOG_E(OSA, "Provided integrity algorithm is currently not supported = %u\n", algorithm);
return -1;
}
int stream_check_integrity(uint8_t algorithm, stream_cipher_t *stream_cipher, uint8_t *expected)
{
uint8_t result[4];
if (algorithm != EIA0_ALG_ID) {
if (stream_compute_integrity(algorithm, stream_cipher, result) != 0) {
return -1;
}
if (memcmp(result, expected, 4) != 0) {
LOG_E(OSA,
"Mismatch found in integrity for algorithm %u,\n"
"\tgot %02x.%02x.%02x.%02x, expecting %02x.%02x.%02x.%02x\n",
algorithm,
result[0],
result[1],
result[2],
result[3],
expected[0],
expected[1],
expected[2],
expected[3]);
return -1;
}
}
/* Integrity verification succeeded */
return 0;
}
+6
View File
@@ -767,3 +767,9 @@ mutex_error:
LOG_E(X2AP, "mutex error\n");
exit(1);
}
void x2ap_trigger(void)
{
MessageDef *msg = itti_alloc_new_message(TASK_X2AP, 0, X2AP_SUBFRAME_PROCESS);
itti_send_msg_to_task(TASK_X2AP, 0, msg);
}
+1
View File
@@ -47,6 +47,7 @@ int x2ap_eNB_init_sctp (x2ap_eNB_instance_t *instance_p,
void *x2ap_task(void *arg);
int is_x2ap_enabled(void);
void x2ap_trigger(void);
#endif /* X2AP_H_ */
-2
View File
@@ -23,8 +23,6 @@
#include "commonDef.h"
#include "security_types.h"
#include "queue.h"
#ifndef COMMON_TYPES_H_
-44
View File
@@ -42,14 +42,6 @@
#define AUTN_LENGTH_BITS (128)
#define AUTN_LENGTH_OCTETS (AUTN_LENGTH_BITS/8)
/* Some methods to convert a string to an int64_t */
/*
#define STRING_TO_64BITS(sTRING, cONTAINER) \
sscanf(sTRING, "%" SCN64, cONTAINER)
#define STRING_TO_U64BITS(sTRING, cONTAINER) \
sscanf(sTRING, "%" SCNu64, cONTAINER)
*/
/* Converts a string to 128 bits gmplib integer holder */
# define STRING_TO_XBITS(sTRING, lENGTH, cONTAINER, rET) \
do { \
@@ -63,18 +55,6 @@ STRING_TO_XBITS(sTRING, 16, cONTAINER, rET)
# define STRING_TO_256BITS(sTRING, cONTAINER, rET) \
STRING_TO_XBITS(sTRING, 32, cONTAINER, rET)
# define STRING_TO_RAND STRING_TO_128BITS
# define STRING_TO_AUTH_KEY STRING_TO_128BITS
# define STRING_TO_AUTH_RES STRING_TO_128BITS
# define STRING_TO_AUTN STRING_TO_128BITS
# define STRING_TO_KASME STRING_TO_256BITS
# define STRING_TO_XRES(sTRING, lENGTH, cONTAINER, rET) \
do { \
STRING_TO_XBITS(sTRING, lENGTH, (cONTAINER)->data, rET); \
if (rET != -1) \
(cONTAINER)->size = lENGTH; \
} while(0)
/* RES amd XRES can have a variable length of 4-16 octets */
typedef struct {
uint8_t size;
@@ -107,28 +87,4 @@ typedef struct eutran_vector_s {
uint8_t kasme[KASME_LENGTH_OCTETS];
} eutran_vector_t;
#define FC_KASME (0x10)
#define FC_KENB (0x11)
#define FC_NH (0x12)
#define FC_KENB_STAR (0x13)
/* 33401 #A.7 Algorithm for key derivation function.
* This FC should be used for:
* - NAS Encryption algorithm
* - NAS Integrity algorithm
* - RRC Encryption algorithm
* - RRC Integrity algorithm
* - User Plane Encryption algorithm
*/
#define FC_ALG_KEY_DER (0x15)
#define FC_KASME_TO_CK (0x16)
typedef enum {
NAS_ENC_ALG = 0x01,
NAS_INT_ALG = 0x02,
RRC_ENC_ALG = 0x03,
RRC_INT_ALG = 0x04,
UP_ENC_ALG = 0x05,
UP_INT_ALG = 0x06
} algorithm_type_dist_t;
#endif /* SECURITY_TYPES_H_ */
+8 -13
View File
@@ -53,8 +53,6 @@ Description Defines the layer 3 messages supported by the NAS sublayer
#include "secu_defs.h"
#include "emmData.h"
//#define DEBUG_NAS_MESSAGE
/****************************************************************************/
/**************** E X T E R N A L D E F I N I T I O N S ****************/
/****************************************************************************/
@@ -1019,7 +1017,8 @@ static int _nas_message_decrypt(
stream_cipher.message = (unsigned char *)src;
/* length in bits */
stream_cipher.blength = length << 3;
nas_stream_encrypt_eea1(&stream_cipher, (unsigned char *)dest);
stream_compute_encrypt(EEA1_128_ALG_ID, &stream_cipher, (unsigned char *)dest);
/* Decode the first octet (security header type or EPS bearer identity,
* and protocol discriminator) */
DECODE_U8(dest, *(uint8_t*)(&header), size);
@@ -1054,7 +1053,8 @@ static int _nas_message_decrypt(
stream_cipher.message = (unsigned char *)src;
/* length in bits */
stream_cipher.blength = length << 3;
nas_stream_encrypt_eea1(&stream_cipher, (unsigned char *)dest);
stream_compute_encrypt(EEA1_128_ALG_ID, &stream_cipher, (unsigned char *)dest);
/* Decode the first octet (security header type or EPS bearer identity,
* and protocol discriminator) */
DECODE_U8(dest, *(uint8_t*)(&header), size);
@@ -1186,8 +1186,7 @@ static int _nas_message_encrypt(
stream_cipher.message = (unsigned char *)src;
/* length in bits */
stream_cipher.blength = length << 3;
nas_stream_encrypt_eea1(&stream_cipher, (unsigned char *)dest);
stream_compute_encrypt(EEA1_128_ALG_ID, &stream_cipher, (unsigned char *)dest);
LOG_FUNC_RETURN (length);
}
@@ -1217,7 +1216,7 @@ static int _nas_message_encrypt(
stream_cipher.message = (unsigned char *)src;
/* length in bits */
stream_cipher.blength = length << 3;
nas_stream_encrypt_eea2(&stream_cipher, (unsigned char *)dest);
stream_compute_encrypt(EEA2_128_ALG_ID, &stream_cipher, (unsigned char *)dest);
LOG_FUNC_RETURN (length);
@@ -1356,10 +1355,8 @@ static uint32_t _nas_message_get_mac(
stream_cipher.message = (unsigned char *)buffer;
/* length in bits */
stream_cipher.blength = length << 3;
stream_compute_integrity(EIA1_128_ALG_ID, &stream_cipher, mac);
nas_stream_encrypt_eia1(
&stream_cipher,
mac);
LOG_TRACE(DEBUG,
"NAS_SECURITY_ALGORITHMS_EIA1 returned MAC %x.%x.%x.%x(%u) for length %d direction %d, count %d",
mac[0], mac[1], mac[2],mac[3],
@@ -1402,10 +1399,8 @@ static uint32_t _nas_message_get_mac(
stream_cipher.message = (unsigned char *)buffer;
/* length in bits */
stream_cipher.blength = length << 3;
stream_compute_integrity(EIA2_128_ALG_ID, &stream_cipher, mac);
nas_stream_encrypt_eia2(
&stream_cipher,
mac);
LOG_TRACE(DEBUG,
"NAS_SECURITY_ALGORITHMS_EIA2 returned MAC %x.%x.%x.%x(%u) for length %d direction %d, count %d",
mac[0], mac[1], mac[2],mac[3],
+61 -36
View File
@@ -29,10 +29,11 @@
#ifndef MILENAGE_H
#define MILENAGE_H
#include <openssl/aes.h>
#include "openair3/SECU/aes_128_ecb.h"
#define u8 uint8_t
/**
milenage_f1 - Milenage f1 and f1* algorithms
@opc: OPc = 128-bit value derived from OP and K
@@ -45,16 +46,29 @@
Returns: true on success, false on failure
*/
void aes_128_encrypt_block(const u8* key, const u8* in, u8* out) {
AES_KEY k;
u8 tmp[16];
AES_set_encrypt_key(key, 128, &k);
AES_encrypt(in, tmp, &k);
void aes_128_encrypt_block(const uint8_t *key, const uint8_t *in, uint8_t *out)
{
abort();
assert(0 != 0 && "Here we are!");
// Precondition: key, in and out occupy 16 bytes
aes_128_t k_iv = {.type = NONE_INITIALIZATION_VECTOR};
memcpy(k_iv.key, key, sizeof(k_iv.key));
byte_array_t msg = {.buf = (uint8_t *)in, .len = 16};
uint8_t tmp[16] = {0};
aes_128_ecb(&k_iv, msg, sizeof(tmp), tmp);
memcpy(out, tmp, sizeof(tmp));
}
static bool milenage_f1(const u8 *opc, const u8 *k, const u8 *_rand,
const u8 *sqn, const u8 *amf, u8 *mac_a, u8 *mac_s) {
u8 tmp1[16], tmp2[16], tmp3[16];
static bool milenage_f1(const uint8_t *opc,
const uint8_t *k,
const uint8_t *_rand,
const uint8_t *sqn,
const uint8_t *amf,
uint8_t *mac_a,
uint8_t *mac_s)
{
uint8_t tmp1[16], tmp2[16], tmp3[16];
int i;
/* tmp1 = TEMP = E_K(RAND XOR OP_C) */
@@ -62,10 +76,10 @@ static bool milenage_f1(const u8 *opc, const u8 *k, const u8 *_rand,
tmp1[i] = _rand[i] ^ opc[i];
aes_128_encrypt_block(k, tmp1, tmp1);
AES_KEY kTab;
uint8_t cyphered[16];
AES_set_encrypt_key(k, 128, &kTab);
AES_encrypt(tmp1, cyphered, &kTab);
uint8_t cyphered[16] = {0};
aes_128_encrypt_block(k, tmp1, cyphered);
/* tmp2 = IN1 = SQN || AMF || SQN || AMF */
memcpy(tmp2, sqn, 6);
memcpy(tmp2 + 6, amf, 2);
@@ -97,7 +111,6 @@ static bool milenage_f1(const u8 *opc, const u8 *k, const u8 *_rand,
return true;
}
/**
milenage_f2345 - Milenage f2, f3, f4, f5, f5* algorithms
@opc: OPc = 128-bit value derived from OP and K
@@ -110,9 +123,16 @@ static bool milenage_f1(const u8 *opc, const u8 *k, const u8 *_rand,
@akstar: Buffer for AK = 48-bit anonymity key (f5*), or %NULL
Returns: true on success, false on failure
*/
static bool milenage_f2345(const u8 *opc, const u8 *k, const u8 *_rand,
u8 *res, u8 *ck, u8 *ik, u8 *ak, u8 *akstar) {
u8 tmp1[16], tmp2[16], tmp3[16];
static bool milenage_f2345(const uint8_t *opc,
const uint8_t *k,
const uint8_t *_rand,
uint8_t *res,
uint8_t *ck,
uint8_t *ik,
uint8_t *ak,
uint8_t *akstar)
{
uint8_t tmp1[16], tmp2[16], tmp3[16];
int i;
/* tmp2 = TEMP = E_K(RAND XOR OP_C) */
@@ -186,7 +206,6 @@ static bool milenage_f2345(const u8 *opc, const u8 *k, const u8 *_rand,
return true;
}
/**
milenage_generate - Generate AKA AUTN,IK,CK,RES
@opc: OPc = 128-bit operator variant algorithm configuration field (encr.)
@@ -200,11 +219,18 @@ static bool milenage_f2345(const u8 *opc, const u8 *k, const u8 *_rand,
@res: Buffer for RES = 64-bit signed response (f2), or %NULL
@res_len: Max length for res; set to used length or 0 on failure
*/
static bool milenage_generate(const u8 *opc, const u8 *amf, const u8 *k,
const u8 *sqn, const u8 *_rand, u8 *autn, u8 *ik,
u8 *ck, u8 *res) {
static bool milenage_generate(const uint8_t *opc,
const uint8_t *amf,
const uint8_t *k,
const uint8_t *sqn,
const uint8_t *_rand,
uint8_t *autn,
uint8_t *ik,
uint8_t *ck,
uint8_t *res)
{
int i;
u8 mac_a[8], ak[6];
uint8_t mac_a[8], ak[6];
if (!milenage_f1(opc, k, _rand, sqn, amf, mac_a, NULL) ||
!milenage_f2345(opc, k, _rand, res, ck, ik, ak, NULL))
@@ -219,7 +245,6 @@ static bool milenage_generate(const u8 *opc, const u8 *amf, const u8 *k,
return true;
}
/**
milenage_auts - Milenage AUTS validation
@opc: OPc = 128-bit operator variant algorithm configuration field (encr.)
@@ -232,10 +257,10 @@ static bool milenage_generate(const u8 *opc, const u8 *amf, const u8 *k,
#define p(a) printf("%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx\n", (int)((a)[0]), (int)((a)[1]), (int)((a)[2]), (int)((a)[3]),(int)((a)[4]), (int)((a)[5]));
// valid code but put in comment as it is not used right now
#if 0
static bool milenage_auts(const u8 *opc, const u8 *k, const u8 *_rand, const u8 *auts,
u8 *sqn) {
u8 amf[2] = { 0x00, 0x00 }; /* TS 33.102 v7.0.0, 6.3.3 */
u8 ak[6], mac_s[8];
static bool milenage_auts(const uint8_t *opc, const uint8_t *k, const uint8_t *_rand, const uint8_t *auts,
uint8_t *sqn) {
uint8_t amf[2] = { 0x00, 0x00 }; /* TS 33.102 v7.0.0, 6.3.3 */
uint8_t ak[6], mac_s[8];
int i;
if (!milenage_f2345(opc, k, _rand, NULL, NULL, NULL, NULL, ak))
@@ -262,8 +287,8 @@ static bool milenage_auts(const u8 *opc, const u8 *k, const u8 *_rand, const u8
@kc: Buffer for Kc = 64-bit Kc
Returns: 0 on success, -1 on failure
*/
static bool gsm_milenage(const u8 *opc, const u8 *k, const u8 *_rand, u8 *sres, u8 *kc) {
u8 res[8], ck[16], ik[16];
static bool gsm_milenage(const uint8_t *opc, const uint8_t *k, const uint8_t *_rand, uint8_t *sres, uint8_t *kc) {
uint8_t res[8], ck[16], ik[16];
int i;
if (milenage_f2345(opc, k, _rand, res, ck, ik, NULL, NULL))
@@ -298,12 +323,12 @@ static bool gsm_milenage(const u8 *opc, const u8 *k, const u8 *_rand, u8 *sres,
@auts: 112-bit buffer for AUTS
Returns: 0 on success, -1 on failure, or -2 on synchronization failure
*/
static int milenage_check(const u8 *opc, const u8 *k, const u8 *sqn, const u8 *_rand,
const u8 *autn, u8 *ik, u8 *ck, u8 *res, size_t *res_len,
u8 *auts) {
static int milenage_check(const uint8_t *opc, const uint8_t *k, const uint8_t *sqn, const uint8_t *_rand,
const uint8_t *autn, uint8_t *ik, uint8_t *ck, uint8_t *res, size_t *res_len,
uint8_t *auts) {
int i;
u8 mac_a[8], ak[6], rx_sqn[6];
const u8 *amf;
uint8_t mac_a[8], ak[6], rx_sqn[6];
const uint8_t *amf;
if (milenage_f2345(opc, k, _rand, res, ck, ik, ak, NULL))
return -1;
@@ -315,7 +340,7 @@ static int milenage_check(const u8 *opc, const u8 *k, const u8 *sqn, const u8 *_
rx_sqn[i] = autn[i] ^ ak[i];
if (memcmp(rx_sqn, sqn, 6) <= 0) {
u8 auts_amf[2] = { 0x00, 0x00 }; /* TS 33.102 v7.0.0, 6.3.3 */
uint8_t auts_amf[2] = { 0x00, 0x00 }; /* TS 33.102 v7.0.0, 6.3.3 */
if (milenage_f2345(opc, k, _rand, NULL, NULL, NULL, NULL, ak))
return -1;
@@ -342,7 +367,7 @@ static int milenage_check(const u8 *opc, const u8 *k, const u8 *sqn, const u8 *_
return 0;
}
static void milenage_opc_gen(const u8 *k, const u8 *op, u8 *opc) {
static void milenage_opc_gen(const uint8_t *k, const uint8_t *op, uint8_t *opc) {
int i;
/* Encrypt OP using K */
aes_128_encrypt_block(k, op, opc);
+10 -9
View File
@@ -40,6 +40,7 @@
#include "aka_functions.h"
#include "secu_defs.h"
#include "kdf.h"
#include "key_nas_deriver.h"
#include "PduSessionEstablishRequest.h"
#include "PduSessionEstablishmentAccept.h"
#include "RegistrationAccept.h"
@@ -50,6 +51,7 @@
#include <openair1/PHY/phy_extern_nr_ue.h>
#include <openair1/SIMULATION/ETH_TRANSPORT/proto.h>
#include "openair2/SDAP/nr_sdap/nr_sdap.h"
#include "openair3/SECU/nas_stream_eia2.h"
uint8_t *registration_request_buf;
uint32_t registration_request_len;
@@ -597,9 +599,7 @@ static void generateSecurityModeComplete(nr_ue_nas_t *nas, as_nas_info_t *initia
stream_cipher.blength = (initialNasMsg->length - 6) << 3;
// only for Type of integrity protection algorithm: 128-5G-IA2 (2)
nas_stream_encrypt_eia2(
&stream_cipher,
mac);
stream_compute_integrity(EIA2_128_ALG_ID, &stream_cipher, mac);
printf("mac %x %x %x %x \n", mac[0], mac[1], mac[2], mac[3]);
for(int i = 0; i < 4; i++){
@@ -702,9 +702,7 @@ static void generateRegistrationComplete(nr_ue_nas_t *nas, as_nas_info_t *initia
stream_cipher.blength = (initialNasMsg->length - 6) << 3;
// only for Type of integrity protection algorithm: 128-5G-IA2 (2)
nas_stream_encrypt_eia2(
&stream_cipher,
mac);
stream_compute_integrity(EIA2_128_ALG_ID, &stream_cipher, mac);
printf("mac %x %x %x %x \n", mac[0], mac[1], mac[2], mac[3]);
for(int i = 0; i < 4; i++){
@@ -861,9 +859,7 @@ static void generatePduSessionEstablishRequest(nr_ue_nas_t *nas, as_nas_info_t *
stream_cipher.blength = (initialNasMsg->length - 6) << 3;
// only for Type of integrity protection algorithm: 128-5G-IA2 (2)
nas_stream_encrypt_eia2(
&stream_cipher,
mac);
stream_compute_integrity(EIA2_128_ALG_ID, &stream_cipher, mac);
printf("mac %x %x %x %x \n", mac[0], mac[1], mac[2], mac[3]);
for(int i = 0; i < 4; i++){
@@ -1003,6 +999,11 @@ void *nas_nrue_task(void *args_p)
case NAS_CONN_RELEASE_IND:
LOG_I(NAS, "[UE %ld] Received %s: cause %u\n", instance, ITTI_MSG_NAME (msg_p),
NAS_CONN_RELEASE_IND (msg_p).cause);
/* the following is not clean, but probably necessary: we need to give
* time to RLC to Ack the SRB1 PDU which contained the RRC release
* message. Hence, we just below wait some time, before finally
* unblocking the nr-uesoftmodem, which will terminate the process. */
usleep(100000);
itti_wait_tasks_unblock(); /* will unblock ITTI to stop nr-uesoftmodem */
break;
@@ -138,6 +138,11 @@ int ngap_ue_context_release_req(instance_t instance,
/* The context for this gNB ue ngap id doesn't exist in the map of gNB UEs */
NGAP_WARN("Failed to find ue context associated with gNB ue ngap id: %u\n",
ue_release_req_p->gNB_ue_ngap_id);
/* send response to free the UE: we don't know it, but it should be
* released since RRC seems to know it (e.g., there is no AMF) */
MessageDef *msg = itti_alloc_new_message(TASK_NGAP, 0, NGAP_UE_CONTEXT_RELEASE_COMMAND);
NGAP_UE_CONTEXT_RELEASE_COMMAND(msg).gNB_ue_ngap_id = ue_release_req_p->gNB_ue_ngap_id;
itti_send_msg_to_task(TASK_RRC_GNB, ngap_gNB_instance_p->instance, msg);
return -1;
}
+1 -1
View File
@@ -78,7 +78,7 @@ static int ngap_gNB_decode_initiating_message(NGAP_NGAP_PDU_t *pdu) {
case NGAP_ProcedureCode_id_PDUSessionResourceRelease:
res = asn_encode_to_new_buffer(NULL, ATS_CANONICAL_XER, &asn_DEF_NGAP_NGAP_PDU, pdu);
free(res.buffer);
NGAP_INFO("TODO PDUSESSIONRelease initiating message\n");
NGAP_INFO("PDUSESSIONRelease initiating message\n");
break;
case NGAP_ProcedureCode_id_ErrorIndication:
+2 -1
View File
@@ -62,9 +62,10 @@ typedef struct{
};
} iv8_t;
typedef enum{
typedef enum {
AES_INITIALIZATION_VECTOR_8,
AES_INITIALIZATION_VECTOR_16,
NONE_INITIALIZATION_VECTOR,
AES_INITIALIZATION_VECTOR_END,
} iv_e;
+53
View File
@@ -0,0 +1,53 @@
/*
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenAirInterface Software Alliance licenses this file to You under
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
* except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.openairinterface.org/?page_id=698
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*-------------------------------------------------------------------------------
* For more information about the OpenAirInterface (OAI) Software Alliance:
* contact@openairinterface.org
*/
#include "aes_128_ecb.h"
#include "common/utils/assertions.h"
#include <openssl/aes.h>
#include <openssl/err.h>
#include <openssl/evp.h>
void aes_128_ecb(const aes_128_t* k_iv, byte_array_t msg, size_t len_out, uint8_t out[len_out])
{
DevAssert(k_iv != NULL);
DevAssert(k_iv->type == NONE_INITIALIZATION_VECTOR);
// Create and initialise the context
EVP_CIPHER_CTX* ctx = EVP_CIPHER_CTX_new();
DevAssert(ctx != NULL);
// Initialise the encryption operation.
int rc = EVP_EncryptInit_ex(ctx, EVP_aes_128_ecb(), NULL, k_iv->key, NULL);
DevAssert(rc == 1);
int len_ev = 0;
rc = EVP_EncryptUpdate(ctx, out, &len_ev, msg.buf, msg.len);
DevAssert(!(len_ev > len_out) && "Buffer overflow");
// Finalise the encryption. Normally ciphertext bytes may be written at
// this stage, but this does not occur in GCM mode
rc = EVP_EncryptFinal_ex(ctx, out + len_ev, &len_ev);
DevAssert(rc == 1);
// Get the tag
// rc == EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_GET_TAG, 16, tag))
EVP_CIPHER_CTX_free(ctx);
}
+30
View File
@@ -0,0 +1,30 @@
/*
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenAirInterface Software Alliance licenses this file to You under
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
* except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.openairinterface.org/?page_id=698
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*-------------------------------------------------------------------------------
* For more information about the OpenAirInterface (OAI) Software Alliance:
* contact@openairinterface.org
*/
#ifndef AES_128_ECB_OAI_H
#define AES_128_ECB_OAI_H
#include "aes_128.h"
#include "common/utils/ds/byte_array.h"
void aes_128_ecb(const aes_128_t* k_iv, byte_array_t msg, size_t len_out, uint8_t out[len_out]);
#endif
+202 -40
View File
@@ -19,16 +19,84 @@
* contact@openairinterface.org
*/
#include "aes_128.h"
#include "aes_128_cbc_cmac.h"
#include "common/utils/assertions.h"
#include "common/utils/LOG/log.h"
#include "kdf.h"
#include "key_nas_deriver.h"
#include "nas_stream_eea1.h"
#include "nas_stream_eea2.h"
#include "nas_stream_eia1.h"
#include "nas_stream_eia2.h"
#include "secu_defs.h"
#include "snow3g.h"
#include <arpa/inet.h>
#include <math.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include "security_types.h"
#include "secu_defs.h"
#include "kdf.h"
#define FC_KENB (0x11)
#define FC_NH (0x12)
#define FC_KENB_STAR (0x13)
/* 33401 #A.7 Algorithm for key derivation function.
* This FC should be used for:
* - NAS Encryption algorithm
* - NAS Integrity algorithm
* - RRC Encryption algorithm
* - RRC Integrity algorithm
* - User Plane Encryption algorithm
*/
#define FC_ALG_KEY_DER (0x15)
#define FC_KASME_TO_CK (0x16)
#define NR_FC_ALG_KEY_DER (0x69)
#define NR_FC_ALG_KEY_NG_RAN_STAR_DER (0x70)
// #define SECU_DEBUG 1
static void derive_key_common(algorithm_type_dist_t alg_type, uint8_t alg_id, const uint8_t kasme[32], uint8_t FC, uint8_t out[32])
{
uint8_t s[7];
#if defined(SECU_DEBUG)
int i;
#endif
/* FC */
s[0] = FC;
/* P0 = algorithm type distinguisher */
s[1] = (uint8_t)(alg_type & 0xFF);
/* L0 = length(P0) = 1 */
s[2] = 0x00;
s[3] = 0x01;
/* P1 */
s[4] = alg_id;
/* L1 = length(P1) = 1 */
s[5] = 0x00;
s[6] = 0x01;
#if defined(SECU_DEBUG)
printf("%s FC %d nas_alg_type distinguisher %d nas_enc_alg_identity %d\n", __FUNCTION__, FC_ALG_KEY_DER, alg_type, alg_id);
for (i = 0; i < 7; i ++) {
printf("0x%02x ", s[i]);
}
printf("\n");
#endif
byte_array_t data = {.len = 7, .buf = s};
kdf(kasme, data, 32, out);
}
#define SECU_DEBUG 1
/*!
* @brief Derive the kNASenc from kasme and perform truncate on the generated key to
* reduce his size to 128 bits. Definition of the derivation function can
@@ -41,50 +109,144 @@
* - 2 for 128-EIA2 AES
* @param[in] kasme Key for MME as provided by AUC
* @param[out] knas Pointer to reference where output of KDF will be stored.
*/
void derive_key_nas(algorithm_type_dist_t alg_type, uint8_t alg_id, const uint8_t kasme[32], uint8_t knas[32])
{
derive_key_common(alg_type, alg_id, kasme, FC_ALG_KEY_DER, knas);
}
void nr_derive_key(algorithm_type_dist_t alg_type, uint8_t alg_id, const uint8_t key[32], uint8_t out[16])
{
uint8_t tmp[32] = {0};
derive_key_common(alg_type, alg_id, key, NR_FC_ALG_KEY_DER, tmp);
// Only the last 16 bytes are needed in 5G
memcpy(out, &tmp[16], 16);
}
/*!
* @brief Derive the keys from key and perform truncate on the generated key to
* reduce his size to 128 bits. Definition of the derivation function can
* be found in 3GPP TS.33401 #A.7
* @param[in] alg_type Algorithm distinguisher
* @param[in] alg_id Algorithm identifier.
* Possible values are:
* - 0 for EIA0 algorithm (Null Integrity Protection algorithm)
* - 1 for 128-EIA1 SNOW 3G
* - 2 for 128-EIA2 AES
* @param[in] key The top key used to derive other subkeys
* @param[out] out Pointer to reference where output of KDF will be stored.
* NOTE: knas is dynamically allocated by the KDF function
*/
int derive_key_nas(algorithm_type_dist_t nas_alg_type, uint8_t nas_enc_alg_id,
const uint8_t kasme[32], uint8_t *knas)
#ifndef NAS_UE
void derive_keNB(const uint8_t kasme[32], const uint32_t nas_count, uint8_t *keNB)
{
uint8_t s[7];
uint8_t out[32];
#if defined(SECU_DEBUG)
int i;
uint8_t s[7] = {0};
// FC
s[0] = FC_KENB;
// P0 = Uplink NAS count
s[1] = (nas_count & 0xff000000) >> 24;
s[2] = (nas_count & 0x00ff0000) >> 16;
s[3] = (nas_count & 0x0000ff00) >> 8;
s[4] = (nas_count & 0x000000ff);
// Length of NAS count
s[5] = 0x00;
s[6] = 0x04;
byte_array_t data = {.buf = s, .len = 7};
kdf(kasme, data, 32, keNB);
}
#endif
/* FC */
s[0] = FC_ALG_KEY_DER;
/* P0 = algorithm type distinguisher */
s[1] = (uint8_t)(nas_alg_type & 0xFF);
/* L0 = length(P0) = 1 */
s[2] = 0x00;
s[3] = 0x01;
/* P1 */
s[4] = nas_enc_alg_id;
/* L1 = length(P1) = 1 */
s[5] = 0x00;
s[6] = 0x01;
#if defined(SECU_DEBUG)
printf("%s FC %d nas_alg_type distinguisher %d nas_enc_alg_identity %d\n",
__FUNCTION__, FC_ALG_KEY_DER, nas_alg_type, nas_enc_alg_id);
for (i = 0; i < 7; i ++) {
printf("0x%02x ", s[i]);
void derive_keNB_star(const uint8_t *kenb_32,
const uint16_t pci,
const uint32_t earfcn_dl,
const bool is_rel8_only,
uint8_t *kenb_star)
{
// see 33.401 section A.5 KeNB* derivation function
uint8_t s[10] = {0};
byte_array_t data = {.buf = s};
// FC = 0x13
s[0] = FC_KENB_STAR;
// P0 = PCI (target physical cell id)
s[1] = (pci & 0x0000ff00) >> 8;
s[2] = (pci & 0x000000ff);
// L0 = length of PCI (i.e. 0x00 0x02)
s[3] = 0x00;
s[4] = 0x02;
// P1 = EARFCN-DL (target physical cell downlink frequency)
if (is_rel8_only) {
s[5] = (earfcn_dl & 0x0000ff00) >> 8;
s[6] = (earfcn_dl & 0x000000ff);
s[7] = 0x00;
s[8] = 0x02;
data.len = 9;
} else {
s[5] = (earfcn_dl & 0x00ff0000) >> 16;
s[6] = (earfcn_dl & 0x0000ff00) >> 8;
s[7] = (earfcn_dl & 0x000000ff);
s[8] = 0x00;
s[9] = 0x03;
data.len = 10;
}
printf("\n");
#endif
kdf(kenb_32, data, 32, kenb_star);
//kdf(kasme, 32, s, 7, out, 32);
byte_array_t data = {.len = 7, .buf = s};
kdf(kasme, data, 32, out);
// L1 length of EARFCN-DL (i.e. L1 = 0x00 0x02 if EARFCN-DL is between 0 and 65535, and L1 = 0x00 0x03 if EARFCN-DL is between
// 65536 and 262143) NOTE: The length of EARFCN-DL cannot be generally set to 3 bytes for backward compatibility reasons: A Rel-8
// entity (UE or eNB) would always assume an input parameter length of 2 bytes for the EARFCN-DL. This
// would lead to different derived keys if another entity assumed an input parameter length of 3 bytes for the
// EARFCN-DL.
}
memcpy(knas, &out[31-16+1], 16);
void nr_derive_key_ng_ran_star(uint16_t pci, uint64_t nr_arfcn_dl, const uint8_t key[32], uint8_t *key_ng_ran_star)
{
uint8_t s[10] = {0};
return 0;
/* FC */
s[0] = NR_FC_ALG_KEY_NG_RAN_STAR_DER;
/* P0 = PCI */
s[1] = (pci & 0x0000ff00) >> 8;
s[2] = (pci & 0x000000ff);
/* L0 = length(P0) = 2 */
s[3] = 0x00;
s[4] = 0x02;
/* P1 = NR ARFCN */
s[5] = (nr_arfcn_dl & 0x00ff0000) >> 16;
s[6] = (nr_arfcn_dl & 0x0000ff00) >> 8;
s[7] = (nr_arfcn_dl & 0x000000ff);
/* L1 = length(P1) = 3 */
s[8] = 0x00;
s[9] = 0x03;
byte_array_t data = {.buf = s, .len = 10};
const uint32_t len_key = 32;
kdf(key, data, len_key, key_ng_ran_star);
}
void derive_skgNB(const uint8_t *keNB, const uint16_t sk_counter, uint8_t *skgNB)
{
uint8_t s[5] = {0};
/* FC is 0x1c (see 3gpp 33.401 annex A.15) */
s[0] = 0x1c;
/* put sk_counter */
s[1] = (sk_counter >> 8) & 0xff;
s[2] = sk_counter & 0xff;
/* put length of sk_counter (2) */
s[3] = 0x00;
s[4] = 0x02;
byte_array_t data = {.buf = s, .len = 5};
kdf(keNB, data, 32, skgNB);
}
+33
View File
@@ -0,0 +1,33 @@
#ifndef KEY_NAS_DERIVER_H
#define KEY_NAS_DERIVER_H
#include <stdbool.h>
#include <stdlib.h>
#include <stdint.h>
typedef enum {
NAS_ENC_ALG = 0x01,
NAS_INT_ALG = 0x02,
RRC_ENC_ALG = 0x03,
RRC_INT_ALG = 0x04,
UP_ENC_ALG = 0x05,
UP_INT_ALG = 0x06
} algorithm_type_dist_t;
void derive_keNB(const uint8_t kasme[32], const uint32_t nas_count, uint8_t *keNB);
void derive_keNB_star(const uint8_t *kenb_32,
const uint16_t pci,
const uint32_t earfcn_dl,
const bool is_rel8_only,
uint8_t *kenb_star);
void derive_key_nas(algorithm_type_dist_t nas_alg_type, uint8_t nas_enc_alg_id, const uint8_t kasme[32], uint8_t knas[32]);
void derive_skgNB(const uint8_t *keNB, const uint16_t sk_counter, uint8_t *skgNB);
void nr_derive_key(algorithm_type_dist_t alg_type, uint8_t alg_id, const uint8_t key[32], uint8_t out[16]);
void nr_derive_key_ng_ran_star(uint16_t pci, uint64_t nr_arfcn_dl, const uint8_t key[32], uint8_t *key_ng_ran_star);
#endif
+44
View File
@@ -0,0 +1,44 @@
/*
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenAirInterface Software Alliance licenses this file to You under
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
* except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.openairinterface.org/?page_id=698
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*-------------------------------------------------------------------------------
* For more information about the OpenAirInterface (OAI) Software Alliance:
* contact@openairinterface.org
*/
#include "nas_stream_eea0.h"
#include "common/utils/assertions.h"
#include "common/utils/LOG/log.h"
#include <string.h>
void nas_stream_encrypt_eea0(nas_stream_cipher_t const *stream_cipher, uint8_t *out)
{
DevAssert(stream_cipher != NULL);
DevAssert(out != NULL);
LOG_D(OSA,
"Entering stream_encrypt_eea0, bits length %u, bearer %u, "
"count %u, direction %s\n",
stream_cipher->blength,
stream_cipher->bearer,
stream_cipher->count,
stream_cipher->direction == SECU_DIRECTION_DOWNLINK ? "Downlink" : "Uplink");
uint32_t byte_length = (stream_cipher->blength + 7) >> 3;
memcpy(out, stream_cipher->message, byte_length);
}
@@ -19,32 +19,14 @@
* contact@openairinterface.org
*/
#ifndef OSA_INTERNAL_H_
#define OSA_INTERNAL_H_
#ifndef OAI_NAS_STREAM_EEA0_H
#define OAI_NAS_STREAM_EEA0_H
#define FC_KENB (0x11)
#define FC_NH (0x12)
#define FC_KENB_STAR (0x13)
/* 33401 #A.7 Algorithm for key derivation function.
* This FC should be used for:
* - NAS Encryption algorithm
* - NAS Integrity algorithm
* - RRC Encryption algorithm
* - RRC Integrity algorithm
* - User Plane Encryption algorithm
*/
#define FC_ALG_KEY_DER (0x15)
#define FC_KASME_TO_CK (0x16)
#include "secu_defs.h"
#define NR_FC_ALG_KEY_DER (0x69)
#define NR_FC_ALG_KEY_NG_RAN_STAR_DER (0x70)
#include <stdlib.h>
#include <stdint.h>
void nas_stream_encrypt_eea0(nas_stream_cipher_t const *stream_cipher, uint8_t *out);
#ifndef hton_int32
# define hton_int32(x) \
(((x & 0x000000FF) << 24) | ((x & 0x0000FF00) << 8) | \
((x & 0x00FF0000) >> 8) | ((x & 0xFF000000) >> 24))
#endif
// #define SECU_DEBUG
#endif /* OSA_INTERNAL_H_ */
+2 -7
View File
@@ -26,13 +26,10 @@
#include "assertions.h"
#include "conversions.h"
#include "secu_defs.h"
#include "nas_stream_eea1.h"
#include "snow3g.h"
// #define SECU_DEBUG
int nas_stream_encrypt_eea1(nas_stream_cipher_t *stream_cipher, uint8_t *out)
void nas_stream_encrypt_eea1(nas_stream_cipher_t const *stream_cipher, uint8_t *out)
{
snow_3g_context_t snow_3g_context;
int n ;
@@ -106,6 +103,4 @@ int nas_stream_encrypt_eea1(nas_stream_cipher_t *stream_cipher, uint8_t *out)
if (zero_bit > 0) {
out[ceil_index - 1] = stream_cipher->message[ceil_index - 1];
}
return 0;
}
+32
View File
@@ -0,0 +1,32 @@
/*
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenAirInterface Software Alliance licenses this file to You under
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
* except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.openairinterface.org/?page_id=698
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*-------------------------------------------------------------------------------
* For more information about the OpenAirInterface (OAI) Software Alliance:
* contact@openairinterface.org
*/
#ifndef OAI_NAS_STREAM_EEA1_H
#define OAI_NAS_STREAM_EEA1_H
#include "secu_defs.h"
#include <stdlib.h>
#include <stdint.h>
void nas_stream_encrypt_eea1(nas_stream_cipher_t const *stream_cipher, uint8_t *out);
#endif

Some files were not shown because too many files have changed in this diff Show More