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:
+18
-27
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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}'
|
||||
|
||||
@@ -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
@@ -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>
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
@@ -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
@@ -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
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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 |
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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) {}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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) {}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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__*/
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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
@@ -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
@@ -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,
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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"
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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
@@ -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=>PV1U_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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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
@@ -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,
|
||||
|
||||
@@ -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.
|
||||
@@ -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__ */
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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 */
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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_ */
|
||||
|
||||
|
||||
@@ -23,8 +23,6 @@
|
||||
|
||||
#include "commonDef.h"
|
||||
|
||||
#include "security_types.h"
|
||||
|
||||
#include "queue.h"
|
||||
|
||||
#ifndef COMMON_TYPES_H_
|
||||
|
||||
@@ -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_ */
|
||||
|
||||
@@ -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],
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
@@ -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_ */
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
Reference in New Issue
Block a user