diff --git a/CMakeLists.txt b/CMakeLists.txt index 627b87593d..8d3834319f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -293,7 +293,7 @@ set_property(CACHE KPM_VERSION PROPERTY STRINGS "KPM_V2_03" "KPM_V3_00") message(STATUS "Selected KPM Version: ${KPM_VERSION}") -add_boolean_option(ENABLE_IMSCOPE OFF "Enable phy scope based on imgui" ON) +add_boolean_option(ENABLE_IMSCOPE OFF "Enable phy scope based on imgui" OFF) ################################################## # ASN.1 grammar C code generation & dependencies # @@ -435,20 +435,18 @@ add_library(f1ap ${F1AP_DIR}/f1ap_cu_rrc_message_transfer.c ${F1AP_DIR}/f1ap_cu_task.c ${F1AP_DIR}/f1ap_cu_ue_context_management.c - ${F1AP_DIR}/f1ap_cu_warning_message_transmission.c ${F1AP_DIR}/f1ap_du_interface_management.c ${F1AP_DIR}/f1ap_du_paging.c ${F1AP_DIR}/f1ap_du_rrc_message_transfer.c - ${F1AP_DIR}/f1ap_du_system_information.c ${F1AP_DIR}/f1ap_du_task.c ${F1AP_DIR}/f1ap_du_ue_context_management.c - ${F1AP_DIR}/f1ap_du_warning_message_transmission.c ${F1AP_DIR}/f1ap_encoder.c ${F1AP_DIR}/f1ap_handlers.c ${F1AP_DIR}/f1ap_itti_messaging.c) target_include_directories(f1ap PUBLIC F1AP_DIR) target_link_libraries(f1ap PUBLIC asn1_f1ap L2_NR) -target_link_libraries(f1ap PRIVATE ngap nr_rrc HASHTABLE) +target_link_libraries(f1ap PRIVATE ngap nr_rrc HASHTABLE f1ap_lib) +target_include_directories(f1ap PRIVATE ${F1AP_DIR}/lib) # LPP ############## @@ -1438,6 +1436,8 @@ add_library(L2_NR ${GNB_APP_SRC} ) target_link_libraries(L2_NR PRIVATE ds alg) +target_link_libraries(L2_NR PRIVATE f1ap_lib) +target_include_directories(L2_NR PRIVATE ${F1AP_DIR}/lib) add_library(e1_if ${NR_RRC_DIR}/cucp_cuup_direct.c diff --git a/ci-scripts/as_ue/aw2s-multi-00102-20.cfg b/ci-scripts/as_ue/aw2s-multi-00102-20.cfg new file mode 100644 index 0000000000..48901cf6f0 --- /dev/null +++ b/ci-scripts/as_ue/aw2s-multi-00102-20.cfg @@ -0,0 +1,284 @@ +/* UE simulator configuration file version 2021-06-17 + * LTE / 5G Non StandAlone + * Copyright (C) 2019-2021 Amarisoft + */ +{ +#define N_ANTENNA_DL 1 +#define N_ANTENNA_UL 1 +#define DL_ARFCN 631296 +#define TDD 1 + +log_options: "all.level=warn,all.max_size=0,nas.level=debug,nas.max_size=1,rrc.level=debug,rrc.max_size=1", +log_filename: "/tmp/ue.log", + +/* Enable remote API and Web interface */ +com_addr: "0.0.0.0:9002", + +include "rf_driver_20/1chan.cfg", + +/* If true, allow the simulation of several UEs at the same time and +allow dynamic UE creation from remote API */ + + cell_groups: [{ + group_type: "nr", + multi_ue: true, + ldpc_max_its:8, + cells: [{ + rf_port: 0, + bandwidth: 20, + band: 78, + dl_nr_arfcn: DL_ARFCN, + ssb_nr_arfcn: DL_ARFCN, + subcarrier_spacing: 30, + n_antenna_dl: N_ANTENNA_DL, + n_antenna_ul: N_ANTENNA_UL, + rx_to_tx_latency:2, + global_timing_advance:-1, + }], + }], + + /* UE capabilities */ + /* USIM data */ + ue_list: [ + { + "ue_id" : 1, + "imsi": "001020000000001", + "K": "fec86ba6eb707ed08905757b1bb44b8f", + "sim_algo":"milenage", + "op": "1006020f0a478bf6b699f15c062e42b3", + + as_release: 15, + ue_category: "nr", + apn:"oai", + attach_pdn_type:"ipv4", + default_nssai: [ { sst: 1, }, ], + default_pdu_session_snssai: { sst: 1, }, + tun_setup_script: "ue-ifup", + }, + { + "ue_id" : 2, + "imsi": "001020000000002", + "K": "fec86ba6eb707ed08905757b1bb44b8f", + "sim_algo":"milenage", + "op": "1006020f0a478bf6b699f15c062e42b3", + + as_release: 15, + ue_category: "nr", + apn:"oai", + attach_pdn_type:"ipv4", + default_nssai: [ { sst: 1, }, ], + default_pdu_session_snssai: { sst: 1, }, + tun_setup_script: "ue-ifup", + }, + { + "ue_id" : 3, + "imsi": "001020000000003", + "K": "fec86ba6eb707ed08905757b1bb44b8f", + "sim_algo":"milenage", + "op": "1006020f0a478bf6b699f15c062e42b3", + + as_release: 15, + ue_category: "nr", + apn:"oai", + attach_pdn_type:"ipv4", + default_nssai: [ { sst: 1, }, ], + default_pdu_session_snssai: { sst: 1, }, + tun_setup_script: "ue-ifup", + }, + { + "ue_id" : 4, + "imsi": "001020000000004", + "K": "fec86ba6eb707ed08905757b1bb44b8f", + "sim_algo":"milenage", + "op": "1006020f0a478bf6b699f15c062e42b3", + + as_release: 15, + ue_category: "nr", + apn:"oai", + attach_pdn_type:"ipv4", + default_nssai: [ { sst: 1, }, ], + default_pdu_session_snssai: { sst: 1, }, + tun_setup_script: "ue-ifup", + }, + { + "ue_id" : 5, + "imsi": "001020000000005", + "K": "fec86ba6eb707ed08905757b1bb44b8f", + "sim_algo":"milenage", + "op": "1006020f0a478bf6b699f15c062e42b3", + + as_release: 15, + ue_category: "nr", + apn:"oai", + attach_pdn_type:"ipv4", + default_nssai: [ { sst: 1, }, ], + default_pdu_session_snssai: { sst: 1, }, + tun_setup_script: "ue-ifup", + }, + { + "ue_id" : 6, + "imsi": "001020000000006", + "K": "fec86ba6eb707ed08905757b1bb44b8f", + "sim_algo":"milenage", + "op": "1006020f0a478bf6b699f15c062e42b3", + + as_release: 15, + ue_category: "nr", + apn:"oai", + attach_pdn_type:"ipv4", + default_nssai: [ { sst: 1, }, ], + default_pdu_session_snssai: { sst: 1, }, + tun_setup_script: "ue-ifup", + }, + { + "ue_id" : 7, + "imsi": "001020000000007", + "K": "fec86ba6eb707ed08905757b1bb44b8f", + "sim_algo":"milenage", + "op": "1006020f0a478bf6b699f15c062e42b3", + + as_release: 15, + ue_category: "nr", + apn:"oai", + attach_pdn_type:"ipv4", + default_nssai: [ { sst: 1, }, ], + default_pdu_session_snssai: { sst: 1, }, + tun_setup_script: "ue-ifup", + }, + { + "ue_id" : 8, + "imsi": "001020000000008", + "K": "fec86ba6eb707ed08905757b1bb44b8f", + "sim_algo":"milenage", + "op": "1006020f0a478bf6b699f15c062e42b3", + + as_release: 15, + ue_category: "nr", + apn:"oai", + attach_pdn_type:"ipv4", + default_nssai: [ { sst: 1, }, ], + default_pdu_session_snssai: { sst: 1, }, + tun_setup_script: "ue-ifup", + }, + { + "ue_id" : 9, + "imsi": "001020000000009", + "K": "fec86ba6eb707ed08905757b1bb44b8f", + "sim_algo":"milenage", + "op": "1006020f0a478bf6b699f15c062e42b3", + + as_release: 15, + ue_category: "nr", + apn:"oai", + attach_pdn_type:"ipv4", + default_nssai: [ { sst: 1, }, ], + default_pdu_session_snssai: { sst: 1, }, + tun_setup_script: "ue-ifup", + }, + { + "ue_id" : 10, + "imsi": "001020000000010", + "K": "fec86ba6eb707ed08905757b1bb44b8f", + "sim_algo":"milenage", + "op": "1006020f0a478bf6b699f15c062e42b3", + + as_release: 15, + ue_category: "nr", + apn:"oai", + attach_pdn_type:"ipv4", + default_nssai: [ { sst: 1, }, ], + default_pdu_session_snssai: { sst: 1, }, + tun_setup_script: "ue-ifup", + }, + { + "ue_id" : 11, + "imsi": "001020000000011", + "K": "fec86ba6eb707ed08905757b1bb44b8f", + "sim_algo":"milenage", + "op": "1006020f0a478bf6b699f15c062e42b3", + + as_release: 15, + ue_category: "nr", + apn:"oai", + attach_pdn_type:"ipv4", + default_nssai: [ { sst: 1, }, ], + default_pdu_session_snssai: { sst: 1, }, + tun_setup_script: "ue-ifup", + }, + { + "ue_id" : 12, + "imsi": "001020000000012", + "K": "fec86ba6eb707ed08905757b1bb44b8f", + "sim_algo":"milenage", + "op": "1006020f0a478bf6b699f15c062e42b3", + + as_release: 15, + ue_category: "nr", + apn:"oai", + attach_pdn_type:"ipv4", + default_nssai: [ { sst: 1, }, ], + default_pdu_session_snssai: { sst: 1, }, + tun_setup_script: "ue-ifup", + }, + { + "ue_id" : 13, + "imsi": "001020000000013", + "K": "fec86ba6eb707ed08905757b1bb44b8f", + "sim_algo":"milenage", + "op": "1006020f0a478bf6b699f15c062e42b3", + + as_release: 15, + ue_category: "nr", + apn:"oai", + attach_pdn_type:"ipv4", + default_nssai: [ { sst: 1, }, ], + default_pdu_session_snssai: { sst: 1, }, + tun_setup_script: "ue-ifup", + }, + { + "ue_id" : 14, + "imsi": "001020000000014", + "K": "fec86ba6eb707ed08905757b1bb44b8f", + "sim_algo":"milenage", + "op": "1006020f0a478bf6b699f15c062e42b3", + + as_release: 15, + ue_category: "nr", + apn:"oai", + attach_pdn_type:"ipv4", + default_nssai: [ { sst: 1, }, ], + default_pdu_session_snssai: { sst: 1, }, + tun_setup_script: "ue-ifup", + }, + { + "ue_id" : 15, + "imsi": "001020000000015", + "K": "fec86ba6eb707ed08905757b1bb44b8f", + "sim_algo":"milenage", + "op": "1006020f0a478bf6b699f15c062e42b3", + + as_release: 15, + ue_category: "nr", + apn:"oai", + attach_pdn_type:"ipv4", + default_nssai: [ { sst: 1, }, ], + default_pdu_session_snssai: { sst: 1, }, + tun_setup_script: "ue-ifup", + }, + { + "ue_id" : 16, + "imsi": "001020000000016", + "K": "fec86ba6eb707ed08905757b1bb44b8f", + "sim_algo":"milenage", + "op": "1006020f0a478bf6b699f15c062e42b3", + + as_release: 15, + ue_category: "nr", + apn:"oai", + attach_pdn_type:"ipv4", + default_nssai: [ { sst: 1, }, ], + default_pdu_session_snssai: { sst: 1, }, + tun_setup_script: "ue-ifup", + }, + ], +} diff --git a/ci-scripts/as_ue/aw2s-multi-00102-2x2.cfg b/ci-scripts/as_ue/aw2s-multi-00102-2x2-v2.cfg similarity index 98% rename from ci-scripts/as_ue/aw2s-multi-00102-2x2.cfg rename to ci-scripts/as_ue/aw2s-multi-00102-2x2-v2.cfg index 04d2bb9ffd..b70ffbb0af 100644 --- a/ci-scripts/as_ue/aw2s-multi-00102-2x2.cfg +++ b/ci-scripts/as_ue/aw2s-multi-00102-2x2-v2.cfg @@ -5,6 +5,7 @@ { #define N_ANTENNA_DL 2 #define N_ANTENNA_UL 2 +#define DL_ARFCN 631296 #define TDD 1 log_options: "all.level=warn,all.max_size=0,nas.level=debug,nas.max_size=1,rrc.level=debug,rrc.max_size=1", @@ -25,8 +26,8 @@ allow dynamic UE creation from remote API */ rf_port: 0, bandwidth: 20, band: 78, - dl_nr_arfcn:630048, - ssb_nr_arfcn:630048, + dl_nr_arfcn: DL_ARFCN, + ssb_nr_arfcn: DL_ARFCN, subcarrier_spacing: 30, n_antenna_dl: N_ANTENNA_DL, n_antenna_ul: N_ANTENNA_UL, diff --git a/ci-scripts/ci_infra.yaml b/ci-scripts/ci_infra.yaml index 1bc26659c6..65c7c464b6 100644 --- a/ci-scripts/ci_infra.yaml +++ b/ci-scripts/ci_infra.yaml @@ -111,7 +111,11 @@ ltebox-nepes: amarisoft_ue: Host: amariue - InitScript: /root/lteue-linux-2023-10-27/ue/lteue /root/oaicicd/ran_sa_aw2s_asue_2x2/aw2s-multi-00102-2x2.cfg & + InitScript: /root/lteue-linux-2023-10-27/ue/lteue /root/oaicicd/ran_sa_aw2s_asue/aw2s-multi-00102-20.cfg & + TermScript: /root/2023-10-27/libs/ws.js -t 10 127.0.0.1:9002 '{"message":"quit"}' || killall -KILL lteue-avx2 +amarisoft_ue_2x2: + Host: amariue + InitScript: /root/lteue-linux-2023-10-27/ue/lteue /root/oaicicd/ran_sa_aw2s_asue_2x2/aw2s-multi-00102-2x2-v2.cfg & TermScript: /root/2023-10-27/libs/ws.js -t 10 127.0.0.1:9002 '{"message":"quit"}' || killall -KILL lteue-avx2 amarisoft_ue_fhi72: Host: amariue diff --git a/ci-scripts/conf_files/gnb.sa.band78.106prb.rfsim.yaml b/ci-scripts/conf_files/gnb.sa.band78.106prb.rfsim.yaml new file mode 100644 index 0000000000..acd9f271d3 --- /dev/null +++ b/ci-scripts/conf_files/gnb.sa.band78.106prb.rfsim.yaml @@ -0,0 +1,208 @@ +Active_gNBs: + - gnb-rfsim +# Asn1_verbosity, choice in: none, info, annoying +Asn1_verbosity: none +gNBs: + ##### Identification parameters: + - gNB_ID: 0xe00 + gNB_name: gnb-rfsim + tracking_area_code: 1 + plmn_list: + - mcc: 208 + mnc: 99 + mnc_length: 2 + snssaiList: + - sst: 1 + sd: 0xffffff + nr_cellid: 12345678 + ##### Physical parameters: + min_rxtxtime: 6 + servingCellConfigCommon: + #spCellConfigCommon + - physCellId: 0 + # downlinkConfigCommon + #frequencyInfoDL + # this is 3300.60 MHz + 53*12*30e-3 MHz = 3319.68 + absoluteFrequencySSB: 621312 + # this is 3300.60 MHz + dl_absoluteFrequencyPointA: 620040 + #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=0,L=106 (275*(L-1))+RBstart + initialDLBWPlocationAndBandwidth: 28875 + # 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: 12 + preambleReceivedTargetPower: -104 + #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: 5 + #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: 3 + #oneHalf (0..15) 4,8,12,16,...60,64 + ssb_perRACH_OccasionAndCB_PreamblesPerSSB: 15 + #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_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: + SCTP_INSTREAMS: 2 + SCTP_OUTSTREAMS: 2 + + ##### AMF parameters: + amf_ip_address: + - ipv4: 192.168.71.132 + + NETWORK_INTERFACES: + GNB_IPV4_ADDRESS_FOR_NG_AMF: 192.168.71.140 + GNB_IPV4_ADDRESS_FOR_NGU: 192.168.71.140 + GNB_PORT_FOR_S1U: 2152 # Spec 2152 + + +MACRLCs: + - num_cc: 1 + tr_s_preference: local_L1 + tr_n_preference: local_RRC + pusch_TargetSNRx10: 200 + pucch_TargetSNRx10: 200 + +L1s: + - num_cc: 1 + tr_n_preference: local_mac + prach_dtx_threshold: 200 + # pucch0_dtx_threshold = 150; + +RUs: + - local_rf: yes + nb_tx: 1 + nb_rx: 1 + att_tx: 0 + att_rx: 0 + bands: [78] + max_pdschReferenceSignalPower: -27 + max_rxgain: 75 + eNB_instances: [0] + ##beamforming 1x2 matrix: 1 layer x 2 antennas + bf_weights: [0x00007fff, 0x0000] + ##beamforming 1x4 matrix: 1 layer x 4 antennas + #bf_weights = [0x00007fff, 0x0000,0x0000, 0x0000]; + ## beamforming 2x2 matrix: + # bf_weights = [0x00007fff, 0x00000000, 0x00000000, 0x00007fff]; + ## beamforming 4x4 matrix: + #bf_weights = [0x00007fff, 0x0000, 0x0000, 0x0000, 0x00000000, 0x00007fff, 0x0000, 0x0000, 0x0000, 0x0000, 0x00007fff, 0x0000, 0x0000, 0x0000, 0x0000, 0x00007fff]; + sf_extension: 0 + sdr_addrs: serial=XXXXXXX + +rfsimulator: + serveraddr: server + +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: info + pdcp_log_level: info + rrc_log_level: info + ngap_log_level: debug + f1ap_log_level: debug diff --git a/ci-scripts/conf_files/gnb.sa.band78.51prb.aw2s.ddsuu.2x2.conf b/ci-scripts/conf_files/gnb.sa.band78.51prb.aw2s.ddsuu.2x2.conf new file mode 100644 index 0000000000..a32aec583a --- /dev/null +++ b/ci-scripts/conf_files/gnb.sa.band78.51prb.aw2s.ddsuu.2x2.conf @@ -0,0 +1,272 @@ +Active_gNBs = ( "gNB-Eurecom-n78_20"); +# Asn1_verbosity, choice in: none, info, annoying +Asn1_verbosity = "none"; + +#device :{ +# name = "aw2sori_transpro"; +#} + +gNBs = +( + { + ////////// Identification parameters: + gNB_ID = 0xe00; + + gNB_name = "gNB-Eurecom-n78_20"; + + // Tracking area code, 0x0000 and 0xfffe are reserved values + tracking_area_code = 0x1; + plmn_list = ({ mcc = 001; mnc = 02; mnc_length = 2; snssaiList = ({ sst =0x1; }) }); + + nr_cellid = 12345678L + + ////////// Physical parameters: + pdsch_AntennaPorts_XP = 2; + pusch_AntennaPorts = 2; + do_CSIRS = 1; + do_SRS = 1; + + servingCellConfigCommon = ( + { + #spCellConfigCommon + + physCellId = 0; + +# downlinkConfigCommon + #frequencyInfoDL + # this is 3469.44 MHz => 301 REs from PointA 25 PRBs + 1 RE + absoluteFrequencySSB = 631296; + dl_frequencyBand = 78; + # this is 3469.44 - (51*12*30e-3/2) = 3460.26 MHz + dl_absoluteFrequencyPointA = 630684; + #scs-SpecificCarrierList + dl_offstToCarrier = 0; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + dl_subcarrierSpacing = 1; + dl_carrierBandwidth = 51; + #initialDownlinkBWP + #genericParameters + # this is RBstart=0,L=50 (275*(L-1))+RBstart + initialDLBWPlocationAndBandwidth = 13750; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + initialDLBWPsubcarrierSpacing = 1; + #pdcch-ConfigCommon + initialDLBWPcontrolResourceSetZero = 11; # this means shift of 14, so Coreset is in PRBs 1..48, SSB starts at PRB 15 + initialDLBWPsearchSpaceZero = 0; + #pdsch-ConfigCommon + + #uplinkConfigCommon + #frequencyInfoUL + ul_frequencyBand = 78; + #scs-SpecificCarrierList + ul_offstToCarrier = 0; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + ul_subcarrierSpacing = 1; + ul_carrierBandwidth = 51; + pMax = 20; + #initialUplinkBWP + #genericParameters + initialULBWPlocationAndBandwidth = 13750; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + initialULBWPsubcarrierSpacing = 1; + #rach-ConfigCommon + #rach-ConfigGeneric + prach_ConfigurationIndex = 100; +#prach_msg1_FDM +#0 = one, 1=two, 2=four, 3=eight + prach_msg1_FDM = 0; + prach_msg1_FrequencyStart = 0; + zeroCorrelationZoneConfig = 15; + preambleReceivedTargetPower = -104; +#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 = 3; +#oneHalf (0..15) 4,8,12,16,...60,64 + ssb_perRACH_OccasionAndCB_PreamblesPerSSB = 15; +#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 =-96; + +# pucch-ConfigCommon setup : +# pucchGroupHopping +# 0 = neither, 1= group hopping, 2=sequence hopping + pucchGroupHopping = 0; + hoppingId = 40; + p0_nominal = -96; + + 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 = 5; + nrofDownlinkSlots = 2; + nrofDownlinkSymbols = 6; + nrofUplinkSlots = 2; + nrofUplinkSymbols = 4; + + ssPBCH_BlockPower = -10; + } + + ); + + + # ------- SCTP definitions + SCTP : + { + # Number of streams to use in input/output + SCTP_INSTREAMS = 2; + SCTP_OUTSTREAMS = 2; + }; + + + ////////// AMF parameters: + amf_ip_address = ({ ipv4 = "172.21.6.100"; }); + + NETWORK_INTERFACES : + { + + GNB_IPV4_ADDRESS_FOR_NG_AMF = "172.21.16.124/20"; + GNB_IPV4_ADDRESS_FOR_NGU = "172.21.16.124/20"; + GNB_PORT_FOR_S1U = 2152; # Spec 2152 + }; + } +); + +MACRLCs = ( + { + num_cc = 1; + tr_s_preference = "local_L1"; + tr_n_preference = "local_RRC"; + pusch_TargetSNRx10 = 200; + pucch_TargetSNRx10 = 200; + } +); + +L1s = ( + { + num_cc = 1; + tr_n_preference = "local_mac"; + prach_dtx_threshold = 120; + pucch0_dtx_threshold = 50; + pusch_dtx_threshold = 10; + } +); + +RUs = ( + { + local_if_name = "ens7f3"; + remote_address = "192.168.80.239"; + local_address = "192.168.80.24"; + local_portc = 50000; + remote_portc = 55444; + local_portd = 52001; + remote_portd = 52183; + local_rf = "no" + tr_preference = "udp_ecpri_if5" + nb_tx = 2 + nb_rx = 2 + att_tx = 18 + att_rx = 0; + num_tp_cores = 4; + rxfh_core_id = 9; + txfh_core_id = 10; + tp_cores = [11,12,13,14]; + nr_flag = 1; + eNB_instances = [0]; + bands = [78]; + sl_ahead = 5; + ##beamforming 1x2 matrix: 1 layer x 2 antennas + bf_weights = [0x00007fff, 0x0000]; + ##beamforming 1x4 matrix: 1 layer x 4 antennas + #bf_weights = [0x00007fff, 0x0000,0x0000, 0x0000]; + ## beamforming 2x2 matrix: + # bf_weights = [0x00007fff, 0x00000000, 0x00000000, 0x00007fff]; + ## beamforming 4x4 matrix: + #bf_weights = [0x00007fff, 0x0000, 0x0000, 0x0000, 0x00000000, 0x00007fff, 0x0000, 0x0000, 0x0000, 0x0000, 0x00007fff, 0x0000, 0x0000, 0x0000, 0x0000, 0x00007fff]; + } +); + + +security = { + # preferred ciphering algorithms + # the first one of the list that an UE supports in chosen + # valid values: nea0, nea1, nea2, nea3 + ciphering_algorithms = ( "nea2", "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 = "yes"; +}; + + log_config : + { + global_log_level ="info"; + global_log_verbosity ="medium"; + hw_log_level ="info"; + hw_log_verbosity ="medium"; + phy_log_level ="info"; + phy_log_verbosity ="medium"; + mac_log_level ="info"; + mac_log_verbosity ="high"; + rlc_log_level ="info"; + rlc_log_verbosity ="medium"; + pdcp_log_level ="info"; + pdcp_log_verbosity ="medium"; + rrc_log_level ="info"; + rrc_log_verbosity ="medium"; + f1ap_log_level ="debug"; + f1ap_log_verbosity ="medium"; + ngap_log_level ="debug"; + ngap_log_verbosity ="medium"; + }; + diff --git a/ci-scripts/conf_files/gnb.sa.band78.51prb.aw2s.ddsuu.conf b/ci-scripts/conf_files/gnb.sa.band78.51prb.aw2s.ddsuu.conf index 4cc3c2be2b..9ee7787eed 100644 --- a/ci-scripts/conf_files/gnb.sa.band78.51prb.aw2s.ddsuu.conf +++ b/ci-scripts/conf_files/gnb.sa.band78.51prb.aw2s.ddsuu.conf @@ -21,10 +21,10 @@ gNBs = nr_cellid = 12345678L ////////// Physical parameters: - pdsch_AntennaPorts_XP = 2; - pusch_AntennaPorts = 2; + pdsch_AntennaPorts_XP = 1; + pusch_AntennaPorts = 1; do_CSIRS = 1; - do_SRS = 1; + do_SRS = 0; servingCellConfigCommon = ( { @@ -34,11 +34,11 @@ gNBs = # downlinkConfigCommon #frequencyInfoDL - # this is 3410.4 MHz => 301 REs from PointA 25 PRBs + 1 RE - absoluteFrequencySSB = 630048; + # this is 3469.44 MHz => 301 REs from PointA 25 PRBs + 1 RE + absoluteFrequencySSB = 631296; dl_frequencyBand = 78; - # this is 3410.4 - (51*12*30e-3/2) = 3401.22 MHz - dl_absoluteFrequencyPointA = 629436; + # this is 3469.44 - (51*12*30e-3/2) = 3460.26 MHz + dl_absoluteFrequencyPointA = 630684; #scs-SpecificCarrierList dl_offstToCarrier = 0; # subcarrierSpacing @@ -207,8 +207,8 @@ RUs = ( remote_portd = 52183; local_rf = "no" tr_preference = "udp_ecpri_if5" - nb_tx = 2 - nb_rx = 2 + nb_tx = 1 + nb_rx = 1 att_tx = 18 att_rx = 0; num_tp_cores = 4; diff --git a/ci-scripts/xml_files/container_sa_aw2s_asue.xml b/ci-scripts/xml_files/container_sa_aw2s_asue.xml index 71789cca52..f023da8402 100644 --- a/ci-scripts/xml_files/container_sa_aw2s_asue.xml +++ b/ci-scripts/xml_files/container_sa_aw2s_asue.xml @@ -24,55 +24,64 @@ TEST-5G-AW2S 20 MHz TDD SA tasks + 1 - 010000 - 001000 - 800813 - 020000 - 002000 - 002001 - 002002 - 002003 - 002004 - 002005 - 002006 - 002007 - 002008 - 002009 - 002010 - 002011 - 002012 - 002013 - 002014 - 002015 - 000100 - 000010 - 000020 - 000030 - 000040 - 002016 - 000200 - 003000 - 004000 - 000002 - 030000 - 333333 + 110000 + 101000 + 100813 + 120000 + 102000 + 102001 + 102002 + 102003 + 102004 + 102005 + 102006 + 102007 + 102008 + 102009 + 102010 + 102011 + 102012 + 102013 + 102014 + 102015 + 100100 + 100010 + 100020 + 100030 + 100040 + 102016 + 100200 + 103000 + 104000 + 100002 + 130000 + 444444 - + Pull_Cluster_Image Pull Images from Cluster oaicicd-ran oai-gnb-aw2s - + + + Initialize_UE + Initialize Amarisoft UE + amarisoft_ue + + + Create_Workspace - Create new Workspace + Creating new Workspace 0 0 - + + Deploy_Object Deploy gNB (TDD/Band78/20MHz/aw2s) in a container ci-scripts/yaml_files/sa_aw2s_gnb @@ -80,106 +89,100 @@ 0 - - Initialize_UE - Initialize Amarisoft UE - amarisoft_ue - - - + Attach_UE Attach UE amarisoft_ue_1 - + Attach_UE Attach UE amarisoft_ue_2 - + Attach_UE Attach UE amarisoft_ue_3 - + Attach_UE Attach UE amarisoft_ue_4 - + Attach_UE Attach UE amarisoft_ue_5 - + Attach_UE Attach UE amarisoft_ue_6 - + Attach_UE Attach UE amarisoft_ue_7 - + Attach_UE Attach UE amarisoft_ue_8 - + Attach_UE Attach UE amarisoft_ue_9 - + Attach_UE Attach UE amarisoft_ue_10 - + Attach_UE Attach UE amarisoft_ue_11 - + Attach_UE Attach UE amarisoft_ue_12 - + Attach_UE Attach UE amarisoft_ue_13 - + Attach_UE Attach UE amarisoft_ue_14 - + Attach_UE Attach UE amarisoft_ue_15 - + Iperf - iperf (DL/7Mbps/UDP)(30 sec)(multi-ue profile) - -u -b 70M -t 30 -R + iperf (DL/3Mbps/UDP)(30 sec)(multi-ue profile) + -u -b 45M -t 30 -R amarisoft_ue_1 amarisoft_ue_2 amarisoft_ue_3 amarisoft_ue_4 amarisoft_ue_5 amarisoft_ue_6 amarisoft_ue_7 amarisoft_ue_8 amarisoft_ue_9 amarisoft_ue_10 amarisoft_ue_11 amarisoft_ue_12 amarisoft_ue_13 amarisoft_ue_14 amarisoft_ue_15 25 80 @@ -187,19 +190,19 @@ oc-cn5g - + Iperf iperf (DL/TCP)(30 sec)(multi-ue profile) -t 30 -R amarisoft_ue_1 amarisoft_ue_2 amarisoft_ue_3 amarisoft_ue_4 amarisoft_ue_5 amarisoft_ue_6 amarisoft_ue_7 amarisoft_ue_8 amarisoft_ue_9 amarisoft_ue_10 amarisoft_ue_11 amarisoft_ue_12 amarisoft_ue_13 amarisoft_ue_14 amarisoft_ue_15 - 4 + 2 oc-cn5g - + Iperf - iperf (UL/3.6Mbps/UDP)(30 sec)(multi-ue profile) - -u -b 36M -t 30 + iperf (UL/1Mbps/UDP)(30 sec)(multi-ue profile) + -u -b 15M -t 30 amarisoft_ue_1 amarisoft_ue_2 amarisoft_ue_3 amarisoft_ue_4 amarisoft_ue_5 amarisoft_ue_6 amarisoft_ue_7 amarisoft_ue_8 amarisoft_ue_9 amarisoft_ue_10 amarisoft_ue_11 amarisoft_ue_12 amarisoft_ue_13 amarisoft_ue_14 amarisoft_ue_15 25 80 @@ -207,7 +210,7 @@ oc-cn5g - + Iperf iperf (UL/TCP)(30 sec)(multi-ue profile) -t 30 @@ -217,51 +220,51 @@ oc-cn5g - + Ping - Ping: 20pings in 20sec, multi-ue + Ping: 50 pings in 10sec, multi-ue amarisoft_ue_1 amarisoft_ue_2 amarisoft_ue_3 amarisoft_ue_4 amarisoft_ue_5 amarisoft_ue_6 amarisoft_ue_7 amarisoft_ue_8 amarisoft_ue_9 amarisoft_ue_10 amarisoft_ue_11 amarisoft_ue_12 amarisoft_ue_13 amarisoft_ue_14 amarisoft_ue_15 - -c 20 %cn_ip% + -c 50 -i 0.2 %cn_ip% 5 25 - + Attach_UE Attach UE amarisoft_ue_16 - + Ping Ping: 50pings in 10sec, multi-ue amarisoft_ue_16 -c 50 -i 0.2 %cn_ip% - 1 + 5 30 - + Detach_UE true Detach UE amarisoft_ue_1 amarisoft_ue_2 amarisoft_ue_3 amarisoft_ue_4 amarisoft_ue_5 amarisoft_ue_6 amarisoft_ue_7 amarisoft_ue_8 amarisoft_ue_9 amarisoft_ue_10 amarisoft_ue_11 amarisoft_ue_12 amarisoft_ue_13 amarisoft_ue_14 amarisoft_ue_15 amarisoft_ue_16 - + Terminate_UE true Terminate UE amarisoft_ue - + IdleSleep Sleep 5 - + Undeploy_Object true Undeploy gNB @@ -270,7 +273,7 @@ 0 - + Clean_Test_Server_Images true Clean Test Images on Test Server diff --git a/ci-scripts/xml_files/container_sa_aw2s_asue_2x2.xml b/ci-scripts/xml_files/container_sa_aw2s_asue_2x2.xml new file mode 100644 index 0000000000..5d43c89c3c --- /dev/null +++ b/ci-scripts/xml_files/container_sa_aw2s_asue_2x2.xml @@ -0,0 +1,280 @@ + + + TEST-5G-2x2-AW2S + 20 MHz TDD 2x2 SA + tasks + + 010000 + 001000 + 800813 + 020000 + 002000 + 002001 + 002002 + 002003 + 002004 + 002005 + 002006 + 002007 + 002008 + 002009 + 002010 + 002011 + 002012 + 002013 + 002014 + 002015 + 000100 + 000010 + 000020 + 000030 + 000040 + 002016 + 000200 + 003000 + 004000 + 000002 + 030000 + 333333 + + + + + Pull_Cluster_Image + Pull Images from Cluster + oaicicd-ran + oai-gnb-aw2s + + + Create_Workspace + Create new Workspace + 0 + 0 + + + Deploy_Object + Deploy gNB (TDD/Band78/20MHz/aw2s) in a container + ci-scripts/yaml_files/sa_aw2s_2x2_gnb + 0 + 0 + + + + Initialize_UE + Initialize Amarisoft UE + amarisoft_ue_2x2 + + + + Attach_UE + Attach UE + amarisoft_ue_1 + + + + Attach_UE + Attach UE + amarisoft_ue_2 + + + + Attach_UE + Attach UE + amarisoft_ue_3 + + + + Attach_UE + Attach UE + amarisoft_ue_4 + + + + Attach_UE + Attach UE + amarisoft_ue_5 + + + + Attach_UE + Attach UE + amarisoft_ue_6 + + + + Attach_UE + Attach UE + amarisoft_ue_7 + + + + Attach_UE + Attach UE + amarisoft_ue_8 + + + + Attach_UE + Attach UE + amarisoft_ue_9 + + + + Attach_UE + Attach UE + amarisoft_ue_10 + + + + Attach_UE + Attach UE + amarisoft_ue_11 + + + + Attach_UE + Attach UE + amarisoft_ue_12 + + + + Attach_UE + Attach UE + amarisoft_ue_13 + + + + Attach_UE + Attach UE + amarisoft_ue_14 + + + + Attach_UE + Attach UE + amarisoft_ue_15 + + + + Iperf + iperf (DL/4Mbps/UDP)(30 sec)(multi-ue profile) + -u -b 60M -t 30 -R + amarisoft_ue_1 amarisoft_ue_2 amarisoft_ue_3 amarisoft_ue_4 amarisoft_ue_5 amarisoft_ue_6 amarisoft_ue_7 amarisoft_ue_8 amarisoft_ue_9 amarisoft_ue_10 amarisoft_ue_11 amarisoft_ue_12 amarisoft_ue_13 amarisoft_ue_14 amarisoft_ue_15 + 25 + 80 + balanced + oc-cn5g + + + + Iperf + iperf (DL/TCP)(30 sec)(multi-ue profile) + -t 30 -R + amarisoft_ue_1 amarisoft_ue_2 amarisoft_ue_3 amarisoft_ue_4 amarisoft_ue_5 amarisoft_ue_6 amarisoft_ue_7 amarisoft_ue_8 amarisoft_ue_9 amarisoft_ue_10 amarisoft_ue_11 amarisoft_ue_12 amarisoft_ue_13 amarisoft_ue_14 amarisoft_ue_15 + 4 + oc-cn5g + + + + Iperf + iperf (UL/1.5Mbps/UDP)(30 sec)(multi-ue profile) + -u -b 22.5M -t 30 + amarisoft_ue_1 amarisoft_ue_2 amarisoft_ue_3 amarisoft_ue_4 amarisoft_ue_5 amarisoft_ue_6 amarisoft_ue_7 amarisoft_ue_8 amarisoft_ue_9 amarisoft_ue_10 amarisoft_ue_11 amarisoft_ue_12 amarisoft_ue_13 amarisoft_ue_14 amarisoft_ue_15 + 25 + 80 + balanced + oc-cn5g + + + + Iperf + iperf (UL/TCP)(30 sec)(multi-ue profile) + -t 30 + oc-cn5g + amarisoft_ue_1 amarisoft_ue_2 amarisoft_ue_3 amarisoft_ue_4 amarisoft_ue_5 amarisoft_ue_6 amarisoft_ue_7 amarisoft_ue_8 amarisoft_ue_9 amarisoft_ue_10 amarisoft_ue_11 amarisoft_ue_12 amarisoft_ue_13 amarisoft_ue_14 amarisoft_ue_15 + 1 + oc-cn5g + + + + Ping + Ping: 20pings in 20sec, multi-ue + amarisoft_ue_1 amarisoft_ue_2 amarisoft_ue_3 amarisoft_ue_4 amarisoft_ue_5 amarisoft_ue_6 amarisoft_ue_7 amarisoft_ue_8 amarisoft_ue_9 amarisoft_ue_10 amarisoft_ue_11 amarisoft_ue_12 amarisoft_ue_13 amarisoft_ue_14 amarisoft_ue_15 + -c 20 %cn_ip% + 5 + 25 + + + + Attach_UE + Attach UE + amarisoft_ue_16 + + + + Ping + Ping: 50pings in 10sec, multi-ue + amarisoft_ue_16 + -c 50 -i 0.2 %cn_ip% + 5 + 30 + + + + Detach_UE + true + Detach UE + amarisoft_ue_1 amarisoft_ue_2 amarisoft_ue_3 amarisoft_ue_4 amarisoft_ue_5 amarisoft_ue_6 amarisoft_ue_7 amarisoft_ue_8 amarisoft_ue_9 amarisoft_ue_10 amarisoft_ue_11 amarisoft_ue_12 amarisoft_ue_13 amarisoft_ue_14 amarisoft_ue_15 amarisoft_ue_16 + + + + Terminate_UE + true + Terminate UE + amarisoft_ue_2x2 + + + + IdleSleep + Sleep + 5 + + + + Undeploy_Object + true + Undeploy gNB + ci-scripts/yaml_files/sa_aw2s_2x2_gnb + 0 + 0 + + + + Clean_Test_Server_Images + true + Clean Test Images on Test Server + 0 + + + diff --git a/ci-scripts/yaml_files/5g_rfsimulator/docker-compose.yaml b/ci-scripts/yaml_files/5g_rfsimulator/docker-compose.yaml index 4e7001638f..448bf45dc4 100644 --- a/ci-scripts/yaml_files/5g_rfsimulator/docker-compose.yaml +++ b/ci-scripts/yaml_files/5g_rfsimulator/docker-compose.yaml @@ -94,7 +94,7 @@ services: public_net: ipv4_address: 192.168.71.140 volumes: - - ../../conf_files/gnb.sa.band78.106prb.rfsim.conf:/opt/oai-gnb/etc/gnb.conf + - ../../conf_files/gnb.sa.band78.106prb.rfsim.yaml:/opt/oai-gnb/etc/gnb.yaml healthcheck: test: /bin/bash -c "pgrep nr-softmodem" interval: 10s diff --git a/ci-scripts/yaml_files/5g_rfsimulator_e1/docker-compose.yaml b/ci-scripts/yaml_files/5g_rfsimulator_e1/docker-compose.yaml index 8c937ed76c..c5d4d3aa61 100644 --- a/ci-scripts/yaml_files/5g_rfsimulator_e1/docker-compose.yaml +++ b/ci-scripts/yaml_files/5g_rfsimulator_e1/docker-compose.yaml @@ -289,7 +289,7 @@ services: USE_ADDITIONAL_OPTIONS: --sa --rfsim --log_config.global_log_options level,nocolor,time -r 106 --numerology 1 -C 3619200000 --uicc0.imsi 208990100001100 - --rfsimulator.serveraddr 192.168.78.2 + --rfsimulator.serveraddr oai-du depends_on: - oai-du networks: diff --git a/ci-scripts/yaml_files/sa_aw2s_2x2_gnb/docker-compose.yml b/ci-scripts/yaml_files/sa_aw2s_2x2_gnb/docker-compose.yml new file mode 100644 index 0000000000..d1f5ae2475 --- /dev/null +++ b/ci-scripts/yaml_files/sa_aw2s_2x2_gnb/docker-compose.yml @@ -0,0 +1,22 @@ +services: + oai-gnb: + image: ${REGISTRY:-oaisoftwarealliance}/oai-gnb-aw2s:${TAG:-develop} + network_mode: "host" + container_name: oai-gnb-aw2s + cap_drop: + - ALL + cap_add: + - SYS_NICE + - IPC_LOCK + ulimits: + core: -1 # for core dumps + environment: + TZ: Europe/Paris + USE_ADDITIONAL_OPTIONS: --sa + volumes: + - ../../conf_files/gnb.sa.band78.51prb.aw2s.ddsuu.2x2.conf:/opt/oai-gnb-aw2s/etc/gnb.conf + healthcheck: + test: /bin/bash -c "pgrep nr-softmodem" + interval: 10s + timeout: 5s + retries: 5 diff --git a/openair2/F1AP/f1ap_du_system_information.h b/common/5g_platform_types.h similarity index 81% rename from openair2/F1AP/f1ap_du_system_information.h rename to common/5g_platform_types.h index b6bbedba2f..05fc2be28d 100644 --- a/openair2/F1AP/f1ap_du_system_information.h +++ b/common/5g_platform_types.h @@ -19,13 +19,16 @@ * contact@openairinterface.org */ -/*! \file f1ap_du_interface_management.h - * \brief f1ap interface management for DU - * \author EURECOM/NTUST - * \date 2018 - * \version 0.1 - * \company Eurecom - * \email: navid.nikaein@eurecom.fr, bing-kai.hong@eurecom.fr - * \note - * \warning - */ \ No newline at end of file +#ifndef FIVEG_PLATFORM_TYPES_H__ +#define FIVEG_PLATFORM_TYPES_H__ + +#include + +typedef struct nssai_s { + uint8_t sst; + uint32_t sd; +} nssai_t; + +typedef enum { NON_DYNAMIC, DYNAMIC } fiveQI_t; + +#endif diff --git a/common/ngran_types.h b/common/ngran_types.h index 37a6ea9177..ac5af71f23 100644 --- a/common/ngran_types.h +++ b/common/ngran_types.h @@ -55,5 +55,4 @@ typedef enum { CPtype = 0, UPtype } E1_t; #define NODE_IS_MBMS(nOdE_TyPe) ((nOdE_TyPe) == ngran_eNB_MBMS_STA) #define GTPV1_U_PORT_NUMBER (2152) -typedef enum { non_dynamic, dynamic } fiveQI_type_t; #endif diff --git a/common/utils/utils.h b/common/utils/utils.h index 082d1dd635..841cb2af9c 100644 --- a/common/utils/utils.h +++ b/common/utils/utils.h @@ -75,7 +75,7 @@ static inline void *calloc_or_fail(size_t nmemb, size_t size) if (ptr == NULL) { fprintf(stderr, "Failed to calloc() %zu elements of %zu bytes: out of memory", nmemb, size); - exit(EXIT_FAILURE); + abort(); } return ptr; diff --git a/doc/E1AP/E1-design.md b/doc/E1AP/E1-design.md index 04d19bb514..4dd042f87d 100644 --- a/doc/E1AP/E1-design.md +++ b/doc/E1AP/E1-design.md @@ -79,7 +79,7 @@ More details about the E1AP procedures in OAI are available in this document: [E # 2. Running the E1 Split -The setup is assuming that all modules are running on the same machine. The user can refer to the [F1 design document](./../F1-design.md) for local deployment of the DU. +The setup is assuming that all modules are running on the same machine. The user can refer to the [F1 design document](./../F1AP/F1-design.md) for local deployment of the DU. ## 2.1 Configuration File diff --git a/doc/F1-design.md b/doc/F1AP/F1-design.md similarity index 100% rename from doc/F1-design.md rename to doc/F1AP/F1-design.md diff --git a/doc/F1AP/F1AP-lib.md b/doc/F1AP/F1AP-lib.md new file mode 100644 index 0000000000..46712914ed --- /dev/null +++ b/doc/F1AP/F1AP-lib.md @@ -0,0 +1,69 @@ + + + + + + + + + + F1AP Messages Encoding & Decoding Library + + + + +[[_TOC_]] + + +# Intro + +This library is for the encoding, decoding and testing of F1AP (F1 Application Protocol) messages. + +# Implementation Details + +The library includes the following components: + +1. **Common Functions**: + +This file [f1ap_lib_common.c](../../openair2/F1AP/lib/f1ap_lib_common.c) and its corresponding header contain utility functions and macros shared across different F1AP functions. + +2. **Message-Specific Modules**: + +Each F1AP message (e.g., DL RRC, UL RRC, etc.) has its corresponding modules and each module will include the encoder, decoder, equality check, and memory management functions specific to that message type. Specifically, the goal is to achieve the following: + +* **Encoder & Decoder**: Implement encoding and decoding functions for each F1AP message. These functions will convert F1AP messages coming from upper or lower layers into an F1AP PDU to be sent over F1 interface. +* **Equality Check (eq_X)**: `eq_X()` function that compares two messages for equality. This function is useful for testing purposes, ensuring that encoded and decoded messages match. +* **Deep Copy (cp_X)**: `cp_X()` function that performs a deep copy of a message. This function is beneficial when sending ITTI messages, as it avoids manual copying. +* **Memory Management (free_X)**: `free_X()` function to release memory associated with a message. Proper memory management helps prevent memory leaks. + +e.g. The following module contains functions that performs the encoding/decoding, equality check, deep copy and memory management for DL/UL RRC message transfer: + +* [f1ap_rrc_message_transfer.c](../../openair2/F1AP/lib/f1ap_rrc_message_transfer.c) + +# Testing + +The functions in the file [f1ap_lib_common.c](../../openair2/F1AP/tests/f1ap_lib_test.c) are used to test F1AP message encoding and decoding functionalities, according to the following steps: + +* call the encoder function for the message to be transferred into a F1AP PDU +* use `f1ap_encode_decode` to perform the following steps: + - Validates the input encoded PDU against constraints. + - Encodes the PDU using APER into a binary buffer. + - Decodes the binary buffer back into a PDU. + - Returns the decoded PDU. +* call the decoder function for the decoded F1AP PDU to obtain the decoded message +* call `eq_dl_rrc_message_transfer` to compare the original message with the decoded one +* call `cp_dl_rrc_message_transfer` to deep copy the original message, then compare the with the original one +* free all messages and PDUs + +A flowchart for a function testing F1AP messages, such as `test_f1ap_setup_request`, would look like this: + +```mermaid +flowchart TD + create[Create F1AP message]-->|f1ap_setup_req_t msg|enc[encode_f1ap_setup_request] + enc-->|F1AP_F1AP_PDU_t *f1enc|encdec[f1ap_encode_decode] + encdec-->|F1AP_F1AP_PDU_t *f1dec|dec[decode_f1ap_setup_request] + create-->|f1ap_setup_req_t msg|eq + dec-->|f1ap_setup_req_t decoded|eq[eq_f1ap_setup_request] + create-->|f1ap_setup_req_t msg|cp[cp_f1ap_setup_request] + cp-->|f1ap_setup_req_t cp|eq[eq_f1ap_setup_request] +``` diff --git a/doc/README.md b/doc/README.md index 70e8bf05be..7f57a24eb0 100644 --- a/doc/README.md +++ b/doc/README.md @@ -65,7 +65,7 @@ Legacy unmaintained files: - General software architecture notes: [SW_archi.md](./SW_archi.md) - [Information on E1](./E1AP/E1-design.md) -- [Information on F1](./F1-design.md) +- [Information on F1](./F1AP/F1-design.md) - [Information on how NR nFAPI works](./NR_NFAPI_archi.md) - [Flow graph of the L1 in gNB](SW-archi-graph.md) - [L1 threads in NR-UE](./nr-ue-design.md) diff --git a/doc/UnitTests.md b/doc/UnitTests.md index aa6b7b1123..76cfe7bee1 100644 --- a/doc/UnitTests.md +++ b/doc/UnitTests.md @@ -24,6 +24,10 @@ cmake .. -GNinja -DENABLE_TESTS=ON ninja tests ``` +The user can use either `ninja` or `make`. + +# Run unit tests + Then, you can run `ctest` to run all tests: ```bash diff --git a/docker/Dockerfile.gNB.aerial.ubuntu22 b/docker/Dockerfile.gNB.aerial.ubuntu22 index dcfe005caa..7440dfc9e8 100644 --- a/docker/Dockerfile.gNB.aerial.ubuntu22 +++ b/docker/Dockerfile.gNB.aerial.ubuntu22 @@ -78,7 +78,8 @@ RUN apt-get update && \ iputils-ping \ gdb \ moreutils \ - libusb-1.0-0 && \ + libusb-1.0-0 \ + libyaml-cpp-dev && \ rm -rf /var/lib/apt/lists/* WORKDIR /opt/oai-gnb/bin @@ -86,7 +87,10 @@ COPY --from=ran-build \ /oai-ran/cmake_targets/ran_build/build/nr-softmodem ./ COPY ./docker/scripts/gnb_entrypoint.sh ./entrypoint.sh -COPY --from=ran-build /oai-ran/cmake_targets/ran_build/build/libparams_libconfig.so /usr/local/lib/ +COPY --from=ran-build \ + /oai-ran/cmake_targets/ran_build/build/libparams_libconfig.so \ + /oai-ran/cmake_targets/ran_build/build/libparams_yaml.so \ + /usr/local/lib/ #copy files from nvIPC COPY --from=ran-build \ @@ -107,4 +111,4 @@ RUN ldconfig && \ WORKDIR /opt/oai-gnb COPY --from=ran-build /tini /tini ENTRYPOINT ["/tini", "-v", "--", "/opt/oai-gnb/bin/entrypoint.sh"] -CMD ["/opt/oai-gnb/bin/nr-softmodem", "-O", "/opt/oai-gnb/etc/gnb.conf"] +CMD ["/opt/oai-gnb/bin/nr-softmodem"] diff --git a/docker/Dockerfile.gNB.aerial.ubuntu22.sanitize-address b/docker/Dockerfile.gNB.aerial.ubuntu22.sanitize-address index 62c7de33d6..4d613718b4 100644 --- a/docker/Dockerfile.gNB.aerial.ubuntu22.sanitize-address +++ b/docker/Dockerfile.gNB.aerial.ubuntu22.sanitize-address @@ -78,7 +78,8 @@ RUN apt-get update && \ iputils-ping \ gdb \ moreutils \ - libusb-1.0-0 && \ + libusb-1.0-0 \ + libyaml-cpp-dev && \ rm -rf /var/lib/apt/lists/* WORKDIR /opt/oai-gnb/bin @@ -92,6 +93,7 @@ COPY --from=ran-build \ /oai-ran/cmake_targets/ran_build/build/libparams_libconfig.so \ /oai-ran/cmake_targets/ran_build/build/libdfts.so \ /oai-ran/cmake_targets/ran_build/build/libldpc*.so \ + /oai-ran/cmake_targets/ran_build/build/libparams_yaml.so \ /usr/local/lib/ #copy files from nvIPC @@ -113,4 +115,4 @@ RUN ldconfig && \ WORKDIR /opt/oai-gnb COPY --from=ran-build /tini /tini ENTRYPOINT ["/tini", "-v", "--", "/opt/oai-gnb/bin/entrypoint.sh"] -CMD ["/opt/oai-gnb/bin/nr-softmodem", "-O", "/opt/oai-gnb/etc/gnb.conf"] +CMD ["/opt/oai-gnb/bin/nr-softmodem"] diff --git a/docker/Dockerfile.gNB.aw2s.rhel9 b/docker/Dockerfile.gNB.aw2s.rhel9 index 0cb4def5fd..65eafac37b 100644 --- a/docker/Dockerfile.gNB.aw2s.rhel9 +++ b/docker/Dockerfile.gNB.aw2s.rhel9 @@ -41,6 +41,9 @@ RUN /bin/sh oaienv && \ FROM registry.access.redhat.com/ubi9/ubi:latest AS oai-gnb-aw2s ENV TZ=Europe/Paris +# Install EPEL for RHEL9 +RUN dnf install -y https://dl.fedoraproject.org/pub/epel/epel-release-latest-9.noarch.rpm + RUN dnf update -y && \ dnf install -y \ procps-ng \ @@ -50,7 +53,8 @@ RUN dnf update -y && \ lksctp-tools \ tzdata \ net-tools \ - iputils && \ + iputils \ + yaml-cpp-devel && \ echo "/usr/local/lib" > /etc/ld.so.conf.d/local-lib.conf && \ echo "/usr/local/lib64" >> /etc/ld.so.conf.d/local-lib.conf @@ -69,6 +73,7 @@ COPY --from=gnb-build \ /oai-ran/cmake_targets/ran_build/build/libdfts.so \ /oai-ran/cmake_targets/ran_build/build/libldpc*.so \ /oai-ran/cmake_targets/ran_build/build/libtelnetsrv.so \ + /oai-ran/cmake_targets/ran_build/build/libparams_yaml.so \ /usr/local/lib/ COPY --from=gnb-base \ @@ -98,4 +103,4 @@ WORKDIR /opt/oai-gnb-aw2s COPY --from=gnb-base /tini /tini ENTRYPOINT ["/tini", "-v", "--", "/opt/oai-gnb-aw2s/bin/entrypoint.sh"] -CMD ["/opt/oai-gnb-aw2s/bin/nr-softmodem", "-O", "/opt/oai-gnb-aw2s/etc/gnb.conf"] +CMD ["/opt/oai-gnb-aw2s/bin/nr-softmodem"] diff --git a/docker/Dockerfile.gNB.aw2s.rocky b/docker/Dockerfile.gNB.aw2s.rocky index bdd1eb4e38..1c0adfccd8 100644 --- a/docker/Dockerfile.gNB.aw2s.rocky +++ b/docker/Dockerfile.gNB.aw2s.rocky @@ -70,6 +70,7 @@ COPY --from=gnb-build \ /oai-ran/cmake_targets/ran_build/build/libdfts.so \ /oai-ran/cmake_targets/ran_build/build/libldpc*.so \ /oai-ran/cmake_targets/ran_build/build/libtelnetsrv.so \ + /oai-ran/cmake_targets/ran_build/build/libparams_yaml.so \ /usr/local/lib/ COPY --from=gnb-base \ @@ -96,4 +97,4 @@ WORKDIR /opt/oai-gnb-aw2s COPY --from=gnb-base /tini /tini ENTRYPOINT ["/tini", "-v", "--", "/opt/oai-gnb-aw2s/bin/entrypoint.sh"] -CMD ["/opt/oai-gnb-aw2s/bin/nr-softmodem", "-O", "/opt/oai-gnb-aw2s/etc/gnb.conf"] +CMD ["/opt/oai-gnb-aw2s/bin/nr-softmodem"] diff --git a/docker/Dockerfile.gNB.aw2s.ubuntu22 b/docker/Dockerfile.gNB.aw2s.ubuntu22 index 1d81423c26..11893171db 100644 --- a/docker/Dockerfile.gNB.aw2s.ubuntu22 +++ b/docker/Dockerfile.gNB.aw2s.ubuntu22 @@ -55,7 +55,8 @@ RUN apt-get update && \ openssl \ net-tools \ iproute2 \ - iputils-ping && \ + iputils-ping \ + libyaml-cpp-dev && \ rm -rf /var/lib/apt/lists/* COPY ./libori.so /usr/local/lib/ @@ -73,6 +74,7 @@ COPY --from=gnb-build \ /oai-ran/cmake_targets/ran_build/build/libdfts.so \ /oai-ran/cmake_targets/ran_build/build/libldpc*.so \ /oai-ran/cmake_targets/ran_build/build/libtelnetsrv.so \ + /oai-ran/cmake_targets/ran_build/build/libparams_yaml.so \ /usr/local/lib/ @@ -95,4 +97,4 @@ WORKDIR /opt/oai-gnb-aw2s COPY --from=gnb-base /tini /tini ENTRYPOINT ["/tini", "-v", "--", "/opt/oai-gnb-aw2s/bin/entrypoint.sh"] -CMD ["/opt/oai-gnb-aw2s/bin/nr-softmodem", "-O", "/opt/oai-gnb-aw2s/etc/gnb.conf"] +CMD ["/opt/oai-gnb-aw2s/bin/nr-softmodem"] diff --git a/docker/Dockerfile.gNB.fhi72.rhel9 b/docker/Dockerfile.gNB.fhi72.rhel9 index 0d629ac8a1..5f68599873 100644 --- a/docker/Dockerfile.gNB.fhi72.rhel9 +++ b/docker/Dockerfile.gNB.fhi72.rhel9 @@ -33,6 +33,9 @@ FROM ran-build-fhi72:latest AS gnb-build FROM registry.access.redhat.com/ubi9/ubi:latest AS oai-gnb-fhi72 ENV TZ=Europe/Paris +# Install EPEL for RHEL9 +RUN dnf install -y https://dl.fedoraproject.org/pub/epel/epel-release-latest-9.noarch.rpm + # Copy the entitlements COPY ./etc-pki-entitlement /etc/pki/entitlement @@ -55,7 +58,8 @@ RUN rm -f /etc/rhsm-host && \ python3 \ python3-pip \ net-tools \ - iputils && \ + iputils \ + yaml-cpp-devel && \ pip3 install six && \ pip3 install requests && \ echo "/usr/local/lib" > /etc/ld.so.conf.d/local-lib.conf && \ @@ -78,6 +82,7 @@ COPY --from=gnb-build \ /oai-ran/cmake_targets/ran_build/build/libldpc*.so \ /oai-ran/cmake_targets/ran_build/build/libtelnetsrv.so \ /oai-ran/cmake_targets/ran_build/build/libtelnetsrv_ci.so \ + /oai-ran/cmake_targets/ran_build/build/libparams_yaml.so \ /usr/local/lib/ ## Libxran library @@ -122,4 +127,4 @@ RUN ldconfig && \ WORKDIR /opt/oai-gnb COPY --from=gnb-base /tini /tini ENTRYPOINT ["/tini", "-v", "--", "/opt/oai-gnb/bin/entrypoint.sh"] -CMD ["/opt/oai-gnb/bin/nr-softmodem", "-O", "/opt/oai-gnb/etc/gnb.conf"] +CMD ["/opt/oai-gnb/bin/nr-softmodem"] diff --git a/docker/Dockerfile.gNB.fhi72.rocky b/docker/Dockerfile.gNB.fhi72.rocky index a98c0b1948..3fdc2f97af 100644 --- a/docker/Dockerfile.gNB.fhi72.rocky +++ b/docker/Dockerfile.gNB.fhi72.rocky @@ -70,6 +70,7 @@ COPY --from=gnb-build \ /oai-ran/cmake_targets/ran_build/build/libldpc*.so \ /oai-ran/cmake_targets/ran_build/build/libtelnetsrv.so \ /oai-ran/cmake_targets/ran_build/build/libtelnetsrv_ci.so \ + /oai-ran/cmake_targets/ran_build/build/libparams_yaml.so \ /usr/local/lib/ ## Libxran library @@ -114,4 +115,4 @@ RUN ldconfig && \ WORKDIR /opt/oai-gnb COPY --from=gnb-base /tini /tini ENTRYPOINT ["/tini", "-v", "--", "/opt/oai-gnb/bin/entrypoint.sh"] -CMD ["/opt/oai-gnb/bin/nr-softmodem", "-O", "/opt/oai-gnb/etc/gnb.conf"] +CMD ["/opt/oai-gnb/bin/nr-softmodem"] diff --git a/docker/Dockerfile.gNB.fhi72.ubuntu22 b/docker/Dockerfile.gNB.fhi72.ubuntu22 index 31f2392af7..069055d63b 100644 --- a/docker/Dockerfile.gNB.fhi72.ubuntu22 +++ b/docker/Dockerfile.gNB.fhi72.ubuntu22 @@ -58,7 +58,8 @@ RUN apt-get update && \ libnuma-dev \ python3 \ python3-six \ - python3-requests &&\ + python3-requests \ + libyaml-cpp-dev && \ # if the --sanitize option was used to build, additional packages are required /bin/bash -c 'if [[ "$BUILD_OPTION" = "--sanitize" ]]; then DEBIAN_FRONTEND=noninteractive apt-get install --yes \ libasan5 \ @@ -80,6 +81,7 @@ COPY --from=gnb-build \ /oai-ran/cmake_targets/ran_build/build/libldpc*.so \ /oai-ran/cmake_targets/ran_build/build/libtelnetsrv.so \ /oai-ran/cmake_targets/ran_build/build/libtelnetsrv_ci.so \ + /oai-ran/cmake_targets/ran_build/build/libparams_yaml.so \ /usr/local/lib/ ## Libxran library @@ -110,4 +112,4 @@ RUN ldconfig && \ WORKDIR /opt/oai-gnb COPY --from=gnb-base /tini /tini ENTRYPOINT ["/tini", "-v", "--", "/opt/oai-gnb/bin/entrypoint.sh"] -CMD ["/opt/oai-gnb/bin/nr-softmodem", "-O", "/opt/oai-gnb/etc/gnb.conf"] +CMD ["/opt/oai-gnb/bin/nr-softmodem"] diff --git a/docker/Dockerfile.gNB.rhel9 b/docker/Dockerfile.gNB.rhel9 index 625590efad..894d1f6aa7 100644 --- a/docker/Dockerfile.gNB.rhel9 +++ b/docker/Dockerfile.gNB.rhel9 @@ -34,6 +34,9 @@ FROM ran-build:latest AS gnb-build FROM registry.access.redhat.com/ubi9/ubi:latest AS oai-gnb ENV TZ=Europe/Paris +# Install EPEL for RHEL9 +RUN dnf install -y https://dl.fedoraproject.org/pub/epel/epel-release-latest-9.noarch.rpm + RUN dnf update -y && \ dnf install -y \ procps-ng \ @@ -46,7 +49,8 @@ RUN dnf update -y && \ python3 \ python3-pip \ net-tools \ - iputils && \ + iputils \ + yaml-cpp-devel && \ pip3 install six && \ pip3 install requests && \ echo "/usr/local/lib" > /etc/ld.so.conf.d/local-lib.conf && \ @@ -67,6 +71,7 @@ COPY --from=gnb-build \ /oai-ran/cmake_targets/ran_build/build/libldpc*.so \ /oai-ran/cmake_targets/ran_build/build/libtelnetsrv.so \ /oai-ran/cmake_targets/ran_build/build/libtelnetsrv_ci.so \ + /oai-ran/cmake_targets/ran_build/build/libparams_yaml.so \ /usr/local/lib/ COPY --from=gnb-base \ @@ -125,4 +130,4 @@ WORKDIR /opt/oai-gnb COPY --from=gnb-base /tini /tini ENTRYPOINT ["/tini", "-v", "--", "/opt/oai-gnb/bin/entrypoint.sh"] -CMD ["/opt/oai-gnb/bin/nr-softmodem", "-O", "/opt/oai-gnb/etc/gnb.conf"] +CMD ["/opt/oai-gnb/bin/nr-softmodem"] diff --git a/docker/Dockerfile.gNB.rocky b/docker/Dockerfile.gNB.rocky index c1665e5a86..5c17c78e57 100644 --- a/docker/Dockerfile.gNB.rocky +++ b/docker/Dockerfile.gNB.rocky @@ -68,6 +68,7 @@ COPY --from=gnb-build \ /oai-ran/cmake_targets/ran_build/build/libldpc*.so \ /oai-ran/cmake_targets/ran_build/build/libtelnetsrv.so \ /oai-ran/cmake_targets/ran_build/build/libtelnetsrv_ci.so \ + /oai-ran/cmake_targets/ran_build/build/libparams_yaml.so \ /usr/local/lib/ COPY --from=gnb-base \ @@ -123,4 +124,4 @@ WORKDIR /opt/oai-gnb COPY --from=gnb-base /tini /tini ENTRYPOINT ["/tini", "-v", "--", "/opt/oai-gnb/bin/entrypoint.sh"] -CMD ["/opt/oai-gnb/bin/nr-softmodem", "-O", "/opt/oai-gnb/etc/gnb.conf"] +CMD ["/opt/oai-gnb/bin/nr-softmodem"] diff --git a/docker/Dockerfile.gNB.ubuntu22 b/docker/Dockerfile.gNB.ubuntu22 index 6213ed0ca3..8d154eeb13 100644 --- a/docker/Dockerfile.gNB.ubuntu22 +++ b/docker/Dockerfile.gNB.ubuntu22 @@ -63,7 +63,8 @@ RUN apt-get update && \ python3 \ python3-six \ python3-requests \ - libusb-1.0-0 && \ + libusb-1.0-0 \ + libyaml-cpp-dev && \ # if the --sanitize option was used to build, additional packages are required /bin/bash -c 'if [[ "$BUILD_OPTION" = "--sanitize" ]]; then DEBIAN_FRONTEND=noninteractive apt-get install --yes \ #libasan5 \ # see below @@ -93,6 +94,7 @@ COPY --from=gnb-build \ /oai-ran/cmake_targets/ran_build/build/libldpc*.so \ /oai-ran/cmake_targets/ran_build/build/libtelnetsrv.so \ /oai-ran/cmake_targets/ran_build/build/libtelnetsrv_ci.so \ + /oai-ran/cmake_targets/ran_build/build/libparams_yaml.so \ /usr/local/lib/ # Now we are copying from builder-image the UHD files. @@ -128,4 +130,4 @@ WORKDIR /opt/oai-gnb COPY --from=gnb-base /tini /tini ENTRYPOINT ["/tini", "-v", "--", "/opt/oai-gnb/bin/entrypoint.sh"] -CMD ["/opt/oai-gnb/bin/nr-softmodem", "-O", "/opt/oai-gnb/etc/gnb.conf"] +CMD ["/opt/oai-gnb/bin/nr-softmodem"] diff --git a/docker/scripts/gnb-aw2s_entrypoint.sh b/docker/scripts/gnb-aw2s_entrypoint.sh index 7085800d13..7df325d78b 100755 --- a/docker/scripts/gnb-aw2s_entrypoint.sh +++ b/docker/scripts/gnb-aw2s_entrypoint.sh @@ -9,14 +9,29 @@ echo "==================================" echo "/proc/sys/kernel/core_pattern=$(cat /proc/sys/kernel/core_pattern)" if [ ! -f $CONFIGFILE ]; then - echo "No configuration file found: please mount at $CONFIGFILE" - exit 255 + echo "No configuration file $CONFIGFILE found: attempting to find YAML config" + YAML_CONFIGFILE=$PREFIX/etc/gnb.yaml + if [ ! -f $YAML_CONFIGFILE ]; then + echo "No configuration file $YAML_CONFIGFILE found. Please mount either at $CONFIGFILE or $YAML_CONFIGFILE" + exit 255 + fi + CONFIGFILE=$YAML_CONFIGFILE fi echo "==================================" echo "== Configuration file:" cat $CONFIGFILE +new_args=() + +while [[ $# -gt 0 ]]; do + new_args+=("$1") + shift +done + +new_args+=("-O") +new_args+=("$CONFIGFILE") + # enable printing of stack traces on assert export OAI_GDBSTACKS=1 @@ -24,7 +39,6 @@ echo "==================================" echo "== Starting gNB soft modem with AW2S" if [[ -v USE_ADDITIONAL_OPTIONS ]]; then echo "Additional option(s): ${USE_ADDITIONAL_OPTIONS}" - new_args=() while [[ $# -gt 0 ]]; do new_args+=("$1") shift @@ -35,6 +49,6 @@ if [[ -v USE_ADDITIONAL_OPTIONS ]]; then echo "${new_args[@]}" exec "${new_args[@]}" else - echo "$@" - exec "$@" + echo "${new_args[@]}" + exec "${new_args[@]}" fi diff --git a/docker/scripts/gnb_entrypoint.sh b/docker/scripts/gnb_entrypoint.sh index 9253d4a3e1..7139bff0ec 100755 --- a/docker/scripts/gnb_entrypoint.sh +++ b/docker/scripts/gnb_entrypoint.sh @@ -9,14 +9,29 @@ echo "==================================" echo "/proc/sys/kernel/core_pattern=$(cat /proc/sys/kernel/core_pattern)" if [ ! -f $CONFIGFILE ]; then - echo "No configuration file found: please mount at $CONFIGFILE" - exit 255 + echo "No configuration file $CONFIGFILE found: attempting to find YAML config" + YAML_CONFIGFILE=$PREFIX/etc/gnb.yaml + if [ ! -f $YAML_CONFIGFILE ]; then + echo "No configuration file $YAML_CONFIGFILE found. Please mount either at $CONFIGFILE or $YAML_CONFIGFILE" + exit 255 + fi + CONFIGFILE=$YAML_CONFIGFILE fi echo "==================================" echo "== Configuration file:" cat $CONFIGFILE +new_args=() + +while [[ $# -gt 0 ]]; do + new_args+=("$1") + shift +done + +new_args+=("-O") +new_args+=("$CONFIGFILE") + # Load the USRP binaries echo "==================================" echo "== Load USRP binaries" @@ -35,7 +50,6 @@ echo "==================================" echo "== Starting gNB soft modem" if [[ -v USE_ADDITIONAL_OPTIONS ]]; then echo "Additional option(s): ${USE_ADDITIONAL_OPTIONS}" - new_args=() while [[ $# -gt 0 ]]; do new_args+=("$1") shift @@ -46,6 +60,6 @@ if [[ -v USE_ADDITIONAL_OPTIONS ]]; then echo "${new_args[@]}" exec "${new_args[@]}" else - echo "$@" - exec "$@" + echo "${new_args[@]}" + exec "${new_args[@]}" fi diff --git a/executables/nr-ru.c b/executables/nr-ru.c index 7f5d193d34..45a1aa024b 100644 --- a/executables/nr-ru.c +++ b/executables/nr-ru.c @@ -622,6 +622,7 @@ static void rx_rf(RU_t *ru, int *frame, int *slot) rxp, samples_per_slot, ru->nb_rx); + gNBscopeCopy(ru, gNbTimeDomainSamples, rxp[0], sizeof(c16_t), 1, samples_per_slot, 0); } VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ, 0 ); diff --git a/executables/nr-ue.c b/executables/nr-ue.c index d26547b14b..01f18dc38d 100644 --- a/executables/nr-ue.c +++ b/executables/nr-ue.c @@ -37,6 +37,7 @@ #include "LAYER2/nr_pdcp/nr_pdcp_oai_api.h" #include "LAYER2/nr_rlc/nr_rlc_oai_api.h" #include "RRC/NR/MESSAGES/asn1_msg.h" +#include "openair1/PHY/TOOLS/phy_scope_interface.h" /* * NR SLOT PROCESSING SEQUENCE @@ -706,8 +707,10 @@ void readFrame(PHY_VARS_NR_UE *UE, openair0_timestamp *timestamp, bool toTrash) + 4 * ((x * fp->samples_per_subframe) + fp->get_samples_slot_timestamp(slot, fp, 0)); } - int tmp = UE->rfdevice.trx_read_func(&UE->rfdevice, timestamp, rxp, fp->get_samples_per_slot(slot, fp), fp->nb_antennas_rx); - AssertFatal(fp->get_samples_per_slot(slot, fp) == tmp, ""); + int read_block_size = fp->get_samples_per_slot(slot, fp); + int tmp = UE->rfdevice.trx_read_func(&UE->rfdevice, timestamp, rxp, read_block_size, fp->nb_antennas_rx); + UEscopeCopy(UE, ueTimeDomainSamplesBeforeSync, rxp[0], sizeof(c16_t), 1, read_block_size, 0); + AssertFatal(read_block_size == tmp, ""); if (IS_SOFTMODEM_RFSIM) dummyWrite(UE, *timestamp, fp->get_samples_per_slot(slot, fp)); @@ -812,6 +815,11 @@ void *UE_thread(void *arg) if (get_softmodem_params()->sync_ref && UE->sl_mode == 2) { UE->is_synchronized = 1; + } else { + //warm up the RF board + int64_t tmp; + for (int i = 0; i < 50; i++) + readFrame(UE, &tmp, true); } while (!oai_exit) { @@ -962,6 +970,7 @@ void *UE_thread(void *arg) const int readBlockSize = get_readBlockSize(slot_nr, fp) - iq_shift_to_apply; openair0_timestamp rx_timestamp; int tmp = UE->rfdevice.trx_read_func(&UE->rfdevice, &rx_timestamp, rxp, readBlockSize, fp->nb_antennas_rx); + UEscopeCopy(UE, ueTimeDomainSamples, rxp[0], sizeof(c16_t), 1, readBlockSize, 0); AssertFatal(readBlockSize == tmp, ""); if(slot_nr == (nb_slot_frame - 1)) { diff --git a/openair1/PHY/NR_TRANSPORT/nr_dlsch.c b/openair1/PHY/NR_TRANSPORT/nr_dlsch.c index ce4109de2c..41746a6ba2 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_dlsch.c +++ b/openair1/PHY/NR_TRANSPORT/nr_dlsch.c @@ -72,6 +72,7 @@ void nr_generate_pdsch(processingData_L1tx_t *msgTx, int frame, int slot) const int layerSz = frame_parms->N_RB_DL * NR_SYMBOLS_PER_SLOT * NR_NB_SC_PER_RB; const int dmrs_Type = rel15->dmrsConfigType; const int nb_re_dmrs = rel15->numDmrsCdmGrpsNoData * (rel15->dmrsConfigType == NFAPI_NR_DMRS_TYPE1 ? 6 : 4); + const int amp_dmrs = (int)((double)amp * sqrt(rel15->numDmrsCdmGrpsNoData)); // 3GPP TS 38.214 Section 4.1: Table 4.1-1 LOG_D(PHY,"pdsch: BWPStart %d, BWPSize %d, rbStart %d, rbsize %d\n", rel15->BWPStart,rel15->BWPSize,rel15->rbStart,rel15->rbSize); const int n_dmrs = (rel15->BWPStart + rel15->rbStart + rel15->rbSize) * nb_re_dmrs; @@ -296,7 +297,7 @@ void nr_generate_pdsch(processingData_L1tx_t *msgTx, int frame, int slot) /* Map DMRS Symbol */ if ((dmrs_symbol_map & (1 << l_symbol)) && (k == ((start_sc + get_dmrs_freq_idx(n, k_prime, delta, dmrs_Type)) % (frame_parms->ofdm_symbol_size)))) { - txdataF_precoding[layer][l_symbol][k] = c16mulRealShift(mod_dmrs[dmrs_idx], Wt[l_prime] * Wf[k_prime] * amp, 15); + txdataF_precoding[layer][l_symbol][k] = c16mulRealShift(mod_dmrs[dmrs_idx], Wt[l_prime] * Wf[k_prime] * amp_dmrs, 15); #ifdef DEBUG_DLSCH_MAPPING printf("dmrs_idx %u\t l %d \t k %d \t k_prime %d \t n %d \t txdataF: %d %d\n", dmrs_idx, diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync.c b/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync.c index 88e77b0840..1d0d85ec54 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync.c @@ -202,7 +202,7 @@ void nr_scan_ssb(void *arg) /* process pss search on received buffer */ ssbInfo->syncRes.frame_id = frame_id; int nid2; - int freq_offset_pss; + int freq_offset_pss = 0; const int sync_pos = pss_synchro_nr((const c16_t **)rxdata, fp, pssTime, diff --git a/openair1/PHY/TOOLS/imscope/imscope.cpp b/openair1/PHY/TOOLS/imscope/imscope.cpp index 8205c85b9e..054fcdad79 100644 --- a/openair1/PHY/TOOLS/imscope/imscope.cpp +++ b/openair1/PHY/TOOLS/imscope/imscope.cpp @@ -279,8 +279,17 @@ class IQHist { } } else if (plot_type == 1) { if (ImPlot::BeginPlot(label.c_str(), {(float)ImGui::GetWindowWidth() * 0.3f, (float)ImGui::GetWindowWidth() * 0.3f})) { - // Limit the amount of data plotted with scatterplot (issue with vertices/draw call) - ImPlot::PlotScatter(label.c_str(), iq_data->real.data(), iq_data->imag.data(), std::min(16000, iq_data->len)); + int points_drawn = 0; + while (points_drawn < iq_data->len) { + // Limit the amount of data plotted with PlotScatter call (issue with vertices/draw call) + int points_to_draw = std::min(iq_data->len - points_drawn, 16000); + ImPlot::SetNextMarkerStyle(ImPlotMarker_Circle, 1, IMPLOT_AUTO_COL, 1); + ImPlot::PlotScatter(label.c_str(), + iq_data->real.data() + points_drawn, + iq_data->imag.data() + points_drawn, + points_to_draw); + points_drawn += points_to_draw; + } ImPlot::EndPlot(); } } else if (plot_type == 2) { @@ -480,6 +489,26 @@ void ShowUeScope(PHY_VARS_NR_UE *ue, float t) pdsch_iq_hist->Draw(iq_data, t, new_data); ImGui::TreePop(); } + if (ImGui::TreeNode("Time domain samples")) { + static auto iq_data = new IQData(); + static auto time_domain_iq = new IQHist("Time domain samples"); + bool new_data = false; + if (time_domain_iq->ShouldReadData()) { + new_data = iq_data->TryCollect(&scope_array[ueTimeDomainSamples], t, time_domain_iq->GetEpsilon()); + } + time_domain_iq->Draw(iq_data, t, new_data); + ImGui::TreePop(); + } + if (ImGui::TreeNode("Time domain samples - before sync")) { + static auto iq_data = new IQData(); + static auto time_domain_iq = new IQHist("Time domain samples - before sync"); + bool new_data = false; + if (time_domain_iq->ShouldReadData()) { + new_data = iq_data->TryCollect(&scope_array[ueTimeDomainSamplesBeforeSync], t, time_domain_iq->GetEpsilon()); + } + time_domain_iq->Draw(iq_data, t, new_data); + ImGui::TreePop(); + } if (ImGui::TreeNode("Broadcast channel")) { ImGui::Text("RSRP %d", ue->measurements.ssb_rsrp_dBm[ue->frame_parms.ssb_index]); if (ImGui::TreeNode("IQ")) { @@ -552,6 +581,16 @@ void ShowGnbScope(PHY_VARS_gNB *gNB, float t) pusch_llr_plot->Draw(t, gNBPuschLlr, "PUSCH LLR"); ImGui::TreePop(); } + if (ImGui::TreeNode("Time domain samples")) { + static auto iq_data = new IQData(); + static auto time_domain_iq = new IQHist("Time domain samples"); + bool new_data = false; + if (time_domain_iq->ShouldReadData()) { + new_data = iq_data->TryCollect(&scope_array[gNbTimeDomainSamples], t, time_domain_iq->GetEpsilon()); + } + time_domain_iq->Draw(iq_data, t, new_data); + ImGui::TreePop(); + } } void *imscope_thread(void *data_void_ptr) @@ -722,6 +761,7 @@ extern "C" void imscope_autoinit(void *dataptr) scope->copyDataUnsafeWithOffset = copyDataUnsafeWithOffset; scope->unlockScopeData = unlockScopeData; scope_params->gNB->scopeData = scope; + scope_params->ru->scopeData = scope; } else { PHY_VARS_NR_UE *ue = (PHY_VARS_NR_UE *)dataptr; scopeData_t *scope = (scopeData_t *)calloc(1, sizeof(scopeData_t)); diff --git a/openair1/PHY/TOOLS/phy_scope_interface.h b/openair1/PHY/TOOLS/phy_scope_interface.h index 2f8378e7b7..2fa97880b4 100644 --- a/openair1/PHY/TOOLS/phy_scope_interface.h +++ b/openair1/PHY/TOOLS/phy_scope_interface.h @@ -73,6 +73,9 @@ enum scopeDataType { MAX_SCOPE_TYPES, gNBPuschRxIq = MAX_SCOPE_TYPES, gNBPuschLlr, + ueTimeDomainSamples, + ueTimeDomainSamplesBeforeSync, + gNbTimeDomainSamples, EXTRA_SCOPE_TYPES }; @@ -127,12 +130,12 @@ void copyData(void *, enum scopeDataType type, void *dataIn, int elementSz, int } #define gNBscopeCopyWithMetadata(gnb, type, ...) \ if (gnb->scopeData) { \ - ((scopeData_t *)gnb->scopeData)->copyData((scopeData_t *)gNB->scopeData, type, ##__VA_ARGS__); \ + ((scopeData_t *)gnb->scopeData)->copyData((scopeData_t *)gnb->scopeData, type, ##__VA_ARGS__); \ } #define gNBscopeCopy(gnb, type, ...) \ if (gnb->scopeData) { \ metadata mt = {.slot = -1, .frame = -1}; \ - ((scopeData_t *)gnb->scopeData)->copyData((scopeData_t *)gNB->scopeData, type, ##__VA_ARGS__, &mt); \ + ((scopeData_t *)gnb->scopeData)->copyData((scopeData_t *)gnb->scopeData, type, ##__VA_ARGS__, &mt); \ } #define GnbScopeUpdate(gnb, type, numElt) \ if (gnb->scopeData) \ diff --git a/openair1/PHY/defs_RU.h b/openair1/PHY/defs_RU.h index 2f564eac6b..3b7b7f2ba0 100644 --- a/openair1/PHY/defs_RU.h +++ b/openair1/PHY/defs_RU.h @@ -661,7 +661,8 @@ typedef struct RU_t_s { /// number of cores for RU ThreadPool int num_tpcores; /// structure for analyzing high-level RT measurements - rt_ru_profiling_t rt_ru_profiling; + rt_ru_profiling_t rt_ru_profiling; + void* scopeData; } RU_t; diff --git a/openair2/COMMON/e1ap_messages_types.h b/openair2/COMMON/e1ap_messages_types.h index cc48a6f9e9..f2fd64252c 100644 --- a/openair2/COMMON/e1ap_messages_types.h +++ b/openair2/COMMON/e1ap_messages_types.h @@ -163,7 +163,7 @@ typedef struct qos_characteristics_s { } packet_error_rate; } dynamic; }; - fiveQI_type_t qos_type; + fiveQI_t qos_type; } qos_characteristics_t; typedef struct ngran_allocation_retention_priority_s { diff --git a/openair2/COMMON/f1ap_messages_types.h b/openair2/COMMON/f1ap_messages_types.h index 3b6082e221..f159e63ca3 100644 --- a/openair2/COMMON/f1ap_messages_types.h +++ b/openair2/COMMON/f1ap_messages_types.h @@ -24,8 +24,7 @@ #include #include -#include "s1ap_messages_types.h" -#include "ngap_messages_types.h" +#include "common/5g_platform_types.h" //-------------------------------------------------------------------------------------------// // Defines to access message fields. @@ -82,12 +81,12 @@ #define F1AP_MAX_NO_UE_ID 1024 #define F1AP_MAX_NO_OF_INDIVIDUAL_CONNECTIONS_TO_RESET 65536 - -typedef net_ip_address_t f1ap_net_ip_address_t; +/* 9.3.1.42 of 3GPP TS 38.473 - gNB-CU System Information */ +#define F1AP_MAX_NO_SIB_TYPES 32 typedef struct f1ap_net_config_t { - f1ap_net_ip_address_t CU_f1_ip_address; - f1ap_net_ip_address_t DU_f1c_ip_address; + char *CU_f1_ip_address; + char *DU_f1c_ip_address; char *DU_f1u_ip_address; uint16_t CUport; uint16_t DUport; @@ -99,6 +98,11 @@ typedef struct f1ap_plmn_t { uint8_t mnc_digit_length; } f1ap_plmn_t; +typedef struct f1ap_cp_tnl_s { + in_addr_t tl_address; // currently only IPv4 supported + uint16_t port; +} f1ap_cp_tnl_t; + typedef enum f1ap_mode_t { F1AP_MODE_TDD = 0, F1AP_MODE_FDD = 1 } f1ap_mode_t; typedef struct f1ap_nr_frequency_info_t { @@ -179,18 +183,24 @@ typedef struct f1ap_du_register_req_t { f1ap_net_config_t net_config; } f1ap_du_register_req_t; +typedef struct f1ap_sib_msg_t { + /// RRC container with system information owned by gNB-CU + uint8_t *SI_container; + int SI_container_length; + /// SIB block type, e.g. 2 for sibType2 + int SI_type; +} f1ap_sib_msg_t; + typedef struct served_cells_to_activate_s { f1ap_plmn_t plmn; // NR Global Cell Id uint64_t nr_cellid; - /// NRPCI + /// NRPCI [int 0..1007] uint16_t nrpci; /// num SI messages per DU cell uint8_t num_SI; - /// SI message containers (up to 21 messages per cell) - uint8_t *SI_container[21]; - int SI_container_length[21]; - int SI_type[21]; + /// gNB-CU System Information message (up to 32 messages per cell) + f1ap_sib_msg_t SI_msg[F1AP_MAX_NO_SIB_TYPES]; } served_cells_to_activate_t; typedef struct f1ap_setup_resp_s { @@ -208,18 +218,8 @@ typedef struct f1ap_setup_resp_s { } f1ap_setup_resp_t; typedef struct f1ap_gnb_cu_configuration_update_s { - /* Connexion id used between SCTP/F1AP */ - uint16_t cnx_id; - - /* SCTP association id */ - sctp_assoc_t assoc_id; - - /* Number of SCTP streams used for a mme association */ - uint16_t sctp_in_streams; - uint16_t sctp_out_streams; - - /// string holding gNB_CU_name - char *gNB_CU_name; + /// Transaction ID + uint64_t transaction_id; /// number of DU cells to activate uint16_t num_cells_to_activate; //0< num_cells_to_activate/mod <= 512; served_cells_to_activate_t cells_to_activate[F1AP_MAX_NB_CELLS]; @@ -228,26 +228,37 @@ typedef struct f1ap_gnb_cu_configuration_update_s { typedef struct f1ap_setup_failure_s { uint16_t cause; uint16_t time_to_wait; - uint16_t criticality_diagnostics; + uint16_t criticality_diagnostics; + /// Transaction ID (M) + uint64_t transaction_id; } f1ap_setup_failure_t; typedef struct f1ap_gnb_cu_configuration_update_acknowledge_s { + uint64_t transaction_id; + // Cells Failed to be Activated List uint16_t num_cells_failed_to_be_activated; - f1ap_plmn_t plmn[F1AP_MAX_NB_CELLS]; - uint64_t nr_cellid[F1AP_MAX_NB_CELLS]; - uint16_t cause[F1AP_MAX_NB_CELLS]; + struct { + // NR CGI + f1ap_plmn_t plmn; + uint64_t nr_cellid; + uint16_t cause; + } cells_failed_to_be_activated[F1AP_MAX_NB_CELLS]; int have_criticality; - uint16_t criticality_diagnostics; + uint16_t criticality_diagnostics; + // gNB-CU TNL Association Setup List uint16_t noofTNLAssociations_to_setup; - uint16_t have_port[F1AP_MAX_NO_OF_TNL_ASSOCIATIONS]; - in_addr_t tl_address[F1AP_MAX_NO_OF_TNL_ASSOCIATIONS]; // currently only IPv4 supported + f1ap_cp_tnl_t tnlAssociations_to_setup[F1AP_MAX_NO_OF_TNL_ASSOCIATIONS]; + // gNB-CU TNL Association Failed to Setup List uint16_t noofTNLAssociations_failed; - in_addr_t tl_address_failed[F1AP_MAX_NO_OF_TNL_ASSOCIATIONS]; // currently only IPv4 supported - uint16_t cause_failed[F1AP_MAX_NO_OF_TNL_ASSOCIATIONS]; + f1ap_cp_tnl_t tnlAssociations_failed[F1AP_MAX_NO_OF_TNL_ASSOCIATIONS]; + // Dedicated SI Delivery Needed UE List uint16_t noofDedicatedSIDeliveryNeededUEs; - uint32_t gNB_CU_ue_id[F1AP_MAX_NO_UE_ID]; - f1ap_plmn_t ue_plmn[F1AP_MAX_NO_UE_ID]; - uint64_t ue_nr_cellid[F1AP_MAX_NO_UE_ID]; + struct { + uint32_t gNB_CU_ue_id; + // NR CGI + f1ap_plmn_t ue_plmn; + uint64_t ue_nr_cellid; + } dedicatedSIDeliveryNeededUEs[F1AP_MAX_NO_UE_ID]; } f1ap_gnb_cu_configuration_update_acknowledge_t; typedef struct f1ap_gnb_cu_configuration_update_failure_s { @@ -285,16 +296,13 @@ typedef struct f1ap_gnb_du_configuration_update_s { f1ap_plmn_t plmn; uint64_t nr_cellid; // NR Global Cell Id } cell_to_delete[F1AP_MAX_NB_CELLS]; - - /// string holding gNB_CU_name + /// gNB-DU unique ID, at least within a gNB-CU (0 .. 2^36 - 1) uint64_t *gNB_DU_ID; } f1ap_gnb_du_configuration_update_t; typedef struct f1ap_gnb_du_configuration_update_acknowledge_s { /// ulong transaction id uint64_t transaction_id; - /// string holding gNB_CU_name - char *gNB_CU_name; /// number of DU cells to activate uint16_t num_cells_to_activate; // 0< num_cells_to_activate <= 512; served_cells_to_activate_t cells_to_activate[F1AP_MAX_NB_CELLS]; @@ -334,6 +342,7 @@ typedef struct f1ap_initial_ul_rrc_message_s { int rrc_container_length; uint8_t *du2cu_rrc_container; int du2cu_rrc_container_length; + uint8_t transaction_id; } f1ap_initial_ul_rrc_message_t; typedef struct f1ap_ul_rrc_message_s { @@ -346,7 +355,7 @@ typedef struct f1ap_ul_rrc_message_s { typedef struct f1ap_up_tnl_s { in_addr_t tl_address; // currently only IPv4 supported - teid_t teid; + uint32_t teid; uint16_t port; } f1ap_up_tnl_t; @@ -376,7 +385,7 @@ typedef struct f1ap_qos_characteristics_s { } packet_error_rate; } dynamic; }; - fiveQI_type_t qos_type; + fiveQI_t qos_type; } f1ap_qos_characteristics_t; typedef struct f1ap_ngran_allocation_retention_priority_s { @@ -401,6 +410,7 @@ typedef struct f1ap_drb_information_s { uint8_t flows_to_be_setup_length; } f1ap_drb_information_t; +typedef enum f1ap_rlc_mode_t { F1AP_RLC_MODE_AM, F1AP_RLC_MODE_UM_BIDIR, F1AP_RLC_UM_UNI_UL, F1AP_RLC_UM_UNI_DL } f1ap_rlc_mode_t; typedef struct f1ap_drb_to_be_setup_s { long drb_id; f1ap_up_tnl_t up_ul_tnl[2]; @@ -408,7 +418,7 @@ typedef struct f1ap_drb_to_be_setup_s { f1ap_up_tnl_t up_dl_tnl[2]; uint8_t up_dl_tnl_length; f1ap_drb_information_t drb_info; - rlc_mode_t rlc_mode; + f1ap_rlc_mode_t rlc_mode; nssai_t nssai; } f1ap_drb_to_be_setup_t; diff --git a/openair2/COMMON/ngap_messages_types.h b/openair2/COMMON/ngap_messages_types.h index 861f5e6d2c..0f1555cfdf 100644 --- a/openair2/COMMON/ngap_messages_types.h +++ b/openair2/COMMON/ngap_messages_types.h @@ -31,8 +31,9 @@ #define NGAP_MESSAGES_TYPES_H_ #include "common/platform_constants.h" #include "common/platform_types.h" -#include "common/ngran_types.h" +#include "common/5g_platform_types.h" #include "LTE_asn_constant.h" +#include "s1ap_messages_types.h" //-------------------------------------------------------------------------------------------// // Defines to access message fields. @@ -196,16 +197,11 @@ typedef enum ngap_rrc_establishment_cause_e { NGAP_RRC_CAUSE_LAST } ngap_rrc_establishment_cause_t; -typedef struct nssai_s { - uint8_t sst; - uint32_t sd; -} nssai_t; - typedef struct pdusession_level_qos_parameter_s { uint8_t qfi; uint64_t fiveQI; uint64_t qos_priority; - fiveQI_type_t fiveQI_type; + fiveQI_t fiveQI_type; ngap_allocation_retention_priority_t allocation_retention_priority; } pdusession_level_qos_parameter_t; diff --git a/openair2/E1AP/e1ap.c b/openair2/E1AP/e1ap.c index fda507ef4e..df359c9234 100644 --- a/openair2/E1AP/e1ap.c +++ b/openair2/E1AP/e1ap.c @@ -686,7 +686,7 @@ static int fill_BEARER_CONTEXT_SETUP_REQUEST(e1ap_bearer_setup_req_t *const bear ieC6_1_1_1->qoS_Flow_Identifier = k->qfi; /* QoS Characteristics */ qos_characteristics_t *qos_char_in = &k->qos_params.qos_characteristics; - if (qos_char_in->qos_type == non_dynamic) { // non Dynamic 5QI + if (qos_char_in->qos_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 = qos_char_in->non_dynamic.fiveqi; @@ -1002,12 +1002,12 @@ static void extract_BEARER_CONTEXT_SETUP_REQUEST(const E1AP_E1AP_PDU_t *pdu, e1a qos_characteristics_t *qos_char = &qos_flow->qos_params.qos_characteristics; if (qos2Setup->qoSFlowLevelQoSParameters.qoS_Characteristics.present == E1AP_QoS_Characteristics_PR_non_Dynamic_5QI) { - qos_char->qos_type = non_dynamic; + qos_char->qos_type = NON_DYNAMIC; qos_char->non_dynamic.fiveqi = qos2Setup->qoSFlowLevelQoSParameters.qoS_Characteristics.choice.non_Dynamic_5QI->fiveQI; } else { E1AP_Dynamic5QIDescriptor_t *dynamic5QI = qos2Setup->qoSFlowLevelQoSParameters.qoS_Characteristics.choice.dynamic_5QI; - qos_char->qos_type = dynamic; + qos_char->qos_type = DYNAMIC; qos_char->dynamic.qos_priority_level = dynamic5QI->qoSPriorityLevel; qos_char->dynamic.packet_delay_budget = dynamic5QI->packetDelayBudget; qos_char->dynamic.packet_error_rate.per_scalar = dynamic5QI->packetErrorRate.pER_Scalar; diff --git a/openair2/F1AP/CMakeLists.txt b/openair2/F1AP/CMakeLists.txt index e6490b96b0..78bc9435a2 100644 --- a/openair2/F1AP/CMakeLists.txt +++ b/openair2/F1AP/CMakeLists.txt @@ -1,3 +1,4 @@ +add_subdirectory(lib) add_subdirectory(MESSAGES) if(ENABLE_TESTS) @@ -5,4 +6,6 @@ if(ENABLE_TESTS) target_link_libraries(f1ap_ids_test UTIL HASHTABLE minimal_lib) add_dependencies(tests f1ap_ids_test) add_test(NAME F1AP_ID_test COMMAND f1ap_ids_test) + + add_subdirectory(tests) endif() diff --git a/openair2/F1AP/f1ap_common.h b/openair2/F1AP/f1ap_common.h index 13f1d8f53b..83781484c7 100644 --- a/openair2/F1AP/f1ap_common.h +++ b/openair2/F1AP/f1ap_common.h @@ -411,8 +411,6 @@ typedef struct f1ap_cudu_inst_s { instance_t gtpInst; } f1ap_cudu_inst_t; -static const int nrb_lut[29] = {11, 18, 24, 25, 31, 32, 38, 51, 52, 65, 66, 78, 79, 93, 106, 107, 121, 132, 133, 135, 160, 162, 189, 216, 217, 245, 264, 270, 273}; - uint8_t F1AP_get_next_transaction_identifier(instance_t mod_idP, instance_t cu_mod_idP); f1ap_cudu_inst_t *getCxt(instance_t instanceP); diff --git a/openair2/F1AP/f1ap_cu_interface_management.c b/openair2/F1AP/f1ap_cu_interface_management.c index 2e73172e2b..aed1ae6d23 100644 --- a/openair2/F1AP/f1ap_cu_interface_management.c +++ b/openair2/F1AP/f1ap_cu_interface_management.c @@ -34,926 +34,187 @@ #include "f1ap_encoder.h" #include "f1ap_itti_messaging.h" #include "f1ap_cu_interface_management.h" - -int CU_send_RESET(sctp_assoc_t assoc_id, const f1ap_reset_t *reset) -{ - AssertFatal(1==0,"Not implemented yet\n"); -} +#include "f1ap_default_values.h" +#include "lib/f1ap_interface_management.h" +#include "lib/f1ap_lib_common.h" int CU_handle_RESET_ACKNOWLEDGE(instance_t instance, sctp_assoc_t assoc_id, uint32_t stream, F1AP_F1AP_PDU_t *pdu) { - AssertFatal(1==0,"Not implemented yet\n"); -} - -int CU_handle_RESET(instance_t instance, sctp_assoc_t assoc_id, uint32_t stream, F1AP_F1AP_PDU_t *pdu) -{ - AssertFatal(1==0,"Not implemented yet\n"); + AssertFatal(1 == 0, "Not implemented yet\n"); } int CU_send_RESET_ACKNOWLEDGE(sctp_assoc_t assoc_id, const f1ap_reset_ack_t *ack) { - AssertFatal(1==0,"Not implemented yet\n"); + AssertFatal(1 == 0, "Not implemented yet\n"); } -/* - Error Indication -*/ -int CU_handle_ERROR_INDICATION(instance_t instance, sctp_assoc_t assoc_id, uint32_t stream, F1AP_F1AP_PDU_t *pdu) -{ - AssertFatal(1==0,"Not implemented yet\n"); -} - -int CU_send_ERROR_INDICATION(sctp_assoc_t assoc_id, F1AP_ErrorIndication_t *ErrorIndication) { - AssertFatal(1==0,"Not implemented yet\n"); -} - -static uint8_t *cp_octet_string(const OCTET_STRING_t *os, int *len) -{ - uint8_t *buf = calloc(os->size, sizeof(*buf)); - AssertFatal(buf != NULL, "out of memory\n"); - memcpy(buf, os->buf, os->size); - *len = os->size; - return buf; -} - -static int read_slice_info(const F1AP_ServedPLMNs_Item_t *plmn, nssai_t *nssai, int max_nssai) -{ - if (plmn->iE_Extensions == NULL) - return 0; - - const F1AP_ProtocolExtensionContainer_10696P34_t *p = (F1AP_ProtocolExtensionContainer_10696P34_t *)plmn->iE_Extensions; - if (p->list.count == 0) - return 0; - - const F1AP_ServedPLMNs_ItemExtIEs_t *splmn = p->list.array[0]; - DevAssert(splmn->id == F1AP_ProtocolIE_ID_id_TAISliceSupportList); - DevAssert(splmn->extensionValue.present == F1AP_ServedPLMNs_ItemExtIEs__extensionValue_PR_SliceSupportList); - const F1AP_SliceSupportList_t *ssl = &splmn->extensionValue.choice.SliceSupportList; - AssertFatal(ssl->list.count <= max_nssai, "cannot handle more than 16 slices\n"); - for (int s = 0; s < ssl->list.count; ++s) { - const F1AP_SliceSupportItem_t *sl = ssl->list.array[s]; - nssai_t *n = &nssai[s]; - OCTET_STRING_TO_INT8(&sl->sNSSAI.sST, n->sst); - n->sd = 0xffffff; - if (sl->sNSSAI.sD != NULL) - OCTET_STRING_TO_INT24(sl->sNSSAI.sD, n->sd); - } - - return ssl->list.count; -} - -/* - F1 Setup -*/ +/** + * @brief F1AP Setup Request decoding (9.2.1.4 of 3GPP TS 38.473) and transfer to RRC + */ int CU_handle_F1_SETUP_REQUEST(instance_t instance, sctp_assoc_t assoc_id, uint32_t stream, F1AP_F1AP_PDU_t *pdu) { LOG_D(F1AP, "CU_handle_F1_SETUP_REQUEST\n"); - F1AP_F1SetupRequest_t *container; - F1AP_F1SetupRequestIEs_t *ie; - int i = 0; DevAssert(pdu != NULL); - container = &pdu->choice.initiatingMessage->value.choice.F1SetupRequest; - /* F1 Setup Request == Non UE-related procedure -> stream 0 */ if (stream != 0) { LOG_W(F1AP, "[SCTP %d] Received f1 setup request on stream != 0 (%d)\n", assoc_id, stream); } - + f1ap_setup_req_t msg = {0}; + /* Decode */ + if (!decode_f1ap_setup_request(pdu, &msg)) { + LOG_E(F1AP, "cannot decode F1AP Setup Request\n"); + free_f1ap_setup_request(&msg); + return -1; + } + /* Send to RRC (ITTI) */ MessageDef *message_p = itti_alloc_new_message(TASK_CU_F1, 0, F1AP_SETUP_REQ); message_p->ittiMsgHeader.originInstance = assoc_id; f1ap_setup_req_t *req = &F1AP_SETUP_REQ(message_p); - - /* Transaction ID*/ - F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_F1SetupRequestIEs_t, ie, container, F1AP_ProtocolIE_ID_id_TransactionID, true); - req->transaction_id = ie->value.choice.TransactionID; - LOG_D(F1AP, "req->transaction_id %lu \n", req->transaction_id); - - /* gNB_DU_id */ - // this function exits if the ie is mandatory - F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_F1SetupRequestIEs_t, ie, container, - F1AP_ProtocolIE_ID_id_gNB_DU_ID, true); - asn_INTEGER2ulong(&ie->value.choice.GNB_DU_ID, &req->gNB_DU_id); - LOG_D(F1AP, "req->gNB_DU_id %lu \n", req->gNB_DU_id); - /* gNB_DU_name */ - F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_F1SetupRequestIEs_t, ie, container, F1AP_ProtocolIE_ID_id_gNB_DU_Name, false); - req->gNB_DU_name = NULL; - if (ie != NULL) { - req->gNB_DU_name = calloc(ie->value.choice.GNB_DU_Name.size + 1, sizeof(char)); - memcpy(req->gNB_DU_name, ie->value.choice.GNB_DU_Name.buf, ie->value.choice.GNB_DU_Name.size); - LOG_D(F1AP, "req->gNB_DU_name %s \n", req->gNB_DU_name); - } - /* GNB_DU_Served_Cells_List */ - F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_F1SetupRequestIEs_t, ie, container, - F1AP_ProtocolIE_ID_id_gNB_DU_Served_Cells_List, true); - req->num_cells_available = ie->value.choice.GNB_DU_Served_Cells_List.list.count; - LOG_D(F1AP, "req->num_cells_available %d \n", req->num_cells_available); - - for (i=0; inum_cells_available; i++) { - F1AP_GNB_DU_Served_Cells_Item_t *served_cells_item = &(((F1AP_GNB_DU_Served_Cells_ItemIEs_t *) - ie->value.choice.GNB_DU_Served_Cells_List.list.array[i])-> - value.choice.GNB_DU_Served_Cells_Item); - F1AP_Served_Cell_Information_t *servedCellInformation= &served_cells_item->served_Cell_Information; - /* tac */ - if (servedCellInformation->fiveGS_TAC) { - req->cell[i].info.tac = malloc(sizeof(*req->cell[i].info.tac)); - AssertFatal(req->cell[i].info.tac != NULL, "out of memory\n"); - OCTET_STRING_TO_INT24(servedCellInformation->fiveGS_TAC, *req->cell[i].info.tac); - LOG_D(F1AP, "req->tac[%d] %d \n", i, *req->cell[i].info.tac); - } - - /* - nRCGI */ - TBCD_TO_MCC_MNC(&(servedCellInformation->nRCGI.pLMN_Identity), - req->cell[i].info.plmn.mcc, - req->cell[i].info.plmn.mnc, - req->cell[i].info.plmn.mnc_digit_length); - // NR cellID - BIT_STRING_TO_NR_CELL_IDENTITY(&servedCellInformation->nRCGI.nRCellIdentity, - req->cell[i].info.nr_cellid); - LOG_D(F1AP, "[SCTP %d] Received nRCGI: MCC %d, MNC %d, CELL_ID %llu\n", assoc_id, - req->cell[i].info.plmn.mcc, - req->cell[i].info.plmn.mnc, - (long long unsigned int)req->cell[i].info.nr_cellid); - /* - nRPCI */ - req->cell[i].info.nr_pci = servedCellInformation->nRPCI; - LOG_D(F1AP, "req->nr_pci[%d] %d \n", i, req->cell[i].info.nr_pci); - - AssertFatal(servedCellInformation->servedPLMNs.list.count == 1, "only one PLMN handled\n"); - req->cell[i].info.num_ssi = read_slice_info(servedCellInformation->servedPLMNs.list.array[0], req->cell[i].info.nssai, 16); - - // FDD Cells - if (servedCellInformation->nR_Mode_Info.present==F1AP_NR_Mode_Info_PR_fDD) { - req->cell[i].info.mode = F1AP_MODE_FDD; - f1ap_fdd_info_t *FDDs = &req->cell[i].info.fdd; - F1AP_FDD_Info_t * fDD_Info=servedCellInformation->nR_Mode_Info.choice.fDD; - FDDs->ul_freqinfo.arfcn = fDD_Info->uL_NRFreqInfo.nRARFCN; - AssertFatal(fDD_Info->uL_NRFreqInfo.freqBandListNr.list.count == 1, "cannot handle more than one frequency band\n"); - for (int f=0; f < fDD_Info->uL_NRFreqInfo.freqBandListNr.list.count; f++) { - F1AP_FreqBandNrItem_t * FreqItem=fDD_Info->uL_NRFreqInfo.freqBandListNr.list.array[f]; - FDDs->ul_freqinfo.band = FreqItem->freqBandIndicatorNr; - AssertFatal(FreqItem->supportedSULBandList.list.count == 0, "cannot handle SUL bands!\n"); - } - FDDs->dl_freqinfo.arfcn = fDD_Info->dL_NRFreqInfo.nRARFCN; - int dlBands=fDD_Info->dL_NRFreqInfo.freqBandListNr.list.count; - AssertFatal(dlBands == 1, "cannot handled more than one frequency band\n"); - for (int dlB=0; dlB < dlBands; dlB++) { - F1AP_FreqBandNrItem_t * FreqItem=fDD_Info->dL_NRFreqInfo.freqBandListNr.list.array[dlB]; - FDDs->dl_freqinfo.band = FreqItem->freqBandIndicatorNr; - int num_available_supported_SULBands = FreqItem->supportedSULBandList.list.count; - AssertFatal(num_available_supported_SULBands == 0, "cannot handle SUL bands!\n"); - } - FDDs->ul_tbw.scs = fDD_Info->uL_Transmission_Bandwidth.nRSCS; - FDDs->ul_tbw.nrb = nrb_lut[fDD_Info->uL_Transmission_Bandwidth.nRNRB]; - FDDs->dl_tbw.scs = fDD_Info->dL_Transmission_Bandwidth.nRSCS; - FDDs->dl_tbw.nrb = nrb_lut[fDD_Info->dL_Transmission_Bandwidth.nRNRB]; - } else if (servedCellInformation->nR_Mode_Info.present==F1AP_NR_Mode_Info_PR_tDD) { - req->cell[i].info.mode = F1AP_MODE_TDD; - f1ap_tdd_info_t *TDDs = &req->cell[i].info.tdd; - F1AP_TDD_Info_t *tDD_Info = servedCellInformation->nR_Mode_Info.choice.tDD; - TDDs->freqinfo.arfcn = tDD_Info->nRFreqInfo.nRARFCN; - AssertFatal(tDD_Info->nRFreqInfo.freqBandListNr.list.count == 1, "cannot handle more than one frequency band\n"); - for (int f=0; f < tDD_Info->nRFreqInfo.freqBandListNr.list.count; f++) { - struct F1AP_FreqBandNrItem * FreqItem=tDD_Info->nRFreqInfo.freqBandListNr.list.array[f]; - TDDs->freqinfo.band = FreqItem->freqBandIndicatorNr; - int num_available_supported_SULBands = FreqItem->supportedSULBandList.list.count; - AssertFatal(num_available_supported_SULBands == 0, "cannot hanlde SUL bands!\n"); - } - TDDs->tbw.scs = tDD_Info->transmission_Bandwidth.nRSCS; - TDDs->tbw.nrb = nrb_lut[tDD_Info->transmission_Bandwidth.nRNRB]; - } else { - AssertFatal(false, "unknown NR Mode info %d\n", servedCellInformation->nR_Mode_Info.present); - } - - /* MeasurementConfig */ - if (servedCellInformation->measurementTimingConfiguration.size > 0) - req->cell[i].info.measurement_timing_config = - cp_octet_string(&servedCellInformation->measurementTimingConfiguration, &req->cell[i].info.measurement_timing_config_len); - - struct F1AP_GNB_DU_System_Information * DUsi=served_cells_item->gNB_DU_System_Information; - if (DUsi != NULL) { - // System Information - req->cell[i].sys_info = calloc(1, sizeof(*req->cell[i].sys_info)); - AssertFatal(req->cell[i].sys_info != NULL, "out of memory\n"); - f1ap_gnb_du_system_info_t *sys_info = req->cell[i].sys_info; - /* mib */ - sys_info->mib = calloc(DUsi->mIB_message.size, sizeof(char)); - memcpy(sys_info->mib, DUsi->mIB_message.buf, DUsi->mIB_message.size); - sys_info->mib_length = DUsi->mIB_message.size; - /* sib1 */ - sys_info->sib1 = calloc(DUsi->sIB1_message.size, sizeof(char)); - memcpy(sys_info->sib1, DUsi->sIB1_message.buf, DUsi->sIB1_message.size); - sys_info->sib1_length = DUsi->sIB1_message.size; - } - } - - /* Handle RRC Version */ - F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_F1SetupRequestIEs_t, ie, container, - F1AP_ProtocolIE_ID_id_GNB_DU_RRC_Version, true); - // Latest RRC Version: "This IE is not used in this release." - // BIT_STRING_to_uint8(&ie->value.choice.RRC_Version.latest_RRC_Version); - if (ie->value.choice.RRC_Version.iE_Extensions) { - F1AP_ProtocolExtensionContainer_10696P228_t *ext = - (F1AP_ProtocolExtensionContainer_10696P228_t *)ie->value.choice.RRC_Version.iE_Extensions; - if (ext->list.count > 0) { - F1AP_RRC_Version_ExtIEs_t *rrcext = ext->list.array[0]; - OCTET_STRING_t *os = &rrcext->extensionValue.choice.OCTET_STRING_SIZE_3_; - DevAssert(os->size == 3); - for (int i = 0; i < 3; ++i) - req->rrc_ver[i] = os->buf[i]; - } - } + *req = msg; /* "move" message into ITTI, RRC thread will free it */ itti_send_msg_to_task(TASK_RRC_GNB, GNB_MODULE_ID_TO_INSTANCE(instance), message_p); - return 0; } +/** + * @brief F1AP Setup Response encoding (9.2.1.5 of 3GPP TS 38.473) and message transfer + */ int CU_send_F1_SETUP_RESPONSE(sctp_assoc_t assoc_id, f1ap_setup_resp_t *f1ap_setup_resp) { - F1AP_F1AP_PDU_t pdu= {0}; uint8_t *buffer=NULL; - uint32_t len=0; - /* Create */ - /* 0. Message Type */ - pdu.present = F1AP_F1AP_PDU_PR_successfulOutcome; - asn1cCalloc(pdu.choice.successfulOutcome, tmp); - tmp->procedureCode = F1AP_ProcedureCode_id_F1Setup; - tmp->criticality = F1AP_Criticality_reject; - tmp->value.present = F1AP_SuccessfulOutcome__value_PR_F1SetupResponse; - F1AP_F1SetupResponse_t *out = &pdu.choice.successfulOutcome->value.choice.F1SetupResponse; - /* mandatory */ - /* c1. Transaction ID (integer value)*/ - asn1cSequenceAdd(out->protocolIEs.list, F1AP_F1SetupResponseIEs_t, ie1); - ie1->id = F1AP_ProtocolIE_ID_id_TransactionID; - ie1->criticality = F1AP_Criticality_reject; - ie1->value.present = F1AP_F1SetupResponseIEs__value_PR_TransactionID; - ie1->value.choice.TransactionID = f1ap_setup_resp->transaction_id; + uint32_t len = 0; - /* optional */ - /* c2. GNB_CU_Name */ - if (f1ap_setup_resp->gNB_CU_name != NULL) { - asn1cSequenceAdd(out->protocolIEs.list, F1AP_F1SetupResponseIEs_t, ie2); - ie2->id = F1AP_ProtocolIE_ID_id_gNB_CU_Name; - ie2->criticality = F1AP_Criticality_ignore; - ie2->value.present = F1AP_F1SetupResponseIEs__value_PR_GNB_CU_Name; - OCTET_STRING_fromBuf(&ie2->value.choice.GNB_CU_Name, f1ap_setup_resp->gNB_CU_name, - strlen(f1ap_setup_resp->gNB_CU_name)); - } - - /* mandatory */ - /* c3. cells to be Activated list */ - int num_cells_to_activate = f1ap_setup_resp->num_cells_to_activate; - LOG_D(F1AP, "num_cells_to_activate = %d \n", num_cells_to_activate); - - if (num_cells_to_activate >0) { - asn1cSequenceAdd(out->protocolIEs.list, F1AP_F1SetupResponseIEs_t, ie3); - ie3->id = F1AP_ProtocolIE_ID_id_Cells_to_be_Activated_List; - ie3->criticality = F1AP_Criticality_reject; - ie3->value.present = F1AP_F1SetupResponseIEs__value_PR_Cells_to_be_Activated_List; - - for (int i=0; ivalue.choice.Cells_to_be_Activated_List.list, - F1AP_Cells_to_be_Activated_List_ItemIEs_t, cells_to_be_activated_ies); - cells_to_be_activated_ies->id = F1AP_ProtocolIE_ID_id_Cells_to_be_Activated_List_Item; - cells_to_be_activated_ies->criticality = F1AP_Criticality_reject; - cells_to_be_activated_ies->value.present = F1AP_Cells_to_be_Activated_List_ItemIEs__value_PR_Cells_to_be_Activated_List_Item; - /* 3.1 cells to be Activated list item */ - F1AP_Cells_to_be_Activated_List_Item_t *cells_to_be_activated_item= - &cells_to_be_activated_ies->value.choice.Cells_to_be_Activated_List_Item; - /* - nRCGI */ - addnRCGI(cells_to_be_activated_item->nRCGI, f1ap_setup_resp->cells_to_activate+i); - - /* optional */ - /* - nRPCI */ - if (1) { - cells_to_be_activated_item->nRPCI = (F1AP_NRPCI_t *)calloc(1, sizeof(F1AP_NRPCI_t)); - *cells_to_be_activated_item->nRPCI = f1ap_setup_resp->cells_to_activate[i].nrpci; // int 0..1007 - } - - /* optional */ - /* - gNB-CU System Information */ - if (f1ap_setup_resp->cells_to_activate[i].num_SI > 0) { - /* 3.1.2 gNB-CUSystem Information */ - F1AP_ProtocolExtensionContainer_10696P112_t *p = calloc(1, sizeof(* p)); - cells_to_be_activated_item->iE_Extensions = (struct F1AP_ProtocolExtensionContainer *) p; - asn1cSequenceAdd(p->list, F1AP_Cells_to_be_Activated_List_ItemExtIEs_t, cells_to_be_activated_itemExtIEs); - cells_to_be_activated_itemExtIEs->id = F1AP_ProtocolIE_ID_id_gNB_CUSystemInformation; - cells_to_be_activated_itemExtIEs->criticality = F1AP_Criticality_reject; - cells_to_be_activated_itemExtIEs->extensionValue.present = F1AP_Cells_to_be_Activated_List_ItemExtIEs__extensionValue_PR_GNB_CUSystemInformation; - F1AP_GNB_CUSystemInformation_t *gNB_CUSystemInformation = - &cells_to_be_activated_itemExtIEs->extensionValue.choice.GNB_CUSystemInformation; - - // for (int sIBtype=2;sIBtype<33;sIBtype++) { //21 ? 33 ? - for (int sIBtype=2; sIBtype<21; sIBtype++) { - if (f1ap_setup_resp->cells_to_activate[i].SI_container[sIBtype]!=NULL) { - AssertFatal(sIBtype < 6 || sIBtype == 9, "Illegal SI type %d\n",sIBtype); - asn1cSequenceAdd(gNB_CUSystemInformation->sibtypetobeupdatedlist.list, F1AP_SibtypetobeupdatedListItem_t, sib_item); - sib_item->sIBtype = sIBtype; - OCTET_STRING_fromBuf(&sib_item->sIBmessage, - (const char *)f1ap_setup_resp->cells_to_activate[i].SI_container[sIBtype], - f1ap_setup_resp->cells_to_activate[i].SI_container_length[sIBtype]); - LOG_D(F1AP, "f1ap_setup_resp->SI_container_length[%d][%d] = %d \n", i,sIBtype,f1ap_setup_resp->cells_to_activate[i].SI_container_length[sIBtype]); - } - } - } - } - } - - /* c5. RRC VERSION */ - asn1cSequenceAdd(out->protocolIEs.list, F1AP_F1SetupResponseIEs_t, ie4); - ie4->id = F1AP_ProtocolIE_ID_id_GNB_CU_RRC_Version; - ie4->criticality = F1AP_Criticality_reject; - ie4->value.present = F1AP_F1SetupResponseIEs__value_PR_RRC_Version; - // RRC Version: "This IE is not used in this release." - // we put one bit for each byte in rrc_ver that is != 0 - uint8_t bits = 0; - for (int i = 0; i < 3; ++i) - bits |= (f1ap_setup_resp->rrc_ver[i] != 0) << i; - BIT_STRING_t *bs = &ie4->value.choice.RRC_Version.latest_RRC_Version; - bs->buf = calloc(1, sizeof(char)); - AssertFatal(bs->buf != NULL, "out of memory\n"); - bs->buf[0] = bits; - bs->size = 1; - bs->bits_unused = 5; - - F1AP_ProtocolExtensionContainer_10696P228_t *p = (F1AP_ProtocolExtensionContainer_10696P228_t*)calloc(1, sizeof(F1AP_ProtocolExtensionContainer_10696P228_t)); - asn1cSequenceAdd(p->list, F1AP_RRC_Version_ExtIEs_t, rrcv_ext); - rrcv_ext->id = F1AP_ProtocolIE_ID_id_latest_RRC_Version_Enhanced; - rrcv_ext->criticality = F1AP_Criticality_ignore; - rrcv_ext->extensionValue.present = F1AP_RRC_Version_ExtIEs__extensionValue_PR_OCTET_STRING_SIZE_3_; - OCTET_STRING_t *os = &rrcv_ext->extensionValue.choice.OCTET_STRING_SIZE_3_; - os->size = 3; - os->buf = malloc(3 * sizeof(*os->buf)); - AssertFatal(os->buf != NULL, "out of memory\n"); - for (int i = 0; i < 3; ++i) - os->buf[i] = f1ap_setup_resp->rrc_ver[i]; - ie4->value.choice.RRC_Version.iE_Extensions = (struct F1AP_ProtocolExtensionContainer *)p; + /* Encode F1 Setup Response */ + F1AP_F1AP_PDU_t *pdu = encode_f1ap_setup_response(f1ap_setup_resp); + /* Free after encode */ + free_f1ap_setup_response(f1ap_setup_resp); /* encode */ - if (f1ap_encode_pdu(&pdu, &buffer, &len) < 0) { + if (f1ap_encode_pdu(pdu, &buffer, &len) < 0) { LOG_E(F1AP, "Failed to encode F1 setup response\n"); + ASN_STRUCT_FREE(asn_DEF_F1AP_F1AP_PDU, pdu); return -1; } - - ASN_STRUCT_RESET(asn_DEF_F1AP_F1AP_PDU, &pdu); + ASN_STRUCT_FREE(asn_DEF_F1AP_F1AP_PDU, pdu); f1ap_itti_send_sctp_data_req(assoc_id, buffer, len); return 0; } +/** + * @brief F1 Setup Failure encoding and transmission + */ int CU_send_F1_SETUP_FAILURE(sctp_assoc_t assoc_id, const f1ap_setup_failure_t *fail) { LOG_D(F1AP, "CU_send_F1_SETUP_FAILURE\n"); - F1AP_F1AP_PDU_t pdu= {0}; - uint8_t *buffer=NULL; - uint32_t len=0; - /* Create */ - /* 0. Message Type */ - asn1cCalloc(pdu.choice.unsuccessfulOutcome, UnsuccessfulOutcome); - pdu.present = F1AP_F1AP_PDU_PR_unsuccessfulOutcome; - UnsuccessfulOutcome->procedureCode = F1AP_ProcedureCode_id_F1Setup; - UnsuccessfulOutcome->criticality = F1AP_Criticality_reject; - UnsuccessfulOutcome->value.present = F1AP_UnsuccessfulOutcome__value_PR_F1SetupFailure; - F1AP_F1SetupFailure_t *out = &pdu.choice.unsuccessfulOutcome->value.choice.F1SetupFailure; - /* mandatory */ - /* c1. Transaction ID (integer value)*/ - asn1cSequenceAdd(out->protocolIEs.list, F1AP_F1SetupFailureIEs_t, ie1); - ie1->id = F1AP_ProtocolIE_ID_id_TransactionID; - ie1->criticality = F1AP_Criticality_reject; - ie1->value.present = F1AP_F1SetupFailureIEs__value_PR_TransactionID; - ie1->value.choice.TransactionID = F1AP_get_next_transaction_identifier(0, 0); - /* mandatory */ - /* c2. Cause */ - asn1cSequenceAdd(out->protocolIEs.list, F1AP_F1SetupFailureIEs_t, ie2); - ie2->id = F1AP_ProtocolIE_ID_id_Cause; - ie2->criticality = F1AP_Criticality_ignore; - ie2->value.present = F1AP_F1SetupFailureIEs__value_PR_Cause; - ie2->value.choice.Cause.present = F1AP_Cause_PR_radioNetwork; - ie2->value.choice.Cause.choice.radioNetwork = F1AP_CauseRadioNetwork_unspecified; - - /* optional */ - /* c3. TimeToWait */ - if (0) { - asn1cSequenceAdd(out->protocolIEs.list, F1AP_F1SetupFailureIEs_t, ie3); - ie3->id = F1AP_ProtocolIE_ID_id_TimeToWait; - ie3->criticality = F1AP_Criticality_ignore; - ie3->value.present = F1AP_F1SetupFailureIEs__value_PR_TimeToWait; - ie3->value.choice.TimeToWait = F1AP_TimeToWait_v10s; - } - - /* optional */ - /* c4. CriticalityDiagnostics*/ - if (0) { - asn1cSequenceAdd(out->protocolIEs.list, F1AP_F1SetupFailureIEs_t, ie4); - ie4->id = F1AP_ProtocolIE_ID_id_CriticalityDiagnostics; - ie4->criticality = F1AP_Criticality_ignore; - ie4->value.present = F1AP_F1SetupFailureIEs__value_PR_CriticalityDiagnostics; - asn1cCallocOne(ie4->value.choice.CriticalityDiagnostics.procedureCode, - F1AP_ProcedureCode_id_UEContextSetup); - asn1cCallocOne(ie4->value.choice.CriticalityDiagnostics.triggeringMessage, - F1AP_TriggeringMessage_initiating_message); - asn1cCallocOne(ie4->value.choice.CriticalityDiagnostics.procedureCriticality, - F1AP_Criticality_reject); - asn1cCallocOne(ie4->value.choice.CriticalityDiagnostics.transactionID, - 0); - } - - /* encode */ - if (f1ap_encode_pdu(&pdu, &buffer, &len) < 0) { + uint8_t *buffer = NULL; + uint32_t len = 0; + /* Encode F1 Setup Failure */ + F1AP_F1AP_PDU_t *pdu = encode_f1ap_setup_failure(fail); + if (f1ap_encode_pdu(pdu, &buffer, &len) < 0) { LOG_E(F1AP, "Failed to encode F1 setup failure\n"); + ASN_STRUCT_FREE(asn_DEF_F1AP_F1AP_PDU, pdu); return -1; } - - ASN_STRUCT_RESET(asn_DEF_F1AP_F1AP_PDU, &pdu); + ASN_STRUCT_FREE(asn_DEF_F1AP_F1AP_PDU, pdu); f1ap_itti_send_sctp_data_req(assoc_id, buffer, len); return 0; } -/* - gNB-DU Configuration Update -*/ - +/** + * @brief Decode and send F1 gNB-DU Configuration Update message to RRC + */ int CU_handle_gNB_DU_CONFIGURATION_UPDATE(instance_t instance, sctp_assoc_t assoc_id, uint32_t stream, F1AP_F1AP_PDU_t *pdu) { - LOG_D(F1AP, "CU_handle_gNB_DU_CONFIGURATION_UPDATE\n"); - F1AP_GNBDUConfigurationUpdate_t *container; - F1AP_GNBDUConfigurationUpdateIEs_t *ie; - int i = 0; + LOG_D(F1AP, "[SCTP %d] CU_handle_gNB_DU_CONFIGURATION_UPDATE\n", assoc_id); DevAssert(pdu != NULL); - container = &pdu->choice.initiatingMessage->value.choice.GNBDUConfigurationUpdate; - /* gNB DU Configuration Update == Non UE-related procedure -> stream 0 */ if (stream != 0) { LOG_W(F1AP, "[SCTP %d] Received f1 setup request on stream != 0 (%d)\n", assoc_id, stream); } - + /* Decode */ + f1ap_gnb_du_configuration_update_t msg = {0}; + if (!decode_f1ap_du_configuration_update(pdu, &msg)) { + LOG_E(F1AP, "cannot decode F1AP gNB-DU Configuration Update\n"); + free_f1ap_du_configuration_update(&msg); + return -1; + } + /* Send to RRC */ MessageDef *message_p = itti_alloc_new_message(TASK_CU_F1, 0, F1AP_GNB_DU_CONFIGURATION_UPDATE); message_p->ittiMsgHeader.originInstance = assoc_id; - f1ap_gnb_du_configuration_update_t *req = &F1AP_GNB_DU_CONFIGURATION_UPDATE(message_p); - - /* 3GPP TS 38.473 Transaction ID*/ - F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_GNBDUConfigurationUpdateIEs_t, ie, container, F1AP_ProtocolIE_ID_id_TransactionID, true); - req->transaction_id = ie->value.choice.TransactionID; - LOG_D(F1AP, "req->transaction_id %lu \n", req->transaction_id); - - /* 3GPP TS 38.473 Served Cells To Add List */ - F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_GNBDUConfigurationUpdateIEs_t, - ie, - container, - F1AP_ProtocolIE_ID_id_Served_Cells_To_Add_List, - false); - - if (ie != NULL) { - req->num_cells_to_add = ie->value.choice.Served_Cells_To_Add_List.list.count; - LOG_D(F1AP, "req->num_cells_to_add %d \n", req->num_cells_to_add); - - for (i = 0; i < req->num_cells_to_add; i++) { - F1AP_Served_Cells_To_Add_Item_t *served_cells_item = - &((F1AP_Served_Cells_To_Add_ItemIEs_t *)ie->value.choice.Served_Cells_To_Add_List.list.array[i]) - ->value.choice.Served_Cells_To_Add_Item; - F1AP_Served_Cell_Information_t *servedCellInformation = &served_cells_item->served_Cell_Information; - /* tac */ - if (servedCellInformation->fiveGS_TAC) { - req->cell_to_add[i].info.tac = malloc(sizeof(*req->cell_to_add[i].info.tac)); - AssertFatal(req->cell_to_add[i].info.tac != NULL, "out of memory\n"); - OCTET_STRING_TO_INT24(servedCellInformation->fiveGS_TAC, *req->cell_to_add[i].info.tac); - LOG_D(F1AP, "req->tac[%d] %d \n", i, *req->cell_to_add[i].info.tac); - } - - /* - nRCGI */ - TBCD_TO_MCC_MNC(&(servedCellInformation->nRCGI.pLMN_Identity), - req->cell_to_add[i].info.plmn.mcc, - req->cell_to_add[i].info.plmn.mnc, - req->cell_to_add[i].info.plmn.mnc_digit_length); - // NR cellID - BIT_STRING_TO_NR_CELL_IDENTITY(&servedCellInformation->nRCGI.nRCellIdentity, req->cell_to_add[i].info.nr_cellid); - LOG_D(F1AP, - "[SCTP %d] Received nRCGI: MCC %d, MNC %d, CELL_ID %llu\n", - assoc_id, - req->cell_to_add[i].info.plmn.mcc, - req->cell_to_add[i].info.plmn.mnc, - (long long unsigned int)req->cell_to_add[i].info.nr_cellid); - - /* - nRPCI */ - req->cell_to_add[i].info.nr_pci = servedCellInformation->nRPCI; - LOG_D(F1AP, "req->nr_pci[%d] %d \n", i, req->cell_to_add[i].info.nr_pci); - - AssertFatal(servedCellInformation->servedPLMNs.list.count == 1, "only one PLMN handled\n"); - req->cell_to_add[i].info.num_ssi = - read_slice_info(servedCellInformation->servedPLMNs.list.array[0], req->cell_to_add[i].info.nssai, 16); - - // FDD Cells - if (servedCellInformation->nR_Mode_Info.present == F1AP_NR_Mode_Info_PR_fDD) { - req->cell_to_add[i].info.mode = F1AP_MODE_FDD; - f1ap_fdd_info_t *FDDs = &req->cell_to_add[i].info.fdd; - F1AP_FDD_Info_t *fDD_Info = servedCellInformation->nR_Mode_Info.choice.fDD; - FDDs->ul_freqinfo.arfcn = fDD_Info->uL_NRFreqInfo.nRARFCN; - AssertFatal(fDD_Info->uL_NRFreqInfo.freqBandListNr.list.count == 1, "cannot handle more than one frequency band\n"); - for (int f = 0; f < fDD_Info->uL_NRFreqInfo.freqBandListNr.list.count; f++) { - F1AP_FreqBandNrItem_t *FreqItem = fDD_Info->uL_NRFreqInfo.freqBandListNr.list.array[f]; - FDDs->ul_freqinfo.band = FreqItem->freqBandIndicatorNr; - AssertFatal(FreqItem->supportedSULBandList.list.count == 0, "cannot handle SUL bands!\n"); - } - FDDs->dl_freqinfo.arfcn = fDD_Info->dL_NRFreqInfo.nRARFCN; - int dlBands = fDD_Info->dL_NRFreqInfo.freqBandListNr.list.count; - AssertFatal(dlBands == 0, "cannot handled more than one frequency band\n"); - for (int dlB = 0; dlB < dlBands; dlB++) { - F1AP_FreqBandNrItem_t *FreqItem = fDD_Info->dL_NRFreqInfo.freqBandListNr.list.array[dlB]; - FDDs->dl_freqinfo.band = FreqItem->freqBandIndicatorNr; - int num_available_supported_SULBands = FreqItem->supportedSULBandList.list.count; - AssertFatal(num_available_supported_SULBands == 0, "cannot handle SUL bands!\n"); - } - FDDs->ul_tbw.scs = fDD_Info->uL_Transmission_Bandwidth.nRSCS; - FDDs->ul_tbw.nrb = nrb_lut[fDD_Info->uL_Transmission_Bandwidth.nRNRB]; - FDDs->dl_tbw.scs = fDD_Info->dL_Transmission_Bandwidth.nRSCS; - FDDs->dl_tbw.nrb = nrb_lut[fDD_Info->dL_Transmission_Bandwidth.nRNRB]; - } else if (servedCellInformation->nR_Mode_Info.present == F1AP_NR_Mode_Info_PR_tDD) { - req->cell_to_add[i].info.mode = F1AP_MODE_TDD; - f1ap_tdd_info_t *TDDs = &req->cell_to_add[i].info.tdd; - F1AP_TDD_Info_t *tDD_Info = servedCellInformation->nR_Mode_Info.choice.tDD; - TDDs->freqinfo.arfcn = tDD_Info->nRFreqInfo.nRARFCN; - AssertFatal(tDD_Info->nRFreqInfo.freqBandListNr.list.count == 1, "cannot handle more than one frequency band\n"); - for (int f = 0; f < tDD_Info->nRFreqInfo.freqBandListNr.list.count; f++) { - struct F1AP_FreqBandNrItem *FreqItem = tDD_Info->nRFreqInfo.freqBandListNr.list.array[f]; - TDDs->freqinfo.band = FreqItem->freqBandIndicatorNr; - int num_available_supported_SULBands = FreqItem->supportedSULBandList.list.count; - AssertFatal(num_available_supported_SULBands == 0, "cannot hanlde SUL bands!\n"); - } - TDDs->tbw.scs = tDD_Info->transmission_Bandwidth.nRSCS; - TDDs->tbw.nrb = nrb_lut[tDD_Info->transmission_Bandwidth.nRNRB]; - } else { - AssertFatal(false, "unknown NR Mode info %d\n", servedCellInformation->nR_Mode_Info.present); - } - - /* MeasurementConfig */ - if (servedCellInformation->measurementTimingConfiguration.size > 0) - req->cell_to_add[i].info.measurement_timing_config = - cp_octet_string(&servedCellInformation->measurementTimingConfiguration, - &req->cell_to_add[i].info.measurement_timing_config_len); - - struct F1AP_GNB_DU_System_Information *DUsi = served_cells_item->gNB_DU_System_Information; - // System Information - req->cell_to_add[i].sys_info = calloc(1, sizeof(*req->cell_to_add[i].sys_info)); - AssertFatal(req->cell_to_add[i].sys_info != NULL, "out of memory\n"); - f1ap_gnb_du_system_info_t *sys_info = req->cell_to_add[i].sys_info; - /* mib */ - sys_info->mib = calloc(DUsi->mIB_message.size, sizeof(char)); - memcpy(sys_info->mib, DUsi->mIB_message.buf, DUsi->mIB_message.size); - sys_info->mib_length = DUsi->mIB_message.size; - /* sib1 */ - sys_info->sib1 = calloc(DUsi->sIB1_message.size, sizeof(char)); - memcpy(sys_info->sib1, DUsi->sIB1_message.buf, DUsi->sIB1_message.size); - sys_info->sib1_length = DUsi->sIB1_message.size; - } - } else { - req->num_cells_to_add = 0; - } - /* 3GPP TS 38.473 Served Cells To Modify List */ - F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_GNBDUConfigurationUpdateIEs_t, - ie, - container, - F1AP_ProtocolIE_ID_id_Served_Cells_To_Modify_List, - false); - - if (ie) { - req->num_cells_to_modify = ie->value.choice.Served_Cells_To_Modify_List.list.count; - LOG_D(F1AP, "req->num_cells_to_modify %d \n", req->num_cells_to_modify); - - for (i = 0; i < req->num_cells_to_modify; i++) { - F1AP_Served_Cells_To_Modify_Item_t *served_cells_item = - &((F1AP_Served_Cells_To_Modify_ItemIEs_t *)ie->value.choice.Served_Cells_To_Modify_List.list.array[i]) - ->value.choice.Served_Cells_To_Modify_Item; - - /* OLD NRCGI */ - TBCD_TO_MCC_MNC(&(served_cells_item->oldNRCGI.pLMN_Identity), - req->cell_to_modify[i].old_plmn.mcc, - req->cell_to_modify[i].old_plmn.mnc, - req->cell_to_modify[i].old_plmn.mnc_digit_length); - - BIT_STRING_TO_NR_CELL_IDENTITY(&served_cells_item->oldNRCGI.nRCellIdentity, req->cell_to_modify[i].old_nr_cellid); - - F1AP_Served_Cell_Information_t *servedCellInformation = &served_cells_item->served_Cell_Information; - /* SERVED CELL INFORMATION*/ - /* tac */ - if (servedCellInformation->fiveGS_TAC) { - req->cell_to_modify[i].info.tac = malloc(sizeof(*req->cell_to_modify[i].info.tac)); - AssertFatal(req->cell_to_modify[i].info.tac != NULL, "out of memory\n"); - OCTET_STRING_TO_INT24(servedCellInformation->fiveGS_TAC, *req->cell_to_modify[i].info.tac); - LOG_D(F1AP, "req->tac[%d] %d \n", i, *req->cell_to_modify[i].info.tac); - } - - /* - nRCGI */ - TBCD_TO_MCC_MNC(&(servedCellInformation->nRCGI.pLMN_Identity), - req->cell_to_modify[i].info.plmn.mcc, - req->cell_to_modify[i].info.plmn.mnc, - req->cell_to_modify[i].info.plmn.mnc_digit_length); - // NR cellID - BIT_STRING_TO_NR_CELL_IDENTITY(&servedCellInformation->nRCGI.nRCellIdentity, req->cell_to_modify[i].info.nr_cellid); - LOG_D(F1AP, - "[SCTP %d] Received nRCGI: MCC %d, MNC %d, CELL_ID %llu\n", - assoc_id, - req->cell_to_modify[i].info.plmn.mcc, - req->cell_to_modify[i].info.plmn.mnc, - (long long unsigned int)req->cell_to_modify[i].info.nr_cellid); - - /* - nRPCI */ - req->cell_to_modify[i].info.nr_pci = servedCellInformation->nRPCI; - LOG_D(F1AP, "req->nr_pci[%d] %d \n", i, req->cell_to_modify[i].info.nr_pci); - - // FDD Cells - if (servedCellInformation->nR_Mode_Info.present == F1AP_NR_Mode_Info_PR_fDD) { - req->cell_to_modify[i].info.mode = F1AP_MODE_FDD; - f1ap_fdd_info_t *FDDs = &req->cell_to_modify[i].info.fdd; - F1AP_FDD_Info_t *fDD_Info = servedCellInformation->nR_Mode_Info.choice.fDD; - FDDs->ul_freqinfo.arfcn = fDD_Info->uL_NRFreqInfo.nRARFCN; - AssertFatal(fDD_Info->uL_NRFreqInfo.freqBandListNr.list.count == 1, "cannot handle more than one frequency band\n"); - for (int f = 0; f < fDD_Info->uL_NRFreqInfo.freqBandListNr.list.count; f++) { - F1AP_FreqBandNrItem_t *FreqItem = fDD_Info->uL_NRFreqInfo.freqBandListNr.list.array[f]; - FDDs->ul_freqinfo.band = FreqItem->freqBandIndicatorNr; - AssertFatal(FreqItem->supportedSULBandList.list.count == 0, "cannot handle SUL bands!\n"); - } - FDDs->dl_freqinfo.arfcn = fDD_Info->dL_NRFreqInfo.nRARFCN; - int dlBands = fDD_Info->dL_NRFreqInfo.freqBandListNr.list.count; - AssertFatal(dlBands == 0, "cannot handled more than one frequency band\n"); - for (int dlB = 0; dlB < dlBands; dlB++) { - F1AP_FreqBandNrItem_t *FreqItem = fDD_Info->dL_NRFreqInfo.freqBandListNr.list.array[dlB]; - FDDs->dl_freqinfo.band = FreqItem->freqBandIndicatorNr; - int num_available_supported_SULBands = FreqItem->supportedSULBandList.list.count; - AssertFatal(num_available_supported_SULBands == 0, "cannot handle SUL bands!\n"); - } - FDDs->ul_tbw.scs = fDD_Info->uL_Transmission_Bandwidth.nRSCS; - FDDs->ul_tbw.nrb = nrb_lut[fDD_Info->uL_Transmission_Bandwidth.nRNRB]; - FDDs->dl_tbw.scs = fDD_Info->dL_Transmission_Bandwidth.nRSCS; - FDDs->dl_tbw.nrb = nrb_lut[fDD_Info->dL_Transmission_Bandwidth.nRNRB]; - } else if (servedCellInformation->nR_Mode_Info.present == F1AP_NR_Mode_Info_PR_tDD) { - req->cell_to_modify[i].info.mode = F1AP_MODE_TDD; - f1ap_tdd_info_t *TDDs = &req->cell_to_modify[i].info.tdd; - F1AP_TDD_Info_t *tDD_Info = servedCellInformation->nR_Mode_Info.choice.tDD; - TDDs->freqinfo.arfcn = tDD_Info->nRFreqInfo.nRARFCN; - AssertFatal(tDD_Info->nRFreqInfo.freqBandListNr.list.count == 1, "cannot handle more than one frequency band\n"); - for (int f = 0; f < tDD_Info->nRFreqInfo.freqBandListNr.list.count; f++) { - struct F1AP_FreqBandNrItem *FreqItem = tDD_Info->nRFreqInfo.freqBandListNr.list.array[f]; - TDDs->freqinfo.band = FreqItem->freqBandIndicatorNr; - int num_available_supported_SULBands = FreqItem->supportedSULBandList.list.count; - AssertFatal(num_available_supported_SULBands == 0, "cannot hanlde SUL bands!\n"); - } - TDDs->tbw.scs = tDD_Info->transmission_Bandwidth.nRSCS; - TDDs->tbw.nrb = nrb_lut[tDD_Info->transmission_Bandwidth.nRNRB]; - } else { - AssertFatal(false, "unknown NR Mode info %d\n", servedCellInformation->nR_Mode_Info.present); - } - - /* MeasurementConfig */ - if (servedCellInformation->measurementTimingConfiguration.size > 0) - req->cell_to_modify[i].info.measurement_timing_config = - cp_octet_string(&servedCellInformation->measurementTimingConfiguration, - &req->cell_to_modify[i].info.measurement_timing_config_len); - - /*gNB DU SYSTEM INFORMATION */ - struct F1AP_GNB_DU_System_Information *DUsi = served_cells_item->gNB_DU_System_Information; - if (DUsi != NULL) { - // System Information - req->cell_to_modify[i].sys_info = calloc(1, sizeof(*req->cell_to_modify[i].sys_info)); - AssertFatal(req->cell_to_modify[i].sys_info != NULL, "out of memory\n"); - f1ap_gnb_du_system_info_t *sys_info = req->cell_to_modify[i].sys_info; - /* mib */ - sys_info->mib = calloc(DUsi->mIB_message.size, sizeof(char)); - AssertFatal(req->cell_to_modify[i].sys_info->mib != NULL, "out of memory\n"); - memcpy(sys_info->mib, DUsi->mIB_message.buf, DUsi->mIB_message.size); - sys_info->mib_length = DUsi->mIB_message.size; - - /* sib1 */ - sys_info->sib1 = calloc(DUsi->sIB1_message.size, sizeof(char)); - AssertFatal(req->cell_to_modify[i].sys_info->sib1 != NULL, "out of memory\n"); - memcpy(sys_info->sib1, DUsi->sIB1_message.buf, DUsi->sIB1_message.size); - sys_info->sib1_length = DUsi->sIB1_message.size; - } - } - } else { - req->num_cells_to_modify = 0; - } - - /* 3GPP TS 38.473 Served Cells To Delete List */ - F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_GNBDUConfigurationUpdateIEs_t, - ie, - container, - F1AP_ProtocolIE_ID_id_Served_Cells_To_Delete_List, - false); - if (ie) { - req->num_cells_to_delete = ie->value.choice.Served_Cells_To_Delete_List.list.count; - LOG_D(F1AP, "req->num_cells_to_delete %d \n", req->num_cells_to_delete); - - for (i = 0; i < req->num_cells_to_delete; i++) { - F1AP_Served_Cells_To_Delete_Item_t *served_cells_item = - &((F1AP_Served_Cells_To_Delete_ItemIEs_t *)ie->value.choice.Served_Cells_To_Delete_List.list.array[i]) - ->value.choice.Served_Cells_To_Delete_Item; - /* - Old nRCGI */ - TBCD_TO_MCC_MNC(&(served_cells_item->oldNRCGI.pLMN_Identity), - req->cell_to_delete[i].plmn.mcc, - req->cell_to_delete[i].plmn.mnc, - req->cell_to_delete[i].plmn.mnc_digit_length); - // NR cellID - BIT_STRING_TO_NR_CELL_IDENTITY(&served_cells_item->oldNRCGI.nRCellIdentity, req->cell_to_delete[i].nr_cellid); - LOG_D(F1AP, - "[SCTP %d] Received nRCGI to delete: MCC %d, MNC %d, CELL_ID %llu\n", - assoc_id, - req->cell_to_delete[i].plmn.mcc, - req->cell_to_delete[i].plmn.mnc, - (long long unsigned int)req->cell_to_delete[i].nr_cellid); - } - } else { - req->num_cells_to_delete = 0; - } - - /* 3GPP TS 38.473 Cells Status List */ - F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_GNBDUConfigurationUpdateIEs_t, ie, container, F1AP_ProtocolIE_ID_id_Cells_Status_List, false); - - /* 3GPP TS 38.473 Dedicated SI Delivery Needed UE List */ - F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_GNBDUConfigurationUpdateIEs_t, - ie, - container, - F1AP_ProtocolIE_ID_id_Dedicated_SIDelivery_NeededUE_List, - false); - - /* 3GPP TS 38.473 gNB-DU ID */ - F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_GNBDUConfigurationUpdateIEs_t, ie, container, F1AP_ProtocolIE_ID_id_gNB_DU_ID, false); - if (ie != NULL) - asn_INTEGER2ulong(&ie->value.choice.GNB_DU_ID, req->gNB_DU_ID); - - /* 3GPP TS 38.473 gNB-DU TNL Association To Remove List */ - F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_GNBDUConfigurationUpdateIEs_t, - ie, - container, - F1AP_ProtocolIE_ID_id_GNB_DU_TNL_Association_To_Remove_List, - false); - + f1ap_gnb_du_configuration_update_t *req = &F1AP_GNB_DU_CONFIGURATION_UPDATE(message_p); // RRC thread will free it + *req = msg; // copy F1 message to ITTI + free_f1ap_du_configuration_update(&msg); LOG_D(F1AP, "Sending F1AP_GNB_DU_CONFIGURATION_UPDATE ITTI message \n"); itti_send_msg_to_task(TASK_RRC_GNB, GNB_MODULE_ID_TO_INSTANCE(instance), message_p); return 0; } -int CU_send_gNB_DU_CONFIGURATION_FAILURE(sctp_assoc_t assoc_id, - f1ap_gnb_du_configuration_update_failure_t *GNBDUConfigurationUpdateFailure) +int CU_send_gNB_DU_CONFIGURATION_UPDATE_ACKNOWLEDGE(sctp_assoc_t assoc_id, f1ap_gnb_du_configuration_update_acknowledge_t *msg) { - AssertFatal(1==0,"Not implemented yet\n"); -} - -int CU_send_gNB_DU_CONFIGURATION_UPDATE_ACKNOWLEDGE( - sctp_assoc_t assoc_id, - f1ap_gnb_du_configuration_update_acknowledge_t *GNBDUConfigurationUpdateAcknowledge) -{ - F1AP_F1AP_PDU_t pdu = {}; uint8_t *buffer; uint32_t len; - - /* Create */ - /* 0. Message */ - - pdu.present = F1AP_F1AP_PDU_PR_successfulOutcome; - asn1cCalloc(pdu.choice.successfulOutcome, succOut); - succOut->procedureCode = F1AP_ProcedureCode_id_gNBDUConfigurationUpdate; - succOut->criticality = F1AP_Criticality_reject; - succOut->value.present = F1AP_SuccessfulOutcome__value_PR_GNBDUConfigurationUpdateAcknowledge; - F1AP_GNBDUConfigurationUpdateAcknowledge_t *ack = &succOut->value.choice.GNBDUConfigurationUpdateAcknowledge; - - /* Mandatory */ - /* Transaction Id */ - asn1cSequenceAdd(ack->protocolIEs.list, F1AP_GNBDUConfigurationUpdateAcknowledgeIEs_t, ie1); - ie1->id = F1AP_ProtocolIE_ID_id_TransactionID; - ie1->criticality = F1AP_Criticality_reject; - ie1->value.present = F1AP_GNBDUConfigurationUpdateAcknowledgeIEs__value_PR_TransactionID; - ie1->value.choice.TransactionID = GNBDUConfigurationUpdateAcknowledge->transaction_id; - - /* Todo add optional fields */ - /* encode */ - - if (f1ap_encode_pdu(&pdu, &buffer, &len) < 0) { - LOG_E(F1AP, "Failed to encode F1 gNB-DU CONFIGURATION UPDATE\n"); + /* Encode F1 gNB-CU Configuration Update message */ + F1AP_F1AP_PDU_t *pdu = encode_f1ap_du_configuration_update_acknowledge(msg); + /* Encode F1AP PDU */ + if (f1ap_encode_pdu(pdu, &buffer, &len) < 0) { + ASN_STRUCT_FREE(asn_DEF_F1AP_F1AP_PDU, pdu); + LOG_E(F1AP, "Failed to encode F1 gNB-DU Configuration Update Acknowledge\n"); return -1; } - LOG_DUMPMSG(F1AP, LOG_DUMP_CHAR, buffer, len, "F1AP gNB-DU CONFIGURATION UPDATE : "); - ASN_STRUCT_RESET(asn_DEF_F1AP_F1AP_PDU, &pdu); + ASN_STRUCT_FREE(asn_DEF_F1AP_F1AP_PDU, pdu); f1ap_itti_send_sctp_data_req(assoc_id, buffer, len); return 0; } -/* - gNB-CU Configuration Update -*/ - -int CU_send_gNB_CU_CONFIGURATION_UPDATE(sctp_assoc_t assoc_id, f1ap_gnb_cu_configuration_update_t *f1ap_gnb_cu_configuration_update) +/** + * @brief F1 gNB-CU Configuration Update message encoding and transfer + */ +int CU_send_gNB_CU_CONFIGURATION_UPDATE(sctp_assoc_t assoc_id, f1ap_gnb_cu_configuration_update_t *msg) { - F1AP_F1AP_PDU_t pdu= {0}; + /* complete F1AP message */ + msg->transaction_id = F1AP_get_next_transaction_identifier(0, 0); // note: has to be done in the caller uint8_t *buffer; uint32_t len; - /* Create */ - /* 0. Message Type */ - pdu.present = F1AP_F1AP_PDU_PR_initiatingMessage; - asn1cCalloc(pdu.choice.initiatingMessage, initMsg); - initMsg->procedureCode = F1AP_ProcedureCode_id_gNBCUConfigurationUpdate; - initMsg->criticality = F1AP_Criticality_reject; - initMsg->value.present = F1AP_InitiatingMessage__value_PR_GNBCUConfigurationUpdate; - F1AP_GNBCUConfigurationUpdate_t *cfgUpdate = &pdu.choice.initiatingMessage->value.choice.GNBCUConfigurationUpdate; - /* mandatory */ - /* c1. Transaction ID (integer value) */ - asn1cSequenceAdd(cfgUpdate->protocolIEs.list, F1AP_GNBCUConfigurationUpdateIEs_t, ieC1); - ieC1->id = F1AP_ProtocolIE_ID_id_TransactionID; - ieC1->criticality = F1AP_Criticality_reject; - ieC1->value.present = F1AP_GNBCUConfigurationUpdateIEs__value_PR_TransactionID; - ieC1->value.choice.TransactionID = F1AP_get_next_transaction_identifier(0, 0); - - // mandatory - // c2. Cells_to_be_Activated_List - if (f1ap_gnb_cu_configuration_update->num_cells_to_activate > 0) { - asn1cSequenceAdd(cfgUpdate->protocolIEs.list, F1AP_GNBCUConfigurationUpdateIEs_t, ieC3); - ieC3->id = F1AP_ProtocolIE_ID_id_Cells_to_be_Activated_List; - ieC3->criticality = F1AP_Criticality_reject; - ieC3->value.present = F1AP_GNBCUConfigurationUpdateIEs__value_PR_Cells_to_be_Activated_List; - - for (int i=0; inum_cells_to_activate; i++) { - asn1cSequenceAdd(ieC3->value.choice.Cells_to_be_Activated_List.list,F1AP_Cells_to_be_Activated_List_ItemIEs_t, - cells_to_be_activated_ies); - cells_to_be_activated_ies->id = F1AP_ProtocolIE_ID_id_Cells_to_be_Activated_List_Item; - cells_to_be_activated_ies->criticality = F1AP_Criticality_reject; - cells_to_be_activated_ies->value.present = F1AP_Cells_to_be_Activated_List_ItemIEs__value_PR_Cells_to_be_Activated_List_Item; - // 2.1 cells to be Activated list item - F1AP_Cells_to_be_Activated_List_Item_t *cells_to_be_activated_list_item= - &cells_to_be_activated_ies->value.choice.Cells_to_be_Activated_List_Item; - // - nRCGI - addnRCGI(cells_to_be_activated_list_item->nRCGI, f1ap_gnb_cu_configuration_update->cells_to_activate+i); - // optional - // -nRPCI - asn1cCalloc(cells_to_be_activated_list_item->nRPCI, tmp); - *tmp = f1ap_gnb_cu_configuration_update->cells_to_activate[i].nrpci; // int 0..1007 - // optional - // 3.1.2 gNB-CUSystem Information - F1AP_ProtocolExtensionContainer_10696P112_t *p = calloc(1,sizeof(*p)); - cells_to_be_activated_list_item->iE_Extensions = (struct F1AP_ProtocolExtensionContainer *) p; - //F1AP_ProtocolExtensionContainer_154P112_t - asn1cSequenceAdd(p->list, F1AP_Cells_to_be_Activated_List_ItemExtIEs_t, cells_to_be_activated_itemExtIEs); - cells_to_be_activated_itemExtIEs->id = F1AP_ProtocolIE_ID_id_gNB_CUSystemInformation; - cells_to_be_activated_itemExtIEs->criticality = F1AP_Criticality_reject; - cells_to_be_activated_itemExtIEs->extensionValue.present = F1AP_Cells_to_be_Activated_List_ItemExtIEs__extensionValue_PR_GNB_CUSystemInformation; - - if (f1ap_gnb_cu_configuration_update->cells_to_activate[i].num_SI > 0) { - F1AP_GNB_CUSystemInformation_t *gNB_CUSystemInformation = - &cells_to_be_activated_itemExtIEs->extensionValue.choice.GNB_CUSystemInformation; - //LOG_I(F1AP, "%s() SI %d size %d: ", __func__, i, f1ap_setup_resp->SI_container_length[i][0]); - //for (int n = 0; n < f1ap_setup_resp->SI_container_length[i][0]; n++) - // printf("%02x ", f1ap_setup_resp->SI_container[i][0][n]); - //printf("\n"); - - // for (int sIBtype=2;sIBtype<33;sIBtype++) { //21 ? 33 ? - for (int sIBtype=2; sIBtype<21; sIBtype++) { - if (f1ap_gnb_cu_configuration_update->cells_to_activate[i].SI_container[sIBtype]!=NULL) { - AssertFatal(sIBtype < 6 || sIBtype == 9, "Illegal SI type %d\n",sIBtype); - asn1cSequenceAdd(gNB_CUSystemInformation->sibtypetobeupdatedlist.list, F1AP_SibtypetobeupdatedListItem_t, sib_item); - sib_item->sIBtype = sIBtype; - OCTET_STRING_fromBuf(&sib_item->sIBmessage, - (const char *)f1ap_gnb_cu_configuration_update->cells_to_activate[i].SI_container[sIBtype], - f1ap_gnb_cu_configuration_update->cells_to_activate[i].SI_container_length[sIBtype]); - LOG_D(F1AP, "f1ap_setup_resp->SI_container_length[%d][%d] = %d \n", i,sIBtype, - f1ap_gnb_cu_configuration_update->cells_to_activate[i].SI_container_length[sIBtype]); - } - } - } - } - } - - /* encode */ - if (f1ap_encode_pdu(&pdu, &buffer, &len) < 0) { - LOG_E(F1AP, "Failed to encode F1 gNB-CU CONFIGURATION UPDATE\n"); + /* Encode F1 gNB-CU Configuration Update message */ + F1AP_F1AP_PDU_t *pdu = encode_f1ap_cu_configuration_update(msg); + /* Free after encoding */ + free_f1ap_cu_configuration_update(msg); + /* Encode F1AP PDU */ + if (f1ap_encode_pdu(pdu, &buffer, &len) < 0) { + ASN_STRUCT_FREE(asn_DEF_F1AP_F1AP_PDU, pdu); + LOG_E(F1AP, "Failed to encode F1 gNB-CU Configuration Update\n"); return -1; } - LOG_DUMPMSG(F1AP, LOG_DUMP_CHAR, buffer, len, "F1AP gNB-CU CONFIGURATION UPDATE : "); - ASN_STRUCT_RESET(asn_DEF_F1AP_F1AP_PDU, &pdu); + ASN_STRUCT_FREE(asn_DEF_F1AP_F1AP_PDU, pdu); f1ap_itti_send_sctp_data_req(assoc_id, buffer, len); return 0; } -int CU_handle_gNB_CU_CONFIGURATION_UPDATE_FAILURE(instance_t instance, sctp_assoc_t assoc_id, uint32_t stream, F1AP_F1AP_PDU_t *pdu) -{ - AssertFatal(1==0,"Not implemented yet\n"); -} - +/** + * @brief gNB CU Configuration Update Acknowledge decoding (9.2.1.11 of 3GPP TS 38.473) + * and handling by CU + */ int CU_handle_gNB_CU_CONFIGURATION_UPDATE_ACKNOWLEDGE(instance_t instance, sctp_assoc_t assoc_id, uint32_t stream, F1AP_F1AP_PDU_t *pdu) { - LOG_I(F1AP,"Cell Configuration ok (assoc_id %d)\n",assoc_id); - return(0); -} - -int CU_handle_gNB_DU_RESOURCE_COORDINATION_REQUEST(instance_t instance, - sctp_assoc_t assoc_id, - uint32_t stream, - F1AP_F1AP_PDU_t *pdu) -{ - AssertFatal(0, "Not implemented yet\n"); -} - -int CU_send_gNB_DU_RESOURCE_COORDINATION_RESPONSE(sctp_assoc_t assoc_id, - F1AP_GNBDUResourceCoordinationResponse_t *GNBDUResourceCoordinationResponse) { - AssertFatal(0, "Not implemented yet\n"); + DevAssert(pdu != NULL); + if (stream != 0) + LOG_W(F1AP, "[SCTP %d] Received gNB CU Configuration Update Acknowledge on stream != 0 (%d)\n", assoc_id, stream); + // Decode + f1ap_gnb_cu_configuration_update_acknowledge_t msg = {0}; + if (!decode_f1ap_cu_configuration_update_acknowledge(pdu, &msg)) { + LOG_E(F1AP, "Failed to decode gNB CU Configuration Update Acknowledge\n"); + return -1; + } + // Allocate ITTI message and send to RRC + MessageDef *message_p = itti_alloc_new_message(TASK_CU_F1, 0, F1AP_GNB_CU_CONFIGURATION_UPDATE_ACKNOWLEDGE); + message_p->ittiMsgHeader.originInstance = assoc_id; + f1ap_gnb_cu_configuration_update_acknowledge_t *ack = &F1AP_GNB_CU_CONFIGURATION_UPDATE_ACKNOWLEDGE(message_p); + *ack = msg; // copy decoded message to ITTI, the RRC thread will free it + itti_send_msg_to_task(TASK_RRC_GNB, GNB_MODULE_ID_TO_INSTANCE(instance), message_p); + return 0; } diff --git a/openair2/F1AP/f1ap_cu_interface_management.h b/openair2/F1AP/f1ap_cu_interface_management.h index 11a45868e1..9d0bf4a391 100644 --- a/openair2/F1AP/f1ap_cu_interface_management.h +++ b/openair2/F1AP/f1ap_cu_interface_management.h @@ -36,17 +36,9 @@ /* * Reset */ -int CU_send_RESET(sctp_assoc_t assoc_id, const f1ap_reset_t *reset); int CU_handle_RESET_ACKNOWLEDGE(instance_t instance, sctp_assoc_t assoc_id, uint32_t stream, F1AP_F1AP_PDU_t *pdu); -int CU_handle_RESET(instance_t instance, sctp_assoc_t assoc_id, uint32_t stream, F1AP_F1AP_PDU_t *pdu); int CU_send_RESET_ACKNOWLEDGE(sctp_assoc_t assoc_id, const f1ap_reset_ack_t *ack); -/* - * Error Indication - */ -int CU_handle_ERROR_INDICATION(instance_t instance, sctp_assoc_t assoc_id, uint32_t stream, F1AP_F1AP_PDU_t *pdu); -int CU_send_ERROR_INDICATION(sctp_assoc_t assoc_id, F1AP_ErrorIndication_t *ErrorIndication); - /* * F1 Setup */ @@ -61,9 +53,6 @@ int CU_send_F1_SETUP_FAILURE(sctp_assoc_t assoc_id, const f1ap_setup_failure_t * */ int CU_handle_gNB_DU_CONFIGURATION_UPDATE(instance_t instance, sctp_assoc_t assoc_id, uint32_t stream, F1AP_F1AP_PDU_t *pdu); -int CU_send_gNB_DU_CONFIGURATION_FAILURE(sctp_assoc_t assoc_id, - f1ap_gnb_du_configuration_update_failure_t *GNBDUConfigurationUpdateFailure); - int CU_send_gNB_DU_CONFIGURATION_UPDATE_ACKNOWLEDGE( sctp_assoc_t assoc_id, f1ap_gnb_du_configuration_update_acknowledge_t *GNBDUConfigurationUpdateAcknowledge); @@ -72,25 +61,10 @@ int CU_send_gNB_DU_CONFIGURATION_UPDATE_ACKNOWLEDGE( * gNB-CU Configuration Update */ int CU_send_gNB_CU_CONFIGURATION_UPDATE(sctp_assoc_t assoc_id, f1ap_gnb_cu_configuration_update_t *f1ap_gnb_cu_configuration_update); -int CU_handle_gNB_CU_CONFIGURATION_UPDATE_FAILURE(instance_t instance, - sctp_assoc_t assoc_id, - uint32_t stream, - F1AP_F1AP_PDU_t *pdu); int CU_handle_gNB_CU_CONFIGURATION_UPDATE_ACKNOWLEDGE(instance_t instance, sctp_assoc_t assoc_id, uint32_t stream, F1AP_F1AP_PDU_t *pdu); -/* - * gNB-DU Resource Coordination - */ -int CU_handle_gNB_DU_RESOURCE_COORDINATION_REQUEST(instance_t instance, - sctp_assoc_t assoc_id, - uint32_t stream, - F1AP_F1AP_PDU_t *pdu); - -int CU_send_gNB_DU_RESOURCE_COORDINATION_RESPONSE(sctp_assoc_t assoc_id, - F1AP_GNBDUResourceCoordinationResponse_t *GNBDUResourceCoordinationResponse); - #endif /* F1AP_CU_INTERFACE_MANAGEMENT_H_ */ diff --git a/openair2/F1AP/f1ap_cu_rrc_message_transfer.c b/openair2/F1AP/f1ap_cu_rrc_message_transfer.c index 8ccca9f478..cf85961ff5 100644 --- a/openair2/F1AP/f1ap_cu_rrc_message_transfer.c +++ b/openair2/F1AP/f1ap_cu_rrc_message_transfer.c @@ -39,67 +39,25 @@ #include "openair3/UTILS/conversions.h" #include "LAYER2/nr_pdcp/nr_pdcp_oai_api.h" +#include "f1ap_rrc_message_transfer.h" + /* Initial UL RRC Message Transfer */ int CU_handle_INITIAL_UL_RRC_MESSAGE_TRANSFER(instance_t instance, sctp_assoc_t assoc_id, uint32_t stream, F1AP_F1AP_PDU_t *pdu) { - LOG_D(F1AP, "CU_handle_INITIAL_UL_RRC_MESSAGE_TRANSFER\n"); - // decode the F1 message - // get the rrc message from the contauiner - // call func rrc_eNB_decode_ccch: <-- needs some update here - MessageDef *message_p; - F1AP_InitialULRRCMessageTransfer_t *container; - F1AP_InitialULRRCMessageTransferIEs_t *ie; - DevAssert(pdu != NULL); - - if (stream != 0) { - LOG_E(F1AP, "[SCTP %d] Received F1 on stream != 0 (%d)\n", - assoc_id, stream); + f1ap_initial_ul_rrc_message_t msg; + if (!decode_initial_ul_rrc_message_transfer(pdu, &msg)) { + LOG_E(F1AP, "cannot decode F1 initial UL RRC message Transfer\n"); return -1; } - container = &pdu->choice.initiatingMessage->value.choice.InitialULRRCMessageTransfer; - /* GNB_DU_UE_F1AP_ID */ - F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_InitialULRRCMessageTransferIEs_t, ie, container, - F1AP_ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID, true); - uint32_t du_ue_id = ie->value.choice.GNB_DU_UE_F1AP_ID; - - /* NRCGI - * Fixme: process NRCGI - */ - F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_InitialULRRCMessageTransferIEs_t, ie, container, - F1AP_ProtocolIE_ID_id_NRCGI, true); - uint64_t nr_cellid; - BIT_STRING_TO_NR_CELL_IDENTITY(&ie->value.choice.NRCGI.nRCellIdentity,nr_cellid); - /* RNTI */ - F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_InitialULRRCMessageTransferIEs_t, ie, container, - F1AP_ProtocolIE_ID_id_C_RNTI, true); - rnti_t rnti = ie->value.choice.C_RNTI; - F1AP_InitialULRRCMessageTransferIEs_t *rrccont; - F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_InitialULRRCMessageTransferIEs_t, rrccont, container, - F1AP_ProtocolIE_ID_id_RRCContainer, true); - AssertFatal(rrccont!=NULL,"RRCContainer is missing\n"); - - F1AP_InitialULRRCMessageTransferIEs_t *du2cu; - F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_InitialULRRCMessageTransferIEs_t, du2cu, container, - F1AP_ProtocolIE_ID_id_DUtoCURRCContainer, false); - // create an ITTI message and copy SDU - message_p = itti_alloc_new_message(TASK_CU_F1, 0, F1AP_INITIAL_UL_RRC_MESSAGE); + MessageDef *message_p = itti_alloc_new_message(TASK_CU_F1, 0, F1AP_INITIAL_UL_RRC_MESSAGE); message_p->ittiMsgHeader.originInstance = assoc_id; f1ap_initial_ul_rrc_message_t *ul_rrc = &F1AP_INITIAL_UL_RRC_MESSAGE(message_p); - ul_rrc->gNB_DU_ue_id = du_ue_id; - ul_rrc->nr_cellid = nr_cellid; // CU instance - ul_rrc->crnti = rnti; - ul_rrc->rrc_container_length = rrccont->value.choice.RRCContainer.size; - ul_rrc->rrc_container = malloc(ul_rrc->rrc_container_length); - memcpy(ul_rrc->rrc_container, rrccont->value.choice.RRCContainer.buf, ul_rrc->rrc_container_length); - AssertFatal(du2cu != NULL, "no masterCellGroup in initial UL RRC message\n"); - ul_rrc->du2cu_rrc_container_length = du2cu->value.choice.DUtoCURRCContainer.size; - ul_rrc->du2cu_rrc_container = malloc(ul_rrc->du2cu_rrc_container_length); - memcpy(ul_rrc->du2cu_rrc_container, du2cu->value.choice.DUtoCURRCContainer.buf, ul_rrc->du2cu_rrc_container_length); + *ul_rrc = msg; /* "move" message into ITTI, RRC thread will free it */ itti_send_msg_to_task(TASK_RRC_GNB, instance, message_p); return 0; @@ -108,105 +66,27 @@ int CU_handle_INITIAL_UL_RRC_MESSAGE_TRANSFER(instance_t instance, sctp_assoc_t /* DL RRC Message Transfer. */ -int CU_send_DL_RRC_MESSAGE_TRANSFER(sctp_assoc_t assoc_id, f1ap_dl_rrc_message_t *f1ap_dl_rrc) +int CU_send_DL_RRC_MESSAGE_TRANSFER(sctp_assoc_t assoc_id, f1ap_dl_rrc_message_t *msg) { - LOG_D(F1AP, "CU send DL_RRC_MESSAGE_TRANSFER \n"); - F1AP_F1AP_PDU_t pdu= {0}; - F1AP_DLRRCMessageTransfer_t *out; - uint8_t *buffer=NULL; - uint32_t len=0; - /* Create */ - /* 0. Message Type */ - pdu.present = F1AP_F1AP_PDU_PR_initiatingMessage; - asn1cCalloc(pdu.choice.initiatingMessage, tmp); - tmp->procedureCode = F1AP_ProcedureCode_id_DLRRCMessageTransfer; - tmp->criticality = F1AP_Criticality_ignore; - tmp->value.present = F1AP_InitiatingMessage__value_PR_DLRRCMessageTransfer; - out = &tmp->value.choice.DLRRCMessageTransfer; - /* mandatory */ - /* c1. GNB_CU_UE_F1AP_ID */ - asn1cSequenceAdd(out->protocolIEs.list, F1AP_DLRRCMessageTransferIEs_t, ie1); - ie1->id = F1AP_ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID; - ie1->criticality = F1AP_Criticality_reject; - ie1->value.present = F1AP_DLRRCMessageTransferIEs__value_PR_GNB_CU_UE_F1AP_ID; - DevAssert(f1ap_dl_rrc->gNB_CU_ue_id != 0); - ie1->value.choice.GNB_CU_UE_F1AP_ID = f1ap_dl_rrc->gNB_CU_ue_id; - - /* mandatory */ - /* c2. GNB_DU_UE_F1AP_ID */ - asn1cSequenceAdd(out->protocolIEs.list, F1AP_DLRRCMessageTransferIEs_t, ie2); - ie2->id = F1AP_ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID; - ie2->criticality = F1AP_Criticality_reject; - ie2->value.present = F1AP_DLRRCMessageTransferIEs__value_PR_GNB_DU_UE_F1AP_ID; - DevAssert(f1ap_dl_rrc->gNB_DU_ue_id != 0); - ie2->value.choice.GNB_DU_UE_F1AP_ID = f1ap_dl_rrc->gNB_DU_ue_id; - - /* optional */ - /* c3. oldgNB_DU_UE_F1AP_ID */ - if (f1ap_dl_rrc->old_gNB_DU_ue_id != NULL) { - asn1cSequenceAdd(out->protocolIEs.list, F1AP_DLRRCMessageTransferIEs_t, ie3); - ie3->id = F1AP_ProtocolIE_ID_id_oldgNB_DU_UE_F1AP_ID; - ie3->criticality = F1AP_Criticality_reject; - ie3->value.present = F1AP_DLRRCMessageTransferIEs__value_PR_GNB_DU_UE_F1AP_ID_1; - ie3->value.choice.GNB_DU_UE_F1AP_ID_1 = *f1ap_dl_rrc->old_gNB_DU_ue_id; - } - - /* mandatory */ - /* c4. SRBID */ - asn1cSequenceAdd(out->protocolIEs.list, F1AP_DLRRCMessageTransferIEs_t, ie4); - ie4->id = F1AP_ProtocolIE_ID_id_SRBID; - ie4->criticality = F1AP_Criticality_reject; - ie4->value.present = F1AP_DLRRCMessageTransferIEs__value_PR_SRBID; - ie4->value.choice.SRBID = f1ap_dl_rrc->srb_id; - - /* optional */ - /* c5. ExecuteDuplication */ - if (f1ap_dl_rrc->execute_duplication) { - asn1cSequenceAdd(out->protocolIEs.list, F1AP_DLRRCMessageTransferIEs_t, ie5); - ie5->id = F1AP_ProtocolIE_ID_id_ExecuteDuplication; - ie5->criticality = F1AP_Criticality_ignore; - ie5->value.present = F1AP_DLRRCMessageTransferIEs__value_PR_ExecuteDuplication; - ie5->value.choice.ExecuteDuplication = F1AP_ExecuteDuplication_true; - } - - // issue in here - /* mandatory */ - /* c6. RRCContainer */ - asn1cSequenceAdd(out->protocolIEs.list, F1AP_DLRRCMessageTransferIEs_t, ie6); - ie6->id = F1AP_ProtocolIE_ID_id_RRCContainer; - ie6->criticality = F1AP_Criticality_reject; - ie6->value.present = F1AP_DLRRCMessageTransferIEs__value_PR_RRCContainer; - OCTET_STRING_fromBuf(&ie6->value.choice.RRCContainer, - (const char *)f1ap_dl_rrc->rrc_container, f1ap_dl_rrc->rrc_container_length); - - /* optional */ - /* c7. RAT_FrequencyPriorityInformation */ - /* TODO */ - if (0) { - int endc=1; - asn1cSequenceAdd(out->protocolIEs.list, F1AP_DLRRCMessageTransferIEs_t, ie7); - ie7->id = F1AP_ProtocolIE_ID_id_RAT_FrequencyPriorityInformation; - ie7->criticality = F1AP_Criticality_reject; - ie7->value.present = F1AP_DLRRCMessageTransferIEs__value_PR_RAT_FrequencyPriorityInformation; - - if (endc==1) { - ie7->value.choice.RAT_FrequencyPriorityInformation.present = F1AP_RAT_FrequencyPriorityInformation_PR_eNDC; - ie7->value.choice.RAT_FrequencyPriorityInformation.choice.eNDC = 123L; - } else { - ie7->value.choice.RAT_FrequencyPriorityInformation.present = F1AP_RAT_FrequencyPriorityInformation_PR_nGRAN; - ie7->value.choice.RAT_FrequencyPriorityInformation.choice.nGRAN = 11L; - } - - //ie->value.choice.RAT_FrequencyPriorityInformation.present = F1AP_RAT_FrequencyPriorityInformation_PR_rAT_FrequencySelectionPriority; - //ie->value.choice.RAT_FrequencyPriorityInformation.choice.rAT_FrequencySelectionPriority = 123L; - } - - /* encode */ - if (f1ap_encode_pdu(&pdu, &buffer, &len) < 0) { - LOG_E(F1AP, "Failed to encode F1 DL RRC MESSAGE TRANSFER \n"); + /* encode DL RRC Message Transfer */ + F1AP_F1AP_PDU_t *pdu = encode_dl_rrc_message_transfer(msg); + if (pdu == NULL) { + LOG_E(F1AP, "Failed to encode F1 DL RRC MESSAGE TRANSFER: can't send message!\n"); + ASN_STRUCT_FREE(asn_DEF_F1AP_F1AP_PDU, pdu); return -1; } - + /* encode F1AP PDU */ + uint8_t *buffer = NULL; + uint32_t len = 0; + if (f1ap_encode_pdu(pdu, &buffer, &len) < 0) { + LOG_E(F1AP, "Failed to encode F1 DL RRC MESSAGE TRANSFER \n"); + ASN_STRUCT_FREE(asn_DEF_F1AP_F1AP_PDU, pdu); + return -1; + } + /* Free F1AP PDU */ + ASN_STRUCT_FREE(asn_DEF_F1AP_F1AP_PDU, pdu); + /* Send to DU */ + LOG_D(F1AP, "CU send DL_RRC_MESSAGE_TRANSFER \n"); f1ap_itti_send_sctp_data_req(assoc_id, buffer, len); return 0; } @@ -216,76 +96,67 @@ int CU_send_DL_RRC_MESSAGE_TRANSFER(sctp_assoc_t assoc_id, f1ap_dl_rrc_message_t */ int CU_handle_UL_RRC_MESSAGE_TRANSFER(instance_t instance, sctp_assoc_t assoc_id, uint32_t stream, F1AP_F1AP_PDU_t *pdu) { - LOG_D(F1AP, "CU_handle_UL_RRC_MESSAGE_TRANSFER \n"); - F1AP_ULRRCMessageTransfer_t *container; - F1AP_ULRRCMessageTransferIEs_t *ie; - uint64_t cu_ue_f1ap_id; - uint64_t du_ue_f1ap_id; - uint64_t srb_id; - DevAssert(pdu != NULL); - if (stream != 0) { LOG_E(F1AP, "[SCTP %d] Received F1 on stream != 0 (%d)\n", assoc_id, stream); return -1; } - container = &pdu->choice.initiatingMessage->value.choice.ULRRCMessageTransfer; - /* GNB_CU_UE_F1AP_ID */ - F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_ULRRCMessageTransferIEs_t, ie, container, - F1AP_ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID, true); - cu_ue_f1ap_id = ie->value.choice.GNB_CU_UE_F1AP_ID; - /* GNB_DU_UE_F1AP_ID */ - F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_ULRRCMessageTransferIEs_t, ie, container, - F1AP_ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID, true); - du_ue_f1ap_id = ie->value.choice.GNB_DU_UE_F1AP_ID; + f1ap_ul_rrc_message_t msg = {0}; - if (!cu_exists_f1_ue_data(cu_ue_f1ap_id)) { - LOG_E(F1AP, "unknown CU UE ID %ld\n", cu_ue_f1ap_id); - return 1; + LOG_D(F1AP, "CU_handle_UL_RRC_MESSAGE_TRANSFER \n"); + if (!decode_ul_rrc_message_transfer(pdu, &msg)) { + LOG_E(F1AP, "cannot decode F1 UL RRC message Transfer\n"); + free_ul_rrc_message_transfer(&msg); + return -1; + } + + if (!cu_exists_f1_ue_data(msg.gNB_CU_ue_id)) { + LOG_E(F1AP, "unknown CU UE ID %d\n", msg.gNB_CU_ue_id); + free_ul_rrc_message_transfer(&msg); + return -1; } /* the RLC-PDCP does not transport the DU UE ID (yet), so we drop it here. * For the moment, let's hope this won't become relevant; to sleep in peace, * let's put an assert to check that it is the expected DU UE ID. */ - f1_ue_data_t ue_data = cu_get_f1_ue_data(cu_ue_f1ap_id); - if (ue_data.secondary_ue != du_ue_f1ap_id) { - LOG_E(F1AP, "unexpected DU UE ID %u received, expected it to be %lu\n", ue_data.secondary_ue, du_ue_f1ap_id); - return 1; + f1_ue_data_t ue_data = cu_get_f1_ue_data(msg.gNB_CU_ue_id); + if (ue_data.secondary_ue != msg.gNB_DU_ue_id) { + LOG_E(F1AP, "unexpected DU UE ID %u received, expected it to be %u\n", ue_data.secondary_ue, msg.gNB_DU_ue_id); + free_ul_rrc_message_transfer(&msg); + return -1; } - /* mandatory */ - /* SRBID */ - F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_ULRRCMessageTransferIEs_t, ie, container, - F1AP_ProtocolIE_ID_id_SRBID, true); - srb_id = ie->value.choice.SRBID; - - if (srb_id < 1 ) - LOG_E(F1AP, "Unexpected UL RRC MESSAGE for srb_id %lu \n", srb_id); + if (msg.srb_id < 1) + LOG_E(F1AP, "Unexpected UL RRC MESSAGE for SRB %d \n", msg.srb_id); else - LOG_D(F1AP, "UL RRC MESSAGE for srb_id %lu in DCCH \n", srb_id); + LOG_D(F1AP, "UL RRC MESSAGE for SRB %d in DCCH \n", msg.srb_id); + + protocol_ctxt_t ctxt = { + .instance = instance, + .module_id = instance, + .enb_flag = 1, + .eNB_index = 0, + .rntiMaybeUEid = msg.gNB_CU_ue_id, + }; + + LOG_D(F1AP, + "[UE %lx] calling pdcp_data_ind for SRB %d with size %d (DCCH) \n", + ctxt.rntiMaybeUEid, + msg.srb_id, + msg.rrc_container_length); + uint8_t *mb = malloc16(msg.rrc_container_length); + memcpy(mb, msg.rrc_container, msg.rrc_container_length); - // issue in here - /* mandatory */ - /* RRC Container */ - F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_ULRRCMessageTransferIEs_t, ie, container, - F1AP_ProtocolIE_ID_id_RRCContainer, true); - protocol_ctxt_t ctxt={0}; - ctxt.instance = instance; - ctxt.module_id = instance; - ctxt.rntiMaybeUEid = cu_ue_f1ap_id; - ctxt.enb_flag = 1; - ctxt.eNB_index = 0; - uint8_t *mb = malloc16(ie->value.choice.RRCContainer.size); - memcpy(mb, ie->value.choice.RRCContainer.buf, ie->value.choice.RRCContainer.size); - LOG_D(F1AP, "Calling pdcp_data_ind for UE RNTI %lx srb_id %lu with size %ld (DCCH) \n", ctxt.rntiMaybeUEid, srb_id, ie->value.choice.RRCContainer.size); nr_pdcp_data_ind(&ctxt, 1, // srb_flag 0, // embms_flag - srb_id, - ie->value.choice.RRCContainer.size, + msg.srb_id, + msg.rrc_container_length, mb, NULL, NULL); + /* Free UL RRC Message Transfer */ + free_ul_rrc_message_transfer(&msg); return 0; } diff --git a/openair2/F1AP/f1ap_cu_ue_context_management.c b/openair2/F1AP/f1ap_cu_ue_context_management.c index 8451fb7062..78e0ba02e9 100644 --- a/openair2/F1AP/f1ap_cu_ue_context_management.c +++ b/openair2/F1AP/f1ap_cu_ue_context_management.c @@ -44,7 +44,7 @@ static void f1ap_write_drb_qos_param(const f1ap_qos_flow_level_qos_parameters_t int type = drb_qos_in->qos_characteristics.qos_type; const f1ap_qos_characteristics_t *drb_qos_char_in = &drb_qos_in->qos_characteristics; - if (type == non_dynamic) { + if (type == NON_DYNAMIC) { asn1_qosparam->qoS_Characteristics.present = F1AP_QoS_Characteristics_PR_non_Dynamic_5QI; asn1cCalloc(asn1_qosparam->qoS_Characteristics.choice.non_Dynamic_5QI, tmp); @@ -130,7 +130,7 @@ static void f1ap_write_flows_mapped(const f1ap_flows_mapped_to_drb_t *flows_mapp const f1ap_qos_characteristics_t *flow_qos_char_in = &flow_qos_params_in->qos_characteristics; int type = flow_qos_params_in->qos_characteristics.qos_type; - if (type == non_dynamic) { + if (type == NON_DYNAMIC) { QosParams->present = F1AP_QoS_Characteristics_PR_non_Dynamic_5QI; asn1cCalloc(QosParams->choice.non_Dynamic_5QI, tmp); @@ -483,12 +483,15 @@ int CU_send_UE_CONTEXT_SETUP_REQUEST(sctp_assoc_t assoc_id, f1ap_ue_context_setu /* 12.1.4 rLCMode */ /* TODO use rlc_mode from f1ap_drb_to_be_setup */ switch (f1ap_ue_context_setup_req->drbs_to_be_setup[i].rlc_mode) { - case RLC_MODE_AM: + case F1AP_RLC_MODE_AM: drbs_toBeSetup_item->rLCMode = F1AP_RLCMode_rlc_am; break; - - default: + case F1AP_RLC_MODE_UM_BIDIR: drbs_toBeSetup_item->rLCMode = F1AP_RLCMode_rlc_um_bidirectional; + break; + default: + AssertFatal(false, "modes other than AM/UM-Bidir not supported\n"); + break; } /* OPTIONAL */ @@ -1218,12 +1221,15 @@ int CU_send_UE_CONTEXT_MODIFICATION_REQUEST(sctp_assoc_t assoc_id, f1ap_ue_conte /* 12.1.4 rLCMode */ /* TODO use rlc_mode from f1ap_drb_to_be_setup */ switch (f1ap_ue_context_modification_req->drbs_to_be_setup[i].rlc_mode) { - case RLC_MODE_AM: + case F1AP_RLC_MODE_AM: drbs_toBeSetupMod_item->rLCMode = F1AP_RLCMode_rlc_am; break; - - default: + case F1AP_RLC_MODE_UM_BIDIR: drbs_toBeSetupMod_item->rLCMode = F1AP_RLCMode_rlc_um_bidirectional; + break; + default: + AssertFatal(false, "modes other than AM/UM-Bidir not supported\n"); + break; } /* OPTIONAL */ diff --git a/openair2/F1AP/f1ap_cu_warning_message_transmission.h b/openair2/F1AP/f1ap_cu_warning_message_transmission.h deleted file mode 100644 index b6bbedba2f..0000000000 --- a/openair2/F1AP/f1ap_cu_warning_message_transmission.h +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The OpenAirInterface Software Alliance licenses this file to You under - * the OAI Public License, Version 1.1 (the "License"); you may not use this file - * except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.openairinterface.org/?page_id=698 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - *------------------------------------------------------------------------------- - * For more information about the OpenAirInterface (OAI) Software Alliance: - * contact@openairinterface.org - */ - -/*! \file f1ap_du_interface_management.h - * \brief f1ap interface management for DU - * \author EURECOM/NTUST - * \date 2018 - * \version 0.1 - * \company Eurecom - * \email: navid.nikaein@eurecom.fr, bing-kai.hong@eurecom.fr - * \note - * \warning - */ \ No newline at end of file diff --git a/openair2/F1AP/f1ap_du_interface_management.c b/openair2/F1AP/f1ap_du_interface_management.c index f560754bf3..85e963ea6a 100644 --- a/openair2/F1AP/f1ap_du_interface_management.c +++ b/openair2/F1AP/f1ap_du_interface_management.c @@ -34,22 +34,13 @@ #include "f1ap_encoder.h" #include "f1ap_itti_messaging.h" #include "f1ap_du_interface_management.h" +#include "lib/f1ap_interface_management.h" +#include "lib/f1ap_lib_common.h" #include "openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.h" #include "assertions.h" #include "GNB_APP/gnb_paramdef.h" -int to_NRNRB(int nrb) { - for (int i=0; inr_pci; // int 0..1007 - - /* - fiveGS_TAC */ - if (c->tac != NULL) { - uint32_t tac = htonl(*c->tac); - asn1cCalloc(scell_info.fiveGS_TAC, netOrder); - OCTET_STRING_fromBuf(netOrder, ((char *)&tac) + 1, 3); - } - - /* - Configured_EPS_TAC */ - if (0) { - scell_info.configured_EPS_TAC = (F1AP_Configured_EPS_TAC_t *)calloc(1, sizeof(F1AP_Configured_EPS_TAC_t)); - OCTET_STRING_fromBuf(scell_info.configured_EPS_TAC, "2", 2); - } - - /* servedPLMN information */ - asn1cSequenceAdd(scell_info.servedPLMNs.list, F1AP_ServedPLMNs_Item_t, servedPLMN_item); - MCC_MNC_TO_PLMNID(c->plmn.mcc, c->plmn.mnc, c->plmn.mnc_digit_length, &servedPLMN_item->pLMN_Identity); - - F1AP_NR_Mode_Info_t *nR_Mode_Info = &scell_info.nR_Mode_Info; - if (c->num_ssi > 0) { - F1AP_ProtocolExtensionContainer_10696P34_t *p = calloc(1, sizeof(*p)); - servedPLMN_item->iE_Extensions = (struct F1AP_ProtocolExtensionContainer *)p; - asn1cSequenceAdd(p->list, F1AP_ServedPLMNs_ItemExtIEs_t, served_plmns_itemExtIEs); - served_plmns_itemExtIEs->criticality = F1AP_Criticality_ignore; - served_plmns_itemExtIEs->id = F1AP_ProtocolIE_ID_id_TAISliceSupportList; - served_plmns_itemExtIEs->extensionValue.present = F1AP_ServedPLMNs_ItemExtIEs__extensionValue_PR_SliceSupportList; - F1AP_SliceSupportList_t *slice_support_list = &served_plmns_itemExtIEs->extensionValue.choice.SliceSupportList; - - for (int s = 0; s < c->num_ssi; s++) { - asn1cSequenceAdd(slice_support_list->list, F1AP_SliceSupportItem_t, slice); - const nssai_t *nssai = &c->nssai[s]; - INT8_TO_OCTET_STRING(nssai->sst, &slice->sNSSAI.sST); - if (nssai->sd != 0xffffff) { - asn1cCalloc(slice->sNSSAI.sD, tmp); - INT24_TO_OCTET_STRING(nssai->sd, tmp); - } - } - } - - if (c->mode == F1AP_MODE_FDD) { // FDD - const f1ap_fdd_info_t *fdd = &c->fdd; - nR_Mode_Info->present = F1AP_NR_Mode_Info_PR_fDD; - asn1cCalloc(nR_Mode_Info->choice.fDD, fDD_Info); - /* FDD.1.1 UL NRFreqInfo ARFCN */ - fDD_Info->uL_NRFreqInfo.nRARFCN = fdd->ul_freqinfo.arfcn; // Integer - - /* FDD.1.2 F1AP_SUL_Information */ - - /* FDD.1.3 freqBandListNr */ - int ul_band = 1; - for (int j = 0; j < ul_band; j++) { - asn1cSequenceAdd(fDD_Info->uL_NRFreqInfo.freqBandListNr.list, F1AP_FreqBandNrItem_t, nr_freqBandNrItem); - /* FDD.1.3.1 freqBandIndicatorNr*/ - nr_freqBandNrItem->freqBandIndicatorNr = fdd->ul_freqinfo.band; - - /* FDD.1.3.2 supportedSULBandList*/ - } - - /* FDD.2.1 DL NRFreqInfo ARFCN */ - fDD_Info->dL_NRFreqInfo.nRARFCN = fdd->dl_freqinfo.arfcn; // Integer - - /* FDD.2.2 F1AP_SUL_Information */ - - /* FDD.2.3 freqBandListNr */ - int dl_bands = 1; - for (int j = 0; j < dl_bands; j++) { - asn1cSequenceAdd(fDD_Info->dL_NRFreqInfo.freqBandListNr.list, F1AP_FreqBandNrItem_t, nr_freqBandNrItem); - /* FDD.2.3.1 freqBandIndicatorNr*/ - nr_freqBandNrItem->freqBandIndicatorNr = fdd->dl_freqinfo.band; - - /* FDD.2.3.2 supportedSULBandList*/ - } // for FDD : DL freq_Bands - - /* FDD.3 UL Transmission Bandwidth */ - fDD_Info->uL_Transmission_Bandwidth.nRSCS = fdd->ul_tbw.scs; - fDD_Info->uL_Transmission_Bandwidth.nRNRB = to_NRNRB(fdd->ul_tbw.nrb); - /* FDD.4 DL Transmission Bandwidth */ - fDD_Info->dL_Transmission_Bandwidth.nRSCS = fdd->dl_tbw.scs; - fDD_Info->dL_Transmission_Bandwidth.nRNRB = to_NRNRB(fdd->dl_tbw.nrb); - } else if (c->mode == F1AP_MODE_TDD) { - const f1ap_tdd_info_t *tdd = &c->tdd; - nR_Mode_Info->present = F1AP_NR_Mode_Info_PR_tDD; - asn1cCalloc(nR_Mode_Info->choice.tDD, tDD_Info); - /* TDD.1.1 nRFreqInfo ARFCN */ - tDD_Info->nRFreqInfo.nRARFCN = tdd->freqinfo.arfcn; - - /* TDD.1.2 F1AP_SUL_Information */ - - /* TDD.1.3 freqBandListNr */ - int bands = 1; - for (int j = 0; j < bands; j++) { - asn1cSequenceAdd(tDD_Info->nRFreqInfo.freqBandListNr.list, F1AP_FreqBandNrItem_t, nr_freqBandNrItem); - /* TDD.1.3.1 freqBandIndicatorNr*/ - nr_freqBandNrItem->freqBandIndicatorNr = tdd->freqinfo.band; - /* TDD.1.3.2 supportedSULBandList*/ - } - - /* TDD.2 transmission_Bandwidth */ - tDD_Info->transmission_Bandwidth.nRSCS = tdd->tbw.scs; - tDD_Info->transmission_Bandwidth.nRNRB = to_NRNRB(tdd->tbw.nrb); - } else { - AssertFatal(false, "unknown mode %d\n", c->mode); - } - - /* - measurementTimingConfiguration */ - OCTET_STRING_fromBuf(&scell_info.measurementTimingConfiguration, - (const char *)c->measurement_timing_config, - c->measurement_timing_config_len); - - return scell_info; -} - -static F1AP_GNB_DU_System_Information_t *encode_system_info(const f1ap_gnb_du_system_info_t *sys_info) -{ - if (sys_info == NULL) - return NULL; /* optional: can be NULL */ - - F1AP_GNB_DU_System_Information_t *enc_sys_info = calloc(1, sizeof(*enc_sys_info)); - AssertFatal(enc_sys_info != NULL, "out of memory\n"); - - AssertFatal(sys_info->mib != NULL, "MIB must be present in DU sys info\n"); - OCTET_STRING_fromBuf(&enc_sys_info->mIB_message, (const char *)sys_info->mib, sys_info->mib_length); - - AssertFatal(sys_info->sib1 != NULL, "SIB1 must be present in DU sys info\n"); - OCTET_STRING_fromBuf(&enc_sys_info->sIB1_message, (const char *)sys_info->sib1, sys_info->sib1_length); - - return enc_sys_info; -} - -// SETUP REQUEST +/** + * @brief F1AP Setup Request + */ int DU_send_F1_SETUP_REQUEST(sctp_assoc_t assoc_id, const f1ap_setup_req_t *setup_req) { LOG_D(F1AP, "DU_send_F1_SETUP_REQUEST\n"); - - F1AP_F1AP_PDU_t pdu= {0}; + F1AP_F1AP_PDU_t *pdu = encode_f1ap_setup_request(setup_req); uint8_t *buffer; uint32_t len; - /* Create */ - /* 0. pdu Type */ - pdu.present = F1AP_F1AP_PDU_PR_initiatingMessage; - asn1cCalloc(pdu.choice.initiatingMessage, initMsg); - initMsg->procedureCode = F1AP_ProcedureCode_id_F1Setup; - initMsg->criticality = F1AP_Criticality_reject; - initMsg->value.present = F1AP_InitiatingMessage__value_PR_F1SetupRequest; - F1AP_F1SetupRequest_t *f1Setup = &initMsg->value.choice.F1SetupRequest; - /* mandatory */ - /* c1. Transaction ID (integer value) */ - asn1cSequenceAdd(f1Setup->protocolIEs.list, F1AP_F1SetupRequestIEs_t, ieC1); - ieC1->id = F1AP_ProtocolIE_ID_id_TransactionID; - ieC1->criticality = F1AP_Criticality_reject; - ieC1->value.present = F1AP_F1SetupRequestIEs__value_PR_TransactionID; - ieC1->value.choice.TransactionID = F1AP_get_next_transaction_identifier(0, 0); - /* mandatory */ - /* c2. GNB_DU_ID (integer value) */ - asn1cSequenceAdd(f1Setup->protocolIEs.list, F1AP_F1SetupRequestIEs_t, ieC2); - ieC2->id = F1AP_ProtocolIE_ID_id_gNB_DU_ID; - ieC2->criticality = F1AP_Criticality_reject; - ieC2->value.present = F1AP_F1SetupRequestIEs__value_PR_GNB_DU_ID; - asn_int642INTEGER(&ieC2->value.choice.GNB_DU_ID, setup_req->gNB_DU_id); - - /* optional */ - /* c3. GNB_DU_Name */ - if (setup_req->gNB_DU_name != NULL) { - asn1cSequenceAdd(f1Setup->protocolIEs.list, F1AP_F1SetupRequestIEs_t, ieC3); - ieC3->id = F1AP_ProtocolIE_ID_id_gNB_DU_Name; - ieC3->criticality = F1AP_Criticality_ignore; - ieC3->value.present = F1AP_F1SetupRequestIEs__value_PR_GNB_DU_Name; - char *gNB_DU_name=setup_req->gNB_DU_name; - OCTET_STRING_fromBuf(&ieC3->value.choice.GNB_DU_Name, gNB_DU_name, strlen(gNB_DU_name)); - } - - /* mandatory */ - /* c4. served cells list */ - asn1cSequenceAdd(f1Setup->protocolIEs.list, F1AP_F1SetupRequestIEs_t, ieCells); - ieCells->id = F1AP_ProtocolIE_ID_id_gNB_DU_Served_Cells_List; - ieCells->criticality = F1AP_Criticality_reject; - ieCells->value.present = F1AP_F1SetupRequestIEs__value_PR_GNB_DU_Served_Cells_List; - int num_cells_available = setup_req->num_cells_available; - LOG_D(F1AP, "num_cells_available = %d \n", num_cells_available); - - for (int i=0; icell[i].info; - const f1ap_gnb_du_system_info_t *sys_info = setup_req->cell[i].sys_info; - asn1cSequenceAdd(ieCells->value.choice.GNB_DU_Served_Cells_List.list, - F1AP_GNB_DU_Served_Cells_ItemIEs_t, duServedCell); - duServedCell->id = F1AP_ProtocolIE_ID_id_GNB_DU_Served_Cells_Item; - duServedCell->criticality = F1AP_Criticality_reject; - duServedCell->value.present = F1AP_GNB_DU_Served_Cells_ItemIEs__value_PR_GNB_DU_Served_Cells_Item; - F1AP_GNB_DU_Served_Cells_Item_t *scell_item = &duServedCell->value.choice.GNB_DU_Served_Cells_Item; - scell_item->served_Cell_Information = encode_served_cell_info(cell); - scell_item->gNB_DU_System_Information = encode_system_info(sys_info); - } - - /* mandatory */ - /* c5. RRC VERSION */ - asn1cSequenceAdd(f1Setup->protocolIEs.list, F1AP_F1SetupRequestIEs_t, ie2); - ie2->id = F1AP_ProtocolIE_ID_id_GNB_DU_RRC_Version; - ie2->criticality = F1AP_Criticality_reject; - ie2->value.present = F1AP_F1SetupRequestIEs__value_PR_RRC_Version; - // RRC Version: "This IE is not used in this release." - // we put one bit for each byte in rrc_ver that is != 0 - uint8_t bits = 0; - for (int i = 0; i < 3; ++i) - bits |= (setup_req->rrc_ver[i] != 0) << i; - BIT_STRING_t *bs = &ie2->value.choice.RRC_Version.latest_RRC_Version; - bs->buf = calloc(1, sizeof(char)); - AssertFatal(bs->buf != NULL, "out of memory\n"); - bs->buf[0] = bits; - bs->size = 1; - bs->bits_unused = 5; - - F1AP_ProtocolExtensionContainer_10696P228_t *p = calloc(1, sizeof(F1AP_ProtocolExtensionContainer_10696P228_t)); - asn1cSequenceAdd(p->list, F1AP_RRC_Version_ExtIEs_t, rrcv_ext); - rrcv_ext->id = F1AP_ProtocolIE_ID_id_latest_RRC_Version_Enhanced; - rrcv_ext->criticality = F1AP_Criticality_ignore; - rrcv_ext->extensionValue.present = F1AP_RRC_Version_ExtIEs__extensionValue_PR_OCTET_STRING_SIZE_3_; - OCTET_STRING_t *os = &rrcv_ext->extensionValue.choice.OCTET_STRING_SIZE_3_; - os->size = 3; - os->buf = malloc(3 * sizeof(*os->buf)); - AssertFatal(os->buf != NULL, "out of memory\n"); - for (int i = 0; i < 3; ++i) - os->buf[i] = setup_req->rrc_ver[i]; - ie2->value.choice.RRC_Version.iE_Extensions = (struct F1AP_ProtocolExtensionContainer*)p; - /* encode */ - if (f1ap_encode_pdu(&pdu, &buffer, &len) < 0) { + if (f1ap_encode_pdu(pdu, &buffer, &len) < 0) { LOG_E(F1AP, "Failed to encode F1 setup request\n"); + /* free PDU */ + ASN_STRUCT_FREE(asn_DEF_F1AP_F1AP_PDU, pdu); return -1; } - - ASN_STRUCT_RESET(asn_DEF_F1AP_F1AP_PDU, &pdu); + /* free PDU */ + ASN_STRUCT_FREE(asn_DEF_F1AP_F1AP_PDU, pdu); + /* Send to ITTI */ f1ap_itti_send_sctp_data_req(assoc_id, buffer, len); return 0; } @@ -432,475 +177,94 @@ int DU_send_F1_SETUP_REQUEST(sctp_assoc_t assoc_id, const f1ap_setup_req_t *setu int DU_handle_F1_SETUP_RESPONSE(instance_t instance, sctp_assoc_t assoc_id, uint32_t stream, F1AP_F1AP_PDU_t *pdu) { LOG_D(F1AP, "DU_handle_F1_SETUP_RESPONSE\n"); - AssertFatal(pdu->present == F1AP_F1AP_PDU_PR_successfulOutcome, - "pdu->present != F1AP_F1AP_PDU_PR_successfulOutcome\n"); - AssertFatal(pdu->choice.successfulOutcome->procedureCode == F1AP_ProcedureCode_id_F1Setup, - "pdu->choice.successfulOutcome->procedureCode != F1AP_ProcedureCode_id_F1Setup\n"); - AssertFatal(pdu->choice.successfulOutcome->criticality == F1AP_Criticality_reject, - "pdu->choice.successfulOutcome->criticality != F1AP_Criticality_reject\n"); - AssertFatal(pdu->choice.successfulOutcome->value.present == F1AP_SuccessfulOutcome__value_PR_F1SetupResponse, - "pdu->choice.successfulOutcome->value.present != F1AP_SuccessfulOutcome__value_PR_F1SetupResponse\n"); - F1AP_F1SetupResponse_t *in = &pdu->choice.successfulOutcome->value.choice.F1SetupResponse; - F1AP_F1SetupResponseIEs_t *ie; - int TransactionId = -1; - int num_cells_to_activate = 0; + /* Decode */ f1ap_setup_resp_t resp = {0}; - - for (int i=0; i < in->protocolIEs.list.count; i++) { - ie = in->protocolIEs.list.array[i]; - - switch (ie->id) { - case F1AP_ProtocolIE_ID_id_TransactionID: - AssertFatal(ie->criticality == F1AP_Criticality_reject, - "ie->criticality != F1AP_Criticality_reject\n"); - AssertFatal(ie->value.present == F1AP_F1SetupResponseIEs__value_PR_TransactionID, - "ie->value.present != F1AP_F1SetupResponseIEs__value_PR_TransactionID\n"); - TransactionId=ie->value.choice.TransactionID; - LOG_D(F1AP, "F1AP: F1Setup-Resp: TransactionId %d\n", - TransactionId); - break; - - case F1AP_ProtocolIE_ID_id_gNB_CU_Name: - AssertFatal(ie->criticality == F1AP_Criticality_ignore, - "ie->criticality != F1AP_Criticality_ignore\n"); - AssertFatal(ie->value.present == F1AP_F1SetupResponseIEs__value_PR_GNB_CU_Name, - "ie->value.present != F1AP_F1SetupResponseIEs__value_PR_GNB_CU_Name\n"); - resp.gNB_CU_name = malloc(ie->value.choice.GNB_CU_Name.size+1); - memcpy(resp.gNB_CU_name, ie->value.choice.GNB_CU_Name.buf, ie->value.choice.GNB_CU_Name.size); - resp.gNB_CU_name[ie->value.choice.GNB_CU_Name.size] = '\0'; - LOG_D(F1AP, "F1AP: F1Setup-Resp: gNB_CU_name %s\n", resp.gNB_CU_name); - break; - - case F1AP_ProtocolIE_ID_id_GNB_CU_RRC_Version: - AssertFatal(ie->criticality == F1AP_Criticality_reject, - "ie->criticality != F1AP_Criticality_reject\n"); - AssertFatal(ie->value.present == F1AP_F1SetupResponseIEs__value_PR_RRC_Version, - "ie->value.present != F1AP_F1SetupResponseIEs__value_PR_RRC_Version\n"); - // RRC Version: "This IE is not used in this release." - if(ie->value.choice.RRC_Version.iE_Extensions) { - F1AP_ProtocolExtensionContainer_10696P228_t *ext = - (F1AP_ProtocolExtensionContainer_10696P228_t *)ie->value.choice.RRC_Version.iE_Extensions; - if(ext->list.count > 0){ - F1AP_RRC_Version_ExtIEs_t *rrcext = ext->list.array[0]; - OCTET_STRING_t *os = &rrcext->extensionValue.choice.OCTET_STRING_SIZE_3_; - for (int i = 0; i < 3; i++) - resp.rrc_ver[i] = os->buf[i]; - } - } - break; - - case F1AP_ProtocolIE_ID_id_Cells_to_be_Activated_List: { - AssertFatal(ie->criticality == F1AP_Criticality_reject, - "ie->criticality != F1AP_Criticality_reject\n"); - AssertFatal(ie->value.present == F1AP_F1SetupResponseIEs__value_PR_Cells_to_be_Activated_List, - "ie->value.present != F1AP_F1SetupResponseIEs__value_PR_Cells_to_be_Activated_List\n"); - num_cells_to_activate = ie->value.choice.Cells_to_be_Activated_List.list.count; - LOG_D(F1AP, "F1AP: Activating %d cells\n",num_cells_to_activate); - - for (int i=0; ivalue.choice.Cells_to_be_Activated_List.list.array[i]; - AssertFatal(cells_to_be_activated_list_item_ies->id == F1AP_ProtocolIE_ID_id_Cells_to_be_Activated_List_Item, - "cells_to_be_activated_list_item_ies->id != F1AP_ProtocolIE_ID_id_Cells_to_be_Activated_List_Item"); - AssertFatal(cells_to_be_activated_list_item_ies->criticality == F1AP_Criticality_reject, - "cells_to_be_activated_list_item_ies->criticality == F1AP_Criticality_reject"); - AssertFatal(cells_to_be_activated_list_item_ies->value.present == F1AP_Cells_to_be_Activated_List_ItemIEs__value_PR_Cells_to_be_Activated_List_Item, - "cells_to_be_activated_list_item_ies->value.present == F1AP_Cells_to_be_Activated_List_ItemIEs__value_PR_Cells_to_be_Activated_List_Item"); - F1AP_Cells_to_be_Activated_List_Item_t *cell = - &cells_to_be_activated_list_item_ies->value.choice.Cells_to_be_Activated_List_Item; - TBCD_TO_MCC_MNC(&cell->nRCGI.pLMN_Identity, - resp.cells_to_activate[i].plmn.mcc, - resp.cells_to_activate[i].plmn.mnc, - resp.cells_to_activate[i].plmn.mnc_digit_length); - LOG_D(F1AP, "nr_cellId : %x %x %x %x %x\n", - cell->nRCGI.nRCellIdentity.buf[0], - cell->nRCGI.nRCellIdentity.buf[1], - cell->nRCGI.nRCellIdentity.buf[2], - cell->nRCGI.nRCellIdentity.buf[3], - cell->nRCGI.nRCellIdentity.buf[4]); - BIT_STRING_TO_NR_CELL_IDENTITY(&cell->nRCGI.nRCellIdentity, resp.cells_to_activate[i].nr_cellid); - if (cell->nRPCI != NULL) - resp.cells_to_activate[i].nrpci = *cell->nRPCI; - F1AP_ProtocolExtensionContainer_10696P112_t *ext = (F1AP_ProtocolExtensionContainer_10696P112_t *)cell->iE_Extensions; - - if (ext==NULL) - continue; - - for (int cnt=0; cntlist.count; cnt++) { - F1AP_Cells_to_be_Activated_List_ItemExtIEs_t *cells_to_be_activated_list_itemExtIEs=(F1AP_Cells_to_be_Activated_List_ItemExtIEs_t *)ext->list.array[cnt]; - - switch (cells_to_be_activated_list_itemExtIEs->id) { - /* - case F1AP_Cells_to_be_Activated_List_ItemExtIEs__extensionValue_PR_NOTHING: - case F1AP_Cells_to_be_Activated_List_ItemExtIEs__extensionValue_PR_GNB_CUSystemInformation, - case F1AP_Cells_to_be_Activated_List_ItemExtIEs__extensionValue_PR_AvailablePLMNList, - case F1AP_Cells_to_be_Activated_List_ItemExtIEs__extensionValue_PR_ExtendedAvailablePLMN_List, - case F1AP_Cells_to_be_Activated_List_ItemExtIEs__extensionValue_PR_IAB_Info_IAB_donor_CU, - case F1AP_Cells_to_be_Activated_List_ItemExtIEs__extensionValue_PR_AvailableSNPN_ID_List - */ - case F1AP_ProtocolIE_ID_id_gNB_CUSystemInformation: { - resp.cells_to_activate[i].nrpci = (cell->nRPCI != NULL) ? *cell->nRPCI : 0; - F1AP_GNB_CUSystemInformation_t *gNB_CUSystemInformation = (F1AP_GNB_CUSystemInformation_t *)&cells_to_be_activated_list_itemExtIEs->extensionValue.choice.GNB_CUSystemInformation; - resp.cells_to_activate[i].num_SI = gNB_CUSystemInformation->sibtypetobeupdatedlist.list.count; - AssertFatal(ext->list.count==1,"At least one SI message should be there, and only 1 for now!\n"); - LOG_D(F1AP, - "F1AP: Cell %d MCC %d MNC %d NRCellid %lx num_si %d\n", - i, - resp.cells_to_activate[i].plmn.mcc, - resp.cells_to_activate[i].plmn.mnc, - resp.cells_to_activate[i].nr_cellid, - resp.cells_to_activate[i].num_SI); - - for (int si = 0; si < gNB_CUSystemInformation->sibtypetobeupdatedlist.list.count; si++) { - F1AP_SibtypetobeupdatedListItem_t *sib_item = gNB_CUSystemInformation->sibtypetobeupdatedlist.list.array[si]; - size_t size = sib_item->sIBmessage.size; - resp.cells_to_activate[i].SI_container_length[si] = size; - LOG_D(F1AP, "F1AP: SI_container_length[%d][%ld] %ld bytes\n", i, sib_item->sIBtype, size); - resp.cells_to_activate[i].SI_container[si] = malloc(resp.cells_to_activate[i].SI_container_length[si]); - memcpy(resp.cells_to_activate[i].SI_container[si], sib_item->sIBmessage.buf, size); - resp.cells_to_activate[i].SI_type[si]=sib_item->sIBtype; - } - - break; - } - - case F1AP_ProtocolIE_ID_id_AvailablePLMNList: - AssertFatal(1==0,"F1AP_ProtocolIE_ID_id_AvailablePLMNList not supported yet\n"); - break; - - case F1AP_ProtocolIE_ID_id_ExtendedAvailablePLMN_List: - AssertFatal(1==0,"F1AP_ProtocolIE_ID_id_AvailablePLMNList not supported yet\n"); - break; - - case F1AP_ProtocolIE_ID_id_IAB_Info_IAB_donor_CU: - AssertFatal(1==0,"F1AP_ProtocolIE_ID_id_AvailablePLMNList not supported yet\n"); - break; - - case F1AP_ProtocolIE_ID_id_AvailableSNPN_ID_List: - AssertFatal(1==0,"F1AP_ProtocolIE_ID_id_AvailablePLMNList not supported yet\n"); - break; - - default: - AssertFatal(1==0,"F1AP_ProtocolIE_ID_id %d unknown\n",(int)cells_to_be_activated_list_itemExtIEs->id); - break; - } - } // for (cnt=... - } // for (cells_to_activate... - - break; - } // case F1AP_ProtocolIE_ID_id_Cells_to_be_Activated_List - - default: - AssertFatal(1==0,"F1AP_ProtocolIE_ID_id %d unknown\n", (int)ie->id); - break; - } // switch ie - } // for IE - - AssertFatal(TransactionId!=-1,"TransactionId was not sent\n"); - LOG_D(F1AP,"F1AP: num_cells_to_activate %d\n",num_cells_to_activate); - resp.num_cells_to_activate = num_cells_to_activate; - - // tmp - for (int i=0; ichoice.unsuccessfulOutcome->value.choice.F1SetupFailure; - /* Transaction ID */ - F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_F1SetupFailureIEs_t, ie, out, F1AP_ProtocolIE_ID_id_TransactionID, true); - /* Cause */ - F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_F1SetupFailureIEs_t, ie, out, - F1AP_ProtocolIE_ID_id_Cause, true); - - if(0) { - /* TimeToWait */ - F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_F1SetupFailureIEs_t, ie, out, - F1AP_ProtocolIE_ID_id_TimeToWait, true); + f1ap_setup_failure_t fail; + if (!decode_f1ap_setup_failure(pdu, &fail)) { + LOG_E(F1AP, "Failed to decode F1AP Setup Failure\n"); + return -1; } - f1_setup_failure(&fail); return 0; } -/* - gNB-DU Configuration Update -*/ - -int DU_send_gNB_DU_CONFIGURATION_UPDATE(sctp_assoc_t assoc_id, const f1ap_gnb_du_configuration_update_t *upd) +/** + * @brief F1 gNB-DU Configuration Update: encoding and ITTI transmission + */ +int DU_send_gNB_DU_CONFIGURATION_UPDATE(sctp_assoc_t assoc_id, f1ap_gnb_du_configuration_update_t *msg) { - F1AP_F1AP_PDU_t pdu= {0}; uint8_t *buffer=NULL; uint32_t len=0; - /* Create */ - /* 0. Message Type */ - pdu.present = F1AP_F1AP_PDU_PR_initiatingMessage; - asn1cCalloc(pdu.choice.initiatingMessage, initMsg); - initMsg->procedureCode = F1AP_ProcedureCode_id_gNBDUConfigurationUpdate; - initMsg->criticality = F1AP_Criticality_reject; - initMsg->value.present = F1AP_InitiatingMessage__value_PR_GNBDUConfigurationUpdate; - F1AP_GNBDUConfigurationUpdate_t *out = &initMsg->value.choice.GNBDUConfigurationUpdate; - - /* mandatory */ - /* c1. Transaction ID (integer value) */ - asn1cSequenceAdd(out->protocolIEs.list, F1AP_GNBDUConfigurationUpdateIEs_t, ie1); - ie1->id = F1AP_ProtocolIE_ID_id_TransactionID; - ie1->criticality = F1AP_Criticality_reject; - ie1->value.present = F1AP_GNBDUConfigurationUpdateIEs__value_PR_TransactionID; - ie1->value.choice.TransactionID = upd->transaction_id; - - /* mandatory */ - /* c2. Served_Cells_To_Add */ - if (upd->num_cells_to_add > 0) { - AssertFatal(false, "code for adding cells not tested\n"); - asn1cSequenceAdd(out->protocolIEs.list, F1AP_GNBDUConfigurationUpdateIEs_t, ie2); - ie2->id = F1AP_ProtocolIE_ID_id_Served_Cells_To_Add_List; - ie2->criticality = F1AP_Criticality_reject; - ie2->value.present = F1AP_GNBDUConfigurationUpdateIEs__value_PR_Served_Cells_To_Add_List; - - for (int j = 0; j < upd->num_cells_to_add; j++) { - const f1ap_served_cell_info_t *cell = &upd->cell_to_add[j].info; - const f1ap_gnb_du_system_info_t *sys_info = upd->cell_to_add[j].sys_info; - asn1cSequenceAdd(ie2->value.choice.Served_Cells_To_Add_List.list, - F1AP_Served_Cells_To_Add_ItemIEs_t, - served_cells_to_add_item_ies); - served_cells_to_add_item_ies->id = F1AP_ProtocolIE_ID_id_Served_Cells_To_Add_Item; - served_cells_to_add_item_ies->criticality = F1AP_Criticality_reject; - served_cells_to_add_item_ies->value.present = F1AP_Served_Cells_To_Add_ItemIEs__value_PR_Served_Cells_To_Add_Item; - F1AP_Served_Cells_To_Add_Item_t *served_cells_to_add_item = - &served_cells_to_add_item_ies->value.choice.Served_Cells_To_Add_Item; - served_cells_to_add_item->served_Cell_Information = encode_served_cell_info(cell); - served_cells_to_add_item->gNB_DU_System_Information = encode_system_info(sys_info); - } - } - - /* mandatory */ - /* c3. Served_Cells_To_Modify */ - if (upd->num_cells_to_modify > 0) { - asn1cSequenceAdd(out->protocolIEs.list, F1AP_GNBDUConfigurationUpdateIEs_t, ie3); - ie3->id = F1AP_ProtocolIE_ID_id_Served_Cells_To_Modify_List; - ie3->criticality = F1AP_Criticality_reject; - ie3->value.present = F1AP_GNBDUConfigurationUpdateIEs__value_PR_Served_Cells_To_Modify_List; - for (int i = 0; i < upd->num_cells_to_modify; i++) { - const f1ap_served_cell_info_t *cell = &upd->cell_to_modify[i].info; - const f1ap_gnb_du_system_info_t *sys_info = upd->cell_to_modify[i].sys_info; - asn1cSequenceAdd(ie3->value.choice.Served_Cells_To_Modify_List.list, - F1AP_Served_Cells_To_Modify_ItemIEs_t, - served_cells_to_modify_item_ies); - served_cells_to_modify_item_ies->id = F1AP_ProtocolIE_ID_id_Served_Cells_To_Modify_Item; - served_cells_to_modify_item_ies->criticality = F1AP_Criticality_reject; - served_cells_to_modify_item_ies->value.present = F1AP_Served_Cells_To_Modify_ItemIEs__value_PR_Served_Cells_To_Modify_Item; - F1AP_Served_Cells_To_Modify_Item_t *served_cells_to_modify_item = - &served_cells_to_modify_item_ies->value.choice.Served_Cells_To_Modify_Item; - - F1AP_NRCGI_t *oldNRCGI = &served_cells_to_modify_item->oldNRCGI; - const f1ap_plmn_t *old_plmn = &upd->cell_to_modify[i].old_plmn; - MCC_MNC_TO_PLMNID(old_plmn->mcc, old_plmn->mnc, old_plmn->mnc_digit_length, &oldNRCGI->pLMN_Identity); - NR_CELL_ID_TO_BIT_STRING(upd->cell_to_modify[i].old_nr_cellid, &oldNRCGI->nRCellIdentity); - - served_cells_to_modify_item->served_Cell_Information = encode_served_cell_info(cell); - served_cells_to_modify_item->gNB_DU_System_Information = encode_system_info(sys_info); - } - } - - /* mandatory */ - /* c4. Served_Cells_To_Delete */ - if (upd->num_cells_to_delete > 0) { - asn1cSequenceAdd(out->protocolIEs.list, F1AP_GNBDUConfigurationUpdateIEs_t, ie4); - ie4->id = F1AP_ProtocolIE_ID_id_Served_Cells_To_Delete_List; - ie4->criticality = F1AP_Criticality_reject; - ie4->value.present = F1AP_GNBDUConfigurationUpdateIEs__value_PR_Served_Cells_To_Delete_List; - AssertFatal(upd->num_cells_to_delete == 0, "code for deleting cells not tested\n"); - for (int i = 0; i < upd->num_cells_to_delete; i++) { - asn1cSequenceAdd(ie4->value.choice.Served_Cells_To_Delete_List.list, - F1AP_Served_Cells_To_Delete_ItemIEs_t, - served_cells_to_delete_item_ies); - served_cells_to_delete_item_ies->id = F1AP_ProtocolIE_ID_id_Served_Cells_To_Delete_Item; - served_cells_to_delete_item_ies->criticality = F1AP_Criticality_reject; - served_cells_to_delete_item_ies->value.present = F1AP_Served_Cells_To_Delete_ItemIEs__value_PR_Served_Cells_To_Delete_Item; - F1AP_Served_Cells_To_Delete_Item_t *served_cells_to_delete_item = - &served_cells_to_delete_item_ies->value.choice.Served_Cells_To_Delete_Item; - addnRCGI(served_cells_to_delete_item->oldNRCGI, &upd->cell_to_delete[i]); - } - } - - AssertFatal(upd->gNB_DU_ID == 0, "encoding of gNB-DU Id not handled yet\n"); - - if (f1ap_encode_pdu(&pdu, &buffer, &len) < 0) { + /* encode F1AP message */ + F1AP_F1AP_PDU_t *pdu = encode_f1ap_du_configuration_update(msg); + /* free anfter encoding */ + free_f1ap_du_configuration_update(msg); + /* encode F1AP pdu */ + if (f1ap_encode_pdu(pdu, &buffer, &len) < 0) { LOG_E(F1AP, "Failed to encode F1 gNB-DU CONFIGURATION UPDATE\n"); return -1; } - - ASN_STRUCT_RESET(asn_DEF_F1AP_F1AP_PDU, &pdu); + /* transfer the message */ + ASN_STRUCT_FREE(asn_DEF_F1AP_F1AP_PDU, pdu); f1ap_itti_send_sctp_data_req(assoc_id, buffer, len); return 0; } -int DU_handle_gNB_DU_CONFIGURATION_FAILURE(instance_t instance, sctp_assoc_t assoc_id, uint32_t stream, F1AP_F1AP_PDU_t *pdu) +/** + * @brief F1 gNB-CU Configuration Update decoding and message transfer + */ +int DU_handle_gNB_CU_CONFIGURATION_UPDATE(instance_t instance, sctp_assoc_t assoc_id, uint32_t stream, F1AP_F1AP_PDU_t *pdu) { - AssertFatal(1==0,"Not implemented yet\n"); + LOG_D(F1AP, "DU_handle_gNB_CU_CONFIGURATION_UPDATE\n"); + f1ap_gnb_cu_configuration_update_t in = {0}; + if (!decode_f1ap_cu_configuration_update(pdu, &in)) { + LOG_E(F1AP, "Failed to decode F1AP Setup Failure\n"); + free_f1ap_cu_configuration_update(&in); + return -1; + } + MessageDef *msg_p = itti_alloc_new_message (TASK_DU_F1, 0, F1AP_GNB_CU_CONFIGURATION_UPDATE); + f1ap_gnb_cu_configuration_update_t *msg = &F1AP_GNB_CU_CONFIGURATION_UPDATE(msg_p); // RRC thread will free it + *msg = in; // copy F1 message to ITTI + LOG_D(F1AP, "Sending F1AP_GNB_CU_CONFIGURATION_UPDATE ITTI message \n"); + itti_send_msg_to_task(TASK_GNB_APP, GNB_MODULE_ID_TO_INSTANCE(assoc_id), msg_p); + return 0; } +/** + * @brief F1 gNB-DU Configuration Update Acknowledge decoding and message transfer + */ int DU_handle_gNB_DU_CONFIGURATION_UPDATE_ACKNOWLEDGE(instance_t instance, sctp_assoc_t assoc_id, uint32_t stream, F1AP_F1AP_PDU_t *pdu) { - AssertFatal(1==0,"Not implemented yet\n"); -} - -int DU_handle_gNB_CU_CONFIGURATION_UPDATE(instance_t instance, sctp_assoc_t assoc_id, uint32_t stream, F1AP_F1AP_PDU_t *pdu) -{ - LOG_D(F1AP, "DU_handle_gNB_CU_CONFIGURATION_UPDATE\n"); - AssertFatal(pdu->present == F1AP_F1AP_PDU_PR_initiatingMessage, - "pdu->present != F1AP_F1AP_PDU_PR_initiatingMessage\n"); - AssertFatal(pdu->choice.initiatingMessage->procedureCode == F1AP_ProcedureCode_id_gNBCUConfigurationUpdate, - "pdu->choice.initiatingMessage->procedureCode != F1AP_ProcedureCode_id_gNBCUConfigurationUpdate\n"); - AssertFatal(pdu->choice.initiatingMessage->criticality == F1AP_Criticality_reject, - "pdu->choice.initiatingMessage->criticality != F1AP_Criticality_reject\n"); - AssertFatal(pdu->choice.initiatingMessage->value.present == F1AP_InitiatingMessage__value_PR_GNBCUConfigurationUpdate, - "pdu->choice.initiatingMessage->value.present != F1AP_InitiatingMessage__value_PR_GNBCUConfigurationUpdate\n"); - F1AP_GNBCUConfigurationUpdate_t *in = &pdu->choice.initiatingMessage->value.choice.GNBCUConfigurationUpdate; - F1AP_GNBCUConfigurationUpdateIEs_t *ie; - int TransactionId = -1; - int num_cells_to_activate = 0; - F1AP_Cells_to_be_Activated_List_Item_t *cell; - MessageDef *msg_p = itti_alloc_new_message (TASK_DU_F1, 0, F1AP_GNB_CU_CONFIGURATION_UPDATE); - LOG_D(F1AP, "F1AP: gNB_CU_Configuration_Update: protocolIEs.list.count %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 F1AP_ProtocolIE_ID_id_TransactionID: - AssertFatal(ie->criticality == F1AP_Criticality_reject, - "ie->criticality != F1AP_Criticality_reject\n"); - AssertFatal(ie->value.present == F1AP_GNBCUConfigurationUpdateIEs__value_PR_TransactionID, - "ie->value.present != F1AP_GNBCUConfigurationUpdateIEs__value_PR_TransactionID\n"); - TransactionId=ie->value.choice.TransactionID; - LOG_D(F1AP, "F1AP: GNB-CU-ConfigurationUpdate: TransactionId %d\n", - TransactionId); - break; - - case F1AP_ProtocolIE_ID_id_Cells_to_be_Activated_List: { - AssertFatal(ie->criticality == F1AP_Criticality_reject, - "ie->criticality != F1AP_Criticality_reject\n"); - AssertFatal(ie->value.present == F1AP_GNBCUConfigurationUpdateIEs__value_PR_Cells_to_be_Activated_List, - "ie->value.present != F1AP_GNBCUConfigurationUpdateIEs__value_PR_Cells_to_be_Activated_List\n"); - num_cells_to_activate = ie->value.choice.Cells_to_be_Activated_List.list.count; - LOG_D(F1AP, "F1AP: Activating %d cells\n",num_cells_to_activate); - - for (int i=0; ivalue.choice.Cells_to_be_Activated_List.list.array[i]; - AssertFatal(cells_to_be_activated_list_item_ies->id == F1AP_ProtocolIE_ID_id_Cells_to_be_Activated_List_Item, - "cells_to_be_activated_list_item_ies->id != F1AP_ProtocolIE_ID_id_Cells_to_be_Activated_List_Item"); - AssertFatal(cells_to_be_activated_list_item_ies->criticality == F1AP_Criticality_reject, - "cells_to_be_activated_list_item_ies->criticality == F1AP_Criticality_reject"); - AssertFatal(cells_to_be_activated_list_item_ies->value.present == F1AP_Cells_to_be_Activated_List_ItemIEs__value_PR_Cells_to_be_Activated_List_Item, - "cells_to_be_activated_list_item_ies->value.present == F1AP_Cells_to_be_Activated_List_ItemIEs__value_PR_Cells_to_be_Activated_List_Item"); - cell = &cells_to_be_activated_list_item_ies->value.choice.Cells_to_be_Activated_List_Item; - TBCD_TO_MCC_MNC(&cell->nRCGI.pLMN_Identity, - F1AP_GNB_CU_CONFIGURATION_UPDATE(msg_p).cells_to_activate[i].plmn.mcc, - F1AP_GNB_CU_CONFIGURATION_UPDATE(msg_p).cells_to_activate[i].plmn.mnc, - F1AP_GNB_CU_CONFIGURATION_UPDATE(msg_p).cells_to_activate[i].plmn.mnc_digit_length); - LOG_D(F1AP, "nr_cellId : %x %x %x %x %x\n", - cell->nRCGI.nRCellIdentity.buf[0], - cell->nRCGI.nRCellIdentity.buf[1], - cell->nRCGI.nRCellIdentity.buf[2], - cell->nRCGI.nRCellIdentity.buf[3], - cell->nRCGI.nRCellIdentity.buf[4]); - BIT_STRING_TO_NR_CELL_IDENTITY(&cell->nRCGI.nRCellIdentity, - F1AP_GNB_CU_CONFIGURATION_UPDATE (msg_p).cells_to_activate[i].nr_cellid); - F1AP_ProtocolExtensionContainer_10696P112_t *ext = (F1AP_ProtocolExtensionContainer_10696P112_t *)cell->iE_Extensions; - - if (ext==NULL) - continue; - - for (int cnt=0; cntlist.count; cnt++) { - F1AP_Cells_to_be_Activated_List_ItemExtIEs_t *cells_to_be_activated_list_itemExtIEs=(F1AP_Cells_to_be_Activated_List_ItemExtIEs_t *)ext->list.array[cnt]; - - switch (cells_to_be_activated_list_itemExtIEs->id) { - /* - case F1AP_Cells_to_be_Activated_List_ItemExtIEs__extensionValue_PR_NOTHING: - case F1AP_Cells_to_be_Activated_List_ItemExtIEs__extensionValue_PR_GNB_CUSystemInformation, - case F1AP_Cells_to_be_Activated_List_ItemExtIEs__extensionValue_PR_AvailablePLMNList, - case F1AP_Cells_to_be_Activated_List_ItemExtIEs__extensionValue_PR_ExtendedAvailablePLMN_List, - case F1AP_Cells_to_be_Activated_List_ItemExtIEs__extensionValue_PR_IAB_Info_IAB_donor_CU, - case F1AP_Cells_to_be_Activated_List_ItemExtIEs__extensionValue_PR_AvailableSNPN_ID_List - */ - case F1AP_ProtocolIE_ID_id_gNB_CUSystemInformation: { - F1AP_GNB_CU_CONFIGURATION_UPDATE (msg_p).cells_to_activate[i].nrpci = (cell->nRPCI != NULL) ? *cell->nRPCI : 0; - F1AP_GNB_CUSystemInformation_t *gNB_CUSystemInformation = (F1AP_GNB_CUSystemInformation_t *)&cells_to_be_activated_list_itemExtIEs->extensionValue.choice.GNB_CUSystemInformation; - F1AP_GNB_CU_CONFIGURATION_UPDATE (msg_p).cells_to_activate[i].num_SI = gNB_CUSystemInformation->sibtypetobeupdatedlist.list.count; - AssertFatal(ext->list.count==1,"At least one SI message should be there, and only 1 for now!\n"); - LOG_D(F1AP, - "F1AP: Cell %d MCC %d MNC %d NRCellid %lx num_si %d\n", - i, - F1AP_GNB_CU_CONFIGURATION_UPDATE(msg_p).cells_to_activate[i].plmn.mcc, - F1AP_GNB_CU_CONFIGURATION_UPDATE(msg_p).cells_to_activate[i].plmn.mnc, - F1AP_GNB_CU_CONFIGURATION_UPDATE(msg_p).cells_to_activate[i].nr_cellid, - F1AP_GNB_CU_CONFIGURATION_UPDATE(msg_p).cells_to_activate[i].num_SI); - - for (int si = 0; si < gNB_CUSystemInformation->sibtypetobeupdatedlist.list.count; si++) { - F1AP_SibtypetobeupdatedListItem_t *sib_item = gNB_CUSystemInformation->sibtypetobeupdatedlist.list.array[si]; - size_t size = sib_item->sIBmessage.size; - F1AP_GNB_CU_CONFIGURATION_UPDATE (msg_p).cells_to_activate[i].SI_container_length[si] = size; - LOG_D(F1AP, "F1AP: SI_container_length[%d][%ld] %ld bytes\n", i, sib_item->sIBtype, size); - F1AP_GNB_CU_CONFIGURATION_UPDATE (msg_p).cells_to_activate[i].SI_container[si] = malloc(F1AP_GNB_CU_CONFIGURATION_UPDATE (msg_p).cells_to_activate[i].SI_container_length[si]); - memcpy((void *)F1AP_GNB_CU_CONFIGURATION_UPDATE (msg_p).cells_to_activate[i].SI_container[si], - (void *)sib_item->sIBmessage.buf, - size); - F1AP_GNB_CU_CONFIGURATION_UPDATE (msg_p).cells_to_activate[i].SI_type[si]=sib_item->sIBtype; - } - - break; - } - - case F1AP_ProtocolIE_ID_id_AvailablePLMNList: - AssertFatal(1==0,"F1AP_ProtocolIE_ID_id_AvailablePLMNList not supported yet\n"); - break; - - case F1AP_ProtocolIE_ID_id_ExtendedAvailablePLMN_List: - AssertFatal(1==0,"F1AP_ProtocolIE_ID_id_AvailablePLMNList not supported yet\n"); - break; - - case F1AP_ProtocolIE_ID_id_IAB_Info_IAB_donor_CU: - AssertFatal(1==0,"F1AP_ProtocolIE_ID_id_AvailablePLMNList not supported yet\n"); - break; - - case F1AP_ProtocolIE_ID_id_AvailableSNPN_ID_List: - AssertFatal(1==0,"F1AP_ProtocolIE_ID_id_AvailablePLMNList not supported yet\n"); - break; - - default: - AssertFatal(1==0,"F1AP_ProtocolIE_ID_id %d unknown\n",(int)cells_to_be_activated_list_itemExtIEs->id); - break; - } - } // for (cnt=... - } // for (cells_to_activate... - - break; - } // case F1AP_ProtocolIE_ID_id_Cells_to_be_Activated_List - - default: - AssertFatal(1==0,"F1AP_ProtocolIE_ID_id %d unknown\n", (int)ie->id); - break; - } // switch ie - } // for IE - - AssertFatal(TransactionId!=-1,"TransactionId was not sent\n"); - LOG_D(F1AP,"F1AP: num_cells_to_activate %d\n",num_cells_to_activate); - F1AP_GNB_CU_CONFIGURATION_UPDATE (msg_p).num_cells_to_activate = num_cells_to_activate; - LOG_D(F1AP, "Sending F1AP_GNB_CU_CONFIGURATION_UPDATE ITTI message \n"); + // Decoding + f1ap_gnb_du_configuration_update_acknowledge_t in = {0}; + if (!decode_f1ap_du_configuration_update_acknowledge(pdu, &in)) { + LOG_E(F1AP, "Failed to decode gNB-DU Configuration Update Acknowledge\n"); + free_f1ap_du_configuration_update_acknowledge(&in); + return -1; + } + // Allocate and send an ITTI message + MessageDef *msg_p = itti_alloc_new_message(TASK_DU_F1, 0, F1AP_GNB_DU_CONFIGURATION_UPDATE_ACKNOWLEDGE); + f1ap_gnb_du_configuration_update_acknowledge_t *msg = &F1AP_GNB_DU_CONFIGURATION_UPDATE_ACKNOWLEDGE(msg_p); + // Copy the decoded message to the ITTI message (RRC thread will free it) + *msg = in; // Copy the decoded message to the ITTI message (RRC thread will free it) itti_send_msg_to_task(TASK_GNB_APP, GNB_MODULE_ID_TO_INSTANCE(assoc_id), msg_p); return 0; } @@ -911,62 +275,22 @@ int DU_send_gNB_CU_CONFIGURATION_UPDATE_FAILURE(sctp_assoc_t assoc_id, GNBCUConfigurationUpdateFailure->cause); } -int DU_send_gNB_CU_CONFIGURATION_UPDATE_ACKNOWLEDGE( - sctp_assoc_t assoc_id, - f1ap_gnb_cu_configuration_update_acknowledge_t *GNBCUConfigurationUpdateAcknowledge) +/** + * @brief Encode and transfer F1 GNB CU Configuration Update Acknowledge message + */ +int DU_send_gNB_CU_CONFIGURATION_UPDATE_ACKNOWLEDGE(sctp_assoc_t assoc_id, f1ap_gnb_cu_configuration_update_acknowledge_t *msg) { - AssertFatal(GNBCUConfigurationUpdateAcknowledge->num_cells_failed_to_be_activated == 0, - "%d cells failed to activate\n", - GNBCUConfigurationUpdateAcknowledge->num_cells_failed_to_be_activated); - AssertFatal(GNBCUConfigurationUpdateAcknowledge->noofTNLAssociations_to_setup == 0, - "%d TNLAssociations to setup, handle this ...\n", - GNBCUConfigurationUpdateAcknowledge->noofTNLAssociations_to_setup); - AssertFatal(GNBCUConfigurationUpdateAcknowledge->noofTNLAssociations_failed == 0, - "%d TNLAssociations failed\n", - GNBCUConfigurationUpdateAcknowledge->noofTNLAssociations_failed); - AssertFatal(GNBCUConfigurationUpdateAcknowledge->noofDedicatedSIDeliveryNeededUEs == 0, - "%d DedicatedSIDeliveryNeededUEs\n", - GNBCUConfigurationUpdateAcknowledge->noofDedicatedSIDeliveryNeededUEs); - F1AP_F1AP_PDU_t pdu= {0}; - uint8_t *buffer=NULL; - uint32_t len=0; - /* Create */ - /* 0. pdu Type */ - pdu.present = F1AP_F1AP_PDU_PR_successfulOutcome; - asn1cCalloc(pdu.choice.successfulOutcome, tmp); - tmp->procedureCode = F1AP_ProcedureCode_id_gNBCUConfigurationUpdate; - tmp->criticality = F1AP_Criticality_reject; - tmp->value.present = F1AP_SuccessfulOutcome__value_PR_GNBCUConfigurationUpdateAcknowledge; - F1AP_GNBCUConfigurationUpdateAcknowledge_t *out = &tmp->value.choice.GNBCUConfigurationUpdateAcknowledge; - /* mandatory */ - /* c1. Transaction ID (integer value)*/ - asn1cSequenceAdd(out->protocolIEs.list, F1AP_GNBCUConfigurationUpdateAcknowledgeIEs_t, ie); - ie->id = F1AP_ProtocolIE_ID_id_TransactionID; - ie->criticality = F1AP_Criticality_reject; - ie->value.present = F1AP_GNBCUConfigurationUpdateAcknowledgeIEs__value_PR_TransactionID; - ie->value.choice.TransactionID = F1AP_get_next_transaction_identifier(0, 0); - - /* encode */ - if (f1ap_encode_pdu(&pdu, &buffer, &len) < 0) { - LOG_E(F1AP, "Failed to encode GNB-DU-Configuration-Update-Acknowledge\n"); + uint8_t *buffer = NULL; + uint32_t len = 0; + /* encode F1 message */ + F1AP_F1AP_PDU_t *pdu = encode_f1ap_cu_configuration_update_acknowledge(msg); + /* encode F1AP PDU */ + if (!pdu || f1ap_encode_pdu(pdu, &buffer, &len) < 0) { + LOG_E(F1AP, "Failed to encode GNB-CU-Configuration-Update-Acknowledge\n"); + ASN_STRUCT_FREE(asn_DEF_F1AP_F1AP_PDU, pdu); return -1; } - - ASN_STRUCT_RESET(asn_DEF_F1AP_F1AP_PDU, &pdu); + ASN_STRUCT_FREE(asn_DEF_F1AP_F1AP_PDU, pdu); f1ap_itti_send_sctp_data_req(assoc_id, buffer, len); return 0; } - -int DU_send_gNB_DU_RESOURCE_COORDINATION_REQUEST(sctp_assoc_t assoc_id, - F1AP_GNBDUResourceCoordinationRequest_t *GNBDUResourceCoordinationRequest) -{ - AssertFatal(0, "Not implemented yet\n"); -} - -int DU_handle_gNB_DU_RESOURCE_COORDINATION_RESPONSE(instance_t instance, - sctp_assoc_t assoc_id, - uint32_t stream, - F1AP_F1AP_PDU_t *pdu) -{ - AssertFatal(0, "Not implemented yet\n"); -} diff --git a/openair2/F1AP/f1ap_du_interface_management.h b/openair2/F1AP/f1ap_du_interface_management.h index f8d7eafb02..bb5caf90df 100644 --- a/openair2/F1AP/f1ap_du_interface_management.h +++ b/openair2/F1AP/f1ap_du_interface_management.h @@ -38,14 +38,6 @@ */ int DU_handle_RESET(instance_t instance, sctp_assoc_t assoc_id, uint32_t stream, F1AP_F1AP_PDU_t *pdu); int DU_send_RESET_ACKNOWLEDGE(sctp_assoc_t assoc_id, const f1ap_reset_ack_t *ack); -int DU_send_RESET(sctp_assoc_t assoc_id, const f1ap_reset_t *reset); -int DU_handle_RESET_ACKNOWLEDGE(instance_t instance, sctp_assoc_t assoc_id, uint32_t stream, F1AP_F1AP_PDU_t *pdu); - -/* - * Error Indication - */ -int DU_send_ERROR_INDICATION(sctp_assoc_t assoc_id, F1AP_F1AP_PDU_t *pdu_p); -int DU_handle_ERROR_INDICATION(instance_t instance, sctp_assoc_t assoc_id, uint32_t stream, F1AP_F1AP_PDU_t *pdu); /* * F1 Setup @@ -59,14 +51,7 @@ int DU_handle_F1_SETUP_FAILURE(instance_t instance, sctp_assoc_t assoc_id, uint3 /* * gNB-DU Configuration Update */ -int DU_send_gNB_DU_CONFIGURATION_UPDATE(sctp_assoc_t assoc_id, const f1ap_gnb_du_configuration_update_t *upd); - -int DU_handle_gNB_DU_CONFIGURATION_FAILURE(instance_t instance, sctp_assoc_t assoc_id, uint32_t stream, F1AP_F1AP_PDU_t *pdu); - -int DU_handle_gNB_DU_CONFIGURATION_UPDATE_ACKNOWLEDGE(instance_t instance, - sctp_assoc_t assoc_id, - uint32_t stream, - F1AP_F1AP_PDU_t *pdu); +int DU_send_gNB_DU_CONFIGURATION_UPDATE(sctp_assoc_t assoc_id, f1ap_gnb_du_configuration_update_t *msg); /* * gNB-CU Configuration Update @@ -79,17 +64,9 @@ int DU_send_gNB_CU_CONFIGURATION_UPDATE_FAILURE(sctp_assoc_t assoc_id, int DU_send_gNB_CU_CONFIGURATION_UPDATE_ACKNOWLEDGE(sctp_assoc_t assoc_id, f1ap_gnb_cu_configuration_update_acknowledge_t *GNBCUConfigurationUpdateAcknowledge); - - -/* - * gNB-DU Resource Coordination - */ -int DU_send_gNB_DU_RESOURCE_COORDINATION_REQUEST(sctp_assoc_t assoc_id, - F1AP_GNBDUResourceCoordinationRequest_t *GNBDUResourceCoordinationRequest); - -int DU_handle_gNB_DU_RESOURCE_COORDINATION_RESPONSE(instance_t instance, - sctp_assoc_t assoc_id, - uint32_t stream, - F1AP_F1AP_PDU_t *pdu); +int DU_handle_gNB_DU_CONFIGURATION_UPDATE_ACKNOWLEDGE(instance_t instance, + sctp_assoc_t assoc_id, + uint32_t stream, + F1AP_F1AP_PDU_t *pdu); #endif /* F1AP_DU_INTERFACE_MANAGEMENT_H_ */ diff --git a/openair2/F1AP/f1ap_du_rrc_message_transfer.c b/openair2/F1AP/f1ap_du_rrc_message_transfer.c index 4a3526dd0a..7fd83ecd78 100644 --- a/openair2/F1AP/f1ap_du_rrc_message_transfer.c +++ b/openair2/F1AP/f1ap_du_rrc_message_transfer.c @@ -53,226 +53,78 @@ #include "openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.h" +#include "f1ap_rrc_message_transfer.h" + /* DL RRC Message Transfer */ int DU_handle_DL_RRC_MESSAGE_TRANSFER(instance_t instance, sctp_assoc_t assoc_id, uint32_t stream, F1AP_F1AP_PDU_t *pdu) { - F1AP_DLRRCMessageTransfer_t *container; - F1AP_DLRRCMessageTransferIEs_t *ie; - int executeDuplication; - //uint64_t subscriberProfileIDforRFP; - //uint64_t rAT_FrequencySelectionPriority; - DevAssert(pdu != NULL); - container = &pdu->choice.initiatingMessage->value.choice.DLRRCMessageTransfer; - /* GNB_CU_UE_F1AP_ID */ - F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_DLRRCMessageTransferIEs_t, ie, container, - F1AP_ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID, true); - uint32_t cu_ue_f1ap_id = ie->value.choice.GNB_CU_UE_F1AP_ID; - /* GNB_DU_UE_F1AP_ID */ - F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_DLRRCMessageTransferIEs_t, ie, container, - F1AP_ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID, true); - uint32_t du_ue_f1ap_id = ie->value.choice.GNB_DU_UE_F1AP_ID; - - /* optional */ - /* oldgNB_DU_UE_F1AP_ID */ - uint32_t *old_gNB_DU_ue_id = NULL; - uint32_t old_gNB_DU_ue_id_stack = 0; - F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_DLRRCMessageTransferIEs_t, ie, container, - F1AP_ProtocolIE_ID_id_oldgNB_DU_UE_F1AP_ID, false); - if (ie) { - /* strange: it is not named OLD_GNB_DU_UE... */ - old_gNB_DU_ue_id_stack = ie->value.choice.GNB_DU_UE_F1AP_ID_1; - old_gNB_DU_ue_id = &old_gNB_DU_ue_id_stack; + f1ap_dl_rrc_message_t msg = {0}; + if (!decode_dl_rrc_message_transfer(pdu, &msg)) { + LOG_E(F1AP, "cannot decode F1 DL RRC message Transfer\n"); + free_dl_rrc_message_transfer(&msg); + return -1; } - /* mandatory */ - /* SRBID */ - F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_DLRRCMessageTransferIEs_t, ie, container, - F1AP_ProtocolIE_ID_id_SRBID, true); - uint64_t srb_id = ie->value.choice.SRBID; - LOG_D(F1AP, "srb_id %lu \n", srb_id); - - /* optional */ - /* ExecuteDuplication */ - if (0) { - F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_DLRRCMessageTransferIEs_t, ie, container, - F1AP_ProtocolIE_ID_id_ExecuteDuplication, true); - executeDuplication = ie->value.choice.ExecuteDuplication; - LOG_D(F1AP, "ExecuteDuplication %d \n", executeDuplication); - } - - // issue in here - /* mandatory */ - /* RRC Container */ - F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_DLRRCMessageTransferIEs_t, ie, container, - F1AP_ProtocolIE_ID_id_RRCContainer, true); - /* optional */ - /* RAT_FrequencyPriorityInformation */ - if (0) { - F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_DLRRCMessageTransferIEs_t, ie, container, - F1AP_ProtocolIE_ID_id_RAT_FrequencyPriorityInformation, true); - - switch(ie->value.choice.RAT_FrequencyPriorityInformation.present) { - case F1AP_RAT_FrequencyPriorityInformation_PR_eNDC: - //subscriberProfileIDforRFP = ie->value.choice.RAT_FrequencyPriorityInformation.choice.subscriberProfileIDforRFP; - break; - - case F1AP_RAT_FrequencyPriorityInformation_PR_nGRAN: - //rAT_FrequencySelectionPriority = ie->value.choice.RAT_FrequencyPriorityInformation.choice.rAT_FrequencySelectionPriority; - break; - - default: - LOG_W(F1AP, "unhandled IE RAT_FrequencyPriorityInformation.present\n"); - break; - } - } - - f1ap_dl_rrc_message_t dl_rrc = { - .gNB_CU_ue_id = cu_ue_f1ap_id, - .gNB_DU_ue_id = du_ue_f1ap_id, - .old_gNB_DU_ue_id = old_gNB_DU_ue_id, - .rrc_container_length = ie->value.choice.RRCContainer.size, - .rrc_container = ie->value.choice.RRCContainer.buf, - .srb_id = srb_id - }; - dl_rrc_message_transfer(&dl_rrc); + dl_rrc_message_transfer(&msg); + /* Free DL RRC Message Transfer */ + free_dl_rrc_message_transfer(&msg); return 0; } /* UL RRC Message Transfer */ int DU_send_INITIAL_UL_RRC_MESSAGE_TRANSFER(sctp_assoc_t assoc_id, const f1ap_initial_ul_rrc_message_t *msg) { - F1AP_F1AP_PDU_t pdu= {0}; - F1AP_InitialULRRCMessageTransfer_t *out; - uint8_t *buffer=NULL; - uint32_t len=0; + /* encode Initial UL RRC Message Transfer */ + F1AP_F1AP_PDU_t *pdu = encode_initial_ul_rrc_message_transfer(msg); + /* free F1AP message after encoding */ + free_initial_ul_rrc_message_transfer(msg); - /* Create */ - /* 0. Message Type */ - pdu.present = F1AP_F1AP_PDU_PR_initiatingMessage; - asn1cCalloc(pdu.choice.initiatingMessage, tmp); - tmp->procedureCode = F1AP_ProcedureCode_id_InitialULRRCMessageTransfer; - tmp->criticality = F1AP_Criticality_ignore; - tmp->value.present = F1AP_InitiatingMessage__value_PR_InitialULRRCMessageTransfer; - out = &tmp->value.choice.InitialULRRCMessageTransfer; - /* mandatory */ - /* c1. GNB_DU_UE_F1AP_ID */ - asn1cSequenceAdd(out->protocolIEs.list, F1AP_InitialULRRCMessageTransferIEs_t, ie1); - ie1->id = F1AP_ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID; - ie1->criticality = F1AP_Criticality_reject; - ie1->value.present = F1AP_InitialULRRCMessageTransferIEs__value_PR_GNB_DU_UE_F1AP_ID; - ie1->value.choice.GNB_DU_UE_F1AP_ID = msg->gNB_DU_ue_id; - /* mandatory */ - /* c2. NRCGI */ - asn1cSequenceAdd(out->protocolIEs.list, F1AP_InitialULRRCMessageTransferIEs_t, ie2); - ie2->id = F1AP_ProtocolIE_ID_id_NRCGI; - ie2->criticality = F1AP_Criticality_reject; - ie2->value.present = F1AP_InitialULRRCMessageTransferIEs__value_PR_NRCGI; - //Fixme: takes always the first cell - addnRCGI(ie2->value.choice.NRCGI, &getCxt(0)->setupReq.cell[0].info); - /* mandatory */ - /* c3. C_RNTI */ // 16 - asn1cSequenceAdd(out->protocolIEs.list, F1AP_InitialULRRCMessageTransferIEs_t, ie3); - ie3->id = F1AP_ProtocolIE_ID_id_C_RNTI; - ie3->criticality = F1AP_Criticality_reject; - ie3->value.present = F1AP_InitialULRRCMessageTransferIEs__value_PR_C_RNTI; - ie3->value.choice.C_RNTI = msg->crnti; - /* mandatory */ - /* c4. RRCContainer */ - asn1cSequenceAdd(out->protocolIEs.list, F1AP_InitialULRRCMessageTransferIEs_t, ie4); - ie4->id = F1AP_ProtocolIE_ID_id_RRCContainer; - ie4->criticality = F1AP_Criticality_reject; - ie4->value.present = F1AP_InitialULRRCMessageTransferIEs__value_PR_RRCContainer; - OCTET_STRING_fromBuf(&ie4->value.choice.RRCContainer, (const char *)msg->rrc_container, msg->rrc_container_length); - - /* optional */ - /* c5. DUtoCURRCContainer */ - if (msg->du2cu_rrc_container != NULL) { - asn1cSequenceAdd(out->protocolIEs.list, F1AP_InitialULRRCMessageTransferIEs_t, ie5); - ie5->id = F1AP_ProtocolIE_ID_id_DUtoCURRCContainer; - ie5->criticality = F1AP_Criticality_reject; - ie5->value.present = F1AP_InitialULRRCMessageTransferIEs__value_PR_DUtoCURRCContainer; - OCTET_STRING_fromBuf(&ie5->value.choice.DUtoCURRCContainer, - (const char *)msg->du2cu_rrc_container, - msg->du2cu_rrc_container_length); - } - /* mandatory */ - /* c6. Transaction ID (integer value) */ - asn1cSequenceAdd(out->protocolIEs.list, F1AP_InitialULRRCMessageTransferIEs_t, ie6); - ie6->id = F1AP_ProtocolIE_ID_id_TransactionID; - ie6->criticality = F1AP_Criticality_ignore; - ie6->value.present = F1AP_InitialULRRCMessageTransferIEs__value_PR_TransactionID; - ie6->value.choice.TransactionID = F1AP_get_next_transaction_identifier(0, 0); - - /* encode */ - if (f1ap_encode_pdu(&pdu, &buffer, &len) < 0) { - LOG_E(F1AP, "Failed to encode F1 INITIAL UL RRC MESSAGE TRANSFER\n"); + if (pdu == NULL) { + LOG_E(F1AP, "cannot encode F1 INITIAL UL RRC MESSAGE TRANSFER, can't send message\n"); + ASN_STRUCT_FREE(asn_DEF_F1AP_F1AP_PDU, pdu); return -1; } + /* encode F1AP PDU */ + uint8_t *buffer = NULL; + uint32_t len = 0; + if (f1ap_encode_pdu(pdu, &buffer, &len) < 0) { + LOG_E(F1AP, "Failed to encode F1 INITIAL UL RRC MESSAGE TRANSFER\n"); + ASN_STRUCT_FREE(asn_DEF_F1AP_F1AP_PDU, pdu); + return -1; + } + ASN_STRUCT_FREE(asn_DEF_F1AP_F1AP_PDU, pdu); + + /* Send to ITTI */ f1ap_itti_send_sctp_data_req(assoc_id, buffer, len); return 0; } int DU_send_UL_NR_RRC_MESSAGE_TRANSFER(sctp_assoc_t assoc_id, const f1ap_ul_rrc_message_t *msg) { - F1AP_F1AP_PDU_t pdu= {0}; - F1AP_ULRRCMessageTransfer_t *out; - uint8_t *buffer = NULL; - uint32_t len; LOG_D(F1AP, "size %d UE RNTI %x in SRB %d\n", msg->rrc_container_length, msg->gNB_DU_ue_id, msg->srb_id); - //for (int i = 0;i < msg->rrc_container_length; i++) - // printf("%02x ", msg->rrc_container[i]); - //printf("\n"); - /* Create */ - /* 0. Message Type */ - pdu.present = F1AP_F1AP_PDU_PR_initiatingMessage; - asn1cCalloc(pdu.choice.initiatingMessage, tmp); - tmp->procedureCode = F1AP_ProcedureCode_id_ULRRCMessageTransfer; - tmp->criticality = F1AP_Criticality_ignore; - tmp->value.present = F1AP_InitiatingMessage__value_PR_ULRRCMessageTransfer; - out = &tmp->value.choice.ULRRCMessageTransfer; - /* mandatory */ - /* c1. GNB_CU_UE_F1AP_ID */ - asn1cSequenceAdd(out->protocolIEs.list, F1AP_ULRRCMessageTransferIEs_t, ie1); - ie1->id = F1AP_ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID; - ie1->criticality = F1AP_Criticality_reject; - ie1->value.present = F1AP_ULRRCMessageTransferIEs__value_PR_GNB_CU_UE_F1AP_ID; - ie1->value.choice.GNB_CU_UE_F1AP_ID = msg->gNB_CU_ue_id; - /* mandatory */ - /* c2. GNB_DU_UE_F1AP_ID */ - asn1cSequenceAdd(out->protocolIEs.list, F1AP_ULRRCMessageTransferIEs_t, ie2); - ie2->id = F1AP_ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID; - ie2->criticality = F1AP_Criticality_reject; - ie2->value.present = F1AP_ULRRCMessageTransferIEs__value_PR_GNB_DU_UE_F1AP_ID; - ie2->value.choice.GNB_DU_UE_F1AP_ID = msg->gNB_DU_ue_id; - /* mandatory */ - /* c3. SRBID */ - asn1cSequenceAdd(out->protocolIEs.list, F1AP_ULRRCMessageTransferIEs_t, ie3); - ie3->id = F1AP_ProtocolIE_ID_id_SRBID; - ie3->criticality = F1AP_Criticality_reject; - ie3->value.present = F1AP_ULRRCMessageTransferIEs__value_PR_SRBID; - ie3->value.choice.SRBID = msg->srb_id; - // issue in here - /* mandatory */ - /* c4. RRCContainer */ - asn1cSequenceAdd(out->protocolIEs.list, F1AP_ULRRCMessageTransferIEs_t, ie4); - ie4->id = F1AP_ProtocolIE_ID_id_RRCContainer; - ie4->criticality = F1AP_Criticality_reject; - ie4->value.present = F1AP_ULRRCMessageTransferIEs__value_PR_RRCContainer; - OCTET_STRING_fromBuf(&ie4->value.choice.RRCContainer, - (const char *) msg->rrc_container, - msg->rrc_container_length); - - /* encode */ - if (f1ap_encode_pdu(&pdu, &buffer, &len) < 0) { - LOG_E(F1AP, "Failed to encode F1 UL RRC MESSAGE TRANSFER \n"); + /* encode UL RRC Message Transfer */ + F1AP_F1AP_PDU_t *pdu = encode_ul_rrc_message_transfer(msg); + if (pdu == NULL) { + LOG_E(F1AP, "Failed to encode F1 UL RRC MESSAGE TRANSFER: cannot send message\n"); + ASN_STRUCT_FREE(asn_DEF_F1AP_F1AP_PDU, pdu); return -1; } - + /* encode F1AP PDU */ + uint8_t *buffer = NULL; + uint32_t len; + if (f1ap_encode_pdu(pdu, &buffer, &len) < 0) { + LOG_E(F1AP, "Failed to encode F1 UL RRC MESSAGE TRANSFER \n"); + ASN_STRUCT_FREE(asn_DEF_F1AP_F1AP_PDU, pdu); + return -1; + } + /* Free F1AP PDU */ + ASN_STRUCT_FREE(asn_DEF_F1AP_F1AP_PDU, pdu); + /* Send to ITTI */ f1ap_itti_send_sctp_data_req(assoc_id, buffer, len); return 0; } diff --git a/openair2/F1AP/f1ap_du_system_information.c b/openair2/F1AP/f1ap_du_system_information.c deleted file mode 100644 index 725bb4e1af..0000000000 --- a/openair2/F1AP/f1ap_du_system_information.c +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The OpenAirInterface Software Alliance licenses this file to You under - * the OAI Public License, Version 1.1 (the "License"); you may not use this file - * except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.openairinterface.org/?page_id=698 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - *------------------------------------------------------------------------------- - * For more information about the OpenAirInterface (OAI) Software Alliance: - * contact@openairinterface.org - */ - -/*! \file f1ap_du_interface_management.h - * \brief f1ap interface management for DU - * \author EURECOM/NTUST - * \date 2018 - * \version 0.1 - * \company Eurecom - * \email: navid.nikaein@eurecom.fr, bing-kai.hong@eurecom.fr - * \note - * \warning - */ diff --git a/openair2/F1AP/f1ap_du_task.c b/openair2/F1AP/f1ap_du_task.c index ff188e52df..6c4f8c3be6 100644 --- a/openair2/F1AP/f1ap_du_task.c +++ b/openair2/F1AP/f1ap_du_task.c @@ -44,7 +44,7 @@ static instance_t du_create_gtpu_instance_to_cu(const f1ap_net_config_t *nc) { openAddr_t tmp = {0}; strncpy(tmp.originHost, nc->DU_f1u_ip_address, sizeof(tmp.originHost) - 1); - strncpy(tmp.destinationHost, nc->CU_f1_ip_address.ipv4_address, sizeof(tmp.destinationHost) - 1); + strncpy(tmp.destinationHost, nc->CU_f1_ip_address, sizeof(tmp.destinationHost) - 1); sprintf(tmp.originService, "%d", nc->DUport); sprintf(tmp.destinationService, "%d", nc->CUport); return gtpv1Init(tmp); @@ -63,9 +63,20 @@ void du_task_send_sctp_association_req(instance_t instance, f1ap_net_config_t *n sctp_new_association_req_p->in_streams = 2; //du_inst->sctp_in_streams; sctp_new_association_req_p->out_streams = 2; //du_inst->sctp_out_streams; // remote - memcpy(&sctp_new_association_req_p->remote_address, &nc->CU_f1_ip_address, sizeof(nc->CU_f1_ip_address)); + sctp_new_association_req_p->remote_address.ipv4 = 1; + strncpy(sctp_new_association_req_p->remote_address.ipv4_address, + nc->CU_f1_ip_address, + sizeof(sctp_new_association_req_p->remote_address.ipv4_address) - 1); // local - memcpy(&sctp_new_association_req_p->local_address, &nc->DU_f1c_ip_address, sizeof(nc->DU_f1c_ip_address)); + sctp_new_association_req_p->local_address.ipv4 = 1; + strncpy(sctp_new_association_req_p->local_address.ipv4_address, + nc->DU_f1c_ip_address, + sizeof(sctp_new_association_req_p->local_address.ipv4_address) - 1); + LOG_D(F1AP, + "Local IPv4 Address: %s, Remote IPv4 Address: %s\n", + sctp_new_association_req_p->local_address.ipv4_address, + sctp_new_association_req_p->remote_address.ipv4_address); + // du_f1ap_register_to_sctp itti_send_msg_to_task(TASK_SCTP, instance, message_p); } @@ -89,6 +100,8 @@ void du_task_handle_sctp_association_resp(instance_t instance, sctp_new_associat f1ap_du_data->du.assoc_id = sctp_new_association_resp->assoc_id; f1ap_du_data->sctp_in_streams = sctp_new_association_resp->in_streams; f1ap_du_data->sctp_out_streams = sctp_new_association_resp->out_streams; + /* next transaction ID */ + f1ap_du_data->setupReq.transaction_id = F1AP_get_next_transaction_identifier(0, 0); /* setup parameters for F1U and start the server */ DU_send_F1_SETUP_REQUEST(f1ap_du_data->du.assoc_id, &f1ap_du_data->setupReq); } diff --git a/openair2/F1AP/f1ap_du_ue_context_management.c b/openair2/F1AP/f1ap_du_ue_context_management.c index 6d9771f1f4..529c478ac2 100644 --- a/openair2/F1AP/f1ap_du_ue_context_management.c +++ b/openair2/F1AP/f1ap_du_ue_context_management.c @@ -45,13 +45,13 @@ static void f1ap_read_drb_qos_param(const F1AP_QoSFlowLevelQoSParameters_t *asn1 const F1AP_QoS_Characteristics_t *dRB_QoS_Char = &asn1_qos->qoS_Characteristics; if (dRB_QoS_Char->present == F1AP_QoS_Characteristics_PR_non_Dynamic_5QI) { - drb_qos_char->qos_type = non_dynamic; + drb_qos_char->qos_type = NON_DYNAMIC; drb_qos_char->non_dynamic.fiveqi = dRB_QoS_Char->choice.non_Dynamic_5QI->fiveQI; drb_qos_char->non_dynamic.qos_priority_level = (dRB_QoS_Char->choice.non_Dynamic_5QI->qoSPriorityLevel != NULL) ? *dRB_QoS_Char->choice.non_Dynamic_5QI->qoSPriorityLevel : -1; } else { - drb_qos_char->qos_type = dynamic; + drb_qos_char->qos_type = DYNAMIC; drb_qos_char->dynamic.fiveqi = (dRB_QoS_Char->choice.dynamic_5QI->fiveQI != NULL) ? *dRB_QoS_Char->choice.dynamic_5QI->fiveQI : -1; drb_qos_char->dynamic.qos_priority_level = dRB_QoS_Char->choice.dynamic_5QI->qoSPriorityLevel; @@ -84,13 +84,13 @@ static void f1ap_read_flows_mapped(const F1AP_Flows_Mapped_To_DRB_List_t *asn1_f const F1AP_QoS_Characteristics_t *Flow_QoS_Char = &Flow_QoS->qoS_Characteristics; if (Flow_QoS_Char->present == F1AP_QoS_Characteristics_PR_non_Dynamic_5QI) { - flow_qos_char->qos_type = non_dynamic; + flow_qos_char->qos_type = NON_DYNAMIC; flow_qos_char->non_dynamic.fiveqi = Flow_QoS_Char->choice.non_Dynamic_5QI->fiveQI; flow_qos_char->non_dynamic.qos_priority_level = (Flow_QoS_Char->choice.non_Dynamic_5QI->qoSPriorityLevel != NULL) ? *Flow_QoS_Char->choice.non_Dynamic_5QI->qoSPriorityLevel : -1; } else { - flow_qos_char->qos_type = dynamic; + flow_qos_char->qos_type = DYNAMIC; flow_qos_char->dynamic.fiveqi = (Flow_QoS_Char->choice.dynamic_5QI->fiveQI != NULL) ? *Flow_QoS_Char->choice.dynamic_5QI->fiveQI : -1; flow_qos_char->dynamic.qos_priority_level = Flow_QoS_Char->choice.dynamic_5QI->qoSPriorityLevel; @@ -209,11 +209,14 @@ int DU_handle_UE_CONTEXT_SETUP_REQUEST(instance_t instance, sctp_assoc_t assoc_i switch (drbs_tobesetup_item_p->rLCMode) { case F1AP_RLCMode_rlc_am: - drb_p->rlc_mode = RLC_MODE_AM; + drb_p->rlc_mode = F1AP_RLC_MODE_AM; + break; + case F1AP_RLCMode_rlc_um_bidirectional: + drb_p->rlc_mode = F1AP_RLC_MODE_UM_BIDIR; break; - default: - drb_p->rlc_mode = RLC_MODE_TM; + LOG_W(F1AP, "unsupported RLC Mode %ld received: setting UM bidir\n", drbs_tobesetup_item_p->rLCMode); + drb_p->rlc_mode = F1AP_RLC_MODE_UM_BIDIR; break; } @@ -930,13 +933,16 @@ int DU_handle_UE_CONTEXT_MODIFICATION_REQUEST(instance_t instance, sctp_assoc_t drb_p->up_ul_tnl[0].port = getCxt(instance)->net_config.CUport; switch (drbs_tobesetupmod_item_p->rLCMode) { - case F1AP_RLCMode_rlc_am: - drb_p->rlc_mode = RLC_MODE_AM; - break; - - default: - drb_p->rlc_mode = RLC_MODE_TM; - break; + case F1AP_RLCMode_rlc_am: + drb_p->rlc_mode = F1AP_RLC_MODE_AM; + break; + case F1AP_RLCMode_rlc_um_bidirectional: + drb_p->rlc_mode = F1AP_RLC_MODE_UM_BIDIR; + break; + default: + LOG_W(F1AP, "unsupported RLC Mode %ld received: setting UM bidir\n", drbs_tobesetupmod_item_p->rLCMode); + drb_p->rlc_mode = F1AP_RLC_MODE_UM_BIDIR; + break; } if (drbs_tobesetupmod_item_p->qoSInformation.present == F1AP_QoSInformation_PR_eUTRANQoS) { diff --git a/openair2/F1AP/f1ap_du_warning_message_transmission.c b/openair2/F1AP/f1ap_du_warning_message_transmission.c deleted file mode 100644 index 725bb4e1af..0000000000 --- a/openair2/F1AP/f1ap_du_warning_message_transmission.c +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The OpenAirInterface Software Alliance licenses this file to You under - * the OAI Public License, Version 1.1 (the "License"); you may not use this file - * except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.openairinterface.org/?page_id=698 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - *------------------------------------------------------------------------------- - * For more information about the OpenAirInterface (OAI) Software Alliance: - * contact@openairinterface.org - */ - -/*! \file f1ap_du_interface_management.h - * \brief f1ap interface management for DU - * \author EURECOM/NTUST - * \date 2018 - * \version 0.1 - * \company Eurecom - * \email: navid.nikaein@eurecom.fr, bing-kai.hong@eurecom.fr - * \note - * \warning - */ diff --git a/openair2/F1AP/f1ap_handlers.c b/openair2/F1AP/f1ap_handlers.c index bfaa9959dc..6234dcd624 100644 --- a/openair2/F1AP/f1ap_handlers.c +++ b/openair2/F1AP/f1ap_handlers.c @@ -48,10 +48,8 @@ static const f1ap_message_processing_t f1ap_messages_processing[][3] = { // {CU_handle_RESET, DU_handle_RESET_ACKNOWLEDGE, 0}, /* Reset */ {CU_handle_F1_SETUP_REQUEST, DU_handle_F1_SETUP_RESPONSE, DU_handle_F1_SETUP_FAILURE}, /* F1Setup */ {0, 0, 0}, /* ErrorIndication */ - {CU_handle_gNB_DU_CONFIGURATION_UPDATE, 0, 0}, /* gNBDUConfigurationUpdate */ - {DU_handle_gNB_CU_CONFIGURATION_UPDATE, - CU_handle_gNB_CU_CONFIGURATION_UPDATE_ACKNOWLEDGE, - CU_handle_gNB_CU_CONFIGURATION_UPDATE_FAILURE}, /* gNBCUConfigurationUpdate */ + {CU_handle_gNB_DU_CONFIGURATION_UPDATE, DU_handle_gNB_DU_CONFIGURATION_UPDATE_ACKNOWLEDGE, 0}, /* gNBDUConfigurationUpdate */ + {DU_handle_gNB_CU_CONFIGURATION_UPDATE, CU_handle_gNB_CU_CONFIGURATION_UPDATE_ACKNOWLEDGE, 0}, /* gNBCUConfigurationUpdate */ {DU_handle_UE_CONTEXT_SETUP_REQUEST, CU_handle_UE_CONTEXT_SETUP_RESPONSE, 0}, /* UEContextSetup */ {DU_handle_UE_CONTEXT_RELEASE_COMMAND, CU_handle_UE_CONTEXT_RELEASE_COMPLETE, 0}, /* UEContextRelease */ {DU_handle_UE_CONTEXT_MODIFICATION_REQUEST, CU_handle_UE_CONTEXT_MODIFICATION_RESPONSE, 0}, /* UEContextModification */ diff --git a/openair2/F1AP/lib/CMakeLists.txt b/openair2/F1AP/lib/CMakeLists.txt new file mode 100644 index 0000000000..cb8d8b9712 --- /dev/null +++ b/openair2/F1AP/lib/CMakeLists.txt @@ -0,0 +1,10 @@ +add_library(f1ap_lib OBJECT + f1ap_lib_common.c + f1ap_rrc_message_transfer.c + f1ap_interface_management.c +) +target_link_libraries(f1ap_lib PRIVATE asn1_f1ap) +target_include_directories(f1ap_lib PUBLIC + ${CMAKE_SOURCE_DIR} + ${CMAKE_CURRENT_SOURCE_DIR} +) diff --git a/openair2/F1AP/lib/f1ap_interface_management.c b/openair2/F1AP/lib/f1ap_interface_management.c new file mode 100644 index 0000000000..cb0b6ab8aa --- /dev/null +++ b/openair2/F1AP/lib/f1ap_interface_management.c @@ -0,0 +1,1767 @@ +/* + * 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 "common/utils/assertions.h" +#include "openair3/UTILS/conversions.h" +#include "common/utils/oai_asn1.h" +#include "common/utils/utils.h" + +#include "f1ap_interface_management.h" +#include "f1ap_lib_common.h" +#include "f1ap_lib_includes.h" +#include "f1ap_messages_types.h" +#include "f1ap_lib_extern.h" + +static const int nrb_lut[29] = {11, 18, 24, 25, 31, 32, 38, 51, 52, 65, 66, 78, 79, 93, 106, + 107, 121, 132, 133, 135, 160, 162, 189, 216, 217, 245, 264, 270, 273}; + +static int to_NRNRB(int nrb) +{ + for (int i = 0; i < sizeofArray(nrb_lut); i++) + if (nrb_lut[i] == nrb) + return i; + AssertFatal(1 == 0, "nrb %d is not in the list of possible NRNRB\n", nrb); +} + +static int read_slice_info(const F1AP_ServedPLMNs_Item_t *plmn, nssai_t *nssai, int max_nssai) +{ + if (plmn->iE_Extensions == NULL) + return 0; + + const F1AP_ProtocolExtensionContainer_10696P34_t *p = (F1AP_ProtocolExtensionContainer_10696P34_t *)plmn->iE_Extensions; + if (p->list.count == 0) + return 0; + + const F1AP_ServedPLMNs_ItemExtIEs_t *splmn = p->list.array[0]; + DevAssert(splmn->id == F1AP_ProtocolIE_ID_id_TAISliceSupportList); + DevAssert(splmn->extensionValue.present == F1AP_ServedPLMNs_ItemExtIEs__extensionValue_PR_SliceSupportList); + const F1AP_SliceSupportList_t *ssl = &splmn->extensionValue.choice.SliceSupportList; + AssertFatal(ssl->list.count <= max_nssai, "cannot handle more than 16 slices\n"); + for (int s = 0; s < ssl->list.count; ++s) { + const F1AP_SliceSupportItem_t *sl = ssl->list.array[s]; + nssai_t *n = &nssai[s]; + OCTET_STRING_TO_INT8(&sl->sNSSAI.sST, n->sst); + n->sd = 0xffffff; + if (sl->sNSSAI.sD != NULL) + OCTET_STRING_TO_INT24(sl->sNSSAI.sD, n->sd); + } + + return ssl->list.count; +} + +/** + * @brief F1AP Setup Request memory management + */ +static void free_f1ap_cell(const f1ap_served_cell_info_t *info, const f1ap_gnb_du_system_info_t *sys_info) +{ + if (sys_info) { + free(sys_info->mib); + free(sys_info->sib1); + free((void *)sys_info); + } + free(info->measurement_timing_config); + free(info->tac); +} + +/** + * @brief Encoding of Served Cell Information (9.3.1.10 of 3GPP TS 38.473) + */ +static F1AP_Served_Cell_Information_t encode_served_cell_info(const f1ap_served_cell_info_t *c) +{ + F1AP_Served_Cell_Information_t scell_info = {0}; + // NR CGI + MCC_MNC_TO_PLMNID(c->plmn.mcc, c->plmn.mnc, c->plmn.mnc_digit_length, &(scell_info.nRCGI.pLMN_Identity)); + NR_CELL_ID_TO_BIT_STRING(c->nr_cellid, &(scell_info.nRCGI.nRCellIdentity)); + // NR PCI + scell_info.nRPCI = c->nr_pci; // int 0..1007 + // 5GS TAC + if (c->tac != NULL) { + uint32_t tac = htonl(*c->tac); + asn1cCalloc(scell_info.fiveGS_TAC, netOrder); + OCTET_STRING_fromBuf(netOrder, ((char *)&tac) + 1, 3); + } + // Served PLMNs + asn1cSequenceAdd(scell_info.servedPLMNs.list, F1AP_ServedPLMNs_Item_t, servedPLMN_item); + MCC_MNC_TO_PLMNID(c->plmn.mcc, c->plmn.mnc, c->plmn.mnc_digit_length, &servedPLMN_item->pLMN_Identity); + // NR-Mode-Info + F1AP_NR_Mode_Info_t *nR_Mode_Info = &scell_info.nR_Mode_Info; + if (c->mode == F1AP_MODE_FDD) { // FDD + const f1ap_fdd_info_t *fdd = &c->fdd; + nR_Mode_Info->present = F1AP_NR_Mode_Info_PR_fDD; + asn1cCalloc(nR_Mode_Info->choice.fDD, fDD_Info); + /* FDD.1.1 UL NRFreqInfo ARFCN */ + fDD_Info->uL_NRFreqInfo.nRARFCN = fdd->ul_freqinfo.arfcn; + /* FDD.1.3 freqBandListNr */ + int ul_band = 1; + for (int j = 0; j < ul_band; j++) { + asn1cSequenceAdd(fDD_Info->uL_NRFreqInfo.freqBandListNr.list, F1AP_FreqBandNrItem_t, nr_freqBandNrItem); + /* FDD.1.3.1 freqBandIndicatorNr*/ + nr_freqBandNrItem->freqBandIndicatorNr = fdd->ul_freqinfo.band; + } + /* FDD.2.1 DL NRFreqInfo ARFCN */ + fDD_Info->dL_NRFreqInfo.nRARFCN = fdd->dl_freqinfo.arfcn; + /* FDD.2.3 freqBandListNr */ + int dl_bands = 1; + for (int j = 0; j < dl_bands; j++) { + asn1cSequenceAdd(fDD_Info->dL_NRFreqInfo.freqBandListNr.list, F1AP_FreqBandNrItem_t, nr_freqBandNrItem); + /* FDD.2.3.1 freqBandIndicatorNr*/ + nr_freqBandNrItem->freqBandIndicatorNr = fdd->dl_freqinfo.band; + } // for FDD : DL freq_Bands + /* FDD.3 UL Transmission Bandwidth */ + fDD_Info->uL_Transmission_Bandwidth.nRSCS = fdd->ul_tbw.scs; + fDD_Info->uL_Transmission_Bandwidth.nRNRB = to_NRNRB(fdd->ul_tbw.nrb); + /* FDD.4 DL Transmission Bandwidth */ + fDD_Info->dL_Transmission_Bandwidth.nRSCS = fdd->dl_tbw.scs; + fDD_Info->dL_Transmission_Bandwidth.nRNRB = to_NRNRB(fdd->dl_tbw.nrb); + } else if (c->mode == F1AP_MODE_TDD) { + const f1ap_tdd_info_t *tdd = &c->tdd; + nR_Mode_Info->present = F1AP_NR_Mode_Info_PR_tDD; + asn1cCalloc(nR_Mode_Info->choice.tDD, tDD_Info); + /* TDD.1.1 nRFreqInfo ARFCN */ + tDD_Info->nRFreqInfo.nRARFCN = tdd->freqinfo.arfcn; + /* TDD.1.3 freqBandListNr */ + int bands = 1; + for (int j = 0; j < bands; j++) { + asn1cSequenceAdd(tDD_Info->nRFreqInfo.freqBandListNr.list, F1AP_FreqBandNrItem_t, nr_freqBandNrItem); + /* TDD.1.3.1 freqBandIndicatorNr*/ + nr_freqBandNrItem->freqBandIndicatorNr = tdd->freqinfo.band; + } + /* TDD.2 transmission_Bandwidth */ + tDD_Info->transmission_Bandwidth.nRSCS = tdd->tbw.scs; + tDD_Info->transmission_Bandwidth.nRNRB = to_NRNRB(tdd->tbw.nrb); + } else { + AssertFatal(false, "unknown duplex mode %d\n", c->mode); + } + // Measurement Timing Configuration + OCTET_STRING_fromBuf(&scell_info.measurementTimingConfiguration, + (const char *)c->measurement_timing_config, + c->measurement_timing_config_len); + + return scell_info; +} + +static bool decode_served_cell_info(const F1AP_Served_Cell_Information_t *in, f1ap_served_cell_info_t *info) +{ + AssertError(in != NULL, return false, "Input message pointer is NULL"); + // 5GS TAC (O) + if (in->fiveGS_TAC) { + info->tac = malloc_or_fail(sizeof(*info->tac)); + OCTET_STRING_TO_INT24(in->fiveGS_TAC, *info->tac); + } + // NR CGI (M) + TBCD_TO_MCC_MNC(&(in->nRCGI.pLMN_Identity), info->plmn.mcc, info->plmn.mnc, info->plmn.mnc_digit_length); + // NR Cell Identity (M) + BIT_STRING_TO_NR_CELL_IDENTITY(&in->nRCGI.nRCellIdentity, info->nr_cellid); + // NR PCI (M) + info->nr_pci = in->nRPCI; + // Served PLMNs (>= 1) + AssertError(in->servedPLMNs.list.count == 1, return false, "at least and only 1 PLMN must be present"); + info->num_ssi = read_slice_info(in->servedPLMNs.list.array[0], info->nssai, 16); + // FDD Info + if (in->nR_Mode_Info.present == F1AP_NR_Mode_Info_PR_fDD) { + info->mode = F1AP_MODE_FDD; + f1ap_fdd_info_t *FDDs = &info->fdd; + F1AP_FDD_Info_t *fDD_Info = in->nR_Mode_Info.choice.fDD; + FDDs->ul_freqinfo.arfcn = fDD_Info->uL_NRFreqInfo.nRARFCN; + // Note: cannot handle more than one UL frequency band + int num_ulBands = fDD_Info->uL_NRFreqInfo.freqBandListNr.list.count; + AssertError(num_ulBands == 1, return false, "1 FDD UL frequency band must be present, more is not supported"); + for (int f = 0; f < num_ulBands && f < 1; f++) { + F1AP_FreqBandNrItem_t *FreqItem = fDD_Info->uL_NRFreqInfo.freqBandListNr.list.array[f]; + FDDs->ul_freqinfo.band = FreqItem->freqBandIndicatorNr; + AssertError(FreqItem->supportedSULBandList.list.count == 0, return false, "cannot handle FDD SUL bands"); + } + // Note: cannot handle more than one DL frequency band + FDDs->dl_freqinfo.arfcn = fDD_Info->dL_NRFreqInfo.nRARFCN; + int num_dlBands = fDD_Info->dL_NRFreqInfo.freqBandListNr.list.count; + AssertError(num_dlBands == 1, return false, "1 FDD DL frequency band must be present, more is not supported"); + for (int dlB = 0; dlB < num_dlBands && dlB < 1; dlB++) { + F1AP_FreqBandNrItem_t *FreqItem = fDD_Info->dL_NRFreqInfo.freqBandListNr.list.array[dlB]; + FDDs->dl_freqinfo.band = FreqItem->freqBandIndicatorNr; + AssertError(FreqItem->supportedSULBandList.list.count == 0, return false, "cannot handle FDD SUL bands"); + } + FDDs->ul_tbw.scs = fDD_Info->uL_Transmission_Bandwidth.nRSCS; + FDDs->ul_tbw.nrb = nrb_lut[fDD_Info->uL_Transmission_Bandwidth.nRNRB]; + FDDs->dl_tbw.scs = fDD_Info->dL_Transmission_Bandwidth.nRSCS; + FDDs->dl_tbw.nrb = nrb_lut[fDD_Info->dL_Transmission_Bandwidth.nRNRB]; + } else if (in->nR_Mode_Info.present == F1AP_NR_Mode_Info_PR_tDD) { + info->mode = F1AP_MODE_TDD; + f1ap_tdd_info_t *TDDs = &info->tdd; + F1AP_TDD_Info_t *tDD_Info = in->nR_Mode_Info.choice.tDD; + TDDs->freqinfo.arfcn = tDD_Info->nRFreqInfo.nRARFCN; + // Handle frequency bands + int num_tddBands = tDD_Info->nRFreqInfo.freqBandListNr.list.count; + AssertError(num_tddBands == 1, return false, "1 TDD DL frequency band must be present, more is not supported"); + for (int f = 0; f < num_tddBands && f < 1; f++) { + struct F1AP_FreqBandNrItem *FreqItem = tDD_Info->nRFreqInfo.freqBandListNr.list.array[f]; + TDDs->freqinfo.band = FreqItem->freqBandIndicatorNr; + AssertError(FreqItem->supportedSULBandList.list.count == 0, return false, "cannot handle TDD SUL bands"); + } + TDDs->tbw.scs = tDD_Info->transmission_Bandwidth.nRSCS; + TDDs->tbw.nrb = nrb_lut[tDD_Info->transmission_Bandwidth.nRNRB]; + } else { + AssertError(1 == 0, return false, "unknown or missing NR Mode info %d\n", in->nR_Mode_Info.present); + } + // MeasurementConfig (M) + AssertError(in->measurementTimingConfiguration.size > 0, return false, "measurementTimingConfigurationc size is 0"); + info->measurement_timing_config = cp_octet_string(&in->measurementTimingConfiguration, &info->measurement_timing_config_len); + return true; +} + +static F1AP_GNB_DU_System_Information_t *encode_system_info(const f1ap_gnb_du_system_info_t *sys_info) +{ + if (sys_info == NULL) + return NULL; /* optional: can be NULL */ + + F1AP_GNB_DU_System_Information_t *enc_sys_info = calloc_or_fail(1, sizeof(*enc_sys_info)); + + AssertFatal(sys_info->mib != NULL, "MIB must be present in DU sys info\n"); + OCTET_STRING_fromBuf(&enc_sys_info->mIB_message, (const char *)sys_info->mib, sys_info->mib_length); + + AssertFatal(sys_info->sib1 != NULL, "SIB1 must be present in DU sys info\n"); + OCTET_STRING_fromBuf(&enc_sys_info->sIB1_message, (const char *)sys_info->sib1, sys_info->sib1_length); + + return enc_sys_info; +} + +static void decode_system_info(struct F1AP_GNB_DU_System_Information *DUsi, f1ap_gnb_du_system_info_t *sys_info) +{ + /* mib */ + sys_info->mib = calloc_or_fail(DUsi->mIB_message.size, sizeof(*sys_info->mib)); + memcpy(sys_info->mib, DUsi->mIB_message.buf, DUsi->mIB_message.size); + sys_info->mib_length = DUsi->mIB_message.size; + /* sib1 */ + sys_info->sib1 = calloc_or_fail(DUsi->sIB1_message.size, sizeof(*sys_info->sib1)); + memcpy(sys_info->sib1, DUsi->sIB1_message.buf, DUsi->sIB1_message.size); + sys_info->sib1_length = DUsi->sIB1_message.size; +} + +static void encode_cells_to_activate(const served_cells_to_activate_t *cell, F1AP_Cells_to_be_Activated_List_ItemIEs_t *cells_to_be_activated_ies) +{ + cells_to_be_activated_ies->id = F1AP_ProtocolIE_ID_id_Cells_to_be_Activated_List_Item; + cells_to_be_activated_ies->criticality = F1AP_Criticality_reject; + cells_to_be_activated_ies->value.present = F1AP_Cells_to_be_Activated_List_ItemIEs__value_PR_Cells_to_be_Activated_List_Item; + // Cells to be Activated List Item (M) + F1AP_Cells_to_be_Activated_List_Item_t *cells_to_be_activated_item = + &cells_to_be_activated_ies->value.choice.Cells_to_be_Activated_List_Item; + // NR CGI (M) + MCC_MNC_TO_PLMNID(cell->plmn.mcc, + cell->plmn.mnc, + cell->plmn.mnc_digit_length, + &(cells_to_be_activated_item->nRCGI.pLMN_Identity)); + NR_CELL_ID_TO_BIT_STRING(cell->nr_cellid, &(cells_to_be_activated_item->nRCGI.nRCellIdentity)); + // NR PCI (O) + asn1cCalloc(cells_to_be_activated_item->nRPCI, tmp); + *tmp = cell->nrpci; + // gNB-CU System Information (O) + for (int n = 0; n < cell->num_SI; n++) { + F1AP_ProtocolExtensionContainer_10696P112_t *p = calloc_or_fail(1, sizeof(*p)); + cells_to_be_activated_item->iE_Extensions = (struct F1AP_ProtocolExtensionContainer *)p; + asn1cSequenceAdd(p->list, F1AP_Cells_to_be_Activated_List_ItemExtIEs_t, cells_to_be_activated_itemExtIEs); + cells_to_be_activated_itemExtIEs->id = F1AP_ProtocolIE_ID_id_gNB_CUSystemInformation; + cells_to_be_activated_itemExtIEs->criticality = F1AP_Criticality_reject; + cells_to_be_activated_itemExtIEs->extensionValue.present = + F1AP_Cells_to_be_Activated_List_ItemExtIEs__extensionValue_PR_GNB_CUSystemInformation; + // gNB-CU System Information message + F1AP_GNB_CUSystemInformation_t *gNB_CUSystemInformation = + &cells_to_be_activated_itemExtIEs->extensionValue.choice.GNB_CUSystemInformation; + const f1ap_sib_msg_t *SI_msg = &cell->SI_msg[n]; + if (SI_msg->SI_container != NULL) { + if (SI_msg->SI_type > 6 && SI_msg->SI_type != 9) { + asn1cSequenceAdd(gNB_CUSystemInformation->sibtypetobeupdatedlist.list, F1AP_SibtypetobeupdatedListItem_t, sib_item); + sib_item->sIBtype = SI_msg->SI_type; + OCTET_STRING_fromBuf(&sib_item->sIBmessage, (const char *)SI_msg->SI_container, SI_msg->SI_container_length); + } + } + } +} + +static bool decode_cells_to_activate(served_cells_to_activate_t *out, const F1AP_Cells_to_be_Activated_List_ItemIEs_t *in) +{ + AssertError(in->id == F1AP_ProtocolIE_ID_id_Cells_to_be_Activated_List_Item, + return false, + "ID != F1AP_ProtocolIE_ID_id_Cells_to_be_Activated_List_Item\n"); + AssertError(in->value.present == F1AP_Cells_to_be_Activated_List_ItemIEs__value_PR_Cells_to_be_Activated_List_Item, + return false, + "in->value.present != F1AP_Cells_to_be_Activated_List_ItemIEs__value_PR_Cells_to_be_Activated_List_Item\n"); + const F1AP_Cells_to_be_Activated_List_Item_t *cell = &in->value.choice.Cells_to_be_Activated_List_Item; + // NR CGI (M) + TBCD_TO_MCC_MNC(&cell->nRCGI.pLMN_Identity, out->plmn.mcc, out->plmn.mnc, out->plmn.mnc_digit_length); + BIT_STRING_TO_NR_CELL_IDENTITY(&cell->nRCGI.nRCellIdentity, out->nr_cellid); + // NR PCI (O) + if (cell->nRPCI != NULL) + out->nrpci = *cell->nRPCI; + /* IE extensions (O) */ + F1AP_ProtocolExtensionContainer_10696P112_t *ext = (F1AP_ProtocolExtensionContainer_10696P112_t *)cell->iE_Extensions; + if (ext != NULL) { + for (int cnt = 0; cnt < ext->list.count; cnt++) { + AssertError(ext->list.count == 1, return false, "At least one SI message should be present, and only 1 is supported"); + F1AP_Cells_to_be_Activated_List_ItemExtIEs_t *cells_to_be_activated_list_itemExtIEs = + (F1AP_Cells_to_be_Activated_List_ItemExtIEs_t *)ext->list.array[cnt]; + /* IE extensions items (O) */ + switch (cells_to_be_activated_list_itemExtIEs->id) { + /* gNB-CU System Information */ + case F1AP_ProtocolIE_ID_id_gNB_CUSystemInformation: { + out->nrpci = (cell->nRPCI != NULL) ? *cell->nRPCI : 0; + F1AP_GNB_CUSystemInformation_t *gNB_CUSystemInformation = + (F1AP_GNB_CUSystemInformation_t *)&cells_to_be_activated_list_itemExtIEs->extensionValue.choice.GNB_CUSystemInformation; + /* System Information */ + out->num_SI = gNB_CUSystemInformation->sibtypetobeupdatedlist.list.count; + for (int s = 0; s < out->num_SI; s++) { + F1AP_SibtypetobeupdatedListItem_t *sib_item = gNB_CUSystemInformation->sibtypetobeupdatedlist.list.array[s]; + /* SI container */ + f1ap_sib_msg_t *SI_msg = &out->SI_msg[s]; + SI_msg->SI_container = cp_octet_string(&sib_item->sIBmessage, &SI_msg->SI_container_length); + /* SIB type */ + SI_msg->SI_type = sib_item->sIBtype; + } + break; + } + case F1AP_ProtocolIE_ID_id_AvailablePLMNList: + AssertError(1 == 0, return false, "F1AP_ProtocolIE_ID_id_AvailablePLMNList is not supported"); + break; + case F1AP_ProtocolIE_ID_id_ExtendedAvailablePLMN_List: + AssertError(1 == 0, return false, "F1AP_ProtocolIE_ID_id_ExtendedAvailablePLMN_List is not supported"); + break; + case F1AP_ProtocolIE_ID_id_IAB_Info_IAB_donor_CU: + AssertError(1 == 0, return false, "F1AP_ProtocolIE_ID_id_IAB_Info_IAB_donor_CU is not supported"); + break; + case F1AP_ProtocolIE_ID_id_AvailableSNPN_ID_List: + AssertError(1 == 0, return false, "F1AP_ProtocolIE_ID_id_AvailableSNPN_ID_List is not supported"); + break; + default: + AssertError(1 == 0, return false, "F1AP_ProtocolIE_ID_id %ld unknown\n", cells_to_be_activated_list_itemExtIEs->id); + break; + } + } + } + return true; +} + +/* ==================================== + * F1 SETUP REQUEST + * ==================================== */ + +/** + * @brief F1 SETUP REQUEST encoding (9.2.1.4 of 3GPP TS 38.473) + * gNB-DU → gNB-CU + */ +F1AP_F1AP_PDU_t *encode_f1ap_setup_request(const f1ap_setup_req_t *msg) +{ + F1AP_F1AP_PDU_t *pdu = calloc_or_fail(1, sizeof(*pdu)); + + /* Create */ + /* 0. pdu Type */ + pdu->present = F1AP_F1AP_PDU_PR_initiatingMessage; + asn1cCalloc(pdu->choice.initiatingMessage, initMsg); + initMsg->procedureCode = F1AP_ProcedureCode_id_F1Setup; + initMsg->criticality = F1AP_Criticality_reject; + initMsg->value.present = F1AP_InitiatingMessage__value_PR_F1SetupRequest; + F1AP_F1SetupRequest_t *f1Setup = &initMsg->value.choice.F1SetupRequest; + // Transaction ID (M) + asn1cSequenceAdd(f1Setup->protocolIEs.list, F1AP_F1SetupRequestIEs_t, ieC1); + ieC1->id = F1AP_ProtocolIE_ID_id_TransactionID; + ieC1->criticality = F1AP_Criticality_reject; + ieC1->value.present = F1AP_F1SetupRequestIEs__value_PR_TransactionID; + ieC1->value.choice.TransactionID = msg->transaction_id; + // gNB-DU ID (M) + asn1cSequenceAdd(f1Setup->protocolIEs.list, F1AP_F1SetupRequestIEs_t, ieC2); + ieC2->id = F1AP_ProtocolIE_ID_id_gNB_DU_ID; + ieC2->criticality = F1AP_Criticality_reject; + ieC2->value.present = F1AP_F1SetupRequestIEs__value_PR_GNB_DU_ID; + asn_int642INTEGER(&ieC2->value.choice.GNB_DU_ID, msg->gNB_DU_id); + // gNB-DU Name (O) + if (msg->gNB_DU_name) { + asn1cSequenceAdd(f1Setup->protocolIEs.list, F1AP_F1SetupRequestIEs_t, ieC3); + ieC3->id = F1AP_ProtocolIE_ID_id_gNB_DU_Name; + ieC3->criticality = F1AP_Criticality_ignore; + ieC3->value.present = F1AP_F1SetupRequestIEs__value_PR_GNB_DU_Name; + OCTET_STRING_fromBuf(&ieC3->value.choice.GNB_DU_Name, msg->gNB_DU_name, strlen(msg->gNB_DU_name)); + } + /// gNB-DU Served Cells List (0..1) + asn1cSequenceAdd(f1Setup->protocolIEs.list, F1AP_F1SetupRequestIEs_t, ieCells); + ieCells->id = F1AP_ProtocolIE_ID_id_gNB_DU_Served_Cells_List; + ieCells->criticality = F1AP_Criticality_reject; + ieCells->value.present = F1AP_F1SetupRequestIEs__value_PR_GNB_DU_Served_Cells_List; + for (int i = 0; i < msg->num_cells_available; i++) { + // gNB-DU Served Cells Item (M) + const f1ap_served_cell_info_t *cell = &msg->cell[i].info; + const f1ap_gnb_du_system_info_t *sys_info = msg->cell[i].sys_info; + asn1cSequenceAdd(ieCells->value.choice.GNB_DU_Served_Cells_List.list, F1AP_GNB_DU_Served_Cells_ItemIEs_t, duServedCell); + duServedCell->id = F1AP_ProtocolIE_ID_id_GNB_DU_Served_Cells_Item; + duServedCell->criticality = F1AP_Criticality_reject; + duServedCell->value.present = F1AP_GNB_DU_Served_Cells_ItemIEs__value_PR_GNB_DU_Served_Cells_Item; + F1AP_GNB_DU_Served_Cells_Item_t *scell_item = &duServedCell->value.choice.GNB_DU_Served_Cells_Item; + scell_item->served_Cell_Information = encode_served_cell_info(cell); + scell_item->gNB_DU_System_Information = encode_system_info(sys_info); + } + // gNB-DU RRC version (M) + asn1cSequenceAdd(f1Setup->protocolIEs.list, F1AP_F1SetupRequestIEs_t, ie2); + ie2->id = F1AP_ProtocolIE_ID_id_GNB_DU_RRC_Version; + ie2->criticality = F1AP_Criticality_reject; + ie2->value.present = F1AP_F1SetupRequestIEs__value_PR_RRC_Version; + // RRC Version: "This IE is not used in this release." + // we put one bit for each byte in rrc_ver that is != 0 + uint8_t bits = 0; + for (int i = 0; i < sizeofArray(msg->rrc_ver); ++i) + bits |= (msg->rrc_ver[i] != 0) << i; + BIT_STRING_t *bs = &ie2->value.choice.RRC_Version.latest_RRC_Version; + bs->buf = calloc_or_fail(1, sizeof(*bs->buf)); + bs->buf[0] = bits; + bs->size = 1; + bs->bits_unused = 5; + + F1AP_ProtocolExtensionContainer_10696P228_t *p = calloc_or_fail(1, sizeof(*p)); + asn1cSequenceAdd(p->list, F1AP_RRC_Version_ExtIEs_t, rrcv_ext); + rrcv_ext->id = F1AP_ProtocolIE_ID_id_latest_RRC_Version_Enhanced; + rrcv_ext->criticality = F1AP_Criticality_ignore; + rrcv_ext->extensionValue.present = F1AP_RRC_Version_ExtIEs__extensionValue_PR_OCTET_STRING_SIZE_3_; + OCTET_STRING_t *os = &rrcv_ext->extensionValue.choice.OCTET_STRING_SIZE_3_; + os->size = sizeofArray(msg->rrc_ver); + os->buf = malloc_or_fail(sizeof(msg->rrc_ver)); + for (int i = 0; i < sizeofArray(msg->rrc_ver); ++i) + os->buf[i] = msg->rrc_ver[i]; + ie2->value.choice.RRC_Version.iE_Extensions = (struct F1AP_ProtocolExtensionContainer *)p; + return pdu; +} + +/** + * @brief F1AP Setup Request decoding + */ +bool decode_f1ap_setup_request(const F1AP_F1AP_PDU_t *pdu, f1ap_setup_req_t *out) +{ + /* Check presence of message type */ + _F1_EQ_CHECK_INT(pdu->present, F1AP_F1AP_PDU_PR_initiatingMessage); + AssertError(pdu->choice.initiatingMessage != NULL, return false, "pdu->choice.initiatingMessage is NULL"); + _F1_EQ_CHECK_LONG(pdu->choice.initiatingMessage->procedureCode, F1AP_ProcedureCode_id_F1Setup); + _F1_EQ_CHECK_INT(pdu->choice.initiatingMessage->value.present, F1AP_InitiatingMessage__value_PR_F1SetupRequest); + /* Check presence of mandatory IEs */ + F1AP_F1SetupRequest_t *in = &pdu->choice.initiatingMessage->value.choice.F1SetupRequest; + F1AP_F1SetupRequestIEs_t *ie; + F1AP_LIB_FIND_IE(F1AP_F1SetupRequestIEs_t, ie, in, F1AP_ProtocolIE_ID_id_TransactionID, true); + F1AP_LIB_FIND_IE(F1AP_F1SetupRequestIEs_t, ie, in, F1AP_ProtocolIE_ID_id_gNB_DU_ID, true); + F1AP_LIB_FIND_IE(F1AP_F1SetupRequestIEs_t, ie, in, F1AP_ProtocolIE_ID_id_GNB_DU_RRC_Version, true); + /* Loop over all IEs */ + for (int i = 0; i < in->protocolIEs.list.count; i++) { + AssertError(in->protocolIEs.list.array[i] != NULL, return false, "in->protocolIEs.list.array[i] is NULL"); + ie = in->protocolIEs.list.array[i]; + switch (ie->id) { + case F1AP_ProtocolIE_ID_id_TransactionID: + // Transaction ID (M) + _F1_EQ_CHECK_INT(ie->value.present, F1AP_F1SetupRequestIEs__value_PR_TransactionID); + AssertError(ie->value.choice.TransactionID != -1, return false, "ie->value.choice.TransactionID is -1"); + out->transaction_id = ie->value.choice.TransactionID; + break; + case F1AP_ProtocolIE_ID_id_gNB_DU_ID: + // gNB-DU ID (M) + _F1_EQ_CHECK_INT(ie->value.present, F1AP_F1SetupRequestIEs__value_PR_GNB_DU_ID); + asn_INTEGER2ulong(&ie->value.choice.GNB_DU_ID, &out->gNB_DU_id); + break; + case F1AP_ProtocolIE_ID_id_gNB_DU_Name: { + const F1AP_GNB_DU_Name_t *du_name = &ie->value.choice.GNB_DU_Name; + out->gNB_DU_name = calloc_or_fail(du_name->size + 1, sizeof(*out->gNB_DU_name)); + strncpy(out->gNB_DU_name, (char *)du_name->buf, du_name->size); + break; + } + case F1AP_ProtocolIE_ID_id_gNB_DU_Served_Cells_List: + /* GNB_DU_Served_Cells_List */ + out->num_cells_available = ie->value.choice.GNB_DU_Served_Cells_List.list.count; + AssertError(out->num_cells_available > 0, return false, "at least 1 cell must be present"); + /* Loop over gNB-DU Served Cells Items */ + for (int i = 0; i < out->num_cells_available; i++) { + F1AP_GNB_DU_Served_Cells_Item_t *served_cells_item = + &(((F1AP_GNB_DU_Served_Cells_ItemIEs_t *)ie->value.choice.GNB_DU_Served_Cells_List.list.array[i]) + ->value.choice.GNB_DU_Served_Cells_Item); + // gNB-DU System Information (O) + struct F1AP_GNB_DU_System_Information *DUsi = served_cells_item->gNB_DU_System_Information; + if (DUsi != NULL) { + // System Information + out->cell[i].sys_info = calloc_or_fail(1, sizeof(*out->cell[i].sys_info)); + f1ap_gnb_du_system_info_t *sys_info = out->cell[i].sys_info; + /* mib */ + sys_info->mib = cp_octet_string(&DUsi->mIB_message, &sys_info->mib_length); + /* sib1 */ + sys_info->sib1 = cp_octet_string(&DUsi->sIB1_message, &sys_info->sib1_length); + } + /* Served Cell Information (M) */ + if (!decode_served_cell_info(&served_cells_item->served_Cell_Information, &out->cell[i].info)) + return false; + } + break; + case F1AP_ProtocolIE_ID_id_GNB_DU_RRC_Version: + /* gNB-DU RRC version (M) */ + if (ie->value.choice.RRC_Version.iE_Extensions) { + F1AP_ProtocolExtensionContainer_10696P228_t *ext = + (F1AP_ProtocolExtensionContainer_10696P228_t *)ie->value.choice.RRC_Version.iE_Extensions; + if (ext->list.count > 0) { + F1AP_RRC_Version_ExtIEs_t *rrcext = ext->list.array[0]; + OCTET_STRING_t *os = &rrcext->extensionValue.choice.OCTET_STRING_SIZE_3_; + DevAssert(os->size == sizeofArray(out->rrc_ver)); + for (int i = 0; i < os->size; ++i) + out->rrc_ver[i] = os->buf[i]; + } + } + break; + default: + AssertError(1 == 0, return false, "F1AP_ProtocolIE_ID_id %ld unknown\n", ie->id); + break; + } + } + return true; +} + +static void copy_f1ap_served_cell_info(f1ap_served_cell_info_t *dest, const f1ap_served_cell_info_t *src) { + *dest = *src; + dest->mode = src->mode; + dest->tdd = src->tdd; + dest->fdd = src->fdd; + dest->plmn = src->plmn; + if (src->tac) { + dest->tac = malloc_or_fail(sizeof(*dest->tac)); + *dest->tac = *src->tac; + } + if (src->measurement_timing_config_len) { + dest->measurement_timing_config = calloc_or_fail(src->measurement_timing_config_len, sizeof(*dest->measurement_timing_config)); + memcpy(dest->measurement_timing_config, src->measurement_timing_config, src->measurement_timing_config_len); + } +} + +/** + * @brief F1AP Setup Request deep copy + */ +f1ap_setup_req_t cp_f1ap_setup_request(const f1ap_setup_req_t *msg) +{ + f1ap_setup_req_t cp = {0}; + /* gNB_DU_id */ + cp.gNB_DU_id = msg->gNB_DU_id; + /* gNB_DU_name */ + if (msg->gNB_DU_name != NULL) + cp.gNB_DU_name = strdup(msg->gNB_DU_name); + /* transaction_id */ + cp.transaction_id = msg->transaction_id; + /* num_cells_available */ + cp.num_cells_available = msg->num_cells_available; + for (int n = 0; n < msg->num_cells_available; n++) { + /* cell.info */ + f1ap_served_cell_info_t *sci = &cp.cell[n].info; + const f1ap_served_cell_info_t *msg_sci = &msg->cell[n].info; + copy_f1ap_served_cell_info(sci, msg_sci); + /* cell.sys_info */ + if (msg->cell[n].sys_info) { + f1ap_gnb_du_system_info_t *orig_sys_info = msg->cell[n].sys_info; + f1ap_gnb_du_system_info_t *copy_sys_info = calloc_or_fail(1, sizeof(*copy_sys_info)); + cp.cell[n].sys_info = copy_sys_info; + if (orig_sys_info->mib_length > 0) { + copy_sys_info->mib = calloc_or_fail(orig_sys_info->mib_length, sizeof(*copy_sys_info->mib)); + copy_sys_info->mib_length = orig_sys_info->mib_length; + memcpy(copy_sys_info->mib, orig_sys_info->mib, copy_sys_info->mib_length); + } + if (orig_sys_info->sib1_length > 0) { + copy_sys_info->sib1 = calloc_or_fail(orig_sys_info->sib1_length, sizeof(*copy_sys_info->sib1)); + copy_sys_info->sib1_length = orig_sys_info->sib1_length; + memcpy(copy_sys_info->sib1, orig_sys_info->sib1, copy_sys_info->sib1_length); + } + } + } + for (int i = 0; i < sizeofArray(msg->rrc_ver); i++) + cp.rrc_ver[i] = msg->rrc_ver[i]; + return cp; +} + +/** + * @brief F1AP Setup Request equality check + */ +bool eq_f1ap_setup_request(const f1ap_setup_req_t *a, const f1ap_setup_req_t *b) +{ + _F1_EQ_CHECK_LONG(a->gNB_DU_id, b->gNB_DU_id); + _F1_EQ_CHECK_STR(a->gNB_DU_name, b->gNB_DU_name); + _F1_EQ_CHECK_LONG(a->transaction_id, b->transaction_id); + _F1_EQ_CHECK_INT(a->num_cells_available, b->num_cells_available); + for (int i = 0; i < a->num_cells_available; i++) { + if (!eq_f1ap_cell_info(&a->cell[i].info, &b->cell[i].info)) + return false; + if (!eq_f1ap_sys_info(a->cell[i].sys_info, b->cell[i].sys_info)) + return false; + } + _F1_EQ_CHECK_LONG(sizeofArray(a->rrc_ver), sizeofArray(b->rrc_ver)); + for (int i = 0; i < sizeofArray(a->rrc_ver); i++) { + _F1_EQ_CHECK_INT(a->rrc_ver[i], b->rrc_ver[i]); + } + return true; +} + +/** + * @brief F1AP Setup Request memory management + */ +void free_f1ap_setup_request(const f1ap_setup_req_t *msg) +{ + DevAssert(msg != NULL); + free(msg->gNB_DU_name); + for (int i = 0; i < msg->num_cells_available; i++) { + free_f1ap_cell(&msg->cell[i].info, msg->cell[i].sys_info); + } +} + +/* ==================================== + * F1 Setup Response + * ==================================== */ + +/** + * @brief F1 Setup Response encoding (9.2.1.5 of 3GPP TS 38.473) + * gNB-CU → gNB-DU + */ +F1AP_F1AP_PDU_t *encode_f1ap_setup_response(const f1ap_setup_resp_t *msg) +{ + F1AP_F1AP_PDU_t *pdu = calloc_or_fail(1, sizeof(*pdu)); + + /* Create */ + /* 0. Message Type */ + pdu->present = F1AP_F1AP_PDU_PR_successfulOutcome; + asn1cCalloc(pdu->choice.successfulOutcome, tmp); + tmp->procedureCode = F1AP_ProcedureCode_id_F1Setup; + tmp->criticality = F1AP_Criticality_reject; + tmp->value.present = F1AP_SuccessfulOutcome__value_PR_F1SetupResponse; + F1AP_F1SetupResponse_t *out = &pdu->choice.successfulOutcome->value.choice.F1SetupResponse; + // Transaction ID (M) + asn1cSequenceAdd(out->protocolIEs.list, F1AP_F1SetupResponseIEs_t, ie1); + ie1->id = F1AP_ProtocolIE_ID_id_TransactionID; + ie1->criticality = F1AP_Criticality_reject; + ie1->value.present = F1AP_F1SetupResponseIEs__value_PR_TransactionID; + ie1->value.choice.TransactionID = msg->transaction_id; + // gNB-CU Name (O) + if (msg->gNB_CU_name != NULL) { + asn1cSequenceAdd(out->protocolIEs.list, F1AP_F1SetupResponseIEs_t, ie2); + ie2->id = F1AP_ProtocolIE_ID_id_gNB_CU_Name; + ie2->criticality = F1AP_Criticality_ignore; + ie2->value.present = F1AP_F1SetupResponseIEs__value_PR_GNB_CU_Name; + OCTET_STRING_fromBuf(&ie2->value.choice.GNB_CU_Name, msg->gNB_CU_name, strlen(msg->gNB_CU_name)); + } + // Cells to be Activated List (O) + for (int i = 0; i < msg->num_cells_to_activate; i++) { + asn1cSequenceAdd(out->protocolIEs.list, F1AP_F1SetupResponseIEs_t, ie3); + ie3->id = F1AP_ProtocolIE_ID_id_Cells_to_be_Activated_List; + ie3->criticality = F1AP_Criticality_reject; + ie3->value.present = F1AP_F1SetupResponseIEs__value_PR_Cells_to_be_Activated_List; + asn1cSequenceAdd(ie3->value.choice.Cells_to_be_Activated_List.list, + F1AP_Cells_to_be_Activated_List_ItemIEs_t, + cells_to_be_activated_ies); + encode_cells_to_activate(&msg->cells_to_activate[i], cells_to_be_activated_ies); + } + // gNB-CU RRC version (M) + asn1cSequenceAdd(out->protocolIEs.list, F1AP_F1SetupResponseIEs_t, ie4); + ie4->id = F1AP_ProtocolIE_ID_id_GNB_CU_RRC_Version; + ie4->criticality = F1AP_Criticality_reject; + ie4->value.present = F1AP_F1SetupResponseIEs__value_PR_RRC_Version; + // RRC Version: "This IE is not used in this release." + // we put one bit for each byte in rrc_ver that is != 0 + uint8_t bits = 0; + for (int i = 0; i < sizeofArray(msg->rrc_ver); ++i) + bits |= (msg->rrc_ver[i] != 0) << i; + BIT_STRING_t *bs = &ie4->value.choice.RRC_Version.latest_RRC_Version; + bs->buf = calloc_or_fail(1, sizeof(*bs->buf)); + bs->buf[0] = bits; + bs->size = 1; + bs->bits_unused = 5; + + F1AP_ProtocolExtensionContainer_10696P228_t *p = calloc_or_fail(1, sizeof(*p)); + asn1cSequenceAdd(p->list, F1AP_RRC_Version_ExtIEs_t, rrcv_ext); + rrcv_ext->id = F1AP_ProtocolIE_ID_id_latest_RRC_Version_Enhanced; + rrcv_ext->criticality = F1AP_Criticality_ignore; + rrcv_ext->extensionValue.present = F1AP_RRC_Version_ExtIEs__extensionValue_PR_OCTET_STRING_SIZE_3_; + OCTET_STRING_t *os = &rrcv_ext->extensionValue.choice.OCTET_STRING_SIZE_3_; + os->size = sizeofArray(msg->rrc_ver); + os->buf = malloc_or_fail(sizeof(msg->rrc_ver)); + for (int i = 0; i < sizeofArray(msg->rrc_ver); ++i) + os->buf[i] = msg->rrc_ver[i]; + ie4->value.choice.RRC_Version.iE_Extensions = (struct F1AP_ProtocolExtensionContainer *)p; + + return pdu; +} + +/** + * @brief F1 Setup Response decoding (9.2.1.5 of 3GPP TS 38.473) + * gNB-CU → gNB-DU + */ +bool decode_f1ap_setup_response(const F1AP_F1AP_PDU_t *pdu, f1ap_setup_resp_t *out) +{ + /* Check presence of message type */ + _F1_EQ_CHECK_INT(pdu->present, F1AP_F1AP_PDU_PR_successfulOutcome); + _F1_EQ_CHECK_LONG(pdu->choice.successfulOutcome->procedureCode, F1AP_ProcedureCode_id_F1Setup); + _F1_EQ_CHECK_INT(pdu->choice.successfulOutcome->value.present, F1AP_SuccessfulOutcome__value_PR_F1SetupResponse); + /* Check presence of mandatory IEs */ + F1AP_F1SetupResponse_t *in = &pdu->choice.successfulOutcome->value.choice.F1SetupResponse; + F1AP_F1SetupResponseIEs_t *ie; + F1AP_LIB_FIND_IE(F1AP_F1SetupResponseIEs_t, ie, in, F1AP_ProtocolIE_ID_id_TransactionID, true); + F1AP_LIB_FIND_IE(F1AP_F1SetupResponseIEs_t, ie, in, F1AP_ProtocolIE_ID_id_GNB_CU_RRC_Version, true); + /* Loop over all IEs */ + for (int i = 0; i < in->protocolIEs.list.count; i++) { + ie = in->protocolIEs.list.array[i]; + switch (ie->id) { + case F1AP_ProtocolIE_ID_id_TransactionID: + // Transaction ID (M) + _F1_EQ_CHECK_INT(ie->value.present, F1AP_F1SetupResponseIEs__value_PR_TransactionID); + AssertError(ie->value.choice.TransactionID != -1, return false, "ie->value.choice.TransactionID is -1"); + out->transaction_id = ie->value.choice.TransactionID; + break; + + case F1AP_ProtocolIE_ID_id_gNB_CU_Name: { + // gNB-CU Name (O) + _F1_EQ_CHECK_INT(ie->value.present, F1AP_F1SetupResponseIEs__value_PR_GNB_CU_Name); + const F1AP_GNB_CU_Name_t *cu_name = &ie->value.choice.GNB_CU_Name; + out->gNB_CU_name = calloc_or_fail(cu_name->size + 1, sizeof(*out->gNB_CU_name)); + strncpy(out->gNB_CU_name, (char *)cu_name->buf, cu_name->size); + } break; + + case F1AP_ProtocolIE_ID_id_GNB_CU_RRC_Version: + // gNB-CU RRC version (M) + _F1_EQ_CHECK_INT(ie->value.present, F1AP_F1SetupResponseIEs__value_PR_RRC_Version); + // RRC Version: "This IE is not used in this release." + if (ie->value.choice.RRC_Version.iE_Extensions) { + F1AP_ProtocolExtensionContainer_10696P228_t *ext = + (F1AP_ProtocolExtensionContainer_10696P228_t *)ie->value.choice.RRC_Version.iE_Extensions; + if (ext->list.count > 0) { + F1AP_RRC_Version_ExtIEs_t *rrcext = ext->list.array[0]; + OCTET_STRING_t *os = &rrcext->extensionValue.choice.OCTET_STRING_SIZE_3_; + for (int i = 0; i < sizeofArray(out->rrc_ver); i++) + out->rrc_ver[i] = os->buf[i]; + } + } + break; + + case F1AP_ProtocolIE_ID_id_Cells_to_be_Activated_List: { + // Cells to be Activated List (O) + if (ie->value.present != F1AP_F1SetupResponseIEs__value_PR_Cells_to_be_Activated_List) + break; + struct F1AP_Cells_to_be_Activated_List *Cells_to_be_Activated_List = &ie->value.choice.Cells_to_be_Activated_List; + out->num_cells_to_activate = Cells_to_be_Activated_List->list.count; + // Loop Cells to be Activated List Items (count >= 1) + AssertError(out->num_cells_to_activate > 0, return false, "At least 1 cell must be present"); + for (int i = 0; i < out->num_cells_to_activate; i++) { + const F1AP_Cells_to_be_Activated_List_ItemIEs_t *itemIEs + = (F1AP_Cells_to_be_Activated_List_ItemIEs_t *)Cells_to_be_Activated_List->list.array[i]; + if (!decode_cells_to_activate(&out->cells_to_activate[i], itemIEs)) + return false; + } + break; + } + default: + AssertError(1 == 0, return false, "F1AP_ProtocolIE_ID_id %ld unknown\n", ie->id); + break; + } + } + + return true; +} + +/** + * @brief F1AP Setup Response equality check + */ +bool eq_f1ap_setup_response(const f1ap_setup_resp_t *a, const f1ap_setup_resp_t *b) +{ + _F1_EQ_CHECK_STR(a->gNB_CU_name, b->gNB_CU_name); + _F1_EQ_CHECK_INT(a->num_cells_to_activate, b->num_cells_to_activate); + _F1_EQ_CHECK_LONG(a->transaction_id, b->transaction_id); + if (a->num_cells_to_activate) { + for (int i = 0; i < a->num_cells_to_activate; i++) { + const served_cells_to_activate_t *a_cell = &a->cells_to_activate[i]; + const served_cells_to_activate_t *b_cell = &b->cells_to_activate[i]; + _F1_EQ_CHECK_LONG(a_cell->nr_cellid, b_cell->nr_cellid); + _F1_EQ_CHECK_INT(a_cell->nrpci, b_cell->nrpci); + _F1_EQ_CHECK_INT(a_cell->num_SI, b_cell->num_SI); + _F1_EQ_CHECK_LONG(a_cell->nr_cellid, b_cell->nr_cellid); + if (!eq_f1ap_plmn(&a_cell->plmn, &b_cell->plmn)) + return false; + if (sizeofArray(a->cells_to_activate[i].SI_msg) != sizeofArray(b->cells_to_activate[i].SI_msg)) + return false; + for (int j = 0; j < b->cells_to_activate[i].num_SI; j++) { + const f1ap_sib_msg_t *a_SI_msg = &a->cells_to_activate[i].SI_msg[j]; + const f1ap_sib_msg_t *b_SI_msg = &b->cells_to_activate[i].SI_msg[j]; + _F1_EQ_CHECK_INT(*a_SI_msg->SI_container, *b_SI_msg->SI_container); + _F1_EQ_CHECK_INT(a_SI_msg->SI_container_length, b_SI_msg->SI_container_length); + _F1_EQ_CHECK_INT(a_SI_msg->SI_type, b_SI_msg->SI_type); + } + } + } + _F1_EQ_CHECK_LONG(sizeofArray(a->rrc_ver), sizeofArray(b->rrc_ver)); + for (int i = 0; i < sizeofArray(a->rrc_ver); i++) { + _F1_EQ_CHECK_INT(a->rrc_ver[i], b->rrc_ver[i]); + } + return true; +} + +/** + * @brief F1AP Setup Response deep copy + */ +f1ap_setup_resp_t cp_f1ap_setup_response(const f1ap_setup_resp_t *msg) +{ + f1ap_setup_resp_t cp = {0}; + /* gNB_CU_name */ + if (msg->gNB_CU_name != NULL) + cp.gNB_CU_name = strdup(msg->gNB_CU_name); + /* transaction_id */ + cp.transaction_id = msg->transaction_id; + /* num_cells_available */ + cp.num_cells_to_activate = msg->num_cells_to_activate; + for (int n = 0; n < msg->num_cells_to_activate; n++) { + /* cell.info */ + served_cells_to_activate_t *cp_cell = &cp.cells_to_activate[n]; + const served_cells_to_activate_t *msg_cell = &msg->cells_to_activate[n]; + cp_cell->nr_cellid = msg_cell->nr_cellid; + cp_cell->nrpci = msg_cell->nrpci; + cp_cell->num_SI = msg_cell->num_SI; + cp_cell->plmn = msg_cell->plmn; + for (int j = 0; j < cp_cell->num_SI; j++) { + f1ap_sib_msg_t *cp_SI_msg = &cp_cell->SI_msg[j]; + const f1ap_sib_msg_t *b_SI_msg = &msg_cell->SI_msg[j]; + cp_SI_msg->SI_container_length = b_SI_msg->SI_container_length; + cp_SI_msg->SI_container = malloc_or_fail(cp_SI_msg->SI_container_length); + *cp_SI_msg->SI_container = *b_SI_msg->SI_container; + cp_SI_msg->SI_type = b_SI_msg->SI_type; + } + } + for (int i = 0; i < sizeofArray(msg->rrc_ver); i++) + cp.rrc_ver[i] = msg->rrc_ver[i]; + return cp; +} + +/** + * @brief F1AP Setup Response memory management + */ +void free_f1ap_setup_response(const f1ap_setup_resp_t *msg) +{ + DevAssert(msg != NULL); + free(msg->gNB_CU_name); + for (int i = 0; i < msg->num_cells_to_activate; i++) + for (int j = 0; j < msg->cells_to_activate[i].num_SI; j++) + if (msg->cells_to_activate[i].SI_msg[j].SI_container_length > 0) + free(msg->cells_to_activate[i].SI_msg[j].SI_container); +} + +/* ==================================== + * F1AP Setup Failure + * ==================================== */ + +/** + * @brief F1AP Setup Failure encoding + */ +F1AP_F1AP_PDU_t *encode_f1ap_setup_failure(const f1ap_setup_failure_t *msg) +{ + F1AP_F1AP_PDU_t *pdu = calloc_or_fail(1, sizeof(*pdu)); + /* Create */ + /* 0. Message Type */ + asn1cCalloc(pdu->choice.unsuccessfulOutcome, UnsuccessfulOutcome); + pdu->present = F1AP_F1AP_PDU_PR_unsuccessfulOutcome; + UnsuccessfulOutcome->procedureCode = F1AP_ProcedureCode_id_F1Setup; + UnsuccessfulOutcome->criticality = F1AP_Criticality_reject; + UnsuccessfulOutcome->value.present = F1AP_UnsuccessfulOutcome__value_PR_F1SetupFailure; + F1AP_F1SetupFailure_t *out = &pdu->choice.unsuccessfulOutcome->value.choice.F1SetupFailure; + /* mandatory */ + /* c1. Transaction ID (integer value)*/ + asn1cSequenceAdd(out->protocolIEs.list, F1AP_F1SetupFailureIEs_t, ie1); + ie1->id = F1AP_ProtocolIE_ID_id_TransactionID; + ie1->criticality = F1AP_Criticality_reject; + ie1->value.present = F1AP_F1SetupFailureIEs__value_PR_TransactionID; + ie1->value.choice.TransactionID = msg->transaction_id; + /* mandatory */ + /* c2. Cause */ + asn1cSequenceAdd(out->protocolIEs.list, F1AP_F1SetupFailureIEs_t, ie2); + ie2->id = F1AP_ProtocolIE_ID_id_Cause; + ie2->criticality = F1AP_Criticality_ignore; + ie2->value.present = F1AP_F1SetupFailureIEs__value_PR_Cause; + ie2->value.choice.Cause.present = F1AP_Cause_PR_radioNetwork; + ie2->value.choice.Cause.choice.radioNetwork = msg->cause; + /* optional */ + /* c3. TimeToWait */ + if (msg->time_to_wait > 0) { + asn1cSequenceAdd(out->protocolIEs.list, F1AP_F1SetupFailureIEs_t, ie3); + ie3->id = F1AP_ProtocolIE_ID_id_TimeToWait; + ie3->criticality = F1AP_Criticality_ignore; + ie3->value.present = F1AP_F1SetupFailureIEs__value_PR_TimeToWait; + ie3->value.choice.TimeToWait = F1AP_TimeToWait_v10s; + } + /* optional */ + /* c4. CriticalityDiagnostics*/ + if (msg->criticality_diagnostics) { + asn1cSequenceAdd(out->protocolIEs.list, F1AP_F1SetupFailureIEs_t, ie4); + ie4->id = F1AP_ProtocolIE_ID_id_CriticalityDiagnostics; + ie4->criticality = F1AP_Criticality_ignore; + ie4->value.present = F1AP_F1SetupFailureIEs__value_PR_CriticalityDiagnostics; + asn1cCallocOne(ie4->value.choice.CriticalityDiagnostics.procedureCode, F1AP_ProcedureCode_id_UEContextSetup); + asn1cCallocOne(ie4->value.choice.CriticalityDiagnostics.triggeringMessage, F1AP_TriggeringMessage_initiating_message); + asn1cCallocOne(ie4->value.choice.CriticalityDiagnostics.procedureCriticality, F1AP_Criticality_reject); + asn1cCallocOne(ie4->value.choice.CriticalityDiagnostics.transactionID, 0); + } + return pdu; +} + +/** + * @brief F1AP Setup Failure decoding + */ +bool decode_f1ap_setup_failure(const F1AP_F1AP_PDU_t *pdu, f1ap_setup_failure_t *out) +{ + F1AP_F1SetupFailureIEs_t *ie; + F1AP_F1SetupFailure_t *in = &pdu->choice.unsuccessfulOutcome->value.choice.F1SetupFailure; + /* Check presence of mandatory IEs */ + F1AP_LIB_FIND_IE(F1AP_F1SetupFailureIEs_t, ie, in, F1AP_ProtocolIE_ID_id_TransactionID, true); + F1AP_LIB_FIND_IE(F1AP_F1SetupFailureIEs_t, ie, in, F1AP_ProtocolIE_ID_id_Cause, true); + /* Loop over all IEs */ + for (int i = 0; i < in->protocolIEs.list.count; i++) { + ie = in->protocolIEs.list.array[i]; + switch (ie->id) { + case F1AP_ProtocolIE_ID_id_TransactionID: + /* Transaction ID (M) */ + out->transaction_id = ie->value.choice.TransactionID; + break; + case F1AP_ProtocolIE_ID_id_Cause: + /* Cause (M) */ + out->cause = ie->value.choice.Cause.choice.radioNetwork; + break; + case F1AP_ProtocolIE_ID_id_TimeToWait: + out->time_to_wait = ie->value.choice.TimeToWait; + break; + case F1AP_ProtocolIE_ID_id_CriticalityDiagnostics: + AssertError(1 == 0, return false, "F1AP_ProtocolIE_ID_id_CriticalityDiagnostics is not supported"); + break; + default: + AssertError(1 == 0, return false, "F1AP_ProtocolIE_ID_id %ld unknown\n", ie->id); + break; + } + } + return true; +} + +/** + * @brief F1AP Setup Failure equality check + */ +bool eq_f1ap_setup_failure(const f1ap_setup_failure_t *a, const f1ap_setup_failure_t *b) +{ + if (a->transaction_id != b->transaction_id) + return false; + return true; +} + +/** + * @brief F1AP Setup Failure deep copy + */ +f1ap_setup_failure_t cp_f1ap_setup_failure(const f1ap_setup_failure_t *msg) +{ + f1ap_setup_failure_t cp = {0}; + /* transaction_id */ + cp.transaction_id = msg->transaction_id; + return cp; +} + +/* ==================================== + * F1AP gNB-DU Configuration Update + * ==================================== */ + +/** + * @brief F1 gNB-DU Configuration Update encoding (9.2.1.7 of 3GPP TS 38.473) + */ +F1AP_F1AP_PDU_t *encode_f1ap_du_configuration_update(const f1ap_gnb_du_configuration_update_t *msg) +{ + F1AP_F1AP_PDU_t *pdu = calloc_or_fail(1, sizeof(*pdu)); + /* Create */ + /* 0. Message Type */ + pdu->present = F1AP_F1AP_PDU_PR_initiatingMessage; + asn1cCalloc(pdu->choice.initiatingMessage, initMsg); + initMsg->procedureCode = F1AP_ProcedureCode_id_gNBDUConfigurationUpdate; + initMsg->criticality = F1AP_Criticality_reject; + initMsg->value.present = F1AP_InitiatingMessage__value_PR_GNBDUConfigurationUpdate; + F1AP_GNBDUConfigurationUpdate_t *out = &initMsg->value.choice.GNBDUConfigurationUpdate; + /* mandatory */ + /* c1. Transaction ID (integer value) */ + asn1cSequenceAdd(out->protocolIEs.list, F1AP_GNBDUConfigurationUpdateIEs_t, ie1); + ie1->id = F1AP_ProtocolIE_ID_id_TransactionID; + ie1->criticality = F1AP_Criticality_reject; + ie1->value.present = F1AP_GNBDUConfigurationUpdateIEs__value_PR_TransactionID; + ie1->value.choice.TransactionID = msg->transaction_id; + /* mandatory */ + /* c2. Served_Cells_To_Add */ + if (msg->num_cells_to_add > 0) { + AssertFatal(false, "code for adding cells not tested\n"); + asn1cSequenceAdd(out->protocolIEs.list, F1AP_GNBDUConfigurationUpdateIEs_t, ie2); + ie2->id = F1AP_ProtocolIE_ID_id_Served_Cells_To_Add_List; + ie2->criticality = F1AP_Criticality_reject; + ie2->value.present = F1AP_GNBDUConfigurationUpdateIEs__value_PR_Served_Cells_To_Add_List; + + for (int j = 0; j < msg->num_cells_to_add; j++) { + const f1ap_served_cell_info_t *cell = &msg->cell_to_add[j].info; + const f1ap_gnb_du_system_info_t *sys_info = msg->cell_to_add[j].sys_info; + asn1cSequenceAdd(ie2->value.choice.Served_Cells_To_Add_List.list, + F1AP_Served_Cells_To_Add_ItemIEs_t, + served_cells_to_add_item_ies); + served_cells_to_add_item_ies->id = F1AP_ProtocolIE_ID_id_Served_Cells_To_Add_Item; + served_cells_to_add_item_ies->criticality = F1AP_Criticality_reject; + served_cells_to_add_item_ies->value.present = F1AP_Served_Cells_To_Add_ItemIEs__value_PR_Served_Cells_To_Add_Item; + F1AP_Served_Cells_To_Add_Item_t *served_cells_to_add_item = + &served_cells_to_add_item_ies->value.choice.Served_Cells_To_Add_Item; + served_cells_to_add_item->served_Cell_Information = encode_served_cell_info(cell); + served_cells_to_add_item->gNB_DU_System_Information = encode_system_info(sys_info); + } + } + + /* mandatory */ + /* c3. Served_Cells_To_Modify */ + if (msg->num_cells_to_modify > 0) { + asn1cSequenceAdd(out->protocolIEs.list, F1AP_GNBDUConfigurationUpdateIEs_t, ie3); + ie3->id = F1AP_ProtocolIE_ID_id_Served_Cells_To_Modify_List; + ie3->criticality = F1AP_Criticality_reject; + ie3->value.present = F1AP_GNBDUConfigurationUpdateIEs__value_PR_Served_Cells_To_Modify_List; + for (int i = 0; i < msg->num_cells_to_modify; i++) { + const f1ap_served_cell_info_t *cell = &msg->cell_to_modify[i].info; + const f1ap_gnb_du_system_info_t *sys_info = msg->cell_to_modify[i].sys_info; + asn1cSequenceAdd(ie3->value.choice.Served_Cells_To_Modify_List.list, + F1AP_Served_Cells_To_Modify_ItemIEs_t, + served_cells_to_modify_item_ies); + served_cells_to_modify_item_ies->id = F1AP_ProtocolIE_ID_id_Served_Cells_To_Modify_Item; + served_cells_to_modify_item_ies->criticality = F1AP_Criticality_reject; + served_cells_to_modify_item_ies->value.present = F1AP_Served_Cells_To_Modify_ItemIEs__value_PR_Served_Cells_To_Modify_Item; + F1AP_Served_Cells_To_Modify_Item_t *served_cells_to_modify_item = + &served_cells_to_modify_item_ies->value.choice.Served_Cells_To_Modify_Item; + + F1AP_NRCGI_t *oldNRCGI = &served_cells_to_modify_item->oldNRCGI; + const f1ap_plmn_t *old_plmn = &msg->cell_to_modify[i].old_plmn; + MCC_MNC_TO_PLMNID(old_plmn->mcc, old_plmn->mnc, old_plmn->mnc_digit_length, &oldNRCGI->pLMN_Identity); + NR_CELL_ID_TO_BIT_STRING(msg->cell_to_modify[i].old_nr_cellid, &oldNRCGI->nRCellIdentity); + + served_cells_to_modify_item->served_Cell_Information = encode_served_cell_info(cell); + served_cells_to_modify_item->gNB_DU_System_Information = encode_system_info(sys_info); + } + } + + /* mandatory */ + /* c4. Served_Cells_To_Delete */ + if (msg->num_cells_to_delete > 0) { + asn1cSequenceAdd(out->protocolIEs.list, F1AP_GNBDUConfigurationUpdateIEs_t, ie4); + ie4->id = F1AP_ProtocolIE_ID_id_Served_Cells_To_Delete_List; + ie4->criticality = F1AP_Criticality_reject; + ie4->value.present = F1AP_GNBDUConfigurationUpdateIEs__value_PR_Served_Cells_To_Delete_List; + AssertFatal(msg->num_cells_to_delete == 0, "code for deleting cells not tested\n"); + for (int i = 0; i < msg->num_cells_to_delete; i++) { + asn1cSequenceAdd(ie4->value.choice.Served_Cells_To_Delete_List.list, + F1AP_Served_Cells_To_Delete_ItemIEs_t, + served_cells_to_delete_item_ies); + served_cells_to_delete_item_ies->id = F1AP_ProtocolIE_ID_id_Served_Cells_To_Delete_Item; + served_cells_to_delete_item_ies->criticality = F1AP_Criticality_reject; + served_cells_to_delete_item_ies->value.present = F1AP_Served_Cells_To_Delete_ItemIEs__value_PR_Served_Cells_To_Delete_Item; + F1AP_Served_Cells_To_Delete_Item_t *served_cells_to_delete_item = + &served_cells_to_delete_item_ies->value.choice.Served_Cells_To_Delete_Item; + F1AP_NRCGI_t *oldNRCGI = &served_cells_to_delete_item->oldNRCGI; + const f1ap_plmn_t *plmn = &msg->cell_to_delete[i].plmn; + MCC_MNC_TO_PLMNID(plmn->mcc, plmn->mnc, plmn->mnc_digit_length, &(oldNRCGI->pLMN_Identity)); + NR_CELL_ID_TO_BIT_STRING(msg->cell_to_delete[i].nr_cellid, &(oldNRCGI->nRCellIdentity)); + } + } + + /* optional */ + /* c5. GNB_DU_ID (integer value) */ + if (msg->gNB_DU_ID != NULL) { + asn1cSequenceAdd(out->protocolIEs.list, F1AP_GNBDUConfigurationUpdateIEs_t, ie5); + ie5->id = F1AP_ProtocolIE_ID_id_gNB_DU_ID; + ie5->criticality = F1AP_Criticality_reject; + ie5->value.present = F1AP_GNBDUConfigurationUpdateIEs__value_PR_GNB_DU_ID; + asn_int642INTEGER(&ie5->value.choice.GNB_DU_ID, *msg->gNB_DU_ID); + } + + return pdu; +} + +/** + * @brief F1 gNB-DU Configuration Update decoding (9.2.1.7 of 3GPP TS 38.473) + */ +bool decode_f1ap_du_configuration_update(const F1AP_F1AP_PDU_t *pdu, f1ap_gnb_du_configuration_update_t *out) +{ + /* Check presence of message type */ + _F1_EQ_CHECK_INT(pdu->present, F1AP_F1AP_PDU_PR_initiatingMessage); + _F1_EQ_CHECK_LONG(pdu->choice.initiatingMessage->procedureCode, F1AP_ProcedureCode_id_gNBDUConfigurationUpdate); + _F1_EQ_CHECK_INT(pdu->choice.initiatingMessage->value.present, F1AP_InitiatingMessage__value_PR_GNBDUConfigurationUpdate); + /* Check presence of mandatory IEs */ + F1AP_GNBDUConfigurationUpdate_t *in = &pdu->choice.initiatingMessage->value.choice.GNBDUConfigurationUpdate; + F1AP_GNBDUConfigurationUpdateIEs_t *ie; + /* Check mandatory IEs */ + F1AP_LIB_FIND_IE(F1AP_GNBDUConfigurationUpdateIEs_t, ie, in, F1AP_ProtocolIE_ID_id_TransactionID, true); + /* Loop over all IEs */ + for (int i = 0; i < in->protocolIEs.list.count; i++) { + AssertError(in->protocolIEs.list.array[i] != NULL, return false, "in->protocolIEs.list.array[i] is NULL"); + ie = in->protocolIEs.list.array[i]; + switch (ie->id) { + case F1AP_ProtocolIE_ID_id_TransactionID: { + out->transaction_id = ie->value.choice.TransactionID; + } break; + case F1AP_ProtocolIE_ID_id_Served_Cells_To_Add_List: { + /* Served Cells To Add List */ + AssertError(out->num_cells_to_add > 0, return false, "at least 1 cell to add shall to be present"); + out->num_cells_to_add = ie->value.choice.Served_Cells_To_Add_List.list.count; + for (int i = 0; i < out->num_cells_to_add; i++) { + F1AP_Served_Cells_To_Add_Item_t *served_cells_item = + &((F1AP_Served_Cells_To_Add_ItemIEs_t *)ie->value.choice.Served_Cells_To_Add_List.list.array[i]) + ->value.choice.Served_Cells_To_Add_Item; + /* Served Cell Information (M) */ + if (!decode_served_cell_info(&served_cells_item->served_Cell_Information, &out->cell_to_add[i].info)) + return false; + /* gNB-DU System Information */ + if (served_cells_item->gNB_DU_System_Information != NULL) { + out->cell_to_add[i].sys_info = calloc_or_fail(1, sizeof(*out->cell_to_add[i].sys_info)); + decode_system_info(served_cells_item->gNB_DU_System_Information, out->cell_to_add[i].sys_info); + } + } + } break; + case F1AP_ProtocolIE_ID_id_Served_Cells_To_Modify_List: { + /* Served Cells To Modify List (O) */ + out->num_cells_to_modify = ie->value.choice.Served_Cells_To_Modify_List.list.count; + AssertError(out->num_cells_to_modify > 0, return false, "at least 1 cell to modify shall to be present"); + for (int i = 0; i < out->num_cells_to_modify; i++) { + /* Served Cells To Modify List item (count >= 1) */ + F1AP_Served_Cells_To_Modify_Item_t *served_cells_item = + &((F1AP_Served_Cells_To_Modify_ItemIEs_t *)ie->value.choice.Served_Cells_To_Modify_List.list.array[i]) + ->value.choice.Served_Cells_To_Modify_Item; + /* Old NR CGI (M) */ + F1AP_NRCGI_t *oldNRCGI = &served_cells_item->oldNRCGI; + f1ap_plmn_t *old_plmn = &out->cell_to_modify[i].old_plmn; + TBCD_TO_MCC_MNC(&(oldNRCGI->pLMN_Identity), old_plmn->mcc, old_plmn->mnc, old_plmn->mnc_digit_length); + /* Old NR CGI Cell ID */ + BIT_STRING_TO_NR_CELL_IDENTITY(&oldNRCGI->nRCellIdentity, out->cell_to_modify[i].old_nr_cellid); + /* Served Cell Information (M) */ + if (!decode_served_cell_info(&served_cells_item->served_Cell_Information, &out->cell_to_modify[i].info)) + return false; + /* gNB-DU System Information (O) */ + if (served_cells_item->gNB_DU_System_Information != NULL) { + out->cell_to_modify[i].sys_info = calloc_or_fail(1, sizeof(*out->cell_to_modify[i].sys_info)); + decode_system_info(served_cells_item->gNB_DU_System_Information, out->cell_to_modify[i].sys_info); + } + } + } break; + case F1AP_ProtocolIE_ID_id_Served_Cells_To_Delete_List: { + /* Served Cells To Delete List */ + out->num_cells_to_delete = ie->value.choice.Served_Cells_To_Delete_List.list.count; + AssertError(out->num_cells_to_delete > 0, return false, "at least 1 cell to delete shall to be present"); + for (int i = 0; i < out->num_cells_to_delete; i++) { + F1AP_Served_Cells_To_Delete_Item_t *served_cells_item = + &((F1AP_Served_Cells_To_Delete_ItemIEs_t *)ie->value.choice.Served_Cells_To_Delete_List.list.array[i]) + ->value.choice.Served_Cells_To_Delete_Item; + F1AP_NRCGI_t *oldNRCGI = &served_cells_item->oldNRCGI; + f1ap_plmn_t *plmn = &out->cell_to_delete[i].plmn; + /* Old NR CGI (M) */ + TBCD_TO_MCC_MNC(&(oldNRCGI->pLMN_Identity), plmn->mcc, plmn->mnc, plmn->mnc_digit_length); + // NR cellID + BIT_STRING_TO_NR_CELL_IDENTITY(&oldNRCGI->nRCellIdentity, out->cell_to_delete[i].nr_cellid); + } + } break; + case F1AP_ProtocolIE_ID_id_Cells_Status_List: + /* Cells Status List (O) */ + AssertError(1 == 0, return false, "F1AP_ProtocolIE_ID_id_Cells_Status_List is not supported"); + break; + case F1AP_ProtocolIE_ID_id_Dedicated_SIDelivery_NeededUE_List: + /* Dedicated SI Delivery Needed UE List (O) */ + AssertError(1 == 0, return false, "F1AP_ProtocolIE_ID_id_Dedicated_SIDelivery_NeededUE_List is not supported"); + break; + case F1AP_ProtocolIE_ID_id_gNB_DU_ID: + /* gNB-DU ID (O)*/ + asn_INTEGER2ulong(&ie->value.choice.GNB_DU_ID, out->gNB_DU_ID); + break; + case F1AP_ProtocolIE_ID_id_GNB_DU_TNL_Association_To_Remove_List: + /* Cells Status List (O) */ + AssertError(1 == 0, return false, "F1AP_ProtocolIE_ID_id_GNB_DU_TNL_Association_To_Remove_List is not supported"); + break; + } + } + return true; +} + +void free_f1ap_du_configuration_update(const f1ap_gnb_du_configuration_update_t *msg) +{ + free(msg->gNB_DU_ID); + for (int i = 0; i < msg->num_cells_to_add; i++) { + free_f1ap_cell(&msg->cell_to_add[i].info, msg->cell_to_add[i].sys_info); + } + for (int i = 0; i < msg->num_cells_to_modify; i++) { + free_f1ap_cell(&msg->cell_to_modify[i].info, msg->cell_to_modify[i].sys_info); + } +} + +/** + * @brief F1 gNB-DU Configuration Update check + */ +bool eq_f1ap_du_configuration_update(const f1ap_gnb_du_configuration_update_t *a, const f1ap_gnb_du_configuration_update_t *b) +{ + if (a->gNB_DU_ID != NULL && b->gNB_DU_ID != NULL) + _F1_EQ_CHECK_LONG(*a->gNB_DU_ID, *b->gNB_DU_ID); + _F1_EQ_CHECK_LONG(a->transaction_id, b->transaction_id); + /* to add */ + _F1_EQ_CHECK_INT(a->num_cells_to_add, b->num_cells_to_add); + for (int i = 0; i < a->num_cells_to_add; i++) { + if (!eq_f1ap_cell_info(&a->cell_to_add[i].info, &b->cell_to_add[i].info)) + return false; + if (a->cell_to_add[i].sys_info && b->cell_to_add[i].sys_info) { + if (!eq_f1ap_sys_info(a->cell_to_add[i].sys_info, b->cell_to_add[i].sys_info)) + return false; + } + } + /* to delete */ + _F1_EQ_CHECK_INT(a->num_cells_to_delete, b->num_cells_to_delete); + for (int i = 0; i < a->num_cells_to_delete; i++) { + _F1_EQ_CHECK_LONG(a->cell_to_delete[i].nr_cellid, b->cell_to_delete[i].nr_cellid); + if (!eq_f1ap_plmn(&a->cell_to_delete[i].plmn, &b->cell_to_delete[i].plmn)) + return false; + } + /* to modify */ + _F1_EQ_CHECK_INT(a->num_cells_to_modify, b->num_cells_to_modify); + for (int i = 0; i < a->num_cells_to_modify; i++) { + if (!eq_f1ap_cell_info(&a->cell_to_modify[i].info, &b->cell_to_modify[i].info)) + return false; + if (a->cell_to_modify[i].sys_info && b->cell_to_modify[i].sys_info) { + if (!eq_f1ap_sys_info(a->cell_to_modify[i].sys_info, b->cell_to_modify[i].sys_info)) + return false; + } + } + return true; +} + +/** + * @brief F1 gNB-DU Configuration Update deep copy + */ +f1ap_gnb_du_configuration_update_t cp_f1ap_du_configuration_update(const f1ap_gnb_du_configuration_update_t *msg) +{ + f1ap_gnb_du_configuration_update_t cp = {0}; + /* gNB_DU_ID */ + if (msg->gNB_DU_ID != NULL) { + cp.gNB_DU_ID = calloc_or_fail(1, sizeof(*cp.gNB_DU_ID)); + *cp.gNB_DU_ID = *msg->gNB_DU_ID; + } + /* transaction_id */ + cp.transaction_id = msg->transaction_id; + /* to add */ + cp.num_cells_to_add = msg->num_cells_to_add; + /* to delete */ + cp.num_cells_to_delete = msg->num_cells_to_delete; + for (int i = 0; i < cp.num_cells_to_delete; i++) { + cp.cell_to_delete[i].nr_cellid = msg->cell_to_delete[i].nr_cellid; + cp.cell_to_delete[i].plmn = msg->cell_to_delete[i].plmn; + } + /* to modify */ + cp.num_cells_to_modify = msg->num_cells_to_modify; + for (int i = 0; i < cp.num_cells_to_modify; i++) { + cp.cell_to_modify[i].info = msg->cell_to_modify[i].info; + f1ap_served_cell_info_t *info = &cp.cell_to_modify[i].info; + if (info->measurement_timing_config_len > 0) { + info->measurement_timing_config = malloc_or_fail(info->measurement_timing_config_len * sizeof(*info->measurement_timing_config)); + for (int j = 0; j < info->measurement_timing_config_len; j++) + info->measurement_timing_config[j] = msg->cell_to_modify[i].info.measurement_timing_config[j]; + } + /* TAC */ + info->tac = calloc_or_fail(1, sizeof(*info->tac)); + *info->tac = *msg->cell_to_modify[i].info.tac; + /* System information */ + cp.cell_to_modify[i].sys_info = malloc_or_fail(sizeof(*cp.cell_to_modify[i].sys_info)); + f1ap_gnb_du_system_info_t *sys_info = cp.cell_to_modify[i].sys_info; + if (msg->cell_to_modify[i].sys_info->mib_length > 0) { + sys_info->mib_length = msg->cell_to_modify[i].sys_info->mib_length; + sys_info->mib = calloc_or_fail(msg->cell_to_modify[i].sys_info->mib_length, sizeof(*sys_info->mib)); + for (int j = 0; j < sys_info->mib_length; j++) + sys_info->mib[j] = msg->cell_to_modify[i].sys_info->mib[j]; + } + if (msg->cell_to_modify[i].sys_info->sib1_length > 0) { + sys_info->sib1_length = msg->cell_to_modify[i].sys_info->sib1_length; + sys_info->sib1 = calloc_or_fail(msg->cell_to_modify[i].sys_info->sib1_length, sizeof(*sys_info->sib1)); + for (int j = 0; j < sys_info->sib1_length; j++) + sys_info->sib1[j] = msg->cell_to_modify[i].sys_info->sib1[j]; + } + } + return cp; +} + +/* ==================================== + * F1AP gNB-CU Configuration Update + * ==================================== */ + +/** + * @brief F1 gNB-CU Configuration Update encoding (9.2.1.10 of 3GPP TS 38.473) + */ +F1AP_F1AP_PDU_t *encode_f1ap_cu_configuration_update(const f1ap_gnb_cu_configuration_update_t *msg) +{ + F1AP_F1AP_PDU_t *pdu = calloc_or_fail(1, sizeof(*pdu)); + /* Create + 0. Message Type */ + pdu->present = F1AP_F1AP_PDU_PR_initiatingMessage; + asn1cCalloc(pdu->choice.initiatingMessage, initMsg); + initMsg->procedureCode = F1AP_ProcedureCode_id_gNBCUConfigurationUpdate; + initMsg->criticality = F1AP_Criticality_reject; + initMsg->value.present = F1AP_InitiatingMessage__value_PR_GNBCUConfigurationUpdate; + F1AP_GNBCUConfigurationUpdate_t *cfgUpdate = &pdu->choice.initiatingMessage->value.choice.GNBCUConfigurationUpdate; + /* mandatory + c1. Transaction ID (integer value) */ + asn1cSequenceAdd(cfgUpdate->protocolIEs.list, F1AP_GNBCUConfigurationUpdateIEs_t, ieC1); + ieC1->id = F1AP_ProtocolIE_ID_id_TransactionID; + ieC1->criticality = F1AP_Criticality_reject; + ieC1->value.present = F1AP_GNBCUConfigurationUpdateIEs__value_PR_TransactionID; + ieC1->value.choice.TransactionID = msg->transaction_id; + /* optional + c2. Cells_to_be_Activated_List (O) */ + for (int i = 0; i < msg->num_cells_to_activate; i++) { + asn1cSequenceAdd(cfgUpdate->protocolIEs.list, F1AP_GNBCUConfigurationUpdateIEs_t, ieC3); + ieC3->id = F1AP_ProtocolIE_ID_id_Cells_to_be_Activated_List; + ieC3->criticality = F1AP_Criticality_reject; + ieC3->value.present = F1AP_GNBCUConfigurationUpdateIEs__value_PR_Cells_to_be_Activated_List; + asn1cSequenceAdd(ieC3->value.choice.Cells_to_be_Activated_List.list, + F1AP_Cells_to_be_Activated_List_ItemIEs_t, + cells_to_be_activated_ies); + encode_cells_to_activate(&msg->cells_to_activate[i], cells_to_be_activated_ies); + } + return pdu; +} + +/** + * @brief F1 gNB-CU Configuration Update decoding (9.2.1.10 of 3GPP TS 38.473) + */ +bool decode_f1ap_cu_configuration_update(const F1AP_F1AP_PDU_t *pdu, f1ap_gnb_cu_configuration_update_t *out) +{ + /* Check presence of message type */ + _F1_EQ_CHECK_INT(pdu->present, F1AP_F1AP_PDU_PR_initiatingMessage); + AssertError(pdu->choice.initiatingMessage != NULL, return false, "pdu->choice.initiatingMessage is NULL"); + _F1_EQ_CHECK_LONG(pdu->choice.initiatingMessage->procedureCode, F1AP_ProcedureCode_id_gNBCUConfigurationUpdate); + _F1_EQ_CHECK_INT(pdu->choice.initiatingMessage->value.present, F1AP_InitiatingMessage__value_PR_GNBCUConfigurationUpdate); + /* Check presence of mandatory IEs */ + F1AP_GNBCUConfigurationUpdate_t *in = &pdu->choice.initiatingMessage->value.choice.GNBCUConfigurationUpdate; + F1AP_GNBCUConfigurationUpdateIEs_t *ie; + F1AP_LIB_FIND_IE(F1AP_GNBCUConfigurationUpdateIEs_t, ie, in, F1AP_ProtocolIE_ID_id_TransactionID, true); + /* Loop over all IEs */ + for (int i = 0; i < in->protocolIEs.list.count; i++) { + ie = in->protocolIEs.list.array[i]; + switch (ie->id) { + case F1AP_ProtocolIE_ID_id_TransactionID: + _F1_EQ_CHECK_INT(ie->value.present, F1AP_GNBCUConfigurationUpdateIEs__value_PR_TransactionID); + AssertError(ie->value.choice.TransactionID != -1, return false, "ie->value.choice.TransactionID is -1"); + out->transaction_id = ie->value.choice.TransactionID; + break; + case F1AP_ProtocolIE_ID_id_Cells_to_be_Activated_List: { + /* Cells to be Activated List (O) */ + _F1_EQ_CHECK_INT(ie->value.present, F1AP_GNBCUConfigurationUpdateIEs__value_PR_Cells_to_be_Activated_List); + /* Cells to be Activated List Item (count >= 1) */ + F1AP_Cells_to_be_Activated_List_t *Cells_to_be_Activated_List = &ie->value.choice.Cells_to_be_Activated_List; + out->num_cells_to_activate = Cells_to_be_Activated_List->list.count; + AssertError(out->num_cells_to_activate > 0, return false, "At least 1 cell to activate must be present"); + for (int i = 0; i < out->num_cells_to_activate; i++) { + if (!decode_cells_to_activate(&out->cells_to_activate[i], + (F1AP_Cells_to_be_Activated_List_ItemIEs_t *)Cells_to_be_Activated_List->list.array[i])) + return false; + } + break; + } + default: + AssertError(1 == 0, return false, "F1AP_ProtocolIE_ID_id %ld unknown\n", ie->id); + break; + } + } + return true; +} + +void free_f1ap_cu_configuration_update(const f1ap_gnb_cu_configuration_update_t *msg) +{ + for (int i = 0; i < msg->num_cells_to_activate; i++) + for (int j = 0; j < msg->cells_to_activate[j].num_SI; j++) + free(msg->cells_to_activate[i].SI_msg[j].SI_container); +} + +/** + * @brief F1 gNB-CU Configuration Update check + */ +bool eq_f1ap_cu_configuration_update(const f1ap_gnb_cu_configuration_update_t *a, const f1ap_gnb_cu_configuration_update_t *b) +{ + _F1_EQ_CHECK_LONG(a->transaction_id, b->transaction_id); + /* to activate */ + _F1_EQ_CHECK_INT(a->num_cells_to_activate, b->num_cells_to_activate); + for (int i = 0; i < a->num_cells_to_activate; i++) { + _F1_EQ_CHECK_LONG(a->cells_to_activate[i].nr_cellid, b->cells_to_activate[i].nr_cellid); + _F1_EQ_CHECK_INT(a->cells_to_activate[i].nrpci, b->cells_to_activate[i].nrpci); + if (!eq_f1ap_plmn(&a->cells_to_activate[i].plmn, &b->cells_to_activate[i].plmn)) + return false; + _F1_EQ_CHECK_INT(a->cells_to_activate[i].num_SI, b->cells_to_activate[i].num_SI); + for (int s = 0; s < a->cells_to_activate[i].num_SI; s++) { + _F1_EQ_CHECK_INT(*a->cells_to_activate[i].SI_msg[s].SI_container, *a->cells_to_activate[i].SI_msg[s].SI_container); + _F1_EQ_CHECK_INT(a->cells_to_activate[i].SI_msg[s].SI_container_length, a->cells_to_activate[i].SI_msg[s].SI_container_length); + _F1_EQ_CHECK_INT(a->cells_to_activate[i].SI_msg[s].SI_type, a->cells_to_activate[i].SI_msg[s].SI_type); + } + } + return true; +} + +/** + * @brief F1 gNB-CU Configuration Update deep copy + */ +f1ap_gnb_cu_configuration_update_t cp_f1ap_cu_configuration_update(const f1ap_gnb_cu_configuration_update_t *msg) +{ + f1ap_gnb_cu_configuration_update_t cp = {0}; + /* transaction_id */ + cp.transaction_id = msg->transaction_id; + cp.num_cells_to_activate = msg->num_cells_to_activate; + for (int i = 0; i < cp.num_cells_to_activate; i++) { + cp.cells_to_activate[i] = msg->cells_to_activate[i]; + for (int s = 0; s < cp.cells_to_activate[i].num_SI; s++) { + cp.cells_to_activate[i].SI_msg[s] = msg->cells_to_activate[i].SI_msg[s]; + f1ap_sib_msg_t *SI_msg = &cp.cells_to_activate[i].SI_msg[s]; + SI_msg->SI_container = calloc_or_fail(SI_msg->SI_container_length, sizeof(*SI_msg->SI_container)); + for (int j = 0; j < SI_msg->SI_container_length; j++) + SI_msg->SI_container[j] = msg->cells_to_activate[i].SI_msg[s].SI_container[j]; + } + } + return cp; +} + +/* ==================================== + * F1AP gNB-CU Configuration Ack + * ==================================== */ + +/** + * @brief F1 gNB-CU Configuration Update Acknowledge message encoding (9.2.1.11 of 3GPP TS 38.473) + * gNB-DU → gNB-CU + */ +F1AP_F1AP_PDU_t *encode_f1ap_cu_configuration_update_acknowledge(const f1ap_gnb_cu_configuration_update_acknowledge_t *msg) +{ + F1AP_F1AP_PDU_t *pdu = calloc_or_fail(1, sizeof(*pdu)); + /* Create */ + /* 0. pdu Type */ + pdu->present = F1AP_F1AP_PDU_PR_successfulOutcome; + asn1cCalloc(pdu->choice.successfulOutcome, tmp); + tmp->procedureCode = F1AP_ProcedureCode_id_gNBCUConfigurationUpdate; + tmp->criticality = F1AP_Criticality_reject; + tmp->value.present = F1AP_SuccessfulOutcome__value_PR_GNBCUConfigurationUpdateAcknowledge; + F1AP_GNBCUConfigurationUpdateAcknowledge_t *out = &tmp->value.choice.GNBCUConfigurationUpdateAcknowledge; + // Transaction ID (M) + asn1cSequenceAdd(out->protocolIEs.list, F1AP_GNBCUConfigurationUpdateAcknowledgeIEs_t, ie1); + ie1->id = F1AP_ProtocolIE_ID_id_TransactionID; + ie1->criticality = F1AP_Criticality_reject; + ie1->value.present = F1AP_GNBCUConfigurationUpdateAcknowledgeIEs__value_PR_TransactionID; + ie1->value.choice.TransactionID = msg->transaction_id; + // Cells Failed to be Activated List (0..1) + if (msg->num_cells_failed_to_be_activated > 0) { + asn1cSequenceAdd(out->protocolIEs.list, F1AP_GNBCUConfigurationUpdateAcknowledgeIEs_t, ie2); + ie2->id = F1AP_ProtocolIE_ID_id_Cells_Failed_to_be_Activated_List; + ie2->criticality = F1AP_Criticality_reject; + ie2->value.present = F1AP_GNBCUConfigurationUpdateAcknowledgeIEs__value_PR_Cells_Failed_to_be_Activated_List; + F1AP_Cells_Failed_to_be_Activated_List_t *failedCellsList = &ie2->value.choice.Cells_Failed_to_be_Activated_List; + for (int i = 0; i < msg->num_cells_failed_to_be_activated; i++) { + asn1cSequenceAdd(failedCellsList->list, F1AP_Cells_Failed_to_be_Activated_List_ItemIEs_t, failedCellIE); + failedCellIE->id = F1AP_ProtocolIE_ID_id_Cells_Failed_to_be_Activated_List_Item; + failedCellIE->criticality = F1AP_Criticality_reject; + failedCellIE->value.present = F1AP_Cells_Failed_to_be_Activated_List_ItemIEs__value_PR_Cells_Failed_to_be_Activated_List_Item; + F1AP_Cells_Failed_to_be_Activated_List_Item_t *p1 = &failedCellIE->value.choice.Cells_Failed_to_be_Activated_List_Item; + // Cause (M) + p1->cause.present = F1AP_Cause_PR_radioNetwork; + p1->cause.choice.radioNetwork = msg->cells_failed_to_be_activated[i].cause; + // NR CGI (M) + const f1ap_plmn_t *plmn = &msg->cells_failed_to_be_activated[i].plmn; + MCC_MNC_TO_PLMNID(plmn->mcc, plmn->mnc, plmn->mnc_digit_length, &(p1->nRCGI.pLMN_Identity)); + printf("plmn->mcc %d %d %d %ld \n", + p1->nRCGI.pLMN_Identity.buf[0], p1->nRCGI.pLMN_Identity.buf[1], p1->nRCGI.pLMN_Identity.buf[2], p1->nRCGI.pLMN_Identity.size); + NR_CELL_ID_TO_BIT_STRING(msg->cells_failed_to_be_activated[i].nr_cellid, &(p1->nRCGI.nRCellIdentity)); + } + } + return pdu; +} + +/** + * @brief F1 gNB-CU Configuration Update Acknowledge decoding (9.2.1.11 of 3GPP TS 38.473) + */ +bool decode_f1ap_cu_configuration_update_acknowledge(const F1AP_F1AP_PDU_t *pdu, + f1ap_gnb_cu_configuration_update_acknowledge_t *out) +{ + /* Message type */ + _F1_EQ_CHECK_INT(pdu->present, F1AP_F1AP_PDU_PR_successfulOutcome); + AssertError(pdu->choice.successfulOutcome != NULL, return false, "pdu->choice.successfulOutcome is NULL"); + _F1_EQ_CHECK_LONG(pdu->choice.successfulOutcome->procedureCode, F1AP_ProcedureCode_id_gNBCUConfigurationUpdate); + _F1_EQ_CHECK_INT(pdu->choice.successfulOutcome->value.present, + F1AP_SuccessfulOutcome__value_PR_GNBCUConfigurationUpdateAcknowledge); + /* payload */ + F1AP_GNBCUConfigurationUpdateAcknowledge_t *in = &pdu->choice.successfulOutcome->value.choice.GNBCUConfigurationUpdateAcknowledge; + F1AP_GNBCUConfigurationUpdateAcknowledgeIEs_t *ie; + /* Check mandatory IEs */ + F1AP_LIB_FIND_IE(F1AP_GNBCUConfigurationUpdateAcknowledgeIEs_t, ie, in, F1AP_ProtocolIE_ID_id_TransactionID, true); + /* Loop over all IEs */ + for (int i = 0; i < in->protocolIEs.list.count; i++) { + ie = in->protocolIEs.list.array[i]; + switch (ie->id) { + case F1AP_ProtocolIE_ID_id_TransactionID: + _F1_EQ_CHECK_INT(ie->value.present, F1AP_GNBCUConfigurationUpdateAcknowledgeIEs__value_PR_TransactionID); + AssertError(ie->value.choice.TransactionID != -1, return false, "ie->value.choice.TransactionID is -1"); + out->transaction_id = ie->value.choice.TransactionID; + break; + case F1AP_ProtocolIE_ID_id_Cells_Failed_to_be_Activated_List: { + /* Decode Cells Failed to be Activated List */ + _F1_EQ_CHECK_INT(ie->value.present, + F1AP_GNBCUConfigurationUpdateAcknowledgeIEs__value_PR_Cells_Failed_to_be_Activated_List); + F1AP_Cells_Failed_to_be_Activated_List_t *cell_fail_list = &ie->value.choice.Cells_Failed_to_be_Activated_List; + out->num_cells_failed_to_be_activated = cell_fail_list->list.count; + for (int j = 0; j < out->num_cells_failed_to_be_activated; j++) { + const F1AP_Cells_Failed_to_be_Activated_List_ItemIEs_t *itemIE = + (F1AP_Cells_Failed_to_be_Activated_List_ItemIEs_t *)cell_fail_list->list.array[j]; + const F1AP_Cells_Failed_to_be_Activated_List_Item_t *item = &itemIE->value.choice.Cells_Failed_to_be_Activated_List_Item; + // NR CGI (M) + f1ap_plmn_t *plmn = &out->cells_failed_to_be_activated[j].plmn; + TBCD_TO_MCC_MNC(&(item->nRCGI.pLMN_Identity), plmn->mcc, plmn->mnc, plmn->mnc_digit_length); + BIT_STRING_TO_NR_CELL_IDENTITY(&item->nRCGI.nRCellIdentity, out->cells_failed_to_be_activated[j].nr_cellid); + // Cause (M) + switch (item->cause.present) { + case F1AP_Cause_PR_radioNetwork: + out->cells_failed_to_be_activated[j].cause = item->cause.choice.radioNetwork; + break; + case F1AP_Cause_PR_transport: + out->cells_failed_to_be_activated[j].cause = item->cause.choice.transport; + break; + case F1AP_Cause_PR_protocol: + out->cells_failed_to_be_activated[j].cause = item->cause.choice.protocol; + break; + case F1AP_Cause_PR_misc: + out->cells_failed_to_be_activated[j].cause = item->cause.choice.misc; + break; + default: + AssertError(1 == 0, return false, "Unknown cause type %d\n", item->cause.present); + break; + } + } + break; + } + default: + AssertError(1 == 0, return false, "F1AP_ProtocolIE_ID_id %ld unknown\n", ie->id); + break; + } + } + return true; +} + +/** + * @brief F1 gNB-CU Configuration Update Acknowledge check + */ +bool eq_f1ap_cu_configuration_update_acknowledge(const f1ap_gnb_cu_configuration_update_acknowledge_t *a, + const f1ap_gnb_cu_configuration_update_acknowledge_t *b) +{ + // Transaction ID + _F1_EQ_CHECK_LONG(a->transaction_id, b->transaction_id); + // number of cells failed to be activated + _F1_EQ_CHECK_INT(a->num_cells_failed_to_be_activated, b->num_cells_failed_to_be_activated); + for (int i = 0; i < a->num_cells_failed_to_be_activated; i++) { + if (!eq_f1ap_plmn(&a->cells_failed_to_be_activated[i].plmn, &b->cells_failed_to_be_activated[i].plmn)) + return false; + _F1_EQ_CHECK_LONG(a->cells_failed_to_be_activated[i].nr_cellid, b->cells_failed_to_be_activated[i].nr_cellid); + _F1_EQ_CHECK_INT(a->cells_failed_to_be_activated[i].cause, b->cells_failed_to_be_activated[i].cause); + } + // TNL Associations to setup + _F1_EQ_CHECK_INT(a->noofTNLAssociations_to_setup, b->noofTNLAssociations_to_setup); + for (int i = 0; i < a->noofTNLAssociations_to_setup; i++) { + // Explicit comparison of TNL Association fields + _F1_EQ_CHECK_INT(a->tnlAssociations_to_setup[i].tl_address, b->tnlAssociations_to_setup[i].tl_address); + _F1_EQ_CHECK_INT(a->tnlAssociations_to_setup[i].port, b->tnlAssociations_to_setup[i].port); + } + // TNL Associations failed to setup + _F1_EQ_CHECK_INT(a->noofTNLAssociations_failed, b->noofTNLAssociations_failed); + for (int i = 0; i < a->noofTNLAssociations_failed; i++) { + // Explicit comparison of TNL Association fields + _F1_EQ_CHECK_INT(a->tnlAssociations_failed[i].tl_address, b->tnlAssociations_failed[i].tl_address); + _F1_EQ_CHECK_INT(a->tnlAssociations_failed[i].port, b->tnlAssociations_failed[i].port); + } + // Dedicated SI Delivery Needed UE List + _F1_EQ_CHECK_INT(a->noofDedicatedSIDeliveryNeededUEs, b->noofDedicatedSIDeliveryNeededUEs); + for (int i = 0; i < a->noofDedicatedSIDeliveryNeededUEs; i++) { + _F1_EQ_CHECK_INT(a->dedicatedSIDeliveryNeededUEs[i].gNB_CU_ue_id, b->dedicatedSIDeliveryNeededUEs[i].gNB_CU_ue_id); + if (!eq_f1ap_plmn(&a->dedicatedSIDeliveryNeededUEs[i].ue_plmn, &b->dedicatedSIDeliveryNeededUEs[i].ue_plmn)) + return false; + _F1_EQ_CHECK_LONG(a->dedicatedSIDeliveryNeededUEs[i].ue_nr_cellid, b->dedicatedSIDeliveryNeededUEs[i].ue_nr_cellid); + } + return true; +} + +/** + * @brief F1 gNB-CU Configuration Update Acknowledge deep copy + */ +f1ap_gnb_cu_configuration_update_acknowledge_t cp_f1ap_cu_configuration_update_acknowledge( + const f1ap_gnb_cu_configuration_update_acknowledge_t *msg) +{ + f1ap_gnb_cu_configuration_update_acknowledge_t cp = {0}; + // Transaction ID + cp.transaction_id = msg->transaction_id; + // number of cells failed to be activated + cp.num_cells_failed_to_be_activated = msg->num_cells_failed_to_be_activated; + for (int i = 0; i < cp.num_cells_failed_to_be_activated; i++) + cp.cells_failed_to_be_activated[i] = msg->cells_failed_to_be_activated[i]; + // TNL Associations to setup + cp.noofTNLAssociations_to_setup = msg->noofTNLAssociations_to_setup; + for (int i = 0; i < cp.noofTNLAssociations_to_setup; i++) + cp.tnlAssociations_to_setup[i] = msg->tnlAssociations_to_setup[i]; + // TNL Associations failed to setup + cp.noofTNLAssociations_failed = msg->noofTNLAssociations_failed; + for (int i = 0; i < cp.noofTNLAssociations_failed; i++) + cp.tnlAssociations_failed[i] = msg->tnlAssociations_failed[i]; + // Dedicated SI Delivery Needed UE List + cp.noofDedicatedSIDeliveryNeededUEs = msg->noofDedicatedSIDeliveryNeededUEs; + for (int i = 0; i < cp.noofDedicatedSIDeliveryNeededUEs; i++) + cp.dedicatedSIDeliveryNeededUEs[i] = msg->dedicatedSIDeliveryNeededUEs[i]; + return cp; +} + +/* ================================== + * F1AP gNB-DU Configuration Ack + * ================================== */ + +/** + * @brief F1 gNB-DU Configuration Update Acknowledge message encoding (9.2.1.8 of 3GPP TS 38.473) + */ +F1AP_F1AP_PDU_t *encode_f1ap_du_configuration_update_acknowledge(const f1ap_gnb_du_configuration_update_acknowledge_t *msg) +{ + F1AP_F1AP_PDU_t *pdu = calloc_or_fail(1, sizeof(*pdu)); + /* Create */ + /* 0. Message */ + pdu->present = F1AP_F1AP_PDU_PR_successfulOutcome; + asn1cCalloc(pdu->choice.successfulOutcome, succOut); + succOut->procedureCode = F1AP_ProcedureCode_id_gNBDUConfigurationUpdate; + succOut->criticality = F1AP_Criticality_reject; + succOut->value.present = F1AP_SuccessfulOutcome__value_PR_GNBDUConfigurationUpdateAcknowledge; + F1AP_GNBDUConfigurationUpdateAcknowledge_t *ack = &succOut->value.choice.GNBDUConfigurationUpdateAcknowledge; + /* Mandatory */ + /* Transaction Id */ + asn1cSequenceAdd(ack->protocolIEs.list, F1AP_GNBDUConfigurationUpdateAcknowledgeIEs_t, ie1); + ie1->id = F1AP_ProtocolIE_ID_id_TransactionID; + ie1->criticality = F1AP_Criticality_reject; + ie1->value.present = F1AP_GNBDUConfigurationUpdateAcknowledgeIEs__value_PR_TransactionID; + ie1->value.choice.TransactionID = msg->transaction_id; + // Cells to be Activated List (O) + for (int i = 0; i < msg->num_cells_to_activate; i++) { + asn1cSequenceAdd(ack->protocolIEs.list, F1AP_GNBDUConfigurationUpdateAcknowledgeIEs_t, ie3); + ie3->id = F1AP_ProtocolIE_ID_id_Cells_to_be_Activated_List; + ie3->criticality = F1AP_Criticality_reject; + ie3->value.present = F1AP_GNBDUConfigurationUpdateAcknowledgeIEs__value_PR_Cells_to_be_Activated_List; + asn1cSequenceAdd(ie3->value.choice.Cells_to_be_Activated_List.list, + F1AP_Cells_to_be_Activated_List_ItemIEs_t, + cells_to_be_activated_ies); + encode_cells_to_activate(&msg->cells_to_activate[i], cells_to_be_activated_ies); + } + return pdu; +} + +/** + * @brief F1 gNB-DU Configuration Update Acknowledge decoding + */ +bool decode_f1ap_du_configuration_update_acknowledge(const F1AP_F1AP_PDU_t *pdu, + f1ap_gnb_du_configuration_update_acknowledge_t *out) +{ + /* message type */ + _F1_EQ_CHECK_INT(pdu->present, F1AP_F1AP_PDU_PR_successfulOutcome); + AssertError(pdu->choice.successfulOutcome != NULL, return false, "pdu->choice.successfulOutcome is NULL"); + _F1_EQ_CHECK_LONG(pdu->choice.successfulOutcome->procedureCode, F1AP_ProcedureCode_id_gNBDUConfigurationUpdate); + _F1_EQ_CHECK_INT(pdu->choice.successfulOutcome->value.present, + F1AP_SuccessfulOutcome__value_PR_GNBDUConfigurationUpdateAcknowledge); + F1AP_GNBDUConfigurationUpdateAcknowledge_t *in = &pdu->choice.successfulOutcome->value.choice.GNBDUConfigurationUpdateAcknowledge; + F1AP_GNBDUConfigurationUpdateAcknowledgeIEs_t *ie; + /* Check mandatory IEs */ + F1AP_LIB_FIND_IE(F1AP_GNBDUConfigurationUpdateAcknowledgeIEs_t, ie, in, F1AP_ProtocolIE_ID_id_TransactionID, true); + /* Loop over all IEs */ + for (int i = 0; i < in->protocolIEs.list.count; i++) { + ie = in->protocolIEs.list.array[i]; + switch (ie->id) { + case F1AP_ProtocolIE_ID_id_TransactionID: + _F1_EQ_CHECK_INT(ie->value.present, F1AP_GNBDUConfigurationUpdateAcknowledgeIEs__value_PR_TransactionID); + AssertError(ie->value.choice.TransactionID != -1, return false, "ie->value.choice.TransactionID is -1"); + out->transaction_id = ie->value.choice.TransactionID; + break; + case F1AP_ProtocolIE_ID_id_Cells_to_be_Activated_List: { + /* Decode Cells Failed to be Activated List */ + _F1_EQ_CHECK_INT(ie->value.present, F1AP_GNBDUConfigurationUpdateAcknowledgeIEs__value_PR_Cells_to_be_Activated_List); + F1AP_Cells_to_be_Activated_List_t *list = &ie->value.choice.Cells_to_be_Activated_List; + out->num_cells_to_activate = list->list.count; + for (int j = 0; j < out->num_cells_to_activate; j++) { + const F1AP_Cells_to_be_Activated_List_ItemIEs_t *itemIE = + (F1AP_Cells_to_be_Activated_List_ItemIEs_t *)list->list.array[j]; + decode_cells_to_activate(&out->cells_to_activate[0], itemIE); + } + break; + } + default: + AssertError(1 == 0, return false, "F1AP_ProtocolIE_ID_id %ld unknown\n", ie->id); + break; + } + } + return true; +} + +/** + * @brief F1 gNB-DU Configuration Update Acknowledge equality check + */ +bool eq_f1ap_du_configuration_update_acknowledge(const f1ap_gnb_du_configuration_update_acknowledge_t *a, + const f1ap_gnb_du_configuration_update_acknowledge_t *b) +{ + // Transaction ID + _F1_EQ_CHECK_LONG(a->transaction_id, b->transaction_id); + // number of cells to activate + _F1_EQ_CHECK_INT(a->num_cells_to_activate, b->num_cells_to_activate); + // loop over cells to activate + for (int i = 0; i < a->num_cells_to_activate; i++) { + _F1_EQ_CHECK_LONG(a->cells_to_activate[i].nr_cellid, b->cells_to_activate[i].nr_cellid); + _F1_EQ_CHECK_INT(a->cells_to_activate[i].nrpci, b->cells_to_activate[i].nrpci); + if (!eq_f1ap_plmn(&a->cells_to_activate[i].plmn, &b->cells_to_activate[i].plmn)) + return false; + _F1_EQ_CHECK_INT(a->cells_to_activate[i].num_SI, b->cells_to_activate[i].num_SI); + for (int s = 0; s < a->cells_to_activate[i].num_SI; s++) { + _F1_EQ_CHECK_INT(*a->cells_to_activate[i].SI_msg[s].SI_container, *b->cells_to_activate[i].SI_msg[s].SI_container); + _F1_EQ_CHECK_INT(a->cells_to_activate[i].SI_msg[s].SI_container_length, + b->cells_to_activate[i].SI_msg[s].SI_container_length); + _F1_EQ_CHECK_INT(a->cells_to_activate[i].SI_msg[s].SI_type, b->cells_to_activate[i].SI_msg[s].SI_type); + } + } + return true; +} + +/** + * @brief F1 gNB-DU Configuration Update Acknowledge deep copy + */ +f1ap_gnb_du_configuration_update_acknowledge_t cp_f1ap_du_configuration_update_acknowledge( + const f1ap_gnb_du_configuration_update_acknowledge_t *msg) +{ + f1ap_gnb_du_configuration_update_acknowledge_t cp = {0}; + // Transaction ID + cp.transaction_id = msg->transaction_id; + // number of cells to activate + cp.num_cells_to_activate = msg->num_cells_to_activate; + // Loop through cells to activate + for (int i = 0; i < cp.num_cells_to_activate; i++) { + cp.cells_to_activate[i] = msg->cells_to_activate[i]; + for (int s = 0; s < cp.cells_to_activate[i].num_SI; s++) { + cp.cells_to_activate[i].SI_msg[s].SI_container = calloc_or_fail(1, sizeof(*cp.cells_to_activate[i].SI_msg[s].SI_container)); + *cp.cells_to_activate[i].SI_msg[s].SI_container = *msg->cells_to_activate[i].SI_msg[s].SI_container; + } + } + return cp; +} + +/** + * @brief gNB-DU Configuration Update Acknowledge memory management + */ +void free_f1ap_du_configuration_update_acknowledge(const f1ap_gnb_du_configuration_update_acknowledge_t *msg) +{ + // SI_container + for (int i = 0; i < msg->num_cells_to_activate; i++) { + for (int j = 0; j < msg->cells_to_activate[i].num_SI; j++) { + if (msg->cells_to_activate[i].SI_msg[j].SI_container) { + free(msg->cells_to_activate[i].SI_msg[j].SI_container); + } + } + } +} diff --git a/openair2/F1AP/lib/f1ap_interface_management.h b/openair2/F1AP/lib/f1ap_interface_management.h new file mode 100644 index 0000000000..bdceee9a61 --- /dev/null +++ b/openair2/F1AP/lib/f1ap_interface_management.h @@ -0,0 +1,82 @@ +/* + * 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 F1AP_INTERFACE_MANAGEMENT_H_ +#define F1AP_INTERFACE_MANAGEMENT_H_ + +#include +#include "f1ap_messages_types.h" + +struct F1AP_F1AP_PDU; + +struct F1AP_F1AP_PDU *encode_f1ap_setup_request(const f1ap_setup_req_t *msg); +bool decode_f1ap_setup_request(const struct F1AP_F1AP_PDU *pdu, f1ap_setup_req_t *out); +f1ap_setup_req_t cp_f1ap_setup_request(const f1ap_setup_req_t *msg); +bool eq_f1ap_setup_request(const f1ap_setup_req_t *a, const f1ap_setup_req_t *b); +void free_f1ap_setup_request(const f1ap_setup_req_t *msg); + +/* F1 Setup Response */ +struct F1AP_F1AP_PDU *encode_f1ap_setup_response(const f1ap_setup_resp_t *msg); +bool decode_f1ap_setup_response(const struct F1AP_F1AP_PDU *pdu, f1ap_setup_resp_t *out); +void free_f1ap_setup_response(const f1ap_setup_resp_t *msg); +f1ap_setup_resp_t cp_f1ap_setup_response(const f1ap_setup_resp_t *msg); +bool eq_f1ap_setup_response(const f1ap_setup_resp_t *a, const f1ap_setup_resp_t *b); + +/* F1 Setup Failure */ +struct F1AP_F1AP_PDU *encode_f1ap_setup_failure(const f1ap_setup_failure_t *msg); +bool decode_f1ap_setup_failure(const struct F1AP_F1AP_PDU *pdu, f1ap_setup_failure_t *out); +bool eq_f1ap_setup_failure(const f1ap_setup_failure_t *a, const f1ap_setup_failure_t *b); +f1ap_setup_failure_t cp_f1ap_setup_failure(const f1ap_setup_failure_t *msg); + +/* F1 gNB-DU Configuration Update */ +struct F1AP_F1AP_PDU *encode_f1ap_du_configuration_update(const f1ap_gnb_du_configuration_update_t *msg); +bool decode_f1ap_du_configuration_update(const struct F1AP_F1AP_PDU *pdu, f1ap_gnb_du_configuration_update_t *out); +bool eq_f1ap_du_configuration_update(const f1ap_gnb_du_configuration_update_t *a, const f1ap_gnb_du_configuration_update_t *b); +f1ap_gnb_du_configuration_update_t cp_f1ap_du_configuration_update(const f1ap_gnb_du_configuration_update_t *msg); +void free_f1ap_du_configuration_update(const f1ap_gnb_du_configuration_update_t *msg); + +/* F1 gNB-CU Configuration Update */ +struct F1AP_F1AP_PDU *encode_f1ap_cu_configuration_update(const f1ap_gnb_cu_configuration_update_t *msg); +bool decode_f1ap_cu_configuration_update(const struct F1AP_F1AP_PDU *pdu, f1ap_gnb_cu_configuration_update_t *out); +bool eq_f1ap_cu_configuration_update(const f1ap_gnb_cu_configuration_update_t *a, const f1ap_gnb_cu_configuration_update_t *b); +f1ap_gnb_cu_configuration_update_t cp_f1ap_cu_configuration_update(const f1ap_gnb_cu_configuration_update_t *msg); +void free_f1ap_cu_configuration_update(const f1ap_gnb_cu_configuration_update_t *msg); + +/* F1 gNB-CU Configuration Update Acknowledge */ +struct F1AP_F1AP_PDU *encode_f1ap_cu_configuration_update_acknowledge(const f1ap_gnb_cu_configuration_update_acknowledge_t *msg); +bool decode_f1ap_cu_configuration_update_acknowledge(const struct F1AP_F1AP_PDU *pdu, + f1ap_gnb_cu_configuration_update_acknowledge_t *out); +bool eq_f1ap_cu_configuration_update_acknowledge(const f1ap_gnb_cu_configuration_update_acknowledge_t *a, + const f1ap_gnb_cu_configuration_update_acknowledge_t *b); +f1ap_gnb_cu_configuration_update_acknowledge_t cp_f1ap_cu_configuration_update_acknowledge( + const f1ap_gnb_cu_configuration_update_acknowledge_t *msg); + +/* F1 gNB-DU Configuration Update Acknowledge */ +struct F1AP_F1AP_PDU *encode_f1ap_du_configuration_update_acknowledge(const f1ap_gnb_du_configuration_update_acknowledge_t *msg); +bool decode_f1ap_du_configuration_update_acknowledge(const struct F1AP_F1AP_PDU *pdu, + f1ap_gnb_du_configuration_update_acknowledge_t *out); +bool eq_f1ap_du_configuration_update_acknowledge(const f1ap_gnb_du_configuration_update_acknowledge_t *a, + const f1ap_gnb_du_configuration_update_acknowledge_t *b); +f1ap_gnb_du_configuration_update_acknowledge_t cp_f1ap_du_configuration_update_acknowledge( + const f1ap_gnb_du_configuration_update_acknowledge_t *msg); +void free_f1ap_du_configuration_update_acknowledge(const f1ap_gnb_du_configuration_update_acknowledge_t *msg); + +#endif /* F1AP_INTERFACE_MANAGEMENT_H_ */ diff --git a/openair2/F1AP/lib/f1ap_lib_common.c b/openair2/F1AP/lib/f1ap_lib_common.c new file mode 100644 index 0000000000..edf48f426c --- /dev/null +++ b/openair2/F1AP/lib/f1ap_lib_common.c @@ -0,0 +1,117 @@ +/* + * 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 "f1ap_lib_common.h" +#include "f1ap_messages_types.h" + +#include "OCTET_STRING.h" +#include "common/utils/utils.h" +#include "common/utils/assertions.h" +#include "common/utils/utils.h" + +bool eq_f1ap_plmn(const f1ap_plmn_t *a, const f1ap_plmn_t *b) +{ + _F1_EQ_CHECK_INT(a->mcc, b->mcc); + _F1_EQ_CHECK_INT(a->mnc, b->mnc); + _F1_EQ_CHECK_INT(a->mnc_digit_length, b->mnc_digit_length); + return true; +} + +bool eq_f1ap_freq_info(const f1ap_nr_frequency_info_t *a, const f1ap_nr_frequency_info_t *b) +{ + if (a->arfcn != b->arfcn) + return false; + if (a->band != b->band) + return false; + return true; +} + +bool eq_f1ap_tx_bandwidth(const f1ap_transmission_bandwidth_t *a, const f1ap_transmission_bandwidth_t *b) +{ + if (a->nrb != b->nrb) + return false; + if (a->scs != b->scs) + return false; + return true; +} + +bool eq_f1ap_cell_info(const f1ap_served_cell_info_t *a, const f1ap_served_cell_info_t *b) +{ + if (a->nr_cellid != b->nr_cellid) + return false; + if (a->nr_pci != b->nr_pci) + return false; + if (*a->tac != *b->tac) + return false; + if (a->mode != b->mode) + return false; + if (a->mode == F1AP_MODE_TDD) { + /* TDD */ + if (!eq_f1ap_tx_bandwidth(&a->tdd.tbw, &b->tdd.tbw)) + return false; + if (!eq_f1ap_freq_info(&a->tdd.freqinfo, &b->tdd.freqinfo)) + return false; + } else if (a->mode == F1AP_MODE_FDD) { + /* FDD */ + if (!eq_f1ap_tx_bandwidth(&a->fdd.dl_tbw, &b->fdd.dl_tbw)) + return false; + if (!eq_f1ap_freq_info(&a->fdd.dl_freqinfo, &b->fdd.dl_freqinfo)) + return false; + if (!eq_f1ap_tx_bandwidth(&a->fdd.ul_tbw, &b->fdd.ul_tbw)) + return false; + if (!eq_f1ap_freq_info(&a->fdd.ul_freqinfo, &b->fdd.ul_freqinfo)) + return false; + } + if (a->measurement_timing_config_len != b->measurement_timing_config_len) + return false; + if (*a->measurement_timing_config != *b->measurement_timing_config) + return false; + if (!eq_f1ap_plmn(&a->plmn, &b->plmn)) + return false; + return true; +} + +bool eq_f1ap_sys_info(const f1ap_gnb_du_system_info_t *a, const f1ap_gnb_du_system_info_t *b) +{ + /* MIB */ + if (a->mib_length != b->mib_length) + return false; + for (int i = 0; i < a->mib_length; i++) { + if (a->mib[i] != b->mib[i]) + return false; + } + /* SIB1 */ + if (a->sib1_length != b->sib1_length) + return false; + for (int i = 0; i < a->sib1_length; i++) { + if (a->sib1[i] != b->sib1[i]) + return false; + } + return true; +} + +uint8_t *cp_octet_string(const OCTET_STRING_t *os, int *len) +{ + uint8_t *buf = calloc_or_fail(os->size, sizeof(*buf)); + memcpy(buf, os->buf, os->size); + *len = os->size; + return buf; +} diff --git a/openair2/F1AP/lib/f1ap_lib_common.h b/openair2/F1AP/lib/f1ap_lib_common.h new file mode 100644 index 0000000000..2380a2da87 --- /dev/null +++ b/openair2/F1AP/lib/f1ap_lib_common.h @@ -0,0 +1,85 @@ +/* + * 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 F1AP_LIB_COMMON_H_ +#define F1AP_LIB_COMMON_H_ + +#include +#include +#include +#include "openair3/UTILS/conversions.h" + +#ifdef ENABLE_TESTS + #define PRINT_ERROR(...) fprintf(stderr, ##__VA_ARGS__) +#else + #define PRINT_ERROR(...) // Do nothing +#endif + +#define _F1_EQ_CHECK_GENERIC(condition, fmt, ...) \ + do { \ + if (!(condition)) { \ + PRINT_ERROR("F1 Equality Check failure: %s:%d: Condition '%s' failed: " fmt " != " fmt "\n", \ + __FILE__, \ + __LINE__, \ + #condition, \ + ##__VA_ARGS__); \ + return false; \ + } \ + } while (0) + +#define _F1_EQ_CHECK_LONG(A, B) _F1_EQ_CHECK_GENERIC(A == B, "%ld", A, B); +#define _F1_EQ_CHECK_INT(A, B) _F1_EQ_CHECK_GENERIC(A == B, "%d", A, B); +#define _F1_EQ_CHECK_STR(A, B) _F1_EQ_CHECK_GENERIC(strcmp(A, B) == 0, "'%s'", A, B); + +/* macro to look up IE. If mandatory and not found, macro will print + * descriptive debug message to stderr and force exit in calling function */ +#define F1AP_LIB_FIND_IE(IE_TYPE, ie, container, IE_ID, mandatory) \ + do { \ + ie = NULL; \ + for (IE_TYPE **ptr = container->protocolIEs.list.array; \ + ptr < &container->protocolIEs.list.array[container->protocolIEs.list.count]; \ + ptr++) { \ + if ((*ptr)->id == IE_ID) { \ + ie = *ptr; \ + break; \ + } \ + } \ + if (mandatory && ie == NULL) { \ + fprintf(stderr, "%s(): could not find element " #IE_ID " with type " #IE_TYPE "\n", __func__); \ + return false; \ + } \ + } while (0) + +struct f1ap_plmn_t; +bool eq_f1ap_plmn(const struct f1ap_plmn_t *a, const struct f1ap_plmn_t *b); +struct f1ap_served_cell_info_t; +bool eq_f1ap_cell_info(const struct f1ap_served_cell_info_t *a, const struct f1ap_served_cell_info_t *b); +struct f1ap_gnb_du_system_info_t; +bool eq_f1ap_sys_info(const struct f1ap_gnb_du_system_info_t *a, const struct f1ap_gnb_du_system_info_t *b); +struct f1ap_nr_frequency_info_t; +bool eq_f1ap_freq_info(const struct f1ap_nr_frequency_info_t *a, const struct f1ap_nr_frequency_info_t *b); +struct f1ap_transmission_bandwidth_t; +bool eq_f1ap_tx_bandwidth(const struct f1ap_transmission_bandwidth_t *a, const struct f1ap_transmission_bandwidth_t *b); + +struct OCTET_STRING; +uint8_t *cp_octet_string(const struct OCTET_STRING *os, int *len); + +#endif /* F1AP_LIB_COMMON_H_ */ diff --git a/openair2/F1AP/f1ap_du_warning_message_transmission.h b/openair2/F1AP/lib/f1ap_lib_extern.h similarity index 81% rename from openair2/F1AP/f1ap_du_warning_message_transmission.h rename to openair2/F1AP/lib/f1ap_lib_extern.h index b6bbedba2f..f95b685540 100644 --- a/openair2/F1AP/f1ap_du_warning_message_transmission.h +++ b/openair2/F1AP/lib/f1ap_lib_extern.h @@ -19,13 +19,9 @@ * contact@openairinterface.org */ -/*! \file f1ap_du_interface_management.h - * \brief f1ap interface management for DU - * \author EURECOM/NTUST - * \date 2018 - * \version 0.1 - * \company Eurecom - * \email: navid.nikaein@eurecom.fr, bing-kai.hong@eurecom.fr - * \note - * \warning - */ \ No newline at end of file +#ifndef F1AP_LIB_EXTERN_H_ +#define F1AP_LIB_EXTERN_H_ + +#include "f1ap_rrc_message_transfer.h" + +#endif /* F1AP_LIB_EXTERN_H_ */ diff --git a/openair2/F1AP/f1ap_cu_warning_message_transmission.c b/openair2/F1AP/lib/f1ap_lib_includes.h similarity index 58% rename from openair2/F1AP/f1ap_cu_warning_message_transmission.c rename to openair2/F1AP/lib/f1ap_lib_includes.h index 725bb4e1af..6ff60a4897 100644 --- a/openair2/F1AP/f1ap_cu_warning_message_transmission.c +++ b/openair2/F1AP/lib/f1ap_lib_includes.h @@ -19,13 +19,26 @@ * contact@openairinterface.org */ -/*! \file f1ap_du_interface_management.h - * \brief f1ap interface management for DU - * \author EURECOM/NTUST - * \date 2018 - * \version 0.1 - * \company Eurecom - * \email: navid.nikaein@eurecom.fr, bing-kai.hong@eurecom.fr - * \note - * \warning - */ +#ifndef F1AP_LIB_INCLUDES_H_ +#define F1AP_LIB_INCLUDES_H_ + +#include "F1AP_F1AP-PDU.h" +#include "F1AP_InitialULRRCMessageTransfer.h" +#include "F1AP_InitiatingMessage.h" +#include "F1AP_NRCellIdentity.h" +#include "F1AP_ProtocolIE-Field.h" +#include "F1AP_ServedPLMNs-Item.h" +#include "F1AP_ProtocolExtensionContainer.h" +#include "F1AP_ProtocolExtensionField.h" +#include "F1AP_ProtocolIE-Field.h" +#include "F1AP_SliceSupportItem.h" +#include "F1AP_NR-Mode-Info.h" +#include "F1AP_GNB-DU-System-Information.h" +#include "F1AP_FDD-Info.h" +#include "F1AP_TDD-Info.h" +#include "F1AP_FreqBandNrItem.h" +#include "F1AP_SuccessfulOutcome.h" +#include "F1AP_SibtypetobeupdatedListItem.h" +#include "F1AP_UnsuccessfulOutcome.h" + +#endif /* F1AP_LIB_INCLUDES_H_ */ diff --git a/openair2/F1AP/lib/f1ap_rrc_message_transfer.c b/openair2/F1AP/lib/f1ap_rrc_message_transfer.c new file mode 100644 index 0000000000..5fc9e2d622 --- /dev/null +++ b/openair2/F1AP/lib/f1ap_rrc_message_transfer.c @@ -0,0 +1,479 @@ +/* + * 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 "f1ap_rrc_message_transfer.h" + +#include "f1ap_lib_common.h" +#include "f1ap_lib_includes.h" +#include "f1ap_messages_types.h" + +#include "common/utils/assertions.h" +#include "openair3/UTILS/conversions.h" +#include "common/utils/oai_asn1.h" +#include "common/utils/utils.h" + +/* ==================================== + * F1AP Initial UL RRC Message Transfer + * ==================================== */ + +/** + * @brief Initial UL RRC Message Transfer encoding + */ +F1AP_F1AP_PDU_t *encode_initial_ul_rrc_message_transfer(const f1ap_initial_ul_rrc_message_t *msg) +{ + F1AP_F1AP_PDU_t *pdu = calloc_or_fail(1, sizeof(*pdu)); + + /* 0. Message Type */ + pdu->present = F1AP_F1AP_PDU_PR_initiatingMessage; + asn1cCalloc(pdu->choice.initiatingMessage, tmp); + tmp->procedureCode = F1AP_ProcedureCode_id_InitialULRRCMessageTransfer; + tmp->criticality = F1AP_Criticality_ignore; + tmp->value.present = F1AP_InitiatingMessage__value_PR_InitialULRRCMessageTransfer; + F1AP_InitialULRRCMessageTransfer_t *out = &tmp->value.choice.InitialULRRCMessageTransfer; + + /* mandatory */ + /* c1. GNB_DU_UE_F1AP_ID */ + asn1cSequenceAdd(out->protocolIEs.list, F1AP_InitialULRRCMessageTransferIEs_t, ie1); + ie1->id = F1AP_ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID; + ie1->criticality = F1AP_Criticality_reject; + ie1->value.present = F1AP_InitialULRRCMessageTransferIEs__value_PR_GNB_DU_UE_F1AP_ID; + ie1->value.choice.GNB_DU_UE_F1AP_ID = msg->gNB_DU_ue_id; + + /* mandatory */ + /* c2. NRCGI */ + asn1cSequenceAdd(out->protocolIEs.list, F1AP_InitialULRRCMessageTransferIEs_t, ie2); + ie2->id = F1AP_ProtocolIE_ID_id_NRCGI; + ie2->criticality = F1AP_Criticality_reject; + ie2->value.present = F1AP_InitialULRRCMessageTransferIEs__value_PR_NRCGI; + MCC_MNC_TO_PLMNID(msg->plmn.mcc, msg->plmn.mnc, msg->plmn.mnc_digit_length, &ie2->value.choice.NRCGI.pLMN_Identity); + NR_CELL_ID_TO_BIT_STRING(msg->nr_cellid, &ie2->value.choice.NRCGI.nRCellIdentity); + + /* mandatory */ + /* c3. C_RNTI */ // 16 + asn1cSequenceAdd(out->protocolIEs.list, F1AP_InitialULRRCMessageTransferIEs_t, ie3); + ie3->id = F1AP_ProtocolIE_ID_id_C_RNTI; + ie3->criticality = F1AP_Criticality_reject; + ie3->value.present = F1AP_InitialULRRCMessageTransferIEs__value_PR_C_RNTI; + ie3->value.choice.C_RNTI = msg->crnti; + + /* mandatory */ + /* c4. RRCContainer */ + asn1cSequenceAdd(out->protocolIEs.list, F1AP_InitialULRRCMessageTransferIEs_t, ie4); + ie4->id = F1AP_ProtocolIE_ID_id_RRCContainer; + ie4->criticality = F1AP_Criticality_reject; + ie4->value.present = F1AP_InitialULRRCMessageTransferIEs__value_PR_RRCContainer; + OCTET_STRING_fromBuf(&ie4->value.choice.RRCContainer, (const char *)msg->rrc_container, msg->rrc_container_length); + + /* optional */ + /* c5. DUtoCURRCContainer */ + if (msg->du2cu_rrc_container != NULL) { + asn1cSequenceAdd(out->protocolIEs.list, F1AP_InitialULRRCMessageTransferIEs_t, ie5); + ie5->id = F1AP_ProtocolIE_ID_id_DUtoCURRCContainer; + ie5->criticality = F1AP_Criticality_reject; + ie5->value.present = F1AP_InitialULRRCMessageTransferIEs__value_PR_DUtoCURRCContainer; + OCTET_STRING_fromBuf(&ie5->value.choice.DUtoCURRCContainer, + (const char *)msg->du2cu_rrc_container, + msg->du2cu_rrc_container_length); + } + + /* mandatory */ + /* c6. Transaction ID (integer value) */ + asn1cSequenceAdd(out->protocolIEs.list, F1AP_InitialULRRCMessageTransferIEs_t, ie6); + ie6->id = F1AP_ProtocolIE_ID_id_TransactionID; + ie6->criticality = F1AP_Criticality_ignore; + ie6->value.present = F1AP_InitialULRRCMessageTransferIEs__value_PR_TransactionID; + ie6->value.choice.TransactionID = msg->transaction_id; + + return pdu; +} + +/** + * @brief Initial UL RRC Message Transfer decoding + */ +bool decode_initial_ul_rrc_message_transfer(const F1AP_F1AP_PDU_t *pdu, f1ap_initial_ul_rrc_message_t *out) +{ + DevAssert(out != NULL); + memset(out, 0, sizeof(*out)); + + F1AP_InitialULRRCMessageTransfer_t *container = &pdu->choice.initiatingMessage->value.choice.InitialULRRCMessageTransfer; + F1AP_InitialULRRCMessageTransferIEs_t *ie; + + F1AP_LIB_FIND_IE(F1AP_InitialULRRCMessageTransferIEs_t, ie, container, F1AP_ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID, true); + out->gNB_DU_ue_id = ie->value.choice.GNB_DU_UE_F1AP_ID; + + F1AP_LIB_FIND_IE(F1AP_InitialULRRCMessageTransferIEs_t, ie, container, F1AP_ProtocolIE_ID_id_NRCGI, true); + PLMNID_TO_MCC_MNC(&ie->value.choice.NRCGI.pLMN_Identity, out->plmn.mcc, out->plmn.mnc, out->plmn.mnc_digit_length); + BIT_STRING_TO_NR_CELL_IDENTITY(&ie->value.choice.NRCGI.nRCellIdentity, out->nr_cellid); + + F1AP_LIB_FIND_IE(F1AP_InitialULRRCMessageTransferIEs_t, ie, container, F1AP_ProtocolIE_ID_id_C_RNTI, true); + out->crnti = ie->value.choice.C_RNTI; + + F1AP_LIB_FIND_IE(F1AP_InitialULRRCMessageTransferIEs_t, ie, container, F1AP_ProtocolIE_ID_id_RRCContainer, true); + out->rrc_container = cp_octet_string(&ie->value.choice.RRCContainer, &out->rrc_container_length); + + F1AP_LIB_FIND_IE(F1AP_InitialULRRCMessageTransferIEs_t, ie, container, F1AP_ProtocolIE_ID_id_DUtoCURRCContainer, false); + if (ie != NULL) + out->du2cu_rrc_container = cp_octet_string(&ie->value.choice.DUtoCURRCContainer, &out->du2cu_rrc_container_length); + + F1AP_LIB_FIND_IE(F1AP_InitialULRRCMessageTransferIEs_t, ie, container, F1AP_ProtocolIE_ID_id_TransactionID, true); + out->transaction_id = ie->value.choice.TransactionID; + + return true; +} + +/** + * @brief Initial UL RRC Message Transfer deep copy + */ +f1ap_initial_ul_rrc_message_t cp_initial_ul_rrc_message_transfer(const f1ap_initial_ul_rrc_message_t *msg) +{ + uint8_t *rrc_container = calloc_or_fail(msg->rrc_container_length, sizeof(*rrc_container)); + memcpy(rrc_container, msg->rrc_container, msg->rrc_container_length); + uint8_t *du2cu_rrc_container = NULL; + if (msg->du2cu_rrc_container_length > 0) { + DevAssert(msg->du2cu_rrc_container != NULL); + du2cu_rrc_container = calloc_or_fail(msg->du2cu_rrc_container_length, sizeof(*du2cu_rrc_container)); + memcpy(du2cu_rrc_container, msg->du2cu_rrc_container, msg->du2cu_rrc_container_length); + } + f1ap_initial_ul_rrc_message_t cp = { + .gNB_DU_ue_id = msg->gNB_DU_ue_id, + .plmn = msg->plmn, + .nr_cellid = msg->nr_cellid, + .crnti = msg->crnti, + .rrc_container = rrc_container, + .rrc_container_length = msg->rrc_container_length, + .du2cu_rrc_container = du2cu_rrc_container, + .du2cu_rrc_container_length = msg->du2cu_rrc_container_length, + .transaction_id = msg->transaction_id + }; + return cp; +} + +/** + * @brief Initial UL RRC Message Transfer equality check + */ +bool eq_initial_ul_rrc_message_transfer(const f1ap_initial_ul_rrc_message_t *a, const f1ap_initial_ul_rrc_message_t *b) +{ + _F1_EQ_CHECK_INT(a->gNB_DU_ue_id, b->gNB_DU_ue_id); + if (!eq_f1ap_plmn(&a->plmn, &b->plmn)) + return false; + _F1_EQ_CHECK_LONG(a->nr_cellid, b->nr_cellid); + _F1_EQ_CHECK_INT(a->crnti, b->crnti); + _F1_EQ_CHECK_INT(a->rrc_container_length, b->rrc_container_length); + _F1_EQ_CHECK_LONG(a->nr_cellid, b->nr_cellid); + if (memcmp(a->rrc_container, b->rrc_container, a->rrc_container_length) != 0) + return false; + _F1_EQ_CHECK_INT(a->du2cu_rrc_container_length, b->du2cu_rrc_container_length); + if (memcmp(a->du2cu_rrc_container, b->du2cu_rrc_container, a->du2cu_rrc_container_length) != 0) + return false; + _F1_EQ_CHECK_INT(a->transaction_id, b->transaction_id); + return true; +} + +/** + * @brief Initial UL RRC Message Transfer memory management + */ +void free_initial_ul_rrc_message_transfer(const f1ap_initial_ul_rrc_message_t *msg) +{ + DevAssert(msg != NULL); + free(msg->rrc_container); + free(msg->du2cu_rrc_container); +} + +/* ==================================== + * F1AP UL RRC Message Transfer + * ==================================== */ + +/** + * @brief UL RRC Message Transfer encoding (9.2.3.3 of 3GPP TS 38.473) + * gNB-DU → gNB-CU + */ +F1AP_F1AP_PDU_t *encode_ul_rrc_message_transfer(const f1ap_ul_rrc_message_t *msg) +{ + + F1AP_F1AP_PDU_t *pdu = calloc(1, sizeof(*pdu)); + AssertFatal(pdu != NULL, "out of memory\n"); + + /* Create */ + /* 0. Message Type */ + pdu->present = F1AP_F1AP_PDU_PR_initiatingMessage; + asn1cCalloc(pdu->choice.initiatingMessage, tmp); + tmp->procedureCode = F1AP_ProcedureCode_id_ULRRCMessageTransfer; + tmp->criticality = F1AP_Criticality_ignore; + tmp->value.present = F1AP_InitiatingMessage__value_PR_ULRRCMessageTransfer; + F1AP_ULRRCMessageTransfer_t *out = &tmp->value.choice.ULRRCMessageTransfer; + // gNB-CU UE F1AP ID (M) + asn1cSequenceAdd(out->protocolIEs.list, F1AP_ULRRCMessageTransferIEs_t, ie1); + ie1->id = F1AP_ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID; + ie1->criticality = F1AP_Criticality_reject; + ie1->value.present = F1AP_ULRRCMessageTransferIEs__value_PR_GNB_CU_UE_F1AP_ID; + ie1->value.choice.GNB_CU_UE_F1AP_ID = msg->gNB_CU_ue_id; + // gNB-DU UE F1AP ID (M) + asn1cSequenceAdd(out->protocolIEs.list, F1AP_ULRRCMessageTransferIEs_t, ie2); + ie2->id = F1AP_ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID; + ie2->criticality = F1AP_Criticality_reject; + ie2->value.present = F1AP_ULRRCMessageTransferIEs__value_PR_GNB_DU_UE_F1AP_ID; + ie2->value.choice.GNB_DU_UE_F1AP_ID = msg->gNB_DU_ue_id; + // SRB ID (M) + asn1cSequenceAdd(out->protocolIEs.list, F1AP_ULRRCMessageTransferIEs_t, ie3); + ie3->id = F1AP_ProtocolIE_ID_id_SRBID; + ie3->criticality = F1AP_Criticality_reject; + ie3->value.present = F1AP_ULRRCMessageTransferIEs__value_PR_SRBID; + ie3->value.choice.SRBID = msg->srb_id; + // RRC-Container (M) + asn1cSequenceAdd(out->protocolIEs.list, F1AP_ULRRCMessageTransferIEs_t, ie4); + ie4->id = F1AP_ProtocolIE_ID_id_RRCContainer; + ie4->criticality = F1AP_Criticality_reject; + ie4->value.present = F1AP_ULRRCMessageTransferIEs__value_PR_RRCContainer; + OCTET_STRING_fromBuf(&ie4->value.choice.RRCContainer, (const char *)msg->rrc_container, msg->rrc_container_length); + + return pdu; +} + +/** + * @brief UL RRC Message Transfer decoding (9.2.3.3 of 3GPP TS 38.473) + * gNB-DU → gNB-CU + */ +bool decode_ul_rrc_message_transfer(const F1AP_F1AP_PDU_t *pdu, f1ap_ul_rrc_message_t *out) +{ + DevAssert(out != NULL); + memset(out, 0, sizeof(*out)); + DevAssert(pdu != NULL); + + F1AP_ULRRCMessageTransfer_t *container = &pdu->choice.initiatingMessage->value.choice.ULRRCMessageTransfer; + F1AP_ULRRCMessageTransferIEs_t *ie; + + // gNB-CU UE F1AP ID (M) + F1AP_LIB_FIND_IE(F1AP_ULRRCMessageTransferIEs_t, ie, container, F1AP_ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID, true); + out->gNB_CU_ue_id = ie->value.choice.GNB_CU_UE_F1AP_ID; + // gNB-DU UE F1AP ID (M) + F1AP_LIB_FIND_IE(F1AP_ULRRCMessageTransferIEs_t, ie, container, F1AP_ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID, true); + out->gNB_DU_ue_id = ie->value.choice.GNB_DU_UE_F1AP_ID; + // SRB ID (M) + F1AP_LIB_FIND_IE(F1AP_ULRRCMessageTransferIEs_t, ie, container, F1AP_ProtocolIE_ID_id_SRBID, true); + out->srb_id = ie->value.choice.SRBID; + // RRC-Container (M) + F1AP_LIB_FIND_IE(F1AP_ULRRCMessageTransferIEs_t, ie, container, F1AP_ProtocolIE_ID_id_RRCContainer, true); + out->rrc_container = cp_octet_string(&ie->value.choice.RRCContainer, &out->rrc_container_length); + + return true; +} + +/** + * @brief UL RRC Message Transfer deep copy + */ +f1ap_ul_rrc_message_t cp_ul_rrc_message_transfer(const f1ap_ul_rrc_message_t *msg) +{ + uint8_t *rrc_container = calloc_or_fail(msg->rrc_container_length, sizeof(*rrc_container)); + memcpy(rrc_container, msg->rrc_container, msg->rrc_container_length); + f1ap_ul_rrc_message_t cp = { + .gNB_DU_ue_id = msg->gNB_DU_ue_id, + .gNB_CU_ue_id = msg->gNB_CU_ue_id, + .srb_id = msg->srb_id, + .rrc_container = rrc_container, + .rrc_container_length = msg->rrc_container_length, + }; + return cp; +} + +/** + * @brief UL RRC Message Transfer equality check + */ +bool eq_ul_rrc_message_transfer(const f1ap_ul_rrc_message_t *a, const f1ap_ul_rrc_message_t *b) +{ + _F1_EQ_CHECK_INT(a->gNB_DU_ue_id, b->gNB_DU_ue_id); + _F1_EQ_CHECK_INT(a->gNB_CU_ue_id, b->gNB_CU_ue_id); + _F1_EQ_CHECK_INT(a->rrc_container_length, b->rrc_container_length); + _F1_EQ_CHECK_INT(a->gNB_DU_ue_id, b->gNB_DU_ue_id); + if (memcmp(a->rrc_container, b->rrc_container, a->rrc_container_length) != 0) + return false; + return true; +} + +/** + * @brief UL RRC Message Transfer memory management + */ +void free_ul_rrc_message_transfer(const f1ap_ul_rrc_message_t *msg) +{ + DevAssert(msg != NULL); + free(msg->rrc_container); +} + +/* ============================ + * F1AP DL RRC Message Transfer + * ============================ */ + +/** + * @brief DL RRC Message Transfer encoding (9.2.3.2 of 3GPP TS 38.473) + * gNB-CU → gNB-DU + */ +F1AP_F1AP_PDU_t *encode_dl_rrc_message_transfer(const f1ap_dl_rrc_message_t *msg) +{ + F1AP_F1AP_PDU_t *pdu = calloc(1, sizeof(*pdu)); + AssertFatal(pdu != NULL, "out of memory\n"); + + /* Create */ + /* 0. Message Type */ + pdu->present = F1AP_F1AP_PDU_PR_initiatingMessage; + asn1cCalloc(pdu->choice.initiatingMessage, tmp); + tmp->procedureCode = F1AP_ProcedureCode_id_DLRRCMessageTransfer; + tmp->criticality = F1AP_Criticality_ignore; + tmp->value.present = F1AP_InitiatingMessage__value_PR_DLRRCMessageTransfer; + F1AP_DLRRCMessageTransfer_t *out = &tmp->value.choice.DLRRCMessageTransfer; + // gNB-CU UE F1AP ID (M) + asn1cSequenceAdd(out->protocolIEs.list, F1AP_DLRRCMessageTransferIEs_t, ie1); + ie1->id = F1AP_ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID; + ie1->criticality = F1AP_Criticality_reject; + ie1->value.present = F1AP_DLRRCMessageTransferIEs__value_PR_GNB_CU_UE_F1AP_ID; + ie1->value.choice.GNB_CU_UE_F1AP_ID = msg->gNB_CU_ue_id; + // gNB-DU UE F1AP ID (M) + asn1cSequenceAdd(out->protocolIEs.list, F1AP_DLRRCMessageTransferIEs_t, ie2); + ie2->id = F1AP_ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID; + ie2->criticality = F1AP_Criticality_reject; + ie2->value.present = F1AP_DLRRCMessageTransferIEs__value_PR_GNB_DU_UE_F1AP_ID; + ie2->value.choice.GNB_DU_UE_F1AP_ID = msg->gNB_DU_ue_id; + // old gNB-DU UE F1AP ID (O) + if (msg->old_gNB_DU_ue_id) { + asn1cSequenceAdd(out->protocolIEs.list, F1AP_DLRRCMessageTransferIEs_t, ie3); + ie3->id = F1AP_ProtocolIE_ID_id_oldgNB_DU_UE_F1AP_ID; + ie3->criticality = F1AP_Criticality_reject; + ie3->value.present = F1AP_DLRRCMessageTransferIEs__value_PR_GNB_DU_UE_F1AP_ID_1; + ie3->value.choice.GNB_DU_UE_F1AP_ID_1 = *msg->old_gNB_DU_ue_id; + } + // SRB ID (M) + asn1cSequenceAdd(out->protocolIEs.list, F1AP_DLRRCMessageTransferIEs_t, ie4); + ie4->id = F1AP_ProtocolIE_ID_id_SRBID; + ie4->criticality = F1AP_Criticality_reject; + ie4->value.present = F1AP_DLRRCMessageTransferIEs__value_PR_SRBID; + ie4->value.choice.SRBID = msg->srb_id; + // Execute Duplication (O) + if (msg->execute_duplication) { + asn1cSequenceAdd(out->protocolIEs.list, F1AP_DLRRCMessageTransferIEs_t, ie5); + ie5->id = F1AP_ProtocolIE_ID_id_ExecuteDuplication; + ie5->criticality = F1AP_Criticality_ignore; + ie5->value.present = F1AP_DLRRCMessageTransferIEs__value_PR_ExecuteDuplication; + ie5->value.choice.ExecuteDuplication = F1AP_ExecuteDuplication_true; + } + // RRC-Container (M) + asn1cSequenceAdd(out->protocolIEs.list, F1AP_DLRRCMessageTransferIEs_t, ie6); + ie6->id = F1AP_ProtocolIE_ID_id_RRCContainer; + ie6->criticality = F1AP_Criticality_reject; + ie6->value.present = F1AP_DLRRCMessageTransferIEs__value_PR_RRCContainer; + OCTET_STRING_fromBuf(&ie6->value.choice.RRCContainer, (const char *)msg->rrc_container, msg->rrc_container_length); + + return pdu; +} + +/** + * @brief DL RRC Message Transfer decoding (9.2.3.2 of 3GPP TS 38.473) + * gNB-CU → gNB-DU + */ +bool decode_dl_rrc_message_transfer(const F1AP_F1AP_PDU_t *pdu, f1ap_dl_rrc_message_t *out) +{ + DevAssert(out != NULL); + memset(out, 0, sizeof(*out)); + + DevAssert(pdu != NULL); + F1AP_DLRRCMessageTransfer_t *container = &pdu->choice.initiatingMessage->value.choice.DLRRCMessageTransfer; + F1AP_DLRRCMessageTransferIEs_t *ie; + // gNB-CU UE F1AP ID (M) + F1AP_LIB_FIND_IE(F1AP_DLRRCMessageTransferIEs_t, ie, container, F1AP_ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID, true); + out->gNB_CU_ue_id = ie->value.choice.GNB_CU_UE_F1AP_ID; + // gNB-DU UE F1AP ID (M) + F1AP_LIB_FIND_IE(F1AP_DLRRCMessageTransferIEs_t, ie, container, F1AP_ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID, true); + out->gNB_DU_ue_id = ie->value.choice.GNB_DU_UE_F1AP_ID; + // old gNB-DU UE F1AP ID (O) + out->old_gNB_DU_ue_id = NULL; + F1AP_LIB_FIND_IE(F1AP_DLRRCMessageTransferIEs_t, ie, container, F1AP_ProtocolIE_ID_id_oldgNB_DU_UE_F1AP_ID, false); + if (ie) { + out->old_gNB_DU_ue_id = malloc_or_fail(sizeof(*out->old_gNB_DU_ue_id)); + *out->old_gNB_DU_ue_id = ie->value.choice.GNB_DU_UE_F1AP_ID_1; + } + // SRB ID (M) + F1AP_LIB_FIND_IE(F1AP_DLRRCMessageTransferIEs_t, ie, container, F1AP_ProtocolIE_ID_id_SRBID, true); + out->srb_id = ie->value.choice.SRBID; + // Execute Duplication (O) + F1AP_LIB_FIND_IE(F1AP_DLRRCMessageTransferIEs_t, ie, container, F1AP_ProtocolIE_ID_id_ExecuteDuplication, false); + if (ie) { + out->execute_duplication = ie->value.choice.ExecuteDuplication; + } + // RRC-Container (M) + F1AP_LIB_FIND_IE(F1AP_DLRRCMessageTransferIEs_t, ie, container, F1AP_ProtocolIE_ID_id_RRCContainer, true); + out->rrc_container = cp_octet_string(&ie->value.choice.RRCContainer, &out->rrc_container_length); + + return true; +} + +/** + * @brief DL RRC Message Transfer deep copy + */ +f1ap_dl_rrc_message_t cp_dl_rrc_message_transfer(const f1ap_dl_rrc_message_t *msg) +{ + uint8_t *rrc_container = calloc_or_fail(msg->rrc_container_length, sizeof(*rrc_container)); + memcpy(rrc_container, msg->rrc_container, msg->rrc_container_length); + + uint32_t *old_gNB_DU_ue_id = NULL; + if (msg->old_gNB_DU_ue_id) { + old_gNB_DU_ue_id = malloc_or_fail(sizeof(*old_gNB_DU_ue_id)); + *old_gNB_DU_ue_id = *(msg->old_gNB_DU_ue_id); + } + + f1ap_dl_rrc_message_t cp = { + .gNB_DU_ue_id = msg->gNB_DU_ue_id, + .gNB_CU_ue_id = msg->gNB_CU_ue_id, + .old_gNB_DU_ue_id = old_gNB_DU_ue_id, + .srb_id = msg->srb_id, + .execute_duplication = msg->execute_duplication, + .rrc_container = rrc_container, + .rrc_container_length = msg->rrc_container_length, + }; + + return cp; +} + +/** + * @brief DL RRC Message Transfer equality check + */ +bool eq_dl_rrc_message_transfer(const f1ap_dl_rrc_message_t *a, const f1ap_dl_rrc_message_t *b) +{ + _F1_EQ_CHECK_INT(a->gNB_DU_ue_id, b->gNB_DU_ue_id); + _F1_EQ_CHECK_INT(a->gNB_CU_ue_id, b->gNB_CU_ue_id); + _F1_EQ_CHECK_INT(a->gNB_DU_ue_id, b->gNB_DU_ue_id); + _F1_EQ_CHECK_INT(a->gNB_DU_ue_id, b->gNB_DU_ue_id); + _F1_EQ_CHECK_INT(a->gNB_DU_ue_id, b->gNB_DU_ue_id); + if (!(a->old_gNB_DU_ue_id == NULL && b->old_gNB_DU_ue_id == NULL)) + _F1_EQ_CHECK_INT(*a->old_gNB_DU_ue_id, *b->old_gNB_DU_ue_id); + _F1_EQ_CHECK_INT(a->srb_id, b->srb_id); + _F1_EQ_CHECK_INT(a->execute_duplication, b->execute_duplication); + _F1_EQ_CHECK_INT(a->rrc_container_length, b->rrc_container_length); + if (memcmp(a->rrc_container, b->rrc_container, a->rrc_container_length) != 0) + return false; + return true; +} + +/** + * @brief DL RRC Message Transfer memory management + */ +void free_dl_rrc_message_transfer(const f1ap_dl_rrc_message_t *msg) +{ + DevAssert(msg != NULL); + free(msg->rrc_container); + free(msg->old_gNB_DU_ue_id); +} diff --git a/openair2/F1AP/lib/f1ap_rrc_message_transfer.h b/openair2/F1AP/lib/f1ap_rrc_message_transfer.h new file mode 100644 index 0000000000..4e6d682f78 --- /dev/null +++ b/openair2/F1AP/lib/f1ap_rrc_message_transfer.h @@ -0,0 +1,50 @@ +/* + * 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 F1AP_RRC_MESSAGE_TRANSFER_H_ +#define F1AP_RRC_MESSAGE_TRANSFER_H_ + +#include +#include "f1ap_messages_types.h" + +struct F1AP_F1AP_PDU; + +struct F1AP_F1AP_PDU *encode_initial_ul_rrc_message_transfer(const f1ap_initial_ul_rrc_message_t *msg); +bool decode_initial_ul_rrc_message_transfer(const struct F1AP_F1AP_PDU *pdu, f1ap_initial_ul_rrc_message_t *out); +f1ap_initial_ul_rrc_message_t cp_initial_ul_rrc_message_transfer(const f1ap_initial_ul_rrc_message_t *msg); +bool eq_initial_ul_rrc_message_transfer(const f1ap_initial_ul_rrc_message_t *a, const f1ap_initial_ul_rrc_message_t *b); +void free_initial_ul_rrc_message_transfer(const f1ap_initial_ul_rrc_message_t *msg); + +/* DL RRC Message transfer */ +struct F1AP_F1AP_PDU *encode_dl_rrc_message_transfer(const f1ap_dl_rrc_message_t *msg); +bool decode_dl_rrc_message_transfer(const struct F1AP_F1AP_PDU *pdu, f1ap_dl_rrc_message_t *out); +f1ap_dl_rrc_message_t cp_dl_rrc_message_transfer(const f1ap_dl_rrc_message_t *msg); +bool eq_dl_rrc_message_transfer(const f1ap_dl_rrc_message_t *a, const f1ap_dl_rrc_message_t *b); +void free_dl_rrc_message_transfer(const f1ap_dl_rrc_message_t *msg); + +/* UL RRC Message transfer */ +struct F1AP_F1AP_PDU *encode_ul_rrc_message_transfer(const f1ap_ul_rrc_message_t *msg); +bool decode_ul_rrc_message_transfer(const struct F1AP_F1AP_PDU *pdu, f1ap_ul_rrc_message_t *out); +f1ap_ul_rrc_message_t cp_ul_rrc_message_transfer(const f1ap_ul_rrc_message_t *msg); +bool eq_ul_rrc_message_transfer(const f1ap_ul_rrc_message_t *a, const f1ap_ul_rrc_message_t *b); +void free_ul_rrc_message_transfer(const f1ap_ul_rrc_message_t *msg); + +#endif /* F1AP_RRC_MESSAGE_TRANSFER_H_ */ diff --git a/openair2/F1AP/tests/CMakeLists.txt b/openair2/F1AP/tests/CMakeLists.txt new file mode 100644 index 0000000000..a73334051a --- /dev/null +++ b/openair2/F1AP/tests/CMakeLists.txt @@ -0,0 +1,6 @@ +add_executable(f1ap_lib_test f1ap_lib_test.c) +add_dependencies(tests f1ap_lib_test) +add_test(NAME f1ap_lib_test COMMAND f1ap_lib_test) +target_link_libraries(f1ap_lib_test PRIVATE f1ap_lib) +target_link_libraries(f1ap_lib_test PRIVATE asn1_f1ap) +target_include_directories(f1ap_lib_test PRIVATE ${CMAKE_SOURCE_DIR}) diff --git a/openair2/F1AP/tests/f1ap_lib_test.c b/openair2/F1AP/tests/f1ap_lib_test.c new file mode 100644 index 0000000000..969efc5afa --- /dev/null +++ b/openair2/F1AP/tests/f1ap_lib_test.c @@ -0,0 +1,564 @@ +#include +#include +#include + +#include "common/utils/assertions.h" +#include "common/utils/utils.h" + +#include "f1ap_messages_types.h" +#include "F1AP_F1AP-PDU.h" + +#include "f1ap_lib_extern.h" +#include "lib/f1ap_interface_management.h" + +void exit_function(const char *file, const char *function, const int line, const char *s, const int assert) +{ + printf("detected error at %s:%d:%s: %s\n", file, line, function, s); + abort(); +} + +static F1AP_F1AP_PDU_t *f1ap_encode_decode(const F1AP_F1AP_PDU_t *enc_pdu) +{ + //xer_fprint(stdout, &asn_DEF_F1AP_F1AP_PDU, enc_pdu); + + DevAssert(enc_pdu != NULL); + char errbuf[1024]; + size_t errlen = sizeof(errbuf); + int ret = asn_check_constraints(&asn_DEF_F1AP_F1AP_PDU, enc_pdu, errbuf, &errlen); + AssertFatal(ret == 0, "asn_check_constraints() failed: %s\n", errbuf); + + uint8_t msgbuf[16384]; + asn_enc_rval_t enc = aper_encode_to_buffer(&asn_DEF_F1AP_F1AP_PDU, NULL, enc_pdu, msgbuf, sizeof(msgbuf)); + AssertFatal(enc.encoded > 0, "aper_encode_to_buffer() failed\n"); + + F1AP_F1AP_PDU_t *dec_pdu = NULL; + asn_codec_ctx_t st = {.max_stack_size = 100 * 1000}; + asn_dec_rval_t dec = aper_decode(&st, &asn_DEF_F1AP_F1AP_PDU, (void **)&dec_pdu, msgbuf, enc.encoded, 0, 0); + AssertFatal(dec.code == RC_OK, "aper_decode() failed\n"); + + //xer_fprint(stdout, &asn_DEF_F1AP_F1AP_PDU, dec_pdu); + return dec_pdu; +} + +static void f1ap_msg_free(F1AP_F1AP_PDU_t *pdu) +{ + ASN_STRUCT_FREE(asn_DEF_F1AP_F1AP_PDU, pdu); +} + +/** + * @brief Test Initial UL RRC Message Transfer encoding/decoding + */ +static void test_initial_ul_rrc_message_transfer(void) +{ + f1ap_plmn_t plmn = { .mcc = 208, .mnc = 95, .mnc_digit_length = 2 }; + uint8_t rrc[] = "RRC Container"; + uint8_t du2cu[] = "DU2CU Container"; + f1ap_initial_ul_rrc_message_t orig = { + .gNB_DU_ue_id = 12, + .plmn = plmn, + .nr_cellid = 135, + .crnti = 0x1234, + .rrc_container = rrc, + .rrc_container_length = sizeof(rrc), + .du2cu_rrc_container = du2cu, + .du2cu_rrc_container_length = sizeof(du2cu), + .transaction_id = 2, + }; + + F1AP_F1AP_PDU_t *f1enc = encode_initial_ul_rrc_message_transfer(&orig); + F1AP_F1AP_PDU_t *f1dec = f1ap_encode_decode(f1enc); + f1ap_msg_free(f1enc); + + f1ap_initial_ul_rrc_message_t decoded; + bool ret = decode_initial_ul_rrc_message_transfer(f1dec, &decoded); + AssertFatal(ret, "decode_initial_ul_rrc_message_transfer(): could not decode message\n"); + f1ap_msg_free(f1dec); + + ret = eq_initial_ul_rrc_message_transfer(&orig, &decoded); + AssertFatal(ret, "eq_initial_ul_rrc_message_transfer(): decoded message doesn't match\n"); + free_initial_ul_rrc_message_transfer(&decoded); + + f1ap_initial_ul_rrc_message_t cp = cp_initial_ul_rrc_message_transfer(&orig); + ret = eq_initial_ul_rrc_message_transfer(&orig, &cp); + AssertFatal(ret, "eq_initial_ul_rrc_message_transfer(): copied message doesn't match\n"); + free_initial_ul_rrc_message_transfer(&cp); +} + +/** + * @brief Test DL RRC Message Transfer encoding/decoding + */ +static void test_dl_rrc_message_transfer(void) +{ + uint8_t *rrc = calloc(strlen("RRC Container") + 1, sizeof(uint8_t)); + uint32_t *old_gNB_DU_ue_id = calloc(1, sizeof(uint32_t)); + AssertFatal(rrc != NULL && old_gNB_DU_ue_id != NULL, "out of memory\n"); + memcpy((void *)rrc, "RRC Container", strlen("RRC Container") + 1); + + f1ap_dl_rrc_message_t orig = { + .gNB_DU_ue_id = 12, + .gNB_CU_ue_id = 12, + .old_gNB_DU_ue_id = old_gNB_DU_ue_id, + .srb_id = 1, + .rrc_container = rrc, + .rrc_container_length = sizeof(rrc), + }; + + F1AP_F1AP_PDU_t *f1enc = encode_dl_rrc_message_transfer(&orig); + F1AP_F1AP_PDU_t *f1dec = f1ap_encode_decode(f1enc); + f1ap_msg_free(f1enc); + + f1ap_dl_rrc_message_t decoded = {0}; + bool ret = decode_dl_rrc_message_transfer(f1dec, &decoded); + AssertFatal(ret, "decode_initial_ul_rrc_message_transfer(): could not decode message\n"); + f1ap_msg_free(f1dec); + + ret = eq_dl_rrc_message_transfer(&orig, &decoded); + AssertFatal(ret, "eq_dl_rrc_message_transfer(): decoded message doesn't match\n"); + free_dl_rrc_message_transfer(&decoded); + + f1ap_dl_rrc_message_t cp = cp_dl_rrc_message_transfer(&orig); + ret = eq_dl_rrc_message_transfer(&orig, &cp); + AssertFatal(ret, "eq_dl_rrc_message_transfer(): copied message doesn't match\n"); + free_dl_rrc_message_transfer(&orig); + free_dl_rrc_message_transfer(&cp); +} + +/** + * @brief Test UL RRC Message Transfer encoding/decoding + */ +static void test_ul_rrc_message_transfer(void) +{ + uint8_t rrc[] = "RRC Container"; + + f1ap_ul_rrc_message_t orig = { + .gNB_DU_ue_id = 12, + .gNB_CU_ue_id = 12, + .srb_id = 1, + .rrc_container = rrc, + .rrc_container_length = sizeof(rrc), + }; + + F1AP_F1AP_PDU_t *f1enc = encode_ul_rrc_message_transfer(&orig); + F1AP_F1AP_PDU_t *f1dec = f1ap_encode_decode(f1enc); + f1ap_msg_free(f1enc); + + f1ap_ul_rrc_message_t decoded = {0}; + bool ret = decode_ul_rrc_message_transfer(f1dec, &decoded); + AssertFatal(ret, "decode_initial_ul_rrc_message_transfer(): could not decode message\n"); + f1ap_msg_free(f1dec); + + ret = eq_ul_rrc_message_transfer(&orig, &decoded); + AssertFatal(ret, "eq_dl_rrc_message_transfer(): decoded message doesn't match\n"); + free_ul_rrc_message_transfer(&decoded); + + f1ap_ul_rrc_message_t cp = cp_ul_rrc_message_transfer(&orig); + ret = eq_ul_rrc_message_transfer(&orig, &cp); + AssertFatal(ret, "eq_dl_rrc_message_transfer(): copied message doesn't match\n"); + free_ul_rrc_message_transfer(&cp); +} + +/** + * @brief Test F1AP Setup Request Encoding/Decoding + */ +static void test_f1ap_setup_request(void) +{ + /* allocate memory */ + /* gNB_DU_name */ + uint8_t *gNB_DU_name = calloc(strlen("OAI DU") + 1, sizeof(uint8_t)); + AssertFatal(gNB_DU_name != NULL, "out of memory\n"); + memcpy((void *)gNB_DU_name, "OAI DU", strlen("OAI DU") + 1); + /* sys_info */ + uint8_t *mib = calloc(3, sizeof(uint8_t)); + uint8_t *sib1 = calloc(3, sizeof(uint8_t)); + f1ap_gnb_du_system_info_t sys_info = { + .mib_length = 3, + .mib = mib, + .sib1_length = 3, + .sib1 = sib1, + }; + /* measurement_timing_information */ + int measurement_timing_config_len = strlen("0") + 1; + uint8_t *measurement_timing_information = calloc(measurement_timing_config_len, sizeof(uint8_t)); + AssertFatal(measurement_timing_information != NULL, "out of memory\n"); + memcpy((void *)measurement_timing_information, "0", measurement_timing_config_len); + /* TAC */ + uint32_t *tac = calloc(1, sizeof(uint32_t)); + /* + * TDD test + */ + // Served Cell Info + f1ap_served_cell_info_t info = { + .mode = F1AP_MODE_TDD, + .tdd.freqinfo.arfcn = 640000, + .tdd.freqinfo.band = 78, + .tdd.tbw.nrb = 66, + .tdd.tbw.scs = 1, + .measurement_timing_config_len = measurement_timing_config_len, + .measurement_timing_config = measurement_timing_information, + .nr_cellid = 123456, + .plmn.mcc = 1, + .plmn.mnc = 1, + .plmn.mnc_digit_length = 3, + .num_ssi = 1, + .nssai[0].sst = 1, + .nssai[0].sd = 1, + .tac = tac, + }; + // create message + f1ap_setup_req_t orig = { + .gNB_DU_id = 1, + .gNB_DU_name = (char *)gNB_DU_name, + .num_cells_available = 1, + .transaction_id = 2, + .rrc_ver[0] = 12, + .rrc_ver[1] = 34, + .rrc_ver[2] = 56, + .cell[0].info = info, + }; + orig.cell[0].sys_info = calloc(1, sizeof(*orig.cell[0].sys_info)); + *orig.cell[0].sys_info = sys_info; + // encode + F1AP_F1AP_PDU_t *f1enc = encode_f1ap_setup_request(&orig); + F1AP_F1AP_PDU_t *f1dec = f1ap_encode_decode(f1enc); + f1ap_msg_free(f1enc); + // decode + f1ap_setup_req_t decoded = {0}; + bool ret = decode_f1ap_setup_request(f1dec, &decoded); + AssertFatal(ret, "decode_f1ap_setup_request(): could not decode message\n"); + f1ap_msg_free(f1dec); + // equality check + ret = eq_f1ap_setup_request(&orig, &decoded); + AssertFatal(ret, "eq_f1ap_setup_request(): decoded message doesn't match\n"); + free_f1ap_setup_request(&decoded); + // deep copy + f1ap_setup_req_t cp = cp_f1ap_setup_request(&orig); + ret = eq_f1ap_setup_request(&orig, &cp); + AssertFatal(ret, "eq_f1ap_setup_request(): copied message doesn't match\n"); + free_f1ap_setup_request(&cp); + /* + * FDD test + */ + info.mode = F1AP_MODE_FDD; + info.tdd.freqinfo.arfcn = 0; + info.tdd.freqinfo.band = 0; + info.tdd.tbw.nrb = 0; + info.tdd.tbw.scs = 0; + info.fdd.ul_freqinfo.arfcn = 640000; + info.fdd.ul_freqinfo.band = 78; + info.fdd.dl_freqinfo.arfcn = 641000; + info.fdd.dl_freqinfo.band = 78; + info.fdd.ul_tbw.nrb = 66; + info.fdd.ul_tbw.scs = 1; + info.fdd.dl_tbw.nrb = 66; + info.fdd.dl_tbw.scs = 1; + // encode + f1enc = encode_f1ap_setup_request(&orig); + f1dec = f1ap_encode_decode(f1enc); + f1ap_msg_free(f1enc); + // decode + ret = decode_f1ap_setup_request(f1dec, &decoded); + AssertFatal(ret, "decode_f1ap_setup_request(): could not decode message\n"); + f1ap_msg_free(f1dec); + // equality check + ret = eq_f1ap_setup_request(&orig, &decoded); + AssertFatal(ret, "eq_f1ap_setup_request(): decoded message doesn't match\n"); + free_f1ap_setup_request(&decoded); + // copy + cp = cp_f1ap_setup_request(&orig); + ret = eq_f1ap_setup_request(&orig, &cp); + AssertFatal(ret, "eq_f1ap_setup_request(): copied message doesn't match\n"); + free_f1ap_setup_request(&cp); + // free original message + free_f1ap_setup_request(&orig); +} + +/** + * @brief Test F1AP Setup Response Encoding/Decoding + */ +static void test_f1ap_setup_response(void) +{ + /* allocate memory */ + /* gNB_CU_name */ + char *cu_name = "OAI-CU"; + int len = strlen(cu_name) + 1; + uint8_t *gNB_CU_name = calloc(len, sizeof(uint8_t)); + AssertFatal(gNB_CU_name != NULL, "out of memory\n"); + memcpy((void *)gNB_CU_name, cu_name, len); + /* create message */ + f1ap_setup_resp_t orig = { + .gNB_CU_name = (char *)gNB_CU_name, + .transaction_id = 2, + .rrc_ver[0] = 12, + .rrc_ver[1] = 34, + .rrc_ver[2] = 56, + .num_cells_to_activate = 1, + .cells_to_activate[0].nr_cellid = 123456, + .cells_to_activate[0].nrpci = 1, + .cells_to_activate[0].plmn.mcc = 12, + .cells_to_activate[0].plmn.mnc = 123, + .cells_to_activate[0].plmn.mnc_digit_length = 3, + }; + /* Cells to activate */ + if (orig.num_cells_to_activate) { + /* SI_container */ + char *s = "test"; + int SI_container_length = strlen(s) + 1; + orig.cells_to_activate[0].num_SI = 1; + f1ap_sib_msg_t *SI_msg = &orig.cells_to_activate[0].SI_msg[0]; + SI_msg->SI_container = malloc_or_fail(SI_container_length); + memcpy(SI_msg->SI_container, (uint8_t *)s, SI_container_length); + SI_msg->SI_container_length = SI_container_length; + SI_msg->SI_type = 7; + } + F1AP_F1AP_PDU_t *f1enc = encode_f1ap_setup_response(&orig); + F1AP_F1AP_PDU_t *f1dec = f1ap_encode_decode(f1enc); + f1ap_msg_free(f1enc); + + f1ap_setup_resp_t decoded = {0}; + bool ret = decode_f1ap_setup_response(f1dec, &decoded); + AssertFatal(ret, "decode_f1ap_setup_response(): could not decode message\n"); + f1ap_msg_free(f1dec); + + ret = eq_f1ap_setup_response(&orig, &decoded); + AssertFatal(ret, "eq_f1ap_setup_response(): decoded message doesn't match\n"); + free_f1ap_setup_response(&decoded); + + f1ap_setup_resp_t cp = cp_f1ap_setup_response(&orig); + ret = eq_f1ap_setup_response(&orig, &cp); + AssertFatal(ret, "eq_f1ap_setup_response(): copied message doesn't match\n"); + free_f1ap_setup_response(&cp); + free_f1ap_setup_response(&orig); +} + +/** + * @brief Test F1AP Setup Failure Encoding/Decoding + */ +static void test_f1ap_setup_failure(void) +{ + /* create message */ + f1ap_setup_failure_t orig = { + .transaction_id = 2, + .cause = 4, + }; + F1AP_F1AP_PDU_t *f1enc = encode_f1ap_setup_failure(&orig); + F1AP_F1AP_PDU_t *f1dec = f1ap_encode_decode(f1enc); + f1ap_msg_free(f1enc); + + f1ap_setup_failure_t decoded = {0}; + bool ret = decode_f1ap_setup_failure(f1dec, &decoded); + AssertFatal(ret, "decode_f1ap_setup_failure(): could not decode message\n"); + f1ap_msg_free(f1dec); + + ret = eq_f1ap_setup_failure(&orig, &decoded); + AssertFatal(ret, "eq_f1ap_setup_failure(): decoded message doesn't match\n"); + + f1ap_setup_failure_t cp = cp_f1ap_setup_failure(&orig); + ret = eq_f1ap_setup_failure(&orig, &cp); + AssertFatal(ret, "eq_f1ap_setup_failure(): copied message doesn't match\n"); +} + +/** + * @brief Test F1 gNB-DU Configuration Update + */ +static void test_f1ap_du_configuration_update(void) +{ + /* sys_info */ + uint8_t *mib = calloc(3, sizeof(uint8_t)); + uint8_t *sib1 = calloc(3, sizeof(uint8_t)); + f1ap_gnb_du_system_info_t sys_info = { + .mib_length = 3, + .mib = mib, + .sib1_length = 3, + .sib1 = sib1, + }; + /* measurement_timing_information modify */ + char *s = "1"; + int measurement_timing_config_len = strlen(s) + 1; + uint8_t *measurement_timing_config_mod = calloc(measurement_timing_config_len, sizeof(uint8_t)); + AssertFatal(measurement_timing_config_mod != NULL, "out of memory\n"); + memcpy((void *)measurement_timing_config_mod, s, measurement_timing_config_len); + /* TAC modify */ + uint32_t *tac = calloc(1, sizeof(uint32_t)); + AssertFatal(tac != NULL, "out of memory\n"); + *tac = 456; + /* info modify */ + f1ap_served_cell_info_t info = { + .mode = F1AP_MODE_TDD, + .tdd.freqinfo.arfcn = 640000, + .tdd.freqinfo.band = 78, + .tdd.tbw.nrb = 66, + .tdd.tbw.scs = 1, + .measurement_timing_config_len = measurement_timing_config_len, + .measurement_timing_config = measurement_timing_config_mod, + .nr_cellid = 123456, + .plmn.mcc = 1, + .plmn.mnc = 1, + .plmn.mnc_digit_length = 3, + .tac = tac, + }; + /* create message */ + f1ap_gnb_du_configuration_update_t orig = { + .transaction_id = 2, + .num_cells_to_modify = 1, + .cell_to_modify[0].info = info, + .num_cells_to_delete = 0, + .cell_to_delete[0].nr_cellid = 1234UL, + .cell_to_delete[0].plmn.mcc = 1, + .cell_to_delete[0].plmn.mnc = 1, + .cell_to_delete[0].plmn.mnc_digit_length = 3, + }; + orig.cell_to_modify[0].sys_info = calloc(1, sizeof(*orig.cell_to_modify[0].sys_info)); + AssertFatal(orig.cell_to_modify[0].sys_info != NULL, "out of memory\n"); + *orig.cell_to_modify[0].sys_info = sys_info; + + F1AP_F1AP_PDU_t *f1enc = encode_f1ap_du_configuration_update(&orig); + F1AP_F1AP_PDU_t *f1dec = f1ap_encode_decode(f1enc); + f1ap_msg_free(f1enc); + + f1ap_gnb_du_configuration_update_t decoded = {0}; + bool ret = decode_f1ap_du_configuration_update(f1dec, &decoded); + AssertFatal(ret, "decode_f1ap_setup_request(): could not decode message\n"); + f1ap_msg_free(f1dec); + + ret = eq_f1ap_du_configuration_update(&orig, &decoded); + AssertFatal(ret, "eq_f1ap_setup_request(): decoded message doesn't match\n"); + free_f1ap_du_configuration_update(&decoded); + + f1ap_gnb_du_configuration_update_t cp = cp_f1ap_du_configuration_update(&orig); + ret = eq_f1ap_du_configuration_update(&orig, &cp); + AssertFatal(ret, "eq_f1ap_setup_request(): copied message doesn't match\n"); + free_f1ap_du_configuration_update(&cp); + free_f1ap_du_configuration_update(&orig); +} + +/** + * @brief Test F1 gNB-DU Configuration Update Acknowledge + */ +static void test_f1ap_du_configuration_update_acknowledge(void) +{ + // Create message + f1ap_gnb_du_configuration_update_acknowledge_t orig = { + .transaction_id = 5, + .num_cells_to_activate = 1, + .cells_to_activate = {{ + .nr_cellid = 987654321, + .nrpci = 50, + .plmn = {.mcc = 001, .mnc = 01, .mnc_digit_length = 2}, + .num_SI = 1, + .SI_msg = {{ + .SI_type = 7, + .SI_container_length = 10, + .SI_container = malloc(sizeof(uint8_t) * 10), + }}, + }}, + }; + for (int i = 0; i < orig.cells_to_activate[0].SI_msg[0].SI_container_length; i++) { + orig.cells_to_activate[0].SI_msg[0].SI_container[i] = i; + } + // ASN.1 enc/dec + F1AP_F1AP_PDU_t *f1enc = encode_f1ap_du_configuration_update_acknowledge(&orig); + F1AP_F1AP_PDU_t *f1dec = f1ap_encode_decode(f1enc); + f1ap_msg_free(f1enc); + // Decoding + f1ap_gnb_du_configuration_update_acknowledge_t decoded = {0}; + bool ret = decode_f1ap_du_configuration_update_acknowledge(f1dec, &decoded); + AssertFatal(ret, "decode_f1ap_du_configuration_update_acknowledge(): could not decode message\n"); + f1ap_msg_free(f1dec); + // Equality check + ret = eq_f1ap_du_configuration_update_acknowledge(&orig, &decoded); + AssertFatal(ret, "eq_f1ap_du_configuration_update_acknowledge(): decoded message doesn't match\n"); + free_f1ap_du_configuration_update_acknowledge(&decoded); + // Deep copy + f1ap_gnb_du_configuration_update_acknowledge_t cp = cp_f1ap_du_configuration_update_acknowledge(&orig); + ret = eq_f1ap_du_configuration_update_acknowledge(&orig, &cp); + AssertFatal(ret, "eq_f1ap_du_configuration_update_acknowledge(): copied message doesn't match\n"); + // Free + free_f1ap_du_configuration_update_acknowledge(&cp); + free_f1ap_du_configuration_update_acknowledge(&orig); +} + +/** + * @brief Test F1 gNB-CU Configuration Update + */ +static void test_f1ap_cu_configuration_update(void) +{ + /* create message */ + f1ap_gnb_cu_configuration_update_t orig = {.transaction_id = 2, + .num_cells_to_activate = 1, + .cells_to_activate = {{.nr_cellid = 123456789, + .nrpci = 100, + .plmn = {.mcc = 001, .mnc = 01, .mnc_digit_length = 2}, + .num_SI = 1, + .SI_msg = {{ + .SI_type = 7, + .SI_container_length = 10, + .SI_container = malloc(sizeof(uint8_t) * 10), + }}}}}; + F1AP_F1AP_PDU_t *f1enc = encode_f1ap_cu_configuration_update(&orig); + F1AP_F1AP_PDU_t *f1dec = f1ap_encode_decode(f1enc); + f1ap_msg_free(f1enc); + + f1ap_gnb_cu_configuration_update_t decoded = {0}; + bool ret = decode_f1ap_cu_configuration_update(f1dec, &decoded); + AssertFatal(ret, "decode_f1ap_setup_request(): could not decode message\n"); + f1ap_msg_free(f1dec); + + ret = eq_f1ap_cu_configuration_update(&orig, &decoded); + AssertFatal(ret, "eq_f1ap_setup_request(): decoded message doesn't match\n"); + free_f1ap_cu_configuration_update(&decoded); + + f1ap_gnb_cu_configuration_update_t cp = cp_f1ap_cu_configuration_update(&orig); + ret = eq_f1ap_cu_configuration_update(&orig, &cp); + AssertFatal(ret, "eq_f1ap_setup_request(): copied message doesn't match\n"); + free_f1ap_cu_configuration_update(&cp); + free_f1ap_cu_configuration_update(&orig); +} + +/** + * @brief Test F1 gNB-CU Configuration Update Acknowledge + */ +static void test_f1ap_cu_configuration_update_acknowledge(void) +{ + // Create the original message + f1ap_gnb_cu_configuration_update_acknowledge_t orig = { + .transaction_id = 2, + .num_cells_failed_to_be_activated = 1, + .cells_failed_to_be_activated = {{.nr_cellid = 123456789, + .plmn = {.mcc = 001, .mnc = 01, .mnc_digit_length = 2}, + .cause = F1AP_CAUSE_RADIO_NETWORK}} + }; + // F1AP Enc/dec + F1AP_F1AP_PDU_t *f1enc = encode_f1ap_cu_configuration_update_acknowledge(&orig); + F1AP_F1AP_PDU_t *f1dec = f1ap_encode_decode(f1enc); + f1ap_msg_free(f1enc); + // Decoding + f1ap_gnb_cu_configuration_update_acknowledge_t decoded = {0}; + bool ret = decode_f1ap_cu_configuration_update_acknowledge(f1dec, &decoded); + AssertFatal(ret, "decode_f1ap_cu_configuration_update_acknowledge(): could not decode message\n"); + f1ap_msg_free(f1dec); + // Equality check + ret = eq_f1ap_cu_configuration_update_acknowledge(&orig, &decoded); + AssertFatal(ret, "eq_f1ap_cu_configuration_update_acknowledge(): decoded message doesn't match\n"); + // No free needed + // Deep copy + f1ap_gnb_cu_configuration_update_acknowledge_t cp = cp_f1ap_cu_configuration_update_acknowledge(&orig); + // Equality check + ret = eq_f1ap_cu_configuration_update_acknowledge(&orig, &cp); + AssertFatal(ret, "eq_f1ap_cu_configuration_update_acknowledge(): copied message doesn't match\n"); + // No free needed +} + +int main() +{ + test_initial_ul_rrc_message_transfer(); + test_dl_rrc_message_transfer(); + test_ul_rrc_message_transfer(); + test_f1ap_setup_request(); + test_f1ap_setup_response(); + test_f1ap_setup_failure(); + test_f1ap_du_configuration_update(); + test_f1ap_cu_configuration_update(); + test_f1ap_cu_configuration_update_acknowledge(); + test_f1ap_du_configuration_update_acknowledge(); + return 0; +} diff --git a/openair2/GNB_APP/gnb_app.c b/openair2/GNB_APP/gnb_app.c index 39946c95f1..0e7e25e2c0 100644 --- a/openair2/GNB_APP/gnb_app.c +++ b/openair2/GNB_APP/gnb_app.c @@ -236,10 +236,10 @@ void *gNB_app_task(void *args_p) case F1AP_GNB_CU_CONFIGURATION_UPDATE: 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); - + LOG_I(GNB_APP, + "Received %s: associated with %d cells to activate\n", + ITTI_MSG_NAME(msg_p), + F1AP_GNB_CU_CONFIGURATION_UPDATE(msg_p).num_cells_to_activate); cell_to_activate += F1AP_GNB_CU_CONFIGURATION_UPDATE(msg_p).num_cells_to_activate; gNB_app_handle_f1ap_gnb_cu_configuration_update(&F1AP_GNB_CU_CONFIGURATION_UPDATE(msg_p)); @@ -247,6 +247,11 @@ void *gNB_app_task(void *args_p) AssertFatal(cell_to_activate == 1,"No cells to activate or cells > 1 %d\n",cell_to_activate); break; + + case F1AP_GNB_DU_CONFIGURATION_UPDATE_ACKNOWLEDGE: + LOG_E(GNB_APP, "[gNB %ld] Handling of %s message not implemented yet\n", instance, msg_name); + break; + case NGAP_DEREGISTERED_GNB_IND: LOG_W(GNB_APP, "[gNB %ld] Received %s: associated AMF %d\n", instance, msg_name, NGAP_DEREGISTERED_GNB_IND(msg_p).nb_amf); diff --git a/openair2/GNB_APP/gnb_config.c b/openair2/GNB_APP/gnb_config.c index d1ed728f35..a528835b03 100644 --- a/openair2/GNB_APP/gnb_config.c +++ b/openair2/GNB_APP/gnb_config.c @@ -27,202 +27,123 @@ EMAIL : Lionel.Gauthier@eurecom.fr, navid.nikaein@eurecom.fr, kroempa@gmail.com */ -#include -#include - -#include "common/utils/LOG/log.h" -#include "common/utils/nr/nr_common.h" -#include "assertions.h" -#include "oai_asn1.h" #include "executables/softmodem-common.h" #include "gnb_config.h" -#include "gnb_paramdef.h" #include "enb_paramdef.h" #include "UTIL/OTG/otg.h" -#include "UTIL/OTG/otg_externs.h" -#include "intertask_interface.h" -#include "ngap_gNB.h" -#include "sctp_eNB_task.h" #include "sctp_default_values.h" -#include "F1AP_CauseRadioNetwork.h" #include "f1ap_common.h" -// #include "SystemInformationBlockType2.h" -// #include "LAYER2/MAC/extern.h" -// #include "LAYER2/MAC/proto.h" #include "PHY/INIT/nr_phy_init.h" #include "radio/ETHERNET/ethernet_lib.h" #include "nfapi_vnf.h" #include "nfapi_pnf.h" -#include "nr_pdcp/nr_pdcp_oai_api.h" - -//#include "L1_paramdef.h" #include "prs_nr_paramdef.h" #include "L1_nr_paramdef.h" #include "MACRLC_nr_paramdef.h" -#include "common/config/config_userapi.h" -//#include "RRC_config_tools.h" #include "gnb_paramdef.h" #include "NR_MAC_gNB/mac_proto.h" -#include - -#include "NR_asn_constant.h" -#include "executables/thread-common.h" -#include "NR_SCS-SpecificCarrier.h" -#include "NR_TDD-UL-DL-ConfigCommon.h" -#include "NR_FrequencyInfoUL.h" -#include "NR_RACH-ConfigGeneric.h" -#include "NR_RACH-ConfigCommon.h" -#include "NR_PUSCH-TimeDomainResourceAllocation.h" -#include "NR_PUSCH-ConfigCommon.h" -#include "NR_PUCCH-ConfigCommon.h" -#include "NR_PDSCH-TimeDomainResourceAllocation.h" -#include "NR_PDSCH-ConfigCommon.h" -#include "NR_RateMatchPattern.h" -#include "NR_RateMatchPatternLTE-CRS.h" -#include "NR_SearchSpace.h" -#include "NR_ControlResourceSet.h" -#include "NR_MeasurementTimingConfiguration.h" -#include "NR_EUTRA-MBSFN-SubframeConfig.h" -#include "uper_decoder.h" -#include "uper_encoder.h" -#include "common/utils/ds/seq_arr.h" - -#include "RRC/NR/MESSAGES/asn1_msg.h" #include "RRC/NR/nr_rrc_extern.h" -#include "openair2/LAYER2/nr_pdcp/nr_pdcp.h" #include "nfapi/oai_integration/vendor_ext.h" #ifdef ENABLE_AERIAL #include "nfapi/oai_integration/aerial/fapi_vnf_p5.h" #endif +#include "lib/f1ap_interface_management.h" -extern uint16_t sf_ahead; +/** + * @brief Helper define to allocate and initialize SetupRelease structures + */ +#define INIT_SETUP_RELEASE(type, element) \ + do { \ + element = calloc_or_fail(1, sizeof(*element)); \ + (element)->present = NR_SetupRelease_##type##_PR_setup; \ + (element)->choice.setup = CALLOC(1, sizeof(*((element)->choice.setup))); \ + } while (0) -void prepare_scc(NR_ServingCellConfigCommon_t *scc) { +/** + * Allocate memory and initialize ServingCellConfigCommon struct members + */ +void prepare_scc(NR_ServingCellConfigCommon_t *scc) +{ + // NR_ServingCellConfigCommon + scc->physCellId = calloc_or_fail(1, sizeof(*scc->physCellId)); + scc->n_TimingAdvanceOffset = calloc_or_fail(1, sizeof(*scc->n_TimingAdvanceOffset)); + scc->ssb_PositionsInBurst = calloc_or_fail(1, sizeof(*scc->ssb_PositionsInBurst)); + scc->ssb_periodicityServingCell = calloc_or_fail(1, sizeof(*scc->ssb_periodicityServingCell)); + scc->ssbSubcarrierSpacing = calloc_or_fail(1, sizeof(*scc->ssbSubcarrierSpacing)); + scc->tdd_UL_DL_ConfigurationCommon = calloc_or_fail(1, sizeof(*scc->tdd_UL_DL_ConfigurationCommon)); + scc->tdd_UL_DL_ConfigurationCommon->pattern2 = calloc_or_fail(1, sizeof(*scc->tdd_UL_DL_ConfigurationCommon->pattern2)); + scc->downlinkConfigCommon = calloc_or_fail(1, sizeof(*scc->downlinkConfigCommon)); + scc->downlinkConfigCommon->frequencyInfoDL = calloc_or_fail(1, sizeof(*scc->downlinkConfigCommon->frequencyInfoDL)); + scc->downlinkConfigCommon->initialDownlinkBWP = calloc_or_fail(1, sizeof(*scc->downlinkConfigCommon->initialDownlinkBWP)); - NR_FreqBandIndicatorNR_t *dl_frequencyBandList,*ul_frequencyBandList; - struct NR_SCS_SpecificCarrier *dl_scs_SpecificCarrierList,*ul_scs_SpecificCarrierList; - // struct NR_RateMatchPattern *ratematchpattern; - // NR_RateMatchPatternId_t *ratematchpatternid; - // NR_TCI_StateId_t *TCI_StateId; - // struct NR_ControlResourceSet *bwp_dl_controlresourceset; - // NR_SearchSpace_t *bwp_dl_searchspace; + NR_FrequencyInfoDL_t *frequencyInfoDL = scc->downlinkConfigCommon->frequencyInfoDL; + frequencyInfoDL->absoluteFrequencySSB = calloc_or_fail(1, sizeof(*frequencyInfoDL->absoluteFrequencySSB)); + NR_FreqBandIndicatorNR_t *dl_frequencyBandList = calloc_or_fail(1, sizeof(*dl_frequencyBandList)); + asn1cSeqAdd(&frequencyInfoDL->frequencyBandList.list, dl_frequencyBandList); + struct NR_SCS_SpecificCarrier *dl_scs_SpecificCarrierList = calloc_or_fail(1, sizeof(*dl_scs_SpecificCarrierList)); + asn1cSeqAdd(&frequencyInfoDL->scs_SpecificCarrierList.list, dl_scs_SpecificCarrierList); - scc->physCellId = CALLOC(1,sizeof(NR_PhysCellId_t)); - scc->downlinkConfigCommon = CALLOC(1,sizeof(struct NR_DownlinkConfigCommon)); - scc->downlinkConfigCommon->frequencyInfoDL = CALLOC(1,sizeof(struct NR_FrequencyInfoDL)); - scc->downlinkConfigCommon->initialDownlinkBWP = CALLOC(1,sizeof(struct NR_BWP_DownlinkCommon)); - scc->uplinkConfigCommon = CALLOC(1,sizeof(struct NR_UplinkConfigCommon)); - scc->uplinkConfigCommon->frequencyInfoUL = CALLOC(1,sizeof(struct NR_FrequencyInfoUL)); - scc->uplinkConfigCommon->initialUplinkBWP = CALLOC(1,sizeof(struct NR_BWP_UplinkCommon)); - //scc->supplementaryUplinkConfig = CALLOC(1,sizeof(struct NR_UplinkConfigCommon)); - scc->n_TimingAdvanceOffset = CALLOC(1, sizeof(long)); - scc->ssb_PositionsInBurst = CALLOC(1,sizeof(struct NR_ServingCellConfigCommon__ssb_PositionsInBurst)); - scc->ssb_periodicityServingCell = CALLOC(1,sizeof(long)); - // scc->rateMatchPatternToAddModList = CALLOC(1,sizeof(struct NR_ServingCellConfigCommon__rateMatchPatternToAddModList)); - // scc->rateMatchPatternToReleaseList = CALLOC(1,sizeof(struct NR_ServingCellConfigCommon__rateMatchPatternToReleaseList)); - scc->ssbSubcarrierSpacing = CALLOC(1,sizeof(NR_SubcarrierSpacing_t)); - scc->tdd_UL_DL_ConfigurationCommon = CALLOC(1,sizeof(struct NR_TDD_UL_DL_ConfigCommon)); - scc->tdd_UL_DL_ConfigurationCommon->pattern2 = CALLOC(1,sizeof(struct NR_TDD_UL_DL_Pattern)); - - scc->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencySSB = CALLOC(1,sizeof(NR_ARFCN_ValueNR_t)); - - dl_frequencyBandList = CALLOC(1,sizeof(NR_FreqBandIndicatorNR_t)); - dl_scs_SpecificCarrierList = CALLOC(1,sizeof(struct NR_SCS_SpecificCarrier)); + INIT_SETUP_RELEASE(PDCCH_ConfigCommon, scc->downlinkConfigCommon->initialDownlinkBWP->pdcch_ConfigCommon); + NR_SetupRelease_PDCCH_ConfigCommon_t *pdcch_ConfigCommon = scc->downlinkConfigCommon->initialDownlinkBWP->pdcch_ConfigCommon; + struct NR_PDCCH_ConfigCommon *pdcchCCSetup = pdcch_ConfigCommon->choice.setup; + pdcchCCSetup->controlResourceSetZero = calloc_or_fail(1, sizeof(*pdcchCCSetup->controlResourceSetZero)); + pdcchCCSetup->searchSpaceZero = calloc_or_fail(1, sizeof(*pdcchCCSetup->searchSpaceZero)); + pdcchCCSetup->commonControlResourceSet = NULL; - asn1cSeqAdd(&scc->downlinkConfigCommon->frequencyInfoDL->frequencyBandList.list,dl_frequencyBandList); - asn1cSeqAdd(&scc->downlinkConfigCommon->frequencyInfoDL->scs_SpecificCarrierList.list,dl_scs_SpecificCarrierList); - // scc->downlinkConfigCommon->initialDownlinkBWP->genericParameters.cyclicPrefix = CALLOC(1,sizeof(long)); - scc->downlinkConfigCommon->initialDownlinkBWP->pdcch_ConfigCommon = CALLOC(1,sizeof(struct NR_SetupRelease_PDCCH_ConfigCommon)); - scc->downlinkConfigCommon->initialDownlinkBWP->pdcch_ConfigCommon->present=NR_SetupRelease_PDCCH_ConfigCommon_PR_setup; - scc->downlinkConfigCommon->initialDownlinkBWP->pdcch_ConfigCommon->choice.setup = CALLOC(1,sizeof(struct NR_PDCCH_ConfigCommon)); - scc->downlinkConfigCommon->initialDownlinkBWP->pdcch_ConfigCommon->choice.setup->controlResourceSetZero = CALLOC(1,sizeof(long)); - scc->downlinkConfigCommon->initialDownlinkBWP->pdcch_ConfigCommon->choice.setup->searchSpaceZero = CALLOC(1,sizeof(long)); + INIT_SETUP_RELEASE(PDSCH_ConfigCommon, scc->downlinkConfigCommon->initialDownlinkBWP->pdsch_ConfigCommon); + NR_SetupRelease_PDSCH_ConfigCommon_t *pdsch_ConfigCommon = scc->downlinkConfigCommon->initialDownlinkBWP->pdsch_ConfigCommon; + pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList = + calloc_or_fail(1, sizeof(*pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList)); - scc->downlinkConfigCommon->initialDownlinkBWP->pdcch_ConfigCommon->choice.setup->commonControlResourceSet = NULL; + scc->uplinkConfigCommon = calloc_or_fail(1, sizeof(*scc->uplinkConfigCommon)); + scc->uplinkConfigCommon->frequencyInfoUL = calloc_or_fail(1, sizeof(*scc->uplinkConfigCommon->frequencyInfoUL)); + scc->uplinkConfigCommon->initialUplinkBWP = calloc_or_fail(1, sizeof(*scc->uplinkConfigCommon->initialUplinkBWP)); - // scc->downlinkConfigCommon->initialDownlinkBWP->pdcch_ConfigCommon->choice.setup->commonSearchSpaceList = CALLOC(1,sizeof(struct NR_PDCCH_ConfigCommon__commonSearchSpaceList)); - // scc->downlinkConfigCommon->initialDownlinkBWP->pdcch_ConfigCommon->choice.setup->searchSpaceSIB1 = CALLOC(1,sizeof(NR_SearchSpaceId_t)); - // scc->downlinkConfigCommon->initialDownlinkBWP->pdcch_ConfigCommon->choice.setup->searchSpaceOtherSystemInformation = CALLOC(1,sizeof(NR_SearchSpaceId_t)); - // scc->downlinkConfigCommon->initialDownlinkBWP->pdcch_ConfigCommon->choice.setup->pagingSearchSpace = CALLOC(1,sizeof(NR_SearchSpaceId_t)); - // scc->downlinkConfigCommon->initialDownlinkBWP->pdcch_ConfigCommon->choice.setup->ra_SearchSpace = CALLOC(1,sizeof(NR_SearchSpaceId_t)); - scc->downlinkConfigCommon->initialDownlinkBWP->pdsch_ConfigCommon = CALLOC(1,sizeof(struct NR_SetupRelease_PDSCH_ConfigCommon)); - scc->downlinkConfigCommon->initialDownlinkBWP->pdsch_ConfigCommon->present = NR_SetupRelease_PDSCH_ConfigCommon_PR_setup; - scc->downlinkConfigCommon->initialDownlinkBWP->pdsch_ConfigCommon->choice.setup = CALLOC(1,sizeof(struct NR_PDSCH_ConfigCommon)); - scc->downlinkConfigCommon->initialDownlinkBWP->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList = CALLOC(1,sizeof(struct NR_PDSCH_TimeDomainResourceAllocationList)); + NR_FrequencyInfoUL_t *frequencyInfoUL = scc->uplinkConfigCommon->frequencyInfoUL; + NR_FreqBandIndicatorNR_t *ul_frequencyBandList = calloc_or_fail(1, sizeof(*ul_frequencyBandList)); + frequencyInfoUL->frequencyBandList = calloc_or_fail(1, sizeof(*frequencyInfoUL->frequencyBandList)); + asn1cSeqAdd(&frequencyInfoUL->frequencyBandList->list, ul_frequencyBandList); + frequencyInfoUL->absoluteFrequencyPointA = calloc_or_fail(1, sizeof(*frequencyInfoUL->absoluteFrequencyPointA)); + frequencyInfoUL->p_Max = calloc_or_fail(1, sizeof(*frequencyInfoUL->p_Max)); - ul_frequencyBandList = CALLOC(1,sizeof(NR_FreqBandIndicatorNR_t)); - scc->uplinkConfigCommon->frequencyInfoUL->frequencyBandList = CALLOC(1,sizeof(struct NR_MultiFrequencyBandListNR)); - asn1cSeqAdd(&scc->uplinkConfigCommon->frequencyInfoUL->frequencyBandList->list,ul_frequencyBandList); + struct NR_SCS_SpecificCarrier *ul_scs_SpecificCarrierList = calloc_or_fail(1, sizeof(*ul_scs_SpecificCarrierList)); + asn1cSeqAdd(&frequencyInfoUL->scs_SpecificCarrierList.list, ul_scs_SpecificCarrierList); - scc->uplinkConfigCommon->frequencyInfoUL->absoluteFrequencyPointA = CALLOC(1,sizeof(NR_ARFCN_ValueNR_t)); - // scc->uplinkConfigCommon->frequencyInfoUL->additionalSpectrumEmission = CALLOC(1,sizeof(NR_AdditionalSpectrumEmission_t)); - scc->uplinkConfigCommon->frequencyInfoUL->p_Max = CALLOC(1,sizeof(NR_P_Max_t)); - // scc->uplinkConfigCommon->frequencyInfoUL->frequencyShift7p5khz = CALLOC(1,sizeof(long)); - - // scc->uplinkConfigCommon->initialUplinkBWP->genericParameters.cyclicPrefix = CALLOC(1,sizeof(long)); - scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon = CALLOC(1,sizeof(NR_SetupRelease_RACH_ConfigCommon_t)); - scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->present = NR_SetupRelease_RACH_ConfigCommon_PR_setup; - scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup = CALLOC(1,sizeof(struct NR_RACH_ConfigCommon)); - // scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->totalNumberOfRA_Preambles = CALLOC(1,sizeof(long)); - scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->ssb_perRACH_OccasionAndCB_PreamblesPerSSB = CALLOC(1,sizeof(struct NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB)); - // scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->groupBconfigured = CALLOC(1,sizeof(struct NR_RACH_ConfigCommon__groupBconfigured)); - scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->rsrp_ThresholdSSB = CALLOC(1,sizeof(NR_RSRP_Range_t)); - // scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->rsrp_ThresholdSSB_SUL = CALLOC(1,sizeof(NR_RSRP_Range_t)); - scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->msg1_SubcarrierSpacing = CALLOC(1,sizeof(NR_SubcarrierSpacing_t)); - scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->msg3_transformPrecoder = CALLOC(1,sizeof(long)); - // 0 - ENABLE, 1 - DISABLE, hence explicitly setting to DISABLED. - *scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->msg3_transformPrecoder = NR_PUSCH_Config__transformPrecoder_disabled; - scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon = CALLOC(1,sizeof(NR_SetupRelease_PUSCH_ConfigCommon_t)); - scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->present = NR_SetupRelease_PUSCH_ConfigCommon_PR_setup; - scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->choice.setup = CALLOC(1,sizeof(struct NR_PUSCH_ConfigCommon)); + INIT_SETUP_RELEASE(RACH_ConfigCommon, scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon); + NR_SetupRelease_RACH_ConfigCommon_t *rach_ConfigCommon = scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon; + struct NR_RACH_ConfigCommon *rachCCSetup = rach_ConfigCommon->choice.setup; + rachCCSetup->ssb_perRACH_OccasionAndCB_PreamblesPerSSB = + calloc_or_fail(1, sizeof(*rachCCSetup->ssb_perRACH_OccasionAndCB_PreamblesPerSSB)); + rachCCSetup->rsrp_ThresholdSSB = calloc_or_fail(1, sizeof(*rachCCSetup->rsrp_ThresholdSSB)); + rachCCSetup->msg1_SubcarrierSpacing = calloc_or_fail(1, sizeof(*rachCCSetup->msg1_SubcarrierSpacing)); + rachCCSetup->msg3_transformPrecoder = calloc_or_fail(1, sizeof(*rachCCSetup->msg3_transformPrecoder)); + *rachCCSetup->msg3_transformPrecoder = NR_PUSCH_Config__transformPrecoder_disabled; - scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->choice.setup->groupHoppingEnabledTransformPrecoding = NULL; - - scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList = CALLOC(1,sizeof(struct NR_PUSCH_TimeDomainResourceAllocationList)); - scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->choice.setup->msg3_DeltaPreamble = CALLOC(1,sizeof(long)); - scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->choice.setup->p0_NominalWithGrant = CALLOC(1,sizeof(long)); - - scc->uplinkConfigCommon->initialUplinkBWP->pucch_ConfigCommon = CALLOC(1,sizeof(struct NR_SetupRelease_PUCCH_ConfigCommon)); - scc->uplinkConfigCommon->initialUplinkBWP->pucch_ConfigCommon->present= NR_SetupRelease_PUCCH_ConfigCommon_PR_setup; - scc->uplinkConfigCommon->initialUplinkBWP->pucch_ConfigCommon->choice.setup = CALLOC(1,sizeof(struct NR_PUCCH_ConfigCommon)); - scc->uplinkConfigCommon->initialUplinkBWP->pucch_ConfigCommon->choice.setup->p0_nominal = CALLOC(1,sizeof(long)); - scc->uplinkConfigCommon->initialUplinkBWP->pucch_ConfigCommon->choice.setup->pucch_ResourceCommon = CALLOC(1,sizeof(long)); - scc->uplinkConfigCommon->initialUplinkBWP->pucch_ConfigCommon->choice.setup->hoppingId = CALLOC(1,sizeof(long)); + INIT_SETUP_RELEASE(PUSCH_ConfigCommon, scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon); + NR_SetupRelease_PUSCH_ConfigCommon_t *pusch_ConfigCommon = scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon; + struct NR_PUSCH_ConfigCommon *puschCCSetup = pusch_ConfigCommon->choice.setup; + puschCCSetup->groupHoppingEnabledTransformPrecoding = NULL; + puschCCSetup->pusch_TimeDomainAllocationList = calloc_or_fail(1, sizeof(*puschCCSetup->pusch_TimeDomainAllocationList)); + puschCCSetup->msg3_DeltaPreamble = calloc_or_fail(1, sizeof(*puschCCSetup->msg3_DeltaPreamble)); + puschCCSetup->p0_NominalWithGrant = calloc_or_fail(1, sizeof(*puschCCSetup->p0_NominalWithGrant)); - // scc->ssb_PositionsInBurst->choice.shortBitmap.buf = MALLOC(1); - // scc->ssb_PositionsInBurst->choice.mediumBitmap.buf = MALLOC(1); - // scc->ssb_PositionsInBurst->choice.longBitmap.buf = MALLOC(8); - + INIT_SETUP_RELEASE(PUCCH_ConfigCommon, scc->uplinkConfigCommon->initialUplinkBWP->pucch_ConfigCommon); + NR_SetupRelease_PUCCH_ConfigCommon_t *pucch_ConfigCommon = scc->uplinkConfigCommon->initialUplinkBWP->pucch_ConfigCommon; + struct NR_PUCCH_ConfigCommon *pucchCCSetup = pucch_ConfigCommon->choice.setup; + pucchCCSetup->p0_nominal = calloc_or_fail(1, sizeof(*pucchCCSetup->p0_nominal)); + pucchCCSetup->pucch_ResourceCommon = calloc_or_fail(1, sizeof(*pucchCCSetup->pucch_ResourceCommon)); + pucchCCSetup->hoppingId = calloc_or_fail(1, sizeof(*pucchCCSetup->hoppingId)); - ul_scs_SpecificCarrierList = CALLOC(1,sizeof(struct NR_SCS_SpecificCarrier)); - asn1cSeqAdd(&scc->uplinkConfigCommon->frequencyInfoUL->scs_SpecificCarrierList.list,ul_scs_SpecificCarrierList); + scc->ext2 = calloc_or_fail(1, sizeof(*scc->ext2)); + scc->ext2->ntn_Config_r17 = calloc_or_fail(1, sizeof(*scc->ext2->ntn_Config_r17)); + scc->ext2->ntn_Config_r17->cellSpecificKoffset_r17 = calloc_or_fail(1, sizeof(*scc->ext2->ntn_Config_r17->cellSpecificKoffset_r17)); - //ratematchpattern = CALLOC(1,sizeof(struct NR_RateMatchPattern)); - //ratematchpattern->patternType.choice.bitmaps = CALLOC(1,sizeof(struct NR_RateMatchPattern__patternType__bitmaps)); - //ratematchpattern->patternType.choice.bitmaps->resourceBlocks.buf = MALLOC(35); - //ratematchpattern->patternType.choice.bitmaps->symbolsInResourceBlock.choice.oneSlot.buf = MALLOC(2); - //ratematchpattern->patternType.choice.bitmaps->symbolsInResourceBlock.choice.twoSlots.buf = MALLOC(4); - //ratematchpattern->patternType.choice.bitmaps->periodicityAndPattern = CALLOC(1,sizeof(struct NR_RateMatchPattern__patternType__bitmaps__periodicityAndPattern)); - //ratematchpattern->patternType.choice.bitmaps->periodicityAndPattern->choice.n2.buf = MALLOC(1); - //ratematchpattern->patternType.choice.bitmaps->periodicityAndPattern->choice.n4.buf = MALLOC(1); - //ratematchpattern->patternType.choice.bitmaps->periodicityAndPattern->choice.n5.buf = MALLOC(1); - //ratematchpattern->patternType.choice.bitmaps->periodicityAndPattern->choice.n8.buf = MALLOC(1); - //ratematchpattern->patternType.choice.bitmaps->periodicityAndPattern->choice.n10.buf = MALLOC(2); - //ratematchpattern->patternType.choice.bitmaps->periodicityAndPattern->choice.n20.buf = MALLOC(3); - //ratematchpattern->patternType.choice.bitmaps->periodicityAndPattern->choice.n40.buf = MALLOC(5); - //ratematchpattern->subcarrierSpacing = CALLOC(1,sizeof(NR_SubcarrierSpacing_t)); - //ratematchpatternid = CALLOC(1,sizeof(NR_RateMatchPatternId_t)); - - scc->ext2 = CALLOC(1, sizeof(*scc->ext2)); - scc->ext2->ntn_Config_r17 = CALLOC(1, sizeof(*scc->ext2->ntn_Config_r17)); - scc->ext2->ntn_Config_r17->cellSpecificKoffset_r17 = CALLOC(1, sizeof(*scc->ext2->ntn_Config_r17->cellSpecificKoffset_r17)); - - scc->ext2->ntn_Config_r17->ephemerisInfo_r17 = CALLOC(1, sizeof(*scc->ext2->ntn_Config_r17->ephemerisInfo_r17)); - scc->ext2->ntn_Config_r17->ta_Info_r17 = CALLOC(1, sizeof(*scc->ext2->ntn_Config_r17->ta_Info_r17)); + scc->ext2->ntn_Config_r17->ephemerisInfo_r17 = calloc_or_fail(1, sizeof(*scc->ext2->ntn_Config_r17->ephemerisInfo_r17)); + scc->ext2->ntn_Config_r17->ta_Info_r17 = calloc_or_fail(1, sizeof(*scc->ext2->ntn_Config_r17->ta_Info_r17)); scc->ext2->ntn_Config_r17->ephemerisInfo_r17->present = NR_EphemerisInfo_r17_PR_positionVelocity_r17; scc->ext2->ntn_Config_r17->ephemerisInfo_r17->choice.positionVelocity_r17 = - CALLOC(1, sizeof(*scc->ext2->ntn_Config_r17->ephemerisInfo_r17->choice.positionVelocity_r17)); + calloc_or_fail(1, sizeof(*scc->ext2->ntn_Config_r17->ephemerisInfo_r17->choice.positionVelocity_r17)); } // Section 4.1 in 38.213 @@ -257,99 +178,128 @@ NR_ServingCellConfigCommon__ssb_PositionsInBurst_PR get_ssb_len(NR_ServingCellCo return NR_ServingCellConfigCommon__ssb_PositionsInBurst_PR_longBitmap; } +static struct NR_SCS_SpecificCarrier configure_scs_carrier(int mu, int N_RB) +{ + struct NR_SCS_SpecificCarrier scs_sc = {0}; + scs_sc.offsetToCarrier = 0; + scs_sc.subcarrierSpacing = mu; + scs_sc.carrierBandwidth = N_RB; + return scs_sc; +} + +static struct NR_PUSCH_TimeDomainResourceAllocation *add_PUSCH_TimeDomainResourceAllocation(int startSymbolAndLength) +{ + struct NR_PUSCH_TimeDomainResourceAllocation *pusch_alloc = calloc_or_fail(1, sizeof(*pusch_alloc)); + pusch_alloc->k2 = calloc_or_fail(1, sizeof(*pusch_alloc->k2)); + *pusch_alloc->k2 = 6; + pusch_alloc->mappingType = NR_PUSCH_TimeDomainResourceAllocation__mappingType_typeB; + pusch_alloc->startSymbolAndLength = startSymbolAndLength; + return pusch_alloc; +} + +/** + * Fill ServingCellConfigCommon struct members for unitary simulators + */ void fill_scc_sim(NR_ServingCellConfigCommon_t *scc, uint64_t *ssb_bitmap, int N_RB_DL, int N_RB_UL, int mu_dl, int mu_ul) { - *scc->physCellId=0; \ - // *scc->n_TimingAdvanceOffset=NR_ServingCellConfigCommon__n_TimingAdvanceOffset_n0; - *scc->ssb_periodicityServingCell=NR_ServingCellConfigCommon__ssb_periodicityServingCell_ms20; - scc->dmrs_TypeA_Position=NR_ServingCellConfigCommon__dmrs_TypeA_Position_pos2; - *scc->ssbSubcarrierSpacing=mu_dl; - if (mu_dl == 0) { - *scc->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencySSB=520432; - *scc->downlinkConfigCommon->frequencyInfoDL->frequencyBandList.list.array[0]=38; - scc->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencyPointA=520000; - } else { - *scc->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencySSB=641032; - *scc->downlinkConfigCommon->frequencyInfoDL->frequencyBandList.list.array[0]=78; - scc->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencyPointA=640000; - } - scc->downlinkConfigCommon->frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->offsetToCarrier=0; - scc->downlinkConfigCommon->frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing=mu_dl; - scc->downlinkConfigCommon->frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->carrierBandwidth=N_RB_DL; - scc->downlinkConfigCommon->initialDownlinkBWP->genericParameters.locationAndBandwidth = - PRBalloc_to_locationandbandwidth(N_RB_DL, 0); - scc->downlinkConfigCommon->initialDownlinkBWP->genericParameters.subcarrierSpacing=mu_dl;//NR_SubcarrierSpacing_kHz30; - *scc->downlinkConfigCommon->initialDownlinkBWP->pdcch_ConfigCommon->choice.setup->controlResourceSetZero=12; - *scc->downlinkConfigCommon->initialDownlinkBWP->pdcch_ConfigCommon->choice.setup->searchSpaceZero=0; - struct NR_PDSCH_TimeDomainResourceAllocation *timedomainresourceallocation0 = CALLOC(1,sizeof(NR_PDSCH_TimeDomainResourceAllocation_t)); - timedomainresourceallocation0->mappingType=NR_PDSCH_TimeDomainResourceAllocation__mappingType_typeA; - timedomainresourceallocation0->startSymbolAndLength=54; - asn1cSeqAdd(&scc->downlinkConfigCommon->initialDownlinkBWP->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList->list, - timedomainresourceallocation0); - struct NR_PDSCH_TimeDomainResourceAllocation *timedomainresourceallocation1 = CALLOC(1,sizeof(NR_PDSCH_TimeDomainResourceAllocation_t)); - timedomainresourceallocation1->mappingType=NR_PDSCH_TimeDomainResourceAllocation__mappingType_typeA; - timedomainresourceallocation1->startSymbolAndLength=57; - asn1cSeqAdd(&scc->downlinkConfigCommon->initialDownlinkBWP->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList->list, - timedomainresourceallocation1); - *scc->uplinkConfigCommon->frequencyInfoUL->frequencyBandList->list.array[0]=mu_ul?78:38; - *scc->uplinkConfigCommon->frequencyInfoUL->absoluteFrequencyPointA=-1; - scc->uplinkConfigCommon->frequencyInfoUL->scs_SpecificCarrierList.list.array[0]->offsetToCarrier=0; - scc->uplinkConfigCommon->frequencyInfoUL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing=mu_ul; - scc->uplinkConfigCommon->frequencyInfoUL->scs_SpecificCarrierList.list.array[0]->carrierBandwidth=N_RB_UL; - *scc->uplinkConfigCommon->frequencyInfoUL->p_Max=20; - scc->uplinkConfigCommon->initialUplinkBWP->genericParameters.locationAndBandwidth = PRBalloc_to_locationandbandwidth(N_RB_UL, 0); - scc->uplinkConfigCommon->initialUplinkBWP->genericParameters.subcarrierSpacing=mu_ul;//NR_SubcarrierSpacing_kHz30; - scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->rach_ConfigGeneric.prach_ConfigurationIndex=98; - scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->rach_ConfigGeneric.msg1_FDM=NR_RACH_ConfigGeneric__msg1_FDM_one; - scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->rach_ConfigGeneric.msg1_FrequencyStart=0; - scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->rach_ConfigGeneric.zeroCorrelationZoneConfig=13; - scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->rach_ConfigGeneric.preambleReceivedTargetPower=-118; - scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->rach_ConfigGeneric.preambleTransMax=NR_RACH_ConfigGeneric__preambleTransMax_n10; - scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->rach_ConfigGeneric.powerRampingStep=NR_RACH_ConfigGeneric__powerRampingStep_dB2; - scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->rach_ConfigGeneric.ra_ResponseWindow=NR_RACH_ConfigGeneric__ra_ResponseWindow_sl20; - scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->ssb_perRACH_OccasionAndCB_PreamblesPerSSB->present=NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_one; - scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->ssb_perRACH_OccasionAndCB_PreamblesPerSSB->choice.one=NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB__one_n64; - scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->ra_ContentionResolutionTimer=NR_RACH_ConfigCommon__ra_ContentionResolutionTimer_sf64; - *scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->rsrp_ThresholdSSB=19; - scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->prach_RootSequenceIndex.present=NR_RACH_ConfigCommon__prach_RootSequenceIndex_PR_l139; - scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->prach_RootSequenceIndex.choice.l139=0; - scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->restrictedSetConfig=NR_RACH_ConfigCommon__restrictedSetConfig_unrestrictedSet; - struct NR_PUSCH_TimeDomainResourceAllocation *pusch_timedomainresourceallocation0 = CALLOC(1,sizeof(struct NR_PUSCH_TimeDomainResourceAllocation)); - pusch_timedomainresourceallocation0->k2 = CALLOC(1,sizeof(long)); - *pusch_timedomainresourceallocation0->k2=6; - pusch_timedomainresourceallocation0->mappingType=NR_PUSCH_TimeDomainResourceAllocation__mappingType_typeB; - pusch_timedomainresourceallocation0->startSymbolAndLength=55; - asn1cSeqAdd(&scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list,pusch_timedomainresourceallocation0); - struct NR_PUSCH_TimeDomainResourceAllocation *pusch_timedomainresourceallocation1 = CALLOC(1,sizeof(struct NR_PUSCH_TimeDomainResourceAllocation)); - pusch_timedomainresourceallocation1->k2 = CALLOC(1,sizeof(long)); - *pusch_timedomainresourceallocation1->k2=6; - pusch_timedomainresourceallocation1->mappingType=NR_PUSCH_TimeDomainResourceAllocation__mappingType_typeB; - pusch_timedomainresourceallocation1->startSymbolAndLength=38; - asn1cSeqAdd(&scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list,pusch_timedomainresourceallocation1); - *scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->choice.setup->msg3_DeltaPreamble=1; - *scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->choice.setup->p0_NominalWithGrant=-90; - scc->uplinkConfigCommon->initialUplinkBWP->pucch_ConfigCommon->choice.setup->pucch_GroupHopping=NR_PUCCH_ConfigCommon__pucch_GroupHopping_neither; - *scc->uplinkConfigCommon->initialUplinkBWP->pucch_ConfigCommon->choice.setup->hoppingId=40; - *scc->uplinkConfigCommon->initialUplinkBWP->pucch_ConfigCommon->choice.setup->p0_nominal=-90; - scc->ssb_PositionsInBurst->present=NR_ServingCellConfigCommon__ssb_PositionsInBurst_PR_mediumBitmap; - *ssb_bitmap=0xff; - scc->tdd_UL_DL_ConfigurationCommon->referenceSubcarrierSpacing=mu_dl; - if (mu_dl == 0) - scc->tdd_UL_DL_ConfigurationCommon->pattern1.dl_UL_TransmissionPeriodicity=NR_TDD_UL_DL_Pattern__dl_UL_TransmissionPeriodicity_ms10; - else - scc->tdd_UL_DL_ConfigurationCommon->pattern1.dl_UL_TransmissionPeriodicity=NR_TDD_UL_DL_Pattern__dl_UL_TransmissionPeriodicity_ms5; - scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofDownlinkSlots=7; - scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofDownlinkSymbols=6; - scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofUplinkSlots=2; - scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofUplinkSymbols=4; - scc->tdd_UL_DL_ConfigurationCommon->pattern2->dl_UL_TransmissionPeriodicity=321; + *scc->physCellId = 0; + *scc->ssb_periodicityServingCell = NR_ServingCellConfigCommon__ssb_periodicityServingCell_ms20; + scc->dmrs_TypeA_Position = NR_ServingCellConfigCommon__dmrs_TypeA_Position_pos2; + *scc->ssbSubcarrierSpacing = mu_dl; - scc->tdd_UL_DL_ConfigurationCommon->pattern2->nrofDownlinkSlots=-1; - scc->tdd_UL_DL_ConfigurationCommon->pattern2->nrofDownlinkSymbols=-1; - scc->tdd_UL_DL_ConfigurationCommon->pattern2->nrofUplinkSlots=-1; - scc->tdd_UL_DL_ConfigurationCommon->pattern2->nrofUplinkSymbols=-1; - scc->ss_PBCH_BlockPower=20; - *scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->msg1_SubcarrierSpacing=-1; + struct NR_FrequencyInfoDL *frequencyInfoDL = scc->downlinkConfigCommon->frequencyInfoDL; + if (mu_dl == 0) { + *frequencyInfoDL->absoluteFrequencySSB = 520432; + *frequencyInfoDL->frequencyBandList.list.array[0] = 38; + frequencyInfoDL->absoluteFrequencyPointA = 520000; + } else { + *frequencyInfoDL->absoluteFrequencySSB = 641032; + *frequencyInfoDL->frequencyBandList.list.array[0] = 78; + frequencyInfoDL->absoluteFrequencyPointA = 640000; + } + + *frequencyInfoDL->scs_SpecificCarrierList.list.array[0] = configure_scs_carrier(mu_dl, N_RB_DL); + struct NR_BWP_DownlinkCommon *initialDownlinkBWP = scc->downlinkConfigCommon->initialDownlinkBWP; + + initialDownlinkBWP->genericParameters.locationAndBandwidth = PRBalloc_to_locationandbandwidth(N_RB_DL, 0); + initialDownlinkBWP->genericParameters.subcarrierSpacing = mu_dl; + *initialDownlinkBWP->pdcch_ConfigCommon->choice.setup->controlResourceSetZero = 12; + *initialDownlinkBWP->pdcch_ConfigCommon->choice.setup->searchSpaceZero = 0; + struct NR_PDSCH_TimeDomainResourceAllocation *timedomainresourceallocation0 = + calloc_or_fail(1, sizeof(*timedomainresourceallocation0)); + timedomainresourceallocation0->mappingType=NR_PDSCH_TimeDomainResourceAllocation__mappingType_typeA; + timedomainresourceallocation0->startSymbolAndLength = 54; + asn1cSeqAdd(&initialDownlinkBWP->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList->list, + timedomainresourceallocation0); + struct NR_PDSCH_TimeDomainResourceAllocation *timedomainresourceallocation1 = + calloc_or_fail(1, sizeof(*timedomainresourceallocation1)); + timedomainresourceallocation1->mappingType = NR_PDSCH_TimeDomainResourceAllocation__mappingType_typeA; + timedomainresourceallocation1->startSymbolAndLength = 57; + asn1cSeqAdd(&initialDownlinkBWP->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList->list, + timedomainresourceallocation1); + + struct NR_FrequencyInfoUL *frequencyInfoUL = scc->uplinkConfigCommon->frequencyInfoUL; + *frequencyInfoUL->frequencyBandList->list.array[0] = mu_ul ? 78 : 38; + *frequencyInfoUL->absoluteFrequencyPointA = -1; + *frequencyInfoUL->scs_SpecificCarrierList.list.array[0] = configure_scs_carrier(mu_ul, N_RB_UL); + *frequencyInfoUL->p_Max = 20; + + struct NR_BWP_UplinkCommon *initialUplinkBWP = scc->uplinkConfigCommon->initialUplinkBWP; + initialUplinkBWP->genericParameters.locationAndBandwidth = PRBalloc_to_locationandbandwidth(N_RB_UL, 0); + initialUplinkBWP->genericParameters.subcarrierSpacing = mu_ul; + + struct NR_SetupRelease_RACH_ConfigCommon *rach_ConfigCommon = initialUplinkBWP->rach_ConfigCommon; + rach_ConfigCommon->choice.setup->rach_ConfigGeneric.prach_ConfigurationIndex = 98; + rach_ConfigCommon->choice.setup->rach_ConfigGeneric.msg1_FDM = NR_RACH_ConfigGeneric__msg1_FDM_one; + rach_ConfigCommon->choice.setup->rach_ConfigGeneric.msg1_FrequencyStart = 0; + rach_ConfigCommon->choice.setup->rach_ConfigGeneric.zeroCorrelationZoneConfig = 13; + rach_ConfigCommon->choice.setup->rach_ConfigGeneric.preambleReceivedTargetPower = -118; + rach_ConfigCommon->choice.setup->rach_ConfigGeneric.preambleTransMax = NR_RACH_ConfigGeneric__preambleTransMax_n10; + rach_ConfigCommon->choice.setup->rach_ConfigGeneric.powerRampingStep = NR_RACH_ConfigGeneric__powerRampingStep_dB2; + rach_ConfigCommon->choice.setup->rach_ConfigGeneric.ra_ResponseWindow = NR_RACH_ConfigGeneric__ra_ResponseWindow_sl20; + rach_ConfigCommon->choice.setup->ssb_perRACH_OccasionAndCB_PreamblesPerSSB->present = + NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_one; + rach_ConfigCommon->choice.setup->ssb_perRACH_OccasionAndCB_PreamblesPerSSB->choice.one = + NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB__one_n64; + rach_ConfigCommon->choice.setup->ra_ContentionResolutionTimer = NR_RACH_ConfigCommon__ra_ContentionResolutionTimer_sf64; + *rach_ConfigCommon->choice.setup->rsrp_ThresholdSSB = 19; + rach_ConfigCommon->choice.setup->prach_RootSequenceIndex.present = NR_RACH_ConfigCommon__prach_RootSequenceIndex_PR_l139; + rach_ConfigCommon->choice.setup->prach_RootSequenceIndex.choice.l139 = 0; + rach_ConfigCommon->choice.setup->restrictedSetConfig = NR_RACH_ConfigCommon__restrictedSetConfig_unrestrictedSet; + *rach_ConfigCommon->choice.setup->msg1_SubcarrierSpacing = -1; + struct NR_SetupRelease_PUSCH_ConfigCommon *pusch_ConfigCommon = initialUplinkBWP->pusch_ConfigCommon; + + asn1cSeqAdd(&pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list, add_PUSCH_TimeDomainResourceAllocation(55)); + asn1cSeqAdd(&pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list, add_PUSCH_TimeDomainResourceAllocation(38)); + + *pusch_ConfigCommon->choice.setup->msg3_DeltaPreamble = 1; + *pusch_ConfigCommon->choice.setup->p0_NominalWithGrant = -90; + struct NR_SetupRelease_PUCCH_ConfigCommon *pucch_ConfigCommon = initialUplinkBWP->pucch_ConfigCommon; + pucch_ConfigCommon->choice.setup->pucch_GroupHopping = NR_PUCCH_ConfigCommon__pucch_GroupHopping_neither; + *pucch_ConfigCommon->choice.setup->hoppingId = 40; + *pucch_ConfigCommon->choice.setup->p0_nominal = -90; + scc->ssb_PositionsInBurst->present = NR_ServingCellConfigCommon__ssb_PositionsInBurst_PR_mediumBitmap; + *ssb_bitmap = 0xff; + + struct NR_TDD_UL_DL_ConfigCommon *tdd_UL_DL_ConfigurationCommon = scc->tdd_UL_DL_ConfigurationCommon; + tdd_UL_DL_ConfigurationCommon->referenceSubcarrierSpacing = mu_dl; + + NR_TDD_UL_DL_Pattern_t *p1 = &tdd_UL_DL_ConfigurationCommon->pattern1; + p1->dl_UL_TransmissionPeriodicity = (mu_dl == 0) ? NR_TDD_UL_DL_Pattern__dl_UL_TransmissionPeriodicity_ms10 + : NR_TDD_UL_DL_Pattern__dl_UL_TransmissionPeriodicity_ms5; + p1->nrofDownlinkSlots = 7; + p1->nrofDownlinkSymbols = 6; + p1->nrofUplinkSlots = 2; + p1->nrofUplinkSymbols = 4; + + struct NR_TDD_UL_DL_Pattern *p2 = tdd_UL_DL_ConfigurationCommon->pattern2; + p2->dl_UL_TransmissionPeriodicity = 321; + p2->nrofDownlinkSlots = -1; + p2->nrofDownlinkSymbols = -1; + p2->nrofUplinkSlots = -1; + p2->nrofUplinkSymbols = -1; + + scc->ss_PBCH_BlockPower = 20; } @@ -473,90 +423,99 @@ void fix_scc(NR_ServingCellConfigCommon_t *scc, uint64_t ssbmap) /* Function to allocate dedicated serving cell config strutures */ void prepare_scd(NR_ServingCellConfig_t *scd) { // Allocate downlink structures - scd->downlinkBWP_ToAddModList = CALLOC(1, sizeof(*scd->downlinkBWP_ToAddModList)); - scd->uplinkConfig = CALLOC(1, sizeof(*scd->uplinkConfig)); - scd->uplinkConfig->uplinkBWP_ToAddModList = CALLOC(1, sizeof(*scd->uplinkConfig->uplinkBWP_ToAddModList)); - scd->bwp_InactivityTimer = CALLOC(1, sizeof(*scd->bwp_InactivityTimer)); - scd->uplinkConfig->firstActiveUplinkBWP_Id = CALLOC(1, sizeof(*scd->uplinkConfig->firstActiveUplinkBWP_Id)); - scd->firstActiveDownlinkBWP_Id = CALLOC(1, sizeof(*scd->firstActiveDownlinkBWP_Id)); + scd->downlinkBWP_ToAddModList = calloc_or_fail(1, sizeof(*scd->downlinkBWP_ToAddModList)); + scd->uplinkConfig = calloc_or_fail(1, sizeof(*scd->uplinkConfig)); + scd->uplinkConfig->uplinkBWP_ToAddModList = calloc_or_fail(1, sizeof(*scd->uplinkConfig->uplinkBWP_ToAddModList)); + scd->bwp_InactivityTimer = calloc_or_fail(1, sizeof(*scd->bwp_InactivityTimer)); + scd->uplinkConfig->firstActiveUplinkBWP_Id = calloc_or_fail(1, sizeof(*scd->uplinkConfig->firstActiveUplinkBWP_Id)); + scd->firstActiveDownlinkBWP_Id = calloc_or_fail(1, sizeof(*scd->firstActiveDownlinkBWP_Id)); *scd->firstActiveDownlinkBWP_Id = 1; *scd->uplinkConfig->firstActiveUplinkBWP_Id = 1; - scd->defaultDownlinkBWP_Id = CALLOC(1, sizeof(*scd->defaultDownlinkBWP_Id)); + scd->defaultDownlinkBWP_Id = calloc_or_fail(1, sizeof(*scd->defaultDownlinkBWP_Id)); *scd->defaultDownlinkBWP_Id = 0; for (int j = 0; j < NR_MAX_NUM_BWP; j++) { // Downlink bandwidth part - NR_BWP_Downlink_t *bwp = calloc(1, sizeof(*bwp)); + NR_BWP_Downlink_t *bwp = calloc_or_fail(1, sizeof(*bwp)); bwp->bwp_Id = j+1; // Allocate downlink dedicated bandwidth part and PDSCH structures - bwp->bwp_Common = calloc(1, sizeof(*bwp->bwp_Common)); - bwp->bwp_Common->pdcch_ConfigCommon = calloc(1, sizeof(*bwp->bwp_Common->pdcch_ConfigCommon)); - bwp->bwp_Common->pdsch_ConfigCommon = calloc(1, sizeof(*bwp->bwp_Common->pdsch_ConfigCommon)); - bwp->bwp_Dedicated = calloc(1, sizeof(*bwp->bwp_Dedicated)); - bwp->bwp_Dedicated->pdsch_Config = calloc(1, sizeof(*bwp->bwp_Dedicated->pdsch_Config)); - bwp->bwp_Dedicated->pdsch_Config->present = NR_SetupRelease_PDSCH_Config_PR_setup; - bwp->bwp_Dedicated->pdsch_Config->choice.setup = calloc(1, sizeof(*bwp->bwp_Dedicated->pdsch_Config->choice.setup)); - bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA = calloc(1, sizeof(*bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA)); - bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->present = NR_SetupRelease_DMRS_DownlinkConfig_PR_setup; + bwp->bwp_Common = calloc_or_fail(1, sizeof(*bwp->bwp_Common)); + bwp->bwp_Common->pdcch_ConfigCommon = calloc_or_fail(1, sizeof(*bwp->bwp_Common->pdcch_ConfigCommon)); + bwp->bwp_Common->pdsch_ConfigCommon = calloc_or_fail(1, sizeof(*bwp->bwp_Common->pdsch_ConfigCommon)); + bwp->bwp_Dedicated = calloc_or_fail(1, sizeof(*bwp->bwp_Dedicated)); + bwp->bwp_Dedicated->pdsch_Config = calloc_or_fail(1, sizeof(*bwp->bwp_Dedicated->pdsch_Config)); + struct NR_SetupRelease_PDSCH_Config *pdsch_Config = bwp->bwp_Dedicated->pdsch_Config; + pdsch_Config->present = NR_SetupRelease_PDSCH_Config_PR_setup; + pdsch_Config->choice.setup = calloc_or_fail(1, sizeof(*pdsch_Config->choice.setup)); + struct NR_PDSCH_Config *pc_setup = pdsch_Config->choice.setup; + pc_setup->dmrs_DownlinkForPDSCH_MappingTypeA = calloc_or_fail(1, sizeof(*pc_setup->dmrs_DownlinkForPDSCH_MappingTypeA)); + struct NR_SetupRelease_DMRS_DownlinkConfig *typeA = pc_setup->dmrs_DownlinkForPDSCH_MappingTypeA; + typeA->present = NR_SetupRelease_DMRS_DownlinkConfig_PR_setup; // Allocate DL DMRS and PTRS configuration - bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup = calloc(1, sizeof(*bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup)); - NR_DMRS_DownlinkConfig_t *NR_DMRS_DownlinkCfg = bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup; - NR_DMRS_DownlinkCfg->phaseTrackingRS=CALLOC(1, sizeof(*NR_DMRS_DownlinkCfg->phaseTrackingRS)); + typeA->choice.setup = calloc_or_fail(1, sizeof(*typeA->choice.setup)); + NR_DMRS_DownlinkConfig_t *NR_DMRS_DownlinkCfg = typeA->choice.setup; + NR_DMRS_DownlinkCfg->phaseTrackingRS = calloc_or_fail(1, sizeof(*NR_DMRS_DownlinkCfg->phaseTrackingRS)); NR_DMRS_DownlinkCfg->phaseTrackingRS->present = NR_SetupRelease_PTRS_DownlinkConfig_PR_setup; - NR_DMRS_DownlinkCfg->phaseTrackingRS->choice.setup = CALLOC(1, sizeof(*NR_DMRS_DownlinkCfg->phaseTrackingRS->choice.setup)); + NR_DMRS_DownlinkCfg->phaseTrackingRS->choice.setup = + calloc_or_fail(1, sizeof(*NR_DMRS_DownlinkCfg->phaseTrackingRS->choice.setup)); NR_PTRS_DownlinkConfig_t *NR_PTRS_DownlinkCfg = NR_DMRS_DownlinkCfg->phaseTrackingRS->choice.setup; - NR_PTRS_DownlinkCfg->frequencyDensity = CALLOC(1, sizeof(*NR_PTRS_DownlinkCfg->frequencyDensity)); - long *dl_rbs = CALLOC(2, sizeof(long)); + NR_PTRS_DownlinkCfg->frequencyDensity = calloc_or_fail(1, sizeof(*NR_PTRS_DownlinkCfg->frequencyDensity)); + long *dl_rbs = calloc_or_fail(2, sizeof(*dl_rbs)); for (int i=0;i<2;i++) { asn1cSeqAdd(&NR_PTRS_DownlinkCfg->frequencyDensity->list, &dl_rbs[i]); } - NR_PTRS_DownlinkCfg->timeDensity = CALLOC(1, sizeof(*NR_PTRS_DownlinkCfg->timeDensity)); - long *dl_mcs = CALLOC(3, sizeof(long)); + NR_PTRS_DownlinkCfg->timeDensity = calloc_or_fail(1, sizeof(*NR_PTRS_DownlinkCfg->timeDensity)); + long *dl_mcs = calloc_or_fail(3, sizeof(*dl_mcs)); for (int i=0;i<3;i++) { asn1cSeqAdd(&NR_PTRS_DownlinkCfg->timeDensity->list, &dl_mcs[i]); } - NR_PTRS_DownlinkCfg->epre_Ratio = CALLOC(1, sizeof(*NR_PTRS_DownlinkCfg->epre_Ratio)); - NR_PTRS_DownlinkCfg->resourceElementOffset = CALLOC(1, sizeof(*NR_PTRS_DownlinkCfg->resourceElementOffset)); + NR_PTRS_DownlinkCfg->epre_Ratio = calloc_or_fail(1, sizeof(*NR_PTRS_DownlinkCfg->epre_Ratio)); + NR_PTRS_DownlinkCfg->resourceElementOffset = calloc_or_fail(1, sizeof(*NR_PTRS_DownlinkCfg->resourceElementOffset)); *NR_PTRS_DownlinkCfg->resourceElementOffset = 0; asn1cSeqAdd(&scd->downlinkBWP_ToAddModList->list,bwp); // Allocate uplink structures - NR_PUSCH_Config_t *pusch_Config = CALLOC(1, sizeof(*pusch_Config)); + NR_PUSCH_Config_t *pusch_Config = calloc_or_fail(1, sizeof(*pusch_Config)); // Allocate UL DMRS and PTRS structures - pusch_Config->dmrs_UplinkForPUSCH_MappingTypeB = CALLOC(1, sizeof(*pusch_Config->dmrs_UplinkForPUSCH_MappingTypeB)); + pusch_Config->dmrs_UplinkForPUSCH_MappingTypeB = calloc_or_fail(1, sizeof(*pusch_Config->dmrs_UplinkForPUSCH_MappingTypeB)); pusch_Config->dmrs_UplinkForPUSCH_MappingTypeB->present = NR_SetupRelease_DMRS_UplinkConfig_PR_setup; - pusch_Config->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup = CALLOC(1, sizeof(*pusch_Config->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup)); + pusch_Config->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup = + calloc_or_fail(1, sizeof(*pusch_Config->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup)); NR_DMRS_UplinkConfig_t *NR_DMRS_UplinkConfig = pusch_Config->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup; - NR_DMRS_UplinkConfig->phaseTrackingRS = CALLOC(1, sizeof(*NR_DMRS_UplinkConfig->phaseTrackingRS)); + NR_DMRS_UplinkConfig->phaseTrackingRS = calloc_or_fail(1, sizeof(*NR_DMRS_UplinkConfig->phaseTrackingRS)); NR_DMRS_UplinkConfig->phaseTrackingRS->present = NR_SetupRelease_PTRS_UplinkConfig_PR_setup; - NR_DMRS_UplinkConfig->phaseTrackingRS->choice.setup = CALLOC(1, sizeof(*NR_DMRS_UplinkConfig->phaseTrackingRS->choice.setup)); + NR_DMRS_UplinkConfig->phaseTrackingRS->choice.setup = + calloc_or_fail(1, sizeof(*NR_DMRS_UplinkConfig->phaseTrackingRS->choice.setup)); NR_PTRS_UplinkConfig_t *NR_PTRS_UplinkConfig = NR_DMRS_UplinkConfig->phaseTrackingRS->choice.setup; - NR_PTRS_UplinkConfig->transformPrecoderDisabled = CALLOC(1, sizeof(*NR_PTRS_UplinkConfig->transformPrecoderDisabled)); - NR_PTRS_UplinkConfig->transformPrecoderDisabled->frequencyDensity = CALLOC(1, sizeof(*NR_PTRS_UplinkConfig->transformPrecoderDisabled->frequencyDensity)); - long *n_rbs = CALLOC(2, sizeof(long)); + NR_PTRS_UplinkConfig->transformPrecoderDisabled = calloc_or_fail(1, sizeof(*NR_PTRS_UplinkConfig->transformPrecoderDisabled)); + NR_PTRS_UplinkConfig->transformPrecoderDisabled->frequencyDensity = + calloc_or_fail(1, sizeof(*NR_PTRS_UplinkConfig->transformPrecoderDisabled->frequencyDensity)); + long *n_rbs = calloc_or_fail(2, sizeof(*n_rbs)); for (int i=0;i<2;i++) { asn1cSeqAdd(&NR_PTRS_UplinkConfig->transformPrecoderDisabled->frequencyDensity->list, &n_rbs[i]); } - NR_PTRS_UplinkConfig->transformPrecoderDisabled->timeDensity = CALLOC(1, sizeof(*NR_PTRS_UplinkConfig->transformPrecoderDisabled->timeDensity)); - long *ptrs_mcs = CALLOC(3, sizeof(long)); + NR_PTRS_UplinkConfig->transformPrecoderDisabled->timeDensity = + calloc_or_fail(1, sizeof(*NR_PTRS_UplinkConfig->transformPrecoderDisabled->timeDensity)); + long *ptrs_mcs = calloc_or_fail(3, sizeof(*ptrs_mcs)); for (int i = 0; i < 3; i++) { asn1cSeqAdd(&NR_PTRS_UplinkConfig->transformPrecoderDisabled->timeDensity->list, &ptrs_mcs[i]); } - NR_PTRS_UplinkConfig->transformPrecoderDisabled->resourceElementOffset = CALLOC(1, sizeof(*NR_PTRS_UplinkConfig->transformPrecoderDisabled->resourceElementOffset)); + NR_PTRS_UplinkConfig->transformPrecoderDisabled->resourceElementOffset = + calloc_or_fail(1, sizeof(*NR_PTRS_UplinkConfig->transformPrecoderDisabled->resourceElementOffset)); *NR_PTRS_UplinkConfig->transformPrecoderDisabled->resourceElementOffset = 0; // UL bandwidth part - NR_BWP_Uplink_t *ubwp = CALLOC(1, sizeof(*ubwp)); + NR_BWP_Uplink_t *ubwp = calloc_or_fail(1, sizeof(*ubwp)); ubwp->bwp_Id = j+1; - ubwp->bwp_Common = CALLOC(1, sizeof(*ubwp->bwp_Common)); - ubwp->bwp_Dedicated = CALLOC(1, sizeof(*ubwp->bwp_Dedicated)); + ubwp->bwp_Common = calloc_or_fail(1, sizeof(*ubwp->bwp_Common)); + ubwp->bwp_Dedicated = calloc_or_fail(1, sizeof(*ubwp->bwp_Dedicated)); - ubwp->bwp_Dedicated->pusch_Config = CALLOC(1, sizeof(*ubwp->bwp_Dedicated->pusch_Config)); + ubwp->bwp_Dedicated->pusch_Config = calloc_or_fail(1, sizeof(*ubwp->bwp_Dedicated->pusch_Config)); ubwp->bwp_Dedicated->pusch_Config->present = NR_SetupRelease_PUSCH_Config_PR_setup; ubwp->bwp_Dedicated->pusch_Config->choice.setup = pusch_Config; @@ -972,7 +931,7 @@ void RCconfig_NR_L1(void) static NR_ServingCellConfigCommon_t *get_scc_config(configmodule_interface_t *cfg, int minRXTXTIME) { - NR_ServingCellConfigCommon_t *scc = calloc(1,sizeof(*scc)); + NR_ServingCellConfigCommon_t *scc = calloc_or_fail(1, sizeof(*scc)); uint64_t ssb_bitmap=0xff; prepare_scc(scc); paramdef_t SCCsParams[] = SCCPARAMS_DESC(scc); @@ -2161,7 +2120,7 @@ int RCconfig_NR_X2(MessageDef *msg_p, uint32_t i) { paramlist_def_t GNBParamList = {GNB_CONFIG_STRING_GNB_LIST,NULL,0}; /* get global parameters, defined outside any section in the config file */ config_get(config_get_if(), GNBSParams, sizeofArray(GNBSParams), NULL); - NR_ServingCellConfigCommon_t *scc = calloc(1,sizeof(NR_ServingCellConfigCommon_t)); + NR_ServingCellConfigCommon_t *scc = calloc_or_fail(1, sizeof(*scc)); uint64_t ssb_bitmap=0xff; memset((void*)scc,0,sizeof(NR_ServingCellConfigCommon_t)); prepare_scc(scc); @@ -2396,7 +2355,6 @@ int gNB_app_handle_f1ap_gnb_cu_configuration_update(f1ap_gnb_cu_configuration_up ret++; mac->f1_config.setup_resp = malloc(sizeof(*mac->f1_config.setup_resp)); AssertFatal(mac->f1_config.setup_resp != NULL, "out of memory\n"); - mac->f1_config.setup_resp->gNB_CU_name = gnb_cu_cfg_update->gNB_CU_name; mac->f1_config.setup_resp->num_cells_to_activate = gnb_cu_cfg_update->num_cells_to_activate; mac->f1_config.setup_resp->cells_to_activate[0] = gnb_cu_cfg_update->cells_to_activate[0]; } else { @@ -2405,6 +2363,8 @@ int gNB_app_handle_f1ap_gnb_cu_configuration_update(f1ap_gnb_cu_configuration_up } } NR_SCHED_UNLOCK(&mac->sched_lock); + /* Free F1AP struct after use */ + free_f1ap_cu_configuration_update(gnb_cu_cfg_update); MessageDef *msg_ack_p = NULL; if (ret > 0) { // generate gNB_CU_CONFIGURATION_UPDATE_ACKNOWLEDGE @@ -2414,6 +2374,7 @@ int gNB_app_handle_f1ap_gnb_cu_configuration_update(f1ap_gnb_cu_configuration_up F1AP_GNB_CU_CONFIGURATION_UPDATE_ACKNOWLEDGE(msg_ack_p).noofTNLAssociations_to_setup =0; F1AP_GNB_CU_CONFIGURATION_UPDATE_ACKNOWLEDGE(msg_ack_p).noofTNLAssociations_failed = 0; F1AP_GNB_CU_CONFIGURATION_UPDATE_ACKNOWLEDGE(msg_ack_p).noofDedicatedSIDeliveryNeededUEs = 0; + F1AP_GNB_CU_CONFIGURATION_UPDATE_ACKNOWLEDGE(msg_ack_p).transaction_id = F1AP_get_next_transaction_identifier(0, 0); itti_send_msg_to_task (TASK_DU_F1, INSTANCE_DEFAULT, msg_ack_p); } diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c index bb84a4793c..407e5869ce 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c +++ b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c @@ -28,6 +28,7 @@ #include "F1AP_CauseRadioNetwork.h" #include "openair3/ocp-gtpu/gtp_itf.h" #include "openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.h" +#include "lib/f1ap_interface_management.h" #include "executables/softmodem-common.h" @@ -169,10 +170,10 @@ void f1_setup_response(const f1ap_setup_resp_t *resp) mac->f1_config.setup_resp = malloc(sizeof(*mac->f1_config.setup_resp)); AssertFatal(mac->f1_config.setup_resp != NULL, "out of memory\n"); - *mac->f1_config.setup_resp = *resp; - if (resp->gNB_CU_name) - mac->f1_config.setup_resp->gNB_CU_name = strdup(resp->gNB_CU_name); - + // Copy F1AP message + *mac->f1_config.setup_resp = cp_f1ap_setup_response(resp); + // free F1AP message after copy + free_f1ap_setup_response(resp); NR_SCHED_UNLOCK(&mac->sched_lock); // NOTE: Before accepting any UEs, we should initialize the UE states. @@ -244,7 +245,7 @@ static int handle_ue_context_srbs_setup(NR_UE_info_t *UE, static NR_RLC_BearerConfig_t *get_bearerconfig_from_drb(const f1ap_drb_to_be_setup_t *drb) { - const NR_RLC_Config_PR rlc_conf = drb->rlc_mode == RLC_MODE_UM ? NR_RLC_Config_PR_um_Bi_Directional : NR_RLC_Config_PR_am; + const NR_RLC_Config_PR rlc_conf = drb->rlc_mode == F1AP_RLC_MODE_AM ? NR_RLC_Config_PR_am : NR_RLC_Config_PR_um_Bi_Directional; long priority = 13; // hardcoded for the moment return get_DRB_RLC_BearerConfig(get_lcid_from_drbid(drb->drb_id), drb->drb_id, rlc_conf, priority); } @@ -262,11 +263,11 @@ static NR_QoS_config_t get_qos_config(const f1ap_qos_characteristics_t *qos_char { NR_QoS_config_t qos_c = {0}; switch (qos_char->qos_type) { - case dynamic: + case DYNAMIC: qos_c.priority = qos_char->dynamic.qos_priority_level; qos_c.fiveQI = qos_char->dynamic.fiveqi > 0 ? qos_char->dynamic.fiveqi : 0; break; - case non_dynamic: + case NON_DYNAMIC: qos_c.fiveQI = qos_char->non_dynamic.fiveqi; qos_c.priority = get_non_dynamic_priority(qos_char->non_dynamic.fiveqi); break; diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_direct.c b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_direct.c index 29a7bc8621..ad8978d514 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_direct.c +++ b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_direct.c @@ -23,6 +23,8 @@ #include "intertask_interface.h" #include "mac_rrc_ul.h" +#include "f1ap_lib_extern.h" +#include "lib/f1ap_interface_management.h" static void f1_reset_du_initiated_direct(const f1ap_reset_t *reset) { @@ -40,47 +42,8 @@ static void f1_setup_request_direct(const f1ap_setup_req_t *req) { MessageDef *msg = itti_alloc_new_message(TASK_MAC_GNB, 0, F1AP_SETUP_REQ); msg->ittiMsgHeader.originInstance = -1; // means monolithic - f1ap_setup_req_t *f1ap_msg = &F1AP_SETUP_REQ(msg); - f1ap_msg->gNB_DU_id = req->gNB_DU_id; - f1ap_msg->gNB_DU_name = strdup(req->gNB_DU_name); - f1ap_msg->num_cells_available = req->num_cells_available; - for (int n = 0; n < req->num_cells_available; ++n) { - f1ap_msg->cell[n].info = req->cell[n].info; // copy most fields - if (req->cell[n].info.tac) { - f1ap_msg->cell[n].info.tac = malloc(sizeof(*f1ap_msg->cell[n].info.tac)); - AssertFatal(f1ap_msg->cell[n].info.tac != NULL, "out of memory\n"); - *f1ap_msg->cell[n].info.tac = *req->cell[n].info.tac; - } - if (req->cell[n].info.measurement_timing_config_len > 0) { - f1ap_msg->cell[n].info.measurement_timing_config = calloc(req->cell[n].info.measurement_timing_config_len, sizeof(uint8_t)); - AssertFatal(f1ap_msg->cell[n].info.measurement_timing_config != NULL, "out of memory\n"); - memcpy(f1ap_msg->cell[n].info.measurement_timing_config, - req->cell[n].info.measurement_timing_config, - req->cell[n].info.measurement_timing_config_len); - f1ap_msg->cell[n].info.measurement_timing_config_len = req->cell[n].info.measurement_timing_config_len; - } - - if (req->cell[n].sys_info) { - f1ap_gnb_du_system_info_t *orig_sys_info = req->cell[n].sys_info; - f1ap_gnb_du_system_info_t *copy_sys_info = calloc(1, sizeof(*copy_sys_info)); - AssertFatal(copy_sys_info, "out of memory\n"); - f1ap_msg->cell[n].sys_info = copy_sys_info; - - copy_sys_info->mib = calloc(orig_sys_info->mib_length, sizeof(uint8_t)); - AssertFatal(copy_sys_info->mib, "out of memory\n"); - memcpy(copy_sys_info->mib, orig_sys_info->mib, orig_sys_info->mib_length); - copy_sys_info->mib_length = orig_sys_info->mib_length; - - if (orig_sys_info->sib1_length > 0) { - copy_sys_info->sib1 = calloc(orig_sys_info->sib1_length, sizeof(uint8_t)); - AssertFatal(copy_sys_info->sib1, "out of memory\n"); - memcpy(copy_sys_info->sib1, orig_sys_info->sib1, orig_sys_info->sib1_length); - copy_sys_info->sib1_length = orig_sys_info->sib1_length; - } - } - } - memcpy(f1ap_msg->rrc_ver, req->rrc_ver, sizeof(req->rrc_ver)); - + f1ap_setup_req_t cp = cp_f1ap_setup_request(req); + F1AP_SETUP_REQ(msg) = cp; itti_send_msg_to_task(TASK_RRC_GNB, 0, msg); } @@ -88,51 +51,8 @@ static void gnb_du_configuration_update_direct(const f1ap_gnb_du_configuration_u { MessageDef *msg = itti_alloc_new_message(TASK_MAC_GNB, 0, F1AP_GNB_DU_CONFIGURATION_UPDATE); msg->ittiMsgHeader.originInstance = -1; // means monolithic - f1ap_gnb_du_configuration_update_t *f1ap_msg = &F1AP_GNB_DU_CONFIGURATION_UPDATE(msg); - DevAssert(upd->gNB_DU_ID == NULL); - f1ap_msg->transaction_id = upd->transaction_id; - DevAssert(upd->num_cells_to_add == 0); - DevAssert(upd->num_cells_to_delete == 0); - - f1ap_msg->num_cells_to_modify = upd->num_cells_to_modify; - for (int n = 0; n < upd->num_cells_to_modify; ++n) { - f1ap_msg->cell_to_modify[n].old_nr_cellid = upd->cell_to_modify[n].old_nr_cellid; - f1ap_msg->cell_to_modify[n].info = upd->cell_to_modify[n].info; // copy most fields - if (upd->cell_to_modify[n].info.tac) { - f1ap_msg->cell_to_modify[n].info.tac = malloc(sizeof(*f1ap_msg->cell_to_modify[n].info.tac)); - AssertFatal(f1ap_msg->cell_to_modify[n].info.tac != NULL, "out of memory\n"); - *f1ap_msg->cell_to_modify[n].info.tac = *upd->cell_to_modify[n].info.tac; - } - if (upd->cell_to_modify[n].info.measurement_timing_config_len > 0) { - f1ap_msg->cell_to_modify[n].info.measurement_timing_config = - calloc(upd->cell_to_modify[n].info.measurement_timing_config_len, sizeof(uint8_t)); - AssertFatal(f1ap_msg->cell_to_modify[n].info.measurement_timing_config != NULL, "out of memory\n"); - memcpy(f1ap_msg->cell_to_modify[n].info.measurement_timing_config, - upd->cell_to_modify[n].info.measurement_timing_config, - upd->cell_to_modify[n].info.measurement_timing_config_len); - f1ap_msg->cell_to_modify[n].info.measurement_timing_config_len = upd->cell_to_modify[n].info.measurement_timing_config_len; - } - - if (upd->cell_to_modify[n].sys_info) { - f1ap_gnb_du_system_info_t *orig_sys_info = upd->cell_to_modify[n].sys_info; - f1ap_gnb_du_system_info_t *copy_sys_info = calloc(1, sizeof(*copy_sys_info)); - AssertFatal(copy_sys_info != NULL, "out of memory\n"); - f1ap_msg->cell_to_modify[n].sys_info = copy_sys_info; - - copy_sys_info->mib = calloc(orig_sys_info->mib_length, sizeof(uint8_t)); - AssertFatal(copy_sys_info->mib != NULL, "out of memory\n"); - memcpy(copy_sys_info->mib, orig_sys_info->mib, orig_sys_info->mib_length); - copy_sys_info->mib_length = orig_sys_info->mib_length; - - if (orig_sys_info->sib1_length > 0) { - copy_sys_info->sib1 = calloc(orig_sys_info->sib1_length, sizeof(uint8_t)); - AssertFatal(copy_sys_info->sib1 != NULL, "out of memory\n"); - memcpy(copy_sys_info->sib1, orig_sys_info->sib1, orig_sys_info->sib1_length); - copy_sys_info->sib1_length = orig_sys_info->sib1_length; - } - } - } - + /* transfer to RRC via ITTI */ + F1AP_GNB_DU_CONFIGURATION_UPDATE(msg) = cp_f1ap_du_configuration_update(upd); itti_send_msg_to_task(TASK_RRC_GNB, 0, msg); } @@ -277,20 +197,8 @@ static void initial_ul_rrc_message_transfer_direct(module_id_t module_id, const { MessageDef *msg = itti_alloc_new_message(TASK_MAC_GNB, 0, F1AP_INITIAL_UL_RRC_MESSAGE); msg->ittiMsgHeader.originInstance = -1; // means monolithic - /* copy all fields, but reallocate rrc_containers! */ f1ap_initial_ul_rrc_message_t *f1ap_msg = &F1AP_INITIAL_UL_RRC_MESSAGE(msg); - *f1ap_msg = *ul_rrc; - - f1ap_msg->rrc_container = malloc(ul_rrc->rrc_container_length); - DevAssert(f1ap_msg->rrc_container); - memcpy(f1ap_msg->rrc_container, ul_rrc->rrc_container, ul_rrc->rrc_container_length); - f1ap_msg->rrc_container_length = ul_rrc->rrc_container_length; - - f1ap_msg->du2cu_rrc_container = malloc(ul_rrc->du2cu_rrc_container_length); - DevAssert(f1ap_msg->du2cu_rrc_container); - memcpy(f1ap_msg->du2cu_rrc_container, ul_rrc->du2cu_rrc_container, ul_rrc->du2cu_rrc_container_length); - f1ap_msg->du2cu_rrc_container_length = ul_rrc->du2cu_rrc_container_length; - + *f1ap_msg = cp_initial_ul_rrc_message_transfer(ul_rrc); itti_send_msg_to_task(TASK_RRC_GNB, module_id, msg); } diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_f1ap.c b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_f1ap.c index 742f85c390..2af81d0cfd 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_f1ap.c +++ b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_f1ap.c @@ -29,24 +29,23 @@ #include "mac_rrc_ul.h" +#include "f1ap_lib_extern.h" +#include "lib/f1ap_interface_management.h" + static f1ap_net_config_t read_DU_IP_config(const eth_params_t* f1_params, const char *f1u_ip_addr) { f1ap_net_config_t nc = {0}; - nc.CU_f1_ip_address.ipv6 = 0; - nc.CU_f1_ip_address.ipv4 = 1; - strcpy(nc.CU_f1_ip_address.ipv4_address, f1_params->remote_addr); + nc.CU_f1_ip_address= strdup(f1_params->remote_addr); nc.CUport = f1_params->remote_portd; - nc.DU_f1c_ip_address.ipv6 = 0; - nc.DU_f1c_ip_address.ipv4 = 1; - strcpy(nc.DU_f1c_ip_address.ipv4_address, f1_params->my_addr); + nc.DU_f1c_ip_address = strdup(f1_params->my_addr); nc.DU_f1u_ip_address = strdup(f1u_ip_addr); nc.DUport = f1_params->my_portd; LOG_I(F1AP, "F1-C DU IPaddr %s, connect to F1-C CU %s, binding GTP to %s\n", - nc.DU_f1c_ip_address.ipv4_address, - nc.CU_f1_ip_address.ipv4_address, + nc.DU_f1c_ip_address, + nc.CU_f1_ip_address, nc.DU_f1u_ip_address); // sctp_in_streams/sctp_out_streams are given by SCTP layer @@ -70,84 +69,23 @@ static void f1_reset_acknowledge_cu_initiated_f1ap(const f1ap_reset_ack_t *ack) static void f1_setup_request_f1ap(const f1ap_setup_req_t *req) { MessageDef *msg = itti_alloc_new_message(TASK_MAC_GNB, 0, F1AP_DU_REGISTER_REQ); - - f1ap_setup_req_t *f1ap_setup = &F1AP_DU_REGISTER_REQ(msg).setup_req; - f1ap_setup->gNB_DU_id = req->gNB_DU_id; - f1ap_setup->gNB_DU_name = strdup(req->gNB_DU_name); - f1ap_setup->num_cells_available = req->num_cells_available; - for (int n = 0; n < req->num_cells_available; ++n) { - f1ap_setup->cell[n].info = req->cell[n].info; // copy most fields - if (req->cell[n].info.tac) { - f1ap_setup->cell[n].info.tac = malloc(sizeof(*f1ap_setup->cell[n].info.tac)); - AssertFatal(f1ap_setup->cell[n].info.tac != NULL, "out of memory\n"); - *f1ap_setup->cell[n].info.tac = *req->cell[n].info.tac; - } - if (req->cell[n].info.measurement_timing_config_len > 0) { - f1ap_setup->cell[n].info.measurement_timing_config = calloc(req->cell[n].info.measurement_timing_config_len, sizeof(uint8_t)); - AssertFatal(f1ap_setup->cell[n].info.measurement_timing_config != NULL, "out of memory\n"); - memcpy(f1ap_setup->cell[n].info.measurement_timing_config, - req->cell[n].info.measurement_timing_config, - req->cell[n].info.measurement_timing_config_len); - f1ap_setup->cell[n].info.measurement_timing_config_len = req->cell[n].info.measurement_timing_config_len; - } - - if (req->cell[n].sys_info) { - f1ap_gnb_du_system_info_t *orig_sys_info = req->cell[n].sys_info; - f1ap_gnb_du_system_info_t *copy_sys_info = calloc(1, sizeof(*copy_sys_info)); - AssertFatal(copy_sys_info, "out of memory\n"); - f1ap_setup->cell[n].sys_info = copy_sys_info; - - copy_sys_info->mib = calloc(orig_sys_info->mib_length, sizeof(uint8_t)); - AssertFatal(copy_sys_info->mib, "out of memory\n"); - memcpy(copy_sys_info->mib, orig_sys_info->mib, orig_sys_info->mib_length); - copy_sys_info->mib_length = orig_sys_info->mib_length; - - if (orig_sys_info->sib1_length > 0) { - copy_sys_info->sib1 = calloc(orig_sys_info->sib1_length, sizeof(uint8_t)); - AssertFatal(copy_sys_info->sib1, "out of memory\n"); - memcpy(copy_sys_info->sib1, orig_sys_info->sib1, orig_sys_info->sib1_length); - copy_sys_info->sib1_length = orig_sys_info->sib1_length; - } - } - } - memcpy(f1ap_setup->rrc_ver, req->rrc_ver, sizeof(req->rrc_ver)); - + f1ap_setup_req_t f1ap_setup = cp_f1ap_setup_request(req); + F1AP_DU_REGISTER_REQ(msg).setup_req = f1ap_setup; F1AP_DU_REGISTER_REQ(msg).net_config = read_DU_IP_config(&RC.nrmac[0]->eth_params_n, RC.nrmac[0]->f1u_addr); - itti_send_msg_to_task(TASK_DU_F1, 0, msg); } static void gnb_du_configuration_update_f1ap(const f1ap_gnb_du_configuration_update_t *upd) { MessageDef *msg = itti_alloc_new_message(TASK_MAC_GNB, 0, F1AP_GNB_DU_CONFIGURATION_UPDATE); - f1ap_gnb_du_configuration_update_t *f1_upd = &F1AP_GNB_DU_CONFIGURATION_UPDATE(msg); - f1_upd->transaction_id = upd->transaction_id; - AssertFatal(upd->num_cells_to_add == 0, "gNB-DU config update: cells to add not supported\n"); - f1_upd->num_cells_to_modify = upd->num_cells_to_modify; - for (int n = 0; n < upd->num_cells_to_modify; ++n) { - f1_upd->cell_to_modify[n].old_plmn = upd->cell_to_modify[n].old_plmn; - f1_upd->cell_to_modify[n].old_nr_cellid = upd->cell_to_modify[n].old_nr_cellid; - f1_upd->cell_to_modify[n].info = upd->cell_to_modify[n].info; - if (upd->cell_to_modify[n].sys_info) { - f1ap_gnb_du_system_info_t *orig_sys_info = upd->cell_to_modify[n].sys_info; - f1ap_gnb_du_system_info_t *copy_sys_info = calloc(1, sizeof(*copy_sys_info)); - f1_upd->cell_to_modify[n].sys_info = copy_sys_info; - - copy_sys_info->mib = calloc(orig_sys_info->mib_length, sizeof(uint8_t)); - AssertFatal(copy_sys_info->mib != NULL, "out of memory\n"); - memcpy(copy_sys_info->mib, orig_sys_info->mib, orig_sys_info->mib_length); - copy_sys_info->mib_length = orig_sys_info->mib_length; - - if (orig_sys_info->sib1_length > 0) { - copy_sys_info->sib1 = calloc(orig_sys_info->sib1_length, sizeof(uint8_t)); - AssertFatal(copy_sys_info->sib1 != NULL, "out of memory\n"); - memcpy(copy_sys_info->sib1, orig_sys_info->sib1, orig_sys_info->sib1_length); - copy_sys_info->sib1_length = orig_sys_info->sib1_length; - } - } - } - AssertFatal(upd->num_cells_to_delete == 0, "gNB-DU config update: cells to add not supported\n"); - itti_send_msg_to_task(TASK_DU_F1, 0, msg); + /* copy F1AP message */ + f1ap_gnb_du_configuration_update_t cp = cp_f1ap_du_configuration_update(upd); + /* transfer to ITTI message */ + F1AP_GNB_DU_CONFIGURATION_UPDATE(msg) = cp; + /* free after copy */ + free_f1ap_du_configuration_update(upd); + /* send to RRC task */ + itti_send_msg_to_task(TASK_RRC_GNB, 0, msg); } static void ue_context_setup_response_f1ap(const f1ap_ue_context_setup_t *req, const f1ap_ue_context_setup_t *resp) @@ -269,20 +207,8 @@ static void ue_context_release_complete_f1ap(const f1ap_ue_context_release_compl static void initial_ul_rrc_message_transfer_f1ap(module_id_t module_id, const f1ap_initial_ul_rrc_message_t *ul_rrc) { MessageDef *msg = itti_alloc_new_message(TASK_MAC_GNB, 0, F1AP_INITIAL_UL_RRC_MESSAGE); - /* copy all fields, but reallocate rrc_containers! */ f1ap_initial_ul_rrc_message_t *f1ap_msg = &F1AP_INITIAL_UL_RRC_MESSAGE(msg); - *f1ap_msg = *ul_rrc; - - f1ap_msg->rrc_container = malloc(ul_rrc->rrc_container_length); - DevAssert(f1ap_msg->rrc_container); - memcpy(f1ap_msg->rrc_container, ul_rrc->rrc_container, ul_rrc->rrc_container_length); - f1ap_msg->rrc_container_length = ul_rrc->rrc_container_length; - - f1ap_msg->du2cu_rrc_container = malloc(ul_rrc->du2cu_rrc_container_length); - DevAssert(f1ap_msg->du2cu_rrc_container); - memcpy(f1ap_msg->du2cu_rrc_container, ul_rrc->du2cu_rrc_container, ul_rrc->du2cu_rrc_container_length); - f1ap_msg->du2cu_rrc_container_length = ul_rrc->du2cu_rrc_container_length; - + *f1ap_msg = cp_initial_ul_rrc_message_transfer(ul_rrc); itti_send_msg_to_task(TASK_DU_F1, module_id, msg); } diff --git a/openair2/RRC/NR/mac_rrc_dl_f1ap.c b/openair2/RRC/NR/mac_rrc_dl_f1ap.c index 439712ec7e..e2e094d866 100644 --- a/openair2/RRC/NR/mac_rrc_dl_f1ap.c +++ b/openair2/RRC/NR/mac_rrc_dl_f1ap.c @@ -23,6 +23,8 @@ #include "mac_rrc_dl.h" #include "nr_rrc_defs.h" +#include "openair2/F1AP/lib/f1ap_rrc_message_transfer.h" +#include "openair2/F1AP/lib/f1ap_interface_management.h" static void f1_reset_cu_initiated_f1ap(sctp_assoc_t assoc_id, const f1ap_reset_t *reset) { @@ -44,6 +46,7 @@ static void f1_setup_response_f1ap(sctp_assoc_t assoc_id, const f1ap_setup_resp_ *f1ap_msg = *resp; if (resp->gNB_CU_name != NULL) f1ap_msg->gNB_CU_name = strdup(resp->gNB_CU_name); + free_f1ap_setup_response(resp); itti_send_msg_to_task(TASK_CU_F1, 0, msg); } @@ -210,18 +213,7 @@ static void dl_rrc_message_transfer_f1ap(sctp_assoc_t assoc_id, const f1ap_dl_rr MessageDef *message_p = itti_alloc_new_message (TASK_RRC_GNB, 0, F1AP_DL_RRC_MESSAGE); message_p->ittiMsgHeader.originInstance = assoc_id; f1ap_dl_rrc_message_t *msg = &F1AP_DL_RRC_MESSAGE(message_p); - *msg = *dl_rrc; - if (dl_rrc->old_gNB_DU_ue_id) { - msg->old_gNB_DU_ue_id = malloc(sizeof(*msg->old_gNB_DU_ue_id)); - AssertFatal(msg->old_gNB_DU_ue_id != NULL, "out of memory\n"); - *msg->old_gNB_DU_ue_id = *dl_rrc->old_gNB_DU_ue_id; - } - if (dl_rrc->rrc_container) { - msg->rrc_container = malloc(dl_rrc->rrc_container_length); - AssertFatal(msg->rrc_container != NULL, "out of memory\n"); - msg->rrc_container_length = dl_rrc->rrc_container_length; - memcpy(msg->rrc_container, dl_rrc->rrc_container, dl_rrc->rrc_container_length); - } + *msg = cp_dl_rrc_message_transfer(dl_rrc); itti_send_msg_to_task (TASK_CU_F1, 0, message_p); } diff --git a/openair2/RRC/NR/rrc_gNB.c b/openair2/RRC/NR/rrc_gNB.c index 2c5e45f428..c1c78943e5 100644 --- a/openair2/RRC/NR/rrc_gNB.c +++ b/openair2/RRC/NR/rrc_gNB.c @@ -94,6 +94,7 @@ #include #include "openair2/F1AP/f1ap_common.h" #include "openair2/F1AP/f1ap_ids.h" +#include "openair2/F1AP/lib/f1ap_lib_extern.h" #include "openair2/SDAP/nr_sdap/nr_sdap_entity.h" #include "openair2/E1AP/e1ap.h" #include "cucp_cuup_if.h" @@ -1839,11 +1840,6 @@ void rrc_gNB_process_initial_ul_rrc_message(sctp_assoc_t assoc_id, const f1ap_in } } ASN_STRUCT_FREE(asn_DEF_NR_UL_CCCH_Message, ul_ccch_msg); - - if (ul_rrc->rrc_container) - free(ul_rrc->rrc_container); - if (ul_rrc->du2cu_rrc_container) - free(ul_rrc->du2cu_rrc_container); } void rrc_gNB_process_release_request(const module_id_t gnb_mod_idP, x2ap_ENDC_sgnb_release_request_t *m) @@ -2161,12 +2157,12 @@ static pdusession_level_qos_parameter_t *get_qos_characteristics(const int qfi, static f1ap_qos_characteristics_t get_qos_char_from_qos_flow_param(const pdusession_level_qos_parameter_t *qos_param) { f1ap_qos_characteristics_t qos_char = {0}; - if (qos_param->fiveQI_type == dynamic) { - qos_char.qos_type = dynamic; + if (qos_param->fiveQI_type == DYNAMIC) { + qos_char.qos_type = DYNAMIC; qos_char.dynamic.fiveqi = qos_param->fiveQI; qos_char.dynamic.qos_priority_level = qos_param->qos_priority; } else { - qos_char.qos_type = non_dynamic; + qos_char.qos_type = NON_DYNAMIC; qos_char.non_dynamic.fiveqi = qos_param->fiveQI; qos_char.non_dynamic.qos_priority_level = qos_param->qos_priority; } @@ -2189,7 +2185,7 @@ static int fill_drb_to_be_setup_from_e1_resp(const gNB_RRC_INST *rrc, const DRB_nGRAN_setup_t *drb_config = &pduSession[p].DRBnGRanList[i]; f1ap_drb_to_be_setup_t *drb = &drbs[nb_drb]; drb->drb_id = pduSession[p].DRBnGRanList[i].id; - drb->rlc_mode = rrc->configuration.um_on_default_drb ? RLC_MODE_UM : RLC_MODE_AM; + drb->rlc_mode = rrc->configuration.um_on_default_drb ? F1AP_RLC_MODE_UM_BIDIR : F1AP_RLC_MODE_AM; drb->up_ul_tnl[0].tl_address = drb_config->UpParamList[0].tlAddress; drb->up_ul_tnl[0].port = rrc->eth_params_s.my_portd; drb->up_ul_tnl[0].teid = drb_config->UpParamList[0].teId; @@ -2439,6 +2435,7 @@ void *rrc_gnb_task(void *args_p) { AssertFatal(NODE_IS_CU(RC.nrrrc[instance]->node_type) || NODE_IS_MONOLITHIC(RC.nrrrc[instance]->node_type), "should not receive F1AP_INITIAL_UL_RRC_MESSAGE, need call by CU!\n"); rrc_gNB_process_initial_ul_rrc_message(msg_p->ittiMsgHeader.originInstance, &F1AP_INITIAL_UL_RRC_MESSAGE(msg_p)); + free_initial_ul_rrc_message_transfer(&F1AP_INITIAL_UL_RRC_MESSAGE(msg_p)); break; /* Messages from PDCP */ @@ -2515,6 +2512,12 @@ void *rrc_gnb_task(void *args_p) { rrc_gNB_process_f1_du_configuration_update(&F1AP_GNB_DU_CONFIGURATION_UPDATE(msg_p), msg_p->ittiMsgHeader.originInstance); break; + case F1AP_GNB_CU_CONFIGURATION_UPDATE_ACKNOWLEDGE: + AssertFatal(!NODE_IS_DU(RC.nrrrc[instance]->node_type), + "should not receive F1AP_GNB_CU_CONFIGURATION_UPDATE_ACKNOWLEDGE in DU!\n"); + LOG_E(NR_RRC, "Handling of F1AP_GNB_CU_CONFIGURATION_UPDATE_ACKNOWLEDGE not implemented\n"); + break; + /* Messages from X2AP */ case X2AP_ENDC_SGNB_ADDITION_REQ: LOG_I(NR_RRC, "Received ENDC sgNB addition request from X2AP \n"); diff --git a/openair2/RRC/NR/rrc_gNB_NGAP.c b/openair2/RRC/NR/rrc_gNB_NGAP.c index 1ef1f8c808..6ffb8ad88e 100644 --- a/openair2/RRC/NR/rrc_gNB_NGAP.c +++ b/openair2/RRC/NR/rrc_gNB_NGAP.c @@ -248,11 +248,11 @@ static void fill_qos(NGAP_QosFlowSetupRequestList_t *qos, pdusession_t *session) AssertFatal(qosChar, "Qos characteristics are not available for qos flow index %d\n", qosIdx); if (qosChar->present == NGAP_QosCharacteristics_PR_nonDynamic5QI) { AssertFatal(qosChar->choice.dynamic5QI, "Non-Dynamic 5QI is NULL\n"); - session->qos[qosIdx].fiveQI_type = non_dynamic; + session->qos[qosIdx].fiveQI_type = NON_DYNAMIC; session->qos[qosIdx].fiveQI = (uint64_t)qosChar->choice.nonDynamic5QI->fiveQI; } else { AssertFatal(qosChar->choice.dynamic5QI, "Dynamic 5QI is NULL\n"); - session->qos[qosIdx].fiveQI_type = dynamic; + session->qos[qosIdx].fiveQI_type = DYNAMIC; session->qos[qosIdx].fiveQI = (uint64_t)(*qosChar->choice.dynamic5QI->fiveQI); } @@ -412,7 +412,7 @@ void trigger_bearer_setup(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, int n, pdusession qos_characteristics_t *qos_char = &qos_flow->qos_params.qos_characteristics; qos_flow->qfi = qos_session->qfi; qos_char->qos_type = qos_session->fiveQI_type; - if (qos_char->qos_type == dynamic) { + if (qos_char->qos_type == DYNAMIC) { qos_char->dynamic.fiveqi = qos_session->fiveQI; qos_char->dynamic.qos_priority_level = qos_session->qos_priority; } else { @@ -861,11 +861,11 @@ static void fill_qos2(NGAP_QosFlowAddOrModifyRequestList_t *qos, pdusession_t *s AssertFatal(qosChar, "Qos characteristics are not available for qos flow index %d\n", qosIdx); if (qosChar->present == NGAP_QosCharacteristics_PR_nonDynamic5QI) { AssertFatal(qosChar->choice.dynamic5QI, "Non-Dynamic 5QI is NULL\n"); - session->qos[qosIdx].fiveQI_type = non_dynamic; + session->qos[qosIdx].fiveQI_type = NON_DYNAMIC; session->qos[qosIdx].fiveQI = (uint64_t)qosChar->choice.nonDynamic5QI->fiveQI; } else { AssertFatal(qosChar->choice.dynamic5QI, "Dynamic 5QI is NULL\n"); - session->qos[qosIdx].fiveQI_type = dynamic; + session->qos[qosIdx].fiveQI_type = DYNAMIC; session->qos[qosIdx].fiveQI = (uint64_t)(*qosChar->choice.dynamic5QI->fiveQI); } diff --git a/openair2/RRC/NR/rrc_gNB_du.c b/openair2/RRC/NR/rrc_gNB_du.c index e20121e8c2..e2806edf60 100644 --- a/openair2/RRC/NR/rrc_gNB_du.c +++ b/openair2/RRC/NR/rrc_gNB_du.c @@ -29,6 +29,7 @@ #include "executables/softmodem-common.h" #include "common/utils/ds/seq_arr.h" #include "common/utils/alg/foreach.h" +#include "lib/f1ap_interface_management.h" int get_dl_band(const struct f1ap_served_cell_info_t *cell_info) { @@ -261,6 +262,8 @@ void rrc_gNB_process_f1_setup_req(f1ap_setup_req_t *req, sctp_assoc_t assoc_id) DevAssert(rrc); LOG_I(NR_RRC, "Received F1 Setup Request from gNB_DU %lu (%s) on assoc_id %d\n", req->gNB_DU_id, req->gNB_DU_name, assoc_id); + // pre-fill F1 Setup Failure message + f1ap_setup_failure_t fail = {.transaction_id = F1AP_get_next_transaction_identifier(0, 0)}; // check: // - it is one cell @@ -269,7 +272,7 @@ void rrc_gNB_process_f1_setup_req(f1ap_setup_req_t *req, sctp_assoc_t assoc_id) // else reject if (req->num_cells_available != 1) { LOG_E(NR_RRC, "can only handle on DU cell, but gNB_DU %ld has %d\n", req->gNB_DU_id, req->num_cells_available); - f1ap_setup_failure_t fail = {.cause = F1AP_CauseRadioNetwork_gNB_CU_Cell_Capacity_Exceeded}; + fail.cause = F1AP_CauseRadioNetwork_gNB_CU_Cell_Capacity_Exceeded; rrc->mac_rrc.f1_setup_failure(assoc_id, &fail); return; } @@ -283,7 +286,7 @@ void rrc_gNB_process_f1_setup_req(f1ap_setup_req_t *req, sctp_assoc_t assoc_id) cell_info->plmn.mcc, cell_info->plmn.mnc_digit_length, cell_info->plmn.mnc); - f1ap_setup_failure_t fail = {.cause = F1AP_CauseRadioNetwork_plmn_not_served_by_the_gNB_CU}; + fail.cause = F1AP_CauseRadioNetwork_plmn_not_served_by_the_gNB_CU; rrc->mac_rrc.f1_setup_failure(assoc_id, &fail); return; } @@ -295,7 +298,7 @@ void rrc_gNB_process_f1_setup_req(f1ap_setup_req_t *req, sctp_assoc_t assoc_id) it->setup_req->gNB_DU_name, it->assoc_id, it->setup_req->gNB_DU_id); - f1ap_setup_failure_t fail = {.cause = F1AP_CauseMisc_unspecified}; + fail.cause = F1AP_CauseMisc_unspecified; rrc->mac_rrc.f1_setup_failure(assoc_id, &fail); return; } @@ -312,7 +315,7 @@ void rrc_gNB_process_f1_setup_req(f1ap_setup_req_t *req, sctp_assoc_t assoc_id) exist_info->nr_pci, new_info->nr_cellid, new_info->nr_pci); - f1ap_setup_failure_t fail = {.cause = F1AP_CauseMisc_unspecified}; + fail.cause = F1AP_CauseMisc_unspecified; rrc->mac_rrc.f1_setup_failure(assoc_id, &fail); return; } @@ -339,7 +342,7 @@ void rrc_gNB_process_f1_setup_req(f1ap_setup_req_t *req, sctp_assoc_t assoc_id) if (sys_info != NULL && sys_info->mib != NULL && !(sys_info->sib1 == NULL && get_softmodem_params()->sa)) { if (!extract_sys_info(sys_info, &mib, &sib1)) { LOG_W(RRC, "rejecting DU ID %ld\n", req->gNB_DU_id); - f1ap_setup_failure_t fail = {.cause = F1AP_CauseProtocol_semantic_error}; + fail.cause = F1AP_CauseProtocol_semantic_error; rrc->mac_rrc.f1_setup_failure(assoc_id, &fail); ASN_STRUCT_FREE(asn_DEF_NR_MeasurementTimingConfiguration, mtc); return; @@ -358,7 +361,8 @@ void rrc_gNB_process_f1_setup_req(f1ap_setup_req_t *req, sctp_assoc_t assoc_id) * allocate memory and copy it in */ du->setup_req = calloc(1,sizeof(*du->setup_req)); AssertFatal(du->setup_req, "out of memory\n"); - *du->setup_req = *req; + // Copy F1AP message + *du->setup_req = cp_f1ap_setup_request(req); // MIB can be null and configured later via DU Configuration Update du->mib = mib; du->sib1 = sib1; @@ -379,6 +383,8 @@ void rrc_gNB_process_f1_setup_req(f1ap_setup_req_t *req, sctp_assoc_t assoc_id) f1ap_setup_resp_t resp = {.transaction_id = req->transaction_id, .num_cells_to_activate = 1, .cells_to_activate[0] = cell}; + // free F1AP message after use + free_f1ap_setup_request(req); int num = read_version(TO_STRING(NR_RRC_VERSION), &resp.rrc_ver[0], &resp.rrc_ver[1], &resp.rrc_ver[2]); AssertFatal(num == 3, "could not read RRC version string %s\n", TO_STRING(NR_RRC_VERSION)); if (rrc->node_name != NULL) @@ -510,8 +516,9 @@ void rrc_gNB_process_f1_du_configuration_update(f1ap_gnb_du_configuration_update /* Send DU Configuration Acknowledgement */ f1ap_gnb_du_configuration_update_acknowledge_t ack = {.transaction_id = conf_up->transaction_id}; - rrc->mac_rrc.gnb_du_configuration_update_acknowledge(assoc_id, &ack); + /* free F1AP message after use */ + free_f1ap_du_configuration_update(conf_up); } void rrc_CU_process_f1_lost_connection(gNB_RRC_INST *rrc, f1ap_lost_connection_t *lc, sctp_assoc_t assoc_id) diff --git a/openair2/RRC/NR_UE/rrc_UE.c b/openair2/RRC/NR_UE/rrc_UE.c index fdff0bc421..ed8c47ae5f 100644 --- a/openair2/RRC/NR_UE/rrc_UE.c +++ b/openair2/RRC/NR_UE/rrc_UE.c @@ -551,14 +551,16 @@ static void nr_rrc_ue_decode_NR_BCCH_BCH_Message(NR_UE_RRC_INST_t *rrc, } int get_sib = 0; - if (get_softmodem_params()->sa && - bcch_message->message.choice.mib->cellBarred == NR_MIB__cellBarred_notBarred && - rrc->nrRrcState != RRC_STATE_DETACH_NR) { + if (get_softmodem_params()->sa && bcch_message->message.present == NR_BCCH_BCH_MessageType_PR_mib + && bcch_message->message.choice.mib->cellBarred == NR_MIB__cellBarred_notBarred && rrc->nrRrcState != RRC_STATE_DETACH_NR) { NR_UE_RRC_SI_INFO *SI_info = &rrc->perNB[gNB_index].SInfo; // to schedule MAC to get SI if required get_sib = check_si_status(SI_info); } - nr_rrc_mac_config_req_mib(rrc->ue_id, 0, bcch_message->message.choice.mib, get_sib); + if (bcch_message->message.present == NR_BCCH_BCH_MessageType_PR_mib) + nr_rrc_mac_config_req_mib(rrc->ue_id, 0, bcch_message->message.choice.mib, get_sib); + else + LOG_E(NR_RRC, "RRC-received BCCH message is not a MIB\n"); ASN_STRUCT_FREE(asn_DEF_NR_BCCH_BCH_Message, bcch_message); return; } diff --git a/openair2/UTIL/OPT/probe.c b/openair2/UTIL/OPT/probe.c index 465baa7301..a4994421c2 100644 --- a/openair2/UTIL/OPT/probe.c +++ b/openair2/UTIL/OPT/probe.c @@ -254,7 +254,7 @@ int opt_create_listener_socket(char *ip_address, uint16_t port) { LOG_E(OPT, "Failed to bind socket to (%s:%u): %s\n", inet_ntoa(opt_listener.address.sin_addr), ntohs(opt_listener.address.sin_port), strerror(errno)); - opt_type = OPT_NONE; + // we log anyway as planned because other OAI process may have created the sink close(opt_listener.sd); opt_listener.sd = -1; return -1; diff --git a/openair3/SCTP/sctp_eNB_task.c b/openair3/SCTP/sctp_eNB_task.c index a6d3a11a39..530b3ea6b0 100644 --- a/openair3/SCTP/sctp_eNB_task.c +++ b/openair3/SCTP/sctp_eNB_task.c @@ -394,7 +394,7 @@ static void sctp_handle_new_association_req(const instance_t instance, struct addrinfo *serv; int status = getaddrinfo(local, NULL, &hints, &serv); - AssertFatal(status == 0, "getaddrinfo() failed: %s\n", gai_strerror(status)); + AssertFatal(status == 0, "getaddrinfo(%s) failed: %s\n", local, gai_strerror(status)); int sd; struct addrinfo *p = NULL; diff --git a/radio/rfsimulator/README.md b/radio/rfsimulator/README.md index ba63ae4ec0..c86724fa0d 100644 --- a/radio/rfsimulator/README.md +++ b/radio/rfsimulator/README.md @@ -71,7 +71,7 @@ The RF simulator is using the configuration module, and its parameters are defin | CL option | usage | default | |:--------------------- |:-------------------------------------------------------------------------------|----: | -|`--rfsimulator.serveraddr `| ip address to connect to, or `server` to behave as a tcp server | 127.0.0.1 | +|`--rfsimulator.serveraddr `| IPv4v6 address or DNS name to connect to, or `server` to behave as a IPv4v6 TCP server | 127.0.0.1 | |`--rfsimulator.serverport `| port number to connect to or to listen on (eNB, which behaves as a tcp server) | 4043 | |`--rfsimulator.options` | list of comma separated run-time options, two are supported: `chanmod`, `saviq`| all options disabled | |`--rfsimulator.options saviq` | store IQs to a file for future replay | disabled | diff --git a/radio/rfsimulator/simulator.c b/radio/rfsimulator/simulator.c index c5197eaab8..3c19b492c8 100644 --- a/radio/rfsimulator/simulator.c +++ b/radio/rfsimulator/simulator.c @@ -29,6 +29,7 @@ */ #include +#include #include #include #include @@ -38,6 +39,8 @@ #include #include #include +#include + #include #include #include @@ -544,30 +547,68 @@ static int rfsimu_vtime_cmd(char *buff, int debug, telnet_printfunc_t prnt, void return CMDSTATUS_FOUND; } -static int startServer(openair0_device *device) { - rfsimulator_state_t *t = (rfsimulator_state_t *) device->priv; +static int startServer(openair0_device *device) +{ + int sock = -1; + struct addrinfo *results = NULL; + struct addrinfo *rp= NULL; + + rfsimulator_state_t *t = (rfsimulator_state_t *)device->priv; t->role = SIMU_ROLE_SERVER; - t->listen_sock = socket(AF_INET, SOCK_STREAM, 0); - if (t->listen_sock < 0) { - LOG_E(HW, "socket(SOCK_STREAM) failed, errno(%d)\n", errno); + + char port[6]; + snprintf(port, sizeof(port), "%d", t->port); + + struct addrinfo hints = { + .ai_family = AF_INET6, + .ai_socktype = SOCK_STREAM, + .ai_flags = AI_PASSIVE, + }; + + int s = getaddrinfo(NULL, port, &hints, &results); + if (s != 0) { + LOG_E(HW, "getaddrinfo: %s\n", gai_strerror(s)); + freeaddrinfo(results); return -1; } + int enable = 1; - if (setsockopt(t->listen_sock, SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(int)) != 0) { - LOG_E(HW, "setsockopt(SO_REUSEADDR) failed, errno(%d)\n", errno); - return -1; + int disable = 0; + for (rp = results; rp != NULL; rp = rp->ai_next) { + sock = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol); + if (sock == -1) { + continue; + } + + if (setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, &disable, sizeof(int)) != 0) { + continue; + } + + if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(int)) != 0) { + continue; + } + + if (bind(sock, rp->ai_addr, rp->ai_addrlen) == 0) { + break; + } + + close(sock); + sock = -1; } - struct sockaddr_in addr = {.sin_family = AF_INET, .sin_port = htons(t->port), .sin_addr = {.s_addr = INADDR_ANY}}; - int rc = bind(t->listen_sock, (struct sockaddr *)&addr, sizeof(addr)); - if (rc < 0) { - LOG_E(HW, "bind() failed, errno(%d)\n", errno); + + freeaddrinfo(results); + + if (sock <= 0) { + LOG_E(HW, "could not open a socket\n"); return -1; } + t->listen_sock = sock; + if (listen(t->listen_sock, 5) != 0) { LOG_E(HW, "listen() failed, errno(%d)\n", errno); return -1; } - struct epoll_event ev= {0}; + struct epoll_event ev = {0}; ev.events = EPOLLIN; ev.data.fd = t->listen_sock; if (epoll_ctl(t->epollfd, EPOLL_CTL_ADD, t->listen_sock, &ev) != 0) { @@ -577,24 +618,58 @@ static int startServer(openair0_device *device) { return 0; } -static int startClient(openair0_device *device) { +static int client_try_connect(const char *host, uint16_t port) +{ + int sock = -1; + int s; + struct addrinfo *result = NULL; + struct addrinfo *rp = NULL; + + char dport[6]; + snprintf(dport, sizeof(dport), "%d", port); + + struct addrinfo hints = { + .ai_family = AF_UNSPEC, + .ai_socktype = SOCK_STREAM, + }; + + s = getaddrinfo(host, dport, &hints, &result); + if (s != 0) { + LOG_E(HW, "getaddrinfo: %s\n", gai_strerror(s)); + return -1; + } + for (rp = result; rp != NULL; rp = rp->ai_next) { + sock = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol); + if (sock == -1) { + continue; + } + + if (connect(sock, rp->ai_addr, rp->ai_addrlen) != -1) { + break; + } + + close(sock); + sock = -1; + } + + freeaddrinfo(result); + + return sock; +} + +static int startClient(openair0_device *device) +{ rfsimulator_state_t *t = device->priv; t->role = SIMU_ROLE_CLIENT; int sock; - if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) { - LOG_E(HW, "socket(SOCK_STREAM) failed, errno(%d)\n", errno); - return -1; - } - struct sockaddr_in addr = {.sin_family = AF_INET, .sin_port = htons(t->port), .sin_addr = {.s_addr = INADDR_ANY}}; - addr.sin_addr.s_addr = inet_addr(t->ip); - bool connected=false; - while(!connected) { + while (true) { LOG_I(HW, "Trying to connect to %s:%d\n", t->ip, t->port); + sock = client_try_connect(t->ip, t->port); - if (connect(sock, (struct sockaddr *)&addr, sizeof(addr)) == 0) { + if (sock > 0) { LOG_I(HW, "Connection to %s:%d established\n", t->ip, t->port); - connected=true; + break; } LOG_I(HW, "connect() to %s:%d failed, errno(%d)\n", t->ip, t->port, errno);