diff --git a/CMakeLists.txt b/CMakeLists.txt index 60f1f12e94..b584e49207 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -280,7 +280,7 @@ if (SANITIZE_UNDEFINED) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=undefined -fno-sanitize-recover=all") endif () -add_definitions("-DASN_DISABLE_OER_SUPPORT") +add_definitions("-DASN_DISABLE_OER_SUPPORT -DHAVE_CONFIG_H -DHAVE_CONFIG_H_") ######################### set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -ggdb2 -Wl,-rpath -Wl,${CMAKE_CURRENT_BINARY_DIR}") @@ -336,23 +336,19 @@ add_definitions("-DPACKAGE_BUGREPORT=\"openair4g-devel@lists.eurecom.fr\"") # Debug related options ######################################### -add_boolean_option(DEBUG_ASN1C False "ASN1 coder/decoder Debug traces, see common/utils/config.h, the logs are regular OAI logs, in the log group 'ASN'") -add_boolean_option(DISABLE_XER_PRINT False "print XER Format") -add_boolean_option(XER_PRINT False "print XER Format") -add_boolean_option(DEBUG_PDCP_PAYLOAD False "print PDCP PDU to stdout") # if true, make sure that global and PDCP log levels are trace +add_boolean_option(DEBUG_ASN1 False "ASN1 coder/decoder Debug") add_boolean_option(DEBUG_MAC_INTERFACE False "print MAC-RLC PDU exchange to stdout") # if true, make sure that global and PDCP log levels are trace -add_boolean_option(PRINT_STATS False "This adds the possibility to see the status") add_boolean_option(T_TRACER True "Activate the T tracer, a debugging/monitoring framework" ) add_boolean_option(UE_AUTOTEST_TRACE False "Activate UE autotest specific logs") add_boolean_option(UE_DEBUG_TRACE False "Activate UE debug trace") add_boolean_option(UE_TIMING_TRACE False "Activate UE timing trace") -add_boolean_option(DEBUG_CONSOLE False "disables stdout/stderr buffering") set (OCP_ITTI ${OPENAIR_DIR}/common/utils/ocp_itti) add_library(ITTI ${OCP_ITTI}/intertask_interface.cpp ${OPENAIR_DIR}/common/utils/backtrace.c ) + target_link_libraries(ITTI PRIVATE asn1_nr_rrc asn1_lte_rrc) # asn1c skeletons have hardcoded this flag to make customized debug logs @@ -819,7 +815,6 @@ include_directories("${OPENAIR2_DIR}/UTIL/OTG") include_directories("${OPENAIR2_DIR}/UTIL/CLI") include_directories("${OPENAIR2_DIR}/UTIL/OPT") include_directories("${OPENAIR2_DIR}/UTIL/OMV") -include_directories("${OPENAIR2_DIR}/RRC/LTE/MESSAGES") include_directories("${OPENAIR_DIR}") ########### @@ -1594,6 +1589,7 @@ set (ENB_APP_SRC set (GNB_APP_SRC ${OPENAIR2_DIR}/GNB_APP/gnb_app.c + ${OPENAIR2_DIR}/E1AP/e1ap_setup.c ${OPENAIR2_DIR}/GNB_APP/gnb_config.c ) @@ -1639,7 +1635,20 @@ add_library(L2_NR ${GNB_APP_SRC} ) -target_link_libraries(L2_NR PRIVATE f1ap x2ap s1ap ngap nr_rrc) +add_library(e1_if + ${NR_RRC_DIR}/cucp_cuup_direct.c + ${NR_RRC_DIR}/cucp_cuup_e1ap.c + ) + +target_link_libraries(e1_if PRIVATE asn1_nr_rrc asn1_lte_rrc asn1_f1ap e1ap GTPV1U) + +add_library(e1_pdcp_if + ${OPENAIR2_DIR}/LAYER2/nr_pdcp/nr_pdcp_e1_api.c + ) + +target_link_libraries(e1_pdcp_if PRIVATE asn1_nr_rrc asn1_lte_rrc) + +target_link_libraries(L2_NR PRIVATE f1ap x2ap s1ap ngap nr_rrc e1ap) add_library(L2_LTE_NR ${L2_RRC_SRC} @@ -2373,7 +2382,7 @@ target_link_libraries(nr-softmodem PRIVATE 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 ITTI ${RAL_LIB} ${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 - x2ap f1ap m2ap m3ap + x2ap f1ap m2ap m3ap e1ap -Wl,--end-group z dl) target_link_libraries(nr-softmodem PRIVATE ${LIBXML2_LIBRARIES}) @@ -2390,8 +2399,27 @@ endif () # force the generation of ASN.1 so that we don't need to wait during the build target_link_libraries(nr-softmodem PRIVATE - asn1_lte_rrc asn1_nr_rrc asn1_s1ap asn1_ngap asn1_m2ap asn1_m3ap asn1_x2ap asn1_f1ap asn1_lpp) + asn1_lte_rrc asn1_nr_rrc asn1_s1ap asn1_ngap asn1_m2ap asn1_m3ap asn1_x2ap asn1_f1ap asn1_lpp) +add_executable(nr-cuup + executables/nr-cuup.c + executables/softmodem-common.c + ${OPENAIR1_DIR}/SIMULATION/ETH_TRANSPORT/netlink_init.c + ${OPENAIR2_DIR}/RRC/NAS/nas_config.c + ${NR_RRC_DIR}/rrc_gNB_UE_context.c + ${OPENAIR2_DIR}/E1AP/e1ap_setup.c + ${NR_PDCP_SRC} + ${NR_SDAP_SRC} + ${T_SOURCE} + ${SHLIB_LOADER_SOURCES} + ) + +target_link_libraries(nr-cuup PRIVATE + CONFIG_LIB ITTI SCTP_CLIENT + GTPV1U e1ap e1_pdcp_if f1ap + SECU_OSA ${OPENSSL_LIBRARIES} crypt z sctp dl pthread) +target_link_libraries(nr-cuup PRIVATE asn1_lte_rrc asn1_nr_rrc) + # nr-uesoftmodem is UE implementation ####################################### diff --git a/ci-scripts/cls_containerize.py b/ci-scripts/cls_containerize.py index e02d208945..324e718ba1 100644 --- a/ci-scripts/cls_containerize.py +++ b/ci-scripts/cls_containerize.py @@ -360,6 +360,7 @@ class Containerize(): if result is not None: imageNames.append(('oai-enb', 'eNB')) imageNames.append(('oai-gnb', 'gNB')) + imageNames.append(('oai-nr-cuup', 'nr-cuup')) imageNames.append(('oai-lte-ue', 'lteUE')) imageNames.append(('oai-nr-ue', 'nrUE')) if self.host == 'Red Hat': @@ -680,7 +681,7 @@ class Containerize(): orgTag = 'develop' if self.ranAllowMerge: orgTag = 'ci-temp' - imageNames = ['oai-enb', 'oai-gnb', 'oai-lte-ue', 'oai-nr-ue', 'oai-lte-ru'] + imageNames = ['oai-enb', 'oai-gnb', 'oai-lte-ue', 'oai-nr-ue', 'oai-lte-ru', 'oai-nr-cuup'] for image in imageNames: tagToUse = self.ImageTagToUse(image) mySSH.command(f'docker image tag {image}:{orgTag} {tagToUse}', '\$', 5) @@ -814,7 +815,7 @@ class Containerize(): else: logging.debug('Removing test images locally') - imageNames = ['oai-enb', 'oai-gnb', 'oai-lte-ue', 'oai-nr-ue', 'oai-lte-ru'] + imageNames = ['oai-enb', 'oai-gnb', 'oai-lte-ue', 'oai-nr-ue', 'oai-lte-ru', 'oai-nr-cuup'] for image in imageNames: cmd = f'docker rmi {self.ImageTagToUse(image)} || true' if lIpAddr != 'none': @@ -856,7 +857,7 @@ class Containerize(): mySSH.command('cd ' + lSourcePath + '/' + self.yamlPath[self.eNB_instance], '\$', 5) mySSH.command('cp docker-compose.yml ci-docker-compose.yml', '\$', 5) - imagesList = ['oai-enb', 'oai-gnb'] + imagesList = ['oai-enb', 'oai-gnb', 'oai-nr-cuup'] for image in imagesList: imageToUse = self.ImageTagToUse(image) mySSH.command(f'sed -i -e "s#image: {image}:latest#image: {imageToUse}#" ci-docker-compose.yml', '\$', 2) @@ -1066,7 +1067,7 @@ class Containerize(): cmd = 'cd ' + self.yamlPath[0] + ' && cp docker-compose.y*ml docker-compose-ci.yml' subprocess.run(cmd, shell=True) - imageNames = ['oai-enb', 'oai-gnb', 'oai-lte-ue', 'oai-nr-ue', 'oai-lte-ru'] + imageNames = ['oai-enb', 'oai-gnb', 'oai-lte-ue', 'oai-nr-ue', 'oai-lte-ru', 'oai-nr-cuup'] for image in imageNames: tagToUse = self.ImageTagToUse(image) cmd = f'cd {self.yamlPath[0]} && sed -i -e "s@{image}:develop@{tagToUse}@" docker-compose-ci.yml' @@ -1160,18 +1161,9 @@ class Containerize(): def CaptureOnDockerNetworks(self): cmd = 'cd ' + self.yamlPath[0] + ' && docker-compose -f docker-compose-ci.yml config | grep com.docker.network.bridge.name | sed -e "s@^.*name: @@"' networkNames = subprocess.check_output(cmd, shell=True, stderr=subprocess.STDOUT, universal_newlines=True, timeout=10) - if re.search('4g.*rfsimulator', self.yamlPath[0]) is not None: - # Excluding any traffic from LTE-UE container (192.168.61.30) - # From the trf-gen, keeping only PING traffic - cmd = 'sudo nohup tshark -f "(host 192.168.61.11 and icmp) or (not host 192.168.61.11 and not host 192.168.61.30 and not arp and not port 53 and not port 2152)"' - elif re.search('5g.*rfsimulator', self.yamlPath[0]) is not None: - # Excluding any traffic from NR-UE containers (192.168.71.150 and 192.168.71.151) - # From the ext-dn, keeping only PING traffic - cmd = 'sudo nohup tshark -f "(host 192.168.72.135 and icmp) or (not host 192.168.72.135 and not host 192.168.71.150 and not host 192.168.71.151 and not arp and not port 53 and not port 2152 and not port 2153)"' - elif re.search('5g_l2sim', self.yamlPath[0]) is not None: - cmd = 'sudo nohup tshark -f "(host 192.168.72.135 and icmp) or (not host 192.168.72.135 and not arp and not port 53 and not port 2152 and not port 2153)"' - else: - return + + # Allow only: control plane RAN (SCTP), HTTP of control in CN (port 80), PFCP traffic (port 8805), MySQL (port 3306) + cmd = 'sudo nohup tshark -f "sctp or port 80 or port 8805 or icmp or port 3306"' for name in networkNames.split('\n'): if re.search('rfsim', name) is not None or re.search('l2sim', name) is not None: cmd += ' -i ' + name @@ -1190,7 +1182,7 @@ class Containerize(): cmd = 'cd ' + self.yamlPath[0] + ' && cp docker-compose.y*ml docker-compose-ci.yml' logging.info(cmd) subprocess.run(cmd, shell=True) - imageNames = ['oai-enb', 'oai-gnb', 'oai-lte-ue', 'oai-nr-ue', 'oai-lte-ru'] + imageNames = ['oai-enb', 'oai-gnb', 'oai-lte-ue', 'oai-nr-ue', 'oai-lte-ru', 'oai-nr-cuup'] for image in imageNames: tagToUse = self.ImageTagToUse(image) cmd = f'cd {self.yamlPath[0]} && sed -i -e "s@{image}:develop@{tagToUse}@" docker-compose-ci.yml' diff --git a/ci-scripts/conf_files/gnb-cucp.sa.f1.conf b/ci-scripts/conf_files/gnb-cucp.sa.f1.conf new file mode 100644 index 0000000000..0a2f88495e --- /dev/null +++ b/ci-scripts/conf_files/gnb-cucp.sa.f1.conf @@ -0,0 +1,235 @@ +Active_gNBs = ( "gNB-OAI"); +# Asn1_verbosity, choice in: none, info, annoying +Asn1_verbosity = "none"; +Num_Threads_PUSCH = 8; +sa = 1; + +gNBs = +( + { + ////////// Identification parameters: + gNB_CU_ID = 0xe00; + +# cell_type = "CELL_MACRO_GNB"; + + gNB_name = "gNB-OAI"; + + // 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, sd = 0xffffff }) }); + + + nr_cellid = 12345678L; + force_256qam_off = 1; + + tr_s_preference = "f1"; + + local_s_if_name = "lo"; + local_s_address = "192.168.72.140"; + remote_s_address = "192.168.72.143"; + local_s_portc = 501; + local_s_portd = 2152; + remote_s_portc = 500; + remote_s_portd = 2152; + ssb_SubcarrierOffset = 0; + min_rxtxtime = 6; + + pdcch_ConfigSIB1 = ( + { + controlResourceSetZero = 12; + searchSpaceZero = 0; + } + ); + + servingCellConfigCommon = ( + { + #spCellConfigCommon + + physCellId = 0; + +# downlinkConfigCommon + #frequencyInfoDL + # this is 3600 MHz + 43 PRBs@30kHz SCS (same as initial BWP) + absoluteFrequencySSB = 641280; + dl_frequencyBand = 78; + # this is 3600 MHz + dl_absoluteFrequencyPointA = 640008; + #scs-SpecificCarrierList + dl_offstToCarrier = 0; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + dl_subcarrierSpacing = 1; + dl_carrierBandwidth = 106; + #initialDownlinkBWP + #genericParameters + # this is RBstart=27,L=48 (275*(L-1))+RBstart + initialDLBWPlocationAndBandwidth = 28875; # 6366 12925 12956 28875 12952 +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + initialDLBWPsubcarrierSpacing = 1; + #pdcch-ConfigCommon + initialDLBWPcontrolResourceSetZero = 11; + initialDLBWPsearchSpaceZero = 0; + + #uplinkConfigCommon + #frequencyInfoUL + ul_frequencyBand = 78; + #scs-SpecificCarrierList + ul_offstToCarrier = 0; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + ul_subcarrierSpacing = 1; + ul_carrierBandwidth = 106; + pMax = 20; + #initialUplinkBWP + #genericParameters + initialULBWPlocationAndBandwidth = 28875; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + initialULBWPsubcarrierSpacing = 1; + #rach-ConfigCommon + #rach-ConfigGeneric + prach_ConfigurationIndex = 98; +#prach_msg1_FDM +#0 = one, 1=two, 2=four, 3=eight + prach_msg1_FDM = 0; + prach_msg1_FrequencyStart = 0; + zeroCorrelationZoneConfig = 13; + preambleReceivedTargetPower = -96; +#preamblTransMax (0...10) = (3,4,5,6,7,8,10,20,50,100,200) + preambleTransMax = 6; +#powerRampingStep +# 0=dB0,1=dB2,2=dB4,3=dB6 + powerRampingStep = 1; +#ra_ReponseWindow +#1,2,4,8,10,20,40,80 + ra_ResponseWindow = 4; +#ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR +#1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen + ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4; +#oneHalf (0..15) 4,8,12,16,...60,64 + ssb_perRACH_OccasionAndCB_PreamblesPerSSB = 14; +#ra_ContentionResolutionTimer +#(0..7) 8,16,24,32,40,48,56,64 + ra_ContentionResolutionTimer = 7; + rsrp_ThresholdSSB = 19; +#prach-RootSequenceIndex_PR +#1 = 839, 2 = 139 + prach_RootSequenceIndex_PR = 2; + prach_RootSequenceIndex = 1; + # SCS for msg1, can only be 15 for 30 kHz < 6 GHz, takes precendence over the one derived from prach-ConfigIndex + # + msg1_SubcarrierSpacing = 1, +# restrictedSetConfig +# 0=unrestricted, 1=restricted type A, 2=restricted type B + restrictedSetConfig = 0, + + msg3_DeltaPreamble = 1; + p0_NominalWithGrant =-90; + +# pucch-ConfigCommon setup : +# pucchGroupHopping +# 0 = neither, 1= group hopping, 2=sequence hopping + pucchGroupHopping = 0; + hoppingId = 40; + p0_nominal = -90; +# ssb_PositionsInBurs_BitmapPR +# 1=short, 2=medium, 3=long + ssb_PositionsInBurst_PR = 2; + ssb_PositionsInBurst_Bitmap = 1; + +# ssb_periodicityServingCell +# 0 = ms5, 1=ms10, 2=ms20, 3=ms40, 4=ms80, 5=ms160, 6=spare2, 7=spare1 + ssb_periodicityServingCell = 2; + +# dmrs_TypeA_position +# 0 = pos2, 1 = pos3 + dmrs_TypeA_Position = 0; + +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + subcarrierSpacing = 1; + + + #tdd-UL-DL-ConfigurationCommon +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + referenceSubcarrierSpacing = 1; + # pattern1 + # dl_UL_TransmissionPeriodicity + # 0=ms0p5, 1=ms0p625, 2=ms1, 3=ms1p25, 4=ms2, 5=ms2p5, 6=ms5, 7=ms10 + dl_UL_TransmissionPeriodicity = 6; + nrofDownlinkSlots = 7; + nrofDownlinkSymbols = 6; + nrofUplinkSlots = 2; + nrofUplinkSymbols = 4; + + ssPBCH_BlockPower = -25; + } + + ); + # ------- SCTP definitions + SCTP : + { + # Number of streams to use in input/output + SCTP_INSTREAMS = 2; + SCTP_OUTSTREAMS = 2; + }; + + + ////////// AMF parameters: + amf_ip_address = ( { ipv4 = "192.168.71.132"; + ipv6 = "192:168:30::17"; + active = "yes"; + preference = "ipv4"; + } + ); + + E1_INTERFACE = + ( + { + type = "cp"; + ipv4_cucp = "192.168.72.140"; + port_cucp = 38462; + ipv4_cuup = "192.168.72.141"; + port_cuup = 38462; + } + ) + + NETWORK_INTERFACES : + { + GNB_INTERFACE_NAME_FOR_NG_AMF = "demo-oai"; + GNB_IPV4_ADDRESS_FOR_NG_AMF = "192.168.71.140/24"; + }; + } +); + +security = { + # preferred ciphering algorithms + # the first one of the list that an UE supports in chosen + # valid values: nea0, nea1, nea2, nea3 + ciphering_algorithms = ( "nea0" ); + + # preferred integrity algorithms + # the first one of the list that an UE supports in chosen + # valid values: nia0, nia1, nia2, nia3 + integrity_algorithms = ( "nia2", "nia0" ); + + # setting 'drb_ciphering' to "no" disables ciphering for DRBs, no matter + # what 'ciphering_algorithms' configures; same thing for 'drb_integrity' + drb_ciphering = "yes"; + drb_integrity = "no"; +}; + log_config : + { + global_log_level ="info"; + hw_log_level ="info"; + phy_log_level ="info"; + mac_log_level ="info"; + rlc_log_level ="debug"; + pdcp_log_level ="info"; + rrc_log_level ="info"; + f1ap_log_level ="debug"; + ngap_log_level ="debug"; + }; + diff --git a/ci-scripts/conf_files/gnb-cuup.sa.f1.conf b/ci-scripts/conf_files/gnb-cuup.sa.f1.conf new file mode 100644 index 0000000000..2a57a37273 --- /dev/null +++ b/ci-scripts/conf_files/gnb-cuup.sa.f1.conf @@ -0,0 +1,87 @@ +Active_gNBs = ( "gNB-OAI"); +# Asn1_verbosity, choice in: none, info, annoying +Asn1_verbosity = "none"; +sa = 1; + +gNBs = +( + { + ////////// Identification parameters: + gNB_CU_ID = 0xe00; + +# cell_type = "CELL_MACRO_GNB"; + + gNB_name = "gNB-OAI"; + + // 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, sd = 0xffffff }) }); + + + tr_s_preference = "f1"; + + local_s_if_name = "lo"; + local_s_address = "192.168.72.141"; + remote_s_address = "192.168.72.142"; + local_s_portc = 501; + local_s_portd = 2152; + remote_s_portc = 500; + remote_s_portd = 2152; + + # ------- SCTP definitions + SCTP : + { + # Number of streams to use in input/output + SCTP_INSTREAMS = 2; + SCTP_OUTSTREAMS = 2; + }; + + E1_INTERFACE = + ( + { + type = "up"; + ipv4_cucp = "192.168.72.140"; + ipv4_cuup = "192.168.72.141"; + } + ) + + NETWORK_INTERFACES : + { + GNB_INTERFACE_NAME_FOR_NG_AMF = "demo-oai"; + GNB_IPV4_ADDRESS_FOR_NG_AMF = "192.168.71.141/24"; + GNB_INTERFACE_NAME_FOR_NGU = "demo-oai"; + GNB_IPV4_ADDRESS_FOR_NGU = "192.168.71.141/24"; + GNB_PORT_FOR_S1U = 2152; # Spec 2152 + }; + } +); + +security = { + # preferred ciphering algorithms + # the first one of the list that an UE supports in chosen + # valid values: nea0, nea1, nea2, nea3 + ciphering_algorithms = ( "nea0" ); + + # preferred integrity algorithms + # the first one of the list that an UE supports in chosen + # valid values: nia0, nia1, nia2, nia3 + integrity_algorithms = ( "nia2", "nia0" ); + + # setting 'drb_ciphering' to "no" disables ciphering for DRBs, no matter + # what 'ciphering_algorithms' configures; same thing for 'drb_integrity' + drb_ciphering = "yes"; + drb_integrity = "no"; +}; + log_config : + { + global_log_level ="info"; + hw_log_level ="info"; + phy_log_level ="info"; + mac_log_level ="info"; + rlc_log_level ="debug"; + pdcp_log_level ="info"; + rrc_log_level ="info"; + f1ap_log_level ="debug"; + ngap_log_level ="debug"; + }; + diff --git a/ci-scripts/conf_files/gnb-du.band78.106prb.rfsim.conf b/ci-scripts/conf_files/gnb-du.band78.106prb.rfsim.conf new file mode 100644 index 0000000000..3c2fbe717e --- /dev/null +++ b/ci-scripts/conf_files/gnb-du.band78.106prb.rfsim.conf @@ -0,0 +1,245 @@ +Active_gNBs = ( "du-rfsim"); +# Asn1_verbosity, choice in: none, info, annoying +Asn1_verbosity = "none"; + +gNBs = +( + { + ////////// Identification parameters: + gNB_ID = 0xe00; + +# cell_type = "CELL_MACRO_GNB"; + + gNB_name = "du-rfsim"; + + // 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, sd = 0xffffff }) }); + + + nr_cellid = 12345678L; + + ////////// Physical parameters: + + min_rxtxtime = 6; + force_256qam_off = 1; + + pdcch_ConfigSIB1 = ( + { + controlResourceSetZero = 12; + searchSpaceZero = 0; + } + ); + + servingCellConfigCommon = ( + { + #spCellConfigCommon + + physCellId = 0; + +# downlinkConfigCommon + #frequencyInfoDL + # this is 3600 MHz + 43 PRBs@30kHz SCS (same as initial BWP) + absoluteFrequencySSB = 641280; + dl_frequencyBand = 78; + # this is 3600 MHz + dl_absoluteFrequencyPointA = 640008; + #scs-SpecificCarrierList + dl_offstToCarrier = 0; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + dl_subcarrierSpacing = 1; + dl_carrierBandwidth = 106; + #initialDownlinkBWP + #genericParameters + # this is RBstart=27,L=48 (275*(L-1))+RBstart + initialDLBWPlocationAndBandwidth = 28875; # 6366 12925 12956 28875 12952 +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + initialDLBWPsubcarrierSpacing = 1; + #pdcch-ConfigCommon + initialDLBWPcontrolResourceSetZero = 12; + initialDLBWPsearchSpaceZero = 0; + + #uplinkConfigCommon + #frequencyInfoUL + ul_frequencyBand = 78; + #scs-SpecificCarrierList + ul_offstToCarrier = 0; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + ul_subcarrierSpacing = 1; + ul_carrierBandwidth = 106; + pMax = 20; + #initialUplinkBWP + #genericParameters + initialULBWPlocationAndBandwidth = 28875; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + initialULBWPsubcarrierSpacing = 1; + #rach-ConfigCommon + #rach-ConfigGeneric + prach_ConfigurationIndex = 98; +#prach_msg1_FDM +#0 = one, 1=two, 2=four, 3=eight + prach_msg1_FDM = 0; + prach_msg1_FrequencyStart = 0; + zeroCorrelationZoneConfig = 13; + preambleReceivedTargetPower = -96; +#preamblTransMax (0...10) = (3,4,5,6,7,8,10,20,50,100,200) + preambleTransMax = 6; +#powerRampingStep +# 0=dB0,1=dB2,2=dB4,3=dB6 + powerRampingStep = 1; +#ra_ReponseWindow +#1,2,4,8,10,20,40,80 + ra_ResponseWindow = 4; +#ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR +#1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen + ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4; +#oneHalf (0..15) 4,8,12,16,...60,64 + ssb_perRACH_OccasionAndCB_PreamblesPerSSB = 14; +#ra_ContentionResolutionTimer +#(0..7) 8,16,24,32,40,48,56,64 + ra_ContentionResolutionTimer = 7; + rsrp_ThresholdSSB = 19; +#prach-RootSequenceIndex_PR +#1 = 839, 2 = 139 + prach_RootSequenceIndex_PR = 2; + prach_RootSequenceIndex = 1; + # SCS for msg1, can only be 15 for 30 kHz < 6 GHz, takes precendence over the one derived from prach-ConfigIndex + # + msg1_SubcarrierSpacing = 1, +# restrictedSetConfig +# 0=unrestricted, 1=restricted type A, 2=restricted type B + restrictedSetConfig = 0, + + msg3_DeltaPreamble = 1; + p0_NominalWithGrant =-90; + +# pucch-ConfigCommon setup : +# pucchGroupHopping +# 0 = neither, 1= group hopping, 2=sequence hopping + pucchGroupHopping = 0; + hoppingId = 40; + p0_nominal = -90; +# ssb_PositionsInBurs_BitmapPR +# 1=short, 2=medium, 3=long + ssb_PositionsInBurst_PR = 2; + ssb_PositionsInBurst_Bitmap = 1; + +# ssb_periodicityServingCell +# 0 = ms5, 1=ms10, 2=ms20, 3=ms40, 4=ms80, 5=ms160, 6=spare2, 7=spare1 + ssb_periodicityServingCell = 2; + +# dmrs_TypeA_position +# 0 = pos2, 1 = pos3 + dmrs_TypeA_Position = 0; + +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + subcarrierSpacing = 1; + + + #tdd-UL-DL-ConfigurationCommon +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + referenceSubcarrierSpacing = 1; + # pattern1 + # dl_UL_TransmissionPeriodicity + # 0=ms0p5, 1=ms0p625, 2=ms1, 3=ms1p25, 4=ms2, 5=ms2p5, 6=ms5, 7=ms10 + dl_UL_TransmissionPeriodicity = 6; + nrofDownlinkSlots = 7; + nrofDownlinkSymbols = 6; + nrofUplinkSlots = 2; + nrofUplinkSymbols = 4; + + ssPBCH_BlockPower = -25; + } + + ); + + + # ------- SCTP definitions + SCTP : + { + # Number of streams to use in input/output + SCTP_INSTREAMS = 2; + SCTP_OUTSTREAMS = 2; + }; + } +); + +MACRLCs = ( + { + num_cc = 1; + tr_s_preference = "local_L1"; + tr_n_preference = "f1"; + local_n_if_name = "eth0"; + local_n_address = "192.168.72.142"; + remote_n_address = "192.168.72.140"; + local_n_portc = 500; + local_n_portd = 2152; + remote_n_portc = 501; + remote_n_portd = 2152; + pusch_TargetSNRx10 = 200; + pucch_TargetSNRx10 = 200; + } +); + +L1s = ( +{ + num_cc = 1; + tr_n_preference = "local_mac"; + prach_dtx_threshold = 200; + pucch0_dtx_threshold = 150; + ofdm_offset_divisor = 8; #set this to UINT_MAX for offset 0 +} +); + +RUs = ( + { + local_rf = "yes" + nb_tx = 1 + nb_rx = 1 + att_tx = 0 + att_rx = 0; + bands = [78]; + max_pdschReferenceSignalPower = -27; + max_rxgain = 114; + eNB_instances = [0]; + #beamforming 1x4 matrix: + bf_weights = [0x00007fff, 0x0000, 0x0000, 0x0000]; + clock_src = "internal"; + } +); + +THREAD_STRUCT = ( + { + #three config for level of parallelism "PARALLEL_SINGLE_THREAD", "PARALLEL_RU_L1_SPLIT", or "PARALLEL_RU_L1_TRX_SPLIT" + parallel_config = "PARALLEL_SINGLE_THREAD"; + #two option for worker "WORKER_DISABLE" or "WORKER_ENABLE" + worker_config = "WORKER_ENABLE"; + } +); + +rfsimulator: { + serveraddr = "server"; + serverport = "4043"; + options = (); #("saviq"); or/and "chanmod" + modelname = "AWGN"; + IQfile = "/tmp/rfsimulator.iqs" +} + +log_config : +{ + global_log_level = "info"; + hw_log_level = "info"; + nr_phy_log_level = "info"; + nr_mac_log_level = "info"; + rlc_log_level = "info"; + pdcp_log_level = "info"; + rrc_log_level = "info"; + f1ap_log_level = "debug"; + ngap_log_level = "debug"; +}; diff --git a/ci-scripts/xml_files/container_5g_e1_rfsim.xml b/ci-scripts/xml_files/container_5g_e1_rfsim.xml new file mode 100644 index 0000000000..7130976dad --- /dev/null +++ b/ci-scripts/xml_files/container_5g_e1_rfsim.xml @@ -0,0 +1,131 @@ + + + rfsim-5gnr-e1 + CUCP-CUUP-DU E1+F1 split + wrench + + 111111 + 100021 + 000020 + 000021 + 000022 + 000023 + 000024 + 020021 + 020022 + 030021 + 100021 + + + + + Pull_Local_Registry + Pull Images from Local Registry + 0 + oai-gnb oai-nr-cuup oai-nr-ue + + + + DeployGenObject + Deploy MySql Database + yaml_files/5g_rfsimulator_e1 + mysql + 1 + + + + DeployGenObject + Deploy OAI 5G CoreNetwork + yaml_files/5g_rfsimulator_e1 + oai-nrf oai-amf oai-smf oai-spgwu oai-ext-dn + 6 + + + + DeployGenObject + Deploy OAI 5G CU-CP RF sim SA + yaml_files/5g_rfsimulator_e1 + oai-cucp + 7 + + + + DeployGenObject + Deploy OAI 5G CU-UP and DU RF sim SA + yaml_files/5g_rfsimulator_e1 + oai-cuup oai-du + 9 + + + + DeployGenObject + Deploy OAI 5G NR-UE RF sim SA + yaml_files/5g_rfsimulator_e1 + oai-nr-ue + 10 + + + + PingFromContainer + Ping ext-dn from NR-UE + rfsim5g-oai-nr-ue + -I oaitun_ue1 -c 20 192.168.73.135 + 5 + + + + PingFromContainer + Ping NR-UE from ext-dn + rfsim5g-oai-ext-dn + -c 20 12.1.1.2 + 5 + + + + IperfFromContainer + Iperf UDP Downlink + rfsim5g-oai-nr-ue + rfsim5g-oai-ext-dn + -B 12.1.1.2 -u -i 1 -s + -c 12.1.1.2 -u -i 1 -t 30 -b 3M + + + + IperfFromContainer + Iperf UDP Uplink + rfsim5g-oai-ext-dn + rfsim5g-oai-nr-ue + -u -i 1 -s + -B 12.1.1.2 -c 192.168.73.135 -u -i 1 -t 30 -b 1M + + + + UndeployGenObject + Undeploy all OAI 5G stack + yaml_files/5g_rfsimulator_e1 + 1,0,0,0 + 1,0,0,0 + + + diff --git a/ci-scripts/xml_files/container_5g_e1_rfsim_down.xml b/ci-scripts/xml_files/container_5g_e1_rfsim_down.xml new file mode 100644 index 0000000000..a1213c9b9b --- /dev/null +++ b/ci-scripts/xml_files/container_5g_e1_rfsim_down.xml @@ -0,0 +1,45 @@ + + + rfsim-5gnr-down-e1 + CleanUp CUCP-CUUP-DU E1+F1 split + trash + + 100022 + 222222 + + + + + UndeployGenObject + Undeploy all OAI 5G stack + yaml_files/5g_rfsimulator_e1 + + + + Clean_Test_Server_Images + Clean Test Images on Test Server + 0 + + + diff --git a/ci-scripts/yaml_files/5g_rfsimulator_e1/docker-compose.yaml b/ci-scripts/yaml_files/5g_rfsimulator_e1/docker-compose.yaml new file mode 100644 index 0000000000..3d4689e912 --- /dev/null +++ b/ci-scripts/yaml_files/5g_rfsimulator_e1/docker-compose.yaml @@ -0,0 +1,350 @@ +version: '3.8' +services: + oai-nrf: + container_name: "rfsim5g-oai-nrf" + image: oai-nrf:august-dev + environment: + - NRF_INTERFACE_NAME_FOR_SBI=eth0 + - NRF_INTERFACE_PORT_FOR_SBI=80 + - NRF_INTERFACE_HTTP2_PORT_FOR_SBI=9090 + - NRF_API_VERSION=v1 + - INSTANCE=0 + - PID_DIRECTORY=/var/run + networks: + core_net: + ipv4_address: 192.168.71.130 + volumes: + - ../5g_rfsimulator/nrf-healthcheck.sh:/openair-nrf/bin/nrf-healthcheck.sh + healthcheck: + test: /bin/bash -c "/openair-nrf/bin/nrf-healthcheck.sh" + interval: 10s + timeout: 5s + retries: 5 + + mysql: + container_name: "rfsim5g-mysql" + image: mysql:5.7 + volumes: + - ../5g_rfsimulator/oai_db.sql:/docker-entrypoint-initdb.d/oai_db.sql + - ../5g_rfsimulator/mysql-healthcheck.sh:/tmp/mysql-healthcheck.sh + environment: + - TZ=Europe/Paris + - MYSQL_DATABASE=oai_db + - MYSQL_USER=test + - MYSQL_PASSWORD=test + - MYSQL_ROOT_PASSWORD=linux + healthcheck: + test: /bin/bash -c "/tmp/mysql-healthcheck.sh" + interval: 10s + timeout: 5s + retries: 5 + networks: + core_net: + ipv4_address: 192.168.71.131 + + oai-amf: + container_name: "rfsim5g-oai-amf" + image: oai-amf:august-dev + environment: + - TZ=Europe/paris + - INSTANCE=0 + - PID_DIRECTORY=/var/run + - MCC=208 + - MNC=99 + - REGION_ID=128 + - AMF_SET_ID=1 + - SERVED_GUAMI_MCC_0=208 + - SERVED_GUAMI_MNC_0=99 + - SERVED_GUAMI_REGION_ID_0=128 + - SERVED_GUAMI_AMF_SET_ID_0=1 + - SERVED_GUAMI_MCC_1=460 + - SERVED_GUAMI_MNC_1=11 + - SERVED_GUAMI_REGION_ID_1=10 + - SERVED_GUAMI_AMF_SET_ID_1=1 + - PLMN_SUPPORT_MCC=208 + - PLMN_SUPPORT_MNC=99 + - PLMN_SUPPORT_TAC=0x0001 + - SST_0=1 + - SD_0=0xffffff + - SST_1=1 + - SD_1=1 + - AMF_INTERFACE_NAME_FOR_NGAP=eth0 + - AMF_INTERFACE_NAME_FOR_N11=eth0 + - SMF_INSTANCE_ID_0=1 + - SMF_FQDN_0=oai-smf + - SMF_IPV4_ADDR_0=0.0.0.0 + - SMF_HTTP_VERSION_0=v1 + - SELECTED_0=true + - SMF_INSTANCE_ID_1=2 + - SMF_FQDN_1=oai-smf + - SMF_IPV4_ADDR_1=0.0.0.0 + - SMF_HTTP_VERSION_1=v1 + - SELECTED_1=false + - MYSQL_SERVER=192.168.71.131 + - MYSQL_USER=root + - MYSQL_PASS=linux + - MYSQL_DB=oai_db + - OPERATOR_KEY=c42449363bbad02b66d16bc975d77cc1 + - NRF_IPV4_ADDRESS=192.168.71.130 + - NRF_PORT=80 + - NF_REGISTRATION=yes + - SMF_SELECTION=yes + - USE_FQDN_DNS=yes + - NRF_API_VERSION=v1 + - NRF_FQDN=oai-nrf + - EXTERNAL_AUSF=no + - AUSF_IPV4_ADDRESS=0.0.0.0 + - AUSF_PORT=80 + - AUSF_API_VERSION=v1 + - AUSF_FQDN=localhost + depends_on: + - oai-nrf + - mysql + volumes: + - ../5g_rfsimulator/amf-healthcheck.sh:/openair-amf/bin/amf-healthcheck.sh + healthcheck: + test: /bin/bash -c "/openair-amf/bin/amf-healthcheck.sh" + interval: 10s + timeout: 15s + retries: 5 + networks: + core_net: + ipv4_address: 192.168.71.132 + + oai-smf: + container_name: "rfsim5g-oai-smf" + image: oai-smf:august-dev + environment: + - TZ=Europe/Paris + - INSTANCE=0 + - PID_DIRECTORY=/var/run + - SMF_INTERFACE_NAME_FOR_N4=eth0 + - SMF_INTERFACE_NAME_FOR_SBI=eth0 + - SMF_INTERFACE_PORT_FOR_SBI=80 + - SMF_INTERFACE_HTTP2_PORT_FOR_SBI=9090 + - SMF_API_VERSION=v1 + - DEFAULT_DNS_IPV4_ADDRESS=172.21.3.100 + - DEFAULT_DNS_SEC_IPV4_ADDRESS=4.4.4.4 + - AMF_IPV4_ADDRESS=0.0.0.0 + - AMF_PORT=80 + - AMF_API_VERSION=v1 + - AMF_FQDN=oai-amf + - UDM_IPV4_ADDRESS=127.0.0.1 + - UDM_PORT=80 + - UDM_API_VERSION=v1 + - UDM_FQDN=localhost + - UPF_IPV4_ADDRESS=192.168.71.134 + - UPF_FQDN_0=oai-spgwu + - NRF_IPV4_ADDRESS=192.168.71.130 + - NRF_PORT=80 + - NRF_API_VERSION=v1 + - NRF_FQDN=oai-nrf + - REGISTER_NRF=yes + - DISCOVER_UPF=yes + - USE_FQDN_DNS=yes + - DNN_NI0=oai + - TYPE0=IPv4 + - DNN_RANGE0=12.1.1.2 - 12.1.1.127 + - NSSAI_SST0=1 + - NSSAI_SD0=0xFFFFFF + - SESSION_AMBR_UL0=200Mbps + - SESSION_AMBR_DL0=400Mbps + - DNN_NI2=oai.ipv4 + depends_on: + - oai-nrf + - oai-amf + volumes: + - ../5g_rfsimulator/smf-healthcheck.sh:/openair-smf/bin/smf-healthcheck.sh + healthcheck: + test: /bin/bash -c "/openair-smf/bin/smf-healthcheck.sh" + interval: 10s + timeout: 5s + retries: 5 + networks: + core_net: + ipv4_address: 192.168.71.133 + + oai-spgwu: + container_name: "rfsim5g-oai-spgwu" + image: oai-spgwu-tiny:august-dev + environment: + - TZ=Europe/Paris + - PID_DIRECTORY=/var/run + - SGW_INTERFACE_NAME_FOR_S1U_S12_S4_UP=eth0 + - SGW_INTERFACE_NAME_FOR_SX=eth0 + - PGW_INTERFACE_NAME_FOR_SGI=eth0 + - NETWORK_UE_NAT_OPTION=yes + - NETWORK_UE_IP=12.1.1.0/24 + - SPGWC0_IP_ADDRESS=192.168.71.133 + - BYPASS_UL_PFCP_RULES=no + - MCC=208 + - MNC=99 + - MNC03=099 + - TAC=1 + - GTP_EXTENSION_HEADER_PRESENT=yes + - GW_ID=1 + - REALM=openairinterface.org + - ENABLE_5G_FEATURES=yes + - REGISTER_NRF=yes + - USE_FQDN_NRF=yes + - UPF_FQDN_5G=oai-spgwu + - NRF_IPV4_ADDRESS=192.168.71.130 + - NRF_PORT=80 + - NRF_API_VERSION=v1 + - NRF_FQDN=oai-nrf + - NSSAI_SST_0=1 + - NSSAI_SD_0=0xffffff + - DNN_0=oai + depends_on: + - oai-nrf + - oai-smf + cap_add: + - NET_ADMIN + - SYS_ADMIN + cap_drop: + - ALL + privileged: true + volumes: + - ../5g_rfsimulator/spgwu-healthcheck.sh:/openair-spgwu-tiny/bin/spgwu-healthcheck.sh + healthcheck: + test: /bin/bash -c "/openair-spgwu-tiny/bin/spgwu-healthcheck.sh" + interval: 10s + timeout: 5s + retries: 5 + networks: + core_net: + ipv4_address: 192.168.71.134 + traffic_net: + ipv4_address: 192.168.73.134 + + oai-ext-dn: + image: ubuntu:bionic + privileged: true + container_name: rfsim5g-oai-ext-dn + entrypoint: /bin/bash -c \ + "apt update; apt install -y procps iptables iproute2 iperf iputils-ping;"\ + "iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE;"\ + "ip route add 12.1.1.0/24 via 192.168.73.134 dev eth0; sleep infinity" + depends_on: + - oai-spgwu + networks: + traffic_net: + ipv4_address: 192.168.73.135 + healthcheck: + test: /bin/bash -c "ping -c 2 192.168.73.134" + interval: 10s + timeout: 5s + retries: 5 + + oai-cucp: + image: oai-gnb:develop + privileged: true + container_name: rfsim5g-oai-cucp + environment: + USE_VOLUMED_CONF: 'yes' + USE_ADDITIONAL_OPTIONS: --sa --rfsim --log_config.global_log_options level,nocolor,time + depends_on: + - oai-ext-dn + networks: + core_net: + ipv4_address: 192.168.71.140 + ran_net: + ipv4_address: 192.168.72.140 + volumes: + - ../../conf_files/gnb-cucp.sa.f1.conf:/opt/oai-gnb/etc/mounted.conf + healthcheck: + test: /bin/bash -c "pgrep nr-softmodem" + interval: 10s + timeout: 5s + retries: 5 + + oai-cuup: + image: oai-nr-cuup:develop + privileged: true + container_name: rfsim5g-oai-cuup + environment: + USE_VOLUMED_CONF: 'yes' + USE_ADDITIONAL_OPTIONS: --sa --rfsim + #--log_config.global_log_options level,nocolor,time + depends_on: + - oai-cucp + networks: + core_net: + ipv4_address: 192.168.71.141 + ran_net: + ipv4_address: 192.168.72.141 + volumes: + - ../../conf_files/gnb-cuup.sa.f1.conf:/opt/oai-gnb/etc/mounted.conf + healthcheck: + test: /bin/bash -c "pgrep nr-cuup" + interval: 10s + timeout: 5s + retries: 5 + + oai-du: + image: oai-gnb:develop + privileged: true + container_name: rfsim5g-oai-du + environment: + RFSIMULATOR: server + USE_VOLUMED_CONF: 'yes' + USE_ADDITIONAL_OPTIONS: --sa --rfsim --log_config.global_log_options level,nocolor,time + networks: + ran_net: + ipv4_address: 192.168.72.142 + volumes: + - ../../conf_files/gnb-du.band78.106prb.rfsim.conf:/opt/oai-gnb/etc/mounted.conf + healthcheck: + test: /bin/bash -c "pgrep nr-softmodem" + interval: 10s + timeout: 5s + retries: 5 + + oai-nr-ue: + image: oai-nr-ue:develop + privileged: true + container_name: rfsim5g-oai-nr-ue + environment: + RFSIMULATOR: 192.168.72.142 + FULL_IMSI: '208990100001100' + FULL_KEY: 'fec86ba6eb707ed08905757b1bb44b8f' + OPC: 'C42449363BBAD02B66D16BC975D77CC1' + DNN: oai + NSSAI_SST: 1 + USE_ADDITIONAL_OPTIONS: --sa --rfsim -r 106 --numerology 1 -C 3619200000 --nokrnmod --log_config.global_log_options level,nocolor,time + depends_on: + - oai-du + networks: + ran_net: + ipv4_address: 192.168.72.150 + healthcheck: + test: /bin/bash -c "pgrep nr-uesoftmodem" + interval: 10s + timeout: 5s + retries: 5 + +networks: + core_net: + driver: bridge + name: rfsim5g-oai-core-net + ipam: + config: + - subnet: 192.168.71.128/26 + driver_opts: + com.docker.network.bridge.name: "rfsim5g-core" + ran_net: + driver: bridge + name: rfsim5g-oai-ran-net + ipam: + config: + - subnet: 192.168.72.128/26 + driver_opts: + com.docker.network.bridge.name: "rfsim5g-ran" + traffic_net: + driver: bridge + name: rfsim5g-oai-traffic_net-net + ipam: + config: + - subnet: 192.168.73.128/26 + driver_opts: + com.docker.network.bridge.name: "rfsim5g-traffic" diff --git a/cmake_targets/build_oai b/cmake_targets/build_oai index 9fb2d64e4a..f9166e0555 100755 --- a/cmake_targets/build_oai +++ b/cmake_targets/build_oai @@ -535,7 +535,7 @@ function main() { execlist="$execlist ocp-enb" fi if [ "$gNB" = "1" ] ; then - execlist="$execlist nr-softmodem" + execlist="$execlist nr-softmodem nr-cuup" fi if [ "$RU" = "1" ] ; then execlist="$execlist oairu" diff --git a/common/ngran_types.h b/common/ngran_types.h index 3dfa7aa01a..ddd1ec2cca 100644 --- a/common/ngran_types.h +++ b/common/ngran_types.h @@ -42,12 +42,16 @@ typedef enum { ngran_gNB_CU = 5, ngran_eNB_DU = 6, ngran_gNB_DU = 7, - ngran_eNB_MBMS_STA = 8 + ngran_eNB_MBMS_STA = 8, + ngran_gNB_CUCP = 9, + ngran_gNB_CUUP = 10 } ngran_node_t; +typedef enum { CPtype = 0, UPtype } E1_t; + #define NODE_IS_MONOLITHIC(nOdE_TyPe) ((nOdE_TyPe) == ngran_eNB || (nOdE_TyPe) == ngran_ng_eNB || (nOdE_TyPe) == ngran_gNB) -#define NODE_IS_CU(nOdE_TyPe) ((nOdE_TyPe) == ngran_eNB_CU || (nOdE_TyPe) == ngran_ng_eNB_CU || (nOdE_TyPe) == ngran_gNB_CU) +#define NODE_IS_CU(nOdE_TyPe) ((nOdE_TyPe) == ngran_eNB_CU || (nOdE_TyPe) == ngran_ng_eNB_CU || (nOdE_TyPe) == ngran_gNB_CU || (nOdE_TyPe) == ngran_gNB_CUCP || (nOdE_TyPe) == ngran_gNB_CUUP) #define NODE_IS_DU(nOdE_TyPe) ((nOdE_TyPe) == ngran_eNB_DU || (nOdE_TyPe) == ngran_gNB_DU) #define NODE_IS_MBMS(nOdE_TyPe) ((nOdE_TyPe) == ngran_eNB_MBMS_STA) - +#define GTPV1_U_PORT_NUMBER (2152) #endif diff --git a/common/utils/LOG/log.c b/common/utils/LOG/log.c index 2215e4bd40..84c70c3767 100644 --- a/common/utils/LOG/log.c +++ b/common/utils/LOG/log.c @@ -483,6 +483,7 @@ int logInit (void) register_log_component("SDAP","",SDAP); register_log_component("S1AP","",S1AP); register_log_component("F1AP","",F1AP); + register_log_component("E1AP","",E1AP); register_log_component("M2AP","",M2AP); register_log_component("M3AP","",M3AP); register_log_component("SCTP","",SCTP); diff --git a/common/utils/ocp_itti/all_msg.h b/common/utils/ocp_itti/all_msg.h index ab75eaffdd..eb484ce8f1 100644 --- a/common/utils/ocp_itti/all_msg.h +++ b/common/utils/ocp_itti/all_msg.h @@ -15,5 +15,6 @@ #include "openair2/COMMON/udp_messages_def.h" #include "openair2/COMMON/gtpv1_u_messages_def.h" #include "openair2/COMMON/f1ap_messages_def.h" +#include "openair2/COMMON/e1ap_messages_def.h" #include "openair2/COMMON/ngap_messages_def.h" diff --git a/common/utils/ocp_itti/intertask_interface.h b/common/utils/ocp_itti/intertask_interface.h index 0a7bbc3b78..2b17c7e3ef 100644 --- a/common/utils/ocp_itti/intertask_interface.h +++ b/common/utils/ocp_itti/intertask_interface.h @@ -79,6 +79,7 @@ typedef struct IttiMsgText_s { #include #include #include +#include #include #include @@ -409,7 +410,7 @@ typedef struct MessageHeader_s { } MessageHeader; typedef struct message_info_s { - int id; + MessagesIds id; message_priorities_t priority; /* Message payload size */ MessageHeaderSize size; diff --git a/doc/E1-design.md b/doc/E1-design.md new file mode 100644 index 0000000000..db4bc85f74 --- /dev/null +++ b/doc/E1-design.md @@ -0,0 +1,108 @@ +[[_TOC_]] + +# 1. Introduction + +E1 is named for the interface that lies between the nodes CU Control Plane (CUCP) and CU User Plane (CUUP). Once the nodes are configured, all user plane traffic flows through CUUP. + +The E1 design in OAI follows the 3GPP specification in TS 38.460. The code design on E1 in OAI is very similar to +F1. The ITTI message passing mechanism is used to exchange messages between E1AP thread, SCTP thread and RRC thread. + +The following sequence chart shows the current E1AP message flow. + +```mermaid +sequenceDiagram + participant c as CUCP + participant u as CUUP + u->>c: SCTP new association + c->>u: SCTP new association response + Note over u: Create UDP sockets for F1-U and N3 + u->>c: E1AP Setup Request + c->>u: E1AP Setup Response + Note over c: Receives PDU session setup request from AMF + c->>u: Bearer Context Setup Request + Note over u: Configure DRBs and create GTP Tunnels for F1-U and N3 + u->>c: Bearer Context Setup Response + Note over c: Sends F1-U UL TNL info to DU and receives DL TNL info + c->>u: Bearer Context Modification Request + Note over u: Updates GTP Tunnels with received info +``` + +_Note that the E1 bearer release procedures are currently not implemented._ + +# 2. Running the E1 Split + +## 2.1 Configuration File + +The gNB is started based on the node type that is specified in the configuration file. To start a gNB instance in CUCP or CUUP, the `tr_s_preference` should be set to "f1" and the config member `E1_INTERFACE` should be present in the config file. The `type` parameter within the `E1_INTERFACE` should be set to `cp`, and `nr-softmodem` should be used to run a CU-CP. The type should be `up` and `nr-cuup` should be used to run the CU-UP. Further, there are the parameters `ipv4_cucp` and `ipv4_cuup` to specify the IP addresses of the respective network functions. + +For CUCP, a typical `E1_INTERFACE` config looks like +``` +E1_INTERFACE = +( + { + type = "cp"; + ipv4_cucp = "127.0.0.4"; + ipv4_cuup = "127.0.0.5"; + } +) +``` + +For CUUP, it is +``` +E1_INTERFACE = +( + { + type = "up"; + ipv4_cucp = "127.0.0.4"; + ipv4_cuup = "127.0.0.5"; + } +) +``` +One could take an existing CU configuration file and add the above parameters to run the gNB as CUCP or CUUP. + +The CUUP uses the IP address specified in `local_s_address` for F1-U and `GNB_IPV4_ADDRESS_FOR_NGU` for N3 links. Note that `local_s_address` is under `gNBs` and `GNB_IPV4_ADDRESS_FOR_NGU` is part of the `NETWORK_INTERFACES` config member. + +Alternatively, you can use the config files `ci-scripts/conf_files/gnb-cucp.sa.conf` and `ci-scripts/conf_files/gnb-cuup.sa.conf` which are already in the repository. + +## 2.2 Steps to Run the Split in rfsimulator with OAI UE + +Note: A 5G core must be running at this point. Steps to start the OAI 5G core can be found [in the oai-cn5g-fed repository](https://gitlab.eurecom.fr/oai/cn5g/oai-cn5g-fed/-/blob/master/docs/DEPLOY_HOME.md) or [here](NR_SA_CN5G_gNB_USRP_COTS_UE_Tutorial.md). + +0. Open wireshark to capture the E1AP messages. You might set the capture filter + to `sctp` to limit the number of captured packages. + +1. Start the CUCP first by running the following command +``` +sudo ./nr-softmodem -O ../../../ci-scripts/conf_files/gnb-cucp.sa.conf --gNBs.[0].min_rxtxtime 6 --sa +``` + +Note that `min_rxtxtime` should be set to `6` only when you are connecting an OAI UE to the gNB. + +2. Start the CUUP and DU (in any order) + +CUUP (has its own executable): +``` +sudo ./nr-cuup -O ../../../ci-scripts/conf_files/gnb-cuup.sa.conf --sa +``` + +DU: +``` +sudo ./nr-softmodem -O ../../../ci-scripts/conf_files/gNB_SA_DU.conf --rfsim --sa +``` + +You need to use `--rfsim` if you are running the test with rfsimulator. + +3. Start OAI UE or COTS UE. + +OAI UE: +``` +sudo RFSIMULATOR=127.0.0.1 ./nr-uesoftmodem -r 106 --numerology 1 --band 78 -C 3619200000 --nokrnmod --rfsim --sa +``` + +# 3. Configuration file IP addresses of network functions + +You can also run the nodes on different machines. If you do so please change the interface parameters accordingly and make sure the interfaces are reachable. Please refer to the following figure for an overview of all parameters. + +![E1/F1/NG parameters](images/e1-archi.png){width=1200} + +[PDF version](images/e1-archi.pdf) | [LaTeX/TikZ version](img/e1-archi.tex) if you want to modify to reflect your setup diff --git a/doc/TESTING_5GSA_setup.md b/doc/TESTING_5GSA_setup.md index 1828f967b1..18b61d30a5 100644 --- a/doc/TESTING_5GSA_setup.md +++ b/doc/TESTING_5GSA_setup.md @@ -91,7 +91,8 @@ In the first part (*amf_ip_address*) we specify the IP of the AMF and in the sec Please read [CN5G tutorial for more details](https://gitlab.eurecom.fr/oai/cn5g/oai-cn5g-fed/-/blob/master/README.md). -### **gNB configuration in CU/DU split mode** +### 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 @@ -112,9 +113,11 @@ MACRLCs = ( ); ``` - 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). diff --git a/doc/images/e1-archi.pdf b/doc/images/e1-archi.pdf new file mode 100644 index 0000000000..ddbed79e51 Binary files /dev/null and b/doc/images/e1-archi.pdf differ diff --git a/doc/images/e1-archi.png b/doc/images/e1-archi.png new file mode 100644 index 0000000000..77b398d81a Binary files /dev/null and b/doc/images/e1-archi.png differ diff --git a/doc/images/e1-archi.tex b/doc/images/e1-archi.tex new file mode 100644 index 0000000000..7a18d63c53 --- /dev/null +++ b/doc/images/e1-archi.tex @@ -0,0 +1,73 @@ +\documentclass{standalone} +%\usepackage[tt=false]{libertine} +\renewcommand{\familydefault}{\sfdefault} +% improve for some encodings +\usepackage{textcomp} +\usepackage{tikz} +\usetikzlibrary{positioning} +\usetikzlibrary{shapes.symbols} +\usetikzlibrary{decorations.markings} +\usetikzlibrary{fit} + +\tikzset{splitpos/.store in=\splitpos,splitpos=0.5} +\newcommand{\ip}[1]{\texttt{#1}} + +\begin{document} +\begin{tikzpicture} + [ + font=\scriptsize, + node distance=1.5cm and 3.2cm, + entity/.style={ + rectangle, + draw, + inner sep=0pt, + minimum height=6mm,minimum width=11mm, + align=center + }, + split/.style={postaction={% + decorate, + decoration={ + markings,mark={ + at position \splitpos + with { + \draw (0pt,2.5pt) -- (0pt,-2.5pt); + } + } + } + } + }, + ip/.style={font=\tiny,outer sep=1pt,inner sep=1pt}, + ] + \node[entity] (cu-cp) {CU-CP}; + \node[entity,below=of cu-cp] (cu-up) {CU-UP}; + \node[entity,below left=0.45cm and 3.2cm of cu-cp] (du) {DU}; + \node[entity,right=of cu-cp] (amf) {AMF}; + \node[entity,right=of cu-up] (upf) {UPF}; + + \draw[split,splitpos=0.5] (cu-cp) -- + node[ip,at start, below right, align=left] {\ip{GNB\_IPV4\_ADDRESS\_FOR\_NG\_AMF:38412}} + node[above] {NG-C/N2} + %node[ip,at end, below left] {127.0.1.10/24} + (amf); + \draw[split,splitpos=0.5] (cu-up) -- + node[ip, at start, below right,align=left] {\ip{GNB\_IPV4\_ADDRESS\_FOR\_NGU:2152}} + node[above] {NG-U/N3} + %node[ip, at end, below left] {127.0.1.10/24} + (upf); + \draw[split,splitpos=0.5] (cu-cp) -- + node[ip, at start, below right] {\ip{ipv4\_cucp:38462}} + node[right] {E1AP} + node[ip, at end, above right] {\ip{ipv4\_cuup:38462}} + (cu-up); + \draw[split] (du.north east) -- + node[ip, at start, below right] {to \ip{remote\_n\_address:38472}} + node[above] {F1-C} + node[ip, at end, above left, align=right] {\ip{local\_s\_address:38472}} + (cu-cp); + \draw[split] (du.south east) -- + node[ip, at start, above right] {to \ip{remote\_n\_address:remote\_n\_portd}} + node[above] {F1-U} + node[ip, at end, below left, align=right] {\ip{local\_s\_address:local\_s\_portd}} + (cu-up); +\end{tikzpicture} +\end{document} diff --git a/docker/Dockerfile.nr-cuup.ubuntu18 b/docker/Dockerfile.nr-cuup.ubuntu18 new file mode 100644 index 0000000000..94d1ff5ef7 --- /dev/null +++ b/docker/Dockerfile.nr-cuup.ubuntu18 @@ -0,0 +1,63 @@ +#/* +# * 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 +# */ +#--------------------------------------------------------------------- +# +# Dockerfile for the Open-Air-Interface BUILD service +# Valid for Ubuntu18.04 +# +#--------------------------------------------------------------------- + +FROM ran-base:latest as gnb-base + +FROM ran-build:latest AS gnb-build + +RUN cp /oai-ran/docker/scripts/gnb_entrypoint.sh /oai-ran/docker/scripts/entrypoint.sh + +FROM ubuntu:bionic as oai-nr-cuup +ENV DEBIAN_FRONTEND=noninteractive +ENV TZ=Europe + +RUN apt-get update && \ + DEBIAN_FRONTEND=noninteractive apt-get upgrade --yes && \ + DEBIAN_FRONTEND=noninteractive apt-get install --yes \ + libsctp1 \ + libconfig9 \ + openssl && \ + rm -rf /var/lib/apt/lists/* + +WORKDIR /opt/oai-gnb/bin +COPY --from=gnb-build \ + /oai-ran/cmake_targets/ran_build/build/nr-cuup \ + /oai-ran/docker/scripts/entrypoint.sh \ + ./ + +COPY --from=gnb-build \ + /oai-ran/cmake_targets/ran_build/build/librfsimulator.so \ + /oai-ran/cmake_targets/ran_build/build/libparams_libconfig.so \ + /oai-ran/cmake_targets/ran_build/build/libtelnetsrv.so \ + /usr/local/lib/ + +# Create directory for configuration files +WORKDIR /opt/oai-gnb/etc + +WORKDIR /opt/oai-gnb +ENTRYPOINT ["/opt/oai-gnb/bin/entrypoint.sh"] +CMD ["/opt/oai-gnb/bin/nr-cuup", "-O", "/opt/oai-gnb/etc/gnb.conf"] diff --git a/executables/nr-cuup.c b/executables/nr-cuup.c new file mode 100644 index 0000000000..e2b2bdb50b --- /dev/null +++ b/executables/nr-cuup.c @@ -0,0 +1,160 @@ +/* + * 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 "common/utils/simple_executable.h" +#include "executables/softmodem-common.h" +#include "common/utils/ocp_itti/intertask_interface.h" +#include "openair3/ocp-gtpu/gtp_itf.h" +#include "openair2/E1AP/e1ap.h" +#include "common/ran_context.h" +#include "nfapi/oai_integration/vendor_ext.h" +#include "openair2/F1AP/f1ap_common.h" +#include "openair2/GNB_APP/gnb_config.h" + +RAN_CONTEXT_t RC; +THREAD_STRUCT thread_struct; +uint64_t downlink_frequency[MAX_NUM_CCs][4]; +int32_t uplink_frequency_offset[MAX_NUM_CCs][4]; +int asn1_xer_print; +int oai_exit = 0; +instance_t CUuniqInstance = 0; +RRC_release_list_t rrc_release_info; + +void exit_function(const char *file, const char *function, const int line, const char *s) +{ +} + +nfapi_mode_t nfapi_mod = -1; +void nfapi_setmode(nfapi_mode_t nfapi_mode) +{ + nfapi_mod = nfapi_mode; +} +nfapi_mode_t nfapi_getmode(void) +{ + return nfapi_mod; +} + +ngran_node_t get_node_type() +{ + return ngran_gNB_CUUP; +} + +rlc_op_status_t rlc_data_req(const protocol_ctxt_t *const pc, + const srb_flag_t sf, + const MBMS_flag_t mf, + const rb_id_t rb_id, + const mui_t mui, + const confirm_t c, + const sdu_size_t size, + mem_block_t *const buf, + const uint32_t *const a, + const uint32_t *const b) +{ + abort(); + return 0; +} + +int nr_rlc_get_available_tx_space(const rnti_t rntiP, const logical_chan_id_t channel_idP) +{ + abort(); + return 0; +} + +void nr_rlc_bearer_init(NR_RLC_BearerConfig_t *RLC_BearerConfig, NR_RLC_BearerConfig__servedRadioBearer_PR rb_type) +{ + abort(); +} + +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) +{ + abort(); +} + +void nr_rlc_bearer_init_ul_spec(struct NR_LogicalChannelConfig *mac_LogicalChannelConfig) +{ + abort(); +} + +rlc_op_status_t nr_rrc_rlc_config_asn1_req(const protocol_ctxt_t *const ctxt_pP, + const NR_SRB_ToAddModList_t *const srb2add_listP, + const NR_DRB_ToAddModList_t *const drb2add_listP, + const NR_DRB_ToReleaseList_t *const drb2release_listP, + struct NR_CellGroupConfig__rlc_BearerToAddModList *rlc_bearer2add_list) +{ + abort(); + return 0; +} + +int nr_rrc_gNB_process_GTPV1U_CREATE_TUNNEL_RESP(const protocol_ctxt_t *const ctxt_pP, const gtpv1u_gnb_create_tunnel_resp_t *const create_tunnel_resp_pP) +{ + abort(); + return 0; +} + +void nr_drb_config(struct NR_RLC_Config *rlc_Config, NR_RLC_Config_PR rlc_config_pr) +{ + abort(); +} + +void prepare_and_send_ue_context_modification_f1(rrc_gNB_ue_context_t *ue_context_p, e1ap_bearer_setup_resp_t *e1ap_resp) +{ + abort(); +} + +f1ap_cudu_inst_t *getCxt(F1_t isCU, instance_t instanceP) +{ + abort(); + return NULL; +} + +void fill_DRB_configList(const protocol_ctxt_t *const ctxt_pP, rrc_gNB_ue_context_t *ue_context_pP) +{ + abort(); +} + +int main(int argc, char **argv) +{ + /// static configuration for NR at the moment + if (load_configmodule(argc, argv, CONFIG_ENABLECMDLINEONLY) == NULL) { + exit_fun("[SOFTMODEM] Error, configuration module init failed\n"); + } + logInit(); + set_softmodem_sighandler(); + itti_init(TASK_MAX, tasks_info); + int rc; + rc = itti_create_task(TASK_SCTP, sctp_eNB_task, NULL); + AssertFatal(rc >= 0, "Create task for SCTP failed\n"); + rc = itti_create_task(TASK_GTPV1_U, gtpv1uTask, NULL); + AssertFatal(rc >= 0, "Create task for GTPV1U failed\n"); + rc = itti_create_task(TASK_CUUP_E1, E1AP_CUUP_task, NULL); + AssertFatal(rc >= 0, "Create task for CUUP E1 failed\n"); + pdcp_layer_init(); + MessageDef *msg = RCconfig_NR_CU_E1(true); + AssertFatal(msg != NULL, "Send init to task for E1AP UP failed\n"); + itti_send_msg_to_task(TASK_CUUP_E1, 0, msg); + + printf("TYPE TO TERMINATE\n"); + itti_wait_tasks_end(); + + logClean(); + printf("Bye.\n"); + return 0; +} diff --git a/executables/nr-softmodem.c b/executables/nr-softmodem.c index dddd1da641..025cc34481 100644 --- a/executables/nr-softmodem.c +++ b/executables/nr-softmodem.c @@ -77,6 +77,9 @@ unsigned short config_frames[4] = {2,9,11,13}; #include "gnb_paramdef.h" #include #include "nfapi/oai_integration/vendor_ext.h" +#include "gnb_config.h" +#include "openair2/E1AP/e1ap_common.h" +#include "openair2/E1AP/e1ap_api.h" pthread_cond_t nfapi_sync_cond; pthread_mutex_t nfapi_sync_mutex; @@ -288,16 +291,60 @@ void exit_function(const char *file, const char *function, const int line, const -int create_gNB_tasks(uint32_t gnb_nb) { +static int create_gNB_tasks(void) { + uint32_t gnb_nb = RC.nb_nr_inst; + uint32_t gnb_id_start = 0; + uint32_t gnb_id_end = gnb_id_start + gnb_nb; LOG_D(GNB_APP, "%s(gnb_nb:%d)\n", __FUNCTION__, gnb_nb); itti_wait_ready(1); + LOG_I(PHY, "%s() Task ready initialize structures\n", __FUNCTION__); + + RCconfig_NR_L1(); + RCconfig_nr_prs(); + + if (RC.nb_nr_macrlc_inst>0) RCconfig_nr_macrlc(); + + LOG_I(PHY, "%s() RC.nb_nr_L1_inst:%d\n", __FUNCTION__, RC.nb_nr_L1_inst); + + if (RC.nb_nr_L1_inst>0) AssertFatal(l1_north_init_gNB()==0,"could not initialize L1 north interface\n"); + + AssertFatal (gnb_nb <= RC.nb_nr_inst, + "Number of gNB is greater than gNB defined in configuration file (%d/%d)!", + gnb_nb, RC.nb_nr_inst); + + LOG_I(GNB_APP,"Allocating gNB_RRC_INST for %d instances\n",RC.nb_nr_inst); + + RC.nrrrc = (gNB_RRC_INST **)malloc(RC.nb_nr_inst*sizeof(gNB_RRC_INST *)); + LOG_I(PHY, "%s() RC.nb_nr_inst:%d RC.nrrrc:%p\n", __FUNCTION__, RC.nb_nr_inst, RC.nrrrc); + ngran_node_t node_type = get_node_type(); + for (int gnb_id = gnb_id_start; (gnb_id < gnb_id_end) ; gnb_id++) { + RC.nrrrc[gnb_id] = (gNB_RRC_INST*)calloc(1,sizeof(gNB_RRC_INST)); + LOG_I(PHY, "%s() Creating RRC instance RC.nrrrc[%d]:%p (%d of %d)\n", __FUNCTION__, gnb_id, RC.nrrrc[gnb_id], gnb_id+1, gnb_id_end); + configure_nr_rrc(gnb_id); + } + + if (RC.nb_nr_inst > 0 && + !get_softmodem_params()->nsa && + !(node_type == ngran_gNB_DU)) { + // we start pdcp in both cuup (for drb) and cucp (for srb) + init_pdcp(); + } + + if (is_x2ap_enabled() ) { //&& !NODE_IS_DU(node_type) + LOG_I(X2AP, "X2AP enabled \n"); + __attribute__((unused)) uint32_t x2_register_gnb_pending = gNB_app_register_x2 (gnb_id_start, gnb_id_end); + } + + /* For the CU case the gNB registration with the AMF might have to take place after the F1 setup, as the PLMN info + * can originate from the DU. Add check on whether x2ap is enabled to account for ENDC NSA scenario.*/ + if ((get_softmodem_params()->sa || is_x2ap_enabled()) && + !NODE_IS_DU(node_type)) { + /* Try to register each gNB */ + //registered_gnb = 0; + __attribute__((unused)) uint32_t register_gnb_pending = gNB_app_register (gnb_id_start, gnb_id_end); + } if (gnb_nb > 0) { - /* Last task to create, others task must be ready before its start */ - /*if (itti_create_task (TASK_GNB_APP, gNB_app_task, NULL) < 0) { - LOG_E(GNB_APP, "Create task for gNB APP failed\n"); - return -1; - }*/ if(itti_create_task(TASK_SCTP, sctp_eNB_task, NULL) < 0) { LOG_E(SCTP, "Create task for SCTP failed\n"); return -1; @@ -312,7 +359,8 @@ int create_gNB_tasks(uint32_t gnb_nb) { } } - if (get_softmodem_params()->sa) { + if (get_softmodem_params()->sa && + !NODE_IS_DU(node_type)) { char* gnb_ipv4_address_for_NGU = NULL; uint32_t gnb_port_for_NGU = 0; @@ -325,9 +373,10 @@ int create_gNB_tasks(uint32_t gnb_nb) { for(int i = GNB_INTERFACE_NAME_FOR_NG_AMF_IDX; i <= GNB_IPV4_ADDRESS_FOR_NG_AMF_IDX; i++) { if( NETParams[i].strptr == NULL) { - LOG_E(NGAP, "No AMF configuration in the file.\n"); + LOG_E(NGAP, "No AMF configuration in the file.\n"); + exit(1); } else { - LOG_D(NGAP, "Configuration in the file: %s.\n",*NETParams[i].strptr); + LOG_D(NGAP, "Configuration in the file: %s.\n",*NETParams[i].strptr); } } @@ -345,15 +394,26 @@ int create_gNB_tasks(uint32_t gnb_nb) { return -1; } - LOG_I(NR_RRC,"Creating NR RRC gNB Task\n"); - + LOG_I(NR_RRC, "Creating NR RRC gNB Task, that will also create TASKS\n"); if (itti_create_task (TASK_RRC_GNB, rrc_gnb_task, NULL) < 0) { LOG_E(NR_RRC, "Create task for NR RRC gNB failed\n"); return -1; } - //Use check on x2ap to consider the NSA scenario and check for SA scenario - if(is_x2ap_enabled() || get_softmodem_params()->sa) { + // If CU + if (node_type == ngran_gNB_CU || node_type == ngran_gNB) { + MessageDef *msg = RCconfig_NR_CU_E1(false); + instance_t inst = 0; + createE1inst(UPtype, inst, &E1AP_SETUP_REQ(msg)); + cuup_init_n3(inst); + itti_free(TASK_UNKNOWN, msg); + getCxtE1(inst)->same_process = true; + ; + RC.nrrrc[gnb_id_start]->e1_inst = inst; // stupid instance !!!*/ + } + + //Use check on x2ap to consider the NSA scenario + if((is_x2ap_enabled() || get_softmodem_params()->sa) && (node_type != ngran_gNB_CUCP)) { if (itti_create_task (TASK_GTPV1_U, >pv1uTask, NULL) < 0) { LOG_E(GTPU, "Create task for GTPV1U failed\n"); return -1; @@ -503,7 +563,7 @@ void init_pdcp(void) { LINK_ENB_PDCP_TO_GTPV1U_BIT; if (!get_softmodem_params()->nsa) { - if (!NODE_IS_DU(RC.nrrrc[0]->node_type)) { + if (!NODE_IS_DU(get_node_type())) { pdcp_layer_init(); nr_pdcp_module_init(pdcp_initmask, 0); } @@ -581,7 +641,7 @@ int main( int argc, char **argv ) { // don't create if node doesn't connect to RRC/S1/GTP if (NFAPI_MODE != NFAPI_MODE_PNF) { - int ret = create_gNB_tasks(1); + int ret = create_gNB_tasks(); AssertFatal(ret == 0, "cannot create ITTI tasks\n"); } diff --git a/executables/nr-uesoftmodem.c b/executables/nr-uesoftmodem.c index 4aef4e56a3..1630ef8ef0 100644 --- a/executables/nr-uesoftmodem.c +++ b/executables/nr-uesoftmodem.c @@ -102,6 +102,8 @@ int config_sync_var=-1; instance_t CUuniqInstance=0; instance_t DUuniqInstance=0; +int get_node_type() {return -1;} + RAN_CONTEXT_t RC; int oai_exit = 0; diff --git a/openair1/SIMULATION/NR_PHY/dlsim.c b/openair1/SIMULATION/NR_PHY/dlsim.c index da5bbbffdf..9b6db46aa8 100644 --- a/openair1/SIMULATION/NR_PHY/dlsim.c +++ b/openair1/SIMULATION/NR_PHY/dlsim.c @@ -81,8 +81,6 @@ const char *__asan_default_options() return "detect_leaks=0"; } -LCHAN_DESC DCCH_LCHAN_DESC,DTCH_DL_LCHAN_DESC,DTCH_UL_LCHAN_DESC; - PHY_VARS_gNB *gNB; PHY_VARS_NR_UE *UE; RAN_CONTEXT_t RC; @@ -100,22 +98,6 @@ nfapi_ue_release_request_body_t release_rntis; //Fixme: Uniq dirty DU instance, by global var, datamodel need better management instance_t DUuniqInstance=0; instance_t CUuniqInstance=0; -teid_t newGtpuCreateTunnel(instance_t instance, - ue_id_t ue_id, - int incoming_bearer_id, - int outgoing_bearer_id, - teid_t outgoing_teid, - int qfi, - transport_layer_addr_t remoteAddr, - int port, - gtpCallback callBack, - gtpCallbackSDAP callBackSDAP) { - return 0; -} - -int newGtpuDeleteAllTunnels(instance_t instance, ue_id_t ue_id) { - return 0; -} // dummy functions int dummy_nr_ue_ul_indication(nr_uplink_indication_t *ul_info) { return(0); } @@ -158,59 +140,6 @@ rrc_data_ind( { } -int -gtpv1u_create_s1u_tunnel( - const instance_t instanceP, - const gtpv1u_enb_create_tunnel_req_t *const create_tunnel_req_pP, - gtpv1u_enb_create_tunnel_resp_t *const create_tunnel_resp_pP -) { - return 0; -} - -int -rrc_gNB_process_GTPV1U_CREATE_TUNNEL_RESP( - const protocol_ctxt_t *const ctxt_pP, - const gtpv1u_enb_create_tunnel_resp_t *const create_tunnel_resp_pP, - uint8_t *inde_list -) { - return 0; -} - -int -gtpv1u_create_ngu_tunnel( - const instance_t instanceP, - const gtpv1u_gnb_create_tunnel_req_t * const create_tunnel_req_pP, - gtpv1u_gnb_create_tunnel_resp_t * const create_tunnel_resp_pP){ - return 0; -} - -int -gtpv1u_update_ngu_tunnel( - const instance_t instanceP, - const gtpv1u_gnb_create_tunnel_req_t *const create_tunnel_req_pP, - const ue_id_t prior_ue_id -){ - return 0; -} - -int gtpv1u_delete_s1u_tunnel(const instance_t instance, const gtpv1u_enb_delete_tunnel_req_t *const req_pP) { - return 0; -} - -int gtpv1u_delete_ngu_tunnel( const instance_t instance, - gtpv1u_gnb_delete_tunnel_req_t *req) { - return 0; -} - -int -nr_rrc_gNB_process_GTPV1U_CREATE_TUNNEL_RESP( - const protocol_ctxt_t *const ctxt_pP, - const gtpv1u_gnb_create_tunnel_resp_t *const create_tunnel_resp_pP, - uint8_t *inde_list -){ - return 0; -} - int nr_derive_key(int alg_type, uint8_t alg_id, const uint8_t key[32], uint8_t **out) { diff --git a/openair1/SIMULATION/NR_PHY/prachsim.c b/openair1/SIMULATION/NR_PHY/prachsim.c index 29da33ac9a..1e211b7eb7 100644 --- a/openair1/SIMULATION/NR_PHY/prachsim.c +++ b/openair1/SIMULATION/NR_PHY/prachsim.c @@ -58,7 +58,9 @@ #define NR_PRACH_DEBUG 1 #define PRACH_WRITE_OUTPUT_DEBUG 1 -LCHAN_DESC DCCH_LCHAN_DESC,DTCH_DL_LCHAN_DESC,DTCH_UL_LCHAN_DESC; +THREAD_STRUCT thread_struct; +char *parallel_config = NULL; +char *worker_config = NULL; char *uecap_file; PHY_VARS_gNB *gNB; @@ -91,22 +93,6 @@ int oai_nfapi_nr_rach_indication(nfapi_nr_rach_indication_t *ind) { return(0); //Fixme: Uniq dirty DU instance, by global var, datamodel need better management instance_t DUuniqInstance=0; instance_t CUuniqInstance=0; -teid_t newGtpuCreateTunnel(instance_t instance, - ue_id_t ue_id, - int incoming_bearer_id, - int outgoing_bearer_id, - teid_t outgoing_teid, - int qfi, - transport_layer_addr_t remoteAddr, - int port, - gtpCallback callBack, - gtpCallbackSDAP callBackSDAP) { - return 0; -} - -int newGtpuDeleteAllTunnels(instance_t instance, ue_id_t ue_id) { - return 0; -} void rrc_data_ind( @@ -118,59 +104,6 @@ rrc_data_ind( { } -int -gtpv1u_create_s1u_tunnel( - const instance_t instanceP, - const gtpv1u_enb_create_tunnel_req_t *const create_tunnel_req_pP, - gtpv1u_enb_create_tunnel_resp_t *const create_tunnel_resp_pP -) { - return 0; -} - -int -rrc_gNB_process_GTPV1U_CREATE_TUNNEL_RESP( - const protocol_ctxt_t *const ctxt_pP, - const gtpv1u_enb_create_tunnel_resp_t *const create_tunnel_resp_pP, - uint8_t *inde_list -) { - return 0; -} - -int -gtpv1u_create_ngu_tunnel( - const instance_t instanceP, - const gtpv1u_gnb_create_tunnel_req_t * const create_tunnel_req_pP, - gtpv1u_gnb_create_tunnel_resp_t * const create_tunnel_resp_pP){ - return 0; -} - -int -gtpv1u_update_ngu_tunnel( - const instance_t instanceP, - const gtpv1u_gnb_create_tunnel_req_t *const create_tunnel_req_pP, - const ue_id_t prior_ue_id -){ - return 0; -} - -int gtpv1u_delete_s1u_tunnel(const instance_t instance, const gtpv1u_enb_delete_tunnel_req_t *const req_pP) { - return 0; -} - -int gtpv1u_delete_ngu_tunnel( const instance_t instance, - gtpv1u_gnb_delete_tunnel_req_t *req) { - return 0; -} - -int -nr_rrc_gNB_process_GTPV1U_CREATE_TUNNEL_RESP( - const protocol_ctxt_t *const ctxt_pP, - const gtpv1u_gnb_create_tunnel_resp_t *const create_tunnel_resp_pP, - uint8_t *inde_list -){ - return 0; -} - int8_t nr_mac_rrc_data_ind_ue(const module_id_t module_id, const int CC_id, const uint8_t gNB_index, diff --git a/openair1/SIMULATION/NR_PHY/ulsim.c b/openair1/SIMULATION/NR_PHY/ulsim.c index 374d85f72f..fefae6581d 100644 --- a/openair1/SIMULATION/NR_PHY/ulsim.c +++ b/openair1/SIMULATION/NR_PHY/ulsim.c @@ -76,8 +76,6 @@ const char *__asan_default_options() return "detect_leaks=0"; } -LCHAN_DESC DCCH_LCHAN_DESC,DTCH_DL_LCHAN_DESC,DTCH_UL_LCHAN_DESC; - PHY_VARS_gNB *gNB; PHY_VARS_NR_UE *UE; RAN_CONTEXT_t RC; @@ -96,22 +94,6 @@ nfapi_ue_release_request_body_t release_rntis; //Fixme: Uniq dirty DU instance, by global var, datamodel need better management instance_t DUuniqInstance=0; instance_t CUuniqInstance=0; -teid_t newGtpuCreateTunnel(instance_t instance, - ue_id_t ue_id, - int incoming_bearer_id, - int outgoing_bearer_id, - teid_t outgoing_teid, - int qfi, - transport_layer_addr_t remoteAddr, - int port, - gtpCallback callBack, - gtpCallbackSDAP callBackSDAP) { - return 0; -} - -int newGtpuDeleteAllTunnels(instance_t instance, ue_id_t ue_id) { - return 0; -} extern void fix_scd(NR_ServingCellConfig_t *scd);// forward declaration @@ -149,59 +131,6 @@ rrc_data_ind( } -int -gtpv1u_create_s1u_tunnel( - const instance_t instanceP, - const gtpv1u_enb_create_tunnel_req_t *const create_tunnel_req_pP, - gtpv1u_enb_create_tunnel_resp_t *const create_tunnel_resp_pP -) { - return 0; -} - -int gtpv1u_delete_s1u_tunnel(const instance_t instance, const gtpv1u_enb_delete_tunnel_req_t *const req_pP) { - return 0; -} - -int gtpv1u_delete_ngu_tunnel( const instance_t instance, - gtpv1u_gnb_delete_tunnel_req_t *req) { - return 0; -} - -int -rrc_gNB_process_GTPV1U_CREATE_TUNNEL_RESP( - const protocol_ctxt_t *const ctxt_pP, - const gtpv1u_enb_create_tunnel_resp_t *const create_tunnel_resp_pP, - uint8_t *inde_list -) { - return 0; -} - -int -gtpv1u_create_ngu_tunnel( - const instance_t instanceP, - const gtpv1u_gnb_create_tunnel_req_t * const create_tunnel_req_pP, - gtpv1u_gnb_create_tunnel_resp_t * const create_tunnel_resp_pP){ - return 0; -} - -int -gtpv1u_update_ngu_tunnel( - const instance_t instanceP, - const gtpv1u_gnb_create_tunnel_req_t *const create_tunnel_req_pP, - const ue_id_t prior_ue_id -){ - return 0; -} - -int -nr_rrc_gNB_process_GTPV1U_CREATE_TUNNEL_RESP( - const protocol_ctxt_t *const ctxt_pP, - const gtpv1u_gnb_create_tunnel_resp_t *const create_tunnel_resp_pP, - uint8_t *inde_list -){ - return 0; -} - // Dummy function to avoid linking error at compilation of nr-ulsim int is_x2ap_enabled(void) { diff --git a/openair2/COMMON/e1ap_messages_def.h b/openair2/COMMON/e1ap_messages_def.h new file mode 100644 index 0000000000..70533f8add --- /dev/null +++ b/openair2/COMMON/e1ap_messages_def.h @@ -0,0 +1,33 @@ +/* + * 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 + */ + +/* gNB_CUUP application layer -> E1AP messages */ +MESSAGE_DEF(E1AP_SETUP_REQ , MESSAGE_PRIORITY_MED , e1ap_setup_req_t , e1ap_setup_req) + +/* E1AP -> eNB_DU or eNB_CU_RRC -> E1AP application layer messages */ +MESSAGE_DEF(E1AP_SETUP_RESP , MESSAGE_PRIORITY_MED, e1ap_setup_resp_t , e1ap_setup_resp) + +MESSAGE_DEF(E1AP_BEARER_CONTEXT_SETUP_REQ , MESSAGE_PRIORITY_MED , e1ap_bearer_setup_req_t , e1ap_bearer_setup_req) + +MESSAGE_DEF(E1AP_BEARER_CONTEXT_SETUP_RESP , MESSAGE_PRIORITY_MED , e1ap_bearer_setup_resp_t , e1ap_bearer_setup_resp) + +MESSAGE_DEF(E1AP_BEARER_CONTEXT_MODIFICATION_REQ , MESSAGE_PRIORITY_MED , e1ap_bearer_setup_req_t , e1ap_bearer_mod_req) + diff --git a/openair2/COMMON/e1ap_messages_types.h b/openair2/COMMON/e1ap_messages_types.h new file mode 100644 index 0000000000..941d95b044 --- /dev/null +++ b/openair2/COMMON/e1ap_messages_types.h @@ -0,0 +1,226 @@ +/* + * 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 + * + * Author and copyright: Laurent Thomas, open-cells.com + * + * 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 E1AP_MESSAGES_TYPES_H +#define E1AP_MESSAGES_TYPES_H + +#include "f1ap_messages_types.h" +#include "ngap_messages_types.h" + +#define E1AP_MAX_NUM_TRANSAC_IDS 4 +#define E1AP_MAX_NUM_PLMNS 4 +#define E1AP_MAX_NUM_CELL_GROUPS 4 +#define E1AP_MAX_NUM_QOS_FLOWS 4 +#define E1AP_MAX_NUM_NGRAN_DRB 4 +#define E1AP_MAX_NUM_PDU_SESSIONS 4 +#define E1AP_MAX_NUM_DRBS 4 +#define E1AP_MAX_NUM_DRBS 4 +#define E1AP_MAX_NUM_UP_PARAM 4 + +#define E1AP_SETUP_REQ(mSGpTR) (mSGpTR)->ittiMsg.e1ap_setup_req +#define E1AP_SETUP_RESP(mSGpTR) (mSGpTR)->ittiMsg.e1ap_setup_resp +#define E1AP_BEARER_CONTEXT_SETUP_REQ(mSGpTR) (mSGpTR)->ittiMsg.e1ap_bearer_setup_req +#define E1AP_BEARER_CONTEXT_SETUP_RESP(mSGpTR) (mSGpTR)->ittiMsg.e1ap_bearer_setup_resp +#define E1AP_BEARER_CONTEXT_MODIFICATION_REQ(mSGpTR) (mSGpTR)->ittiMsg.e1ap_bearer_setup_req + +typedef f1ap_net_ip_address_t e1ap_net_ip_address_t; + +typedef struct PLMN_ID_s { + int mcc; + int mnc; + int mnc_digit_length; +} PLMN_ID_t; + +typedef struct e1ap_setup_req_s { + uint64_t gNB_cu_up_id; + char * gNB_cu_up_name; + int assoc_id; + uint64_t transac_id; + int supported_plmns; + PLMN_ID_t plmns[E1AP_MAX_NUM_PLMNS]; + uint16_t sctp_in_streams; + uint16_t sctp_out_streams; + uint16_t default_sctp_stream_id; + net_ip_address_t CUUP_e1_ip_address; + net_ip_address_t CUCP_e1_ip_address; + long cn_support; + uint16_t remotePortF1U; + char* localAddressF1U; + uint16_t localPortF1U; + char* localAddressN3; + uint16_t localPortN3; + uint16_t remotePortN3; +} e1ap_setup_req_t; + +typedef struct e1ap_setup_resp_s { + long transac_id; +} e1ap_setup_resp_t; + +typedef struct cell_group_s { + long id; +} cell_group_t; + +typedef struct up_params_s { + in_addr_t tlAddress; + long teId; + int cell_group_id; +} up_params_t; + +typedef struct drb_to_setup_s { + long drbId; + long pDCP_SN_Size_UL; + long pDCP_SN_Size_DL; + long rLC_Mode; + long qci; + long qosPriorityLevel; + long pre_emptionCapability; + long pre_emptionVulnerability; + in_addr_t tlAddress; + long teId; + int numCellGroups; + cell_group_t cellGroupList[E1AP_MAX_NUM_CELL_GROUPS]; +} drb_to_setup_t; + +typedef struct qos_flow_to_setup_s { + long id; + fiveQI_type_t fiveQI_type; + long fiveQI; + long qoSPriorityLevel; + long packetDelayBudget; + long packetError_scalar; + long packetError_exponent; + long priorityLevel; + long pre_emptionCapability; + long pre_emptionVulnerability; +} qos_flow_to_setup_t; + +typedef struct DRB_nGRAN_to_setup_s { + long id; + long defaultDRB; + long sDAP_Header_UL; + long sDAP_Header_DL; + long pDCP_SN_Size_UL; + long pDCP_SN_Size_DL; + long discardTimer; + long reorderingTimer; + long rLC_Mode; + in_addr_t tlAddress; + int teId; + int numDlUpParam; + up_params_t DlUpParamList[E1AP_MAX_NUM_UP_PARAM]; + int numCellGroups; + cell_group_t cellGroupList[E1AP_MAX_NUM_CELL_GROUPS]; + int numQosFlow2Setup; + qos_flow_to_setup_t qosFlows[E1AP_MAX_NUM_QOS_FLOWS]; +} DRB_nGRAN_to_setup_t; + +typedef struct pdu_session_to_setup_s { + long sessionId; + long sessionType; + int8_t sst; + long integrityProtectionIndication; + long confidentialityProtectionIndication; + in_addr_t tlAddress; + in_addr_t tlAddress_dl; + int32_t teId; + int32_t teId_dl; + int tl_port; + int tl_port_dl; + long numDRB2Setup; + DRB_nGRAN_to_setup_t DRBnGRanList[E1AP_MAX_NUM_NGRAN_DRB]; + long numDRB2Modify; + DRB_nGRAN_to_setup_t DRBnGRanModList[E1AP_MAX_NUM_NGRAN_DRB]; +} pdu_session_to_setup_t; + +typedef struct e1ap_bearer_setup_req_s { + uint32_t gNB_cu_cp_ue_id; + uint32_t gNB_cu_up_ue_id; + rnti_t rnti; + uint64_t cipheringAlgorithm; + uint64_t integrityProtectionAlgorithm; + char encryptionKey[128]; + char integrityProtectionKey[128]; + long ueDlAggMaxBitRate; + PLMN_ID_t servingPLMNid; + long activityNotificationLevel; + int numDRBs; + drb_to_setup_t DRBList[E1AP_MAX_NUM_DRBS]; + int numPDUSessions; + pdu_session_to_setup_t pduSession[E1AP_MAX_NUM_PDU_SESSIONS]; + int numPDUSessionsMod; + pdu_session_to_setup_t pduSessionMod[E1AP_MAX_NUM_PDU_SESSIONS]; +} e1ap_bearer_setup_req_t; + +typedef struct e1ap_bearer_release_cmd_s { + uint32_t gNB_cu_cp_ue_id; + uint32_t gNB_cu_up_ue_id; + long cause_type; + long cause; +} e1ap_bearer_release_cmd_t; + +typedef struct drb_setup_s { + int drbId; + in_addr_t tlAddress; + int teId; + int numUpParam; + up_params_t UpParamList[E1AP_MAX_NUM_UP_PARAM]; +} drb_setup_t; + +typedef struct qos_flow_setup_s { + long id; +} qos_flow_setup_t; + +typedef struct DRB_nGRAN_setup_s { + long id; + int numUpParam; + up_params_t UpParamList[E1AP_MAX_NUM_UP_PARAM]; + int numQosFlowSetup; + qos_flow_setup_t qosFlows[E1AP_MAX_NUM_QOS_FLOWS]; +} DRB_nGRAN_setup_t; + +typedef struct DRB_nGRAN_failed_s { + long id; + long cause_type; + long cause; +} DRB_nGRAN_failed_t; + +typedef struct pdu_session_setup_s { + long id; + in_addr_t tlAddress; + long teId; + int numDRBSetup; + DRB_nGRAN_setup_t DRBnGRanList[E1AP_MAX_NUM_NGRAN_DRB]; + int numDRBFailed; + DRB_nGRAN_failed_t DRBnGRanFailedList[E1AP_MAX_NUM_NGRAN_DRB]; +} pdu_session_setup_t; + +typedef struct e1ap_bearer_setup_resp_s { + uint64_t gNB_cu_cp_ue_id; + uint64_t gNB_cu_up_ue_id; + int numDRBs; + drb_setup_t DRBList[E1AP_MAX_NUM_DRBS]; + int numPDUSessions; + pdu_session_setup_t pduSession[E1AP_MAX_NUM_PDU_SESSIONS]; +} e1ap_bearer_setup_resp_t; + +#endif /* E1AP_MESSAGES_TYPES_H */ diff --git a/openair2/COMMON/gtpv1_u_messages_types.h b/openair2/COMMON/gtpv1_u_messages_types.h index 7c784a0c35..77e92f39bb 100644 --- a/openair2/COMMON/gtpv1_u_messages_types.h +++ b/openair2/COMMON/gtpv1_u_messages_types.h @@ -185,7 +185,7 @@ typedef struct gtpv1u_gnb_create_tunnel_resp_s { ue_id_t ue_id; int num_tunnels; teid_t gnb_NGu_teid[NR_GTPV1U_MAX_BEARERS_PER_UE]; ///< Tunnel Endpoint Identifier - pdusessionid_t pdusession_id[NR_GTPV1U_MAX_BEARERS_PER_UE]; + pdusessionid_t pdusession_id[NR_GTPV1U_MAX_BEARERS_PER_UE]; transport_layer_addr_t gnb_addr; } gtpv1u_gnb_create_tunnel_resp_t; typedef struct gtpv1u_gnb_delete_tunnel_req_s { diff --git a/openair2/COMMON/messages_def.h b/openair2/COMMON/messages_def.h index 394b40eeed..8334700dd0 100644 --- a/openair2/COMMON/messages_def.h +++ b/openair2/COMMON/messages_def.h @@ -41,3 +41,4 @@ #include "sctp_messages_def.h" #include "udp_messages_def.h" #include "gtpv1_u_messages_def.h" +#include "e1ap_messages_def.h" diff --git a/openair2/COMMON/ngap_messages_types.h b/openair2/COMMON/ngap_messages_types.h index 961599a9ed..70412e8368 100644 --- a/openair2/COMMON/ngap_messages_types.h +++ b/openair2/COMMON/ngap_messages_types.h @@ -274,9 +274,15 @@ typedef struct ngap_transport_layer_addr_s { dEST.length = sOURCE.length; \ } while (0) +typedef enum { + non_dynamic, + dynamic +} fiveQI_type_t; + typedef struct pdusession_level_qos_parameter_s { uint8_t qfi; uint64_t fiveQI; + fiveQI_type_t fiveQI_type; ngap_allocation_retention_priority_t allocation_retention_priority; } pdusession_level_qos_parameter_t; @@ -706,12 +712,21 @@ typedef struct ngap_pdusession_setup_req_s { /* gNB ue ngap id as initialized by NGAP layer */ uint32_t gNB_ue_ngap_id; + /* S-NSSAI */ + ngap_allowed_NSSAI_t allowed_nssai[8]; + /* Number of pdusession to be setup in the list */ uint8_t nb_pdusessions_tosetup; /* E RAB setup request */ pdusession_t pdusession_setup_params[NGAP_MAX_PDUSESSION]; + /* UE Uplink Aggregated Max Bitrates */ + uint64_t ueAggMaxBitRateUplink; + + /* UE Downlink Aggregated Max Bitrates */ + uint64_t ueAggMaxBitRateDownlink; + } ngap_pdusession_setup_req_t; typedef struct ngap_pdusession_setup_resp_s { diff --git a/openair2/E1AP/CMakeLists.txt b/openair2/E1AP/CMakeLists.txt index 89d87fe555..a8bacdd3fa 100644 --- a/openair2/E1AP/CMakeLists.txt +++ b/openair2/E1AP/CMakeLists.txt @@ -1,7 +1,7 @@ add_subdirectory(MESSAGES) -add_library(E1AP e1ap.c) -target_link_libraries(E1AP - PUBLIC asn1_e1ap - PRIVATE UTIL asn1_nr_rrc asn1_lte_rrc) -target_include_directories(E1AP PUBLIC ${CMAKE_CURRENT_DIR}) +add_library(e1ap e1ap.c e1ap_common.c e1ap_api.c) +target_link_libraries(e1ap + PUBLIC asn1_e1ap f1ap + PRIVATE asn1_nr_rrc asn1_lte_rrc asn1_f1ap UTIL e1_pdcp_if e1_if) +target_include_directories(e1ap PUBLIC ${CMAKE_CURRENT_DIR}) diff --git a/openair2/E1AP/e1ap.c b/openair2/E1AP/e1ap.c index b49f4d4ca1..52043602e2 100644 --- a/openair2/E1AP/e1ap.c +++ b/openair2/E1AP/e1ap.c @@ -22,48 +22,87 @@ */ #include "e1ap.h" +#include "e1ap_common.h" +#include "e1ap_api.h" +#include "gnb_config.h" +#include "openair2/SDAP/nr_sdap/nr_sdap_entity.h" +#include "openair3/UTILS/conversions.h" +#include "openair2/RRC/NR/MESSAGES/asn1_msg.h" +#include "common/openairinterface5g_limits.h" +#include "common/utils/LOG/log.h" +#include "openair2/F1AP/f1ap_common.h" +#include "e1ap_default_values.h" -int asn1_encoder_xer_print = 1; +#define E1AP_NUM_MSG_HANDLERS 14 +typedef int (*e1ap_message_processing_t)(e1ap_upcp_inst_t *inst, const E1AP_E1AP_PDU_t *message_p); +e1ap_message_processing_t e1ap_message_processing[E1AP_NUM_MSG_HANDLERS][3] = { -int e1ap_assoc_id(bool isCu, instance_t instance) { - return 0; + { 0, 0, 0 }, /* Reset */ + { 0, 0, 0 }, /* ErrorIndication */ + { 0, 0, 0 }, /* privateMessage */ + { e1apCUCP_handle_SETUP_REQUEST, e1apCUUP_handle_SETUP_RESPONSE, e1apCUUP_handle_SETUP_FAILURE }, /* gNBCUUPE1Setup */ + { 0, 0, 0 }, /* gNBCUCPE1Setup */ + { 0, 0, 0 }, /* gNBCUUPConfigurationUpdate */ + { 0, 0, 0 }, /* gNBCUCPConfigurationUpdate */ + { 0, 0, 0 }, /* E1Release */ + { e1apCUUP_handle_BEARER_CONTEXT_SETUP_REQUEST, e1apCUCP_handle_BEARER_CONTEXT_SETUP_RESPONSE, e1apCUCP_handle_BEARER_CONTEXT_SETUP_FAILURE }, /* bearerContextSetup */ + { e1apCUUP_handle_BEARER_CONTEXT_MODIFICATION_REQUEST, 0, 0 }, /* bearerContextModification */ + { 0, 0, 0 }, /* bearerContextModificationRequired */ + { e1apCUUP_handle_BEARER_CONTEXT_RELEASE_COMMAND, e1apCUCP_handle_BEARER_CONTEXT_RELEASE_COMPLETE, 0 }, /* bearerContextRelease */ + { 0, 0, 0 }, /* bearerContextReleaseRequired */ + { 0, 0, 0 } /* bearerContextInactivityNotification */ +}; + +const char *e1ap_direction2String(int e1ap_dir) { + static const char *e1ap_direction_String[] = { + "", /* Nothing */ + "Initiating message", /* initiating message */ + "Successfull outcome", /* successfull outcome */ + "UnSuccessfull outcome", /* successfull outcome */ + }; + return(e1ap_direction_String[e1ap_dir]); } -int e1ap_encode_send(bool isCu, instance_t instance, E1AP_E1AP_PDU_t *pdu, uint16_t stream, const char *func) { - DevAssert(pdu != NULL); +int e1ap_handle_message(instance_t instance, uint32_t assoc_id, + const uint8_t *const data, const uint32_t data_length) { + E1AP_E1AP_PDU_t pdu= {0}; + int ret; + DevAssert(data != NULL); - if (asn1_encoder_xer_print) { - LOG_E(E1AP, "----------------- ASN1 ENCODER PRINT START ----------------- \n"); - xer_fprint(stdout, &asn_DEF_E1AP_E1AP_PDU, pdu); - LOG_E(E1AP, "----------------- ASN1 ENCODER PRINT END----------------- \n"); + if (e1ap_decode_pdu(&pdu, data, data_length) < 0) { + LOG_E(E1AP, "Failed to decode PDU\n"); + return -1; } - - char errbuf[2048]; /* Buffer for error message */ - size_t errlen = sizeof(errbuf); /* Size of the buffer */ - int ret = asn_check_constraints(&asn_DEF_E1AP_E1AP_PDU, pdu, errbuf, &errlen); - - if(ret) { - fprintf(stderr, "%s: Constraint validation failed: %s\n", func, errbuf); - } - - void *buffer = NULL; - ssize_t encoded = aper_encode_to_new_buffer(&asn_DEF_E1AP_E1AP_PDU, 0, pdu, buffer); - - if (encoded < 0) { - LOG_E(E1AP, "%s: Failed to encode E1AP message\n", func); + const E1AP_ProcedureCode_t procedureCode = pdu.choice.initiatingMessage->procedureCode; + /* Checking procedure Code and direction of message */ + if ((procedureCode >= E1AP_NUM_MSG_HANDLERS) || (pdu.present > E1AP_E1AP_PDU_PR_unsuccessfulOutcome) || (pdu.present <= E1AP_E1AP_PDU_PR_NOTHING)) { + LOG_E(E1AP, "[SCTP %d] Either procedureCode %ld or direction %d exceed expected\n", assoc_id, procedureCode, pdu.present); + ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_E1AP_E1AP_PDU, &pdu); return -1; - } else { - MessageDef *message = itti_alloc_new_message(isCu?TASK_CUCP_E1:TASK_CUUP_E1, 0, SCTP_DATA_REQ); - sctp_data_req_t *s = &message->ittiMsg.sctp_data_req; - s->assoc_id = e1ap_assoc_id(isCu,instance); - s->buffer = buffer; - s->buffer_length = encoded; - s->stream = stream; - LOG_I(E1AP, "%s: Sending ITTI message to SCTP Task\n", func); - itti_send_msg_to_task(TASK_SCTP, instance, message); } - return encoded; + if (e1ap_message_processing[procedureCode][pdu.present - 1] == NULL) { + // No handler present. This can mean not implemented or no procedure for eNB (wrong direction). + LOG_E(E1AP, "[SCTP %d] No handler for procedureCode %ld in %s\n", assoc_id, procedureCode, e1ap_direction2String(pdu.present - 1)); + ret=-1; + } else { + /* Calling the right handler */ + LOG_I(E1AP, "Calling handler with instance %ld\n",instance); + ret = (*e1ap_message_processing[procedureCode][pdu.present - 1])(getCxtE1(instance), &pdu); + } + + ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_E1AP_E1AP_PDU, &pdu); + return ret; +} + +void e1_task_handle_sctp_data_ind(instance_t instance, sctp_data_ind_t *sctp_data_ind) +{ + int result; + DevAssert(sctp_data_ind != NULL); + e1ap_handle_message(instance, sctp_data_ind->assoc_id, + sctp_data_ind->buffer, sctp_data_ind->buffer_length); + result = itti_free(TASK_UNKNOWN, sctp_data_ind->buffer); + AssertFatal (result == EXIT_SUCCESS, "Failed to free memory (%d)!\n", result); } void e1ap_itti_send_sctp_close_association(bool isCu, instance_t instance) { @@ -73,14 +112,16 @@ void e1ap_itti_send_sctp_close_association(bool isCu, instance_t instance) { itti_send_msg_to_task(TASK_SCTP, instance, message); } -int e1ap_send_RESET(bool isCu, instance_t instance, E1AP_Reset_t *Reset) { +int e1ap_send_RESET(bool isCu, e1ap_setup_req_t *setupReq, E1AP_Reset_t *Reset) +{ AssertFatal(false,"Not implemented yet\n"); E1AP_E1AP_PDU_t pdu= {0}; - return e1ap_encode_send(isCu, instance, &pdu,0, __func__); + return e1ap_encode_send(isCu, setupReq, &pdu, 0, __func__); } int e1ap_send_RESET_ACKNOWLEDGE(instance_t instance, E1AP_Reset_t *Reset) { AssertFatal(false,"Not implemented yet\n"); + return -1; } int e1ap_handle_RESET(instance_t instance, @@ -88,6 +129,7 @@ int e1ap_handle_RESET(instance_t instance, uint32_t stream, E1AP_E1AP_PDU_t *pdu) { AssertFatal(false,"Not implemented yet\n"); + return -1; } int e1ap_handle_RESET_ACKNOWLEDGE(instance_t instance, @@ -95,6 +137,7 @@ int e1ap_handle_RESET_ACKNOWLEDGE(instance_t instance, uint32_t stream, E1AP_E1AP_PDU_t *pdu) { AssertFatal(false,"Not implemented yet\n"); + return -1; } /* @@ -105,10 +148,12 @@ int e1ap_handle_ERROR_INDICATION(instance_t instance, uint32_t stream, E1AP_E1AP_PDU_t *pdu) { AssertFatal(false,"Not implemented yet\n"); + return -1; } int e1ap_send_ERROR_INDICATION(instance_t instance, E1AP_ErrorIndication_t *ErrorIndication) { AssertFatal(false,"Not implemented yet\n"); + return -1; } @@ -116,74 +161,316 @@ int e1ap_send_ERROR_INDICATION(instance_t instance, E1AP_ErrorIndication_t *Erro E1 Setup: can be sent on both ways, to be refined */ -int e1apCUUP_send_SETUP_REQUEST(instance_t instance, E1AP_Reset_t *Reset) { - AssertFatal(false,"Not implemented yet\n"); +static void fill_SETUP_REQUEST(e1ap_setup_req_t *setup, E1AP_E1AP_PDU_t *pdu) +{ + /* Create */ + /* 0. pdu Type */ + pdu->present = E1AP_E1AP_PDU_PR_initiatingMessage; + asn1cCalloc(pdu->choice.initiatingMessage, initMsg); + initMsg->procedureCode = E1AP_ProcedureCode_id_gNB_CU_UP_E1Setup; + initMsg->criticality = E1AP_Criticality_reject; + initMsg->value.present = E1AP_InitiatingMessage__value_PR_GNB_CU_UP_E1SetupRequest; + E1AP_GNB_CU_UP_E1SetupRequest_t *e1SetupUP = &initMsg->value.choice.GNB_CU_UP_E1SetupRequest; + /* mandatory */ + /* c1. Transaction ID (integer value) */ + asn1cSequenceAdd(e1SetupUP->protocolIEs.list, E1AP_GNB_CU_UP_E1SetupRequestIEs_t, ieC1); + ieC1->id = E1AP_ProtocolIE_ID_id_TransactionID; + ieC1->criticality = E1AP_Criticality_reject; + ieC1->value.present = E1AP_GNB_CU_UP_E1SetupRequestIEs__value_PR_TransactionID; + setup->transac_id = E1AP_get_next_transaction_identifier(); + ieC1->value.choice.TransactionID = setup->transac_id; + LOG_I(E1AP, "Transaction ID of setup request %ld\n", setup->transac_id); + /* mandatory */ + /* c2. GNB_CU_ID (integer value) */ + asn1cSequenceAdd(e1SetupUP->protocolIEs.list, E1AP_GNB_CU_UP_E1SetupRequestIEs_t, ieC2); + ieC2->id = E1AP_ProtocolIE_ID_id_gNB_CU_UP_ID; + ieC2->criticality = E1AP_Criticality_reject; + ieC2->value.present = E1AP_GNB_CU_UP_E1SetupRequestIEs__value_PR_GNB_CU_UP_ID; + asn_int642INTEGER(&ieC2->value.choice.GNB_CU_UP_ID, setup->gNB_cu_up_id); + /* mandatory */ + /* c4. CN Support */ + asn1cSequenceAdd(e1SetupUP->protocolIEs.list, E1AP_GNB_CU_UP_E1SetupRequestIEs_t, ieC4); + ieC4->id = E1AP_ProtocolIE_ID_id_CNSupport; + ieC4->criticality = E1AP_Criticality_reject; + ieC4->value.present = E1AP_GNB_CU_UP_E1SetupRequestIEs__value_PR_CNSupport; + ieC4->value.choice.CNSupport = setup->cn_support; + + /* mandatory */ + /* c5. Supported PLMNs */ + asn1cSequenceAdd(e1SetupUP->protocolIEs.list, E1AP_GNB_CU_UP_E1SetupRequestIEs_t, ieC5); + ieC5->id = E1AP_ProtocolIE_ID_id_SupportedPLMNs; + ieC5->criticality = E1AP_Criticality_reject; + ieC5->value.present = E1AP_GNB_CU_UP_E1SetupRequestIEs__value_PR_SupportedPLMNs_List; + + int numSupportedPLMNs = setup->supported_plmns; + + for (int i=0; i < numSupportedPLMNs; i++) { + asn1cSequenceAdd(ieC5->value.choice.SupportedPLMNs_List.list, E1AP_SupportedPLMNs_Item_t, supportedPLMN); + /* 5.1 PLMN Identity */ + MCC_MNC_TO_PLMNID(setup->plmns[i].mcc, setup->plmns[i].mnc, setup->plmns[i].mnc_digit_length, &supportedPLMN->pLMN_Identity); + } } -int e1apCUCP_send_SETUP_RESPONSE(instance_t instance) { - AssertFatal(false,"Not implemented yet\n"); +static void fill_SETUP_RESPONSE(const e1ap_setup_resp_t *e1ap_setup_resp, E1AP_E1AP_PDU_t *pdu) +{ + /* Create */ + /* 0. pdu Type */ + pdu->present = E1AP_E1AP_PDU_PR_successfulOutcome; + asn1cCalloc(pdu->choice.successfulOutcome, initMsg); + initMsg->procedureCode = E1AP_ProcedureCode_id_gNB_CU_UP_E1Setup; + initMsg->criticality = E1AP_Criticality_reject; + initMsg->value.present = E1AP_SuccessfulOutcome__value_PR_GNB_CU_UP_E1SetupResponse; + E1AP_GNB_CU_UP_E1SetupResponse_t *out = &pdu->choice.successfulOutcome->value.choice.GNB_CU_UP_E1SetupResponse; + /* mandatory */ + /* c1. Transaction ID (integer value) */ + asn1cSequenceAdd(out->protocolIEs.list, E1AP_GNB_CU_UP_E1SetupResponseIEs_t, ieC1); + ieC1->id = E1AP_ProtocolIE_ID_id_TransactionID; + ieC1->criticality = E1AP_Criticality_reject; + ieC1->value.present = E1AP_GNB_CU_UP_E1SetupResponseIEs__value_PR_TransactionID; + ieC1->value.choice.TransactionID = e1ap_setup_resp->transac_id; } -int e1apCUCP_send_SETUP_FAILURE() { - AssertFatal(false,"Not implemented yet\n"); +void e1ap_send_SETUP_RESPONSE(instance_t inst, const e1ap_setup_resp_t *e1ap_setup_resp) +{ + AssertFatal(getCxtE1(inst), ""); + e1ap_setup_req_t *setupReq = &getCxtE1(inst)->setupReq; + E1AP_E1AP_PDU_t pdu = {0}; + fill_SETUP_RESPONSE(e1ap_setup_resp, &pdu); + e1ap_encode_send(getCxtE1(inst)->type, setupReq, &pdu, 0, __func__); } -int e1apCUCP_handle_SETUP_REQUEST(instance_t instance, - uint32_t assoc_id, - uint32_t stream, - E1AP_E1AP_PDU_t *pdu) { - AssertFatal(false,"Not implemented yet\n"); +static void fill_SETUP_FAILURE(long transac_id, E1AP_E1AP_PDU_t *pdu) +{ + /* Create */ + /* 0. pdu Type */ + pdu->present = E1AP_E1AP_PDU_PR_unsuccessfulOutcome; + asn1cCalloc(pdu->choice.unsuccessfulOutcome, initMsg); + initMsg->procedureCode = E1AP_ProcedureCode_id_gNB_CU_UP_E1Setup; + initMsg->criticality = E1AP_Criticality_reject; + initMsg->value.present = E1AP_UnsuccessfulOutcome__value_PR_GNB_CU_UP_E1SetupFailure; + E1AP_GNB_CU_UP_E1SetupFailure_t *out = &pdu->choice.unsuccessfulOutcome->value.choice.GNB_CU_UP_E1SetupFailure; + /* mandatory */ + /* c1. Transaction ID (integer value) */ + asn1cSequenceAdd(out->protocolIEs.list, E1AP_GNB_CU_UP_E1SetupFailureIEs_t, ieC1); + ieC1->id = E1AP_ProtocolIE_ID_id_TransactionID; + ieC1->criticality = E1AP_Criticality_reject; + ieC1->value.present = E1AP_GNB_CU_UP_E1SetupResponseIEs__value_PR_TransactionID; + ieC1->value.choice.TransactionID = transac_id; + /* mandatory */ + /* c2. cause (integer value) */ + asn1cSequenceAdd(out->protocolIEs.list, E1AP_GNB_CU_UP_E1SetupFailureIEs_t, ieC2); + ieC2->id = E1AP_ProtocolIE_ID_id_Cause; + ieC2->criticality = E1AP_Criticality_ignore; + ieC2->value.present = E1AP_GNB_CU_UP_E1SetupFailureIEs__value_PR_Cause; + ieC2->value.choice.Cause.present = E1AP_Cause_PR_radioNetwork; //choose this accordingly + ieC2->value.choice.Cause.choice.radioNetwork = E1AP_CauseRadioNetwork_unspecified; } -int e1apCUUP_handle_SETUP_RESPONSE(instance_t instance, - uint32_t assoc_id, - uint32_t stream, - E1AP_E1AP_PDU_t *pdu) { - AssertFatal(false,"Not implemented yet\n"); +void e1apCUCP_send_SETUP_FAILURE(e1ap_setup_req_t *setupReq, long transac_id) +{ + E1AP_E1AP_PDU_t pdu = {0}; + fill_SETUP_FAILURE(transac_id, &pdu); + e1ap_encode_send(CPtype, setupReq, &pdu, 0, __func__); } -int e1apCUUP_handle_SETUP_FAILURE(instance_t instance, - uint32_t assoc_id, - uint32_t stream, - E1AP_E1AP_PDU_t *pdu) { - AssertFatal(false,"Not implemented yet\n"); +void extract_SETUP_REQUEST(const E1AP_E1AP_PDU_t *pdu, + e1ap_setup_req_t *req) { + E1AP_GNB_CU_UP_E1SetupRequestIEs_t *ie; + E1AP_GNB_CU_UP_E1SetupRequest_t *in = &pdu->choice.initiatingMessage->value.choice.GNB_CU_UP_E1SetupRequest; + /* assoc_id */ + /* req->assoc_id = assoc_id; */ + + /* transac_id */ + F1AP_FIND_PROTOCOLIE_BY_ID(E1AP_GNB_CU_UP_E1SetupRequestIEs_t, ie, in, + E1AP_ProtocolIE_ID_id_TransactionID, true); + req->transac_id = ie->value.choice.TransactionID; + LOG_D(E1AP, "gNB CU UP E1 setup request transaction ID: %ld\n", req->transac_id); + + /* gNB CU UP ID */ + F1AP_FIND_PROTOCOLIE_BY_ID(E1AP_GNB_CU_UP_E1SetupRequestIEs_t, ie, in, + E1AP_ProtocolIE_ID_id_gNB_CU_UP_ID, true); + asn_INTEGER2ulong(&ie->value.choice.GNB_CU_UP_ID, &req->gNB_cu_up_id); + LOG_D(E1AP, "gNB CU UP ID: %ld\n", req->gNB_cu_up_id); + + /* CN Support */ + F1AP_FIND_PROTOCOLIE_BY_ID(E1AP_GNB_CU_UP_E1SetupRequestIEs_t, ie, in, + E1AP_ProtocolIE_ID_id_CNSupport, true); + req->cn_support = ie->value.choice.CNSupport; + LOG_D(E1AP, "E1ap CN support: %ld\n", req->cn_support); + + /* Supported PLMNs */ + F1AP_FIND_PROTOCOLIE_BY_ID(E1AP_GNB_CU_UP_E1SetupRequestIEs_t, ie, in, + E1AP_ProtocolIE_ID_id_SupportedPLMNs, true); + req->supported_plmns = ie->value.choice.SupportedPLMNs_List.list.count; + LOG_D(E1AP, "Number of supported PLMNs: %d\n", req->supported_plmns); + + for (int i=0; i < req->supported_plmns; i++) { + E1AP_SupportedPLMNs_Item_t *supported_plmn_item = (E1AP_SupportedPLMNs_Item_t *)(ie->value.choice.SupportedPLMNs_List.list.array[i]); + + /* PLMN Identity */ + PLMNID_TO_MCC_MNC(&supported_plmn_item->pLMN_Identity, + req->plmns[i].mcc, + req->plmns[i].mnc, + req->plmns[i].mnc_digit_length); + LOG_D(E1AP, "MCC: %d\nMNC: %d\n", req->plmns[i].mcc, req->plmns[i].mnc); + } +} + +int e1apCUCP_handle_SETUP_REQUEST(e1ap_upcp_inst_t *inst, const E1AP_E1AP_PDU_t *pdu) +{ + DevAssert(pdu != NULL); + extract_SETUP_REQUEST(pdu, &inst->setupReq); + /* Create ITTI message and send to queue */ + MessageDef *msg_p = itti_alloc_new_message(TASK_CUCP_E1, 0 /*unused by callee*/, E1AP_SETUP_REQ); + memcpy(&E1AP_SETUP_REQ(msg_p), &inst->setupReq, sizeof(e1ap_setup_req_t)); + + if (inst->setupReq.supported_plmns > 0) { + itti_send_msg_to_task(TASK_RRC_GNB, 0 /*unused by callee*/, msg_p); + } else { + e1apCUCP_send_SETUP_FAILURE(&inst->setupReq, inst->setupReq.transac_id); + itti_free(TASK_CUCP_E1, msg_p); + return -1; + } + + return 0; +} + +int e1apCUUP_handle_SETUP_RESPONSE(e1ap_upcp_inst_t *inst, const E1AP_E1AP_PDU_t *pdu) +{ + LOG_D(E1AP, "%s\n", __func__); + DevAssert(pdu->present == E1AP_E1AP_PDU_PR_successfulOutcome); + DevAssert(pdu->choice.successfulOutcome->procedureCode == E1AP_ProcedureCode_id_gNB_CU_UP_E1Setup); + DevAssert(pdu->choice.successfulOutcome->criticality == E1AP_Criticality_reject); + DevAssert(pdu->choice.successfulOutcome->value.present == E1AP_SuccessfulOutcome__value_PR_GNB_CU_UP_E1SetupResponse); + const E1AP_GNB_CU_UP_E1SetupResponse_t *in = &pdu->choice.successfulOutcome->value.choice.GNB_CU_UP_E1SetupResponse; + E1AP_GNB_CU_UP_E1SetupResponseIEs_t *ie; + + /* transac_id */ + long transaction_id; + long old_transaction_id = inst->setupReq.transac_id; + F1AP_FIND_PROTOCOLIE_BY_ID(E1AP_GNB_CU_UP_E1SetupResponseIEs_t, ie, in, + E1AP_ProtocolIE_ID_id_TransactionID, true); + transaction_id = ie->value.choice.TransactionID; + LOG_D(E1AP, "gNB CU UP E1 setup response transaction ID: %ld\n", transaction_id); + + if (old_transaction_id != transaction_id) + LOG_E(E1AP, "Transaction IDs do not match %ld != %ld\n", old_transaction_id, transaction_id); + + E1AP_free_transaction_identifier(transaction_id); + + /* do the required processing */ + + return 0; +} + +int e1apCUUP_handle_SETUP_FAILURE(e1ap_upcp_inst_t *inst, const E1AP_E1AP_PDU_t *pdu) +{ + E1AP_GNB_CU_UP_E1SetupFailureIEs_t *ie; + DevAssert(pdu != NULL); + E1AP_GNB_CU_UP_E1SetupFailure_t *in = &pdu->choice.unsuccessfulOutcome->value.choice.GNB_CU_UP_E1SetupFailure; + /* Transaction ID */ + F1AP_FIND_PROTOCOLIE_BY_ID(E1AP_GNB_CU_UP_E1SetupFailureIEs_t, ie, in, + E1AP_ProtocolIE_ID_id_TransactionID, true); + /* Cause */ + F1AP_FIND_PROTOCOLIE_BY_ID(E1AP_GNB_CU_UP_E1SetupFailureIEs_t, ie, in, + E1AP_ProtocolIE_ID_id_Cause, true); + + return 0; +} + +static void fill_CONFIGURATION_UPDATE(E1AP_E1AP_PDU_t *pdu) +{ + /* Create */ + /* 0. pdu Type */ + pdu->present = E1AP_E1AP_PDU_PR_initiatingMessage; + asn1cCalloc(pdu->choice.initiatingMessage, msg); + msg->procedureCode = E1AP_ProcedureCode_id_gNB_CU_UP_ConfigurationUpdate; + msg->criticality = E1AP_Criticality_reject; + msg->value.present = E1AP_InitiatingMessage__value_PR_GNB_CU_UP_ConfigurationUpdate; + E1AP_GNB_CU_UP_ConfigurationUpdate_t *out = &pdu->choice.initiatingMessage->value.choice.GNB_CU_UP_ConfigurationUpdate; + /* mandatory */ + /* c1. Transaction ID (integer value) */ + asn1cSequenceAdd(out->protocolIEs.list, E1AP_GNB_CU_UP_ConfigurationUpdateIEs_t, ieC1); + ieC1->id = E1AP_ProtocolIE_ID_id_TransactionID; + ieC1->criticality = E1AP_Criticality_reject; + ieC1->value.present = E1AP_GNB_CU_UP_ConfigurationUpdateIEs__value_PR_TransactionID; + ieC1->value.choice.TransactionID = 0;//get this from stored transaction IDs in CU + /* mandatory */ + /* c2. Supported PLMNs */ + asn1cSequenceAdd(out->protocolIEs.list, E1AP_GNB_CU_UP_ConfigurationUpdateIEs_t, ieC2); + ieC2->id = E1AP_ProtocolIE_ID_id_SupportedPLMNs; + ieC2->criticality = E1AP_Criticality_reject; + ieC2->value.present = E1AP_GNB_CU_UP_ConfigurationUpdateIEs__value_PR_SupportedPLMNs_List; + + int numSupportedPLMNs = 1; + + for (int i=0; i < numSupportedPLMNs; i++) { + asn1cSequenceAdd(ieC2->value.choice.SupportedPLMNs_List.list, E1AP_SupportedPLMNs_Item_t, supportedPLMN); + /* 5.1 PLMN Identity */ + OCTET_STRING_fromBuf(&supportedPLMN->pLMN_Identity, "OAI", strlen("OAI")); + } + + /* mandatory */ + /* c3. TNLA to remove list */ + asn1cSequenceAdd(out->protocolIEs.list, E1AP_GNB_CU_UP_ConfigurationUpdateIEs_t, ieC3); + ieC3->id = E1AP_ProtocolIE_ID_id_GNB_CU_UP_TNLA_To_Remove_List; + ieC3->criticality = E1AP_Criticality_reject; + ieC3->value.present = E1AP_GNB_CU_UP_ConfigurationUpdateIEs__value_PR_GNB_CU_UP_TNLA_To_Remove_List; + + int numTNLAtoRemoveList = 1; + + for (int i=0; i < numTNLAtoRemoveList; i++) { + asn1cSequenceAdd(ieC2->value.choice.GNB_CU_UP_TNLA_To_Remove_List.list, E1AP_GNB_CU_UP_TNLA_To_Remove_Item_t, TNLAtoRemove); + TNLAtoRemove->tNLAssociationTransportLayerAddress.present = E1AP_CP_TNL_Information_PR_endpoint_IP_Address; + TRANSPORT_LAYER_ADDRESS_IPv4_TO_BIT_STRING(1234, &TNLAtoRemove->tNLAssociationTransportLayerAddress.choice.endpoint_IP_Address); // TODO: correct me + } } /* E1 configuration update: can be sent in both ways, to be refined */ -int e1apCUUP_send_gNB_DU_CONFIGURATION_UPDATE(instance_t instance) { - AssertFatal(false,"Not implemented yet\n"); +void e1apCUUP_send_CONFIGURATION_UPDATE(e1ap_setup_req_t *setupReq) +{ + E1AP_E1AP_PDU_t pdu = {0}; + fill_CONFIGURATION_UPDATE(&pdu); + e1ap_encode_send(UPtype, setupReq, &pdu, 0, __func__); } -int e1apCUCP_send_gNB_DU_CONFIGURATION_FAILURE(instance_t instance) { +int e1apCUCP_send_gNB_DU_CONFIGURATION_FAILURE(e1ap_setup_req_t *setupReq) +{ AssertFatal(false,"Not implemented yet\n"); + return -1; } -int e1apCUCP_send_gNB_DU_CONFIGURATION_UPDATE_ACKNOWLEDGE(instance_t instance) { +int e1apCUCP_send_gNB_DU_CONFIGURATION_UPDATE_ACKNOWLEDGE(e1ap_setup_req_t *setupReq) +{ AssertFatal(false,"Not implemented yet\n"); + return -1; } -int e1apCUCP_handle_gNB_DU_CONFIGURATION_UPDATE(instance_t instance, - uint32_t assoc_id, - uint32_t stream, - E1AP_E1AP_PDU_t *pdu) { +int e1apCUCP_handle_CONFIGURATION_UPDATE(e1ap_setup_req_t *setupReq, E1AP_E1AP_PDU_t *pdu) +{ + /* + E1AP_GNB_CU_UP_E1SetupRequestIEs_t *ie; + DevAssert(pdu != NULL); + E1AP_GNB_CU_UP_E1SetupRequest_t *in = &pdu->choice.initiatingMessage->value.choice.GNB_CU_UP_E1SetupRequest; + */ + AssertFatal(false,"Not implemented yet\n"); + return -1; } -int e1apCUUP_handle_gNB_DU_CONFIGURATION_UPDATE_ACKNOWLEDGE(instance_t instance, - uint32_t assoc_id, - uint32_t stream, - E1AP_E1AP_PDU_t *pdu) { +int e1apCUUP_handle_gNB_DU_CONFIGURATION_UPDATE_ACKNOWLEDGE(e1ap_setup_req_t *setupReq, uint32_t assoc_id, uint32_t stream, E1AP_E1AP_PDU_t *pdu) +{ AssertFatal(false,"Not implemented yet\n"); + return -1; } -int e1apCUUP_handle_gNB_DU_CONFIGURATION_FAILURE(instance_t instance, - uint32_t assoc_id, - uint32_t stream, - E1AP_E1AP_PDU_t *pdu) { +int e1apCUUP_handle_gNB_DU_CONFIGURATION_FAILURE(e1ap_setup_req_t *setupReq, uint32_t assoc_id, uint32_t stream, E1AP_E1AP_PDU_t *pdu) +{ AssertFatal(false,"Not implemented yet\n"); + return -1; } /* @@ -192,10 +479,12 @@ int e1apCUUP_handle_gNB_DU_CONFIGURATION_FAILURE(instance_t instance, int e1ap_send_RELEASE_REQUEST(instance_t instance) { AssertFatal(false,"Not implemented yet\n"); + return -1; } int e1ap_send_RELEASE_ACKNOWLEDGE(instance_t instance) { AssertFatal(false,"Not implemented yet\n"); + return -1; } int e1ap_handle_RELEASE_REQUEST(instance_t instance, @@ -203,6 +492,7 @@ int e1ap_handle_RELEASE_REQUEST(instance_t instance, uint32_t stream, E1AP_E1AP_PDU_t *pdu) { AssertFatal(false,"Not implemented yet\n"); + return -1; } int e1ap_handle_RELEASE_ACKNOWLEDGE(instance_t instance, @@ -210,66 +500,750 @@ int e1ap_handle_RELEASE_ACKNOWLEDGE(instance_t instance, uint32_t stream, E1AP_E1AP_PDU_t *pdu) { AssertFatal(false,"Not implemented yet\n"); + return -1; } /* BEARER CONTEXT SETUP REQUEST */ -int e1apCUCP_send_BEARER_CONTEXT_SETUP_REQUEST(instance_t instance) { - AssertFatal(false,"Not implemented yet\n"); +static int fill_BEARER_CONTEXT_SETUP_REQUEST(e1ap_setup_req_t *setup, e1ap_bearer_setup_req_t *const bearerCxt, E1AP_E1AP_PDU_t *pdu) +{ + pdu->present = E1AP_E1AP_PDU_PR_initiatingMessage; + asn1cCalloc(pdu->choice.initiatingMessage, msg); + msg->procedureCode = E1AP_ProcedureCode_id_bearerContextSetup; + msg->criticality = E1AP_Criticality_reject; + msg->value.present = E1AP_InitiatingMessage__value_PR_BearerContextSetupRequest; + E1AP_BearerContextSetupRequest_t *out = &pdu->choice.initiatingMessage->value.choice.BearerContextSetupRequest; + /* mandatory */ + /* c1. gNB-CU-UP UE E1AP ID */ + asn1cSequenceAdd(out->protocolIEs.list, E1AP_BearerContextSetupRequestIEs_t, ieC1); + ieC1->id = E1AP_ProtocolIE_ID_id_gNB_CU_CP_UE_E1AP_ID; + ieC1->criticality = E1AP_Criticality_reject; + ieC1->value.present = E1AP_BearerContextSetupRequestIEs__value_PR_GNB_CU_CP_UE_E1AP_ID; + ieC1->value.choice.GNB_CU_CP_UE_E1AP_ID = bearerCxt->gNB_cu_cp_ue_id; + /* mandatory */ + /* c2. Security Information */ + asn1cSequenceAdd(out->protocolIEs.list, E1AP_BearerContextSetupRequestIEs_t, ieC2); + ieC2->id = E1AP_ProtocolIE_ID_id_SecurityInformation; + ieC2->criticality = E1AP_Criticality_reject; + ieC2->value.present = E1AP_BearerContextSetupRequestIEs__value_PR_SecurityInformation; + ieC2->value.choice.SecurityInformation.securityAlgorithm.cipheringAlgorithm = bearerCxt->cipheringAlgorithm; + OCTET_STRING_fromBuf(&ieC2->value.choice.SecurityInformation.uPSecuritykey.encryptionKey, + bearerCxt->encryptionKey, strlen(bearerCxt->encryptionKey)); + + asn1cCallocOne(ieC2->value.choice.SecurityInformation.securityAlgorithm.integrityProtectionAlgorithm, bearerCxt->integrityProtectionAlgorithm); + asn1cCalloc(ieC2->value.choice.SecurityInformation.uPSecuritykey.integrityProtectionKey, protKey); + OCTET_STRING_fromBuf(protKey, bearerCxt->integrityProtectionKey, strlen(bearerCxt->integrityProtectionKey)); + /* mandatory */ + /* c3. UE DL Aggregate Maximum Bit Rate */ + asn1cSequenceAdd(out->protocolIEs.list, E1AP_BearerContextSetupRequestIEs_t, ieC3); + ieC3->id = E1AP_ProtocolIE_ID_id_UEDLAggregateMaximumBitRate; + ieC3->criticality = E1AP_Criticality_reject; + ieC3->value.present = E1AP_BearerContextSetupRequestIEs__value_PR_BitRate; + asn_long2INTEGER(&ieC3->value.choice.BitRate, bearerCxt->ueDlAggMaxBitRate); + /* mandatory */ + /* c4. Serving PLMN */ + asn1cSequenceAdd(out->protocolIEs.list, E1AP_BearerContextSetupRequestIEs_t, ieC4); + ieC4->id = E1AP_ProtocolIE_ID_id_Serving_PLMN; + ieC4->criticality = E1AP_Criticality_ignore; + ieC4->value.present = E1AP_BearerContextSetupRequestIEs__value_PR_PLMN_Identity; + PLMN_ID_t *servingPLMN = setup->plmns; // First PLMN is serving PLMN. TODO: Remove hard coding here + MCC_MNC_TO_PLMNID(servingPLMN->mcc, servingPLMN->mnc, servingPLMN->mnc_digit_length, &ieC4->value.choice.PLMN_Identity); + /* mandatory */ + /* Activity Notification Level */ + asn1cSequenceAdd(out->protocolIEs.list, E1AP_BearerContextSetupRequestIEs_t, ieC5); + ieC5->id = E1AP_ProtocolIE_ID_id_ActivityNotificationLevel; + ieC5->criticality = E1AP_Criticality_reject; + ieC5->value.present = E1AP_BearerContextSetupRequestIEs__value_PR_ActivityNotificationLevel; + ieC5->value.choice.ActivityNotificationLevel = E1AP_ActivityNotificationLevel_pdu_session;// TODO: Remove hard coding + /* mandatory */ + /* */ + asn1cSequenceAdd(out->protocolIEs.list, E1AP_BearerContextSetupRequestIEs_t, ieC6); + ieC6->id = E1AP_ProtocolIE_ID_id_System_BearerContextSetupRequest; + ieC6->criticality = E1AP_Criticality_reject; + ieC6->value.present = E1AP_BearerContextSetupRequestIEs__value_PR_System_BearerContextSetupRequest; + ieC6->value.choice.System_BearerContextSetupRequest.present = E1AP_System_BearerContextSetupRequest_PR_nG_RAN_BearerContextSetupRequest; + E1AP_ProtocolIE_Container_4932P19_t *msgNGRAN_list = calloc(1, sizeof(E1AP_ProtocolIE_Container_4932P19_t)); + ieC6->value.choice.System_BearerContextSetupRequest.choice.nG_RAN_BearerContextSetupRequest = (struct E1AP_ProtocolIE_Container *) msgNGRAN_list; + asn1cSequenceAdd(msgNGRAN_list->list, E1AP_NG_RAN_BearerContextSetupRequest_t, msgNGRAN); + msgNGRAN->id = E1AP_ProtocolIE_ID_id_PDU_Session_Resource_To_Setup_List; + msgNGRAN->criticality = E1AP_Criticality_reject; + msgNGRAN->value.present = E1AP_NG_RAN_BearerContextSetupRequest__value_PR_PDU_Session_Resource_To_Setup_List; + E1AP_PDU_Session_Resource_To_Setup_List_t *pdu2Setup = &msgNGRAN->value.choice.PDU_Session_Resource_To_Setup_List; + for(pdu_session_to_setup_t *i=bearerCxt->pduSession; i < bearerCxt->pduSession+bearerCxt->numPDUSessions; i++) { + asn1cSequenceAdd(pdu2Setup->list, E1AP_PDU_Session_Resource_To_Setup_Item_t, ieC6_1); + ieC6_1->pDU_Session_ID = i->sessionId; + ieC6_1->pDU_Session_Type = i->sessionType; + + INT8_TO_OCTET_STRING(i->sst, &ieC6_1->sNSSAI.sST); + + ieC6_1->securityIndication.integrityProtectionIndication = i->integrityProtectionIndication; + ieC6_1->securityIndication.confidentialityProtectionIndication = i->confidentialityProtectionIndication; + + ieC6_1->nG_UL_UP_TNL_Information.present = E1AP_UP_TNL_Information_PR_gTPTunnel; + asn1cCalloc(ieC6_1->nG_UL_UP_TNL_Information.choice.gTPTunnel, gTPTunnel); + TRANSPORT_LAYER_ADDRESS_IPv4_TO_BIT_STRING(i->tlAddress, &gTPTunnel->transportLayerAddress); + INT32_TO_OCTET_STRING(i->teId, &gTPTunnel->gTP_TEID); + + for (DRB_nGRAN_to_setup_t *j=i->DRBnGRanList; j < i->DRBnGRanList+i->numDRB2Setup; j++) { + asn1cSequenceAdd(ieC6_1->dRB_To_Setup_List_NG_RAN.list, E1AP_DRB_To_Setup_Item_NG_RAN_t, ieC6_1_1); + ieC6_1_1->dRB_ID = j->id; + + ieC6_1_1->sDAP_Configuration.defaultDRB = j->defaultDRB; + ieC6_1_1->sDAP_Configuration.sDAP_Header_UL = j->sDAP_Header_UL; + ieC6_1_1->sDAP_Configuration.sDAP_Header_DL = j->sDAP_Header_DL; + + ieC6_1_1->pDCP_Configuration.pDCP_SN_Size_UL = j->pDCP_SN_Size_UL; + ieC6_1_1->pDCP_Configuration.pDCP_SN_Size_DL = j->pDCP_SN_Size_DL; + asn1cCallocOne(ieC6_1_1->pDCP_Configuration.discardTimer, j->discardTimer); + E1AP_T_ReorderingTimer_t *roTimer = calloc(1, sizeof(E1AP_T_ReorderingTimer_t)); + ieC6_1_1->pDCP_Configuration.t_ReorderingTimer = roTimer; + roTimer->t_Reordering = j->reorderingTimer; + ieC6_1_1->pDCP_Configuration.rLC_Mode = j->rLC_Mode; + + for (cell_group_t *k=j->cellGroupList; k < j->cellGroupList+j->numCellGroups; k++) { + asn1cSequenceAdd(ieC6_1_1->cell_Group_Information.list, E1AP_Cell_Group_Information_Item_t, ieC6_1_1_1); + ieC6_1_1_1->cell_Group_ID = k->id; + } + + for (qos_flow_to_setup_t *k=j->qosFlows; k < j->qosFlows+j->numQosFlow2Setup; k++) { + asn1cSequenceAdd(ieC6_1_1->qos_flow_Information_To_Be_Setup, E1AP_QoS_Flow_QoS_Parameter_Item_t, ieC6_1_1_1); + ieC6_1_1_1->qoS_Flow_Identifier = k->id; + + if (k->fiveQI_type == non_dynamic) { // non Dynamic 5QI + ieC6_1_1_1->qoSFlowLevelQoSParameters.qoS_Characteristics.present = E1AP_QoS_Characteristics_PR_non_Dynamic_5QI; + asn1cCalloc(ieC6_1_1_1->qoSFlowLevelQoSParameters.qoS_Characteristics.choice.non_Dynamic_5QI, non_Dynamic_5QI); + non_Dynamic_5QI->fiveQI = k->fiveQI; + } else { // dynamic 5QI + ieC6_1_1_1->qoSFlowLevelQoSParameters.qoS_Characteristics.present = E1AP_QoS_Characteristics_PR_dynamic_5QI; + asn1cCalloc(ieC6_1_1_1->qoSFlowLevelQoSParameters.qoS_Characteristics.choice.dynamic_5QI, dynamic_5QI); + dynamic_5QI->qoSPriorityLevel = k->qoSPriorityLevel; + dynamic_5QI->packetDelayBudget = k->packetDelayBudget; + dynamic_5QI->packetErrorRate.pER_Scalar = k->packetError_scalar; + dynamic_5QI->packetErrorRate.pER_Exponent = k->packetError_exponent; + } + + ieC6_1_1_1->qoSFlowLevelQoSParameters.nGRANallocationRetentionPriority.priorityLevel = k->priorityLevel; + ieC6_1_1_1->qoSFlowLevelQoSParameters.nGRANallocationRetentionPriority.pre_emptionCapability = k->pre_emptionCapability; + ieC6_1_1_1->qoSFlowLevelQoSParameters.nGRANallocationRetentionPriority.pre_emptionVulnerability = k->pre_emptionVulnerability; + } + } + } + return 0; } -int e1apCUUP_send_BEARER_CONTEXT_SETUP_RESPONSE(instance_t instance) { - AssertFatal(false,"Not implemented yet\n"); +void e1apCUCP_send_BEARER_CONTEXT_SETUP_REQUEST(instance_t instance, e1ap_bearer_setup_req_t *const bearerCxt) +{ + if (!getCxtE1(instance)) { + LOG_E(E1AP, "Received a UE bearer to establish while no CU-UP is connected, response on NGAP to send failure is not developped\n"); + // Fixme: add response on NGAP to send failure + return; + } + + E1AP_E1AP_PDU_t pdu = {0}; + e1ap_setup_req_t *setupReq = &getCxtE1(instance)->setupReq; + fill_BEARER_CONTEXT_SETUP_REQUEST(setupReq, bearerCxt, &pdu); + e1ap_encode_send(CPtype, setupReq, &pdu, 0, __func__); +} + +static void fill_BEARER_CONTEXT_SETUP_RESPONSE(e1ap_bearer_setup_resp_t *const resp, E1AP_E1AP_PDU_t *pdu) +{ + /* Create */ + /* 0. pdu Type */ + pdu->present = E1AP_E1AP_PDU_PR_successfulOutcome; + asn1cCalloc(pdu->choice.successfulOutcome, msg); + msg->procedureCode = E1AP_ProcedureCode_id_bearerContextSetup; + msg->criticality = E1AP_Criticality_reject; + msg->value.present = E1AP_SuccessfulOutcome__value_PR_BearerContextSetupResponse; + E1AP_BearerContextSetupResponse_t *out = &pdu->choice.successfulOutcome->value.choice.BearerContextSetupResponse; + /* mandatory */ + /* c1. gNB-CU-CP UE E1AP ID */ + asn1cSequenceAdd(out->protocolIEs.list, E1AP_BearerContextSetupResponseIEs_t, ieC1); + ieC1->id = E1AP_ProtocolIE_ID_id_gNB_CU_CP_UE_E1AP_ID; + ieC1->criticality = E1AP_Criticality_reject; + ieC1->value.present = E1AP_BearerContextSetupResponseIEs__value_PR_GNB_CU_CP_UE_E1AP_ID; + ieC1->value.choice.GNB_CU_CP_UE_E1AP_ID = resp->gNB_cu_cp_ue_id; + /* mandatory */ + /* c2. gNB-CU-UP UE E1AP ID */ + asn1cSequenceAdd(out->protocolIEs.list, E1AP_BearerContextSetupResponseIEs_t, ieC2); + ieC2->id = E1AP_ProtocolIE_ID_id_gNB_CU_UP_UE_E1AP_ID; + ieC2->criticality = E1AP_Criticality_reject; + ieC2->value.present = E1AP_BearerContextSetupResponseIEs__value_PR_GNB_CU_UP_UE_E1AP_ID; + ieC2->value.choice.GNB_CU_CP_UE_E1AP_ID = resp->gNB_cu_up_ue_id; + + asn1cSequenceAdd(out->protocolIEs.list, E1AP_BearerContextSetupResponseIEs_t, ieC3); + ieC3->id = E1AP_ProtocolIE_ID_id_System_BearerContextSetupResponse; + ieC3->criticality = E1AP_Criticality_reject; + ieC3->value.present = E1AP_BearerContextSetupResponseIEs__value_PR_System_BearerContextSetupResponse; + if (0) { // EUTRAN + ieC3->value.choice.System_BearerContextSetupResponse.present = E1AP_System_BearerContextSetupResponse_PR_e_UTRAN_BearerContextSetupResponse; + E1AP_ProtocolIE_Container_4932P21_t *msgEUTRAN_list = calloc(1, sizeof(E1AP_ProtocolIE_Container_4932P21_t)); + ieC3->value.choice.System_BearerContextSetupResponse.choice.e_UTRAN_BearerContextSetupResponse = (struct E1AP_ProtocolIE_Container *) msgEUTRAN_list; + asn1cSequenceAdd(msgEUTRAN_list->list, E1AP_EUTRAN_BearerContextSetupResponse_t, msgEUTRAN); + msgEUTRAN->id = E1AP_ProtocolIE_ID_id_DRB_Setup_List_EUTRAN; + msgEUTRAN->criticality = E1AP_Criticality_reject; + msgEUTRAN->value.present = E1AP_EUTRAN_BearerContextSetupResponse__value_PR_DRB_Setup_List_EUTRAN; + E1AP_DRB_Setup_List_EUTRAN_t *drbSetup = &msgEUTRAN->value.choice.DRB_Setup_List_EUTRAN; + + for (drb_setup_t *i=resp->DRBList; i < resp->DRBList+resp->numDRBs; i++) { + asn1cSequenceAdd(drbSetup->list, E1AP_DRB_Setup_Item_EUTRAN_t, ieC3_1); + ieC3_1->dRB_ID = i->drbId; + + ieC3_1->s1_DL_UP_TNL_Information.present = E1AP_UP_TNL_Information_PR_gTPTunnel; + asn1cCalloc(ieC3_1->s1_DL_UP_TNL_Information.choice.gTPTunnel, gTPTunnel); + TRANSPORT_LAYER_ADDRESS_IPv4_TO_BIT_STRING(i->tlAddress, &gTPTunnel->transportLayerAddress); + INT32_TO_OCTET_STRING(i->teId, &gTPTunnel->gTP_TEID); + + for (up_params_t *j=i->UpParamList; j < i->UpParamList+i->numUpParam; j++) { + asn1cSequenceAdd(ieC3_1->uL_UP_Transport_Parameters.list, E1AP_UP_Parameters_Item_t, ieC3_1_1); + ieC3_1_1->uP_TNL_Information.present = E1AP_UP_TNL_Information_PR_gTPTunnel; + asn1cCalloc(ieC3_1_1->uP_TNL_Information.choice.gTPTunnel, gTPTunnel); + TRANSPORT_LAYER_ADDRESS_IPv4_TO_BIT_STRING(j->tlAddress, &gTPTunnel->transportLayerAddress); + INT32_TO_OCTET_STRING(j->teId, &gTPTunnel->gTP_TEID); + } + } + } else { + ieC3->value.choice.System_BearerContextSetupResponse.present = E1AP_System_BearerContextSetupResponse_PR_nG_RAN_BearerContextSetupResponse; + E1AP_ProtocolIE_Container_4932P22_t *msgNGRAN_list = calloc(1, sizeof(E1AP_ProtocolIE_Container_4932P22_t)); + ieC3->value.choice.System_BearerContextSetupResponse.choice.nG_RAN_BearerContextSetupResponse = (struct E1AP_ProtocolIE_Container *) msgNGRAN_list; + asn1cSequenceAdd(msgNGRAN_list->list, E1AP_NG_RAN_BearerContextSetupResponse_t, msgNGRAN); + msgNGRAN->id = E1AP_ProtocolIE_ID_id_PDU_Session_Resource_Setup_List; + msgNGRAN->criticality = E1AP_Criticality_reject; + msgNGRAN->value.present = E1AP_NG_RAN_BearerContextSetupResponse__value_PR_PDU_Session_Resource_Setup_List; + E1AP_PDU_Session_Resource_Setup_List_t *pduSetup = &msgNGRAN->value.choice.PDU_Session_Resource_Setup_List; + + for (pdu_session_setup_t *i=resp->pduSession; i < resp->pduSession+resp->numPDUSessions; i++) { + asn1cSequenceAdd(pduSetup->list, E1AP_PDU_Session_Resource_Setup_Item_t, ieC3_1); + ieC3_1->pDU_Session_ID = i->id; + + ieC3_1->nG_DL_UP_TNL_Information.present = E1AP_UP_TNL_Information_PR_gTPTunnel; + asn1cCalloc(ieC3_1->nG_DL_UP_TNL_Information.choice.gTPTunnel, gTPTunnel); + TRANSPORT_LAYER_ADDRESS_IPv4_TO_BIT_STRING(i->tlAddress, &gTPTunnel->transportLayerAddress); + INT32_TO_OCTET_STRING(i->teId, &gTPTunnel->gTP_TEID); + + for (DRB_nGRAN_setup_t *j=i->DRBnGRanList; j < i->DRBnGRanList+i->numDRBSetup; j++) { + asn1cSequenceAdd(ieC3_1->dRB_Setup_List_NG_RAN.list, E1AP_DRB_Setup_Item_NG_RAN_t, ieC3_1_1); + ieC3_1_1->dRB_ID = j->id; + + for (up_params_t *k=j->UpParamList; k < j->UpParamList+j->numUpParam; k++) { + asn1cSequenceAdd(ieC3_1_1->uL_UP_Transport_Parameters.list, E1AP_UP_Parameters_Item_t, ieC3_1_1_1); + ieC3_1_1_1->uP_TNL_Information.present = E1AP_UP_TNL_Information_PR_gTPTunnel; + asn1cCalloc(ieC3_1_1_1->uP_TNL_Information.choice.gTPTunnel, gTPTunnel); + TRANSPORT_LAYER_ADDRESS_IPv4_TO_BIT_STRING(k->tlAddress, &gTPTunnel->transportLayerAddress); + INT32_TO_OCTET_STRING(k->teId, &gTPTunnel->gTP_TEID); + } + + for (qos_flow_setup_t *k=j->qosFlows; k < j->qosFlows+j->numQosFlowSetup; k++) { + asn1cSequenceAdd(ieC3_1_1->flow_Setup_List.list, E1AP_QoS_Flow_Item_t, ieC3_1_1_1); + ieC3_1_1_1->qoS_Flow_Identifier = k->id; + } + } + + if (i->numDRBFailed > 0) + ieC3_1->dRB_Failed_List_NG_RAN = calloc(1, sizeof(E1AP_DRB_Failed_List_NG_RAN_t)); + + for (DRB_nGRAN_failed_t *j=i->DRBnGRanFailedList; j < i->DRBnGRanFailedList+i->numDRBFailed; j++) { + asn1cSequenceAdd(ieC3_1->dRB_Failed_List_NG_RAN->list, E1AP_DRB_Failed_Item_NG_RAN_t, ieC3_1_1); + ieC3_1_1->dRB_ID = j->id; + + ieC3_1_1->cause.present = j->cause_type; + switch (ieC3_1_1->cause.present) { + case E1AP_Cause_PR_radioNetwork: + ieC3_1_1->cause.choice.radioNetwork = j->cause; + break; + + case E1AP_Cause_PR_transport: + ieC3_1_1->cause.choice.transport = j->cause; + break; + + case E1AP_Cause_PR_protocol: + ieC3_1_1->cause.choice.protocol = j->cause; + break; + + case E1AP_Cause_PR_misc: + ieC3_1_1->cause.choice.misc = j->cause; + break; + + default: + LOG_E(E1AP, "DRB setup failure cause out of expected range\n"); + break; + } + } + } + } +} + +void e1apCUUP_send_BEARER_CONTEXT_SETUP_RESPONSE(e1ap_upcp_inst_t *inst, e1ap_bearer_setup_resp_t *const resp) +{ + E1AP_E1AP_PDU_t pdu = {0}; + fill_BEARER_CONTEXT_SETUP_RESPONSE(resp, &pdu); + e1ap_encode_send(UPtype, &inst->setupReq, &pdu, 0, __func__); } int e1apCUUP_send_BEARER_CONTEXT_SETUP_FAILURE(instance_t instance) { AssertFatal(false,"Not implemented yet\n"); + return -1; } -int e1apCUUP_handle_BEARER_CONTEXT_SETUP_REQUEST(instance_t instance, - uint32_t assoc_id, - uint32_t stream, - E1AP_E1AP_PDU_t *pdu) { - AssertFatal(false,"Not implemented yet\n"); +void extract_BEARER_CONTEXT_SETUP_REQUEST(const E1AP_E1AP_PDU_t *pdu, + e1ap_bearer_setup_req_t *bearerCxt) { + const E1AP_BearerContextSetupRequest_t *in = &pdu->choice.initiatingMessage->value.choice.BearerContextSetupRequest; + E1AP_BearerContextSetupRequestIEs_t *ie; + + LOG_I(E1AP, "Bearer context setup number of IEs %d\n", in->protocolIEs.list.count); + + for (int i=0; i < in->protocolIEs.list.count; i++) { + ie = in->protocolIEs.list.array[i]; + + switch(ie->id) { + case E1AP_ProtocolIE_ID_id_gNB_CU_CP_UE_E1AP_ID: + DevAssert(ie->criticality == E1AP_Criticality_reject); + DevAssert(ie->value.present == E1AP_BearerContextSetupRequestIEs__value_PR_GNB_CU_CP_UE_E1AP_ID); + bearerCxt->gNB_cu_cp_ue_id = ie->value.choice.GNB_CU_CP_UE_E1AP_ID; + break; + + case E1AP_ProtocolIE_ID_id_SecurityInformation: + DevAssert(ie->criticality == E1AP_Criticality_reject); + DevAssert(ie->value.present == E1AP_BearerContextSetupRequestIEs__value_PR_SecurityInformation); + bearerCxt->cipheringAlgorithm = ie->value.choice.SecurityInformation.securityAlgorithm.cipheringAlgorithm; + memcpy(bearerCxt->encryptionKey, + ie->value.choice.SecurityInformation.uPSecuritykey.encryptionKey.buf, + ie->value.choice.SecurityInformation.uPSecuritykey.encryptionKey.size); + if (ie->value.choice.SecurityInformation.securityAlgorithm.integrityProtectionAlgorithm) { + bearerCxt->integrityProtectionAlgorithm = *ie->value.choice.SecurityInformation.securityAlgorithm.integrityProtectionAlgorithm; + } + if (ie->value.choice.SecurityInformation.uPSecuritykey.integrityProtectionKey) { + memcpy(bearerCxt->integrityProtectionKey, + ie->value.choice.SecurityInformation.uPSecuritykey.integrityProtectionKey->buf, + ie->value.choice.SecurityInformation.uPSecuritykey.integrityProtectionKey->size); + } + break; + + case E1AP_ProtocolIE_ID_id_UEDLAggregateMaximumBitRate: + DevAssert(ie->criticality == E1AP_Criticality_reject); + DevAssert(ie->value.present == E1AP_BearerContextSetupRequestIEs__value_PR_BitRate); + asn_INTEGER2long(&ie->value.choice.BitRate, &bearerCxt->ueDlAggMaxBitRate); + break; + + case E1AP_ProtocolIE_ID_id_Serving_PLMN: + DevAssert(ie->criticality == E1AP_Criticality_ignore); + DevAssert(ie->value.present == E1AP_BearerContextSetupRequestIEs__value_PR_PLMN_Identity); + PLMNID_TO_MCC_MNC(&ie->value.choice.PLMN_Identity, + bearerCxt->servingPLMNid.mcc, + bearerCxt->servingPLMNid.mnc, + bearerCxt->servingPLMNid.mnc_digit_length); + break; + + case E1AP_ProtocolIE_ID_id_ActivityNotificationLevel: + DevAssert(ie->criticality == E1AP_Criticality_reject); + DevAssert(ie->value.present == E1AP_BearerContextSetupRequestIEs__value_PR_ActivityNotificationLevel); + bearerCxt->activityNotificationLevel = ie->value.choice.ActivityNotificationLevel; + break; + + case E1AP_ProtocolIE_ID_id_System_BearerContextSetupRequest: + DevAssert(ie->criticality == E1AP_Criticality_reject); + DevAssert(ie->value.present == E1AP_BearerContextSetupRequestIEs__value_PR_System_BearerContextSetupRequest); + DevAssert(ie->value.choice.System_BearerContextSetupRequest.present == + E1AP_System_BearerContextSetupRequest_PR_nG_RAN_BearerContextSetupRequest); + DevAssert(ie->value.choice.System_BearerContextSetupRequest.choice.nG_RAN_BearerContextSetupRequest); + E1AP_ProtocolIE_Container_4932P19_t *msgNGRAN_list = (E1AP_ProtocolIE_Container_4932P19_t *) ie->value.choice.System_BearerContextSetupRequest.choice.nG_RAN_BearerContextSetupRequest; + E1AP_NG_RAN_BearerContextSetupRequest_t *msgNGRAN = msgNGRAN_list->list.array[0]; + DevAssert(msgNGRAN_list->list.count == 1); + DevAssert(msgNGRAN->id == E1AP_ProtocolIE_ID_id_PDU_Session_Resource_To_Setup_List); + DevAssert(msgNGRAN->value.present == E1AP_NG_RAN_BearerContextSetupRequest__value_PR_PDU_Session_Resource_To_Setup_List); + + E1AP_PDU_Session_Resource_To_Setup_List_t *pdu2SetupList = &msgNGRAN->value.choice.PDU_Session_Resource_To_Setup_List; + bearerCxt->numPDUSessions = pdu2SetupList->list.count; + for (int i=0; i < pdu2SetupList->list.count; i++) { + pdu_session_to_setup_t *pdu_session = bearerCxt->pduSession + i; + E1AP_PDU_Session_Resource_To_Setup_Item_t *pdu2Setup = pdu2SetupList->list.array[i]; + + pdu_session->sessionId = pdu2Setup->pDU_Session_ID; + pdu_session->sessionType = pdu2Setup->pDU_Session_Type; + + OCTET_STRING_TO_INT8(&pdu2Setup->sNSSAI.sST, pdu_session->sst); + + pdu_session->integrityProtectionIndication = pdu2Setup->securityIndication.integrityProtectionIndication; + pdu_session->confidentialityProtectionIndication = pdu2Setup->securityIndication.confidentialityProtectionIndication; + + if (pdu2Setup->nG_UL_UP_TNL_Information.choice.gTPTunnel) { // Optional IE + DevAssert(pdu2Setup->nG_UL_UP_TNL_Information.present == + E1AP_UP_TNL_Information_PR_gTPTunnel); + BIT_STRING_TO_TRANSPORT_LAYER_ADDRESS_IPv4(&pdu2Setup->nG_UL_UP_TNL_Information.choice.gTPTunnel->transportLayerAddress, + pdu_session->tlAddress); + OCTET_STRING_TO_INT32(&pdu2Setup->nG_UL_UP_TNL_Information.choice.gTPTunnel->gTP_TEID, pdu_session->teId); + } + + E1AP_DRB_To_Setup_List_NG_RAN_t *drb2SetupList = &pdu2Setup->dRB_To_Setup_List_NG_RAN; + pdu_session->numDRB2Setup = drb2SetupList->list.count; + for (int j=0; j < drb2SetupList->list.count; j++) { + DRB_nGRAN_to_setup_t *drb = pdu_session->DRBnGRanList + j; + E1AP_DRB_To_Setup_Item_NG_RAN_t *drb2Setup = drb2SetupList->list.array[j]; + + drb->id = drb2Setup->dRB_ID; + + drb->defaultDRB = drb2Setup->sDAP_Configuration.defaultDRB; + drb->sDAP_Header_UL = drb2Setup->sDAP_Configuration.sDAP_Header_UL; + drb->sDAP_Header_DL = drb2Setup->sDAP_Configuration.sDAP_Header_DL; + + drb->pDCP_SN_Size_UL = drb2Setup->pDCP_Configuration.pDCP_SN_Size_UL; + drb->pDCP_SN_Size_DL = drb2Setup->pDCP_Configuration.pDCP_SN_Size_DL; + + if (drb2Setup->pDCP_Configuration.discardTimer) { + drb->discardTimer = *drb2Setup->pDCP_Configuration.discardTimer; + } + + if (drb2Setup->pDCP_Configuration.t_ReorderingTimer) { + drb->reorderingTimer = drb2Setup->pDCP_Configuration.t_ReorderingTimer->t_Reordering; + } + + drb->rLC_Mode = drb2Setup->pDCP_Configuration.rLC_Mode; + + E1AP_Cell_Group_Information_t *cellGroupList = &drb2Setup->cell_Group_Information; + drb->numCellGroups = cellGroupList->list.count; + for (int k=0; k < cellGroupList->list.count; k++) { + E1AP_Cell_Group_Information_Item_t *cg2Setup = cellGroupList->list.array[k]; + + drb->cellGroupList[k].id = cg2Setup->cell_Group_ID; + } + + E1AP_QoS_Flow_QoS_Parameter_List_t *qos2SetupList = &drb2Setup->qos_flow_Information_To_Be_Setup; + drb->numQosFlow2Setup = qos2SetupList->list.count; + for (int k=0; k < qos2SetupList->list.count; k++) { + qos_flow_to_setup_t *qos = drb->qosFlows + k; + E1AP_QoS_Flow_QoS_Parameter_Item_t *qos2Setup = qos2SetupList->list.array[k]; + + qos->id = qos2Setup->qoS_Flow_Identifier; + + if (qos2Setup->qoSFlowLevelQoSParameters.qoS_Characteristics.present == + E1AP_QoS_Characteristics_PR_non_Dynamic_5QI) { + qos->fiveQI_type = non_dynamic; + qos->fiveQI = qos2Setup->qoSFlowLevelQoSParameters.qoS_Characteristics.choice.non_Dynamic_5QI->fiveQI; + } else { + E1AP_Dynamic5QIDescriptor_t *dynamic5QI = qos2Setup->qoSFlowLevelQoSParameters.qoS_Characteristics.choice.dynamic_5QI; + qos->fiveQI_type = dynamic; + qos->qoSPriorityLevel = dynamic5QI->qoSPriorityLevel; + qos->packetDelayBudget = dynamic5QI->packetDelayBudget; + qos->packetError_scalar = dynamic5QI->packetErrorRate.pER_Scalar; + qos->packetError_exponent = dynamic5QI->packetErrorRate.pER_Exponent; + } + + qos->priorityLevel = qos2Setup->qoSFlowLevelQoSParameters.nGRANallocationRetentionPriority.priorityLevel; + qos->pre_emptionCapability = qos2Setup->qoSFlowLevelQoSParameters.nGRANallocationRetentionPriority.pre_emptionCapability; + qos->pre_emptionVulnerability = qos2Setup->qoSFlowLevelQoSParameters.nGRANallocationRetentionPriority.pre_emptionVulnerability; + } + } + } + break; + + default: + LOG_E(E1AP, "Handle for this IE is not implemented (or) invalid IE detected\n"); + break; + } + } + + } -int e1apCUCP_handle_BEARER_CONTEXT_SETUP_RESPONSE(instance_t instance, - uint32_t assoc_id, - uint32_t stream, - E1AP_E1AP_PDU_t *pdu) { - AssertFatal(false,"Not implemented yet\n"); +int e1apCUUP_handle_BEARER_CONTEXT_SETUP_REQUEST(e1ap_upcp_inst_t *e1_inst, const E1AP_E1AP_PDU_t *pdu) +{ + DevAssert(pdu != NULL); + DevAssert(pdu->present == E1AP_E1AP_PDU_PR_initiatingMessage); + DevAssert(pdu->choice.initiatingMessage->procedureCode == E1AP_ProcedureCode_id_bearerContextSetup); + DevAssert(pdu->choice.initiatingMessage->criticality == E1AP_Criticality_reject); + DevAssert(pdu->choice.initiatingMessage->value.present == E1AP_InitiatingMessage__value_PR_BearerContextSetupRequest); + + e1ap_bearer_setup_req_t bearerCxt = {0}; + extract_BEARER_CONTEXT_SETUP_REQUEST(pdu, &bearerCxt); + process_e1_bearer_context_setup_req(e1_inst->instance, &bearerCxt); + return 0; } -int e1apCUCP_handle_BEARER_CONTEXT_SETUP_FAILURE(instance_t instance, - uint32_t assoc_id, - uint32_t stream, - E1AP_E1AP_PDU_t *pdu) { +void extract_BEARER_CONTEXT_SETUP_RESPONSE(const E1AP_E1AP_PDU_t *pdu, + e1ap_bearer_setup_resp_t *bearerCxt) { + const E1AP_BearerContextSetupResponse_t *in = &pdu->choice.successfulOutcome->value.choice.BearerContextSetupResponse; + E1AP_BearerContextSetupResponseIEs_t *ie; + + LOG_I(E1AP, "Bearer context setup response number of IEs %d\n", in->protocolIEs.list.count); + + for (int i=0; i < in->protocolIEs.list.count; i++) { + ie = in->protocolIEs.list.array[i]; + + switch(ie->id) { + case E1AP_ProtocolIE_ID_id_gNB_CU_CP_UE_E1AP_ID: + DevAssert(ie->criticality == E1AP_Criticality_reject); + DevAssert(ie->value.present == E1AP_BearerContextSetupResponseIEs__value_PR_GNB_CU_CP_UE_E1AP_ID); + bearerCxt->gNB_cu_cp_ue_id = ie->value.choice.GNB_CU_CP_UE_E1AP_ID; + break; + + case E1AP_ProtocolIE_ID_id_gNB_CU_UP_UE_E1AP_ID: + DevAssert(ie->criticality == E1AP_Criticality_reject); + DevAssert(ie->value.present == E1AP_BearerContextSetupResponseIEs__value_PR_GNB_CU_UP_UE_E1AP_ID); + bearerCxt->gNB_cu_up_ue_id = ie->value.choice.GNB_CU_UP_UE_E1AP_ID; + break; + + case E1AP_ProtocolIE_ID_id_System_BearerContextSetupResponse: + DevAssert(ie->criticality == E1AP_Criticality_reject); + DevAssert(ie->value.present == E1AP_BearerContextSetupResponseIEs__value_PR_System_BearerContextSetupResponse); + DevAssert(ie->value.choice.System_BearerContextSetupResponse.present == + E1AP_System_BearerContextSetupResponse_PR_nG_RAN_BearerContextSetupResponse); + E1AP_ProtocolIE_Container_4932P22_t *msgNGRAN_list = (E1AP_ProtocolIE_Container_4932P22_t *) ie->value.choice.System_BearerContextSetupResponse.choice.nG_RAN_BearerContextSetupResponse; + DevAssert(msgNGRAN_list->list.count == 1); + E1AP_NG_RAN_BearerContextSetupResponse_t *msgNGRAN = msgNGRAN_list->list.array[0]; + DevAssert(msgNGRAN->id == E1AP_ProtocolIE_ID_id_PDU_Session_Resource_Setup_List); + DevAssert(msgNGRAN->criticality == E1AP_Criticality_reject); + DevAssert(msgNGRAN->value.present == E1AP_NG_RAN_BearerContextSetupResponse__value_PR_PDU_Session_Resource_Setup_List); + E1AP_PDU_Session_Resource_Setup_List_t *pduSetupList = &msgNGRAN->value.choice.PDU_Session_Resource_Setup_List; + bearerCxt->numPDUSessions = pduSetupList->list.count; + + for (int i=0; i < pduSetupList->list.count; i++) { + pdu_session_setup_t *pduSetup = bearerCxt->pduSession + i; + E1AP_PDU_Session_Resource_Setup_Item_t *pdu_session = pduSetupList->list.array[i]; + pduSetup->id = pdu_session->pDU_Session_ID; + + if (pdu_session->nG_DL_UP_TNL_Information.choice.gTPTunnel) { + DevAssert(pdu_session->nG_DL_UP_TNL_Information.present == E1AP_UP_TNL_Information_PR_gTPTunnel); + BIT_STRING_TO_TRANSPORT_LAYER_ADDRESS_IPv4(&pdu_session->nG_DL_UP_TNL_Information.choice.gTPTunnel->transportLayerAddress, + pduSetup->tlAddress); + OCTET_STRING_TO_INT32(&pdu_session->nG_DL_UP_TNL_Information.choice.gTPTunnel->gTP_TEID, + pduSetup->teId); + } + + pduSetup->numDRBSetup = pdu_session->dRB_Setup_List_NG_RAN.list.count; + for (int j=0; j < pdu_session->dRB_Setup_List_NG_RAN.list.count; j++) { + DRB_nGRAN_setup_t *drbSetup = pduSetup->DRBnGRanList + j; + E1AP_DRB_Setup_Item_NG_RAN_t *drb = pdu_session->dRB_Setup_List_NG_RAN.list.array[j]; + + drbSetup->id = drb->dRB_ID; + + drbSetup->numUpParam = drb->uL_UP_Transport_Parameters.list.count; + for (int k=0; k < drb->uL_UP_Transport_Parameters.list.count; k++) { + up_params_t *UL_UP_param = drbSetup->UpParamList + k; + E1AP_UP_Parameters_Item_t *in_UL_UP_param = drb->uL_UP_Transport_Parameters.list.array[k]; + + DevAssert(in_UL_UP_param->uP_TNL_Information.present == E1AP_UP_TNL_Information_PR_gTPTunnel); + E1AP_GTPTunnel_t *gTPTunnel = in_UL_UP_param->uP_TNL_Information.choice.gTPTunnel; + if (gTPTunnel) { + BIT_STRING_TO_TRANSPORT_LAYER_ADDRESS_IPv4(&gTPTunnel->transportLayerAddress, + UL_UP_param->tlAddress); + OCTET_STRING_TO_INT32(&gTPTunnel->gTP_TEID, + UL_UP_param->teId); + } else { + AssertFatal(false, "gTPTunnel information in required\n"); + } + } + } + } + break; + + // TODO: remaining IE handlers + + default: + LOG_E(E1AP, "Handle for this IE is not implemented (or) invalid IE detected\n"); + break; + } + } +} + +int e1apCUCP_handle_BEARER_CONTEXT_SETUP_RESPONSE(e1ap_upcp_inst_t *inst, const E1AP_E1AP_PDU_t *pdu) +{ + DevAssert(pdu->present == E1AP_E1AP_PDU_PR_successfulOutcome); + DevAssert(pdu->choice.successfulOutcome->procedureCode == E1AP_ProcedureCode_id_bearerContextSetup); + DevAssert(pdu->choice.successfulOutcome->criticality == E1AP_Criticality_reject); + DevAssert(pdu->choice.successfulOutcome->value.present == E1AP_SuccessfulOutcome__value_PR_BearerContextSetupResponse); + + MessageDef *msg = itti_alloc_new_message(TASK_CUCP_E1, 0, E1AP_BEARER_CONTEXT_SETUP_RESP); + e1ap_bearer_setup_resp_t *bearerCxt = &E1AP_BEARER_CONTEXT_SETUP_RESP(msg); + extract_BEARER_CONTEXT_SETUP_RESPONSE(pdu, bearerCxt); + // Fixme: instance is the NGAP instance, no good way to set it here + instance_t instance = 0; + itti_send_msg_to_task(TASK_RRC_GNB, instance, msg); + + return 0; +} + +int e1apCUCP_handle_BEARER_CONTEXT_SETUP_FAILURE(e1ap_upcp_inst_t *inst, const E1AP_E1AP_PDU_t *pdu) +{ AssertFatal(false,"Not implemented yet\n"); + return -1; } /* BEARER CONTEXT MODIFICATION REQUEST */ -int e1apCUCP_send_BEARER_CONTEXT_MODIFICATION_REQUEST(instance_t instance) { - AssertFatal(false,"Not implemented yet\n"); +static int fill_BEARER_CONTEXT_MODIFICATION_REQUEST(e1ap_setup_req_t *setupReq, e1ap_bearer_setup_req_t *const bearerCxt, E1AP_E1AP_PDU_t *pdu) +{ + pdu->present = E1AP_E1AP_PDU_PR_initiatingMessage; + asn1cCalloc(pdu->choice.initiatingMessage, msg); + msg->procedureCode = E1AP_ProcedureCode_id_bearerContextModification; + msg->criticality = E1AP_Criticality_reject; + msg->value.present = E1AP_InitiatingMessage__value_PR_BearerContextModificationRequest; + E1AP_BearerContextModificationRequest_t *out = &pdu->choice.initiatingMessage->value.choice.BearerContextModificationRequest; + /* mandatory */ + /* c1. gNB-CU-CP UE E1AP ID */ + asn1cSequenceAdd(out->protocolIEs.list, E1AP_BearerContextModificationRequestIEs_t, ieC1); + ieC1->id = E1AP_ProtocolIE_ID_id_gNB_CU_CP_UE_E1AP_ID; + ieC1->criticality = E1AP_Criticality_reject; + ieC1->value.present = E1AP_BearerContextModificationRequestIEs__value_PR_GNB_CU_CP_UE_E1AP_ID; + ieC1->value.choice.GNB_CU_CP_UE_E1AP_ID = bearerCxt->gNB_cu_cp_ue_id; + /* mandatory */ + /* c2. gNB-CU-UP UE E1AP ID */ + asn1cSequenceAdd(out->protocolIEs.list, E1AP_BearerContextModificationRequestIEs_t, ieC2); + ieC2->id = E1AP_ProtocolIE_ID_id_gNB_CU_UP_UE_E1AP_ID; + ieC2->criticality = E1AP_Criticality_reject; + ieC2->value.present = E1AP_BearerContextModificationRequestIEs__value_PR_GNB_CU_UP_UE_E1AP_ID; + ieC2->value.choice.GNB_CU_UP_UE_E1AP_ID = bearerCxt->gNB_cu_cp_ue_id; + /* optional */ + /* */ + asn1cSequenceAdd(out->protocolIEs.list, E1AP_BearerContextModificationRequestIEs_t, ieC3); + ieC3->id = E1AP_ProtocolIE_ID_id_System_BearerContextModificationRequest; + ieC3->criticality = E1AP_Criticality_reject; + ieC3->value.present = E1AP_BearerContextModificationRequestIEs__value_PR_System_BearerContextModificationRequest; + ieC3->value.choice.System_BearerContextModificationRequest.present = E1AP_System_BearerContextModificationRequest_PR_nG_RAN_BearerContextModificationRequest; + E1AP_ProtocolIE_Container_4932P26_t *msgNGRAN_list = calloc(1, sizeof(E1AP_ProtocolIE_Container_4932P26_t)); + ieC3->value.choice.System_BearerContextModificationRequest.choice.nG_RAN_BearerContextModificationRequest = (struct E1AP_ProtocolIE_Container *) msgNGRAN_list; + asn1cSequenceAdd(msgNGRAN_list->list, E1AP_NG_RAN_BearerContextModificationRequest_t, msgNGRAN); + msgNGRAN->id = E1AP_ProtocolIE_ID_id_PDU_Session_Resource_To_Modify_List; + msgNGRAN->criticality = E1AP_Criticality_reject; + msgNGRAN->value.present = E1AP_NG_RAN_BearerContextModificationRequest__value_PR_PDU_Session_Resource_To_Modify_List; + E1AP_PDU_Session_Resource_To_Modify_List_t *pdu2Setup = &msgNGRAN->value.choice.PDU_Session_Resource_To_Modify_List; + for(pdu_session_to_setup_t *i=bearerCxt->pduSessionMod; i < bearerCxt->pduSessionMod+bearerCxt->numPDUSessionsMod; i++) { + asn1cSequenceAdd(pdu2Setup->list, E1AP_PDU_Session_Resource_To_Modify_Item_t, ieC3_1); + ieC3_1->pDU_Session_ID = i->sessionId; + + for (DRB_nGRAN_to_setup_t *j=i->DRBnGRanModList; j < i->DRBnGRanModList+i->numDRB2Modify; j++) { + asn1cCalloc(ieC3_1->dRB_To_Modify_List_NG_RAN, drb2Mod_List); + asn1cSequenceAdd(drb2Mod_List->list, E1AP_DRB_To_Modify_Item_NG_RAN_t, drb2Mod); + drb2Mod->dRB_ID = j->id; + + if (j->numDlUpParam > 0) { + asn1cCalloc(drb2Mod->dL_UP_Parameters, DL_UP_Param_List); + for (up_params_t *k=j->DlUpParamList; k < j->DlUpParamList+j->numDlUpParam; k++) { + asn1cSequenceAdd(DL_UP_Param_List->list, E1AP_UP_Parameters_Item_t, DL_UP_Param); + DL_UP_Param->uP_TNL_Information.present = E1AP_UP_TNL_Information_PR_gTPTunnel; + asn1cCalloc(DL_UP_Param->uP_TNL_Information.choice.gTPTunnel, gTPTunnel); + TRANSPORT_LAYER_ADDRESS_IPv4_TO_BIT_STRING(k->tlAddress, &gTPTunnel->transportLayerAddress); + INT32_TO_OCTET_STRING(k->teId, &gTPTunnel->gTP_TEID); + + DL_UP_Param->cell_Group_ID = k->cell_group_id; + } + } + } + } + return 0; +} + +static void e1apCUCP_send_BEARER_CONTEXT_MODIFICATION_REQUEST(instance_t inst, e1ap_bearer_setup_req_t *const bearerCxt) +{ + AssertFatal(getCxtE1(inst), ""); + e1ap_setup_req_t *setupReq = &getCxtE1(inst)->setupReq; + E1AP_E1AP_PDU_t pdu = {0}; + fill_BEARER_CONTEXT_MODIFICATION_REQUEST(setupReq, bearerCxt, &pdu); + e1ap_encode_send(CPtype, setupReq, &pdu, 0, __func__); } int e1apCUUP_send_BEARER_CONTEXT_MODIFICATION_RESPONSE(instance_t instance) { AssertFatal(false,"Not implemented yet\n"); + return -1; } int e1apCUUP_send_BEARER_CONTEXT_MODIFICATION_FAILURE(instance_t instance) { AssertFatal(false,"Not implemented yet\n"); + return -1; } -int e1apCUUP_handle_BEARER_CONTEXT_MODIFICATION_REQUEST(instance_t instance, - uint32_t assoc_id, - uint32_t stream, - E1AP_E1AP_PDU_t *pdu) { - AssertFatal(false,"Not implemented yet\n"); +void extract_BEARER_CONTEXT_MODIFICATION_REQUEST(const E1AP_E1AP_PDU_t *pdu, + e1ap_bearer_setup_req_t *bearerCxt) { + const E1AP_BearerContextModificationRequest_t *in = &pdu->choice.initiatingMessage->value.choice.BearerContextModificationRequest; + E1AP_BearerContextModificationRequestIEs_t *ie; + + LOG_I(E1AP, "Bearer context setup number of IEs %d\n", in->protocolIEs.list.count); + + for (int i=0; i < in->protocolIEs.list.count; i++) { + ie = in->protocolIEs.list.array[i]; + + switch(ie->id) { + case E1AP_ProtocolIE_ID_id_gNB_CU_CP_UE_E1AP_ID: + DevAssert(ie->criticality == E1AP_Criticality_reject); + DevAssert(ie->value.present == E1AP_BearerContextModificationRequestIEs__value_PR_GNB_CU_CP_UE_E1AP_ID); + bearerCxt->gNB_cu_cp_ue_id = ie->value.choice.GNB_CU_CP_UE_E1AP_ID; + break; + + case E1AP_ProtocolIE_ID_id_gNB_CU_UP_UE_E1AP_ID: + DevAssert(ie->criticality == E1AP_Criticality_reject); + DevAssert(ie->value.present == E1AP_BearerContextModificationRequestIEs__value_PR_GNB_CU_UP_UE_E1AP_ID); + bearerCxt->gNB_cu_up_ue_id = ie->value.choice.GNB_CU_UP_UE_E1AP_ID; + break; + + case E1AP_ProtocolIE_ID_id_System_BearerContextModificationRequest: + DevAssert(ie->criticality == E1AP_Criticality_reject); + DevAssert(ie->value.present == E1AP_BearerContextModificationRequestIEs__value_PR_System_BearerContextModificationRequest); + DevAssert(ie->value.choice.System_BearerContextModificationRequest.present == + E1AP_System_BearerContextModificationRequest_PR_nG_RAN_BearerContextModificationRequest); + DevAssert(ie->value.choice.System_BearerContextModificationRequest.choice.nG_RAN_BearerContextModificationRequest != NULL); + E1AP_ProtocolIE_Container_4932P26_t *msgNGRAN_list = (E1AP_ProtocolIE_Container_4932P26_t *) ie->value.choice.System_BearerContextModificationRequest.choice.nG_RAN_BearerContextModificationRequest; + E1AP_NG_RAN_BearerContextModificationRequest_t *msgNGRAN = msgNGRAN_list->list.array[0]; + DevAssert(msgNGRAN_list->list.count == 1); + DevAssert(msgNGRAN->id == E1AP_ProtocolIE_ID_id_PDU_Session_Resource_To_Modify_List); + DevAssert(msgNGRAN->value.present = + E1AP_NG_RAN_BearerContextModificationRequest__value_PR_PDU_Session_Resource_To_Modify_List); + + E1AP_PDU_Session_Resource_To_Modify_List_t *pdu2ModList = &msgNGRAN->value.choice.PDU_Session_Resource_To_Modify_List; + bearerCxt->numPDUSessionsMod = pdu2ModList->list.count; + for (int i=0; i < pdu2ModList->list.count; i++) { + pdu_session_to_setup_t *pdu_session = bearerCxt->pduSessionMod + i; + E1AP_PDU_Session_Resource_To_Modify_Item_t *pdu2Mod = pdu2ModList->list.array[i]; + + pdu_session->sessionId = pdu2Mod->pDU_Session_ID; + + E1AP_DRB_To_Modify_List_NG_RAN_t *drb2ModList = pdu2Mod->dRB_To_Modify_List_NG_RAN; + pdu_session->numDRB2Modify = drb2ModList->list.count; + for (int j=0; j < drb2ModList->list.count; j++) { + DRB_nGRAN_to_setup_t *drb = pdu_session->DRBnGRanModList + j; + E1AP_DRB_To_Modify_Item_NG_RAN_t *drb2Mod = drb2ModList->list.array[j]; + + drb->id = drb2Mod->dRB_ID; + + E1AP_UP_Parameters_t *dl_up_paramList = drb2Mod->dL_UP_Parameters; + drb->numDlUpParam = dl_up_paramList->list.count; + for (int k=0; k < dl_up_paramList->list.count; k++) { + up_params_t *dl_up_param = drb->DlUpParamList + k; + E1AP_UP_Parameters_Item_t *dl_up_param_in = dl_up_paramList->list.array[k]; + if (dl_up_param_in->uP_TNL_Information.choice.gTPTunnel) { // Optional IE + DevAssert(dl_up_param_in->uP_TNL_Information.present = E1AP_UP_TNL_Information_PR_gTPTunnel); + BIT_STRING_TO_TRANSPORT_LAYER_ADDRESS_IPv4(&dl_up_param_in->uP_TNL_Information.choice.gTPTunnel->transportLayerAddress, + dl_up_param->tlAddress); + OCTET_STRING_TO_INT32(&dl_up_param_in->uP_TNL_Information.choice.gTPTunnel->gTP_TEID, dl_up_param->teId); + } else { + AssertFatal(false, "gTPTunnel IE is missing. It is mandatory at this point\n"); + } + dl_up_param->cell_group_id = dl_up_param_in->cell_Group_ID; + } + } + } + break; + + default: + LOG_E(E1AP, "Handle for this IE is not implemented (or) invalid IE detected\n"); + break; + } + } +} + +int e1apCUUP_handle_BEARER_CONTEXT_MODIFICATION_REQUEST(e1ap_upcp_inst_t *e1_inst, const E1AP_E1AP_PDU_t *pdu) +{ + DevAssert(pdu != NULL); + DevAssert(pdu->present == E1AP_E1AP_PDU_PR_initiatingMessage); + DevAssert(pdu->choice.initiatingMessage->procedureCode == E1AP_ProcedureCode_id_bearerContextModification); + DevAssert(pdu->choice.initiatingMessage->criticality == E1AP_Criticality_reject); + DevAssert(pdu->choice.initiatingMessage->value.present == E1AP_InitiatingMessage__value_PR_BearerContextModificationRequest); + + e1ap_bearer_setup_req_t bearerCxt = {0}; + extract_BEARER_CONTEXT_MODIFICATION_REQUEST(pdu, &bearerCxt); + CUUP_process_bearer_context_mod_req(e1_inst->instance, &bearerCxt); + return 0; } int e1apCUCP_handle_BEARER_CONTEXT_MODIFICATION_RESPONSE(instance_t instance, @@ -277,6 +1251,7 @@ int e1apCUCP_handle_BEARER_CONTEXT_MODIFICATION_RESPONSE(instance_t instance, uint32_t stream, E1AP_E1AP_PDU_t *pdu) { AssertFatal(false,"Not implemented yet\n"); + return -1; } int e1apCUCP_handle_BEARER_CONTEXT_MODIFICATION_FAILURE(instance_t instance, @@ -284,14 +1259,17 @@ int e1apCUCP_handle_BEARER_CONTEXT_MODIFICATION_FAILURE(instance_t instance, uint32_t stream, E1AP_E1AP_PDU_t *pdu) { AssertFatal(false,"Not implemented yet\n"); + return -1; } int e1apCUUP_send_BEARER_CONTEXT_MODIFICATION_REQUIRED(instance_t instance) { AssertFatal(false,"Not implemented yet\n"); + return -1; } int e1apCUCP_send_BEARER_CONTEXT_MODIFICATION_CONFIRM(instance_t instance) { AssertFatal(false,"Not implemented yet\n"); + return -1; } int e1apCUCP_handle_BEARER_CONTEXT_MODIFICATION_REQUIRED(instance_t instance, @@ -299,6 +1277,7 @@ int e1apCUCP_handle_BEARER_CONTEXT_MODIFICATION_REQUIRED(instance_t instance, uint32_t stream, E1AP_E1AP_PDU_t *pdu) { AssertFatal(false,"Not implemented yet\n"); + return -1; } int e1apCUUP_handle_BEARER_CONTEXT_MODIFICATION_CONFIRM(instance_t instance, @@ -306,35 +1285,178 @@ int e1apCUUP_handle_BEARER_CONTEXT_MODIFICATION_CONFIRM(instance_t instance, uint32_t stream, E1AP_E1AP_PDU_t *pdu) { AssertFatal(false,"Not implemented yet\n"); + return -1; } /* BEARER CONTEXT RELEASE */ -int e1apCUCP_send_BEARER_CONTEXT_RELEASE_COMMAND(instance_t instance) { - AssertFatal(false,"Not implemented yet\n"); +static int fill_BEARER_CONTEXT_RELEASE_COMMAND(e1ap_setup_req_t *setupReq, e1ap_bearer_release_cmd_t *const cmd, E1AP_E1AP_PDU_t *pdu) +{ + pdu->present = E1AP_E1AP_PDU_PR_initiatingMessage; + asn1cCalloc(pdu->choice.initiatingMessage, msg); + msg->procedureCode = E1AP_ProcedureCode_id_bearerContextRelease; + msg->criticality = E1AP_Criticality_reject; + msg->value.present = E1AP_InitiatingMessage__value_PR_BearerContextReleaseCommand; + E1AP_BearerContextReleaseCommand_t *out = &pdu->choice.initiatingMessage->value.choice.BearerContextReleaseCommand; + /* mandatory */ + /* c1. gNB-CU-CP UE E1AP ID */ + asn1cSequenceAdd(out->protocolIEs.list, E1AP_BearerContextReleaseCommandIEs_t, ieC1); + ieC1->id = E1AP_ProtocolIE_ID_id_gNB_CU_CP_UE_E1AP_ID; + ieC1->criticality = E1AP_Criticality_reject; + ieC1->value.present = E1AP_BearerContextReleaseCommandIEs__value_PR_GNB_CU_CP_UE_E1AP_ID; + ieC1->value.choice.GNB_CU_CP_UE_E1AP_ID = cmd->gNB_cu_cp_ue_id; + /* mandatory */ + /* c2. gNB-CU-UP UE E1AP ID */ + asn1cSequenceAdd(out->protocolIEs.list, E1AP_BearerContextReleaseCommandIEs_t, ieC2); + ieC2->id = E1AP_ProtocolIE_ID_id_gNB_CU_UP_UE_E1AP_ID; + ieC2->criticality = E1AP_Criticality_reject; + ieC2->value.present = E1AP_BearerContextReleaseCommandIEs__value_PR_GNB_CU_UP_UE_E1AP_ID; + ieC2->value.choice.GNB_CU_UP_UE_E1AP_ID = cmd->gNB_cu_cp_ue_id; + + return 0; } -int e1apCUUP_send_BEARER_CONTEXT_RELEASE_COMPLETE(instance_t instance) { - AssertFatal(false,"Not implemented yet\n"); +int e1apCUCP_send_BEARER_CONTEXT_RELEASE_COMMAND(e1ap_setup_req_t *setupReq, e1ap_bearer_release_cmd_t *const cmd) +{ + E1AP_E1AP_PDU_t pdu = {0}; + fill_BEARER_CONTEXT_RELEASE_COMMAND(setupReq, cmd, &pdu); + return e1ap_encode_send(CPtype, setupReq, &pdu, 0, __func__); +} + +int fill_BEARER_CONTEXT_RELEASE_COMPLETE(e1ap_setup_req_t *setupReq, e1ap_bearer_release_cmd_t *const cmd, E1AP_E1AP_PDU_t *pdu) +{ + pdu->present = E1AP_E1AP_PDU_PR_successfulOutcome; + asn1cCalloc(pdu->choice.successfulOutcome, msg); + msg->procedureCode = E1AP_ProcedureCode_id_bearerContextRelease; + msg->criticality = E1AP_Criticality_reject; + msg->value.present = E1AP_SuccessfulOutcome__value_PR_BearerContextReleaseComplete; + E1AP_BearerContextReleaseComplete_t *out = &pdu->choice.successfulOutcome->value.choice.BearerContextReleaseComplete; + /* mandatory */ + /* c1. gNB-CU-CP UE E1AP ID */ + asn1cSequenceAdd(out->protocolIEs.list, E1AP_BearerContextReleaseCompleteIEs_t, ieC1); + ieC1->id = E1AP_ProtocolIE_ID_id_gNB_CU_CP_UE_E1AP_ID; + ieC1->criticality = E1AP_Criticality_reject; + ieC1->value.present = E1AP_BearerContextReleaseCompleteIEs__value_PR_GNB_CU_CP_UE_E1AP_ID; + ieC1->value.choice.GNB_CU_CP_UE_E1AP_ID = cmd->gNB_cu_cp_ue_id; + /* mandatory */ + /* c2. gNB-CU-UP UE E1AP ID */ + asn1cSequenceAdd(out->protocolIEs.list, E1AP_BearerContextReleaseCompleteIEs_t, ieC2); + ieC2->id = E1AP_ProtocolIE_ID_id_gNB_CU_UP_UE_E1AP_ID; + ieC2->criticality = E1AP_Criticality_reject; + ieC2->value.present = E1AP_BearerContextReleaseCompleteIEs__value_PR_GNB_CU_UP_UE_E1AP_ID; + ieC2->value.choice.GNB_CU_UP_UE_E1AP_ID = cmd->gNB_cu_cp_ue_id; + + return 0; +} + +int e1apCUUP_send_BEARER_CONTEXT_RELEASE_COMPLETE(e1ap_upcp_inst_t *inst, e1ap_bearer_release_cmd_t *const cmd) +{ + E1AP_E1AP_PDU_t pdu = {0}; + fill_BEARER_CONTEXT_RELEASE_COMPLETE(&inst->setupReq, cmd, &pdu); + return e1ap_encode_send(CPtype, &inst->setupReq, &pdu, 0, __func__); } int e1apCUUP_send_BEARER_CONTEXT_RELEASE_REQUEST(instance_t instance) { AssertFatal(false,"Not implemented yet\n"); + return -1; } -int e1apCUUP_handle_BEARER_CONTEXT_RELEASE_COMMAND(instance_t instance, - uint32_t assoc_id, - uint32_t stream, - E1AP_E1AP_PDU_t *pdu) { - AssertFatal(false,"Not implemented yet\n"); +void extract_BEARER_CONTEXT_RELEASE_COMMAND(const E1AP_E1AP_PDU_t *pdu, + e1ap_bearer_release_cmd_t *bearerCxt) { + const E1AP_BearerContextReleaseCommand_t *in = &pdu->choice.initiatingMessage->value.choice.BearerContextReleaseCommand; + E1AP_BearerContextReleaseCommandIEs_t *ie; + + LOG_I(E1AP, "Bearer context setup number of IEs %d\n", in->protocolIEs.list.count); + + for (int i=0; i < in->protocolIEs.list.count; i++) { + ie = in->protocolIEs.list.array[i]; + + switch(ie->id) { + case E1AP_ProtocolIE_ID_id_gNB_CU_CP_UE_E1AP_ID: + DevAssert(ie->criticality == E1AP_Criticality_reject); + DevAssert(ie->value.present == E1AP_BearerContextReleaseCommandIEs__value_PR_GNB_CU_CP_UE_E1AP_ID); + bearerCxt->gNB_cu_cp_ue_id = ie->value.choice.GNB_CU_CP_UE_E1AP_ID; + break; + + case E1AP_ProtocolIE_ID_id_gNB_CU_UP_UE_E1AP_ID: + DevAssert(ie->criticality == E1AP_Criticality_reject); + DevAssert(ie->value.present == E1AP_BearerContextReleaseCommandIEs__value_PR_GNB_CU_UP_UE_E1AP_ID); + bearerCxt->gNB_cu_up_ue_id = ie->value.choice.GNB_CU_UP_UE_E1AP_ID; + break; + + case E1AP_ProtocolIE_ID_id_Cause: + DevAssert(ie->criticality == E1AP_Criticality_ignore); + DevAssert(ie->value.present == E1AP_BearerContextReleaseCommandIEs__value_PR_Cause); + bearerCxt->cause_type = ie->value.choice.Cause.present; + if ((ie->value.choice.Cause.present != E1AP_Cause_PR_NOTHING) && + (ie->value.choice.Cause.present != E1AP_Cause_PR_choice_extension)) + bearerCxt->cause = ie->value.choice.Cause.choice.radioNetwork; + + + default: + LOG_E(E1AP, "Handle for this IE is not implemented (or) invalid IE detected\n"); + break; + } + } } -int e1apCUCP_handle_BEARER_CONTEXT_RELEASE_COMPLETE(instance_t instance, - uint32_t assoc_id, - uint32_t stream, - E1AP_E1AP_PDU_t *pdu) { - AssertFatal(false,"Not implemented yet\n"); +int e1apCUUP_handle_BEARER_CONTEXT_RELEASE_COMMAND(e1ap_upcp_inst_t *e1_inst, const E1AP_E1AP_PDU_t *pdu) +{ + DevAssert(pdu != NULL); + DevAssert(pdu->present == E1AP_E1AP_PDU_PR_initiatingMessage); + DevAssert(pdu->choice.initiatingMessage->procedureCode == E1AP_ProcedureCode_id_bearerContextRelease); + DevAssert(pdu->choice.initiatingMessage->criticality == E1AP_Criticality_reject); + DevAssert(pdu->choice.initiatingMessage->value.present == E1AP_InitiatingMessage__value_PR_BearerContextReleaseCommand); + + e1ap_bearer_release_cmd_t bearerCxt = {0}; + extract_BEARER_CONTEXT_RELEASE_COMMAND(pdu, &bearerCxt); + CUUP_process_bearer_release_command(e1_inst->instance, &bearerCxt); + return 0; +} + +void extract_BEARER_CONTEXT_RELEASE_COMPLETE(const E1AP_E1AP_PDU_t *pdu, + e1ap_bearer_release_cmd_t *bearerCxt) { + const E1AP_BearerContextReleaseComplete_t *in = &pdu->choice.successfulOutcome->value.choice.BearerContextReleaseComplete; + E1AP_BearerContextReleaseCompleteIEs_t *ie; + + LOG_I(E1AP, "Bearer context setup number of IEs %d\n", in->protocolIEs.list.count); + + for (int i=0; i < in->protocolIEs.list.count; i++) { + ie = in->protocolIEs.list.array[i]; + + switch(ie->id) { + case E1AP_ProtocolIE_ID_id_gNB_CU_CP_UE_E1AP_ID: + DevAssert(ie->criticality == E1AP_Criticality_reject); + DevAssert(ie->value.present == E1AP_BearerContextReleaseCompleteIEs__value_PR_GNB_CU_CP_UE_E1AP_ID); + bearerCxt->gNB_cu_cp_ue_id = ie->value.choice.GNB_CU_CP_UE_E1AP_ID; + break; + + case E1AP_ProtocolIE_ID_id_gNB_CU_UP_UE_E1AP_ID: + DevAssert(ie->criticality == E1AP_Criticality_reject); + DevAssert(ie->value.present == E1AP_BearerContextReleaseCompleteIEs__value_PR_GNB_CU_UP_UE_E1AP_ID); + bearerCxt->gNB_cu_up_ue_id = ie->value.choice.GNB_CU_UP_UE_E1AP_ID; + break; + + default: + LOG_E(E1AP, "Handle for this IE is not implemented (or) invalid IE detected\n"); + break; + } + } +} + +int e1apCUCP_handle_BEARER_CONTEXT_RELEASE_COMPLETE(e1ap_upcp_inst_t *e1_inst, const E1AP_E1AP_PDU_t *pdu) +{ + DevAssert(pdu != NULL); + DevAssert(pdu->present == E1AP_E1AP_PDU_PR_successfulOutcome); + DevAssert(pdu->choice.successfulOutcome->procedureCode == E1AP_ProcedureCode_id_bearerContextRelease); + DevAssert(pdu->choice.successfulOutcome->criticality == E1AP_Criticality_reject); + DevAssert(pdu->choice.successfulOutcome->value.present == E1AP_SuccessfulOutcome__value_PR_BearerContextReleaseComplete); + + e1ap_bearer_release_cmd_t bearerCxt = {0}; + extract_BEARER_CONTEXT_RELEASE_COMPLETE(pdu, &bearerCxt); + //TODO: CUCP_process_bearer_release_complete(&beareCxt, instance); + return 0; } int e1apCUCP_handle_BEARER_CONTEXT_RELEASE_REQUEST(instance_t instance, @@ -342,6 +1464,7 @@ int e1apCUCP_handle_BEARER_CONTEXT_RELEASE_REQUEST(instance_t instance, uint32_t stream, E1AP_E1AP_PDU_t *pdu) { AssertFatal(false,"Not implemented yet\n"); + return -1; } /* @@ -350,6 +1473,7 @@ BEARER CONTEXT INACTIVITY NOTIFICATION int e1apCUUP_send_BEARER_CONTEXT_INACTIVITY_NOTIFICATION(instance_t instance) { AssertFatal(false,"Not implemented yet\n"); + return -1; } int e1apCUCP_handle_BEARER_CONTEXT_INACTIVITY_NOTIFICATION(instance_t instance, @@ -357,6 +1481,7 @@ int e1apCUCP_handle_BEARER_CONTEXT_INACTIVITY_NOTIFICATION(instance_t instance, uint32_t stream, E1AP_E1AP_PDU_t *pdu) { AssertFatal(false,"Not implemented yet\n"); + return -1; } /* DL DATA @@ -364,10 +1489,12 @@ int e1apCUCP_handle_BEARER_CONTEXT_INACTIVITY_NOTIFICATION(instance_t instance, int e1apCUUP_send_DL_DATA_NOTIFICATION(instance_t instance) { AssertFatal(false,"Not implemented yet\n"); + return -1; } int e1apCUUP_send_DATA_USAGE_REPORT(instance_t instance) { AssertFatal(false,"Not implemented yet\n"); + return -1; } int e1apCUCP_handle_DL_DATA_NOTIFICATION(instance_t instance, @@ -375,6 +1502,7 @@ int e1apCUCP_handle_DL_DATA_NOTIFICATION(instance_t instance, uint32_t stream, E1AP_E1AP_PDU_t *pdu) { AssertFatal(false,"Not implemented yet\n"); + return -1; } int e1apCUCP_handle_send_DATA_USAGE_REPORT(instance_t instance, @@ -382,4 +1510,236 @@ int e1apCUCP_handle_send_DATA_USAGE_REPORT(instance_t instance, uint32_t stream, E1AP_E1AP_PDU_t *pdu) { AssertFatal(false,"Not implemented yet\n"); + return -1; } + +static instance_t cuup_task_create_gtpu_instance_to_du(eth_params_t *IPaddrs) { + openAddr_t tmp= {0}; + strncpy(tmp.originHost, IPaddrs->my_addr, sizeof(tmp.originHost)-1); + sprintf(tmp.originService, "%d", IPaddrs->my_portd); + return gtpv1Init(tmp); +} + +static void e1_task_send_sctp_association_req(long task_id, instance_t instance, e1ap_setup_req_t *e1ap_setup_req) +{ + DevAssert(e1ap_setup_req != NULL); + getCxtE1(instance)->sockState = SCTP_STATE_CLOSED; + MessageDef *message_p = itti_alloc_new_message(task_id, 0, SCTP_NEW_ASSOCIATION_REQ); + sctp_new_association_req_t *sctp_new_req = &message_p->ittiMsg.sctp_new_association_req; + sctp_new_req->ulp_cnx_id = instance; + sctp_new_req->port = E1AP_PORT_NUMBER; + sctp_new_req->ppid = E1AP_SCTP_PPID; + sctp_new_req->in_streams = e1ap_setup_req->sctp_in_streams; + sctp_new_req->out_streams = e1ap_setup_req->sctp_out_streams; + // remote + sctp_new_req->remote_address = e1ap_setup_req->CUCP_e1_ip_address; + // local + sctp_new_req->local_address = e1ap_setup_req->CUUP_e1_ip_address; + itti_send_msg_to_task(TASK_SCTP, instance, message_p); +} + +static void e1apCUUP_send_SETUP_REQUEST(e1ap_setup_req_t *setup) +{ + E1AP_E1AP_PDU_t pdu = {0}; + fill_SETUP_REQUEST(setup, &pdu); + e1ap_encode_send(UPtype, setup, &pdu, 0, __func__); +} + +static void e1_task_handle_sctp_association_resp(E1_t type, instance_t instance, sctp_new_association_resp_t *sctp_new_association_resp) +{ + DevAssert(sctp_new_association_resp != NULL); + getCxtE1(instance)->sockState = sctp_new_association_resp->sctp_state; + if (sctp_new_association_resp->sctp_state != SCTP_STATE_ESTABLISHED) { + LOG_W(E1AP, "Received unsuccessful result for SCTP association (%u), instance %ld, cnx_id %u\n", + sctp_new_association_resp->sctp_state, + instance, + sctp_new_association_resp->ulp_cnx_id); + long timer_id; // if we want to cancel timer + timer_setup(1, 0, TASK_CUUP_E1, 0, TIMER_ONE_SHOT, NULL, &timer_id); + return; + } + + if (type == UPtype) { + e1ap_setup_req_t *e1ap_cuup_setup_req = &getCxtE1(instance)->setupReq; + e1ap_cuup_setup_req->assoc_id = sctp_new_association_resp->assoc_id; + e1ap_cuup_setup_req->sctp_in_streams = sctp_new_association_resp->in_streams; + e1ap_cuup_setup_req->sctp_out_streams = sctp_new_association_resp->out_streams; + e1ap_cuup_setup_req->default_sctp_stream_id = 0; + + eth_params_t IPaddr; + IPaddr.my_addr = e1ap_cuup_setup_req->localAddressF1U; + IPaddr.my_portd = e1ap_cuup_setup_req->localPortF1U; + if (getCxtE1(instance)->gtpInstF1U < 0) + getCxtE1(instance)->gtpInstF1U = cuup_task_create_gtpu_instance_to_du(&IPaddr); + if (getCxtE1(instance)->gtpInstF1U < 0) + LOG_E(E1AP, "Failed to create CUUP F1-U UDP listener"); + extern instance_t CUuniqInstance; + CUuniqInstance = getCxtE1(instance)->gtpInstF1U; + cuup_init_n3(instance); + e1apCUUP_send_SETUP_REQUEST(&getCxtE1(instance)->setupReq); + } +} + +void cuup_init_n3(instance_t instance) +{ + if (getCxtE1(instance)->gtpInstN3 < 0) { + e1ap_setup_req_t *setup = &getCxtE1(instance)->setupReq; + openAddr_t tmp = {0}; + strcpy(tmp.originHost, setup->localAddressN3); + sprintf(tmp.originService, "%d", setup->localPortN3); + sprintf(tmp.destinationService, "%d", setup->remotePortN3); + LOG_I(GTPU, "Configuring GTPu address : %s, port : %s\n", tmp.originHost, tmp.originService); + // Fixme: fully inconsistent instances management + // dirty global var is a bad fix + extern instance_t legacyInstanceMapping; + legacyInstanceMapping = getCxtE1(instance)->gtpInstN3 = gtpv1Init(tmp); + } + if (getCxtE1(instance)->gtpInstN3 < 0) + LOG_E(E1AP, "Failed to create CUUP N3 UDP listener"); + extern instance_t *N3GTPUInst; + N3GTPUInst = &getCxtE1(instance)->gtpInstN3; +} + +void cucp_task_send_sctp_init_req(instance_t instance, char *my_addr) { + LOG_I(E1AP, "E1AP_CUCP_SCTP_REQ(create socket)\n"); + MessageDef *message_p = NULL; + message_p = itti_alloc_new_message (TASK_CUCP_E1, 0, SCTP_INIT_MSG); + message_p->ittiMsg.sctp_init.port = E1AP_PORT_NUMBER; + message_p->ittiMsg.sctp_init.ppid = E1AP_SCTP_PPID; + message_p->ittiMsg.sctp_init.ipv4 = 1; + message_p->ittiMsg.sctp_init.ipv6 = 0; + message_p->ittiMsg.sctp_init.nb_ipv4_addr = 1; + message_p->ittiMsg.sctp_init.ipv4_address[0] = inet_addr(my_addr); + /* + * SR WARNING: ipv6 multi-homing fails sometimes for localhost. + * * * * Disable it for now. + */ + message_p->ittiMsg.sctp_init.nb_ipv6_addr = 0; + message_p->ittiMsg.sctp_init.ipv6_address[0] = "0:0:0:0:0:0:0:1"; + itti_send_msg_to_task(TASK_SCTP, instance, message_p); +} + +void e1_task_handle_sctp_association_ind(E1_t type, instance_t instance, sctp_new_association_ind_t *sctp_new_ind) +{ + if (getCxtE1(instance)) + LOG_W(E1AP, "CUCP incoming call, re-use older socket context, finish implementation required\n"); + else + createE1inst(type, instance, NULL); + getCxtE1(instance)->sockState = SCTP_STATE_ESTABLISHED; + getCxtE1(instance)->incoming_sock = true; + e1ap_setup_req_t *setup_req = &getCxtE1(instance)->setupReq; + setup_req->assoc_id = sctp_new_ind->assoc_id; + setup_req->sctp_in_streams = sctp_new_ind->in_streams; + setup_req->sctp_out_streams = sctp_new_ind->out_streams; + setup_req->default_sctp_stream_id = 0; +} + +void e1apHandleTimer(instance_t myInstance) +{ + LOG_W(E1AP, "Try to reconnect to CP\n"); + if (getCxtE1(myInstance)->sockState != SCTP_STATE_ESTABLISHED) + e1_task_send_sctp_association_req(TASK_CUUP_E1, myInstance, &getCxtE1(myInstance)->setupReq); +} + +void *E1AP_CUCP_task(void *arg) { + LOG_I(E1AP, "Starting E1AP at CU CP\n"); + MessageDef *msg = NULL; + e1ap_common_init(); + int result; + + while (1) { + itti_receive_msg(TASK_CUCP_E1, &msg); + instance_t myInstance=ITTI_MSG_DESTINATION_INSTANCE(msg); + const int msgType = ITTI_MSG_ID(msg); + LOG_I(E1AP, "CUCP received %s for instance %ld\n", messages_info[msgType].name, myInstance); + + switch (ITTI_MSG_ID(msg)) { + case SCTP_NEW_ASSOCIATION_IND: + e1_task_handle_sctp_association_ind(CPtype, ITTI_MSG_ORIGIN_INSTANCE(msg), &msg->ittiMsg.sctp_new_association_ind); + break; + + case SCTP_NEW_ASSOCIATION_RESP: + e1_task_handle_sctp_association_resp(CPtype, ITTI_MSG_ORIGIN_INSTANCE(msg), &msg->ittiMsg.sctp_new_association_resp); + break; + + case E1AP_SETUP_REQ: { + e1ap_setup_req_t *req = &E1AP_SETUP_REQ(msg); + if (req->CUCP_e1_ip_address.ipv4 == 0) { + LOG_E(E1AP, "No IPv4 address configured\n"); + return NULL; + } + cucp_task_send_sctp_init_req(0, req->CUCP_e1_ip_address.ipv4_address); + } break; + + case SCTP_DATA_IND: + e1_task_handle_sctp_data_ind(myInstance, &msg->ittiMsg.sctp_data_ind); + break; + + case E1AP_SETUP_RESP: + e1ap_send_SETUP_RESPONSE(myInstance, &E1AP_SETUP_RESP(msg)); + break; + + case E1AP_BEARER_CONTEXT_SETUP_REQ: + e1apCUCP_send_BEARER_CONTEXT_SETUP_REQUEST(myInstance, &E1AP_BEARER_CONTEXT_SETUP_REQ(msg)); + break; + + case E1AP_BEARER_CONTEXT_MODIFICATION_REQ: + e1apCUCP_send_BEARER_CONTEXT_MODIFICATION_REQUEST(myInstance, &E1AP_BEARER_CONTEXT_SETUP_REQ(msg)); + break; + + default: + LOG_E(E1AP, "Unknown message received in TASK_CUCP_E1\n"); + break; + } + + result = itti_free(ITTI_MSG_ORIGIN_ID(msg), msg); + AssertFatal(result == EXIT_SUCCESS, "Failed to free memory (%d) in E1AP_CUCP_task!\n", result); + msg = NULL; + + } +} + +void *E1AP_CUUP_task(void *arg) { + LOG_I(E1AP, "Starting E1AP at CU UP\n"); + e1ap_common_init(); + int result; + + // SCTP + while (1) { + MessageDef *msg = NULL; + itti_receive_msg(TASK_CUUP_E1, &msg); + const instance_t myInstance = ITTI_MSG_DESTINATION_INSTANCE(msg); + const int msgType = ITTI_MSG_ID(msg); + LOG_I(E1AP, "CUUP received %s for instance %ld\n", messages_info[msgType].name, myInstance); + switch (msgType) { + case E1AP_SETUP_REQ: { + e1ap_setup_req_t *msgSetup = &E1AP_SETUP_REQ(msg); + createE1inst(UPtype, myInstance, msgSetup); + + e1_task_send_sctp_association_req(TASK_CUUP_E1, myInstance, msgSetup); + } break; + + case SCTP_NEW_ASSOCIATION_RESP: + e1_task_handle_sctp_association_resp(UPtype, myInstance, &msg->ittiMsg.sctp_new_association_resp); + break; + + case SCTP_DATA_IND: + e1_task_handle_sctp_data_ind(myInstance, &msg->ittiMsg.sctp_data_ind); + break; + + case TIMER_HAS_EXPIRED: + e1apHandleTimer(myInstance); + break; + + default: + LOG_E(E1AP, "Unknown message received in TASK_CUUP_E1\n"); + break; + } + + result = itti_free(ITTI_MSG_ORIGIN_ID(msg), msg); + AssertFatal(result == EXIT_SUCCESS, "Failed to free memory (%d) in E1AP_CUUP_task!\n", result); + msg = NULL; + + } +} + diff --git a/openair2/E1AP/e1ap.h b/openair2/E1AP/e1ap.h index ef22152648..af1dcae363 100644 --- a/openair2/E1AP/e1ap.h +++ b/openair2/E1AP/e1ap.h @@ -24,11 +24,33 @@ #ifndef __E1AP_H_ #define __E1AP_H_ -#include -#include "common/openairinterface5g_limits.h" -#include +#include "openair2/COMMON/e1ap_messages_types.h" +#include "e1ap_asnc.h" +#include "openair2/E1AP/e1ap_common.h" -#include -#include -#include +int e1apCUCP_handle_SETUP_REQUEST(e1ap_upcp_inst_t *inst, const E1AP_E1AP_PDU_t *pdu); + +int e1apCUUP_handle_SETUP_RESPONSE(e1ap_upcp_inst_t *inst, const E1AP_E1AP_PDU_t *pdu); + +int e1apCUUP_handle_SETUP_FAILURE(e1ap_upcp_inst_t *inst, const E1AP_E1AP_PDU_t *pdu); + +int e1apCUUP_handle_BEARER_CONTEXT_SETUP_REQUEST(e1ap_upcp_inst_t *inst, const E1AP_E1AP_PDU_t *pdu); + +int e1apCUCP_handle_BEARER_CONTEXT_SETUP_RESPONSE(e1ap_upcp_inst_t *inst, const E1AP_E1AP_PDU_t *pdu); + +int e1apCUCP_handle_BEARER_CONTEXT_SETUP_FAILURE(e1ap_upcp_inst_t *inst, const E1AP_E1AP_PDU_t *pdu); + +int e1apCUUP_handle_BEARER_CONTEXT_MODIFICATION_REQUEST(e1ap_upcp_inst_t *inst, const E1AP_E1AP_PDU_t *pdu); + +void e1apCUUP_send_BEARER_CONTEXT_SETUP_RESPONSE(e1ap_upcp_inst_t *inst, e1ap_bearer_setup_resp_t *const resp); + +int e1apCUUP_handle_BEARER_CONTEXT_RELEASE_COMMAND(e1ap_upcp_inst_t *inst, const E1AP_E1AP_PDU_t *pdu); + +int e1apCUCP_handle_BEARER_CONTEXT_RELEASE_COMPLETE(e1ap_upcp_inst_t *inst, const E1AP_E1AP_PDU_t *pdu); + +int e1apCUUP_send_BEARER_CONTEXT_RELEASE_COMPLETE(e1ap_upcp_inst_t *inst, e1ap_bearer_release_cmd_t *const cmd); + +void *E1AP_CUUP_task(void *arg); + +void *E1AP_CUCP_task(void *arg); #endif diff --git a/openair2/E1AP/e1ap_api.c b/openair2/E1AP/e1ap_api.c new file mode 100644 index 0000000000..23a9fcd1ea --- /dev/null +++ b/openair2/E1AP/e1ap_api.c @@ -0,0 +1,195 @@ +/* + * 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 + * + * Author and copyright: Laurent Thomas, open-cells.com + * + * 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 +#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/ocp-gtpu/gtp_itf.h" +#include "e1ap_asnc.h" +#include "e1ap_common.h" +#include "e1ap.h" + +struct NR_DRB_ToAddMod; +static void fill_DRB_configList_e1(NR_DRB_ToAddModList_t *DRB_configList, pdu_session_to_setup_t *pdu) { + + for (int i=0; i < pdu->numDRB2Setup; i++) { + DRB_nGRAN_to_setup_t *drb = pdu->DRBnGRanList + i; + asn1cSequenceAdd(DRB_configList->list, struct NR_DRB_ToAddMod, ie); + ie->drb_Identity = drb->id; + ie->cnAssociation = CALLOC(1, sizeof(*ie->cnAssociation)); + ie->cnAssociation->present = NR_DRB_ToAddMod__cnAssociation_PR_sdap_Config; + + // sdap_Config + asn1cCalloc(ie->cnAssociation->choice.sdap_Config, sdap_config); + sdap_config->pdu_Session = pdu->sessionId; + sdap_config->sdap_HeaderDL = drb->sDAP_Header_DL; + sdap_config->sdap_HeaderUL = drb->sDAP_Header_UL; + sdap_config->defaultDRB = drb->defaultDRB; + + asn1cCalloc(sdap_config->mappedQoS_FlowsToAdd, FlowsToAdd); + for (int j=0; j < drb->numQosFlow2Setup; j++) { + asn1cSequenceAdd(FlowsToAdd->list, NR_QFI_t, qfi); + *qfi = drb->qosFlows[j].fiveQI; + } + sdap_config->mappedQoS_FlowsToRelease = NULL; + + // pdcp_Config + ie->reestablishPDCP = NULL; + ie->recoverPDCP = NULL; + asn1cCalloc(ie->pdcp_Config, pdcp_config); + asn1cCalloc(pdcp_config->drb, drbCfg); + asn1cCallocOne(drbCfg->discardTimer, drb->discardTimer); + asn1cCallocOne(drbCfg->pdcp_SN_SizeUL, drb->pDCP_SN_Size_UL); + asn1cCallocOne(drbCfg->pdcp_SN_SizeDL, drb->pDCP_SN_Size_DL); + drbCfg->headerCompression.present = NR_PDCP_Config__drb__headerCompression_PR_notUsed; + drbCfg->headerCompression.choice.notUsed = 0; + + drbCfg->integrityProtection = NULL; + drbCfg->statusReportRequired = NULL; + drbCfg->outOfOrderDelivery = NULL; + pdcp_config->moreThanOneRLC = NULL; + + pdcp_config->t_Reordering = calloc(1, sizeof(*pdcp_config->t_Reordering)); + *pdcp_config->t_Reordering = drb->reorderingTimer; + pdcp_config->ext1 = NULL; + + if (pdu->integrityProtectionIndication == 0 || // Required + pdu->integrityProtectionIndication == 1) { // Preferred + asn1cCallocOne(drbCfg->integrityProtection, NR_PDCP_Config__drb__integrityProtection_enabled); + } + + if (pdu->confidentialityProtectionIndication == 0 || // Required + pdu->confidentialityProtectionIndication == 1) { // Preferred + asn1cCalloc(pdcp_config->ext1, ext1); + asn1cCallocOne(ext1->cipheringDisabled, NR_PDCP_Config__ext1__cipheringDisabled_true); + } + } +} + +static int drb_config_N3gtpu_create(e1ap_bearer_setup_req_t * const req, + gtpv1u_gnb_create_tunnel_resp_t *create_tunnel_resp, + instance_t instance) { + + gtpv1u_gnb_create_tunnel_req_t create_tunnel_req={0}; + + NR_DRB_ToAddModList_t DRB_configList = {0}; + for (int i=0; i < req->numPDUSessions; i++) { + pdu_session_to_setup_t *const pdu = &req->pduSession[i]; + create_tunnel_req.pdusession_id[i] = pdu->sessionId; + create_tunnel_req.incoming_rb_id[i] = pdu->DRBnGRanList[0].id; // taking only the first DRB. TODO:change this + memcpy(&create_tunnel_req.dst_addr[i].buffer, + &pdu->tlAddress, + sizeof(uint8_t)*4); + create_tunnel_req.dst_addr[i].length = 32; // 8bits * 4bytes + create_tunnel_req.outgoing_teid[i] = pdu->teId; + fill_DRB_configList_e1(&DRB_configList, pdu); + } + create_tunnel_req.num_tunnels = req->numPDUSessions; + create_tunnel_req.ue_id = (req->gNB_cu_cp_ue_id & 0xFFFF); + + // Create N3 tunnel + int ret = gtpv1u_create_ngu_tunnel(instance, + &create_tunnel_req, + create_tunnel_resp); + if (ret != 0) { + LOG_E(NR_RRC,"rrc_gNB_process_NGAP_PDUSESSION_SETUP_REQ : gtpv1u_create_ngu_tunnel failed,start to release UE id %ld\n", + create_tunnel_req.ue_id); + return ret; + } + + // Configure DRBs + uint8_t *kUPenc = NULL; + uint8_t *kUPint = NULL; + + 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_pdcp_e1_add_drbs(true, // set this to notify PDCP that his not UE + create_tunnel_req.ue_id, + &DRB_configList, + (req->integrityProtectionAlgorithm << 4) | req->cipheringAlgorithm, + kUPenc, + kUPint); + return ret; +} + +void process_e1_bearer_context_setup_req(instance_t instance, e1ap_bearer_setup_req_t *const req) +{ + e1ap_upcp_inst_t *inst = getCxtE1(instance); + AssertFatal(inst, ""); + gtpv1u_gnb_create_tunnel_resp_t create_tunnel_resp_N3={0}; + + // GTP tunnel for UL + drb_config_N3gtpu_create(req, &create_tunnel_resp_N3, inst->gtpInstN3); + + MessageDef *msg = itti_alloc_new_message(TASK_CUCP_E1, 0, E1AP_BEARER_CONTEXT_SETUP_RESP); + e1ap_bearer_setup_resp_t *resp = &E1AP_BEARER_CONTEXT_SETUP_RESP(msg); + + in_addr_t my_addr; + if (inet_pton(AF_INET, inst->setupReq.localAddressF1U, &my_addr) != 1) + LOG_E(E1AP, "can't use the F1-U local interface: %s\n", inst->setupReq.localAddressF1U); + fill_e1ap_bearer_setup_resp(resp, req, inst->gtpInstF1U, req->gNB_cu_cp_ue_id, inst->setupReq.remotePortF1U, my_addr); + + resp->gNB_cu_cp_ue_id = req->gNB_cu_cp_ue_id; + resp->numPDUSessions = req->numPDUSessions; + for (int i=0; i < req->numPDUSessions; i++) { + pdu_session_setup_t *pduSetup = resp->pduSession + i; + pdu_session_to_setup_t *pdu2Setup = req->pduSession + i; + + pduSetup->id = pdu2Setup->sessionId; + if (inet_pton(AF_INET, inst->setupReq.localAddressN3, &pduSetup->tlAddress) != 1) + LOG_E(E1AP, "can't use the N3 local interface: %s\n", inst->setupReq.localAddressN3); + pduSetup->teId = create_tunnel_resp_N3.gnb_NGu_teid[i]; + pduSetup->numDRBSetup = pdu2Setup->numDRB2Setup; + + // At this point we don't have a way to know the DRBs that failed to setup + // We assume all DRBs to setup have are setup successfully so we always send successful outcome in response + // TODO: Modify nr_pdcp_add_drbs() to return DRB list that failed to setup to support E1AP + pduSetup->numDRBFailed = 0; + } + + e1apCUUP_send_BEARER_CONTEXT_SETUP_RESPONSE(inst, resp); +} + +void CUUP_process_bearer_context_mod_req(instance_t instance, e1ap_bearer_setup_req_t *const req) +{ + e1ap_upcp_inst_t *inst = getCxtE1(instance); + AssertFatal(inst, ""); + // assume we receive modification of F1-U but it is wrong, we can also get modification of N3 when HO will occur + CU_update_UP_DL_tunnel(req, inst->gtpInstF1U, req->gNB_cu_cp_ue_id); + // TODO: send bearer cxt mod response +} + +void CUUP_process_bearer_release_command(instance_t instance, e1ap_bearer_release_cmd_t *const cmd) +{ + e1ap_upcp_inst_t *inst = getCxtE1(instance); + AssertFatal(inst, ""); + newGtpuDeleteAllTunnels(inst->gtpInstN3, cmd->gNB_cu_up_ue_id); + newGtpuDeleteAllTunnels(inst->gtpInstF1U, cmd->gNB_cu_up_ue_id); + e1apCUUP_send_BEARER_CONTEXT_RELEASE_COMPLETE(inst, cmd); +} diff --git a/openair2/E1AP/e1ap_api.h b/openair2/E1AP/e1ap_api.h new file mode 100644 index 0000000000..1b9f219fcc --- /dev/null +++ b/openair2/E1AP/e1ap_api.h @@ -0,0 +1,35 @@ +/* + * 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 + * + * Author and copyright: Laurent Thomas, open-cells.com + * + * 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 E1AP_API_H +#define E1AP_API_H + +#include "platform_types.h" +#include "openair2/COMMON/e1ap_messages_types.h" +#include "openair2/E1AP/e1ap_common.h" +void cuup_init_n3(instance_t instance); +void process_e1_bearer_context_setup_req(instance_t, e1ap_bearer_setup_req_t *const req); +void CUUP_process_bearer_context_mod_req(instance_t, e1ap_bearer_setup_req_t *const req); + +void CUUP_process_bearer_release_command(instance_t, e1ap_bearer_release_cmd_t *const cmd); +#endif diff --git a/openair2/E1AP/e1ap_asnc.h b/openair2/E1AP/e1ap_asnc.h new file mode 100644 index 0000000000..00dbcc13f3 --- /dev/null +++ b/openair2/E1AP/e1ap_asnc.h @@ -0,0 +1,65 @@ +/* + * 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 + * + * Author and copyright: Laurent Thomas, open-cells.com + * + * 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 E1AP_ASNC_H +#define E1AP_ASNC_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#endif diff --git a/openair2/E1AP/e1ap_common.c b/openair2/E1AP/e1ap_common.c new file mode 100644 index 0000000000..2db1ecef65 --- /dev/null +++ b/openair2/E1AP/e1ap_common.c @@ -0,0 +1,235 @@ +/* + * 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 + * + * Author and copyright: Laurent Thomas, open-cells.com + * + * 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 +#include +#include "e1ap_common.h" +#include "e1ap_default_values.h" +#include "e1ap_asnc.h" +#include "common/openairinterface5g_limits.h" +#include "common/utils/ocp_itti/intertask_interface.h" + +static e1ap_upcp_inst_t *e1ap_inst[NUMBER_OF_gNB_MAX] = {0}; + +e1ap_upcp_inst_t *getCxtE1(instance_t instance) +{ + AssertFatal(instance < sizeofArray(e1ap_inst), "instance exceeds limit\n"); + return e1ap_inst[instance]; +} + +int e1ap_assoc_id(E1_t type, instance_t instance) { + AssertFatal(e1ap_inst[instance] != NULL, "Trying to access uninitiated instance of CUCP\n"); + return e1ap_inst[instance]->setupReq.assoc_id; +} + +void createE1inst(E1_t type, instance_t instance, e1ap_setup_req_t *req) { + AssertFatal(e1ap_inst[instance] == NULL, "Double call to E1 instance %d\n", (int)instance); + e1ap_inst[instance] = calloc(1, sizeof(e1ap_upcp_inst_t)); + e1ap_inst[instance]->type = type; + e1ap_inst[instance]->instance = instance; + if (req) + memcpy(&e1ap_inst[instance]->setupReq, req, sizeof(*req)); + e1ap_inst[instance]->gtpInstN3 = -1; + e1ap_inst[instance]->gtpInstF1U = -1; +} + +E1AP_TransactionID_t transacID[E1AP_MAX_NUM_TRANSAC_IDS] = {0}; + +void e1ap_common_init() { + srand(time(NULL)); +} + +bool check_transac_id(E1AP_TransactionID_t id, int *freeIdx) { + + bool isFreeIdxSet = false; + for (int i=0; i < E1AP_MAX_NUM_TRANSAC_IDS; i++) { + if (id == transacID[i]) + return false; + else if (!isFreeIdxSet && (transacID[i] == 0)) { + *freeIdx = i; + isFreeIdxSet = true; + } + } + + return true; +} + +E1AP_TransactionID_t E1AP_get_next_transaction_identifier() { + E1AP_TransactionID_t genTransacId; + bool isTransacIdValid = false; + int freeIdx; + + while (!isTransacIdValid) { + genTransacId = rand() & 255; + isTransacIdValid = check_transac_id(genTransacId, &freeIdx); + } + + AssertFatal(freeIdx < E1AP_MAX_NUM_TRANSAC_IDS, "Free Index exceeds array length\n"); + transacID[freeIdx] = genTransacId; + return genTransacId; +} + +void E1AP_free_transaction_identifier(E1AP_TransactionID_t id) { + + for (int i=0; i < E1AP_MAX_NUM_TRANSAC_IDS; i++) { + if (id == transacID[i]) { + transacID[i] = 0; + return; + } + } + LOG_E(E1AP, "Couldn't find transaction ID %ld in list\n", id); +} + +int e1ap_decode_initiating_message(E1AP_E1AP_PDU_t *pdu) { + DevAssert(pdu != NULL); + + switch(pdu->choice.initiatingMessage->procedureCode) { + case E1AP_ProcedureCode_id_gNB_CU_UP_E1Setup: + break; + + case E1AP_ProcedureCode_id_gNB_CU_UP_ConfigurationUpdate: + break; + + case E1AP_ProcedureCode_id_bearerContextSetup: + break; + + case E1AP_ProcedureCode_id_bearerContextModification: + break; + + default: + LOG_E(E1AP, "Unsupported procedure code (%d) for initiating message\n", + (int)pdu->choice.initiatingMessage->procedureCode); + return -1; + } + return 0; +} + +int e1ap_decode_successful_outcome(E1AP_E1AP_PDU_t *pdu) { + DevAssert(pdu != NULL); + switch(pdu->choice.successfulOutcome->procedureCode) { + case E1AP_ProcedureCode_id_gNB_CU_UP_E1Setup: + break; + + case E1AP_ProcedureCode_id_bearerContextSetup: + break; + + default: + LOG_E(E1AP, "Unsupported procedure code (%d) for successful message\n", + (int)pdu->choice.successfulOutcome->procedureCode); + return -1; + } + return 0; +} + +int e1ap_decode_unsuccessful_outcome(E1AP_E1AP_PDU_t *pdu) { + DevAssert(pdu != NULL); + switch(pdu->choice.unsuccessfulOutcome->procedureCode) { + case E1AP_ProcedureCode_id_gNB_CU_UP_E1Setup: + break; + + default: + LOG_E(E1AP, "Unsupported procedure code (%d) for unsuccessful message\n", + (int)pdu->choice.unsuccessfulOutcome->procedureCode); + return -1; + } + return 0; +} + +int e1ap_decode_pdu(E1AP_E1AP_PDU_t *pdu, const uint8_t *const buffer, uint32_t length) { + asn_dec_rval_t dec_ret; + DevAssert(buffer != NULL); + dec_ret = aper_decode(NULL, + &asn_DEF_E1AP_E1AP_PDU, + (void **)&pdu, + buffer, + length, + 0, + 0); + + if (LOG_DEBUGFLAG(DEBUG_ASN1)) { + LOG_E(E1AP, "----------------- ASN1 DECODER PRINT START----------------- \n"); + xer_fprint(stdout, &asn_DEF_E1AP_E1AP_PDU, pdu); + LOG_E(E1AP, "----------------- ASN1 DECODER PRINT END ----------------- \n"); + } + + if (dec_ret.code != RC_OK) { + AssertFatal(1==0,"Failed to decode pdu\n"); + return -1; + } + + switch(pdu->present) { + case E1AP_E1AP_PDU_PR_initiatingMessage: + return e1ap_decode_initiating_message(pdu); + + case E1AP_E1AP_PDU_PR_successfulOutcome: + return e1ap_decode_successful_outcome(pdu); + + case E1AP_E1AP_PDU_PR_unsuccessfulOutcome: + return e1ap_decode_unsuccessful_outcome(pdu); + + default: + LOG_E(E1AP, "Unknown presence (%d) or not implemented\n", (int)pdu->present); + break; + } + + return -1; +} + +int e1ap_encode_send(E1_t type, e1ap_setup_req_t *setupReq, E1AP_E1AP_PDU_t *pdu, uint16_t stream, const char *func) +{ + DevAssert(pdu != NULL); + + if (LOG_DEBUGFLAG(DEBUG_ASN1)) { + LOG_E(E1AP, "----------------- ASN1 ENCODER PRINT START ----------------- \n"); + xer_fprint(stdout, &asn_DEF_E1AP_E1AP_PDU, pdu); + LOG_E(E1AP, "----------------- ASN1 ENCODER PRINT END----------------- \n"); + } + + char errbuf[2048]; /* Buffer for error message */ + size_t errlen = sizeof(errbuf); /* Size of the buffer */ + int ret = asn_check_constraints(&asn_DEF_E1AP_E1AP_PDU, pdu, errbuf, &errlen); + + if(ret) { + LOG_E(E1AP, "%s: Constraint validation failed: %s\n", func, errbuf); + } + + void *buffer = NULL; + ssize_t encoded = aper_encode_to_new_buffer(&asn_DEF_E1AP_E1AP_PDU, 0, pdu, &buffer); + ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_E1AP_E1AP_PDU, pdu); + + if (encoded < 0) { + LOG_E(E1AP, "%s: Failed to encode E1AP message\n", func); + return -1; + } else { + MessageDef *message = itti_alloc_new_message((type==CPtype)?TASK_CUCP_E1:TASK_CUUP_E1, 0, SCTP_DATA_REQ); + sctp_data_req_t *s = &message->ittiMsg.sctp_data_req; + s->assoc_id = setupReq->assoc_id; + s->buffer = buffer; + s->buffer_length = encoded; + s->stream = stream; + LOG_I(E1AP, "%s: Sending ITTI message to SCTP Task\n", func); + itti_send_msg_to_task(TASK_SCTP, 0 /*unused by callee*/, message); + } + + return encoded; +} diff --git a/openair2/E1AP/e1ap_common.h b/openair2/E1AP/e1ap_common.h new file mode 100644 index 0000000000..80a2b925e1 --- /dev/null +++ b/openair2/E1AP/e1ap_common.h @@ -0,0 +1,64 @@ +/* + * 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 + * + * Author and copyright: Laurent Thomas, open-cells.com + * + * 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 E1AP_COMMON_H_ +#define E1AP_COMMON_H_ +#include "openair2/COMMON/e1ap_messages_types.h" +#include "e1ap_asnc.h" +#include "openair2/COMMON/sctp_messages_types.h" +#include "common/ngran_types.h" + +typedef struct e1ap_upcp_inst_s { + bool incoming_sock; + instance_t instance; + bool same_process; + E1_t type; + enum sctp_state_e sockState; + uint32_t assoc_id; + instance_t gtpInstN3; + instance_t gtpInstF1U; + e1ap_setup_req_t setupReq; + e1ap_bearer_setup_req_t bearerSetupReq; + e1ap_bearer_setup_resp_t bearerSetupResp; +} e1ap_upcp_inst_t; + +extern int asn1_xer_print; + +int e1ap_decode_pdu(E1AP_E1AP_PDU_t *pdu, const uint8_t *const buffer, uint32_t length); + +e1ap_upcp_inst_t *getCxtE1(instance_t instance); + +E1AP_TransactionID_t E1AP_get_next_transaction_identifier(); + +void createE1inst(E1_t type, instance_t instance, e1ap_setup_req_t *req); + +bool check_transac_id(E1AP_TransactionID_t id, int *freeIdx); + +int e1ap_assoc_id(E1_t type, instance_t instance); + +int e1ap_encode_send(E1_t type, e1ap_setup_req_t *setupReq, E1AP_E1AP_PDU_t *pdu, uint16_t stream, const char *func); + +void e1ap_common_init(); + +void E1AP_free_transaction_identifier(E1AP_TransactionID_t id); +#endif /* E1AP_COMMON_H_ */ diff --git a/executables/create_nr_tasks.h b/openair2/E1AP/e1ap_default_values.h similarity index 88% rename from executables/create_nr_tasks.h rename to openair2/E1AP/e1ap_default_values.h index 23dd23e7db..f5980031df 100644 --- a/executables/create_nr_tasks.h +++ b/openair2/E1AP/e1ap_default_values.h @@ -19,11 +19,10 @@ * contact@openairinterface.org */ -#ifndef CREATE_NR_TASKS_H_ -#define CREATE_NR_TASKS_H_ +#ifndef E1AP_DEFAULT_VALUES_H +#define E1AP_DEFAULT_VALUES_H +#define E1AP_PORT_NUMBER (38462) +#define E1AP_SCTP_PPID (64) -int create_gNB_tasks(uint32_t gnb_nb); - - -#endif /* CREATE_TASKS_H_ */ +#endif diff --git a/openair2/E1AP/e1ap_setup.c b/openair2/E1AP/e1ap_setup.c new file mode 100644 index 0000000000..349e3dcab5 --- /dev/null +++ b/openair2/E1AP/e1ap_setup.c @@ -0,0 +1,129 @@ +/* + * 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 +#include +#include +#include "common/utils/LOG/log.h" +#include "common/utils/nr/nr_common.h" +#include "common/utils/LOG/log_extern.h" +#include "assertions.h" +#include "common/utils/ocp_itti/intertask_interface.h" +#include "openair2/GNB_APP/gnb_paramdef.h" +#include "openair3/ocp-gtpu/gtp_itf.h" + +static void get_NGU_S1U_addr(char **addr, uint16_t *port) +{ + int num_gnbs = 0; + char *gnb_ipv4_address_for_NGU = NULL; + uint32_t gnb_port_for_NGU = 0; + char *gnb_ipv4_address_for_S1U = NULL; + uint32_t gnb_port_for_S1U = 0; + char gtpupath[MAX_OPTNAME_SIZE * 2 + 8]; + + paramdef_t GNBSParams[] = GNBSPARAMS_DESC; + paramdef_t NETParams[] = GNBNETPARAMS_DESC; + LOG_I(GTPU, "Configuring GTPu\n"); + + /* get number of active eNodeBs */ + config_get(GNBSParams, sizeof(GNBSParams) / sizeof(paramdef_t), NULL); + num_gnbs = GNBSParams[GNB_ACTIVE_GNBS_IDX].numelt; + AssertFatal(num_gnbs > 0, "Failed to parse config file no active gNodeBs in %s \n", GNB_CONFIG_STRING_ACTIVE_GNBS); + + sprintf(gtpupath, "%s.[%i].%s", GNB_CONFIG_STRING_GNB_LIST, 0, GNB_CONFIG_STRING_NETWORK_INTERFACES_CONFIG); + config_get(NETParams, sizeof(NETParams) / sizeof(paramdef_t), gtpupath); + char *address; + if (NETParams[1].strptr != NULL) { + LOG_I(GTPU, "SA mode \n"); + address = strdup(gnb_ipv4_address_for_NGU); + *port = gnb_port_for_NGU; + } else { + LOG_I(GTPU, "NSA mode \n"); + address = strdup(gnb_ipv4_address_for_S1U); + *port = gnb_port_for_S1U; + } + if (strchr(address, '/')) + *strchr(address, '/') = 0; + *addr = address; + return; +} + +MessageDef *RCconfig_NR_CU_E1(bool separate_CUUP_process) +{ + MessageDef *msgConfig = itti_alloc_new_message(TASK_GNB_APP, 0, E1AP_SETUP_REQ); + if (!msgConfig) + return NULL; + + paramdef_t GNBSParams[] = GNBSPARAMS_DESC; + paramdef_t GNBParams[] = GNBPARAMS_DESC; + paramlist_def_t GNBParamList = {GNB_CONFIG_STRING_GNB_LIST, NULL, 0}; + config_get(GNBSParams, sizeofArray(GNBSParams), NULL); + char aprefix[MAX_OPTNAME_SIZE * 2 + 8]; + sprintf(aprefix, "%s.[%i]", GNB_CONFIG_STRING_GNB_LIST, 0); + int num_gnbs = GNBSParams[GNB_ACTIVE_GNBS_IDX].numelt; + AssertFatal(num_gnbs == 1, "Support only one gNB per process\n"); + + if (num_gnbs > 0) { + config_getlist(&GNBParamList, GNBParams, sizeofArray(GNBParams), NULL); + paramdef_t *gnbParms = GNBParamList.paramarray[0]; + AssertFatal(gnbParms[GNB_GNB_ID_IDX].uptr != NULL, "gNB id %u is not defined in configuration file\n", 0); + e1ap_setup_req_t *e1Setup = &E1AP_SETUP_REQ(msgConfig); + msgConfig->ittiMsgHeader.destinationInstance = 0; + e1Setup->gNB_cu_up_id = *(gnbParms[GNB_GNB_ID_IDX].uptr); + + paramdef_t PLMNParams[] = GNBPLMNPARAMS_DESC; + paramlist_def_t PLMNParamList = {GNB_CONFIG_STRING_PLMN_LIST, NULL, 0}; + /* map parameter checking array instances to parameter definition array instances */ + checkedparam_t config_check_PLMNParams[] = PLMNPARAMS_CHECK; + + for (int I = 0; I < sizeofArray(PLMNParams); ++I) + PLMNParams[I].chkPptr = &(config_check_PLMNParams[I]); + + config_getlist(&PLMNParamList, PLMNParams, sizeofArray(PLMNParams), aprefix); + int numPLMNs = PLMNParamList.numelt; + e1Setup->supported_plmns = numPLMNs; + + for (int I = 0; I < numPLMNs; I++) { + e1Setup->plmns[I].mcc = *PLMNParamList.paramarray[I][GNB_MOBILE_COUNTRY_CODE_IDX].uptr; + e1Setup->plmns[I].mnc = *PLMNParamList.paramarray[I][GNB_MOBILE_NETWORK_CODE_IDX].uptr; + e1Setup->plmns[I].mnc = *PLMNParamList.paramarray[I][GNB_MNC_DIGIT_LENGTH].u8ptr; + } + + e1Setup->remotePortF1U = *(GNBParamList.paramarray[0][GNB_REMOTE_S_PORTD_IDX].uptr); + e1Setup->localAddressF1U = strdup(*(GNBParamList.paramarray[0][GNB_LOCAL_S_ADDRESS_IDX].strptr)); + e1Setup->localPortF1U = *(GNBParamList.paramarray[0][GNB_LOCAL_S_PORTD_IDX].uptr); + get_NGU_S1U_addr(&e1Setup->localAddressN3, &e1Setup->localPortN3); + e1Setup->remotePortN3 = GTPV1_U_PORT_NUMBER; + + if (separate_CUUP_process) { + paramlist_def_t GNBE1ParamList = {GNB_CONFIG_STRING_E1_PARAMETERS, NULL, 0}; + paramdef_t GNBE1Params[] = GNBE1PARAMS_DESC; + config_getlist(&GNBE1ParamList, GNBE1Params, sizeofArray(GNBE1Params), aprefix); + paramdef_t *e1Parms = GNBE1ParamList.paramarray[0]; + strcpy(e1Setup->CUCP_e1_ip_address.ipv4_address, *(e1Parms[GNB_CONFIG_E1_IPV4_ADDRESS_CUCP].strptr)); + e1Setup->CUCP_e1_ip_address.ipv4 = 1; + strcpy(e1Setup->CUUP_e1_ip_address.ipv4_address, *(e1Parms[GNB_CONFIG_E1_IPV4_ADDRESS_CUUP].strptr)); + e1Setup->CUUP_e1_ip_address.ipv4 = 1; + e1Setup->cn_support = *e1Parms[GNB_CONFIG_E1_CN_SUPPORT].uptr; + } + } + return msgConfig; +} diff --git a/openair2/ENB_APP/enb_app.c b/openair2/ENB_APP/enb_app.c index 98ddaebfdc..9a0ed3f04a 100644 --- a/openair2/ENB_APP/enb_app.c +++ b/openair2/ENB_APP/enb_app.c @@ -40,7 +40,8 @@ # include "intertask_interface.h" # include "s1ap_eNB.h" -#include "sctp_eNB_task.h" +# include "sctp_eNB_task.h" +# include "openair3/ocp-gtpu/gtp_itf.h" # include "x2ap_eNB.h" # include "x2ap_messages_types.h" diff --git a/openair2/ENB_APP/enb_config.c b/openair2/ENB_APP/enb_config.c index fbb5fd0225..776c89c02b 100644 --- a/openair2/ENB_APP/enb_config.c +++ b/openair2/ENB_APP/enb_config.c @@ -2015,7 +2015,7 @@ int RCconfig_gtpu(void ) { int num_enbs = 0; char *enb_interface_name_for_S1U = NULL; char *enb_ipv4_address_for_S1U = NULL; - uint32_t enb_port_for_S1U = 0; + uint16_t enb_port_for_S1U = 0; char *address = NULL; char *cidr = NULL; char gtpupath[MAX_OPTNAME_SIZE*2 + 8]; diff --git a/openair2/ENB_APP/enb_paramdef.h b/openair2/ENB_APP/enb_paramdef.h index 1f2ca6392f..647ac96c18 100644 --- a/openair2/ENB_APP/enb_paramdef.h +++ b/openair2/ENB_APP/enb_paramdef.h @@ -1123,12 +1123,13 @@ typedef struct srb1_params_s { /* S1/X2 interface configuration parameters */ /* optname helpstr paramflags XXXptr defXXXval type numelt */ /*--------------------------------------------------------------------------------------------------------------------------------------------------*/ +// clang-format off #define NETPARAMS_DESC { \ {ENB_CONFIG_STRING_ENB_INTERFACE_NAME_FOR_S1_MME, NULL, 0, strptr:NULL, defstrval:NULL, TYPE_STRING, 0}, \ {ENB_CONFIG_STRING_ENB_IPV4_ADDRESS_FOR_S1_MME, NULL, 0, strptr:NULL, defstrval:NULL, TYPE_STRING, 0}, \ {ENB_CONFIG_STRING_ENB_INTERFACE_NAME_FOR_S1U, NULL, 0, strptr:NULL, defstrval:NULL, TYPE_STRING, 0}, \ {ENB_CONFIG_STRING_ENB_IPV4_ADDR_FOR_S1U, NULL, 0, strptr:NULL, defstrval:NULL, TYPE_STRING, 0}, \ - {ENB_CONFIG_STRING_ENB_PORT_FOR_S1U, NULL, 0, uptr:NULL, defintval:2152L, TYPE_UINT, 0}, \ + {ENB_CONFIG_STRING_ENB_PORT_FOR_S1U, NULL, 0, u16ptr:NULL, defuintval:GTPV1_U_PORT_NUMBER, TYPE_UINT16, 0}, \ {ENB_CONFIG_STRING_ENB_IPV4_ADDR_FOR_X2C, NULL, 0, strptr:NULL, defstrval:NULL, TYPE_STRING, 0}, \ {ENB_CONFIG_STRING_ENB_PORT_FOR_X2C, NULL, 0, uptr:NULL, defintval:0L, TYPE_UINT, 0}, \ {ENB_CONFIG_STRING_ENB_IPV4_ADDR_FOR_M2C, NULL, 0, strptr:NULL, defstrval:NULL, TYPE_STRING, 0}, \ @@ -1144,8 +1145,10 @@ typedef struct srb1_params_s { #define GTPUPARAMS_DESC { \ {ENB_CONFIG_STRING_ENB_INTERFACE_NAME_FOR_S1U, NULL, 0, strptr:&enb_interface_name_for_S1U, defstrval:"lo", TYPE_STRING, 0}, \ {ENB_CONFIG_STRING_ENB_IPV4_ADDR_FOR_S1U, NULL, 0, strptr:&enb_ipv4_address_for_S1U, defstrval:"127.0.0.1", TYPE_STRING, 0}, \ - {ENB_CONFIG_STRING_ENB_PORT_FOR_S1U, NULL, 0, uptr:&enb_port_for_S1U, defintval:2152, TYPE_UINT, 0} \ + {ENB_CONFIG_STRING_ENB_PORT_FOR_S1U, NULL, 0, u16ptr:&enb_port_for_S1U, defuintval:GTPV1_U_PORT_NUMBER, TYPE_UINT16, 0} \ } +// clang-format on + /*-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/ diff --git a/openair2/F1AP/dummy_enb.c b/openair2/F1AP/dummy_enb.c index afb4a1048a..942e652213 100644 --- a/openair2/F1AP/dummy_enb.c +++ b/openair2/F1AP/dummy_enb.c @@ -26,12 +26,6 @@ #include "NR_ServingCellConfigCommon.h" #include "NR_MIB.h" -void apply_macrlc_config(gNB_RRC_INST *rrc, - rrc_gNB_ue_context_t *const ue_context_pP, - const protocol_ctxt_t *const ctxt_pP ) { - abort(); -} - bool sdap_data_req(protocol_ctxt_t *ctxt_p, const ue_id_t ue_id, const srb_flag_t srb_flag, diff --git a/openair2/F1AP/f1ap_cu_interface_management.c b/openair2/F1AP/f1ap_cu_interface_management.c index 39274cdf38..0dfcefaef3 100644 --- a/openair2/F1AP/f1ap_cu_interface_management.c +++ b/openair2/F1AP/f1ap_cu_interface_management.c @@ -144,7 +144,9 @@ int CU_handle_F1_SETUP_REQUEST(instance_t instance, // LTS: FIXME data model failure: we don't KNOW if we receive a 4G or a 5G cell // Furthermore, cell_type is not a attribute of a cell in the data structure !!!!!!!!!! - if (RC.nrrrc && RC.nrrrc[GNB_INSTANCE_TO_MODULE_ID(instance)]->node_type == ngran_gNB_CU) + if (RC.nrrrc && + ( RC.nrrrc[GNB_INSTANCE_TO_MODULE_ID(instance)]->node_type == ngran_gNB_CU || + RC.nrrrc[GNB_INSTANCE_TO_MODULE_ID(instance)]->node_type == ngran_gNB_CUCP) ) f1ap_req(true, instance)->cell_type=CELL_MACRO_GNB; else f1ap_req(true, instance)->cell_type=CELL_MACRO_ENB; diff --git a/openair2/F1AP/f1ap_cu_task.c b/openair2/F1AP/f1ap_cu_task.c index b4e0c1ad2a..09b3651035 100644 --- a/openair2/F1AP/f1ap_cu_task.c +++ b/openair2/F1AP/f1ap_cu_task.c @@ -57,8 +57,11 @@ static void cu_task_handle_sctp_association_ind(instance_t instance, sctp_new_as f1ap_cu_data->sctp_in_streams = sctp_new_association_ind->in_streams; f1ap_cu_data->sctp_out_streams = sctp_new_association_ind->out_streams; f1ap_cu_data->default_sctp_stream_id = 0; - getCxt(CUtype, instance)->gtpInst=cu_task_create_gtpu_instance(IPaddrs); - AssertFatal(getCxt(CUtype, instance)->gtpInst>0,"Failed to create CU F1-U UDP listener"); + if (RC.nrrrc[GNB_INSTANCE_TO_MODULE_ID(instance)]->node_type != ngran_gNB_CUCP) { + getCxt(CUtype, instance)->gtpInst = cu_task_create_gtpu_instance(IPaddrs); + AssertFatal(getCxt(CUtype, instance)->gtpInst > 0, "Failed to create CU F1-U UDP listener"); + } else + LOG_I(F1AP, "In F1AP connection, don't start GTP-U, as we have also E1AP\n"); // Fixme: fully inconsistent instances management // dirty global var is a bad fix CUuniqInstance=getCxt(CUtype, instance)->gtpInst; @@ -120,7 +123,9 @@ void *F1AP_CU_task(void *arg) { eth_params_t *IPaddrs; // Hardcoded instance id! - if (RC.nrrrc && RC.nrrrc[0]->node_type == ngran_gNB_CU) + if (RC.nrrrc && + (RC.nrrrc[0]->node_type == ngran_gNB_CU || + RC.nrrrc[0]->node_type == ngran_gNB_CUCP ) ) IPaddrs=&RC.nrrrc[0]->eth_params_s; else IPaddrs=&RC.rrc[0]->eth_params_s; @@ -129,71 +134,57 @@ void *F1AP_CU_task(void *arg) { while (1) { itti_receive_msg(TASK_CU_F1, &received_msg); - + LOG_I(F1AP, "CU Task Received %s for instance %ld\n", + ITTI_MSG_NAME(received_msg), ITTI_MSG_DESTINATION_INSTANCE(received_msg)); switch (ITTI_MSG_ID(received_msg)) { case SCTP_NEW_ASSOCIATION_IND: - LOG_I(F1AP, "CU Task Received SCTP_NEW_ASSOCIATION_IND for instance %ld\n", - ITTI_MSG_DESTINATION_INSTANCE(received_msg)); cu_task_handle_sctp_association_ind(ITTI_MSG_ORIGIN_INSTANCE(received_msg), &received_msg->ittiMsg.sctp_new_association_ind, IPaddrs); break; case SCTP_NEW_ASSOCIATION_RESP: - LOG_I(F1AP, "CU Task Received SCTP_NEW_ASSOCIATION_RESP for instance %ld\n", - ITTI_MSG_DESTINATION_INSTANCE(received_msg)); cu_task_handle_sctp_association_resp(ITTI_MSG_DESTINATION_INSTANCE(received_msg), &received_msg->ittiMsg.sctp_new_association_resp); break; case SCTP_DATA_IND: - LOG_I(F1AP, "CU Task Received SCTP_DATA_IND for Instance %ld\n", - ITTI_MSG_DESTINATION_INSTANCE(received_msg)); cu_task_handle_sctp_data_ind(ITTI_MSG_DESTINATION_INSTANCE(received_msg), &received_msg->ittiMsg.sctp_data_ind); break; case F1AP_SETUP_RESP: // from rrc - LOG_I(F1AP, "CU Task Received F1AP_SETUP_RESP\n"); CU_send_F1_SETUP_RESPONSE(ITTI_MSG_DESTINATION_INSTANCE(received_msg), &F1AP_SETUP_RESP(received_msg)); break; case F1AP_GNB_CU_CONFIGURATION_UPDATE: // from rrc - LOG_I(F1AP, "CU Task Received F1AP_GNB_CU_CONFIGURAITON_UPDATE\n"); - // CU_send_f1setup_resp(ITTI_MSG_DESTINATION_INSTANCE(received_msg), - // &F1AP_SETUP_RESP(received_msg)); CU_send_gNB_CU_CONFIGURATION_UPDATE(ITTI_MSG_DESTINATION_INSTANCE(received_msg), &F1AP_GNB_CU_CONFIGURATION_UPDATE(received_msg)); break; case F1AP_DL_RRC_MESSAGE: // from rrc - LOG_I(F1AP, "CU Task Received F1AP_DL_RRC_MESSAGE\n"); CU_send_DL_RRC_MESSAGE_TRANSFER(ITTI_MSG_DESTINATION_INSTANCE(received_msg), &F1AP_DL_RRC_MESSAGE(received_msg)); free(F1AP_DL_RRC_MESSAGE(received_msg).rrc_container); break; case F1AP_UE_CONTEXT_SETUP_REQ: // from rrc - LOG_I(F1AP, "CU Task Received F1AP_UE_CONTEXT_SETUP_REQ\n"); CU_send_UE_CONTEXT_SETUP_REQUEST(ITTI_MSG_DESTINATION_INSTANCE(received_msg), &F1AP_UE_CONTEXT_SETUP_REQ(received_msg)); break; case F1AP_UE_CONTEXT_MODIFICATION_REQ: - LOG_I(F1AP, "CU Task received F1AP_UE_CONTEXT_MODIFICATION_REQ\n"); CU_send_UE_CONTEXT_MODIFICATION_REQUEST(ITTI_MSG_DESTINATION_INSTANCE(received_msg), - &F1AP_UE_CONTEXT_MODIFICATION_REQ(received_msg)); + &F1AP_UE_CONTEXT_SETUP_REQ(received_msg)); break; case F1AP_UE_CONTEXT_RELEASE_CMD: // from rrc - LOG_I(F1AP, "CU Task Received F1AP_UE_CONTEXT_RELEASE_CMD\n"); CU_send_UE_CONTEXT_RELEASE_COMMAND(ITTI_MSG_DESTINATION_INSTANCE(received_msg), &F1AP_UE_CONTEXT_RELEASE_CMD(received_msg)); break; case F1AP_PAGING_IND: - LOG_I(F1AP, "CU Task Received F1AP_PAGING_IND\n"); CU_send_Paging(ITTI_MSG_DESTINATION_INSTANCE(received_msg), &F1AP_PAGING_IND(received_msg)); break; diff --git a/openair2/F1AP/f1ap_cu_ue_context_management.c b/openair2/F1AP/f1ap_cu_ue_context_management.c index 597887b841..d609cb98cb 100644 --- a/openair2/F1AP/f1ap_cu_ue_context_management.c +++ b/openair2/F1AP/f1ap_cu_ue_context_management.c @@ -510,6 +510,7 @@ int CU_send_UE_CONTEXT_SETUP_REQUEST(instance_t instance, /* 12.1.3 uLUPTNLInformation_ToBeSetup_List */ for (int j = 0; j < f1ap_ue_context_setup_req->drbs_to_be_setup[i].up_ul_tnl_length; j++) { + /*Use a dummy teid for the outgoing GTP-U tunnel (DU) which will be updated once we get the UE context setup response from the DU*/ /* Use a dummy address and teid for the outgoing GTP-U tunnel (DU) which will be updated once we get the UE context setup response from the DU */ transport_layer_addr_t addr = { length: 32, buffer: { 0 } }; f1ap_ue_context_setup_req->drbs_to_be_setup[i].up_ul_tnl[j].teid = newGtpuCreateTunnel(getCxt(CUtype, instance)->gtpInst, @@ -1009,7 +1010,7 @@ int CU_handle_UE_CONTEXT_RELEASE_COMPLETE(instance_t instance, f1ap_remove_ue(CUtype, instance, rnti); return 0; } -//void CU_send_UE_CONTEXT_MODIFICATION_REQUEST(F1AP_UEContextModificationRequest_t *UEContextModificationRequest) { + int CU_send_UE_CONTEXT_MODIFICATION_REQUEST(instance_t instance, f1ap_ue_context_setup_t *f1ap_ue_context_modification_req) { F1AP_F1AP_PDU_t pdu= {0}; F1AP_UEContextModificationRequest_t *out; @@ -1477,19 +1478,6 @@ int CU_send_UE_CONTEXT_MODIFICATION_REQUEST(instance_t instance, f1ap_ue_context /* 12.1.3 uLUPTNLInformation_ToBeSetup_List */ for (int j = 0; j < f1ap_ue_context_modification_req->drbs_to_be_setup[i].up_ul_tnl_length; j++) { /* Use a dummy address and teid for the outgoing GTP-U tunnel (DU) which will be updated once we get the UE context modification response from the DU */ - transport_layer_addr_t addr = { length: 32, buffer: { 0 } }; - - f1ap_ue_context_modification_req->drbs_to_be_setup[i].up_ul_tnl[j].teid = newGtpuCreateTunnel(getCxt(CUtype, instance)->gtpInst, - f1ap_ue_context_modification_req->rnti, - f1ap_ue_context_modification_req->drbs_to_be_setup[i].drb_id, - f1ap_ue_context_modification_req->drbs_to_be_setup[i].drb_id, - 0xFFFF, // We will set the right value from DU answer - -1, // no qfi - addr, // We will set the right value from DU answer - f1ap_ue_context_modification_req->drbs_to_be_setup[i].up_dl_tnl[0].port, - cu_f1u_data_req, - NULL); - /* 12.3.1 ULTunnels_ToBeSetup_Item */ asn1cSequenceAdd(drbs_toBeSetupMod_item->uLUPTNLInformation_ToBeSetup_List.list, F1AP_ULUPTNLInformation_ToBeSetup_Item_t, uLUPTNLInformation_ToBeSetup_Item); uLUPTNLInformation_ToBeSetup_Item->uLUPTNLInformation.present = F1AP_UPTransportLayerInformation_PR_gTPTunnel; diff --git a/openair2/F1AP/f1ap_decoder.c b/openair2/F1AP/f1ap_decoder.c index 6d1c60c67d..0085add838 100644 --- a/openair2/F1AP/f1ap_decoder.c +++ b/openair2/F1AP/f1ap_decoder.c @@ -166,7 +166,8 @@ static int f1ap_decode_unsuccessful_outcome(F1AP_F1AP_PDU_t *pdu) { int f1ap_decode_pdu(F1AP_F1AP_PDU_t *pdu, const uint8_t *const buffer, uint32_t length) { asn_dec_rval_t dec_ret; DevAssert(buffer != NULL); - dec_ret = aper_decode(NULL, + asn_codec_ctx_t st={.max_stack_size = 100 * 1000}; + dec_ret = aper_decode(&st, &asn_DEF_F1AP_F1AP_PDU, (void **)&pdu, buffer, diff --git a/openair2/F1AP/f1ap_du_task.c b/openair2/F1AP/f1ap_du_task.c index ac952e0498..c11316e19b 100644 --- a/openair2/F1AP/f1ap_du_task.c +++ b/openair2/F1AP/f1ap_du_task.c @@ -107,18 +107,18 @@ void *F1AP_DU_task(void *arg) { MessageDef *msg = NULL; itti_receive_msg(TASK_DU_F1, &msg); instance_t myInstance=ITTI_MSG_DESTINATION_INSTANCE(msg); - + LOG_I(F1AP, "DU Task Received %s for instance %ld\n", + ITTI_MSG_NAME(msg),myInstance); switch (ITTI_MSG_ID(msg)) { - case F1AP_SETUP_REQ: + case F1AP_SETUP_REQ: { // this is not a true F1 message, but rather an ITTI message sent by enb_app // 1. save the itti msg so that you can use it to sen f1ap_setup_req, fill the f1ap_setup_req message, // 2. store the message in f1ap context, that is also stored in RC // 2. send a sctp_association req - LOG_I(F1AP, "DU Task Received F1AP_SETUP_REQ\n"); - f1ap_setup_req_t *msgSetup=&F1AP_SETUP_REQ(msg); + f1ap_setup_req_t *msgSetup = &F1AP_SETUP_REQ(msg); createF1inst(false, myInstance, msgSetup); - du_task_send_sctp_association_req(myInstance,msgSetup); - break; + du_task_send_sctp_association_req(myInstance, msgSetup); + } break; case F1AP_GNB_CU_CONFIGURATION_UPDATE_ACKNOWLEDGE: DU_send_gNB_CU_CONFIGURATION_UPDATE_ACKNOWLEDGE(ITTI_MSG_ORIGIN_INSTANCE(msg), @@ -133,32 +133,23 @@ void *F1AP_DU_task(void *arg) { case SCTP_NEW_ASSOCIATION_RESP: // 1. store the respon // 2. send the f1setup_req - LOG_I(F1AP, "DU Task Received SCTP_NEW_ASSOCIATION_RESP\n"); du_task_handle_sctp_association_resp(myInstance, &msg->ittiMsg.sctp_new_association_resp); break; case SCTP_DATA_IND: // ex: any F1 incoming message for DU ends here - LOG_I(F1AP, "DU Task Received SCTP_DATA_IND\n"); du_task_handle_sctp_data_ind(myInstance, &msg->ittiMsg.sctp_data_ind); break; case F1AP_INITIAL_UL_RRC_MESSAGE: // from rrc - LOG_I(F1AP, "DU Task Received F1AP_INITIAL_UL_RRC_MESSAGE\n"); + { f1ap_initial_ul_rrc_message_t *msgRrc = &F1AP_INITIAL_UL_RRC_MESSAGE(msg); - DU_send_INITIAL_UL_RRC_MESSAGE_TRANSFER(0,0,0,msgRrc->crnti, - msgRrc->rrc_container, - msgRrc->rrc_container_length, - msgRrc->du2cu_rrc_container, - msgRrc->du2cu_rrc_container_length - ); - break; + DU_send_INITIAL_UL_RRC_MESSAGE_TRANSFER(0, 0, 0, msgRrc->crnti, msgRrc->rrc_container, msgRrc->rrc_container_length, msgRrc->du2cu_rrc_container, msgRrc->du2cu_rrc_container_length); + } break; case F1AP_UL_RRC_MESSAGE: // to rrc - LOG_D(F1AP, "DU Task Received F1AP_UL_RRC_MESSAGE\n"); - if (RC.nrrrc && RC.nrrrc[0]->node_type == ngran_gNB_DU) { DU_send_UL_NR_RRC_MESSAGE_TRANSFER(myInstance, &F1AP_UL_RRC_MESSAGE(msg)); @@ -174,12 +165,10 @@ void *F1AP_DU_task(void *arg) { break; case F1AP_UE_CONTEXT_MODIFICATION_RESP: - LOG_I(F1AP, "DU task received itti message from RRC for F1AP_UE_CONTEXT_MODIFICATION_RESP message generation \n"); DU_send_UE_CONTEXT_MODIFICATION_RESPONSE(myInstance, &F1AP_UE_CONTEXT_MODIFICATION_RESP(msg)); break; case F1AP_UE_CONTEXT_RELEASE_REQ: // from MAC - LOG_I(F1AP, "DU Task Received F1AP_UE_CONTEXT_RELEASE_REQ\n"); DU_send_UE_CONTEXT_RELEASE_REQUEST(myInstance, &F1AP_UE_CONTEXT_RELEASE_REQ(msg)); break; diff --git a/openair2/F1AP/f1ap_du_ue_context_management.c b/openair2/F1AP/f1ap_du_ue_context_management.c index 4be90a9c15..23ab58c6ed 100644 --- a/openair2/F1AP/f1ap_du_ue_context_management.c +++ b/openair2/F1AP/f1ap_du_ue_context_management.c @@ -1078,7 +1078,7 @@ int DU_send_UE_CONTEXT_RELEASE_COMPLETE(instance_t instance, static instance_t du_create_gtpu_instance_to_cu(char *CUaddr, uint16_t CUport, char *DUaddr, uint16_t DUport) { - openAddr_t tmp={0}; + openAddr_t tmp = {0}; strncpy(tmp.originHost, DUaddr, sizeof(tmp.originHost)-1); strncpy(tmp.destinationHost, CUaddr, sizeof(tmp.destinationHost)-1); sprintf(tmp.originService, "%d", DUport); diff --git a/openair2/GNB_APP/gnb_app.c b/openair2/GNB_APP/gnb_app.c index 862cf9dddc..680b566eec 100644 --- a/openair2/GNB_APP/gnb_app.c +++ b/openair2/GNB_APP/gnb_app.c @@ -35,7 +35,6 @@ #include #include "gnb_app.h" -#include "gnb_config.h" #include "assertions.h" #include "common/ran_context.h" @@ -52,6 +51,8 @@ #include "nfapi/oai_integration/vendor_ext.h" #include #include "openair2/LAYER2/PDCP_v10.1.0/pdcp.h" +#include "openair2/E1AP/e1ap.h" +#include "gnb_config.h" extern unsigned char NB_gNB_INST; extern RAN_CONTEXT_t RC; @@ -59,7 +60,7 @@ extern RAN_CONTEXT_t RC; #define GNB_REGISTER_RETRY_DELAY 10 /*------------------------------------------------------------------------------*/ -static void configure_nr_rrc(uint32_t gnb_id) +void configure_nr_rrc(uint32_t gnb_id) { MessageDef *msg_p = NULL; // int CC_id; @@ -80,7 +81,7 @@ static void configure_nr_rrc(uint32_t gnb_id) /*------------------------------------------------------------------------------*/ -static uint32_t gNB_app_register(uint32_t gnb_id_start, uint32_t gnb_id_end)//, const Enb_properties_array_t *enb_properties) +uint32_t gNB_app_register(uint32_t gnb_id_start, uint32_t gnb_id_end)//, const Enb_properties_array_t *enb_properties) { uint32_t gnb_id; MessageDef *msg_p; @@ -102,7 +103,6 @@ static uint32_t gNB_app_register(uint32_t gnb_id_start, uint32_t gnb_id_end)//, itti_send_msg_to_task (TASK_NGAP, GNB_MODULE_ID_TO_INSTANCE(gnb_id), msg_p); } - if (gnb_id == 0) RCconfig_nr_gtpu(); } LOG_I(GNB_APP,"[gNB %d] gNB_app_register for instance %d\n", gnb_id, GNB_MODULE_ID_TO_INSTANCE(gnb_id)); @@ -115,7 +115,7 @@ static uint32_t gNB_app_register(uint32_t gnb_id_start, uint32_t gnb_id_end)//, /*------------------------------------------------------------------------------*/ -static uint32_t gNB_app_register_x2(uint32_t gnb_id_start, uint32_t gnb_id_end) { +uint32_t gNB_app_register_x2(uint32_t gnb_id_start, uint32_t gnb_id_end) { uint32_t gnb_id; MessageDef *msg_p; uint32_t register_gnb_x2_pending = 0; @@ -138,10 +138,6 @@ static uint32_t gNB_app_register_x2(uint32_t gnb_id_start, uint32_t gnb_id_end) void *gNB_app_task(void *args_p) { - uint32_t gnb_nb = RC.nb_nr_inst; - uint32_t gnb_id_start = 0; - uint32_t gnb_id_end = gnb_id_start + gnb_nb; - uint32_t gnb_id; MessageDef *msg_p = NULL; const char *msg_name = NULL; instance_t instance; @@ -151,60 +147,35 @@ void *gNB_app_task(void *args_p) int cell_to_activate = 0; itti_mark_task_ready (TASK_GNB_APP); + ngran_node_t node_type = get_node_type(); - LOG_I(PHY, "%s() Task ready initialize structures\n", __FUNCTION__); - - RCconfig_NR_L1(); - RCconfig_nr_prs(); - - if (RC.nb_nr_macrlc_inst>0) RCconfig_nr_macrlc(); - - LOG_I(PHY, "%s() RC.nb_nr_L1_inst:%d\n", __FUNCTION__, RC.nb_nr_L1_inst); - - if (RC.nb_nr_L1_inst>0) AssertFatal(l1_north_init_gNB()==0,"could not initialize L1 north interface\n"); - - AssertFatal (gnb_nb <= RC.nb_nr_inst, - "Number of gNB is greater than gNB defined in configuration file (%d/%d)!", - gnb_nb, RC.nb_nr_inst); - - LOG_I(GNB_APP,"Allocating gNB_RRC_INST for %d instances\n",RC.nb_nr_inst); - - RC.nrrrc = (gNB_RRC_INST **)malloc(RC.nb_nr_inst*sizeof(gNB_RRC_INST *)); - LOG_I(PHY, "%s() RC.nb_nr_inst:%d RC.nrrrc:%p\n", __FUNCTION__, RC.nb_nr_inst, RC.nrrrc); - for (gnb_id = gnb_id_start; (gnb_id < gnb_id_end) ; gnb_id++) { - RC.nrrrc[gnb_id] = (gNB_RRC_INST*)calloc(1,sizeof(gNB_RRC_INST)); - LOG_I(PHY, "%s() Creating RRC instance RC.nrrrc[%d]:%p (%d of %d)\n", __FUNCTION__, gnb_id, RC.nrrrc[gnb_id], gnb_id+1, gnb_id_end); - configure_nr_rrc(gnb_id); - } - - if (RC.nb_nr_inst > 0 && !get_softmodem_params()->nsa) { - init_pdcp(); - } - - if (is_x2ap_enabled() ) { //&& !NODE_IS_DU(RC.rrc[0]->node_type) - LOG_I(X2AP, "X2AP enabled \n"); - __attribute__((unused)) uint32_t x2_register_gnb_pending = gNB_app_register_x2 (gnb_id_start, gnb_id_end); - } - - /* For the CU case the gNB registration with the AMF might have to take place after the F1 setup, as the PLMN info - * can originate from the DU. Add check on whether x2ap is enabled to account for ENDC NSA scenario.*/ - if ((get_softmodem_params()->sa || is_x2ap_enabled()) && !NODE_IS_DU(RC.nrrrc[0]->node_type) ) { //&& !NODE_IS_CU(RC.nrrrc[0]->node_type)) { - /* Try to register each gNB */ - //registered_gnb = 0; - __attribute__((unused)) uint32_t register_gnb_pending = gNB_app_register (gnb_id_start, gnb_id_end); - } - if (RC.nb_nr_inst > 0) { - if (NODE_IS_CU(RC.nrrrc[0]->node_type)) { + if (node_type == ngran_gNB_CUCP || + node_type == ngran_gNB_CU || + node_type == ngran_eNB_CU || + node_type == ngran_ng_eNB_CU) { if (itti_create_task(TASK_CU_F1, F1AP_CU_task, NULL) < 0) { - LOG_E(F1AP, "Create task for F1AP CU failed\n"); - AssertFatal(1==0,"exiting"); + LOG_E(F1AP, "Create task for F1AP CU failed\n"); + AssertFatal(1==0,"exiting"); } } - if (NODE_IS_DU(RC.nrrrc[0]->node_type)) { + if (node_type == ngran_gNB_CUCP) { + if (itti_create_task(TASK_CUCP_E1, E1AP_CUCP_task, NULL) < 0) + AssertFatal(false, "Create task for E1AP CP failed\n"); + MessageDef *msg = RCconfig_NR_CU_E1(true); + if (msg) + itti_send_msg_to_task(TASK_CUCP_E1, 0, msg); + else + AssertFatal(false, "Send inti to task for E1AP CP failed\n"); + } + if (node_type == ngran_gNB_CUUP) { + AssertFatal(false, "To run CU-UP use executable nr-cuup\n"); + } + + if (NODE_IS_DU(node_type)) { if (itti_create_task(TASK_DU_F1, F1AP_DU_task, NULL) < 0) { LOG_E(F1AP, "Create task for F1AP DU failed\n"); AssertFatal(1==0,"exiting"); @@ -213,7 +184,7 @@ void *gNB_app_task(void *args_p) LOG_I(GNB_APP,"ngran_gNB_DU: Allocating ITTI message for F1AP_SETUP_REQ\n"); msg_p = itti_alloc_new_message (TASK_GNB_APP, 0, F1AP_SETUP_REQ); RCconfig_NR_DU_F1(msg_p, 0); - + itti_send_msg_to_task (TASK_DU_F1, GNB_MODULE_ID_TO_INSTANCE(0), msg_p); } } @@ -279,7 +250,7 @@ void *gNB_app_task(void *args_p) break; case F1AP_SETUP_RESP: - AssertFatal(NODE_IS_DU(RC.nrrrc[0]->node_type), "Should not have received F1AP_SETUP_RESP in CU/gNB\n"); + AssertFatal(NODE_IS_DU(node_type), "Should not have received F1AP_SETUP_RESP in CU/gNB\n"); LOG_I(GNB_APP, "Received %s: associated ngran_gNB_CU %s with %d cells to activate\n", ITTI_MSG_NAME (msg_p), F1AP_SETUP_RESP(msg_p).gNB_CU_name,F1AP_SETUP_RESP(msg_p).num_cells_to_activate); @@ -289,7 +260,7 @@ void *gNB_app_task(void *args_p) break; case F1AP_GNB_CU_CONFIGURATION_UPDATE: - AssertFatal(NODE_IS_DU(RC.nrrrc[0]->node_type), "Should not have received F1AP_GNB_CU_CONFIGURATION_UPDATE in CU/gNB\n"); + AssertFatal(NODE_IS_DU(node_type), "Should not have received F1AP_GNB_CU_CONFIGURATION_UPDATE in CU/gNB\n"); LOG_I(GNB_APP, "Received %s: associated ngran_gNB_CU %s with %d cells to activate\n", ITTI_MSG_NAME (msg_p), F1AP_GNB_CU_CONFIGURATION_UPDATE(msg_p).gNB_CU_name,F1AP_GNB_CU_CONFIGURATION_UPDATE(msg_p).num_cells_to_activate); diff --git a/openair2/GNB_APP/gnb_app.h b/openair2/GNB_APP/gnb_app.h index b0b422aae1..44c4374fc3 100644 --- a/openair2/GNB_APP/gnb_app.h +++ b/openair2/GNB_APP/gnb_app.h @@ -33,6 +33,7 @@ #include void *gNB_app_task(void *args_p); - - +void configure_nr_rrc(uint32_t gnb_id); +uint32_t gNB_app_register(uint32_t gnb_id_start, uint32_t gnb_id_end); +uint32_t gNB_app_register_x2(uint32_t gnb_id_start, uint32_t gnb_id_end); #endif /* GNB_APP_H_ */ diff --git a/openair2/GNB_APP/gnb_config.c b/openair2/GNB_APP/gnb_config.c index e4a855acda..dd4cb32bd7 100644 --- a/openair2/GNB_APP/gnb_config.c +++ b/openair2/GNB_APP/gnb_config.c @@ -91,8 +91,6 @@ extern uint16_t sf_ahead; int macrlc_has_f1 = 0; -static ngran_node_t get_node_type(void); - extern int config_check_band_frequencies(int ind, int16_t band, uint64_t downlink_frequency, int32_t uplink_frequency_offset, uint32_t frame_type); @@ -1154,7 +1152,8 @@ void RCconfig_NRRRC(MessageDef *msg_p, uint32_t i, gNB_RRC_INST *rrc) { printf("NRRRC %d: Southbound Transport %s\n",i,*(GNBParamList.paramarray[i][GNB_TRANSPORT_S_PREFERENCE_IDX].strptr)); - if (strcmp(*(GNBParamList.paramarray[i][GNB_TRANSPORT_S_PREFERENCE_IDX].strptr), "f1") == 0) { + rrc->node_type = get_node_type(); + if (NODE_IS_CU(rrc->node_type)) { paramdef_t SCTPParams[] = GNBSCTPPARAMS_DESC; char aprefix[MAX_OPTNAME_SIZE*2 + 8]; sprintf(aprefix,"%s.[%u].%s",GNB_CONFIG_STRING_GNB_LIST,i,GNB_CONFIG_STRING_SCTP_CONFIG); @@ -1171,21 +1170,12 @@ void RCconfig_NRRRC(MessageDef *msg_p, uint32_t i, gNB_RRC_INST *rrc) { rrc->eth_params_s.my_portd = *(GNBParamList.paramarray[i][GNB_LOCAL_S_PORTD_IDX].uptr); rrc->eth_params_s.remote_portd = *(GNBParamList.paramarray[i][GNB_REMOTE_S_PORTD_IDX].uptr); rrc->eth_params_s.transp_preference = ETH_UDP_MODE; - rrc->node_type = ngran_gNB_CU; rrc->sctp_in_streams = (uint16_t)*(SCTPParams[GNB_SCTP_INSTREAMS_IDX].uptr); rrc->sctp_out_streams = (uint16_t)*(SCTPParams[GNB_SCTP_OUTSTREAMS_IDX].uptr); - } else { - // set to ngran_gNB for now, it will get set to ngran_gNB_DU if macrlc entity which uses F1 is present - // Note: we will have to handle the case of ngran_ng_gNB_DU - if (macrlc_has_f1 == 0) { - rrc->node_type = ngran_gNB; - LOG_I(NR_RRC,"Setting node_type to ngran_gNB\n"); - } else { - rrc->node_type = ngran_gNB_DU; - LOG_I(NR_RRC,"Setting node_type to ngran_gNB_DU\n"); - } } + + rrc->nr_cellid = (uint64_t)*(GNBParamList.paramarray[i][GNB_NRCELLID_IDX].u64ptr); rrc->um_on_default_drb = *(GNBParamList.paramarray[i][GNB_UMONDEFAULTDRB_IDX].uptr); @@ -1282,55 +1272,6 @@ void RCconfig_NRRRC(MessageDef *msg_p, uint32_t i, gNB_RRC_INST *rrc) { config_security(rrc); }//End RCconfig_NRRRC function -int RCconfig_nr_gtpu(void ) { - - int num_gnbs = 0; - char* gnb_ipv4_address_for_NGU = NULL; - uint32_t gnb_port_for_NGU = 0; - char* gnb_ipv4_address_for_S1U = NULL; - uint32_t gnb_port_for_S1U = 0; - char gtpupath[MAX_OPTNAME_SIZE*2 + 8]; - - paramdef_t GNBSParams[] = GNBSPARAMS_DESC; - paramdef_t NETParams[] = GNBNETPARAMS_DESC; - LOG_I(GTPU,"Configuring GTPu\n"); - -/* get number of active eNodeBs */ - config_get( GNBSParams,sizeof(GNBSParams)/sizeof(paramdef_t),NULL); - num_gnbs = GNBSParams[GNB_ACTIVE_GNBS_IDX].numelt; - AssertFatal (num_gnbs >0, - "Failed to parse config file no active gNodeBs in %s \n", GNB_CONFIG_STRING_ACTIVE_GNBS); - - sprintf(gtpupath,"%s.[%i].%s",GNB_CONFIG_STRING_GNB_LIST,0,GNB_CONFIG_STRING_NETWORK_INTERFACES_CONFIG); - config_get(NETParams,sizeof(NETParams)/sizeof(paramdef_t),gtpupath); - char *cidr=NULL, *address = NULL; - int port; - if (NETParams[1].strptr != NULL) { - LOG_I(GTPU, "SA mode \n"); - address = strtok_r(gnb_ipv4_address_for_NGU, "/", &cidr); - port=gnb_port_for_NGU; - } else { - LOG_I(GTPU, "NSA mode \n"); - address = strtok_r(gnb_ipv4_address_for_S1U, "/", &cidr); - port=gnb_port_for_S1U; - } - - if (address) { - MessageDef *message; - message = itti_alloc_new_message(TASK_GNB_APP, 0, GTPV1U_REQ); - AssertFatal(message!=NULL,""); - IPV4_STR_ADDR_TO_INT_NWBO (address, GTPV1U_REQ(message).localAddr, "BAD IP ADDRESS FORMAT FOR gNB NG_U !\n" ); - LOG_I(GTPU,"Configuring GTPu address : %s -> %x\n",address,GTPV1U_REQ(message).localAddr); - GTPV1U_REQ(message).localPort = port; - strcpy(GTPV1U_REQ(message).localAddrStr,address); - sprintf(GTPV1U_REQ(message).localPortStr,"%d", port); - itti_send_msg_to_task (TASK_GTPV1_U, 0, message); // data model is wrong: gtpu doesn't have enb_id (or module_id) - } else - LOG_E(GTPU,"invalid address for NGU or S1U\n"); - -return 0; -} - int RCconfig_NR_NG(MessageDef *msg_p, uint32_t i) { int j,k = 0; @@ -1957,8 +1898,8 @@ int RCconfig_NR_DU_F1(MessageDef *msg_p, uint32_t i) { f1Setup->mib_length[k] = rrc->carrier.sizeof_MIB; NR_BCCH_DL_SCH_Message_t *bcch_message = NULL; - - asn_dec_rval_t dec_rval = uper_decode_complete( NULL, + asn_codec_ctx_t st={100*1000}; + asn_dec_rval_t dec_rval = uper_decode_complete( &st, &asn_DEF_NR_BCCH_DL_SCH_Message, (void **)&bcch_message, (const void *)rrc->carrier.SIB1, @@ -2252,16 +2193,24 @@ int gNB_app_handle_f1ap_gnb_cu_configuration_update(f1ap_gnb_cu_configuration_up return(ret); } -static ngran_node_t get_node_type(void) +ngran_node_t get_node_type(void) { paramdef_t MacRLC_Params[] = MACRLCPARAMS_DESC; paramlist_def_t MacRLC_ParamList = {CONFIG_STRING_MACRLC_LIST,NULL,0}; paramdef_t GNBParams[] = GNBPARAMS_DESC; paramlist_def_t GNBParamList = {GNB_CONFIG_STRING_GNB_LIST,NULL,0}; + paramdef_t GNBE1Params[] = GNBE1PARAMS_DESC; + paramlist_def_t GNBE1ParamList = {GNB_CONFIG_STRING_E1_PARAMETERS, NULL, 0}; + config_getlist( &GNBParamList,GNBParams,sizeof(GNBParams)/sizeof(paramdef_t),NULL); + + if (GNBParamList.numelt == 0) // We have no valid configuration, let's return a default + return ngran_gNB; + config_getlist( &MacRLC_ParamList,MacRLC_Params,sizeof(MacRLC_Params)/sizeof(paramdef_t), NULL); - config_getlist( &GNBParamList,GNBParams,sizeof(GNBParams)/sizeof(paramdef_t),NULL); - + char aprefix[MAX_OPTNAME_SIZE*2 + 8]; + sprintf(aprefix, "%s.[%i]", GNB_CONFIG_STRING_GNB_LIST, 0); + config_getlist( &GNBE1ParamList, GNBE1Params, sizeof(GNBE1Params)/sizeof(paramdef_t), aprefix); if ( MacRLC_ParamList.numelt > 0) { RC.nb_nr_macrlc_inst = MacRLC_ParamList.numelt; for (int j = 0; j < RC.nb_nr_macrlc_inst; j++) { @@ -2271,9 +2220,16 @@ static ngran_node_t get_node_type(void) } } - if (strcmp(*(GNBParamList.paramarray[0][GNB_TRANSPORT_S_PREFERENCE_IDX].strptr), "f1") == 0) - return ngran_gNB_CU; - else if (macrlc_has_f1 == 0) + if (strcmp(*(GNBParamList.paramarray[0][GNB_TRANSPORT_S_PREFERENCE_IDX].strptr), "f1") == 0) { + if ( GNBE1ParamList.paramarray == NULL || GNBE1ParamList.numelt == 0 ) + return ngran_gNB_CU; + else if (strcmp(*(GNBE1ParamList.paramarray[0][GNB_CONFIG_E1_CU_TYPE_IDX].strptr), "cp") == 0) + return ngran_gNB_CUCP; + else if (strcmp(*(GNBE1ParamList.paramarray[0][GNB_CONFIG_E1_CU_TYPE_IDX].strptr), "up") == 0) + return ngran_gNB_CUUP; + else + return ngran_gNB_CU; + } else if (macrlc_has_f1 == 0) return ngran_gNB; else return ngran_gNB_DU; @@ -2309,9 +2265,7 @@ void nr_read_config_and_init(void) { RCconfig_NRRRC(msg_p,gnb_id, RC.nrrrc[gnb_id]); } - if (NODE_IS_CU(RC.nrrrc[0]->node_type)) { + if (NODE_IS_CU(RC.nrrrc[0]->node_type) && RC.nrrrc[0]->node_type != ngran_gNB_CUCP) { pdcp_layer_init(); -// nr_DRB_preconfiguration(0x1234); - rrc_init_nr_global_param(); } } diff --git a/openair2/GNB_APP/gnb_config.h b/openair2/GNB_APP/gnb_config.h index b2a9ece078..3089753cff 100644 --- a/openair2/GNB_APP/gnb_config.h +++ b/openair2/GNB_APP/gnb_config.h @@ -41,6 +41,7 @@ #include "s1ap_messages_types.h" #include "ngap_messages_types.h" #include "f1ap_messages_types.h" +#include "e1ap_messages_types.h" #include "rrc_messages_types.h" #include "intertask_interface.h" @@ -94,7 +95,6 @@ extern void NRRCconfig_RU(void); extern void RCconfig_nr_prs(void); extern void RCconfig_NR_L1(void); extern void RCconfig_nr_macrlc(void); -extern int RCconfig_nr_gtpu(void ); extern void NRRCConfig(void); //void enb_config_display(void); @@ -107,6 +107,8 @@ int RCconfig_NR_DU_F1(MessageDef *msg_p, uint32_t i); int gNB_app_handle_f1ap_setup_resp(f1ap_setup_resp_t *resp); int gNB_app_handle_f1ap_gnb_cu_configuration_update(f1ap_gnb_cu_configuration_update_t *gnb_cu_cfg_update); void nr_read_config_and_init(void); +MessageDef *RCconfig_NR_CU_E1(bool separate_CUUP_process); +ngran_node_t get_node_type(void); #endif /* GNB_CONFIG_H_ */ /** @} */ diff --git a/openair2/GNB_APP/gnb_paramdef.h b/openair2/GNB_APP/gnb_paramdef.h index bf5e9f9660..8b62b7720b 100644 --- a/openair2/GNB_APP/gnb_paramdef.h +++ b/openair2/GNB_APP/gnb_paramdef.h @@ -34,6 +34,7 @@ #define __GNB_APP_GNB_PARAMDEF__H__ #include "common/config/config_paramdesc.h" +#include "common/ngran_types.h" #include "RRC_nr_paramsvalues.h" @@ -369,6 +370,27 @@ typedef enum { /*-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/ +/* E1 configuration section */ +#define GNB_CONFIG_STRING_E1_PARAMETERS "E1_INTERFACE" + +#define GNB_CONFIG_E1_CU_TYPE_IDX 0 +#define GNB_CONFIG_E1_IPV4_ADDRESS_CUCP 1 +#define GNB_CONFIG_E1_IPV4_ADDRESS_CUUP 2 +#define GNB_CONFIG_E1_CN_SUPPORT 3 + +#define GNB_CONFIG_STRING_E1_CU_TYPE "type" +#define GNB_CONFIG_STRING_E1_IPV4_ADDRESS_CUCP "ipv4_cucp" +#define GNB_CONFIG_STRING_E1_IPV4_ADDRESS_CUUP "ipv4_cuup" +#define GNB_CONFIG_STRING_E1_CN_SUPPORT "cn_support" + +// clang-format off +#define GNBE1PARAMS_DESC { \ + {GNB_CONFIG_STRING_E1_CU_TYPE, NULL, 0, strptr:NULL, defstrval:NULL, TYPE_STRING, 0}, \ + {GNB_CONFIG_STRING_E1_IPV4_ADDRESS_CUCP, NULL, 0, strptr:NULL, defstrval:NULL, TYPE_STRING, 0}, \ + {GNB_CONFIG_STRING_E1_IPV4_ADDRESS_CUUP, NULL, 0, strptr:NULL, defstrval:NULL, TYPE_STRING, 0}, \ + {GNB_CONFIG_STRING_E1_CN_SUPPORT, NULL, 0, uptr :NULL, defintval:1L, TYPE_UINT, 0} \ + } +// clang-format on /* L1 configuration section names */ #define CONFIG_STRING_L1_LIST "L1s" #define CONFIG_STRING_L1_CONFIG "l1_config" diff --git a/openair2/LAYER2/MAC/mac_proto.h b/openair2/LAYER2/MAC/mac_proto.h index af94ef3ae0..abb6ba0ec3 100644 --- a/openair2/LAYER2/MAC/mac_proto.h +++ b/openair2/LAYER2/MAC/mac_proto.h @@ -664,8 +664,6 @@ int remove_ue_list(UE_list_t *listP, int UE_id); void dump_ue_list(UE_list_t *listP); void init_ue_list(UE_list_t *listP); int UE_num_active_CC(UE_info_t *listP, int ue_idP); -int UE_PCCID(module_id_t mod_idP, int ue_idP); -rnti_t UE_RNTI(module_id_t mod_idP, int ue_idP); uint8_t find_rb_table_index(uint8_t average_rbs); diff --git a/openair2/LAYER2/NR_MAC_gNB/main.c b/openair2/LAYER2/NR_MAC_gNB/main.c index 6d592b797f..e9d41986c5 100644 --- a/openair2/LAYER2/NR_MAC_gNB/main.c +++ b/openair2/LAYER2/NR_MAC_gNB/main.c @@ -249,14 +249,11 @@ void mac_top_init_gNB(ngran_node_t node_type) AssertFatal(rlc_module_init(1) == 0,"Could not initialize RLC layer\n"); // These should be out of here later - pdcp_layer_init(); + if (get_softmodem_params()->usim_test == 0 ) pdcp_layer_init(); if(IS_SOFTMODEM_NOS1 && get_softmodem_params()->phy_test) nr_DRB_preconfiguration(0x1234); - rrc_init_nr_global_param(); - - } else { RC.nrmac = NULL; } diff --git a/openair2/LAYER2/nr_pdcp/nr_pdcp_e1_api.c b/openair2/LAYER2/nr_pdcp/nr_pdcp_e1_api.c new file mode 100644 index 0000000000..9a584a3b27 --- /dev/null +++ b/openair2/LAYER2/nr_pdcp/nr_pdcp_e1_api.c @@ -0,0 +1,59 @@ +/* + * 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 _GNU_SOURCE +#define _GNU_SOURCE +#endif +#include "nr_pdcp_e1_api.h" + +void e1_add_drb(int is_gnb, + uint64_t ue_id, + struct NR_DRB_ToAddMod *s, + int ciphering_algorithm, + int integrity_algorithm, + unsigned char *ciphering_key, + unsigned char *integrity_key) +{ + add_drb_am(is_gnb, ue_id, s, ciphering_algorithm, integrity_algorithm, + ciphering_key, integrity_key); + LOG_I(PDCP, "%s:%s:%d: added DRB for UE ID %ld\n", __FILE__, __FUNCTION__, __LINE__, ue_id); +} + +void nr_pdcp_e1_add_drbs(eNB_flag_t enb_flag, + uint64_t ue_id, + NR_DRB_ToAddModList_t *const drb2add_list, + const uint8_t security_modeP, + uint8_t *const kUPenc, + uint8_t *const kUPint) { + + if (drb2add_list != NULL) { + for (int i = 0; i < drb2add_list->list.count; i++) { + e1_add_drb(enb_flag, ue_id, drb2add_list->list.array[i], + security_modeP & 0x0f, (security_modeP >> 4) & 0x0f, + kUPenc, kUPint); + } + } else + LOG_W(PDCP, "%s with void list\n", __FUNCTION__); + if (kUPenc) + free(kUPenc); + if (kUPint) + free(kUPint); +} diff --git a/openair2/LAYER2/nr_pdcp/nr_pdcp_e1_api.h b/openair2/LAYER2/nr_pdcp/nr_pdcp_e1_api.h new file mode 100644 index 0000000000..a4b44fb74a --- /dev/null +++ b/openair2/LAYER2/nr_pdcp/nr_pdcp_e1_api.h @@ -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 + */ + +#ifndef _GNU_SOURCE +#define _GNU_SOURCE +#endif +#include "common/utils/oai_asn1.h" +#include "NR_RadioBearerConfig.h" + +#include "pdcp.h" +#include "LAYER2/nr_rlc/nr_rlc_oai_api.h" +#include +#include "openair2/SDAP/nr_sdap/nr_sdap.h" + +void e1_add_drb(int is_gnb, + uint64_t ue_id, + struct NR_DRB_ToAddMod *s, + int ciphering_algorithm, + int integrity_algorithm, + unsigned char *ciphering_key, + unsigned char *integrity_key); + +void nr_pdcp_e1_add_drbs(eNB_flag_t enb_flag, + uint64_t ue_id, + NR_DRB_ToAddModList_t *const drb2add_list, + const uint8_t security_modeP, + uint8_t *const kUPenc, + uint8_t *const kUPint); + +void add_drb_am(int is_gnb, ue_id_t rntiMaybeUEid, struct NR_DRB_ToAddMod *s, + int ciphering_algorithm, + int integrity_algorithm, + unsigned char *ciphering_key, + unsigned char *integrity_key); + diff --git a/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.c b/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.c index fd1430420c..190757d74c 100644 --- a/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.c +++ b/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.c @@ -38,6 +38,8 @@ #include "LAYER2/nr_rlc/nr_rlc_oai_api.h" #include #include "openair2/SDAP/nr_sdap/nr_sdap.h" +#include "nr_pdcp_e1_api.h" +#include "gnb_config.h" #include "executables/softmodem-common.h" #define TODO do { \ @@ -56,10 +58,11 @@ static int nr_pdcp_current_time_last_subframe; hash_table_t *pdcp_coll_p; static uint64_t pdcp_optmask; -ngran_node_t node_type = ngran_gNB; uint8_t first_dcch = 0; uint8_t proto_agent_flag = 0; +static ngran_node_t node_type; + /****************************************************************************/ /* rlc_data_req queue - begin */ /****************************************************************************/ @@ -524,6 +527,10 @@ int pdcp_fifo_flush_sdus(const protocol_ctxt_t *const ctxt_pP) return 0; } +static void set_node_type() { + node_type = get_node_type(); +} + void pdcp_layer_init(void) { /* hack: be sure to initialize only once */ @@ -539,7 +546,9 @@ void pdcp_layer_init(void) nr_pdcp_ue_manager = new_nr_pdcp_ue_manager(1); - if ((RC.nrrrc == NULL) || (!NODE_IS_CU(RC.nrrrc[0]->node_type))) { + set_node_type(); + + if ((RC.nrrrc == NULL) || (!NODE_IS_CU(node_type))) { init_nr_rlc_data_req_queue(); } @@ -667,7 +676,7 @@ rb_found: ctxt.brOption = 0; ctxt.rntiMaybeUEid = ue->rntiMaybeUEid; - if (RC.nrrrc != NULL && NODE_IS_CU(RC.nrrrc[0]->node_type)) { + if (NODE_IS_CU(node_type)) { MessageDef *message_p = itti_alloc_new_message_sized(TASK_PDCP_ENB, 0, GTPV1U_TUNNEL_DATA_REQ, sizeof(gtpv1u_tunnel_data_req_t) @@ -688,7 +697,6 @@ rb_found: extern instance_t CUuniqInstance; itti_send_msg_to_task(TASK_GTPV1_U, CUuniqInstance, message_p); } else { - memblock = get_free_mem_block(size, __FUNCTION__); memcpy(memblock->data, buf, size); LOG_D(PDCP, "%s(): (drb %d) calling rlc_data_req size %d\n", __func__, rb_id, size); @@ -764,7 +772,7 @@ srb_found: LOG_D(PDCP, "%s(): (srb %d) calling rlc_data_req size %d\n", __func__, srb_id, size); //for (i = 0; i < size; i++) printf(" %2.2x", (unsigned char)memblock->data[i]); //printf("\n"); - if ((RC.nrrrc == NULL) || (!NODE_IS_CU(RC.nrrrc[0]->node_type))) { + if ((RC.nrrrc == NULL) || (!NODE_IS_CU(node_type))) { if (entity->is_gnb) { f1ap_dl_rrc_message_t dl_rrc = {.old_gNB_DU_ue_id = 0xFFFFFF, .rrc_container = (uint8_t *)buf, .rrc_container_length = size, .rnti = ue->rntiMaybeUEid, .srb_id = DCCH}; gNB_RRC_INST *rrc = RC.nrrrc[0]; @@ -1056,35 +1064,30 @@ void nr_DRB_preconfiguration(ue_id_t crntiMaybeUEid) drb_ToAddMod->reestablishPDCP = NULL; drb_ToAddMod->recoverPDCP = NULL; drb_ToAddMod->pdcp_Config = calloc(1,sizeof(*drb_ToAddMod->pdcp_Config)); - drb_ToAddMod->pdcp_Config->drb = calloc(1,sizeof(*drb_ToAddMod->pdcp_Config->drb)); - drb_ToAddMod->pdcp_Config->drb->discardTimer = calloc(1,sizeof(*drb_ToAddMod->pdcp_Config->drb->discardTimer)); - *drb_ToAddMod->pdcp_Config->drb->discardTimer=NR_PDCP_Config__drb__discardTimer_infinity; - drb_ToAddMod->pdcp_Config->drb->pdcp_SN_SizeUL = calloc(1,sizeof(*drb_ToAddMod->pdcp_Config->drb->pdcp_SN_SizeUL)); - *drb_ToAddMod->pdcp_Config->drb->pdcp_SN_SizeUL = NR_PDCP_Config__drb__pdcp_SN_SizeUL_len18bits; - drb_ToAddMod->pdcp_Config->drb->pdcp_SN_SizeDL = calloc(1,sizeof(*drb_ToAddMod->pdcp_Config->drb->pdcp_SN_SizeDL)); - *drb_ToAddMod->pdcp_Config->drb->pdcp_SN_SizeDL = NR_PDCP_Config__drb__pdcp_SN_SizeDL_len18bits; - drb_ToAddMod->pdcp_Config->drb->headerCompression.present = NR_PDCP_Config__drb__headerCompression_PR_notUsed; - drb_ToAddMod->pdcp_Config->drb->headerCompression.choice.notUsed = 0; + asn1cCalloc(drb_ToAddMod->pdcp_Config->drb, drb); + asn1cCallocOne(drb->discardTimer, NR_PDCP_Config__drb__discardTimer_infinity); + asn1cCallocOne(drb->pdcp_SN_SizeUL, NR_PDCP_Config__drb__pdcp_SN_SizeUL_len18bits); + asn1cCallocOne(drb->pdcp_SN_SizeDL, NR_PDCP_Config__drb__pdcp_SN_SizeDL_len18bits); + drb->headerCompression.present = NR_PDCP_Config__drb__headerCompression_PR_notUsed; + drb->headerCompression.choice.notUsed = 0; - drb_ToAddMod->pdcp_Config->drb->integrityProtection=NULL; - drb_ToAddMod->pdcp_Config->drb->statusReportRequired=NULL; - drb_ToAddMod->pdcp_Config->drb->outOfOrderDelivery=NULL; + drb->integrityProtection = NULL; + drb->statusReportRequired = NULL; + drb->outOfOrderDelivery = NULL; drb_ToAddMod->pdcp_Config->moreThanOneRLC = NULL; - drb_ToAddMod->pdcp_Config->t_Reordering = calloc(1,sizeof(*drb_ToAddMod->pdcp_Config->t_Reordering)); - *drb_ToAddMod->pdcp_Config->t_Reordering = NR_PDCP_Config__t_Reordering_ms0; + asn1cCallocOne(drb_ToAddMod->pdcp_Config->t_Reordering, NR_PDCP_Config__t_Reordering_ms0); drb_ToAddMod->pdcp_Config->ext1 = NULL; asn1cSeqAdd(&rbconfig->drb_ToAddModList->list,drb_ToAddMod); rbconfig->drb_ToReleaseList = NULL; - rbconfig->securityConfig = calloc(1,sizeof(*rbconfig->securityConfig)); - rbconfig->securityConfig->securityAlgorithmConfig = calloc(1,sizeof(*rbconfig->securityConfig->securityAlgorithmConfig)); - rbconfig->securityConfig->securityAlgorithmConfig->cipheringAlgorithm = NR_CipheringAlgorithm_nea0; - rbconfig->securityConfig->securityAlgorithmConfig->integrityProtAlgorithm=NULL; - rbconfig->securityConfig->keyToUse = calloc(1,sizeof(*rbconfig->securityConfig->keyToUse)); - *rbconfig->securityConfig->keyToUse = NR_SecurityConfig__keyToUse_master; + asn1cCalloc(rbconfig->securityConfig, secConf); + asn1cCalloc(secConf->securityAlgorithmConfig, secConfAlgo); + secConfAlgo->cipheringAlgorithm = NR_CipheringAlgorithm_nea0; + secConfAlgo->integrityProtAlgorithm = NULL; + asn1cCallocOne(secConf->keyToUse, NR_SecurityConfig__keyToUse_master); if ( LOG_DEBUGFLAG(DEBUG_ASN1) ) { xer_fprint(stdout, &asn_DEF_NR_RadioBearerConfig, (const void*)rbconfig); @@ -1108,11 +1111,7 @@ void nr_DRB_preconfiguration(ue_id_t crntiMaybeUEid) nr_pdcp_add_drbs(ctxt.enb_flag, ctxt.rntiMaybeUEid, rbconfig->drb_ToAddModList, 0, NULL, NULL, Rlc_Bearer_ToAdd_list); - nr_rrc_rlc_config_asn1_req (&ctxt, - (NR_SRB_ToAddModList_t *) NULL, - rbconfig->drb_ToAddModList, - rbconfig->drb_ToReleaseList, - Rlc_Bearer_ToAdd_list); + nr_rrc_rlc_config_asn1_req(&ctxt, (NR_SRB_ToAddModList_t *)NULL, rbconfig->drb_ToAddModList, rbconfig->drb_ToReleaseList, Rlc_Bearer_ToAdd_list); LOG_D(PDCP, "%s:%d: done RRC PDCP/RLC ASN1 request for UE ID/RNTI %ld\n", __FUNCTION__, __LINE__, ctxt.rntiMaybeUEid); } diff --git a/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.c b/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.c index 29aab4ab5a..60c002537a 100644 --- a/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.c +++ b/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.c @@ -985,6 +985,7 @@ rlc_op_status_t nr_rrc_rlc_config_asn1_req (const protocol_ctxt_t * const ctxt if(rlc_bearer2add_list->list.array[j]->servedRadioBearer->present == NR_RLC_BearerConfig__servedRadioBearer_PR_srb_Identity){ if(srb2add_listP->list.array[i]->srb_Identity == rlc_bearer2add_list->list.array[j]->servedRadioBearer->choice.srb_Identity){ add_rlc_srb(rnti, srb2add_listP->list.array[i], rlc_bearer2add_list->list.array[j]); + LOG_D(RLC, "Add srb %ld\n", srb2add_listP->list.array[i]->srb_Identity); } } } diff --git a/openair2/LAYER2/nr_rlc/nr_rlc_ue_manager.h b/openair2/LAYER2/nr_rlc/nr_rlc_ue_manager.h index 92d20d1aca..c7e42a0a0d 100644 --- a/openair2/LAYER2/nr_rlc/nr_rlc_ue_manager.h +++ b/openair2/LAYER2/nr_rlc/nr_rlc_ue_manager.h @@ -28,6 +28,7 @@ typedef void nr_rlc_ue_manager_t; typedef struct nr_rlc_ue_t { int rnti; + ue_id_t ue_id; nr_rlc_entity_t *srb0; nr_rlc_entity_t *srb[3]; nr_rlc_entity_t *drb[MAX_DRBS_PER_UE]; diff --git a/openair2/MCE_APP/mce_app.c b/openair2/MCE_APP/mce_app.c index 37b461e819..e626a09a98 100644 --- a/openair2/MCE_APP/mce_app.c +++ b/openair2/MCE_APP/mce_app.c @@ -40,7 +40,8 @@ # include "intertask_interface.h" # include "s1ap_eNB.h" -#include "sctp_eNB_task.h" +# include "sctp_eNB_task.h" +# include "openair3/ocp-gtpu/gtp_itf.h" # include "x2ap_eNB.h" # include "x2ap_messages_types.h" diff --git a/openair2/RRC/LTE/rrc_eNB.c b/openair2/RRC/LTE/rrc_eNB.c index b4f7eece01..171e69ea59 100644 --- a/openair2/RRC/LTE/rrc_eNB.c +++ b/openair2/RRC/LTE/rrc_eNB.c @@ -5629,6 +5629,7 @@ rrc_eNB_generate_RRCConnectionSetup( case ngran_eNB_CU : case ngran_ng_eNB_CU : case ngran_gNB_CU : + case ngran_gNB_CUCP : // create an ITTI message /* TODO: F1 IDs ar missing in RRC */ message_p = itti_alloc_new_message (TASK_RRC_ENB, 0, F1AP_DL_RRC_MESSAGE); diff --git a/openair2/RRC/NR/MESSAGES/asn1_msg.c b/openair2/RRC/NR/MESSAGES/asn1_msg.c index 299e0acaa9..8dbc078c2c 100644 --- a/openair2/RRC/NR/MESSAGES/asn1_msg.c +++ b/openair2/RRC/NR/MESSAGES/asn1_msg.c @@ -295,11 +295,6 @@ uint8_t do_MIB_NR(gNB_RRC_INST *rrc,uint32_t frame) { 24); AssertFatal (enc_rval.encoded > 0, "ASN1 message encoding failed (%s, %lu)!\n", enc_rval.failed_type->name, enc_rval.encoded); - - if (enc_rval.encoded==-1) { - return(-1); - } - return((enc_rval.encoded+7)/8); } @@ -638,11 +633,6 @@ uint8_t do_SIB23_NR(rrc_gNB_carrier_data_t *carrier, 100); AssertFatal (enc_rval.encoded > 0, "ASN1 message encoding failed (%s, %lu)!\n", enc_rval.failed_type->name, enc_rval.encoded); - - if (enc_rval.encoded==-1) { - return(-1); - } - return((enc_rval.encoded+7)/8); } @@ -690,11 +680,8 @@ int do_RRCReject(uint8_t Mod_id, buffer, 100); - if(enc_rval.encoded == -1) { - LOG_E(NR_RRC, "[gNB AssertFatal]ASN1 message encoding failed (%s, %lu)!\n", - enc_rval.failed_type->name, enc_rval.encoded); - return -1; - } + AssertFatal(enc_rval.encoded > 0, "ASN1 message encoding failed (%s, %lu)!\n", + enc_rval.failed_type->name, enc_rval.encoded); LOG_D(NR_RRC,"RRCReject Encoded %zd bits (%zd bytes)\n", enc_rval.encoded,(enc_rval.encoded+7)/8); @@ -1297,13 +1284,11 @@ int do_RRCSetup(rrc_gNB_ue_context_t *const ue_context_pP, (void *)&dl_ccch_msg, buffer, 1000); + - if(enc_rval.encoded == -1) { - LOG_E(NR_RRC, "[gNB AssertFatal]ASN1 message encoding failed (%s, %lu)!\n", + AssertFatal(enc_rval.encoded >0, "ASN1 message encoding failed (%s, %lu)!\n", enc_rval.failed_type->name, enc_rval.encoded); - return -1; - } - + LOG_D(NR_RRC,"RRCSetup Encoded %zd bits (%zd bytes)\n", enc_rval.encoded,(enc_rval.encoded+7)/8); return((enc_rval.encoded+7)/8); @@ -1346,19 +1331,11 @@ uint8_t do_NR_SecurityModeCommand( buffer, 100); - if(enc_rval.encoded == -1) { - LOG_I(NR_RRC, "[gNB AssertFatal]ASN1 message encoding failed (%s, %lu)!\n", - enc_rval.failed_type->name, enc_rval.encoded); - return -1; - } + AssertFatal(enc_rval.encoded >0 , "ASN1 message encoding failed (%s, %lu)!\n", + enc_rval.failed_type->name, enc_rval.encoded); LOG_D(NR_RRC, "[gNB %d] securityModeCommand for UE %lx Encoded %zd bits (%zd bytes)\n", ctxt_pP->module_id, ctxt_pP->rntiMaybeUEid, enc_rval.encoded, (enc_rval.encoded + 7) / 8); - if (enc_rval.encoded==-1) { - LOG_E(NR_RRC, "[gNB %d] ASN1 : securityModeCommand encoding failed for UE %lx\n", ctxt_pP->module_id, ctxt_pP->rntiMaybeUEid); - return(-1); - } - // rrc_ue_process_ueCapabilityEnquiry(0,1000,&dl_dcch_msg.message.choice.c1.choice.ueCapabilityEnquiry,0); // exit(-1); return((enc_rval.encoded+7)/8); @@ -1411,6 +1388,9 @@ uint8_t do_NR_SA_UECapabilityEnquiry( const protocol_ctxt_t *const ctxt_pP, (void *)sa_band_filter, req_freq_buf, 1024); + AssertFatal(enc_rval.encoded >0, "ASN1 message encoding failed (%s, %lu)!\n", + enc_rval.failed_type->name, enc_rval.encoded); + if ( LOG_DEBUGFLAG(DEBUG_ASN1) ) { xer_fprint(stdout, &asn_DEF_NR_UE_CapabilityRequestFilterNR, (void *)sa_band_filter); @@ -1435,19 +1415,11 @@ uint8_t do_NR_SA_UECapabilityEnquiry( const protocol_ctxt_t *const ctxt_pP, buffer, 100); - if(enc_rval.encoded == -1) { - LOG_I(NR_RRC, "[gNB AssertFatal]ASN1 message encoding failed (%s, %lu)!\n", - enc_rval.failed_type->name, enc_rval.encoded); - return -1; - } - + AssertFatal(enc_rval.encoded >0, "ASN1 message encoding failed (%s, %lu)!\n", + enc_rval.failed_type->name, enc_rval.encoded); + LOG_D(NR_RRC, "[gNB %d] NR UECapabilityRequest for UE %lx Encoded %zd bits (%zd bytes)\n", ctxt_pP->module_id, ctxt_pP->rntiMaybeUEid, enc_rval.encoded, (enc_rval.encoded + 7) / 8); - if (enc_rval.encoded==-1) { - LOG_E(NR_RRC, "[gNB %d] ASN1 : NR UECapabilityRequest encoding failed for UE %lx\n", ctxt_pP->module_id, ctxt_pP->rntiMaybeUEid); - return(-1); - } - return((enc_rval.encoded+7)/8); } @@ -1480,11 +1452,8 @@ uint8_t do_NR_RRCRelease(uint8_t *buffer, (void *)&dl_dcch_msg, buffer, buffer_size); - if(enc_rval.encoded == -1) { - LOG_I(NR_RRC, "[gNB AssertFatal]ASN1 message encoding failed (%s, %lu)!\n", - enc_rval.failed_type->name, enc_rval.encoded); - return -1; - } + AssertFatal(enc_rval.encoded > 0, "ASN1 message encoding failed (%s, %lu)!\n", + enc_rval.failed_type->name, enc_rval.encoded); return((enc_rval.encoded+7)/8); } @@ -1508,19 +1477,18 @@ int16_t do_RRCReconfiguration( NR_CellGroupConfig_t *cellGroupConfig) //------------------------------------------------------------------------------ { - NR_DL_DCCH_Message_t dl_dcch_msg; + NR_DL_DCCH_Message_t dl_dcch_msg={0}; asn_enc_rval_t enc_rval; NR_RRCReconfiguration_IEs_t *ie; unsigned char masterCellGroup_buf[1000]; - memset(&dl_dcch_msg, 0, sizeof(NR_DL_DCCH_Message_t)); dl_dcch_msg.message.present = NR_DL_DCCH_MessageType_PR_c1; - dl_dcch_msg.message.choice.c1 = CALLOC(1, sizeof(struct NR_DL_DCCH_MessageType__c1)); - dl_dcch_msg.message.choice.c1->present = NR_DL_DCCH_MessageType__c1_PR_rrcReconfiguration; + asn1cCalloc(dl_dcch_msg.message.choice.c1, c1);// = CALLOC(1, sizeof(struct NR_DL_DCCH_MessageType__c1)); + c1->present = NR_DL_DCCH_MessageType__c1_PR_rrcReconfiguration; - dl_dcch_msg.message.choice.c1->choice.rrcReconfiguration = calloc(1, sizeof(NR_RRCReconfiguration_t)); - dl_dcch_msg.message.choice.c1->choice.rrcReconfiguration->rrc_TransactionIdentifier = Transaction_id; - dl_dcch_msg.message.choice.c1->choice.rrcReconfiguration->criticalExtensions.present = NR_RRCReconfiguration__criticalExtensions_PR_rrcReconfiguration; + asn1cCalloc(c1->choice.rrcReconfiguration, rrcReconf); // = calloc(1, sizeof(NR_RRCReconfiguration_t)); + rrcReconf->rrc_TransactionIdentifier = Transaction_id; + rrcReconf->criticalExtensions.present = NR_RRCReconfiguration__criticalExtensions_PR_rrcReconfiguration; /******************** Radio Bearer Config ********************/ /* Configure Security */ @@ -1532,7 +1500,8 @@ int16_t do_RRCReconfiguration( // *security_config->keyToUse = NR_SecurityConfig__keyToUse_master; ie = calloc(1, sizeof(NR_RRCReconfiguration_IEs_t)); - if (SRB_configList || DRB_configList) { + if ((SRB_configList && SRB_configList->list.size) || + (DRB_configList && DRB_configList->list.size)) { ie->radioBearerConfig = calloc(1, sizeof(NR_RadioBearerConfig_t)); ie->radioBearerConfig->srb_ToAddModList = SRB_configList; ie->radioBearerConfig->drb_ToAddModList = DRB_configList; @@ -1561,42 +1530,42 @@ int16_t do_RRCReconfiguration( configuration); enc_rval = uper_encode_to_buffer(&asn_DEF_NR_CellGroupConfig, - NULL, - (void *)cellGroupConfig, - masterCellGroup_buf, - 1000); - if(enc_rval.encoded == -1) { - LOG_E(NR_RRC, "ASN1 message CellGroupConfig encoding failed (%s, %lu)!\n", - enc_rval.failed_type->name, enc_rval.encoded); - return -1; - } + NULL, + (void *)cellGroupConfig, + masterCellGroup_buf, + 1000); + AssertFatal(enc_rval.encoded >0, "ASN1 message encoding failed (%s, %lu)!\n", + enc_rval.failed_type->name, enc_rval.encoded); if ( LOG_DEBUGFLAG(DEBUG_ASN1) ) { xer_fprint(stdout, &asn_DEF_NR_CellGroupConfig, (const void *) cellGroupConfig); } ie->nonCriticalExtension->masterCellGroup = calloc(1,sizeof(OCTET_STRING_t)); - + ie->nonCriticalExtension->masterCellGroup->buf = masterCellGroup_buf; ie->nonCriticalExtension->masterCellGroup->size = (enc_rval.encoded+7)/8; } - + dl_dcch_msg.message.choice.c1->choice.rrcReconfiguration->criticalExtensions.choice.rrcReconfiguration = ie; - + if ( LOG_DEBUGFLAG(DEBUG_ASN1) ) { xer_fprint(stdout, &asn_DEF_NR_DL_DCCH_Message, (void *)&dl_dcch_msg); } - + enc_rval = uper_encode_to_buffer(&asn_DEF_NR_DL_DCCH_Message, - NULL, - (void *)&dl_dcch_msg, - buffer, - buffer_size); - - if(enc_rval.encoded == -1) { - LOG_I(NR_RRC, "[gNB AssertFatal]ASN1 message encoding failed (%s, %lu)!\n", - enc_rval.failed_type->name, enc_rval.encoded); - return -1; - } - + NULL, + (void *)&dl_dcch_msg, + buffer, + buffer_size); + + AssertFatal(enc_rval.encoded >0, "ASN1 message encoding failed (%s, %lu)!\n", + enc_rval.failed_type->name, enc_rval.encoded); + + LOG_D(NR_RRC,"[gNB %d] RRCReconfiguration for UE %lx Encoded %zd bits (%zd bytes)\n", + ctxt_pP->module_id, + ctxt_pP->rntiMaybeUEid, + enc_rval.encoded, + (enc_rval.encoded+7)/8); + return((enc_rval.encoded+7)/8); } @@ -1731,9 +1700,9 @@ uint8_t do_RRCSetupComplete(uint8_t Mod_id, uint8_t *buffer, size_t buffer_size, NR_UL_DCCH_Message_t ul_dcch_msg; NR_RRCSetupComplete_t *RrcSetupComplete; memset((void *)&ul_dcch_msg,0,sizeof(NR_UL_DCCH_Message_t)); - + uint8_t buf[6]; - + ul_dcch_msg.message.present = NR_UL_DCCH_MessageType_PR_c1; ul_dcch_msg.message.choice.c1 = CALLOC(1,sizeof(struct NR_UL_DCCH_MessageType__c1)); ul_dcch_msg.message.choice.c1->present = NR_UL_DCCH_MessageType__c1_PR_rrcSetupComplete; @@ -1746,7 +1715,7 @@ uint8_t do_RRCSetupComplete(uint8_t Mod_id, uint8_t *buffer, size_t buffer_size, // sizeof(*RrcSetupComplete->criticalExtensions.choice.rrcSetupComplete->nonCriticalExtension)); RrcSetupComplete->criticalExtensions.choice.rrcSetupComplete->selectedPLMN_Identity = sel_plmn_id; RrcSetupComplete->criticalExtensions.choice.rrcSetupComplete->registeredAMF = NULL; - + RrcSetupComplete->criticalExtensions.choice.rrcSetupComplete->ng_5G_S_TMSI_Value = CALLOC(1, sizeof(struct NR_RRCSetupComplete_IEs__ng_5G_S_TMSI_Value)); RrcSetupComplete->criticalExtensions.choice.rrcSetupComplete->ng_5G_S_TMSI_Value->present = NR_RRCSetupComplete_IEs__ng_5G_S_TMSI_Value_PR_ng_5G_S_TMSI; RrcSetupComplete->criticalExtensions.choice.rrcSetupComplete->ng_5G_S_TMSI_Value->choice.ng_5G_S_TMSI.size = 6; @@ -1757,23 +1726,23 @@ uint8_t do_RRCSetupComplete(uint8_t Mod_id, uint8_t *buffer, size_t buffer_size, RrcSetupComplete->criticalExtensions.choice.rrcSetupComplete->ng_5G_S_TMSI_Value->choice.ng_5G_S_TMSI.buf[3] = 0x78; RrcSetupComplete->criticalExtensions.choice.rrcSetupComplete->ng_5G_S_TMSI_Value->choice.ng_5G_S_TMSI.buf[4] = 0x9A; RrcSetupComplete->criticalExtensions.choice.rrcSetupComplete->ng_5G_S_TMSI_Value->choice.ng_5G_S_TMSI.buf[5] = 0xBC; - - memset(&RrcSetupComplete->criticalExtensions.choice.rrcSetupComplete->dedicatedNAS_Message,0,sizeof(OCTET_STRING_t)); - OCTET_STRING_fromBuf(&RrcSetupComplete->criticalExtensions.choice.rrcSetupComplete->dedicatedNAS_Message,dedicatedInfoNAS,dedicatedInfoNASLength); -if ( LOG_DEBUGFLAG(DEBUG_ASN1) ) { - xer_fprint(stdout, &asn_DEF_NR_UL_DCCH_Message, (void *)&ul_dcch_msg); -} - -enc_rval = uper_encode_to_buffer(&asn_DEF_NR_UL_DCCH_Message, - NULL, - (void *)&ul_dcch_msg, - buffer, - buffer_size); -AssertFatal(enc_rval.encoded > 0,"ASN1 message encoding failed (%s, %lu)!\n", - enc_rval.failed_type->name,enc_rval.encoded); -LOG_D(NR_RRC,"RRCSetupComplete Encoded %zd bits (%zd bytes)\n",enc_rval.encoded,(enc_rval.encoded+7)/8); - -return((enc_rval.encoded+7)/8); + + memset(&RrcSetupComplete->criticalExtensions.choice.rrcSetupComplete->dedicatedNAS_Message,0,sizeof(OCTET_STRING_t)); + OCTET_STRING_fromBuf(&RrcSetupComplete->criticalExtensions.choice.rrcSetupComplete->dedicatedNAS_Message,dedicatedInfoNAS,dedicatedInfoNASLength); + if ( LOG_DEBUGFLAG(DEBUG_ASN1) ) { + xer_fprint(stdout, &asn_DEF_NR_UL_DCCH_Message, (void *)&ul_dcch_msg); + } + + enc_rval = uper_encode_to_buffer(&asn_DEF_NR_UL_DCCH_Message, + NULL, + (void *)&ul_dcch_msg, + buffer, + buffer_size); + AssertFatal(enc_rval.encoded > 0,"ASN1 message encoding failed (%s, %lu)!\n", + enc_rval.failed_type->name,enc_rval.encoded); + LOG_D(NR_RRC,"RRCSetupComplete Encoded %zd bits (%zd bytes)\n",enc_rval.encoded,(enc_rval.encoded+7)/8); + + return((enc_rval.encoded+7)/8); } //------------------------------------------------------------------------------ @@ -1993,11 +1962,8 @@ NR_SRB_ToAddModList_t **SRB_configList buffer, 100); - if(enc_rval.encoded == -1) { - LOG_E(NR_RRC, "[gNB AssertFatal]ASN1 message encoding failed (%s, %lu)!\n", - enc_rval.failed_type->name, enc_rval.encoded); - return -1; - } + AssertFatal(enc_rval.encoded > 0, "ASN1 message encoding failed (%s, %lu)!\n", + enc_rval.failed_type->name, enc_rval.encoded); LOG_D(NR_RRC,"RRCReestablishment Encoded %u bits (%u bytes)\n", (uint32_t)enc_rval.encoded, (uint32_t)(enc_rval.encoded+7)/8); diff --git a/openair2/RRC/NR/cucp_cuup_direct.c b/openair2/RRC/NR/cucp_cuup_direct.c new file mode 100644 index 0000000000..12530c7b82 --- /dev/null +++ b/openair2/RRC/NR/cucp_cuup_direct.c @@ -0,0 +1,229 @@ +/* + * 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: + * conmnc_digit_lengtht@openairinterface.org + */ + +#include + +#include "cucp_cuup_if.h" +#include "platform_types.h" +#include "nr_rrc_defs.h" + +#include "softmodem-common.h" +#include "nr_rrc_proto.h" +#include "nr_rrc_extern.h" +#include "openair2/COMMON/e1ap_messages_types.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 +#include "openair3/ocp-gtpu/gtp_itf.h" +#include "rrc_gNB_GTPV1U.h" +#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, + e1ap_bearer_setup_req_t *const req, + instance_t gtpInst, + ue_id_t ue_id, + int remote_port, + in_addr_t my_addr) { + + resp->numPDUSessions = req->numPDUSessions; + transport_layer_addr_t dummy_address = {0}; + dummy_address.length = 32; // IPv4 + for (int i=0; i < req->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 *drb2Setup = req->pduSession[i].DRBnGRanList + j; + DRB_nGRAN_setup_t *drbSetup = resp->pduSession[i].DRBnGRanList + j; + + drbSetup->numUpParam = 1; + drbSetup->UpParamList[0].tlAddress = my_addr; + drbSetup->UpParamList[0].teId = newGtpuCreateTunnel(gtpInst, + (ue_id & 0xFFFF), + drb2Setup->id, + drb2Setup->id, + 0xFFFF, // We will set the right value from DU answer + -1, // no qfi + dummy_address, // We will set the right value from DU answer + remote_port, + cu_f1u_data_req, + NULL); + drbSetup->id = drb2Setup->id; + + drbSetup->numQosFlowSetup = drb2Setup->numQosFlow2Setup; + for (int k=0; k < drbSetup->numQosFlowSetup; k++) { + drbSetup->qosFlows[k].id = drb2Setup->qosFlows[k].id; + } + } + } +} + +void CU_update_UP_DL_tunnel(e1ap_bearer_setup_req_t *const req, instance_t instance, ue_id_t ue_id) { + for (int i=0; i < req->numPDUSessionsMod; i++) { + for (int j=0; j < req->pduSessionMod[i].numDRB2Modify; j++) { + DRB_nGRAN_to_setup_t *drb_p = req->pduSessionMod[i].DRBnGRanModList + j; + + transport_layer_addr_t newRemoteAddr; + newRemoteAddr.length = 32; // IPv4 + memcpy(newRemoteAddr.buffer, + &drb_p->DlUpParamList[0].tlAddress, + sizeof(in_addr_t)); + + GtpuUpdateTunnelOutgoingAddressAndTeid(instance, + (ue_id & 0xFFFF), + (ebi_t)drb_p->id, + *(in_addr_t*)&newRemoteAddr.buffer, + drb_p->DlUpParamList[0].teId); + } + } +} + +static int drb_config_gtpu_create(const protocol_ctxt_t *const ctxt_p, + rrc_gNB_ue_context_t *ue_context_p, + e1ap_bearer_setup_req_t *const req, + NR_DRB_ToAddModList_t *DRB_configList, + NR_SRB_ToAddModList_t *SRB_configList, + instance_t instance) { + + gtpv1u_gnb_create_tunnel_req_t create_tunnel_req={0}; + gtpv1u_gnb_create_tunnel_resp_t create_tunnel_resp={0}; + + for (int i=0; i < ue_context_p->ue_context.nb_of_pdusessions; i++) { + pdu_session_param_t *pdu = ue_context_p->ue_context.pduSession + i; + create_tunnel_req.pdusession_id[i] = pdu->param.pdusession_id; + create_tunnel_req.incoming_rb_id[i] = i + 1; + create_tunnel_req.outgoing_qfi[i] = req->pduSession[i].DRBnGRanList[0].qosFlows[0].id; + memcpy(&create_tunnel_req.dst_addr[i].buffer, + &pdu->param.upf_addr.buffer, + sizeof(uint8_t)*20); + create_tunnel_req.dst_addr[i].length = pdu->param.upf_addr.length; + create_tunnel_req.outgoing_teid[i] = pdu->param.gtp_teid; + } + create_tunnel_req.num_tunnels = ue_context_p->ue_context.nb_of_pdusessions; + create_tunnel_req.ue_id = ue_context_p->ue_context.rnti; + + int ret = gtpv1u_create_ngu_tunnel(getCxtE1(instance)->gtpInstN3, &create_tunnel_req, &create_tunnel_resp); + + if (ret != 0) { + LOG_E(NR_RRC,"rrc_gNB_process_NGAP_PDUSESSION_SETUP_REQ : gtpv1u_create_ngu_tunnel failed,start to release UE rnti %ld\n", + create_tunnel_req.ue_id); + return ret; + } + + nr_rrc_gNB_process_GTPV1U_CREATE_TUNNEL_RESP(ctxt_p, + &create_tunnel_resp); + + uint8_t *kRRCenc = NULL; + uint8_t *kRRCint = NULL; + uint8_t *kUPenc = NULL; + uint8_t *kUPint = NULL; + /* Derive the keys from kgnb */ + if (DRB_configList != NULL) { + nr_derive_key_up_enc(ue_context_p->ue_context.ciphering_algorithm, + ue_context_p->ue_context.kgnb, + &kUPenc); + nr_derive_key_up_int(ue_context_p->ue_context.integrity_algorithm, + ue_context_p->ue_context.kgnb, + &kUPint); + } + + nr_derive_key_rrc_enc(ue_context_p->ue_context.ciphering_algorithm, + ue_context_p->ue_context.kgnb, + &kRRCenc); + nr_derive_key_rrc_int(ue_context_p->ue_context.integrity_algorithm, + ue_context_p->ue_context.kgnb, + &kRRCint); + /* Refresh SRBs/DRBs */ + + LOG_D(NR_RRC,"Configuring PDCP DRBs/SRBs for UE %x\n",ue_context_p->ue_context.rnti); + + nr_pdcp_add_srbs(ctxt_p->enb_flag, ctxt_p->rntiMaybeUEid, + SRB_configList, + (ue_context_p->ue_context.integrity_algorithm << 4) + | ue_context_p->ue_context.ciphering_algorithm, + kRRCenc, + kRRCint); + + nr_pdcp_add_drbs(ctxt_p->enb_flag, ctxt_p->rntiMaybeUEid, + DRB_configList, + (ue_context_p->ue_context.integrity_algorithm << 4) + | ue_context_p->ue_context.ciphering_algorithm, + kUPenc, + kUPint, + get_softmodem_params()->sa ? ue_context_p->ue_context.masterCellGroup->rlc_BearerToAddModList : NULL); + + return ret; +} + +static NR_SRB_ToAddModList_t **generateSRB2_confList(gNB_RRC_UE_t *ue, NR_SRB_ToAddModList_t *SRB_configList, uint8_t xid) +{ + NR_SRB_ToAddModList_t **SRB_configList2 = NULL; + + SRB_configList2 = &ue->SRB_configList2[xid]; + if (*SRB_configList2 == NULL) { + *SRB_configList2 = CALLOC(1, sizeof(**SRB_configList2)); + NR_SRB_ToAddMod_t *SRB2_config = CALLOC(1, sizeof(*SRB2_config)); + SRB2_config->srb_Identity = 2; + asn1cSeqAdd(&(*SRB_configList2)->list, SRB2_config); + asn1cSeqAdd(&SRB_configList->list, SRB2_config); + } + + return SRB_configList2; +} +static void cucp_cuup_bearer_context_setup_direct(e1ap_bearer_setup_req_t *const req, instance_t instance) { + rrc_gNB_ue_context_t *ue_context_p = rrc_gNB_get_ue_context(RC.nrrrc[GNB_INSTANCE_TO_MODULE_ID(instance)], req->rnti); + protocol_ctxt_t ctxt = {0}; + PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, 0, GNB_FLAG_YES, ue_context_p->ue_context.rnti, 0, 0, 0); + + fill_DRB_configList(&ctxt, ue_context_p); + + gNB_RRC_INST *rrc = RC.nrrrc[ctxt.module_id]; + // Fixme: xid not random, but almost! + NR_SRB_ToAddModList_t **SRB_configList2 = generateSRB2_confList(&ue_context_p->ue_context, ue_context_p->ue_context.SRB_configList, ue_context_p->ue_context.pduSession[0].xid); + // GTP tunnel for UL + int ret = drb_config_gtpu_create(&ctxt, ue_context_p, req, ue_context_p->ue_context.DRB_configList, *SRB_configList2, rrc->e1_inst); + if (ret < 0) AssertFatal(false, "Unable to configure DRB or to create GTP Tunnel\n"); + + if(!NODE_IS_CU(RC.nrrrc[ctxt.module_id]->node_type)) { + rrc_gNB_generate_dedicatedRRCReconfiguration(&ctxt, ue_context_p, NULL); + } 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_context_p->ue_context.rnti, remote_port, my_addr); + + 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) { + instance_t gtpInst = getCxt(CUtype, instance)->gtpInst; + CU_update_UP_DL_tunnel(req, gtpInst, req->rnti); +} + +void cucp_cuup_message_transfer_direct_init(gNB_RRC_INST *rrc) { + rrc->cucp_cuup.bearer_context_setup = cucp_cuup_bearer_context_setup_direct; + rrc->cucp_cuup.bearer_context_mod = cucp_cuup_bearer_context_mod_direct; +} diff --git a/openair2/RRC/NR/cucp_cuup_e1ap.c b/openair2/RRC/NR/cucp_cuup_e1ap.c new file mode 100644 index 0000000000..069629db0b --- /dev/null +++ b/openair2/RRC/NR/cucp_cuup_e1ap.c @@ -0,0 +1,61 @@ +/* + * 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: + * conmnc_digit_lengtht@openairinterface.org + */ + +#include "cucp_cuup_if.h" +#include + +#include "platform_types.h" +#include "nr_rrc_defs.h" + +#include "nr_rrc_proto.h" +#include "nr_rrc_extern.h" +#include "cucp_cuup_if.h" +#include "openair2/COMMON/e1ap_messages_types.h" +#include "UTIL/OSA/osa_defs.h" +#include +#include "common/ran_context.h" + +extern RAN_CONTEXT_t RC; + +static void cucp_cuup_bearer_context_setup_e1ap(e1ap_bearer_setup_req_t *const req, instance_t instance) { + rrc_gNB_ue_context_t *ue_context_p = rrc_gNB_get_ue_context(RC.nrrrc[GNB_INSTANCE_TO_MODULE_ID(instance)], req->rnti); + protocol_ctxt_t ctxt = {0}; + PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, 0, GNB_FLAG_YES, ue_context_p->ue_context.rnti, 0, 0, 0); + + fill_DRB_configList(&ctxt, ue_context_p); + MessageDef *msg_p = itti_alloc_new_message(TASK_CUCP_E1, instance, E1AP_BEARER_CONTEXT_SETUP_REQ); + e1ap_bearer_setup_req_t *bearer_req = &E1AP_BEARER_CONTEXT_SETUP_REQ(msg_p); + memcpy(bearer_req, req, sizeof(e1ap_bearer_setup_req_t)); + + itti_send_msg_to_task (TASK_CUCP_E1, instance, msg_p); +} + +static void cucp_cuup_bearer_context_mod_e1ap(e1ap_bearer_setup_req_t *const req, instance_t instance) { + MessageDef *msg = itti_alloc_new_message(TASK_CUCP_E1, instance, E1AP_BEARER_CONTEXT_MODIFICATION_REQ); + e1ap_bearer_setup_req_t *req_msg = &E1AP_BEARER_CONTEXT_SETUP_REQ(msg); + memcpy(req_msg, req, sizeof(*req)); + itti_send_msg_to_task(TASK_CUCP_E1, instance, msg); +} + +void cucp_cuup_message_transfer_e1ap_init(gNB_RRC_INST *rrc) { + rrc->cucp_cuup.bearer_context_setup = cucp_cuup_bearer_context_setup_e1ap; + rrc->cucp_cuup.bearer_context_mod = cucp_cuup_bearer_context_mod_e1ap; +} diff --git a/openair2/RRC/NR/cucp_cuup_if.h b/openair2/RRC/NR/cucp_cuup_if.h new file mode 100644 index 0000000000..079a32e850 --- /dev/null +++ b/openair2/RRC/NR/cucp_cuup_if.h @@ -0,0 +1,42 @@ +/* + * 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: + * conmnc_digit_lengtht@openairinterface.org + */ + +#ifndef CUCP_CUUP_IF_H +#define CUCP_CUUP_IF_H + +#include +#include "platform_types.h" + +struct e1ap_bearer_setup_req_s; +struct e1ap_bearer_setup_resp_s; +typedef void (*cucp_cuup_bearer_context_setup_func_t)(struct e1ap_bearer_setup_req_s *const req, instance_t instance); + +struct gNB_RRC_INST_s; +void cucp_cuup_message_transfer_direct_init(struct gNB_RRC_INST_s *rrc); +void cucp_cuup_message_transfer_e1ap_init(struct gNB_RRC_INST_s *rrc); +void fill_e1ap_bearer_setup_resp(struct e1ap_bearer_setup_resp_s *resp, + struct e1ap_bearer_setup_req_s *const req, + instance_t gtpInst, + ue_id_t ue_id, + int remote_port, + in_addr_t my_addr); +void CU_update_UP_DL_tunnel(struct e1ap_bearer_setup_req_s *const req, instance_t instance, ue_id_t ue_id); +#endif diff --git a/openair2/RRC/NR/nr_rrc_common.c b/openair2/RRC/NR/nr_rrc_common.c index 828e392460..85e9c71eaa 100644 --- a/openair2/RRC/NR/nr_rrc_common.c +++ b/openair2/RRC/NR/nr_rrc_common.c @@ -49,21 +49,14 @@ extern UE_MAC_INST *UE_mac_inst; extern mui_t rrc_gNB_mui; //----------------------------------------------------------------------------- -int rrc_init_nr_global_param(void){ - +void rrc_init_nr_srb_param(NR_LCHAN_DESC *chan) +{ rrc_rlc_register_rrc (rrc_data_ind, NULL); //register with rlc - DCCH_LCHAN_DESC.transport_block_size = 4; - DCCH_LCHAN_DESC.max_transport_blocks = 16; - DCCH_LCHAN_DESC.Delay_class = 1; - DTCH_DL_LCHAN_DESC.transport_block_size = 52; - DTCH_DL_LCHAN_DESC.max_transport_blocks = 20; - DTCH_DL_LCHAN_DESC.Delay_class = 1; - DTCH_UL_LCHAN_DESC.transport_block_size = 52; - DTCH_UL_LCHAN_DESC.max_transport_blocks = 20; - DTCH_UL_LCHAN_DESC.Delay_class = 1; - - return 0; + chan->transport_block_size = 4; + chan->max_transport_blocks = 16; + chan->Delay_class = 1; + return; } //----------------------------------------------------------------------------- diff --git a/openair2/RRC/NR/nr_rrc_defs.h b/openair2/RRC/NR/nr_rrc_defs.h index 6b60d64842..b3026f6a0e 100644 --- a/openair2/RRC/NR/nr_rrc_defs.h +++ b/openair2/RRC/NR/nr_rrc_defs.h @@ -43,6 +43,7 @@ #include "common/platform_constants.h" #include "COMMON/platform_types.h" #include "mac_rrc_dl.h" +#include "cucp_cuup_if.h" //#include "COMMON/mac_rrc_primitives.h" @@ -416,7 +417,7 @@ typedef struct rrc_gNB_ue_context_s { // another key for protocol layers but should not be used as a key for RB tree uid_t local_uid; - /* UE id for initial connection to S1AP */ + /* UE id for initial connection to NGAP */ struct gNB_RRC_UE_s ue_context; } rrc_gNB_ue_context_t; @@ -476,6 +477,11 @@ typedef struct nr_mac_rrc_dl_if_s { dl_rrc_message_transfer_func_t dl_rrc_message_transfer; } nr_mac_rrc_dl_if_t; +typedef struct cucp_cuup_if_s { + cucp_cuup_bearer_context_setup_func_t bearer_context_setup; + cucp_cuup_bearer_context_setup_func_t bearer_context_mod; +} cucp_cuup_if_t; + //---NR---(completely change)--------------------- typedef struct gNB_RRC_INST_s { @@ -499,6 +505,9 @@ typedef struct gNB_RRC_INST_s { // RRC configuration gNB_RrcConfigurationReq configuration; + // gNB N3 GTPU instance + instance_t e1_inst; + // other PLMN parameters /// Mobile country code int mcc; @@ -527,6 +536,8 @@ typedef struct gNB_RRC_INST_s { nr_security_configuration_t security; nr_mac_rrc_dl_if_t mac_rrc; + cucp_cuup_if_t cucp_cuup; + } gNB_RRC_INST; #include "nr_rrc_proto.h" //should be put here otherwise compilation error diff --git a/openair2/RRC/NR/nr_rrc_extern.h b/openair2/RRC/NR/nr_rrc_extern.h index 7283b25be0..70493f1010 100644 --- a/openair2/RRC/NR/nr_rrc_extern.h +++ b/openair2/RRC/NR/nr_rrc_extern.h @@ -53,8 +53,7 @@ extern void* bigphys_malloc(int); //uint8_t RACH_TIME_ALLOC; extern uint16_t RACH_FREQ_ALLOC; -//uint8_t NB_RACH; -extern LCHAN_DESC BCCH_LCHAN_DESC,CCCH_LCHAN_DESC,DCCH_LCHAN_DESC,DTCH_DL_LCHAN_DESC,DTCH_UL_LCHAN_DESC; +// uint8_t NB_RACH; extern MAC_MEAS_T BCCH_MEAS_TRIGGER,CCCH_MEAS_TRIGGER,DCCH_MEAS_TRIGGER,DTCH_MEAS_TRIGGER; extern MAC_AVG_T BCCH_MEAS_AVG,CCCH_MEAS_AVG,DCCH_MEAS_AVG, DTCH_MEAS_AVG; @@ -63,7 +62,6 @@ extern UE_PF_PO_t UE_PF_PO[NFAPI_CC_MAX][MAX_MOBILES_PER_ENB]; extern pthread_mutex_t ue_pf_po_mutex; extern uint16_t reestablish_rnti_map[MAX_MOBILES_PER_ENB][2]; -char openair_rrc_gNB_configuration(const module_id_t gnb_mod_idP, gNB_RrcConfigurationReq *configuration); #endif diff --git a/openair2/RRC/NR/nr_rrc_proto.h b/openair2/RRC/NR/nr_rrc_proto.h index 0d7e0e7f97..dc32e71aea 100644 --- a/openair2/RRC/NR/nr_rrc_proto.h +++ b/openair2/RRC/NR/nr_rrc_proto.h @@ -44,12 +44,7 @@ #include "NR_SecurityConfig.h" #define NR_MAX_SUPPORTED_DL_LAYERS 2 - -int rrc_init_nr_global_param(void); - -void rrc_config_nr_buffer(NR_SRB_INFO* Srb_info, - uint8_t Lchan_type, - uint8_t Role); +void rrc_init_nr_srb_param(NR_LCHAN_DESC *chan); uint16_t mac_rrc_nr_data_req(const module_id_t Mod_idP, const int CC_id, @@ -104,18 +99,6 @@ int generate_CG_Config(gNB_RRC_INST *rrc, NR_RRCReconfiguration_t *reconfig, NR_RadioBearerConfig_t *rbconfig); -void apply_macrlc_config(gNB_RRC_INST *rrc, - rrc_gNB_ue_context_t *const ue_context_pP, - const protocol_ctxt_t *const ctxt_pP ); - -void -rrc_gNB_generate_RRCSetup( - const protocol_ctxt_t *const ctxt_pP, - rrc_gNB_ue_context_t *const ue_context_pP, - const uint8_t *masterCellGroup, - int masterCellGroup_len, - NR_ServingCellConfigCommon_t *scc); - int parse_CG_ConfigInfo(gNB_RRC_INST *rrc, NR_CG_ConfigInfo_t *CG_ConfigInfo, x2ap_ENDC_sgnb_addition_req_t *m); void @@ -124,10 +107,7 @@ rrc_gNB_generate_SecurityModeCommand( rrc_gNB_ue_context_t *const ue_context_pP ); - uint8_t -rrc_gNB_get_next_transaction_identifier( - module_id_t gnb_mod_idP -); +unsigned int rrc_gNB_get_next_transaction_identifier(module_id_t gnb_mod_idP); void rrc_gNB_generate_UECapabilityEnquiry( @@ -209,6 +189,23 @@ rlc_op_status_t nr_rrc_rlc_config_asn1_req (const protocol_ctxt_t * const ctxt const NR_DRB_ToReleaseList_t * const drb2release_listP, struct NR_CellGroupConfig__rlc_BearerToAddModList *rlc_bearer2add_list); +void bearer_context_setup_direct(e1ap_bearer_setup_req_t *req, + instance_t instance); + +void bearer_context_setup_e1ap(e1ap_bearer_setup_req_t *req, + instance_t instance); + +void ue_cxt_mod_send_e1ap(MessageDef *msg, + instance_t instance); + +void ue_cxt_mod_direct(MessageDef *msg, + instance_t instance); + +void fill_DRB_configList(const protocol_ctxt_t *const ctxt_pP, + rrc_gNB_ue_context_t *ue_context_pP); + +void prepare_and_send_ue_context_modification_f1(rrc_gNB_ue_context_t *ue_context_p, + e1ap_bearer_setup_resp_t *e1ap_resp); void nr_pdcp_add_srbs(eNB_flag_t enb_flag, ue_id_t rntiMaybeUEid, NR_SRB_ToAddModList_t *const srb2add_list, const uint8_t security_modeP, uint8_t *const kRRCenc, uint8_t *const kUPint); void nr_pdcp_add_drbs(eNB_flag_t enb_flag, diff --git a/openair2/RRC/NR/rrc_gNB.c b/openair2/RRC/NR/rrc_gNB.c index b5a63cdf0d..0e2d5dac29 100644 --- a/openair2/RRC/NR/rrc_gNB.c +++ b/openair2/RRC/NR/rrc_gNB.c @@ -99,6 +99,10 @@ #include #include #include "LAYER2/nr_rlc/nr_rlc_oai_api.h" +#include "openair2/LAYER2/nr_pdcp/nr_pdcp_e1_api.h" +#include "openair2/F1AP/f1ap_common.h" +#include "openair2/SDAP/nr_sdap/nr_sdap_entity.h" +#include "cucp_cuup_if.h" #include "BIT_STRING.h" #include "assertions.h" @@ -132,10 +136,12 @@ bool DURecvCb(protocol_ctxt_t *ctxt_pP, return true; } -void openair_nr_rrc_on(const protocol_ctxt_t *const ctxt_pP) { - LOG_I(NR_RRC, PROTOCOL_NR_RRC_CTXT_FMT" gNB:OPENAIR NR RRC IN....\n",PROTOCOL_NR_RRC_CTXT_ARGS(ctxt_pP)); - rrc_config_nr_buffer (&RC.nrrrc[ctxt_pP->module_id]->carrier.SI, BCCH, 1); - RC.nrrrc[ctxt_pP->module_id]->carrier.SI.Active = 1; +static void openair_nr_rrc_on(gNB_RRC_INST *rrc) +{ + NR_SRB_INFO *si = &rrc->carrier.SI; + si->Rx_buffer.payload_size = 0; + si->Tx_buffer.payload_size = 0; + si->Active = 1; } ///---------------------------------------------------------------------------------------------------------------/// @@ -193,27 +199,34 @@ static void init_NR_SI(gNB_RRC_INST *rrc, gNB_RrcConfigurationReq *configuration } } -static void rrc_gNB_mac_rrc_init(gNB_RRC_INST *rrc) +static void rrc_gNB_CU_DU_init(gNB_RRC_INST *rrc) { switch (rrc->node_type) { + case ngran_gNB_CUCP: + mac_rrc_dl_f1ap_init(&rrc->mac_rrc); + cucp_cuup_message_transfer_e1ap_init(rrc); + break; case ngran_gNB_CU: mac_rrc_dl_f1ap_init(&rrc->mac_rrc); + cucp_cuup_message_transfer_direct_init(rrc); break; + case ngran_gNB: + mac_rrc_dl_direct_init(&rrc->mac_rrc); + cucp_cuup_message_transfer_direct_init(rrc); + break; case ngran_gNB_DU: /* silently drop this, as we currently still need the RRC at the DU. As * soon as this is not the case anymore, we can add the AssertFatal() */ //AssertFatal(1==0,"nothing to do for DU\n"); break; - case ngran_gNB: - mac_rrc_dl_direct_init(&rrc->mac_rrc); - break; default: AssertFatal(0 == 1, "Unknown node type %d\n", rrc->node_type); break; } } -char openair_rrc_gNB_configuration(const module_id_t gnb_mod_idP, gNB_RrcConfigurationReq *configuration) { +static void openair_rrc_gNB_configuration(const module_id_t gnb_mod_idP, gNB_RrcConfigurationReq *configuration) +{ protocol_ctxt_t ctxt = { 0 }; gNB_RRC_INST *rrc=RC.nrrrc[gnb_mod_idP]; PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, gnb_mod_idP, GNB_FLAG_YES, NOT_A_RNTI, 0, 0,gnb_mod_idP); @@ -225,7 +238,7 @@ char openair_rrc_gNB_configuration(const module_id_t gnb_mod_idP, gNB_RrcConfigu AssertFatal(configuration!=NULL,"configuration input is null\n"); rrc->module_id = gnb_mod_idP; rrc->Nb_ue = 0; - rrc_gNB_mac_rrc_init(rrc); + rrc_gNB_CU_DU_init(rrc); uid_linear_allocator_init(&rrc->uid_allocator); RB_INIT(&rrc->rrc_ue_head); rrc->initial_id2_s1ap_ids = hashtable_create (NUMBER_OF_UE_MAX * 2, NULL, NULL); @@ -241,13 +254,12 @@ char openair_rrc_gNB_configuration(const module_id_t gnb_mod_idP, gNB_RrcConfigu rrc->cell_info_configured = 0; LOG_I(NR_RRC, PROTOCOL_NR_RRC_CTXT_FMT" Checking release \n",PROTOCOL_NR_RRC_CTXT_ARGS(&ctxt)); init_NR_SI(rrc, configuration); - rrc_init_nr_global_param(); - openair_nr_rrc_on(&ctxt); - return 0; -}//END openair_rrc_gNB_configuration + openair_nr_rrc_on(rrc); + return; +} // END openair_rrc_gNB_configuration - -void rrc_gNB_process_AdditionRequestInformation(const module_id_t gnb_mod_idP, x2ap_ENDC_sgnb_addition_req_t *m) { +static void rrc_gNB_process_AdditionRequestInformation(const module_id_t gnb_mod_idP, x2ap_ENDC_sgnb_addition_req_t *m) +{ struct NR_CG_ConfigInfo *cg_configinfo = NULL; asn_dec_rval_t dec_rval = uper_decode_complete(NULL, &asn_DEF_NR_CG_ConfigInfo, @@ -272,24 +284,20 @@ void rrc_gNB_process_AdditionRequestInformation(const module_id_t gnb_mod_idP, x dec_rval.consumed, (dec_rval.consumed +7/8)); } - //----------------------------------------------------------------------------- -uint8_t -rrc_gNB_get_next_transaction_identifier( - module_id_t gnb_mod_idP -) +unsigned int rrc_gNB_get_next_transaction_identifier(module_id_t gnb_mod_idP) //----------------------------------------------------------------------------- { - static uint8_t nr_rrc_transaction_identifier[NUMBER_OF_gNB_MAX]; - nr_rrc_transaction_identifier[gnb_mod_idP] = (nr_rrc_transaction_identifier[gnb_mod_idP] + 1) % NR_RRC_TRANSACTION_IDENTIFIER_NUMBER; - LOG_T(NR_RRC, "generated xid is %d\n", nr_rrc_transaction_identifier[gnb_mod_idP]); - return nr_rrc_transaction_identifier[gnb_mod_idP]; + static unsigned int transaction_id[NUMBER_OF_gNB_MAX] = {0}; + // used also in NGAP thread, so need thread safe operation + unsigned int tmp = __atomic_add_fetch(&transaction_id[gnb_mod_idP], 1, __ATOMIC_SEQ_CST); + tmp %= NR_RRC_TRANSACTION_IDENTIFIER_NUMBER; + LOG_T(NR_RRC, "generated xid is %d\n", tmp); + return tmp; } -void apply_macrlc_config(gNB_RRC_INST *rrc, - rrc_gNB_ue_context_t *const ue_context_pP, - const protocol_ctxt_t *const ctxt_pP ) { - +static void apply_macrlc_config(gNB_RRC_INST *rrc, rrc_gNB_ue_context_t *const ue_context_pP, const protocol_ctxt_t *const ctxt_pP) +{ NR_CellGroupConfig_t *cgc = get_softmodem_params()->sa ? ue_context_pP->ue_context.masterCellGroup : NULL; rrc_mac_config_req_gNB(rrc->module_id, rrc->configuration.pdsch_AntennaPorts, @@ -308,27 +316,18 @@ void apply_macrlc_config(gNB_RRC_INST *rrc, ue_context_pP->ue_context.DRB_configList, NULL, get_softmodem_params()->sa ? cgc->rlc_BearerToAddModList : NULL); - } //----------------------------------------------------------------------------- -void -rrc_gNB_generate_RRCSetup( - const protocol_ctxt_t *const ctxt_pP, - rrc_gNB_ue_context_t *const ue_context_pP, - const uint8_t *masterCellGroup, - int masterCellGroup_len, - NR_ServingCellConfigCommon_t *scc) +static void rrc_gNB_generate_RRCSetup(const protocol_ctxt_t *const ctxt_pP, + rrc_gNB_ue_context_t *const ue_context_pP, + const uint8_t *masterCellGroup, + int masterCellGroup_len, + NR_ServingCellConfigCommon_t *scc) //----------------------------------------------------------------------------- { LOG_I(NR_RRC, "rrc_gNB_generate_RRCSetup for RNTI %04lx\n", ctxt_pP->rntiMaybeUEid); - // T(T_GNB_RRC_SETUP, - // T_INT(ctxt_pP->module_id), - // T_INT(ctxt_pP->frame), - // T_INT(ctxt_pP->subframe), - // T_INT(ctxt_pP->rnti)); - gNB_RRC_UE_t *ue_p = &ue_context_pP->ue_context; gNB_RRC_INST *rrc = RC.nrrrc[ctxt_pP->module_id]; unsigned char buf[1024]; @@ -368,11 +367,7 @@ rrc_gNB_generate_RRCSetup( } //----------------------------------------------------------------------------- -void -rrc_gNB_generate_RRCSetup_for_RRCReestablishmentRequest( - const protocol_ctxt_t *const ctxt_pP, - const int CC_id -) +static void rrc_gNB_generate_RRCSetup_for_RRCReestablishmentRequest(const protocol_ctxt_t *const ctxt_pP, const int CC_id) //----------------------------------------------------------------------------- { LOG_I(NR_RRC, "generate RRCSetup for RRCReestablishmentRequest \n"); @@ -440,10 +435,7 @@ rrc_gNB_generate_RRCSetup_for_RRCReestablishmentRequest( rrc_instance_p->mac_rrc.dl_rrc_message_transfer(ctxt_pP->module_id, &dl_rrc); } -void -rrc_gNB_generate_RRCReject( - const protocol_ctxt_t *const ctxt_pP, - rrc_gNB_ue_context_t *const ue_context_pP) +static void rrc_gNB_generate_RRCReject(const protocol_ctxt_t *const ctxt_pP, rrc_gNB_ue_context_t *const ue_context_pP) //----------------------------------------------------------------------------- { LOG_I(NR_RRC, "rrc_gNB_generate_RRCReject \n"); @@ -482,12 +474,7 @@ rrc_gNB_generate_RRCReject( /* * Process the rrc setup complete message from UE (SRB1 Active) */ -void -rrc_gNB_process_RRCSetupComplete( - const protocol_ctxt_t *const ctxt_pP, - rrc_gNB_ue_context_t *ue_context_pP, - NR_RRCSetupComplete_IEs_t *rrcSetupComplete -) +static void rrc_gNB_process_RRCSetupComplete(const protocol_ctxt_t *const ctxt_pP, rrc_gNB_ue_context_t *ue_context_pP, NR_RRCSetupComplete_IEs_t *rrcSetupComplete) //----------------------------------------------------------------------------- { LOG_A(NR_RRC, PROTOCOL_NR_RRC_CTXT_UE_FMT" [RAPROC] Logical Channel UL-DCCH, " "processing NR_RRCSetupComplete from UE (SRB1 Active)\n", @@ -504,22 +491,9 @@ rrc_gNB_process_RRCSetupComplete( } //----------------------------------------------------------------------------- -void -rrc_gNB_generate_defaultRRCReconfiguration( - const protocol_ctxt_t *const ctxt_pP, - rrc_gNB_ue_context_t *ue_context_pP -) +static void rrc_gNB_generate_defaultRRCReconfiguration(const protocol_ctxt_t *const ctxt_pP, rrc_gNB_ue_context_t *ue_context_pP) //----------------------------------------------------------------------------- { - uint8_t buffer[RRC_BUF_SIZE]; - int16_t size; - /*NR_SRB_ToAddModList_t **SRB_configList2 = NULL; - NR_SRB_ToAddModList_t *SRB_configList = ue_context_pP->ue_context.SRB_configList; - NR_DRB_ToAddModList_t **DRB_configList = NULL; - NR_DRB_ToAddModList_t **DRB_configList2 = NULL; - NR_SRB_ToAddMod_t *SRB2_config = NULL; - NR_DRB_ToAddMod_t *DRB_config = NULL; - NR_SDAP_Config_t *sdap_config = NULL;*/ struct NR_RRCReconfiguration_v1530_IEs__dedicatedNAS_MessageList *dedicatedNAS_MessageList = NULL; NR_DedicatedNAS_Message_t *dedicatedNAS_Message = NULL; @@ -527,66 +501,6 @@ rrc_gNB_generate_defaultRRCReconfiguration( uint8_t xid = rrc_gNB_get_next_transaction_identifier(ctxt_pP->module_id); /******************** Radio Bearer Config ********************/ - /* Configure SRB2 */ - /*SRB_configList2 = &ue_context_pP->ue_context.SRB_configList2[xid]; - if (*SRB_configList2) { - free(*SRB_configList2); - } - *SRB_configList2 = CALLOC(1, sizeof(**SRB_configList2)); - memset(*SRB_configList2, 0, sizeof(**SRB_configList2)); - SRB2_config = CALLOC(1, sizeof(*SRB2_config)); - SRB2_config->srb_Identity = 2; - asn1cSeqAdd(&(*SRB_configList2)->list, SRB2_config); - asn1cSeqAdd(&SRB_configList->list, SRB2_config);*/ - - /* Configure DRB */ - /*DRB_configList = &ue_context_pP->ue_context.DRB_configList; - if (*DRB_configList) { - free(*DRB_configList); - } - *DRB_configList = CALLOC(1, sizeof(**DRB_configList)); - memset(*DRB_configList, 0, sizeof(**DRB_configList)); - - DRB_configList2 = &ue_context_pP->ue_context.DRB_configList2[xid]; - if (*DRB_configList2) { - free(*DRB_configList2); - } - *DRB_configList2 = CALLOC(1, sizeof(**DRB_configList2)); - memset(*DRB_configList2, 0, sizeof(**DRB_configList2)); - - DRB_config = CALLOC(1, sizeof(*DRB_config)); - DRB_config->drb_Identity = 1; - DRB_config->cnAssociation = CALLOC(1, sizeof(*DRB_config->cnAssociation)); - DRB_config->cnAssociation->present = NR_DRB_ToAddMod__cnAssociation_PR_sdap_Config; - // TODO sdap_Config - sdap_config = CALLOC(1, sizeof(NR_SDAP_Config_t)); - memset(sdap_config, 0, sizeof(NR_SDAP_Config_t)); - DRB_config->cnAssociation->choice.sdap_Config = sdap_config; - // TODO pdcp_Config - DRB_config->reestablishPDCP = NULL; - DRB_config->recoverPDCP = NULL; - DRB_config->pdcp_Config = calloc(1, sizeof(*DRB_config->pdcp_Config)); - DRB_config->pdcp_Config->drb = calloc(1,sizeof(*DRB_config->pdcp_Config->drb)); - DRB_config->pdcp_Config->drb->discardTimer = calloc(1, sizeof(*DRB_config->pdcp_Config->drb->discardTimer)); - *DRB_config->pdcp_Config->drb->discardTimer = NR_PDCP_Config__drb__discardTimer_infinity; - DRB_config->pdcp_Config->drb->pdcp_SN_SizeUL = calloc(1, sizeof(*DRB_config->pdcp_Config->drb->pdcp_SN_SizeUL)); - *DRB_config->pdcp_Config->drb->pdcp_SN_SizeUL = NR_PDCP_Config__drb__pdcp_SN_SizeUL_len18bits; - DRB_config->pdcp_Config->drb->pdcp_SN_SizeDL = calloc(1, sizeof(*DRB_config->pdcp_Config->drb->pdcp_SN_SizeDL)); - *DRB_config->pdcp_Config->drb->pdcp_SN_SizeDL = NR_PDCP_Config__drb__pdcp_SN_SizeDL_len18bits; - DRB_config->pdcp_Config->drb->headerCompression.present = NR_PDCP_Config__drb__headerCompression_PR_notUsed; - DRB_config->pdcp_Config->drb->headerCompression.choice.notUsed = 0; - - DRB_config->pdcp_Config->drb->integrityProtection = NULL; - DRB_config->pdcp_Config->drb->statusReportRequired = NULL; - DRB_config->pdcp_Config->drb->outOfOrderDelivery = NULL; - DRB_config->pdcp_Config->moreThanOneRLC = NULL; - - DRB_config->pdcp_Config->t_Reordering = calloc(1, sizeof(*DRB_config->pdcp_Config->t_Reordering)); - *DRB_config->pdcp_Config->t_Reordering = NR_PDCP_Config__t_Reordering_ms100; - DRB_config->pdcp_Config->ext1 = NULL; - - asn1cSeqAdd(&(*DRB_configList)->list, DRB_config); - asn1cSeqAdd(&(*DRB_configList2)->list, DRB_config);*/ dedicatedNAS_MessageList = CALLOC(1, sizeof(struct NR_RRCReconfiguration_v1530_IEs__dedicatedNAS_MessageList)); @@ -594,7 +508,6 @@ rrc_gNB_generate_defaultRRCReconfiguration( for (int i = 0; i < ue_context_pP->ue_context.nb_of_pdusessions; i++) { if (ue_context_pP->ue_context.pduSession[i].param.nas_pdu.buffer != NULL) { dedicatedNAS_Message = CALLOC(1, sizeof(NR_DedicatedNAS_Message_t)); - memset(dedicatedNAS_Message, 0, sizeof(OCTET_STRING_t)); OCTET_STRING_fromBuf(dedicatedNAS_Message, (char *)ue_context_pP->ue_context.pduSession[i].param.nas_pdu.buffer, ue_context_pP->ue_context.pduSession[i].param.nas_pdu.length); @@ -608,7 +521,6 @@ rrc_gNB_generate_defaultRRCReconfiguration( if (ue_context_pP->ue_context.nas_pdu_flag == 1) { dedicatedNAS_Message = CALLOC(1, sizeof(NR_DedicatedNAS_Message_t)); - memset(dedicatedNAS_Message, 0, sizeof(OCTET_STRING_t)); OCTET_STRING_fromBuf(dedicatedNAS_Message, (char *)ue_context_pP->ue_context.nas_pdu.buffer, ue_context_pP->ue_context.nas_pdu.length); @@ -625,21 +537,23 @@ rrc_gNB_generate_defaultRRCReconfiguration( NR_MeasConfig_t *measconfig = get_defaultMeasConfig(&rrc->configuration); gNB_RRC_UE_t *ue_p = &ue_context_pP->ue_context; - memset(buffer, 0, sizeof(buffer)); - size = do_RRCReconfiguration(ctxt_pP, buffer, sizeof(buffer), - xid, - NULL, //*SRB_configList2, - NULL, //*DRB_configList, - NULL, - NULL, - NULL, - measconfig, - dedicatedNAS_MessageList, - ue_context_pP, - &rrc->carrier, - &rrc->configuration, - NULL, - ue_p->masterCellGroup); + uint8_t buffer[RRC_BUF_SIZE] = {0}; + int size = do_RRCReconfiguration(ctxt_pP, + buffer, + sizeof(buffer), + xid, + NULL, //*SRB_configList2, + NULL, //*DRB_configList, + NULL, + NULL, + NULL, + measconfig, + dedicatedNAS_MessageList, + ue_context_pP, + &rrc->carrier, + &rrc->configuration, + NULL, + ue_p->masterCellGroup); AssertFatal(size > 0, "cannot encode RRCReconfiguration in %s()\n", __func__); LOG_W(RRC, "do_RRCReconfiguration(): size %d\n", size); @@ -647,6 +561,7 @@ rrc_gNB_generate_defaultRRCReconfiguration( xer_fprint(stdout, &asn_DEF_NR_CellGroupConfig, ue_p->masterCellGroup); } + // suspicious if it is always malloced before ? free(ue_context_pP->ue_context.nas_pdu.buffer); LOG_DUMPMSG(NR_RRC, DEBUG_RRC,(char *)buffer, size, "[MSG] RRC Reconfiguration\n"); @@ -666,6 +581,8 @@ rrc_gNB_generate_defaultRRCReconfiguration( ue_context_pP->ue_context.rnti); switch (RC.nrrrc[ctxt_pP->module_id]->node_type) { case ngran_gNB_CU: + case ngran_gNB_CUCP: + case ngran_gNB: nr_rrc_data_req(ctxt_pP, DCCH, rrc_gNB_mui++, @@ -682,28 +599,6 @@ rrc_gNB_generate_defaultRRCReconfiguration( AssertFatal(1==0,"nothing to do for DU\n"); break; - case ngran_gNB: - { - LOG_D(NR_RRC, "[FRAME %05d][RRC_gNB][MOD %u][][--- PDCP_DATA_REQ/%d Bytes (rrcReconfiguration to UE %x MUI %d) --->][PDCP][MOD %u][RB %u]\n", - ctxt_pP->frame, - ctxt_pP->module_id, - size, - ue_context_pP->ue_context.rnti, - rrc_gNB_mui, - ctxt_pP->module_id, - DCCH); - nr_rrc_data_req(ctxt_pP, - DCCH, - rrc_gNB_mui++, - SDU_CONFIRM_NO, - size, - buffer, - PDCP_TRANSMISSION_MODE_CONTROL); - // rrc_pdcp_config_asn1_req - // rrc_rlc_config_asn1_req - } - break; - default : LOG_W(NR_RRC, "Unknown node type %d\n", RC.nrrrc[ctxt_pP->module_id]->node_type); } @@ -735,37 +630,22 @@ rrc_gNB_generate_defaultRRCReconfiguration( } } -//----------------------------------------------------------------------------- -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 fill_DRB_configList(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]; gNB_RRC_UE_t *ue_p = &ue_context_pP->ue_context; NR_DRB_ToAddModList_t **DRB_configList = NULL; NR_DRB_ToAddModList_t **DRB_configList2 = NULL; - NR_SRB_ToAddModList_t *SRB_configList = ue_context_pP->ue_context.SRB_configList; - struct NR_RRCReconfiguration_v1530_IEs__dedicatedNAS_MessageList - *dedicatedNAS_MessageList = NULL; - NR_DedicatedNAS_Message_t *dedicatedNAS_Message = NULL; - uint8_t buffer[RRC_BUF_SIZE]; - uint16_t size; int qos_flow_index = 0; int pdu_sessions_done = 0; int i; uint8_t drb_id_to_setup_start = 0; uint8_t nb_drb_to_setup = rrc->configuration.drbs; long drb_priority[NGAP_MAX_DRBS_PER_UE]; - NR_CellGroupConfig_t *cellGroupConfig = NULL; uint8_t xid = rrc_gNB_get_next_transaction_identifier(ctxt_pP->module_id); - NR_SRB_ToAddModList_t **SRB_configList2 = generateSRB2_confList(ue_p, SRB_configList, xid); - DRB_configList = &ue_context_pP->ue_context.DRB_configList; if (*DRB_configList) { free(*DRB_configList); @@ -780,8 +660,6 @@ rrc_gNB_generate_dedicatedRRCReconfiguration( *DRB_configList2 = CALLOC(1, sizeof(**DRB_configList2)); memset(*DRB_configList2, 0, sizeof(**DRB_configList2)); - dedicatedNAS_MessageList = CALLOC(1, sizeof(struct NR_RRCReconfiguration_v1530_IEs__dedicatedNAS_MessageList)); - for (i = 0; i < ue_context_pP->ue_context.setup_pdu_sessions; i++) { if (pdu_sessions_done >= ue_context_pP->ue_context.nb_of_pdusessions) { break; @@ -880,11 +758,42 @@ rrc_gNB_generate_dedicatedRRCReconfiguration( asn1cSeqAdd(&(*DRB_configList)->list, DRB_config); asn1cSeqAdd(&(*DRB_configList2)->list, DRB_config); } + LOG_D(RRC, "DRB Priority %ld\n", drb_priority[drb_id]); // To supress warning for now } } ue_context_pP->ue_context.pduSession[i].status = PDU_SESSION_STATUS_DONE; ue_context_pP->ue_context.pduSession[i].xid = xid; + } +} + +//----------------------------------------------------------------------------- +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 +) +//----------------------------------------------------------------------------- +{ + gNB_RRC_INST *rrc = RC.nrrrc[ctxt_pP->module_id]; + long drb_priority[1] = {13}; // For now, we assume only one drb per pdu sessions with a default preiority (will be dynamique in future) + NR_CellGroupConfig_t *cellGroupConfig = NULL; + uint8_t buffer[RRC_BUF_SIZE]; + uint16_t size; + int xid = -1; + + int drb_id_to_setup_start = 1; + NR_DRB_ToAddModList_t *DRB_configList = ue_context_pP->ue_context.DRB_configList; + int nb_drb_to_setup = DRB_configList->list.count; + + struct NR_RRCReconfiguration_v1530_IEs__dedicatedNAS_MessageList *dedicatedNAS_MessageList = NULL; + NR_DedicatedNAS_Message_t *dedicatedNAS_Message = NULL; + dedicatedNAS_MessageList = CALLOC(1, sizeof(struct NR_RRCReconfiguration_v1530_IEs__dedicatedNAS_MessageList)); + + for (int i=0; i < nb_drb_to_setup; i++) { + NR_DRB_ToAddMod_t *DRB_config = DRB_configList->list.array[i]; + if (drb_id_to_setup_start == 1) drb_id_to_setup_start = DRB_config->drb_Identity; if (ue_context_pP->ue_context.pduSession[i].param.nas_pdu.buffer != NULL) { dedicatedNAS_Message = CALLOC(1, sizeof(NR_DedicatedNAS_Message_t)); @@ -899,6 +808,8 @@ rrc_gNB_generate_dedicatedRRCReconfiguration( // TODO LOG_E(NR_RRC,"no NAS info (pdusession id %d)\n", i); } + + xid = ue_context_pP->ue_context.pduSession[i].xid; } /* If list is empty free the list and reset the address */ @@ -919,10 +830,14 @@ rrc_gNB_generate_dedicatedRRCReconfiguration( cellGroupConfig = cell_groupConfig_from_DU; } + AssertFatal(xid > -1, "Invalid xid %d. No PDU sessions setup to configure.\n", xid); + NR_SRB_ToAddModList_t *SRB_configList2 = NULL; + SRB_configList2 = ue_context_pP->ue_context.SRB_configList2[xid]; + size = do_RRCReconfiguration(ctxt_pP, buffer, sizeof(buffer), xid, - *SRB_configList2, - *DRB_configList, + SRB_configList2, + DRB_configList, NULL, NULL, NULL, @@ -936,7 +851,7 @@ rrc_gNB_generate_dedicatedRRCReconfiguration( LOG_DUMPMSG(NR_RRC,DEBUG_RRC,(char *)buffer,size,"[MSG] RRC Reconfiguration\n"); /* Free all NAS PDUs */ - for (i = 0; i < ue_context_pP->ue_context.nb_of_pdusessions; i++) { + for (int i = 0; i < ue_context_pP->ue_context.nb_of_pdusessions; i++) { if (ue_context_pP->ue_context.pduSession[i].param.nas_pdu.buffer != NULL) { /* Free the NAS PDU buffer and invalidate it */ free(ue_context_pP->ue_context.pduSession[i].param.nas_pdu.buffer); @@ -1208,19 +1123,7 @@ rrc_gNB_generate_dedicatedRRCReconfiguration_release( } memset(buffer, 0, sizeof(buffer)); - size = do_RRCReconfiguration(ctxt_pP, buffer, sizeof(buffer), xid, - NULL, - NULL, - *DRB_Release_configList2, - NULL, - NULL, - NULL, - dedicatedNAS_MessageList, - NULL, - NULL, - NULL, - NULL, - NULL); + size = do_RRCReconfiguration(ctxt_pP, buffer, sizeof(buffer), xid, NULL, NULL, *DRB_Release_configList2, NULL, NULL, NULL, dedicatedNAS_MessageList, NULL, NULL, NULL, NULL, NULL); ue_context_pP->ue_context.pdu_session_release_command_flag = 1; @@ -1273,10 +1176,6 @@ rrc_gNB_process_RRCReconfigurationComplete( ) { int drb_id; - uint8_t *kRRCenc = NULL; - uint8_t *kRRCint = NULL; - uint8_t *kUPenc = NULL; - uint8_t *kUPint = NULL; 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]; @@ -1285,36 +1184,6 @@ rrc_gNB_process_RRCReconfigurationComplete( ue_context_pP->ue_context.ue_reestablishment_timer = 0; - /* Derive the keys from kgnb */ - if (DRB_configList != NULL) { - nr_derive_key_up_enc(ue_context_pP->ue_context.ciphering_algorithm, - ue_context_pP->ue_context.kgnb, - &kUPenc); - nr_derive_key_up_int(ue_context_pP->ue_context.integrity_algorithm, - ue_context_pP->ue_context.kgnb, - &kUPint); - } - - nr_derive_key_rrc_enc(ue_context_pP->ue_context.ciphering_algorithm, - ue_context_pP->ue_context.kgnb, - &kRRCenc); - nr_derive_key_rrc_int(ue_context_pP->ue_context.integrity_algorithm, - ue_context_pP->ue_context.kgnb, - &kRRCint); - /* Refresh SRBs/DRBs */ - - LOG_D(NR_RRC,"Configuring PDCP DRBs/SRBs for UE %x\n",ue_context_pP->ue_context.rnti); - - nr_pdcp_add_srbs(ctxt_pP->enb_flag, ctxt_pP->rntiMaybeUEid, SRB_configList, (ue_context_pP->ue_context.integrity_algorithm << 4) | ue_context_pP->ue_context.ciphering_algorithm, kRRCenc, kRRCint); - - nr_pdcp_add_drbs(ctxt_pP->enb_flag, - ctxt_pP->rntiMaybeUEid, - DRB_configList, - (ue_context_pP->ue_context.integrity_algorithm << 4) | ue_context_pP->ue_context.ciphering_algorithm, - kUPenc, - kUPint, - get_softmodem_params()->sa ? ue_context_pP->ue_context.masterCellGroup->rlc_BearerToAddModList : NULL); - /* Refresh SRBs/DRBs */ if (!NODE_IS_CU(RC.nrrrc[ctxt_pP->module_id]->node_type)) { LOG_D(NR_RRC,"Configuring RLC DRBs/SRBs for UE %x\n",ue_context_pP->ue_context.rnti); @@ -1500,13 +1369,7 @@ rrc_gNB_generate_RRCReestablishment( } //----------------------------------------------------------------------------- -void -rrc_gNB_process_RRCConnectionReestablishmentComplete( - const protocol_ctxt_t *const ctxt_pP, - const rnti_t reestablish_rnti, - rrc_gNB_ue_context_t *ue_context_pP, - const uint8_t xid -) +void rrc_gNB_process_RRCConnectionReestablishmentComplete(const protocol_ctxt_t *const ctxt_pP, const rnti_t reestablish_rnti, rrc_gNB_ue_context_t *ue_context_pP, const uint8_t old_xid) //----------------------------------------------------------------------------- { LOG_I(NR_RRC, @@ -1524,12 +1387,12 @@ rrc_gNB_process_RRCConnectionReestablishmentComplete( uint8_t buffer[RRC_BUF_SIZE]; uint16_t size; - uint8_t next_xid = rrc_gNB_get_next_transaction_identifier(ctxt_pP->module_id); + uint8_t new_xid = rrc_gNB_get_next_transaction_identifier(ctxt_pP->module_id); int ret = 0; ue_context_pP->ue_context.StatusRrc = NR_RRC_CONNECTED; ue_context_pP->ue_context.ue_rrc_inactivity_timer = 1; // set rrc inactivity when UE goes into RRC_CONNECTED - ue_context_pP->ue_context.reestablishment_xid = next_xid; - SRB_configList2 = &ue_context_pP->ue_context.SRB_configList2[xid]; + ue_context_pP->ue_context.reestablishment_xid = new_xid; + SRB_configList2 = &ue_context_pP->ue_context.SRB_configList2[old_xid]; // get old configuration of SRB2 if (*SRB_configList2 != NULL) { @@ -1540,7 +1403,7 @@ rrc_gNB_process_RRCConnectionReestablishmentComplete( for (i = 0; (i < (*SRB_configList2)->list.count) && (i < 3); i++) { if ((*SRB_configList2)->list.array[i]->srb_Identity == 2 ) { - LOG_D(NR_RRC, "get SRB2_config from (ue_context_pP->ue_context.SRB_configList2[%d])\n", xid); + LOG_D(NR_RRC, "get SRB2_config from (ue_context_pP->ue_context.SRB_configList2[%d])\n", old_xid); SRB2_config = (*SRB_configList2)->list.array[i]; break; } @@ -1550,12 +1413,12 @@ rrc_gNB_process_RRCConnectionReestablishmentComplete( // SRB2_config = CALLOC(1, sizeof(*SRB2_config)); // SRB2_config->srb_Identity = 2; - SRB_configList2 = &(ue_context_pP->ue_context.SRB_configList2[next_xid]); - DRB_configList2 = &(ue_context_pP->ue_context.DRB_configList2[next_xid]); + SRB_configList2 = &(ue_context_pP->ue_context.SRB_configList2[new_xid]); + DRB_configList2 = &(ue_context_pP->ue_context.DRB_configList2[new_xid]); if (*SRB_configList2) { free(*SRB_configList2); - LOG_D(NR_RRC, "free(ue_context_pP->ue_context.SRB_configList2[%d])\n", next_xid); + LOG_D(NR_RRC, "free(ue_context_pP->ue_context.SRB_configList2[%d])\n", new_xid); } *SRB_configList2 = CALLOC(1, sizeof(**SRB_configList2)); @@ -1566,8 +1429,7 @@ rrc_gNB_process_RRCConnectionReestablishmentComplete( asn1cSeqAdd(&(*SRB_configList2)->list, SRB2_config); LOG_D(NR_RRC, "Add SRB2_config (srb_Identity:%ld) to ue_context_pP->ue_context.SRB_configList\n", SRB2_config->srb_Identity); - LOG_D(NR_RRC, "Add SRB2_config (srb_Identity:%ld) to ue_context_pP->ue_context.SRB_configList2[%d]\n", - SRB2_config->srb_Identity, next_xid); + LOG_D(NR_RRC, "Add SRB2_config (srb_Identity:%ld) to ue_context_pP->ue_context.SRB_configList2[%d]\n", SRB2_config->srb_Identity, new_xid); } else { // SRB configuration list only contains SRB1. LOG_W(NR_RRC,"SRB2 configuration does not exist in SRB configuration list\n"); @@ -1575,7 +1437,7 @@ rrc_gNB_process_RRCConnectionReestablishmentComplete( if (*DRB_configList2) { free(*DRB_configList2); - LOG_D(NR_RRC, "free(ue_context_pP->ue_context.DRB_configList2[%d])\n", next_xid); + LOG_D(NR_RRC, "free(ue_context_pP->ue_context.DRB_configList2[%d])\n", new_xid); } *DRB_configList2 = CALLOC(1, sizeof(**DRB_configList2)); @@ -1691,27 +1553,29 @@ rrc_gNB_process_RRCConnectionReestablishmentComplete( /* TODO parameters yet to process ... */ /* TODO should test if pdu session are Ok before! */ ue_context_pP->ue_context.pduSession[i].status = PDU_SESSION_STATUS_DONE; - ue_context_pP->ue_context.pduSession[i].xid = xid; + ue_context_pP->ue_context.pduSession[i].xid = old_xid; LOG_D(NR_RRC, "setting the status for the default DRB (index %d) to (%d,%s)\n", i, ue_context_pP->ue_context.pduSession[i].status, "PDU_SESSION_STATUS_DONE"); } memset(buffer, 0, sizeof(buffer)); - size = do_RRCReconfiguration(ctxt_pP, buffer, sizeof(buffer), - xid, + size = do_RRCReconfiguration(ctxt_pP, + buffer, + sizeof(buffer), + old_xid, *SRB_configList2, - DRB_configList, - NULL, - NULL, - NULL, - NULL, // MeasObj_list, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL); + DRB_configList, + NULL, + NULL, + NULL, + NULL, // MeasObj_list, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL); LOG_DUMPMSG(NR_RRC,DEBUG_RRC,(char *)buffer,size, "[MSG] RRC Reconfiguration\n"); @@ -2135,21 +1999,13 @@ int nr_rrc_gNB_decode_ccch(protocol_ctxt_t *const ctxt_pP, // SRB1 ue_context_p->ue_context.Srb1.Active = 1; ue_context_p->ue_context.Srb1.Srb_info.Srb_id = Idx; - memcpy(&ue_context_p->ue_context.Srb1.Srb_info.Lchan_desc[0], - &DCCH_LCHAN_DESC, - LCHAN_DESC_SIZE); - memcpy(&ue_context_p->ue_context.Srb1.Srb_info.Lchan_desc[1], - &DCCH_LCHAN_DESC, - LCHAN_DESC_SIZE); + rrc_init_nr_srb_param(&ue_context_p->ue_context.Srb1.Srb_info.Lchan_desc[0]); + rrc_init_nr_srb_param(&ue_context_p->ue_context.Srb1.Srb_info.Lchan_desc[1]); // SRB2: set it to go through SRB1 with id 1 (DCCH) ue_context_p->ue_context.Srb2.Active = 1; ue_context_p->ue_context.Srb2.Srb_info.Srb_id = Idx; - memcpy(&ue_context_p->ue_context.Srb2.Srb_info.Lchan_desc[0], - &DCCH_LCHAN_DESC, - LCHAN_DESC_SIZE); - memcpy(&ue_context_p->ue_context.Srb2.Srb_info.Lchan_desc[1], - &DCCH_LCHAN_DESC, - LCHAN_DESC_SIZE); + rrc_init_nr_srb_param(&ue_context_p->ue_context.Srb2.Srb_info.Lchan_desc[0]); + rrc_init_nr_srb_param(&ue_context_p->ue_context.Srb2.Srb_info.Lchan_desc[1]); rrc_gNB_generate_RRCReestablishment(ctxt_pP, ue_context_p, 0); @@ -2483,7 +2339,6 @@ rrc_gNB_decode_dcch( nr_rrc_pdcp_config_security(ctxt_pP, ue_context_p, 1); rrc_gNB_generate_UECapabilityEnquiry(ctxt_pP, ue_context_p); - //rrc_gNB_generate_defaultRRCReconfiguration(ctxt_pP, ue_context_p); break; case NR_UL_DCCH_MessageType__c1_PR_securityModeFailure: LOG_DUMPMSG(NR_RRC,DEBUG_RRC,(char *)Rx_sdu,sdu_sizeP, @@ -3499,6 +3354,7 @@ static void rrc_CU_process_ue_context_setup_response(MessageDef *msg_p, const ch } if (ue_context_p->ue_context.established_pdu_sessions_flag == 1) { + fill_DRB_configList(&ctxt, ue_context_p); rrc_gNB_generate_dedicatedRRCReconfiguration(&ctxt, ue_context_p, cellGroupConfig); } else { rrc_gNB_generate_defaultRRCReconfiguration(&ctxt, ue_context_p); @@ -3511,10 +3367,31 @@ static void rrc_CU_process_ue_context_setup_response(MessageDef *msg_p, const ch static void rrc_CU_process_ue_context_modification_response(MessageDef *msg_p, const char *msg_name, 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); 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]; struct rrc_gNB_ue_context_s *ue_context_p = rrc_gNB_get_ue_context(rrc, ctxt.rntiMaybeUEid); + + e1ap_bearer_setup_req_t req = {0}; + req.numPDUSessionsMod = ue_context_p->ue_context.nb_of_pdusessions; + req.gNB_cu_cp_ue_id = ue_context_p->ue_context.gNB_ue_ngap_id; + req.rnti = ue_context_p->ue_context.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 + rrc->cucp_cuup.bearer_context_mod(&req, instance); + NR_CellGroupConfig_t *cellGroupConfig = NULL; if(resp->du_to_cu_rrc_information->cellGroupConfig!=NULL){ @@ -3803,6 +3680,98 @@ void nr_rrc_subframe_process(protocol_ctxt_t *const ctxt_pP, const int CC_id) { } } +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"); + gNB_RRC_INST *rrc = RC.nrrrc[0]; //TODO: remove hardcoding of RC index here + MessageDef *msg_p = itti_alloc_new_message(TASK_RRC_GNB, instance, E1AP_SETUP_RESP); + + e1ap_setup_resp_t *resp = &E1AP_SETUP_RESP(msg_p); + resp->transac_id = req->transac_id; + + for (int i=0; i < req->supported_plmns; i++) { + if (rrc->configuration.mcc[i] == req->plmns[i].mcc && + rrc->configuration.mnc[i] == req->plmns[i].mnc) { + LOG_E(NR_RRC, "PLMNs received from CUUP (mcc:%d, mnc:%d) did not match with PLMNs in RRC (mcc:%d, mnc:%d)\n", + req->plmns[i].mcc, req->plmns[i].mnc, rrc->configuration.mcc[i], rrc->configuration.mnc[i]); + return -1; + } + } + + itti_send_msg_to_task(TASK_CUCP_E1, instance, msg_p); + + 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) { + + /*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*/ + + protocol_ctxt_t ctxt = {0}; + PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, 0, GNB_FLAG_YES, ue_context_p->ue_context.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_context_p->ue_context.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; + } + + itti_send_msg_to_task (TASK_CU_F1, ctxt.module_id, message_p); +} + +void rrc_gNB_process_e1_bearer_context_setup_resp(e1ap_bearer_setup_resp_t *resp, instance_t instance) { + // Find the UE context from UE ID and send ITTI message to F1AP to send UE context modification message to DU + + uint16_t ue_initial_id = 0; // Making an invalid UE initial ID + rrc_gNB_ue_context_t *ue_context_p = rrc_gNB_get_ue_context_from_ngap_ids(instance, ue_initial_id, resp->gNB_cu_cp_ue_id); + protocol_ctxt_t ctxt = {0}; + PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, 0, GNB_FLAG_YES, ue_context_p->ue_context.rnti, 0, 0, 0); + + gtpv1u_gnb_create_tunnel_resp_t create_tunnel_resp={0}; + create_tunnel_resp.num_tunnels = resp->numPDUSessions; + for (int i=0; i < resp->numPDUSessions; i++) { + create_tunnel_resp.pdusession_id[i] = resp->pduSession[i].id; + create_tunnel_resp.gnb_NGu_teid[i] = resp->pduSession[i].teId; + memcpy(create_tunnel_resp.gnb_addr.buffer, + &resp->pduSession[i].tlAddress, + sizeof(in_addr_t)); + create_tunnel_resp.gnb_addr.length = sizeof(in_addr_t); // IPv4 byte length + } + + nr_rrc_gNB_process_GTPV1U_CREATE_TUNNEL_RESP(&ctxt, + &create_tunnel_resp); + + ue_context_p->ue_context.setup_pdu_sessions += resp->numPDUSessions; + + // TODO: SV: combine e1ap_bearer_setup_req_t and e1ap_bearer_setup_resp_t and minimize assignments + prepare_and_send_ue_context_modification_f1(ue_context_p, resp); +} + static void print_rrc_meas(FILE *f, const NR_MeasResults_t *measresults) { DevAssert(measresults->measResultServingMOList.list.count >= 1); @@ -4021,6 +3990,15 @@ void *rrc_gnb_task(void *args_p) { rrc_gNB_process_NGAP_UE_CONTEXT_RELEASE_COMMAND(msg_p, msg_name_p, instance); break; + case E1AP_SETUP_REQ: + LOG_I(NR_RRC, "Received E1AP_SETUP_REQ for instance %d\n", (int)instance); + rrc_gNB_process_e1_setup_req(&E1AP_SETUP_REQ(msg_p), instance); + break; + + case E1AP_BEARER_CONTEXT_SETUP_RESP: + LOG_I(NR_RRC, "Received E1AP_BEARER_CONTEXT_SETUP_RESP for instance %d\n", (int)instance); + rrc_gNB_process_e1_bearer_context_setup_resp(&E1AP_BEARER_CONTEXT_SETUP_RESP(msg_p), instance); + case NGAP_PAGING_IND: rrc_gNB_process_PAGING_IND(msg_p, msg_name_p, instance); break; @@ -4063,6 +4041,7 @@ rrc_gNB_generate_SecurityModeCommand( switch (RC.nrrrc[ctxt_pP->module_id]->node_type) { case ngran_gNB_CU: + case ngran_gNB_CUCP: // create an ITTI message memcpy(ue_context_pP->ue_context.Srb1.Srb_info.Tx_buffer.Payload, buffer, size); ue_context_pP->ue_context.Srb1.Srb_info.Tx_buffer.payload_size = size; @@ -4125,6 +4104,7 @@ rrc_gNB_generate_UECapabilityEnquiry( size); switch (RC.nrrrc[ctxt_pP->module_id]->node_type) { case ngran_gNB_CU: + case ngran_gNB_CUCP: nr_rrc_data_req( ctxt_pP, DCCH, @@ -4352,3 +4332,4 @@ void nr_rrc_trigger(protocol_ctxt_t *ctxt, int CC_id, int frame, int subframe) 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); } + diff --git a/openair2/RRC/NR/rrc_gNB_GTPV1U.c b/openair2/RRC/NR/rrc_gNB_GTPV1U.c index ec220172d0..3fef7bc0ef 100644 --- a/openair2/RRC/NR/rrc_gNB_GTPV1U.c +++ b/openair2/RRC/NR/rrc_gNB_GTPV1U.c @@ -49,7 +49,6 @@ rrc_gNB_process_GTPV1U_CREATE_TUNNEL_RESP( const gtpv1u_enb_create_tunnel_resp_t *const create_tunnel_resp_pP, uint8_t *inde_list ) { - rnti_t rnti; int i; struct rrc_gNB_ue_context_s *ue_context_p = NULL; @@ -57,7 +56,6 @@ rrc_gNB_process_GTPV1U_CREATE_TUNNEL_RESP( LOG_D(RRC, PROTOCOL_RRC_CTXT_UE_FMT" RX CREATE_TUNNEL_RESP num tunnels %u \n", PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP), create_tunnel_resp_pP->num_tunnels); - rnti = create_tunnel_resp_pP->rnti; ue_context_p = rrc_gNB_get_ue_context(RC.nrrrc[ctxt_pP->module_id], ctxt_pP->rntiMaybeUEid); for (i = 0; i < create_tunnel_resp_pP->num_tunnels; i++) { @@ -74,7 +72,6 @@ rrc_gNB_process_GTPV1U_CREATE_TUNNEL_RESP( create_tunnel_resp_pP->enb_addr.length); } - (void)rnti; /* avoid gcc warning "set but not used" */ return 0; } else { return -1; @@ -84,10 +81,8 @@ rrc_gNB_process_GTPV1U_CREATE_TUNNEL_RESP( int nr_rrc_gNB_process_GTPV1U_CREATE_TUNNEL_RESP( const protocol_ctxt_t *const ctxt_pP, - const gtpv1u_gnb_create_tunnel_resp_t *const create_tunnel_resp_pP, - uint8_t *inde_list + const gtpv1u_gnb_create_tunnel_resp_t *const create_tunnel_resp_pP ) { - rnti_t rnti; int i; struct rrc_gNB_ue_context_s *ue_context_p = NULL; @@ -95,24 +90,21 @@ nr_rrc_gNB_process_GTPV1U_CREATE_TUNNEL_RESP( LOG_D(NR_RRC, PROTOCOL_NR_RRC_CTXT_UE_FMT" RX CREATE_TUNNEL_RESP num tunnels %u \n", PROTOCOL_NR_RRC_CTXT_UE_ARGS(ctxt_pP), create_tunnel_resp_pP->num_tunnels); - rnti = create_tunnel_resp_pP->ue_id; ue_context_p = rrc_gNB_get_ue_context(RC.nrrrc[ctxt_pP->module_id], ctxt_pP->rntiMaybeUEid); for (i = 0; i < create_tunnel_resp_pP->num_tunnels; i++) { - ue_context_p->ue_context.gnb_gtp_teid[inde_list[i]] = create_tunnel_resp_pP->gnb_NGu_teid[i]; - ue_context_p->ue_context.gnb_gtp_addrs[inde_list[i]] = create_tunnel_resp_pP->gnb_addr; - ue_context_p->ue_context.gnb_gtp_psi[inde_list[i]] = create_tunnel_resp_pP->pdusession_id[i]; - LOG_I(NR_RRC, PROTOCOL_NR_RRC_CTXT_UE_FMT" nr_rrc_gNB_process_GTPV1U_CREATE_TUNNEL_RESP tunnel (%u, %u) bearer UE context index %u, msg index %u, id %u, gtp addr len %d \n", + ue_context_p->ue_context.gnb_gtp_teid[i] = create_tunnel_resp_pP->gnb_NGu_teid[i]; + ue_context_p->ue_context.gnb_gtp_addrs[i] = create_tunnel_resp_pP->gnb_addr; + ue_context_p->ue_context.gnb_gtp_psi[i] = create_tunnel_resp_pP->pdusession_id[i]; + LOG_I(NR_RRC, PROTOCOL_NR_RRC_CTXT_UE_FMT" nr_rrc_gNB_process_GTPV1U_CREATE_TUNNEL_RESP tunnel (%u, %u) bearer UE context index %u, id %u, gtp addr len %d \n", PROTOCOL_NR_RRC_CTXT_UE_ARGS(ctxt_pP), create_tunnel_resp_pP->gnb_NGu_teid[i], - ue_context_p->ue_context.gnb_gtp_teid[inde_list[i]], - inde_list[i], + ue_context_p->ue_context.gnb_gtp_teid[i], i, create_tunnel_resp_pP->pdusession_id[i], create_tunnel_resp_pP->gnb_addr.length); } - (void)rnti; /* avoid gcc warning "set but not used" */ return 0; } else { return -1; diff --git a/openair2/RRC/NR/rrc_gNB_GTPV1U.h b/openair2/RRC/NR/rrc_gNB_GTPV1U.h index 748bd98789..03ef050bcf 100644 --- a/openair2/RRC/NR/rrc_gNB_GTPV1U.h +++ b/openair2/RRC/NR/rrc_gNB_GTPV1U.h @@ -41,8 +41,7 @@ rrc_gNB_process_GTPV1U_CREATE_TUNNEL_RESP( int nr_rrc_gNB_process_GTPV1U_CREATE_TUNNEL_RESP( const protocol_ctxt_t *const ctxt_pP, - const gtpv1u_gnb_create_tunnel_resp_t *const create_tunnel_resp_pP, - uint8_t *inde_list + const gtpv1u_gnb_create_tunnel_resp_t *const create_tunnel_resp_pP ); #endif diff --git a/openair2/RRC/NR/rrc_gNB_NGAP.c b/openair2/RRC/NR/rrc_gNB_NGAP.c index 3eccf0ef37..6f3ebcd06d 100644 --- a/openair2/RRC/NR/rrc_gNB_NGAP.c +++ b/openair2/RRC/NR/rrc_gNB_NGAP.c @@ -57,6 +57,7 @@ #include "NGAP_Cause.h" #include "NGAP_CauseRadioNetwork.h" #include "f1ap_messages_types.h" +#include "openair2/E1AP/e1ap_asnc.h" extern RAN_CONTEXT_t RC; @@ -242,7 +243,7 @@ rrc_gNB_NGAP_get_ue_ids( } //------------------------------------------------------------------------------ -static struct rrc_gNB_ue_context_s * +struct rrc_gNB_ue_context_s * rrc_gNB_get_ue_context_from_ngap_ids( const instance_t instanceP, const uint16_t ue_initial_idP, @@ -474,7 +475,6 @@ rrc_gNB_process_NGAP_INITIAL_CONTEXT_SETUP_REQ( protocol_ctxt_t ctxt={0}; uint8_t pdu_sessions_done = 0; gtpv1u_gnb_create_tunnel_resp_t create_tunnel_resp; - uint8_t inde_list[NR_NB_RB_MAX - 3]= {0}; int ret = 0; ue_initial_id = NGAP_INITIAL_CONTEXT_SETUP_REQ(msg_p).ue_initial_id; @@ -495,12 +495,14 @@ rrc_gNB_process_NGAP_INITIAL_CONTEXT_SETUP_REQ( return (-1); } else { PROTOCOL_CTXT_SET_BY_INSTANCE(&ctxt, instance, GNB_FLAG_YES, ue_context_p->ue_context.rnti, 0, 0); + gNB_RRC_INST *rrc = RC.nrrrc[ctxt.module_id]; ue_context_p->ue_context.gNB_ue_ngap_id = NGAP_INITIAL_CONTEXT_SETUP_REQ (msg_p).gNB_ue_ngap_id; ue_context_p->ue_context.amf_ue_ngap_id = NGAP_INITIAL_CONTEXT_SETUP_REQ (msg_p).amf_ue_ngap_id; ue_context_p->ue_context.nas_pdu_flag = NGAP_INITIAL_CONTEXT_SETUP_REQ (msg_p).nas_pdu_flag; uint8_t nb_pdusessions_tosetup = NGAP_INITIAL_CONTEXT_SETUP_REQ (msg_p).nb_of_pdusessions; if (nb_pdusessions_tosetup != 0) { + AssertFatal(rrc->node_type != ngran_gNB_CUCP, "PDU sessions in Initial context setup request not handled by E1 yet\n"); gtpv1u_gnb_create_tunnel_req_t create_tunnel_req={0}; for (int i = 0; i < NR_NB_RB_MAX - 3; i++) { if(ue_context_p->ue_context.pduSession[i].status >= PDU_SESSION_STATUS_DONE) @@ -520,7 +522,6 @@ rrc_gNB_process_NGAP_INITIAL_CONTEXT_SETUP_REQ( i, create_tunnel_req.outgoing_teid[pdu_sessions_done], create_tunnel_req.pdusession_id[pdu_sessions_done]); - inde_list[pdu_sessions_done] = i; pdu_sessions_done++; if(pdu_sessions_done >= nb_pdusessions_tosetup) { @@ -549,9 +550,8 @@ rrc_gNB_process_NGAP_INITIAL_CONTEXT_SETUP_REQ( nr_rrc_gNB_process_GTPV1U_CREATE_TUNNEL_RESP( &ctxt, - &create_tunnel_resp, - &inde_list[0]); - ue_context_p->ue_context.setup_pdu_sessions += nb_pdusessions_tosetup; + &create_tunnel_resp); + ue_context_p->ue_context.setup_pdu_sessions += NGAP_INITIAL_CONTEXT_SETUP_REQ (msg_p).nb_of_pdusessions; ue_context_p->ue_context.established_pdu_sessions_flag = 1; } @@ -804,6 +804,7 @@ rrc_gNB_process_NGAP_DOWNLINK_NAS( */ switch (RC.nrrrc[ctxt.module_id]->node_type) { case ngran_gNB_CU: + case ngran_gNB_CUCP: /* Transfer data to PDCP */ nr_rrc_data_req ( &ctxt, @@ -945,7 +946,7 @@ rrc_gNB_send_NGAP_PDUSESSION_SETUP_RESP( } //------------------------------------------------------------------------------ -int +void rrc_gNB_process_NGAP_PDUSESSION_SETUP_REQ( MessageDef *msg_p, const char *msg_name, @@ -953,21 +954,20 @@ rrc_gNB_process_NGAP_PDUSESSION_SETUP_REQ( ) //------------------------------------------------------------------------------ { + gNB_RRC_INST *rrc; uint16_t ue_initial_id; uint32_t gNB_ue_ngap_id; rrc_gNB_ue_context_t *ue_context_p = NULL; protocol_ctxt_t ctxt={0}; - gtpv1u_gnb_create_tunnel_req_t create_tunnel_req={0}; - gtpv1u_gnb_create_tunnel_resp_t create_tunnel_resp={0}; - uint8_t pdu_sessions_done; - uint8_t inde_list[NR_NB_RB_MAX - 3]= {0}; - int ret = 0; - ue_initial_id = NGAP_PDUSESSION_SETUP_REQ(msg_p).ue_initial_id; - gNB_ue_ngap_id = NGAP_PDUSESSION_SETUP_REQ(msg_p).gNB_ue_ngap_id; + ngap_pdusession_setup_req_t* msg=&NGAP_PDUSESSION_SETUP_REQ(msg_p); + ue_initial_id = msg->ue_initial_id; + gNB_ue_ngap_id = msg->gNB_ue_ngap_id; ue_context_p = rrc_gNB_get_ue_context_from_ngap_ids(instance, ue_initial_id, gNB_ue_ngap_id); + PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, 0, GNB_FLAG_YES, ue_context_p->ue_context.rnti, 0, 0, 0); + rrc = RC.nrrrc[ctxt.module_id]; LOG_I(NR_RRC, "[gNB %ld] Received %s: ue_initial_id %d, gNB_ue_ngap_id %u \n", - instance, msg_name, ue_initial_id, gNB_ue_ngap_id); + instance, msg_name, ue_initial_id, gNB_ue_ngap_id); if (ue_context_p == NULL) { MessageDef *msg_fail_p = NULL; @@ -976,110 +976,102 @@ rrc_gNB_process_NGAP_PDUSESSION_SETUP_REQ( NGAP_PDUSESSION_SETUP_REQ(msg_fail_p).gNB_ue_ngap_id = gNB_ue_ngap_id; // TODO add failure cause when defined! itti_send_msg_to_task (TASK_NGAP, instance, msg_fail_p); - return (-1); - } else { - memset(&create_tunnel_req, 0, sizeof(gtpv1u_gnb_create_tunnel_req_t)); - uint8_t nb_pdusessions_tosetup = NGAP_PDUSESSION_SETUP_REQ(msg_p).nb_pdusessions_tosetup; - pdu_sessions_done = 0; + return ; + } + + ue_context_p->ue_context.nb_of_pdusessions = msg->nb_pdusessions_tosetup; + ue_context_p->ue_context.gNB_ue_ngap_id = msg->gNB_ue_ngap_id; + ue_context_p->ue_context.amf_ue_ngap_id = msg->amf_ue_ngap_id; - PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, 0, GNB_FLAG_YES, ue_context_p->ue_context.rnti, 0, 0, 0); - for (int i = 0; i < NR_NB_RB_MAX - 3; i++) { - if(ue_context_p->ue_context.pduSession[i].status >= PDU_SESSION_STATUS_DONE) - continue; - ue_context_p->ue_context.pduSession[i].status = PDU_SESSION_STATUS_NEW; - ue_context_p->ue_context.pduSession[i].param = NGAP_PDUSESSION_SETUP_REQ(msg_p).pdusession_setup_params[pdu_sessions_done]; - create_tunnel_req.pdusession_id[pdu_sessions_done] = NGAP_PDUSESSION_SETUP_REQ(msg_p).pdusession_setup_params[pdu_sessions_done].pdusession_id; - create_tunnel_req.incoming_rb_id[pdu_sessions_done]= i+1; - create_tunnel_req.outgoing_teid[pdu_sessions_done] = NGAP_PDUSESSION_SETUP_REQ(msg_p).pdusession_setup_params[pdu_sessions_done].gtp_teid; - create_tunnel_req.outgoing_qfi[pdu_sessions_done] = NGAP_PDUSESSION_SETUP_REQ(msg_p).pdusession_setup_params[pdu_sessions_done].qos[0].qfi; - memcpy(create_tunnel_req.dst_addr[pdu_sessions_done].buffer, - NGAP_PDUSESSION_SETUP_REQ(msg_p).pdusession_setup_params[pdu_sessions_done].upf_addr.buffer, - sizeof(uint8_t)*20); - create_tunnel_req.dst_addr[pdu_sessions_done].length = NGAP_PDUSESSION_SETUP_REQ(msg_p).pdusession_setup_params[pdu_sessions_done].upf_addr.length; - LOG_I(NR_RRC,"NGAP PDUSESSION SETUP REQ: local index %d teid %u, pdusession id %d \n", - i, - create_tunnel_req.outgoing_teid[pdu_sessions_done], - create_tunnel_req.pdusession_id[pdu_sessions_done]); - inde_list[pdu_sessions_done] = i; - pdu_sessions_done++; + /* Configurations are referred from rrc_gNB_generate_dedicatedRRCReconfiguration() and + rrc_gNB_process_RRCReconfigurationComplete() - if(pdu_sessions_done >= nb_pdusessions_tosetup) { - break; + At CU-CP we configure the E1 bearer context setup parameters (PDU sessions, DRBs and + QoS flows) same as in these functions. At CU-UP we create PDU Sessions and allocate DRBs. + */ + e1ap_bearer_setup_req_t bearer_req; + + bearer_req.gNB_cu_cp_ue_id = gNB_ue_ngap_id; + bearer_req.rnti = ue_context_p->ue_context.rnti; + bearer_req.cipheringAlgorithm = ue_context_p->ue_context.ciphering_algorithm; + memcpy(bearer_req.encryptionKey, ue_context_p->ue_context.kgnb, sizeof(ue_context_p->ue_context.kgnb)); + bearer_req.integrityProtectionAlgorithm = ue_context_p->ue_context.integrity_algorithm; + memcpy(bearer_req.integrityProtectionKey, ue_context_p->ue_context.kgnb, sizeof(ue_context_p->ue_context.kgnb)); + bearer_req.ueDlAggMaxBitRate = msg->ueAggMaxBitRateDownlink; + + bearer_req.numPDUSessions = msg->nb_pdusessions_tosetup; + + for (int i=0; i < bearer_req.numPDUSessions; i++) { + ue_context_p->ue_context.pduSession[i].param = msg->pdusession_setup_params[i]; + + pdu_session_to_setup_t *pdu = bearer_req.pduSession + i; + pdu->sessionId = msg->pdusession_setup_params[i].pdusession_id; + pdu->sessionType = msg->pdusession_setup_params[i].upf_addr.pdu_session_type; + pdu->sst = msg->allowed_nssai[i].sST; + if (rrc->security.do_drb_integrity) { + pdu->integrityProtectionIndication = E1AP_IntegrityProtectionIndication_required; + } else { + pdu->integrityProtectionIndication = E1AP_IntegrityProtectionIndication_not_needed; + } + + if (rrc->security.do_drb_ciphering) { + pdu->confidentialityProtectionIndication = E1AP_ConfidentialityProtectionIndication_required; + } else { + pdu->confidentialityProtectionIndication = E1AP_ConfidentialityProtectionIndication_not_needed; + } + pdu->teId = msg->pdusession_setup_params[i].gtp_teid; + memcpy(&pdu->tlAddress, + msg->pdusession_setup_params[i].upf_addr.buffer, + sizeof(uint8_t)*4); + + ue_context_p->ue_context.pduSession[i].param = msg->pdusession_setup_params[i]; + ue_context_p->ue_context.nb_of_pdusessions = msg->nb_pdusessions_tosetup; + ue_context_p->ue_context.gNB_ue_ngap_id = msg->gNB_ue_ngap_id; + ue_context_p->ue_context.amf_ue_ngap_id = msg->amf_ue_ngap_id; + pdu->numDRB2Setup = 1; // One DRB per PDU Session. TODO: Remove hardcoding + ue_context_p->ue_context.setup_pdu_sessions += pdu->numDRB2Setup; + for (int j=0; j < pdu->numDRB2Setup; j++) { + DRB_nGRAN_to_setup_t *drb = pdu->DRBnGRanList + j; + + drb->id = i + j + 1; + + drb->defaultDRB = E1AP_DefaultDRB_true; + + drb->sDAP_Header_UL = !(rrc->configuration.enable_sdap); + drb->sDAP_Header_DL = !(rrc->configuration.enable_sdap); + + drb->pDCP_SN_Size_UL = E1AP_PDCP_SN_Size_s_18; + drb->pDCP_SN_Size_DL = E1AP_PDCP_SN_Size_s_18; + + drb->discardTimer = E1AP_DiscardTimer_infinity; + drb->reorderingTimer = E1AP_T_Reordering_ms0; + + drb->rLC_Mode = E1AP_RLC_Mode_rlc_am; + + drb->numCellGroups = 1; // assume one cell group associated with a DRB + + for (int k=0; k < drb->numCellGroups; k++) { + cell_group_t *cellGroup = drb->cellGroupList + k; + cellGroup->id = 0; // MCG + } + + drb->numQosFlow2Setup = msg->pdusession_setup_params[i].nb_qos; + for (int k=0; k < drb->numQosFlow2Setup; k++) { + qos_flow_to_setup_t *qos = drb->qosFlows + k; + + qos->id = msg->pdusession_setup_params[i].qos[k].qfi; + qos->fiveQI = msg->pdusession_setup_params[i].qos[k].fiveQI; + qos->fiveQI_type = msg->pdusession_setup_params[i].qos[k].fiveQI_type; + + qos->qoSPriorityLevel = msg->pdusession_setup_params[i].qos[k].allocation_retention_priority.priority_level; + qos->pre_emptionCapability = msg->pdusession_setup_params[i].qos[k].allocation_retention_priority.pre_emp_capability; + qos->pre_emptionVulnerability = msg->pdusession_setup_params[i].qos[k].allocation_retention_priority.pre_emp_vulnerability; } } - - ue_context_p->ue_context.nb_of_pdusessions = NGAP_PDUSESSION_SETUP_REQ(msg_p).nb_pdusessions_tosetup; - ue_context_p->ue_context.gNB_ue_ngap_id = NGAP_PDUSESSION_SETUP_REQ(msg_p).gNB_ue_ngap_id; - ue_context_p->ue_context.amf_ue_ngap_id = NGAP_PDUSESSION_SETUP_REQ(msg_p).amf_ue_ngap_id; - create_tunnel_req.ue_id = ue_context_p->ue_context.rnti; - create_tunnel_req.num_tunnels = pdu_sessions_done; - - ret = gtpv1u_create_ngu_tunnel( - instance, - &create_tunnel_req, - &create_tunnel_resp); - if (ret != 0) { - LOG_E(NR_RRC,"rrc_gNB_process_NGAP_PDUSESSION_SETUP_REQ : gtpv1u_create_ngu_tunnel failed,start to release UE %x\n",ue_context_p->ue_context.rnti); - ue_context_p->ue_context.ue_release_timer_ng = 1; - ue_context_p->ue_context.ue_release_timer_thres_ng = 100; - ue_context_p->ue_context.ue_release_timer = 0; - ue_context_p->ue_context.ue_reestablishment_timer = 0; - ue_context_p->ue_context.ul_failure_timer = 20000; // set ul_failure to 20000 for triggering rrc_eNB_send_S1AP_UE_CONTEXT_RELEASE_REQ - // rrc_gNB_free_UE(ctxt.module_id,ue_context_p); - ue_context_p->ue_context.ul_failure_timer = 0; - return (0); - } - nr_rrc_gNB_process_GTPV1U_CREATE_TUNNEL_RESP( - &ctxt, - &create_tunnel_resp, - &inde_list[0]); - ue_context_p->ue_context.setup_pdu_sessions += nb_pdusessions_tosetup; - - // TEST - // ue_context_p->ue_context.pdusession[0].status = PDU_SESSION_STATUS_DONE; - // rrc_gNB_send_NGAP_PDUSESSION_SETUP_RESP(&ctxt, ue_context_p, 0); - if(!NODE_IS_CU(RC.nrrrc[ctxt.module_id]->node_type)){ - rrc_gNB_generate_dedicatedRRCReconfiguration(&ctxt, ue_context_p, NULL); - } - else{ - /*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*/ - 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_context_p->ue_context.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*/ - gtpv1u_gnb_create_tunnel_req_t create_tunnel_req; - memset(&create_tunnel_req, 0, sizeof(gtpv1u_gnb_create_tunnel_req_t)); - req->drbs_to_be_setup = malloc(1*sizeof(f1ap_drb_to_be_setup_t)); - req->drbs_to_be_setup_length = 1; - f1ap_drb_to_be_setup_t *DRBs=req->drbs_to_be_setup; - LOG_D(RRC, "Length of DRB list:%d \n", req->drbs_to_be_setup_length); - DRBs[0].drb_id = 1; - DRBs[0].rlc_mode = RLC_MODE_AM; - DRBs[0].up_ul_tnl[0].tl_address = inet_addr(RC.nrrrc[ctxt.module_id]->eth_params_s.my_addr); - DRBs[0].up_ul_tnl[0].port=RC.nrrrc[ctxt.module_id]->eth_params_s.my_portd; - DRBs[0].up_ul_tnl_length = 1; - DRBs[0].up_dl_tnl[0].tl_address = inet_addr(RC.nrrrc[ctxt.module_id]->eth_params_s.remote_addr); - DRBs[0].up_dl_tnl[0].port=RC.nrrrc[ctxt.module_id]->eth_params_s.remote_portd; - DRBs[0].up_dl_tnl_length = 1; - - itti_send_msg_to_task (TASK_CU_F1, ctxt.module_id, message_p); - } - return(0); } + + rrc->cucp_cuup.bearer_context_setup(&bearer_req, instance); + return; } //------------------------------------------------------------------------------ diff --git a/openair2/RRC/NR/rrc_gNB_NGAP.h b/openair2/RRC/NR/rrc_gNB_NGAP.h index a03e4df41f..6c8a861f03 100644 --- a/openair2/RRC/NR/rrc_gNB_NGAP.h +++ b/openair2/RRC/NR/rrc_gNB_NGAP.h @@ -101,7 +101,7 @@ rrc_gNB_send_NGAP_PDUSESSION_SETUP_RESP( uint8_t xid ); -int +void rrc_gNB_process_NGAP_PDUSESSION_SETUP_REQ( MessageDef *msg_p, const char *msg_name, @@ -189,6 +189,13 @@ nr_rrc_pdcp_config_security( const uint8_t send_security_mode_command ); +struct rrc_gNB_ue_context_s * +rrc_gNB_get_ue_context_from_ngap_ids( + const instance_t instanceP, + const uint16_t ue_initial_idP, + const uint32_t gNB_ue_ngap_idP +); + int rrc_gNB_process_PAGING_IND( MessageDef *msg_p, diff --git a/openair2/RRC/NR/rrc_gNB_radio_bearers.c b/openair2/RRC/NR/rrc_gNB_radio_bearers.c index 9c3b6aada0..ff8149b83f 100644 --- a/openair2/RRC/NR/rrc_gNB_radio_bearers.c +++ b/openair2/RRC/NR/rrc_gNB_radio_bearers.c @@ -22,32 +22,6 @@ #include "rrc_gNB_radio_bearers.h" #include "oai_asn1.h" -NR_SRB_ToAddMod_t *generateSRB2() { - NR_SRB_ToAddMod_t *SRB2_config = NULL; - - SRB2_config = CALLOC(1, sizeof(*SRB2_config)); - SRB2_config->srb_Identity = 2; - - return SRB2_config; -} - -NR_SRB_ToAddModList_t **generateSRB2_confList(gNB_RRC_UE_t *ue, - NR_SRB_ToAddModList_t *SRB_configList, - uint8_t xid) { - NR_SRB_ToAddModList_t **SRB_configList2 = NULL; - - SRB_configList2 = &ue->SRB_configList2[xid]; - if (*SRB_configList2 == NULL) { - *SRB_configList2 = CALLOC(1, sizeof(**SRB_configList2)); - memset(*SRB_configList2, 0, sizeof(**SRB_configList2)); - NR_SRB_ToAddMod_t *SRB2_config = generateSRB2(); - asn1cSeqAdd(&(*SRB_configList2)->list, SRB2_config); - asn1cSeqAdd(&SRB_configList->list, SRB2_config); - } - - return SRB_configList2; -} - NR_DRB_ToAddMod_t *generateDRB(gNB_RRC_UE_t *ue, uint8_t drb_id, const pdu_session_param_t *pduSession, diff --git a/openair2/RRC/NR/rrc_gNB_radio_bearers.h b/openair2/RRC/NR/rrc_gNB_radio_bearers.h index a686fed767..86ab093ced 100644 --- a/openair2/RRC/NR/rrc_gNB_radio_bearers.h +++ b/openair2/RRC/NR/rrc_gNB_radio_bearers.h @@ -35,10 +35,6 @@ #define GBR_FLOW (1) #define NONGBR_FLOW (0) -NR_SRB_ToAddMod_t *generateSRB2(void); -NR_SRB_ToAddModList_t **generateSRB2_confList(gNB_RRC_UE_t *ue, - NR_SRB_ToAddModList_t *SRB_configList, - uint8_t xid); NR_DRB_ToAddMod_t *generateDRB(gNB_RRC_UE_t *rrc_ue, uint8_t drb_id, const pdu_session_param_t *pduSession, diff --git a/openair2/SDAP/nr_sdap/nr_sdap_entity.c b/openair2/SDAP/nr_sdap/nr_sdap_entity.c index 09e80feccf..e9a22eb578 100644 --- a/openair2/SDAP/nr_sdap/nr_sdap_entity.c +++ b/openair2/SDAP/nr_sdap/nr_sdap_entity.c @@ -35,6 +35,8 @@ typedef struct { static nr_sdap_entity_info sdap_info; +instance_t *N3GTPUInst = NULL; + nr_pdcp_ue_manager_t *nr_pdcp_sdap_get_ue_manager(void); void nr_pdcp_submit_sdap_ctrl_pdu(ue_id_t ue_id, rb_id_t sdap_ctrl_pdu_drb, nr_sdap_ul_hdr_t ctrl_pdu) @@ -216,7 +218,8 @@ static void nr_sdap_rx_entity(nr_sdap_entity_t *entity, req->ue_id = ue_id; req->bearer_id = pdusession_id; LOG_D(SDAP, "%s() sending message to gtp size %d\n", __func__, size-offset); - itti_send_msg_to_task(TASK_GTPV1_U, INSTANCE_DEFAULT, message_p); + // very very dirty hack gloabl var N3GTPUInst + itti_send_msg_to_task(TASK_GTPV1_U, *N3GTPUInst, message_p); } else { //nrUE /* * TS 37.324 5.2 Data transfer diff --git a/openair2/SDAP/nr_sdap/nr_sdap_entity.h b/openair2/SDAP/nr_sdap/nr_sdap_entity.h index e8ed236fd1..4b5303a5b6 100644 --- a/openair2/SDAP/nr_sdap/nr_sdap_entity.h +++ b/openair2/SDAP/nr_sdap/nr_sdap_entity.h @@ -51,6 +51,9 @@ * the GTP-U Extension Header. Inside the DL PDU SESSION INFORMATION frame. * TS 38.415 Fig. 5.5.2.1-1 */ + +extern instance_t *N3GTPUInst; + typedef struct nr_sdap_dl_hdr_s { uint8_t QFI:6; uint8_t RQI:1; diff --git a/openair3/MME_APP/mme_app.c b/openair3/MME_APP/mme_app.c index 2c1d524c15..43a5df2ac8 100644 --- a/openair3/MME_APP/mme_app.c +++ b/openair3/MME_APP/mme_app.c @@ -40,7 +40,8 @@ # include "intertask_interface.h" # include "s1ap_eNB.h" -#include "sctp_eNB_task.h" +# include "sctp_eNB_task.h" +# include "openair3/ocp-gtpu/gtp_itf.h" # include "x2ap_eNB.h" # include "x2ap_messages_types.h" diff --git a/openair3/NGAP/ngap_gNB_handlers.c b/openair3/NGAP/ngap_gNB_handlers.c index ab2503f1d5..47f4b8445d 100644 --- a/openair3/NGAP/ngap_gNB_handlers.c +++ b/openair3/NGAP/ngap_gNB_handlers.c @@ -48,10 +48,7 @@ #include "conversions.h" #include "NGAP_NonDynamic5QIDescriptor.h" -static -int ngap_gNB_handle_ng_setup_response(uint32_t assoc_id, - uint32_t stream, - NGAP_NGAP_PDU_t *pdu); +static int ngap_gNB_handle_ng_setup_response(uint32_t ssoc_id, uint32_t stream, NGAP_NGAP_PDU_t *pdu); static int ngap_gNB_handle_ng_setup_failure(uint32_t assoc_id, uint32_t stream, @@ -188,8 +185,7 @@ void ngap_handle_ng_setup_message(ngap_gNB_amf_data_t *amf_desc_p, int sctp_shut /* If there are no more associated AMF, inform gNB app */ if (amf_desc_p->ngap_gNB_instance->ngap_amf_associated_nb == 0) { - MessageDef *message_p; - message_p = itti_alloc_new_message(TASK_NGAP, 0, NGAP_DEREGISTERED_GNB_IND); + MessageDef *message_p = itti_alloc_new_message(TASK_NGAP, 0, NGAP_DEREGISTERED_GNB_IND); NGAP_DEREGISTERED_GNB_IND(message_p).nb_amf = 0; itti_send_msg_to_task(TASK_GNB_APP, amf_desc_p->ngap_gNB_instance->instance, message_p); } @@ -206,8 +202,7 @@ void ngap_handle_ng_setup_message(ngap_gNB_amf_data_t *amf_desc_p, int sctp_shut /* If there are no more pending messages, inform gNB app */ if (amf_desc_p->ngap_gNB_instance->ngap_amf_pending_nb == 0) { - MessageDef *message_p; - message_p = itti_alloc_new_message(TASK_NGAP, 0, NGAP_REGISTER_GNB_CNF); + MessageDef *message_p = itti_alloc_new_message(TASK_NGAP, 0, NGAP_REGISTER_GNB_CNF); NGAP_REGISTER_GNB_CNF(message_p).nb_amf = amf_desc_p->ngap_gNB_instance->ngap_amf_associated_nb; itti_send_msg_to_task(TASK_GNB_APP, amf_desc_p->ngap_gNB_instance->instance, message_p); } @@ -838,7 +833,6 @@ int ngap_gNB_handle_initial_context_request(uint32_t assoc_id, int i; ngap_gNB_amf_data_t *amf_desc_p = NULL; ngap_gNB_ue_context_t *ue_desc_p = NULL; - MessageDef *message_p = NULL; NGAP_InitialContextSetupRequest_t *container; NGAP_InitialContextSetupRequestIEs_t *ie; NGAP_RAN_UE_NGAP_ID_t ran_ue_ngap_id; @@ -890,20 +884,21 @@ int ngap_gNB_handle_initial_context_request(uint32_t assoc_id, ue_desc_p->rx_stream = stream; ue_desc_p->amf_ue_ngap_id = amf_ue_ngap_id; - message_p = itti_alloc_new_message(TASK_NGAP, 0, NGAP_INITIAL_CONTEXT_SETUP_REQ); - NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).ue_initial_id = ue_desc_p->ue_initial_id; + MessageDef *message_p = itti_alloc_new_message(TASK_NGAP, 0, NGAP_INITIAL_CONTEXT_SETUP_REQ); + ngap_initial_context_setup_req_t * msg=&NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p); + msg->ue_initial_id = ue_desc_p->ue_initial_id; ue_desc_p->ue_initial_id = 0; - NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).gNB_ue_ngap_id = ue_desc_p->gNB_ue_ngap_id; - NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).amf_ue_ngap_id = ue_desc_p->amf_ue_ngap_id; + msg->gNB_ue_ngap_id = ue_desc_p->gNB_ue_ngap_id; + msg->amf_ue_ngap_id = ue_desc_p->amf_ue_ngap_id; /* id-UEAggregateMaximumBitRate */ NGAP_FIND_PROTOCOLIE_BY_ID(NGAP_InitialContextSetupRequestIEs_t, ie, container, NGAP_ProtocolIE_ID_id_UEAggregateMaximumBitRate, false); if (ie != NULL) { /* checked by macro but cppcheck doesn't see it */ asn_INTEGER2ulong(&(ie->value.choice.UEAggregateMaximumBitRate.uEAggregateMaximumBitRateUL), - &(NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).ue_ambr.br_ul)); + &(msg->ue_ambr.br_ul)); asn_INTEGER2ulong(&(ie->value.choice.UEAggregateMaximumBitRate.uEAggregateMaximumBitRateDL), - &(NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).ue_ambr.br_dl)); + &(msg->ue_ambr.br_dl)); } else { NGAP_ERROR("could not found NGAP_ProtocolIE_ID_id_UEAggregateMaximumBitRate\n"); } @@ -914,12 +909,12 @@ int ngap_gNB_handle_initial_context_request(uint32_t assoc_id, NGAP_ProtocolIE_ID_id_GUAMI, true); if (ie != NULL) { /* checked by macro but cppcheck doesn't see it */ - TBCD_TO_MCC_MNC(&ie->value.choice.GUAMI.pLMNIdentity, NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).guami.mcc, - NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).guami.mnc, NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).guami.mnc_len); + TBCD_TO_MCC_MNC(&ie->value.choice.GUAMI.pLMNIdentity, msg->guami.mcc, + msg->guami.mnc, msg->guami.mnc_len); - OCTET_STRING_TO_INT8(&ie->value.choice.GUAMI.aMFRegionID, NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).guami.amf_region_id); - OCTET_STRING_TO_INT16(&ie->value.choice.GUAMI.aMFSetID, NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).guami.amf_set_id); - OCTET_STRING_TO_INT8(&ie->value.choice.GUAMI.aMFPointer, NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).guami.amf_pointer); + OCTET_STRING_TO_INT8(&ie->value.choice.GUAMI.aMFRegionID, msg->guami.amf_region_id); + OCTET_STRING_TO_INT16(&ie->value.choice.GUAMI.aMFSetID, msg->guami.amf_set_id); + OCTET_STRING_TO_INT8(&ie->value.choice.GUAMI.aMFPointer, msg->guami.amf_pointer); } else {/* ie != NULL */ return -1; } @@ -928,7 +923,7 @@ int ngap_gNB_handle_initial_context_request(uint32_t assoc_id, NGAP_ProtocolIE_ID_id_PDUSessionResourceSetupListCxtReq, false); if (ie != NULL) { /* checked by macro but cppcheck doesn't see it */ - NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).nb_of_pdusessions = + msg->nb_of_pdusessions = ie->value.choice.PDUSessionResourceSetupListCxtReq.list.count; for (i = 0; i < ie->value.choice.PDUSessionResourceSetupListCxtReq.list.count; i++) { @@ -938,19 +933,19 @@ int ngap_gNB_handle_initial_context_request(uint32_t assoc_id, NGAP_PDUSessionResourceSetupRequestTransferIEs_t *pdusessionTransfer_ies = NULL; item_p = (NGAP_PDUSessionResourceSetupItemCxtReq_t *)ie->value.choice.PDUSessionResourceSetupListCxtReq.list.array[i]; - NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).pdusession_param[i].pdusession_id = item_p->pDUSessionID; + msg->pdusession_param[i].pdusession_id = item_p->pDUSessionID; if (item_p->nAS_PDU != NULL) { /* Only copy NAS pdu if present */ - NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).pdusession_param[i].nas_pdu.length = item_p->nAS_PDU->size; - NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).pdusession_param[i].nas_pdu.buffer = + msg->pdusession_param[i].nas_pdu.length = item_p->nAS_PDU->size; + msg->pdusession_param[i].nas_pdu.buffer = malloc(sizeof(uint8_t) * item_p->nAS_PDU->size); - memcpy(NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).pdusession_param[i].nas_pdu.buffer, + memcpy(msg->pdusession_param[i].nas_pdu.buffer, item_p->nAS_PDU->buf, item_p->nAS_PDU->size); NGAP_DEBUG("Received NAS message with the PDUSESSION setup procedure\n"); } else { - NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).pdusession_param[i].nas_pdu.length = 0; - NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).pdusession_param[i].nas_pdu.buffer = NULL; + msg->pdusession_param[i].nas_pdu.length = 0; + msg->pdusession_param[i].nas_pdu.buffer = NULL; } @@ -979,14 +974,14 @@ int ngap_gNB_handle_initial_context_request(uint32_t assoc_id, gTPTunnel_p = pdusessionTransfer_ies->value.choice.UPTransportLayerInformation.choice.gTPTunnel; /* Set the transport layer address */ - memcpy(NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).pdusession_param[i].upf_addr.buffer, + memcpy(msg->pdusession_param[i].upf_addr.buffer, gTPTunnel_p->transportLayerAddress.buf, gTPTunnel_p->transportLayerAddress.size); - NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).pdusession_param[i].upf_addr.length = + msg->pdusession_param[i].upf_addr.length = gTPTunnel_p->transportLayerAddress.size * 8 - gTPTunnel_p->transportLayerAddress.bits_unused; /* GTP tunnel endpoint ID */ - OCTET_STRING_TO_INT32(&gTPTunnel_p->gTP_TEID, NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).pdusession_param[i].gtp_teid); + OCTET_STRING_TO_INT32(&gTPTunnel_p->gTP_TEID, msg->pdusession_param[i].gtp_teid); } break; @@ -1001,7 +996,7 @@ int ngap_gNB_handle_initial_context_request(uint32_t assoc_id, /* mandatory PDUSessionType */ case NGAP_ProtocolIE_ID_id_PDUSessionType: - NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).pdusession_param[i].upf_addr.pdu_session_type = (uint8_t)pdusessionTransfer_ies->value.choice.PDUSessionType; + msg->pdusession_param[i].upf_addr.pdu_session_type = (uint8_t)pdusessionTransfer_ies->value.choice.PDUSessionType; break; /* optional SecurityIndication */ @@ -1021,25 +1016,25 @@ int ngap_gNB_handle_initial_context_request(uint32_t assoc_id, DevAssert(pdusessionTransfer_ies->value.choice.QosFlowSetupRequestList.list.count > 0); DevAssert(pdusessionTransfer_ies->value.choice.QosFlowSetupRequestList.list.count <= NGAP_maxnoofQosFlows); - NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).pdusession_param[i].nb_qos = pdusessionTransfer_ies->value.choice.QosFlowSetupRequestList.list.count; + msg->pdusession_param[i].nb_qos = pdusessionTransfer_ies->value.choice.QosFlowSetupRequestList.list.count; for(int qosIdx = 0; qosIdx < pdusessionTransfer_ies->value.choice.QosFlowSetupRequestList.list.count; qosIdx++) { qosFlowItem_p = pdusessionTransfer_ies->value.choice.QosFlowSetupRequestList.list.array[qosIdx]; /* Set the QOS informations */ - NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).pdusession_param[i].qos[qosIdx].qfi = (uint8_t)qosFlowItem_p->qosFlowIdentifier; + msg->pdusession_param[i].qos[qosIdx].qfi = (uint8_t)qosFlowItem_p->qosFlowIdentifier; if(qosFlowItem_p->qosFlowLevelQosParameters.qosCharacteristics.present == NGAP_QosCharacteristics_PR_nonDynamic5QI){ if(qosFlowItem_p->qosFlowLevelQosParameters.qosCharacteristics.choice.nonDynamic5QI != NULL){ - NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).pdusession_param[i].qos[qosIdx].fiveQI = + msg->pdusession_param[i].qos[qosIdx].fiveQI = (uint64_t)qosFlowItem_p->qosFlowLevelQosParameters.qosCharacteristics.choice.nonDynamic5QI->fiveQI; } } - NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).pdusession_param[i].qos[qosIdx].allocation_retention_priority.priority_level = + msg->pdusession_param[i].qos[qosIdx].allocation_retention_priority.priority_level = qosFlowItem_p->qosFlowLevelQosParameters.allocationAndRetentionPriority.priorityLevelARP; - NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).pdusession_param[i].qos[qosIdx].allocation_retention_priority.pre_emp_capability = + msg->pdusession_param[i].qos[qosIdx].allocation_retention_priority.pre_emp_capability = qosFlowItem_p->qosFlowLevelQosParameters.allocationAndRetentionPriority.pre_emptionCapability; - NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).pdusession_param[i].qos[qosIdx].allocation_retention_priority.pre_emp_vulnerability = + msg->pdusession_param[i].qos[qosIdx].allocation_retention_priority.pre_emp_vulnerability = qosFlowItem_p->qosFlowLevelQosParameters.allocationAndRetentionPriority.pre_emptionVulnerability; } } @@ -1051,14 +1046,14 @@ int ngap_gNB_handle_initial_context_request(uint32_t assoc_id, break; default: - NGAP_ERROR("could not found protocolIEs id %ld\n", pdusessionTransfer_ies->id); + NGAP_ERROR("Not found protocolIEs id %ld\n", pdusessionTransfer_ies->id); return -1; } } } /* for i... */ } else {/* ie != NULL */ - NGAP_ERROR("could not found NGAP_ProtocolIE_ID_id_PDUSessionResourceSetupListCxtReq\n"); + NGAP_ERROR("Not found NGAP_ProtocolIE_ID_id_PDUSessionResourceSetupListCxtReq\n"); } /* id-AllowedNSSAI */ @@ -1075,35 +1070,35 @@ int ngap_gNB_handle_initial_context_request(uint32_t assoc_id, if (ie == NULL) { NGAP_WARN("AllowedNSSAI not present, forging 2 NSSAI\n"); - NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).nb_allowed_nssais = 2; + msg->nb_allowed_nssais = 2; - NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).allowed_nssai[0].sST = 01; + msg->allowed_nssai[0].sST = 01; - NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).allowed_nssai[0].sD_flag = 1; - NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).allowed_nssai[0].sD[0] = 01; - NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).allowed_nssai[0].sD[1] = 02; - NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).allowed_nssai[0].sD[2] = 03; + msg->allowed_nssai[0].sD_flag = 1; + msg->allowed_nssai[0].sD[0] = 01; + msg->allowed_nssai[0].sD[1] = 02; + msg->allowed_nssai[0].sD[2] = 03; - NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).allowed_nssai[1].sST = 01; + msg->allowed_nssai[1].sST = 01; - NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).allowed_nssai[1].sD_flag = 1; - NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).allowed_nssai[1].sD[0] = 00;//11; - NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).allowed_nssai[1].sD[1] = 00;//22; - NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).allowed_nssai[1].sD[2] = 01;//33; + msg->allowed_nssai[1].sD_flag = 1; + msg->allowed_nssai[1].sD[0] = 00;//11; + msg->allowed_nssai[1].sD[1] = 00;//22; + msg->allowed_nssai[1].sD[2] = 01;//33; } else { NGAP_INFO("AllowedNSSAI.list.count %d\n", ie->value.choice.AllowedNSSAI.list.count); - NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).nb_allowed_nssais = ie->value.choice.AllowedNSSAI.list.count; + msg->nb_allowed_nssais = ie->value.choice.AllowedNSSAI.list.count; for(i = 0; i < ie->value.choice.AllowedNSSAI.list.count; i++) { allow_nssai_item_p = ie->value.choice.AllowedNSSAI.list.array[i]; - OCTET_STRING_TO_INT8(&allow_nssai_item_p->s_NSSAI.sST, NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).allowed_nssai[i].sST); + OCTET_STRING_TO_INT8(&allow_nssai_item_p->s_NSSAI.sST, msg->allowed_nssai[i].sST); if(allow_nssai_item_p->s_NSSAI.sD != NULL) { - NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).allowed_nssai[i].sD_flag = 1; - NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).allowed_nssai[i].sD[0] = allow_nssai_item_p->s_NSSAI.sD->buf[0]; - NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).allowed_nssai[i].sD[1] = allow_nssai_item_p->s_NSSAI.sD->buf[1]; - NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).allowed_nssai[i].sD[2] = allow_nssai_item_p->s_NSSAI.sD->buf[2]; + msg->allowed_nssai[i].sD_flag = 1; + msg->allowed_nssai[i].sD[0] = allow_nssai_item_p->s_NSSAI.sD->buf[0]; + msg->allowed_nssai[i].sD[1] = allow_nssai_item_p->s_NSSAI.sD->buf[1]; + msg->allowed_nssai[i].sD[2] = allow_nssai_item_p->s_NSSAI.sD->buf[2]; } } } @@ -1116,13 +1111,13 @@ int ngap_gNB_handle_initial_context_request(uint32_t assoc_id, NGAP_ProtocolIE_ID_id_UESecurityCapabilities, true); if (ie != NULL) { /* checked by macro but cppcheck doesn't see it */ - NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).security_capabilities.nRencryption_algorithms = + msg->security_capabilities.nRencryption_algorithms = BIT_STRING_to_uint16(&ie->value.choice.UESecurityCapabilities.nRencryptionAlgorithms); - NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).security_capabilities.nRintegrity_algorithms = + msg->security_capabilities.nRintegrity_algorithms = BIT_STRING_to_uint16(&ie->value.choice.UESecurityCapabilities.nRintegrityProtectionAlgorithms); - NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).security_capabilities.eUTRAencryption_algorithms = + msg->security_capabilities.eUTRAencryption_algorithms = BIT_STRING_to_uint16(&ie->value.choice.UESecurityCapabilities.eUTRAencryptionAlgorithms); - NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).security_capabilities.eUTRAintegrity_algorithms = + msg->security_capabilities.eUTRAintegrity_algorithms = BIT_STRING_to_uint16(&ie->value.choice.UESecurityCapabilities.eUTRAintegrityProtectionAlgorithms); } else {/* ie != NULL */ return -1; @@ -1133,7 +1128,7 @@ int ngap_gNB_handle_initial_context_request(uint32_t assoc_id, NGAP_ProtocolIE_ID_id_SecurityKey, true); if (ie != NULL) { /* checked by macro but cppcheck doesn't see it */ - memcpy(&NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).security_key, + memcpy(&msg->security_key, ie->value.choice.SecurityKey.buf, ie->value.choice.SecurityKey.size); } else {/* ie != NULL */ @@ -1148,11 +1143,11 @@ int ngap_gNB_handle_initial_context_request(uint32_t assoc_id, NGAP_MobilityRestrictionList_t *mobility_rest_list_p = NULL; mobility_rest_list_p = &ie->value.choice.MobilityRestrictionList; - NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).mobility_restriction_flag = 1; + msg->mobility_restriction_flag = 1; TBCD_TO_MCC_MNC(&mobility_rest_list_p->servingPLMN, - NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).mobility_restriction.serving_plmn.mcc, - NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).mobility_restriction.serving_plmn.mnc, - NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).mobility_restriction.serving_plmn.mnc_digit_length); + msg->mobility_restriction.serving_plmn.mcc, + msg->mobility_restriction.serving_plmn.mnc, + msg->mobility_restriction.serving_plmn.mnc_digit_length); } @@ -1162,10 +1157,10 @@ int ngap_gNB_handle_initial_context_request(uint32_t assoc_id, if (ie != NULL) { /* checked by macro but cppcheck doesn't see it */ if(ie->value.choice.NAS_PDU.size > 0) { - NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).nas_pdu_flag = 1; - NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).nas_pdu.length = ie->value.choice.NAS_PDU.size; - NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).nas_pdu.buffer = malloc(sizeof(uint8_t) * ie->value.choice.NAS_PDU.size); - memcpy(NGAP_INITIAL_CONTEXT_SETUP_REQ(message_p).nas_pdu.buffer, + msg->nas_pdu_flag = 1; + msg->nas_pdu.length = ie->value.choice.NAS_PDU.size; + msg->nas_pdu.buffer = malloc(sizeof(uint8_t) * ie->value.choice.NAS_PDU.size); + memcpy(msg->nas_pdu.buffer, ie->value.choice.NAS_PDU.buf, ie->value.choice.NAS_PDU.size); } } @@ -1259,7 +1254,6 @@ int ngap_gNB_handle_pdusession_setup_request(uint32_t assoc_id, NGAP_RAN_UE_NGAP_ID_t ran_ue_ngap_id; ngap_gNB_amf_data_t *amf_desc_p = NULL; ngap_gNB_ue_context_t *ue_desc_p = NULL; - MessageDef *message_p = NULL; NGAP_PDUSessionResourceSetupRequest_t *container; NGAP_PDUSessionResourceSetupRequestIEs_t *ie; DevAssert(pdu != NULL); @@ -1313,17 +1307,26 @@ int ngap_gNB_handle_pdusession_setup_request(uint32_t assoc_id, (uint64_t)ue_desc_p->amf_ue_ngap_id, amf_ue_ngap_id); } - message_p = itti_alloc_new_message(TASK_NGAP, 0, NGAP_PDUSESSION_SETUP_REQ); - NGAP_PDUSESSION_SETUP_REQ(message_p).ue_initial_id = ue_desc_p->ue_initial_id; + MessageDef * message_p = itti_alloc_new_message(TASK_NGAP, 0, NGAP_PDUSESSION_SETUP_REQ); + ngap_pdusession_setup_req_t * msg=&NGAP_PDUSESSION_SETUP_REQ(message_p); + msg->ue_initial_id = ue_desc_p->ue_initial_id; ue_desc_p->ue_initial_id = 0; - NGAP_PDUSESSION_SETUP_REQ(message_p).gNB_ue_ngap_id = ue_desc_p->gNB_ue_ngap_id; - NGAP_PDUSESSION_SETUP_REQ(message_p).amf_ue_ngap_id = ue_desc_p->amf_ue_ngap_id; + msg->gNB_ue_ngap_id = ue_desc_p->gNB_ue_ngap_id; + msg->amf_ue_ngap_id = ue_desc_p->amf_ue_ngap_id; + + /* UE Aggregated Maximum Bitrate */ + NGAP_FIND_PROTOCOLIE_BY_ID(NGAP_PDUSessionResourceSetupRequestIEs_t, ie, container, + NGAP_ProtocolIE_ID_id_UEAggregateMaximumBitRate, true); + asn_INTEGER2ulong(&(ie->value.choice.UEAggregateMaximumBitRate.uEAggregateMaximumBitRateUL), + &msg->ueAggMaxBitRateUplink); + asn_INTEGER2ulong(&(ie->value.choice.UEAggregateMaximumBitRate.uEAggregateMaximumBitRateDL), + &msg->ueAggMaxBitRateDownlink); NGAP_FIND_PROTOCOLIE_BY_ID(NGAP_PDUSessionResourceSetupRequestIEs_t, ie, container, NGAP_ProtocolIE_ID_id_PDUSessionResourceSetupListSUReq, true); if (ie != NULL) { /* checked by macro but cppcheck doesn't see it */ - NGAP_PDUSESSION_SETUP_REQ(message_p).nb_pdusessions_tosetup = + msg->nb_pdusessions_tosetup = ie->value.choice.PDUSessionResourceSetupListSUReq.list.count; for (int i = 0; i < ie->value.choice.PDUSessionResourceSetupListSUReq.list.count; i++) { @@ -1332,20 +1335,29 @@ int ngap_gNB_handle_pdusession_setup_request(uint32_t assoc_id, NGAP_PDUSessionResourceSetupRequestTransfer_t *pdusessionTransfer_p = NULL; NGAP_PDUSessionResourceSetupRequestTransferIEs_t *pdusessionTransfer_ies = NULL; + // PDU session ID item_p = (NGAP_PDUSessionResourceSetupItemSUReq_t *)ie->value.choice.PDUSessionResourceSetupListSUReq.list.array[i]; - NGAP_PDUSESSION_SETUP_REQ(message_p).pdusession_setup_params[i].pdusession_id = item_p->pDUSessionID; + msg->pdusession_setup_params[i].pdusession_id = item_p->pDUSessionID; + // S-NSSAI + OCTET_STRING_TO_INT8(&item_p->s_NSSAI.sST, msg->allowed_nssai[i].sST); + if(item_p->s_NSSAI.sD != NULL) { + msg->allowed_nssai[i].sD_flag = 1; + msg->allowed_nssai[i].sD[0] = item_p->s_NSSAI.sD->buf[0]; + msg->allowed_nssai[i].sD[1] = item_p->s_NSSAI.sD->buf[1]; + msg->allowed_nssai[i].sD[2] = item_p->s_NSSAI.sD->buf[2]; + } // check for the NAS PDU if (item_p->pDUSessionNAS_PDU->size > 0 ) { - NGAP_PDUSESSION_SETUP_REQ(message_p).pdusession_setup_params[i].nas_pdu.length = item_p->pDUSessionNAS_PDU->size; - NGAP_PDUSESSION_SETUP_REQ(message_p).pdusession_setup_params[i].nas_pdu.buffer = malloc(sizeof(uint8_t) * item_p->pDUSessionNAS_PDU->size); - memcpy(NGAP_PDUSESSION_SETUP_REQ(message_p).pdusession_setup_params[i].nas_pdu.buffer, + msg->pdusession_setup_params[i].nas_pdu.length = item_p->pDUSessionNAS_PDU->size; + msg->pdusession_setup_params[i].nas_pdu.buffer = malloc(sizeof(uint8_t) * item_p->pDUSessionNAS_PDU->size); + memcpy(msg->pdusession_setup_params[i].nas_pdu.buffer, item_p->pDUSessionNAS_PDU->buf, item_p->pDUSessionNAS_PDU->size); - // NGAP_INFO("received a NAS PDU with size %d (%02x.%02x)\n",NGAP_PDUSESSION_SETUP_REQ(message_p).pdusession_setup_params[i].nas_pdu.length, item_p->nAS_PDU.buf[0], item_p->nAS_PDU.buf[1]); + // NGAP_INFO("received a NAS PDU with size %d (%02x.%02x)\n",msg->pdusession_setup_params[i].nas_pdu.length, item_p->nAS_PDU.buf[0], item_p->nAS_PDU.buf[1]); } else { - NGAP_PDUSESSION_SETUP_REQ(message_p).pdusession_setup_params[i].nas_pdu.length = 0; - NGAP_PDUSESSION_SETUP_REQ(message_p).pdusession_setup_params[i].nas_pdu.buffer = NULL; + msg->pdusession_setup_params[i].nas_pdu.length = 0; + msg->pdusession_setup_params[i].nas_pdu.buffer = NULL; NGAP_WARN("NAS PDU is not provided, generate a PDUSESSION_SETUP Failure (TBD) back to AMF \n"); } @@ -1374,10 +1386,10 @@ int ngap_gNB_handle_pdusession_setup_request(uint32_t assoc_id, NGAP_GTPTunnel_t *gTPTunnel_p; gTPTunnel_p = pdusessionTransfer_ies->value.choice.UPTransportLayerInformation.choice.gTPTunnel; /* The transport layer address for the IP packets */ - OCTET_STRING_TO_INT32(&gTPTunnel_p->gTP_TEID, NGAP_PDUSESSION_SETUP_REQ(message_p).pdusession_setup_params[i].gtp_teid); - NGAP_PDUSESSION_SETUP_REQ(message_p).pdusession_setup_params[i].upf_addr.length = + OCTET_STRING_TO_INT32(&gTPTunnel_p->gTP_TEID, msg->pdusession_setup_params[i].gtp_teid); + msg->pdusession_setup_params[i].upf_addr.length = gTPTunnel_p->transportLayerAddress.size * 8 - gTPTunnel_p->transportLayerAddress.bits_unused; - memcpy(NGAP_PDUSESSION_SETUP_REQ(message_p).pdusession_setup_params[i].upf_addr.buffer , + memcpy(msg->pdusession_setup_params[i].upf_addr.buffer , gTPTunnel_p->transportLayerAddress.buf, gTPTunnel_p->transportLayerAddress.size); } break; @@ -1392,7 +1404,7 @@ int ngap_gNB_handle_pdusession_setup_request(uint32_t assoc_id, /* mandatory PDUSessionType */ case NGAP_ProtocolIE_ID_id_PDUSessionType: - NGAP_PDUSESSION_SETUP_REQ(message_p).pdusession_setup_params[i].upf_addr.pdu_session_type = (uint8_t)pdusessionTransfer_ies->value.choice.PDUSessionType; + msg->pdusession_setup_params[i].upf_addr.pdu_session_type = (uint8_t)pdusessionTransfer_ies->value.choice.PDUSessionType; break; /* optional SecurityIndication */ @@ -1412,24 +1424,28 @@ int ngap_gNB_handle_pdusession_setup_request(uint32_t assoc_id, DevAssert(pdusessionTransfer_ies->value.choice.QosFlowSetupRequestList.list.count > 0); DevAssert(pdusessionTransfer_ies->value.choice.QosFlowSetupRequestList.list.count <= NGAP_maxnoofQosFlows); - NGAP_PDUSESSION_SETUP_REQ(message_p).pdusession_setup_params[i].nb_qos = pdusessionTransfer_ies->value.choice.QosFlowSetupRequestList.list.count; + msg->pdusession_setup_params[i].nb_qos = pdusessionTransfer_ies->value.choice.QosFlowSetupRequestList.list.count; for(int qosIdx = 0; qosIdx < pdusessionTransfer_ies->value.choice.QosFlowSetupRequestList.list.count; qosIdx++){ qosFlowItem_p = pdusessionTransfer_ies->value.choice.QosFlowSetupRequestList.list.array[qosIdx]; /* Set the QOS informations */ - NGAP_PDUSESSION_SETUP_REQ(message_p).pdusession_setup_params[i].qos[qosIdx].qfi = (uint8_t)qosFlowItem_p->qosFlowIdentifier; + msg->pdusession_setup_params[i].qos[qosIdx].qfi = (uint8_t)qosFlowItem_p->qosFlowIdentifier; if(qosFlowItem_p->qosFlowLevelQosParameters.qosCharacteristics.present == NGAP_QosCharacteristics_PR_nonDynamic5QI){ + msg->pdusession_setup_params[i].qos[qosIdx].fiveQI_type = non_dynamic; if(qosFlowItem_p->qosFlowLevelQosParameters.qosCharacteristics.choice.nonDynamic5QI != NULL){ - NGAP_PDUSESSION_SETUP_REQ(message_p).pdusession_setup_params[i].qos[qosIdx].fiveQI = + msg->pdusession_setup_params[i].qos[qosIdx].fiveQI = (uint64_t)qosFlowItem_p->qosFlowLevelQosParameters.qosCharacteristics.choice.nonDynamic5QI->fiveQI; } + } else if (qosFlowItem_p->qosFlowLevelQosParameters.qosCharacteristics.present == NGAP_QosCharacteristics_PR_dynamic5QI) + { + msg->pdusession_setup_params[i].qos[qosIdx].fiveQI_type = dynamic; } - NGAP_PDUSESSION_SETUP_REQ(message_p).pdusession_setup_params[i].qos[qosIdx].allocation_retention_priority.priority_level = + msg->pdusession_setup_params[i].qos[qosIdx].allocation_retention_priority.priority_level = qosFlowItem_p->qosFlowLevelQosParameters.allocationAndRetentionPriority.priorityLevelARP; - NGAP_PDUSESSION_SETUP_REQ(message_p).pdusession_setup_params[i].qos[qosIdx].allocation_retention_priority.pre_emp_capability = + msg->pdusession_setup_params[i].qos[qosIdx].allocation_retention_priority.pre_emp_capability = qosFlowItem_p->qosFlowLevelQosParameters.allocationAndRetentionPriority.pre_emptionCapability; - NGAP_PDUSESSION_SETUP_REQ(message_p).pdusession_setup_params[i].qos[qosIdx].allocation_retention_priority.pre_emp_vulnerability = + msg->pdusession_setup_params[i].qos[qosIdx].allocation_retention_priority.pre_emp_vulnerability = qosFlowItem_p->qosFlowLevelQosParameters.allocationAndRetentionPriority.pre_emptionVulnerability; } } @@ -1461,7 +1477,6 @@ int ngap_gNB_handle_paging(uint32_t assoc_id, ngap_gNB_amf_data_t *amf_desc_p = NULL; ngap_gNB_instance_t *ngap_gNB_instance = NULL; - MessageDef *message_p = NULL; NGAP_Paging_t *container; NGAP_PagingIEs_t *ie; DevAssert(pdu != NULL); @@ -1490,42 +1505,44 @@ int ngap_gNB_handle_paging(uint32_t assoc_id, return -1; } - message_p = itti_alloc_new_message(TASK_NGAP, 0, NGAP_PAGING_IND); + MessageDef *message_p = itti_alloc_new_message(TASK_NGAP, 0, NGAP_PAGING_IND); + ngap_paging_ind_t * msg=&NGAP_PAGING_IND(message_p); + /* convert NGAP_PagingIEs_t to ngap_paging_ind_t */ /* id-UEIdentityIndexValue : convert UE Identity Index value */ NGAP_FIND_PROTOCOLIE_BY_ID(NGAP_PagingIEs_t, ie, container, NGAP_ProtocolIE_ID_id_UEPagingIdentity, true); if (ie != NULL) { /* checked by macro but cppcheck doesn't see it */ - OCTET_STRING_TO_INT16(&ie->value.choice.UEPagingIdentity.choice.fiveG_S_TMSI->aMFSetID, NGAP_PAGING_IND(message_p).ue_paging_identity.s_tmsi.amf_set_id); - OCTET_STRING_TO_INT8(&ie->value.choice.UEPagingIdentity.choice.fiveG_S_TMSI->aMFPointer, NGAP_PAGING_IND(message_p).ue_paging_identity.s_tmsi.amf_pointer); - OCTET_STRING_TO_INT32(&ie->value.choice.UEPagingIdentity.choice.fiveG_S_TMSI->fiveG_TMSI, NGAP_PAGING_IND(message_p).ue_paging_identity.s_tmsi.m_tmsi); + OCTET_STRING_TO_INT16(&ie->value.choice.UEPagingIdentity.choice.fiveG_S_TMSI->aMFSetID, msg->ue_paging_identity.s_tmsi.amf_set_id); + OCTET_STRING_TO_INT8(&ie->value.choice.UEPagingIdentity.choice.fiveG_S_TMSI->aMFPointer, msg->ue_paging_identity.s_tmsi.amf_pointer); + OCTET_STRING_TO_INT32(&ie->value.choice.UEPagingIdentity.choice.fiveG_S_TMSI->fiveG_TMSI, msg->ue_paging_identity.s_tmsi.m_tmsi); NGAP_DEBUG("[SCTP %d] Received Paging Identity amf_set_id %d, amf_pointer %d, m_tmsi %d\n", assoc_id, - NGAP_PAGING_IND(message_p).ue_paging_identity.s_tmsi.amf_set_id, - NGAP_PAGING_IND(message_p).ue_paging_identity.s_tmsi.amf_pointer, - NGAP_PAGING_IND(message_p).ue_paging_identity.s_tmsi.m_tmsi); + msg->ue_paging_identity.s_tmsi.amf_set_id, + msg->ue_paging_identity.s_tmsi.amf_pointer, + msg->ue_paging_identity.s_tmsi.m_tmsi); } else { return -1; } - NGAP_PAGING_IND(message_p).paging_drx = NGAP_PAGING_DRX_256; + msg->paging_drx = NGAP_PAGING_DRX_256; /* id-pagingDRX */ NGAP_FIND_PROTOCOLIE_BY_ID(NGAP_PagingIEs_t, ie, container, NGAP_ProtocolIE_ID_id_PagingDRX, false); /* optional */ if (ie) { - NGAP_PAGING_IND(message_p).paging_drx = ie->value.choice.PagingDRX; + msg->paging_drx = ie->value.choice.PagingDRX; } else { - NGAP_PAGING_IND(message_p).paging_drx = NGAP_PAGING_DRX_256; + msg->paging_drx = NGAP_PAGING_DRX_256; } - memset (&NGAP_PAGING_IND(message_p).plmn_identity[0], 0, sizeof(plmn_identity_t)*256); - memset (&NGAP_PAGING_IND(message_p).tac[0], 0, sizeof(int16_t)*256); - NGAP_PAGING_IND(message_p).tai_size = 0; + memset (&msg->plmn_identity[0], 0, sizeof(plmn_identity_t)*256); + memset (&msg->tac[0], 0, sizeof(int16_t)*256); + msg->tai_size = 0; /* id-TAIList */ NGAP_FIND_PROTOCOLIE_BY_ID(NGAP_PagingIEs_t, ie, container, NGAP_ProtocolIE_ID_id_TAIListForPaging, true); @@ -1536,15 +1553,15 @@ int ngap_gNB_handle_paging(uint32_t assoc_id, for (int i = 0; i < ie->value.choice.TAIListForPaging.list.count; i++) { NGAP_TAIListForPagingItem_t *item_p; item_p = (NGAP_TAIListForPagingItem_t *)ie->value.choice.TAIListForPaging.list.array[i]; - TBCD_TO_MCC_MNC(&(item_p->tAI.pLMNIdentity), NGAP_PAGING_IND(message_p).plmn_identity[i].mcc, - NGAP_PAGING_IND(message_p).plmn_identity[i].mnc, - NGAP_PAGING_IND(message_p).plmn_identity[i].mnc_digit_length); - OCTET_STRING_TO_INT16(&(item_p->tAI.tAC), NGAP_PAGING_IND(message_p).tac[i]); - NGAP_PAGING_IND(message_p).tai_size++; + TBCD_TO_MCC_MNC(&(item_p->tAI.pLMNIdentity), msg->plmn_identity[i].mcc, + msg->plmn_identity[i].mnc, + msg->plmn_identity[i].mnc_digit_length); + OCTET_STRING_TO_INT16(&(item_p->tAI.tAC), msg->tac[i]); + msg->tai_size++; NGAP_DEBUG("[SCTP %d] Received Paging: MCC %d, MNC %d, TAC %d\n", assoc_id, - NGAP_PAGING_IND(message_p).plmn_identity[i].mcc, - NGAP_PAGING_IND(message_p).plmn_identity[i].mnc, - NGAP_PAGING_IND(message_p).tac[i]); + msg->plmn_identity[i].mcc, + msg->plmn_identity[i].mnc, + msg->tac[i]); } } else { return -1; @@ -1552,10 +1569,10 @@ int ngap_gNB_handle_paging(uint32_t assoc_id, //paging parameter values NGAP_DEBUG("[SCTP %d] Received Paging parameters: Paging Identity amf_set_id %d amf_pointer %d m_tmsi %d paging_drx %d paging_priority %d\n",assoc_id, - NGAP_PAGING_IND(message_p).ue_paging_identity.s_tmsi.amf_set_id, - NGAP_PAGING_IND(message_p).ue_paging_identity.s_tmsi.amf_pointer, - NGAP_PAGING_IND(message_p).ue_paging_identity.s_tmsi.m_tmsi, - NGAP_PAGING_IND(message_p).paging_drx, NGAP_PAGING_IND(message_p).paging_priority); + msg->ue_paging_identity.s_tmsi.amf_set_id, + msg->ue_paging_identity.s_tmsi.amf_pointer, + msg->ue_paging_identity.s_tmsi.m_tmsi, + msg->paging_drx, msg->paging_priority); /* send message to RRC */ itti_send_msg_to_task(TASK_RRC_GNB, ngap_gNB_instance->instance, message_p); @@ -1570,7 +1587,6 @@ int ngap_gNB_handle_pdusession_modify_request(uint32_t assoc_id, int i, nb_of_pdusessions_failed; ngap_gNB_amf_data_t *amf_desc_p = NULL; ngap_gNB_ue_context_t *ue_desc_p = NULL; - MessageDef *message_p = NULL; NGAP_PDUSessionResourceModifyRequest_t *container; NGAP_PDUSessionResourceModifyRequestIEs_t *ie; NGAP_RAN_UE_NGAP_ID_t gnb_ue_ngap_id; @@ -1617,8 +1633,9 @@ int ngap_gNB_handle_pdusession_modify_request(uint32_t assoc_id, if (ue_desc_p->amf_ue_ngap_id != amf_ue_ngap_id) { NGAP_WARN("UE context amf_ue_ngap_id is different form that of the message (%ld != %ld)", (uint64_t)ue_desc_p->amf_ue_ngap_id, amf_ue_ngap_id); - message_p = itti_alloc_new_message (TASK_RRC_GNB, 0, NGAP_PDUSESSION_MODIFY_RESP); - NGAP_PDUSESSION_MODIFY_RESP (message_p).gNB_ue_ngap_id = gnb_ue_ngap_id; + MessageDef *message_p = itti_alloc_new_message (TASK_RRC_GNB, 0, NGAP_PDUSESSION_MODIFY_RESP); + ngap_pdusession_modify_resp_t* msg=&NGAP_PDUSESSION_MODIFY_RESP(message_p); + msg->gNB_ue_ngap_id = gnb_ue_ngap_id; NGAP_FIND_PROTOCOLIE_BY_ID(NGAP_PDUSessionResourceModifyRequestIEs_t, ie, container, NGAP_ProtocolIE_ID_id_PDUSessionResourceModifyListModReq, true); @@ -1627,32 +1644,32 @@ int ngap_gNB_handle_pdusession_modify_request(uint32_t assoc_id, NGAP_PDUSessionResourceModifyItemModReq_t *item_p; item_p = (NGAP_PDUSessionResourceModifyItemModReq_t *)ie->value.choice.PDUSessionResourceModifyListModReq.list.array[nb_of_pdusessions_failed]; - NGAP_PDUSESSION_MODIFY_RESP(message_p).pdusessions_failed[nb_of_pdusessions_failed].pdusession_id = item_p->pDUSessionID; - NGAP_PDUSESSION_MODIFY_RESP(message_p).pdusessions_failed[nb_of_pdusessions_failed].cause = NGAP_Cause_PR_radioNetwork; - NGAP_PDUSESSION_MODIFY_RESP(message_p).pdusessions_failed[nb_of_pdusessions_failed].cause_value = NGAP_CauseRadioNetwork_unknown_local_UE_NGAP_ID; + msg->pdusessions_failed[nb_of_pdusessions_failed].pdusession_id = item_p->pDUSessionID; + msg->pdusessions_failed[nb_of_pdusessions_failed].cause = NGAP_Cause_PR_radioNetwork; + msg->pdusessions_failed[nb_of_pdusessions_failed].cause_value = NGAP_CauseRadioNetwork_unknown_local_UE_NGAP_ID; } } else { return -1; } - NGAP_PDUSESSION_MODIFY_RESP(message_p).nb_of_pdusessions_failed = nb_of_pdusessions_failed; - ngap_gNB_pdusession_modify_resp(amf_desc_p->ngap_gNB_instance->instance, - &NGAP_PDUSESSION_MODIFY_RESP(message_p)); + msg->nb_of_pdusessions_failed = nb_of_pdusessions_failed; + ngap_gNB_pdusession_modify_resp(amf_desc_p->ngap_gNB_instance->instance,msg); itti_free(TASK_RRC_GNB,message_p); message_p = NULL; return -1; } - message_p = itti_alloc_new_message(TASK_NGAP, 0, NGAP_PDUSESSION_MODIFY_REQ); - NGAP_PDUSESSION_MODIFY_REQ(message_p).ue_initial_id = ue_desc_p->ue_initial_id; - NGAP_PDUSESSION_MODIFY_REQ(message_p).amf_ue_ngap_id = amf_ue_ngap_id; - NGAP_PDUSESSION_MODIFY_REQ(message_p).gNB_ue_ngap_id = gnb_ue_ngap_id; + MessageDef *message_p = itti_alloc_new_message(TASK_NGAP, 0, NGAP_PDUSESSION_MODIFY_REQ); + ngap_pdusession_modify_req_t * msg=&NGAP_PDUSESSION_MODIFY_REQ(message_p); + msg->ue_initial_id = ue_desc_p->ue_initial_id; + msg->amf_ue_ngap_id = amf_ue_ngap_id; + msg->gNB_ue_ngap_id = gnb_ue_ngap_id; /* id-PDUSessionResourceModifyListModReq */ NGAP_FIND_PROTOCOLIE_BY_ID(NGAP_PDUSessionResourceModifyRequestIEs_t, ie, container, NGAP_ProtocolIE_ID_id_PDUSessionResourceModifyListModReq, true); if (ie != NULL) { /* checked by macro but cppcheck doesn't see it */ - NGAP_PDUSESSION_MODIFY_REQ(message_p).nb_pdusessions_tomodify = + msg->nb_pdusessions_tomodify = ie->value.choice.PDUSessionResourceModifyListModReq.list.count; for (i = 0; i < ie->value.choice.PDUSessionResourceModifyListModReq.list.count; i++) { @@ -1663,17 +1680,17 @@ int ngap_gNB_handle_pdusession_modify_request(uint32_t assoc_id, item_p = (NGAP_PDUSessionResourceModifyItemModReq_t *)ie->value.choice.PDUSessionResourceModifyListModReq.list.array[i]; - NGAP_PDUSESSION_MODIFY_REQ(message_p).pdusession_modify_params[i].pdusession_id = item_p->pDUSessionID; + msg->pdusession_modify_params[i].pdusession_id = item_p->pDUSessionID; // check for the NAS PDU if (item_p->nAS_PDU != NULL && item_p->nAS_PDU->size > 0 ) { - NGAP_PDUSESSION_MODIFY_REQ(message_p).pdusession_modify_params[i].nas_pdu.length = item_p->nAS_PDU->size; - NGAP_PDUSESSION_MODIFY_REQ(message_p).pdusession_modify_params[i].nas_pdu.buffer = malloc(sizeof(uint8_t) * item_p->nAS_PDU->size); - memcpy(NGAP_PDUSESSION_MODIFY_REQ(message_p).pdusession_modify_params[i].nas_pdu.buffer, + msg->pdusession_modify_params[i].nas_pdu.length = item_p->nAS_PDU->size; + msg->pdusession_modify_params[i].nas_pdu.buffer = malloc(sizeof(uint8_t) * item_p->nAS_PDU->size); + memcpy(msg->pdusession_modify_params[i].nas_pdu.buffer, item_p->nAS_PDU->buf, item_p->nAS_PDU->size); } else { - NGAP_PDUSESSION_MODIFY_REQ(message_p).pdusession_modify_params[i].nas_pdu.length = 0; - NGAP_PDUSESSION_MODIFY_REQ(message_p).pdusession_modify_params[i].nas_pdu.buffer = NULL; + msg->pdusession_modify_params[i].nas_pdu.length = 0; + msg->pdusession_modify_params[i].nas_pdu.buffer = NULL; continue; } @@ -1718,25 +1735,25 @@ int ngap_gNB_handle_pdusession_modify_request(uint32_t assoc_id, DevAssert(pdusessionTransfer_ies->value.choice.QosFlowAddOrModifyRequestList.list.count > 0); DevAssert(pdusessionTransfer_ies->value.choice.QosFlowAddOrModifyRequestList.list.count <= NGAP_maxnoofQosFlows); - NGAP_PDUSESSION_MODIFY_REQ(message_p).pdusession_modify_params[i].nb_qos = pdusessionTransfer_ies->value.choice.QosFlowAddOrModifyRequestList.list.count; + msg->pdusession_modify_params[i].nb_qos = pdusessionTransfer_ies->value.choice.QosFlowAddOrModifyRequestList.list.count; for(int qosIdx = 0; qosIdx < pdusessionTransfer_ies->value.choice.QosFlowAddOrModifyRequestList.list.count; qosIdx++) { qosFlowItem_p = pdusessionTransfer_ies->value.choice.QosFlowAddOrModifyRequestList.list.array[qosIdx]; /* Set the QOS informations */ - NGAP_PDUSESSION_MODIFY_REQ(message_p).pdusession_modify_params[i].qos[qosIdx].qfi = (uint8_t)qosFlowItem_p->qosFlowIdentifier; + msg->pdusession_modify_params[i].qos[qosIdx].qfi = (uint8_t)qosFlowItem_p->qosFlowIdentifier; if(qosFlowItem_p->qosFlowLevelQosParameters) { if (qosFlowItem_p->qosFlowLevelQosParameters->qosCharacteristics.present == NGAP_QosCharacteristics_PR_nonDynamic5QI) { - NGAP_PDUSESSION_MODIFY_REQ(message_p).pdusession_modify_params[i].qos[qosIdx].fiveQI = + msg->pdusession_modify_params[i].qos[qosIdx].fiveQI = qosFlowItem_p->qosFlowLevelQosParameters->qosCharacteristics.choice.nonDynamic5QI->fiveQI; } else if (qosFlowItem_p->qosFlowLevelQosParameters->qosCharacteristics.present == NGAP_QosCharacteristics_PR_dynamic5QI) { // TODO } - NGAP_PDUSESSION_MODIFY_REQ(message_p).pdusession_modify_params[i].qos[qosIdx].allocation_retention_priority.priority_level = + msg->pdusession_modify_params[i].qos[qosIdx].allocation_retention_priority.priority_level = qosFlowItem_p->qosFlowLevelQosParameters->allocationAndRetentionPriority.priorityLevelARP; - NGAP_PDUSESSION_MODIFY_REQ(message_p).pdusession_modify_params[i].qos[qosIdx].allocation_retention_priority.pre_emp_capability = + msg->pdusession_modify_params[i].qos[qosIdx].allocation_retention_priority.pre_emp_capability = qosFlowItem_p->qosFlowLevelQosParameters->allocationAndRetentionPriority.pre_emptionCapability; - NGAP_PDUSESSION_MODIFY_REQ(message_p).pdusession_modify_params[i].qos[qosIdx].allocation_retention_priority.pre_emp_vulnerability = + msg->pdusession_modify_params[i].qos[qosIdx].allocation_retention_priority.pre_emp_vulnerability = qosFlowItem_p->qosFlowLevelQosParameters->allocationAndRetentionPriority.pre_emptionVulnerability; } } @@ -1784,7 +1801,6 @@ int ngap_gNB_handle_pdusession_release_command(uint32_t assoc_id, int i; ngap_gNB_amf_data_t *amf_desc_p = NULL; ngap_gNB_ue_context_t *ue_desc_p = NULL; - MessageDef *message_p = NULL; NGAP_PDUSessionResourceReleaseCommand_t *container; NGAP_PDUSessionResourceReleaseCommandIEs_t *ie; NGAP_RAN_UE_NGAP_ID_t gnb_ue_ngap_id; @@ -1841,22 +1857,24 @@ int ngap_gNB_handle_pdusession_release_command(uint32_t assoc_id, NGAP_DEBUG("[SCTP %d] Received pdu session release command for gNB_UE_NGAP_ID %lu amf_ue_ngap_id %lu\n", assoc_id, gnb_ue_ngap_id, amf_ue_ngap_id); - message_p = itti_alloc_new_message(TASK_NGAP, 0, NGAP_PDUSESSION_RELEASE_COMMAND); - NGAP_PDUSESSION_RELEASE_COMMAND(message_p).gNB_ue_ngap_id = gnb_ue_ngap_id; - NGAP_PDUSESSION_RELEASE_COMMAND(message_p).amf_ue_ngap_id = amf_ue_ngap_id; + MessageDef * message_p = itti_alloc_new_message(TASK_NGAP, 0, NGAP_PDUSESSION_RELEASE_COMMAND); + ngap_pdusession_release_command_t * msg=&NGAP_PDUSESSION_RELEASE_COMMAND(message_p); + + msg->gNB_ue_ngap_id = gnb_ue_ngap_id; + msg->amf_ue_ngap_id = amf_ue_ngap_id; /* id-NAS-PDU */ NGAP_FIND_PROTOCOLIE_BY_ID(NGAP_PDUSessionResourceReleaseCommandIEs_t, ie, container, NGAP_ProtocolIE_ID_id_NAS_PDU, false); if(ie && ie->value.choice.NAS_PDU.size > 0) { - NGAP_PDUSESSION_RELEASE_COMMAND(message_p).nas_pdu.length = ie->value.choice.NAS_PDU.size; - NGAP_PDUSESSION_RELEASE_COMMAND(message_p).nas_pdu.buffer = malloc(sizeof(uint8_t) * ie->value.choice.NAS_PDU.size); - memcpy(NGAP_PDUSESSION_RELEASE_COMMAND(message_p).nas_pdu.buffer, + msg->nas_pdu.length = ie->value.choice.NAS_PDU.size; + msg->nas_pdu.buffer = malloc(sizeof(uint8_t) * ie->value.choice.NAS_PDU.size); + memcpy(msg->nas_pdu.buffer, ie->value.choice.NAS_PDU.buf, ie->value.choice.NAS_PDU.size); } else { - NGAP_PDUSESSION_RELEASE_COMMAND(message_p).nas_pdu.length = 0; - NGAP_PDUSESSION_RELEASE_COMMAND(message_p).nas_pdu.buffer = NULL; + msg->nas_pdu.length = 0; + msg->nas_pdu.buffer = NULL; } /* id-PDUSessionResourceToReleaseListRelCmd */ @@ -1864,22 +1882,22 @@ int ngap_gNB_handle_pdusession_release_command(uint32_t assoc_id, NGAP_ProtocolIE_ID_id_PDUSessionResourceToReleaseListRelCmd, true); if (ie != NULL) { /* checked by macro but cppcheck doesn't see it */ - NGAP_PDUSESSION_RELEASE_COMMAND(message_p).nb_pdusessions_torelease = ie->value.choice.PDUSessionResourceToReleaseListRelCmd.list.count; + msg->nb_pdusessions_torelease = ie->value.choice.PDUSessionResourceToReleaseListRelCmd.list.count; for (i = 0; i < ie->value.choice.PDUSessionResourceToReleaseListRelCmd.list.count; i++) { NGAP_PDUSessionResourceToReleaseItemRelCmd_t *item_p; item_p = (NGAP_PDUSessionResourceToReleaseItemRelCmd_t *)ie->value.choice.PDUSessionResourceToReleaseListRelCmd.list.array[i]; - NGAP_PDUSESSION_RELEASE_COMMAND(message_p).pdusession_release_params[i].pdusession_id = item_p->pDUSessionID; + msg->pdusession_release_params[i].pdusession_id = item_p->pDUSessionID; if(item_p->pDUSessionResourceReleaseCommandTransfer.size > 0) { - NGAP_PDUSESSION_RELEASE_COMMAND(message_p).pdusession_release_params[i].transfer_length = item_p->pDUSessionResourceReleaseCommandTransfer.size; - NGAP_PDUSESSION_RELEASE_COMMAND(message_p).pdusession_release_params[i].transfer_buffer = malloc(sizeof(uint8_t) * item_p->pDUSessionResourceReleaseCommandTransfer.size); - memcpy(NGAP_PDUSESSION_RELEASE_COMMAND(message_p).pdusession_release_params[i].transfer_buffer, + msg->pdusession_release_params[i].transfer_length = item_p->pDUSessionResourceReleaseCommandTransfer.size; + msg->pdusession_release_params[i].transfer_buffer = malloc(sizeof(uint8_t) * item_p->pDUSessionResourceReleaseCommandTransfer.size); + memcpy(msg->pdusession_release_params[i].transfer_buffer, item_p->pDUSessionResourceReleaseCommandTransfer.buf, item_p->pDUSessionResourceReleaseCommandTransfer.size); }else { - NGAP_PDUSESSION_RELEASE_COMMAND(message_p).pdusession_release_params[i].transfer_length = 0; - NGAP_PDUSESSION_RELEASE_COMMAND(message_p).pdusession_release_params[i].transfer_buffer = NULL; + msg->pdusession_release_params[i].transfer_length = 0; + msg->pdusession_release_params[i].transfer_buffer = NULL; NGAP_ERROR("[NGAP] Received pdu session release command for pDUSessionResourceReleaseCommandTransfer is NULL!\n"); } NGAP_DEBUG("[NGAP] Received pdu session release command for pDUSessionID id %ld\n", item_p->pDUSessionID); diff --git a/openair3/SCTP/sctp_eNB_task.c b/openair3/SCTP/sctp_eNB_task.c index 49a0674bdf..14128dd53e 100644 --- a/openair3/SCTP/sctp_eNB_task.c +++ b/openair3/SCTP/sctp_eNB_task.c @@ -617,10 +617,7 @@ sctp_handle_new_association_req( } //------------------------------------------------------------------------------ -static void sctp_send_data( - instance_t instance, - task_id_t task_id, - sctp_data_req_t *sctp_data_req_p) +static void sctp_send_data(sctp_data_req_t *sctp_data_req_p) { struct sctp_cnx_list_elm_s *sctp_cnx = NULL; @@ -660,10 +657,7 @@ static void sctp_send_data( } //------------------------------------------------------------------------------ -static int sctp_close_association( - const instance_t instance, - const task_id_t requestor, - sctp_close_association_t *close_association_p) +static int sctp_close_association(sctp_close_association_t *close_association_p) { struct sctp_cnx_list_elm_s *sctp_cnx = NULL; @@ -1152,10 +1146,8 @@ static void sctp_eNB_process_itti_msg() break; case SCTP_CLOSE_ASSOCIATION: - sctp_close_association(ITTI_MSG_DESTINATION_INSTANCE(received_msg), - ITTI_MSG_ORIGIN_ID(received_msg), - &received_msg->ittiMsg.sctp_close_association); - break; + sctp_close_association(&received_msg->ittiMsg.sctp_close_association); + break; case TERMINATE_MESSAGE: SCTP_WARN("*** Exiting SCTP thread\n"); @@ -1163,9 +1155,7 @@ static void sctp_eNB_process_itti_msg() break; case SCTP_DATA_REQ: { - sctp_send_data(ITTI_MSG_DESTINATION_INSTANCE(received_msg), - ITTI_MSG_ORIGIN_ID(received_msg), - &received_msg->ittiMsg.sctp_data_req); + sctp_send_data(&received_msg->ittiMsg.sctp_data_req); } break; diff --git a/openair3/ocp-gtpu/gtp_itf.cpp b/openair3/ocp-gtpu/gtp_itf.cpp index 8045e7f635..b598a29c16 100644 --- a/openair3/ocp-gtpu/gtp_itf.cpp +++ b/openair3/ocp-gtpu/gtp_itf.cpp @@ -94,7 +94,6 @@ typedef struct Gtpv1uExtHeader { #define GTP_END_MARKER (254) #define GTP_GPDU (255) - typedef struct gtpv1u_bearer_s { /* TEID used in dl and ul */ teid_t teid_incoming; ///< eNB TEID @@ -127,8 +126,7 @@ class gtpEndPoint { uint8_t foundAddr[20]; int foundAddrLen; int ipVersion; - map ue2te_mapping; - map te2ue_mapping; + map ue2te_mapping; // we use the same port number for source and destination address // this allow using non standard gtp port number (different from 2152) // and so, for example tu run 4G and 5G cores on one system @@ -142,7 +140,7 @@ class gtpEndPoints { pthread_mutex_t gtp_lock=PTHREAD_MUTEX_INITIALIZER; // the instance id will be the Linux socket handler, as this is uniq map instances; - + map te2ue_mapping; gtpEndPoints() { unsigned int seed; fill_random(&seed, sizeof(seed)); @@ -593,22 +591,17 @@ teid_t newGtpuCreateTunnel(instance_t instance, teid_t incoming_teid=gtpv1uNewTeid(); - while ( inst->te2ue_mapping.find(incoming_teid) != inst->te2ue_mapping.end() ) { + while (globGtp.te2ue_mapping.find(incoming_teid) != globGtp.te2ue_mapping.end()) { LOG_W(GTPU, "[%ld] generated a random Teid that exists, re-generating (%x)\n", instance, incoming_teid); incoming_teid=gtpv1uNewTeid(); }; - inst->te2ue_mapping[incoming_teid].ue_id=ue_id; - - inst->te2ue_mapping[incoming_teid].incoming_rb_id= incoming_bearer_id; - - inst->te2ue_mapping[incoming_teid].outgoing_teid= outgoing_teid; - - inst->te2ue_mapping[incoming_teid].callBack=callBack; - - inst->te2ue_mapping[incoming_teid].callBackSDAP = callBackSDAP; - - inst->te2ue_mapping[incoming_teid].pdusession_id = (uint8_t)outgoing_bearer_id; + globGtp.te2ue_mapping[incoming_teid].ue_id = ue_id; + globGtp.te2ue_mapping[incoming_teid].incoming_rb_id = incoming_bearer_id; + globGtp.te2ue_mapping[incoming_teid].outgoing_teid = outgoing_teid; + globGtp.te2ue_mapping[incoming_teid].callBack = callBack; + globGtp.te2ue_mapping[incoming_teid].callBackSDAP = callBackSDAP; + globGtp.te2ue_mapping[incoming_teid].pdusession_id = (uint8_t)outgoing_bearer_id; gtpv1u_bearer_t *tmp=&inst->ue2te_mapping[ue_id].bearers[outgoing_bearer_id]; @@ -641,13 +634,14 @@ teid_t newGtpuCreateTunnel(instance_t instance, pthread_mutex_unlock(&globGtp.gtp_lock); char ip4[INET_ADDRSTRLEN]; char ip6[INET6_ADDRSTRLEN]; - LOG_I(GTPU, "[%ld] Created tunnel for UE ID %lu, teid for DL: %x, teid for UL %x to remote IPv4: %s, IPv6 %s\n", + LOG_I(GTPU, + "[%ld] Created tunnel for UE ID %lu, teid for incoming: %x, teid for outgoing %x to remote IPv4: %s, IPv6 %s\n", instance, ue_id, tmp->teid_incoming, tmp->teid_outgoing, - inet_ntop(AF_INET,(void *)&tmp->outgoing_ip_addr, ip4,INET_ADDRSTRLEN ), - inet_ntop(AF_INET6,(void *)&tmp->outgoing_ip6_addr.s6_addr, ip6, INET6_ADDRSTRLEN)); + inet_ntop(AF_INET, (void *)&tmp->outgoing_ip_addr, ip4, INET_ADDRSTRLEN), + inet_ntop(AF_INET6, (void *)&tmp->outgoing_ip6_addr.s6_addr, ip6, INET6_ADDRSTRLEN)); return incoming_teid; } @@ -795,7 +789,7 @@ int newGtpuDeleteAllTunnels(instance_t instance, ue_id_t ue_id) { for (auto j=ptrUe->second.bearers.begin(); j!=ptrUe->second.bearers.end(); ++j) { - inst->te2ue_mapping.erase(j->second.teid_incoming); + globGtp.te2ue_mapping.erase(j->second.teid_incoming); nb++; } @@ -826,7 +820,7 @@ int newGtpuDeleteTunnels(instance_t instance, ue_id_t ue_id, int nbTunnels, pdus if ( ptr2 == ptrUe->second.bearers.end() ) { LOG_E(GTPU,"[%ld] GTP-U instance: delete of not existing tunnel UE ID:RAB: %ld/%x\n", instance, ue_id, pdusession_id[i]); } else { - inst->te2ue_mapping.erase(ptr2->second.teid_incoming); + globGtp.te2ue_mapping.erase(ptr2->second.teid_incoming); nb++; } } @@ -913,9 +907,9 @@ static int Gtpv1uHandleEndMarker(int h, // the socket Linux file handler is the instance id getInstRetInt(h); - auto tunnel=inst->te2ue_mapping.find(ntohl(msgHdr->teid)); + auto tunnel = globGtp.te2ue_mapping.find(ntohl(msgHdr->teid)); - if ( tunnel == inst->te2ue_mapping.end() ) { + if (tunnel == globGtp.te2ue_mapping.end()) { LOG_E(GTPU,"[%d] Received a incoming packet on unknown teid (%x) Dropping!\n", h, msgHdr->teid); pthread_mutex_unlock(&globGtp.gtp_lock); return GTPNOK; @@ -973,10 +967,9 @@ static int Gtpv1uHandleGpdu(int h, pthread_mutex_lock(&globGtp.gtp_lock); // the socket Linux file handler is the instance id getInstRetInt(h); + auto tunnel = globGtp.te2ue_mapping.find(ntohl(msgHdr->teid)); - auto tunnel=inst->te2ue_mapping.find(ntohl(msgHdr->teid)); - - if ( tunnel == inst->te2ue_mapping.end() ) { + if (tunnel == globGtp.te2ue_mapping.end()) { LOG_E(GTPU,"[%d] Received a incoming packet on unknown teid (%x) Dropping!\n", h, ntohl(msgHdr->teid)); pthread_mutex_unlock(&globGtp.gtp_lock); return GTPNOK; @@ -1143,10 +1136,7 @@ static int Gtpv1uHandleGpdu(int h, * according to TS 38.425: Fig. 5.5.2.2-1 and section 5.5.3.24*/ extensionHeader->length = 1+sizeof(DlDataDeliveryStatus_flagsT)+3+1+1; gtpv1uCreateAndSendMsg( - h, peerIp, peerPort, GTP_GPDU, - inst->te2ue_mapping[ntohl(msgHdr->teid)].outgoing_teid, - NULL, 0, false, false, 0, 0, NR_RAN_CONTAINER, - extensionHeader->buffer, extensionHeader->length); + h, peerIp, peerPort, GTP_GPDU, globGtp.te2ue_mapping[ntohl(msgHdr->teid)].outgoing_teid, NULL, 0, false, false, 0, 0, NR_RAN_CONTAINER, extensionHeader->buffer, extensionHeader->length); } LOG_D(GTPU,"[%d] Received a %d bytes packet for: teid:%x\n", h, @@ -1224,19 +1214,19 @@ void *gtpv1uTask(void *args) { if (message_p != NULL ) { openAddr_t addr= {0}; - - switch (ITTI_MSG_ID(message_p)) { - // DATA TO BE SENT TO UDP + const instance_t myInstance = ITTI_MSG_DESTINATION_INSTANCE(message_p); + const int msgType = ITTI_MSG_ID(message_p); + LOG_D(GTPU, "GTP-U received %s for instance %ld\n", messages_info[msgType].name, myInstance); + switch (msgType) { + // DATA TO BE SENT TO UDP case GTPV1U_TUNNEL_DATA_REQ: { - gtpv1uSend(compatInst(ITTI_MSG_DESTINATION_INSTANCE(message_p)), - >PV1U_TUNNEL_DATA_REQ(message_p), false, false); + gtpv1uSend(compatInst(myInstance), >PV1U_TUNNEL_DATA_REQ(message_p), false, false); } break; case GTPV1U_DU_BUFFER_REPORT_REQ:{ - gtpv1uSendDlDeliveryStatus(compatInst(ITTI_MSG_DESTINATION_INSTANCE(message_p)), - >PV1U_DU_BUFFER_REPORT_REQ(message_p)); + gtpv1uSendDlDeliveryStatus(compatInst(myInstance), >PV1U_DU_BUFFER_REPORT_REQ(message_p)); } break; @@ -1248,8 +1238,7 @@ void *gtpv1uTask(void *args) { break; case GTPV1U_ENB_END_MARKER_REQ: - gtpv1uEndTunnel(compatInst(ITTI_MSG_DESTINATION_INSTANCE(message_p)), - >PV1U_TUNNEL_DATA_REQ(message_p)); + gtpv1uEndTunnel(compatInst(myInstance), >PV1U_TUNNEL_DATA_REQ(message_p)); itti_free(TASK_GTPV1_U, GTPV1U_TUNNEL_DATA_REQ(message_p).buffer); break; diff --git a/openair3/ocp-gtpu/gtp_itf.h b/openair3/ocp-gtpu/gtp_itf.h index 86d719c200..8729be9fa5 100644 --- a/openair3/ocp-gtpu/gtp_itf.h +++ b/openair3/ocp-gtpu/gtp_itf.h @@ -93,8 +93,8 @@ extern "C" { gtpCallbackSDAP callBackSDAP); void GtpuUpdateTunnelOutgoingAddressAndTeid(instance_t instance, - ue_id_t ue_id, - ebi_t bearer_id, + ue_id_t ue_id, + ebi_t bearer_id, in_addr_t newOutgoingAddr, teid_t newOutgoingTeid); @@ -149,7 +149,7 @@ extern "C" { //RB_ENTRY(gtpv1u_ue_data_s) gtpv1u_ue_node; } gtpv1u_ue_data_t; - + #ifdef __cplusplus } #endif