diff --git a/docker/debug_core_image.sh b/docker/debug_core_image.sh index 3b2fc5db0a..307bd90bc5 100755 --- a/docker/debug_core_image.sh +++ b/docker/debug_core_image.sh @@ -54,7 +54,7 @@ fi # the source directory to show correct line numbers docker run --rm -it \ -v $COREDUMP:/tmp/coredump \ - -v $SOURCES:/opt/$TYPEPATH/src \ + -v $SOURCES:/oai-ran/ \ --entrypoint bash \ $IMAGE \ -c "gdb --dir=src/cmake_targets/ran_build/build $EXEC /tmp/coredump" diff --git a/openair2/COMMON/f1ap_messages_def.h b/openair2/COMMON/f1ap_messages_def.h index 405ecae3d5..18b16563d8 100644 --- a/openair2/COMMON/f1ap_messages_def.h +++ b/openair2/COMMON/f1ap_messages_def.h @@ -48,18 +48,18 @@ MESSAGE_DEF(F1AP_INITIAL_UL_RRC_MESSAGE , MESSAGE_PRIORITY_MED, f1ap_i MESSAGE_DEF(F1AP_UL_RRC_MESSAGE , MESSAGE_PRIORITY_MED, f1ap_ul_rrc_message_t , f1ap_ul_rrc_message) //MESSAGE_DEF(F1AP_INITIAL_CONTEXT_SETUP_RESP, MESSAGE_PRIORITY_MED, f1ap_initial_context_setup_resp_t, f1ap_initial_context_setup_resp) //MESSAGE_DEF(F1AP_INITIAL_CONTEXT_SETUP_FAILURE, MESSAGE_PRIORITY_MED, f1ap_initial_context_setup_failure_t, f1ap_initial_context_setup_failure) -MESSAGE_DEF(F1AP_UE_CONTEXT_RELEASE_REQ, MESSAGE_PRIORITY_MED, f1ap_ue_context_release_req_t, f1ap_ue_context_release_req) -MESSAGE_DEF(F1AP_UE_CONTEXT_RELEASE_CMD, MESSAGE_PRIORITY_MED, f1ap_ue_context_release_cmd_t, f1ap_ue_context_release_cmd) -MESSAGE_DEF(F1AP_UE_CONTEXT_RELEASE_COMPLETE, MESSAGE_PRIORITY_MED, f1ap_ue_context_release_complete_t, f1ap_ue_context_release_complete) +MESSAGE_DEF(F1AP_UE_CONTEXT_RELEASE_REQ, MESSAGE_PRIORITY_MED, f1ap_ue_context_rel_req_t, f1ap_ue_context_release_req) +MESSAGE_DEF(F1AP_UE_CONTEXT_RELEASE_CMD, MESSAGE_PRIORITY_MED, f1ap_ue_context_rel_cmd_t, f1ap_ue_context_release_cmd) +MESSAGE_DEF(F1AP_UE_CONTEXT_RELEASE_COMPLETE, MESSAGE_PRIORITY_MED, f1ap_ue_context_rel_cplt_t, f1ap_ue_context_release_complete) MESSAGE_DEF(F1AP_UE_CONTEXT_MODIFICATION_REQUIRED, MESSAGE_PRIORITY_MED, f1ap_ue_context_modif_required_t, f1ap_ue_context_modification_required) /* RRC -> F1AP messages */ MESSAGE_DEF(F1AP_DL_RRC_MESSAGE , MESSAGE_PRIORITY_MED, f1ap_dl_rrc_message_t , f1ap_dl_rrc_message ) //MESSAGE_DEF(F1AP_INITIAL_CONTEXT_SETUP_REQ , MESSAGE_PRIORITY_MED, f1ap_initial_context_setup_req_t , f1ap_initial_context_setup_req ) -MESSAGE_DEF(F1AP_UE_CONTEXT_SETUP_REQ, MESSAGE_PRIORITY_MED, f1ap_ue_context_setup_t, f1ap_ue_context_setup_req) -MESSAGE_DEF(F1AP_UE_CONTEXT_SETUP_RESP, MESSAGE_PRIORITY_MED, f1ap_ue_context_setup_t, f1ap_ue_context_setup_resp) -MESSAGE_DEF(F1AP_UE_CONTEXT_MODIFICATION_REQ, MESSAGE_PRIORITY_MED, f1ap_ue_context_modif_req_t, f1ap_ue_context_modification_req) -MESSAGE_DEF(F1AP_UE_CONTEXT_MODIFICATION_RESP, MESSAGE_PRIORITY_MED, f1ap_ue_context_modif_resp_t, f1ap_ue_context_modification_resp) +MESSAGE_DEF(F1AP_UE_CONTEXT_SETUP_REQ, MESSAGE_PRIORITY_MED, f1ap_ue_context_setup_req_t, f1ap_ue_context_setup_req) +MESSAGE_DEF(F1AP_UE_CONTEXT_SETUP_RESP, MESSAGE_PRIORITY_MED, f1ap_ue_context_setup_resp_t, f1ap_ue_context_setup_resp) +MESSAGE_DEF(F1AP_UE_CONTEXT_MODIFICATION_REQ, MESSAGE_PRIORITY_MED, f1ap_ue_context_mod_req_t, f1ap_ue_context_mod_req) +MESSAGE_DEF(F1AP_UE_CONTEXT_MODIFICATION_RESP, MESSAGE_PRIORITY_MED, f1ap_ue_context_mod_resp_t, f1ap_ue_context_modification_resp) MESSAGE_DEF(F1AP_UE_CONTEXT_MODIFICATION_CONFIRM, MESSAGE_PRIORITY_MED, f1ap_ue_context_modif_confirm_t, f1ap_ue_context_modification_confirm) MESSAGE_DEF(F1AP_UE_CONTEXT_MODIFICATION_REFUSE, MESSAGE_PRIORITY_MED, f1ap_ue_context_modif_refuse_t, f1ap_ue_context_modification_refuse) diff --git a/openair2/COMMON/f1ap_messages_types.h b/openair2/COMMON/f1ap_messages_types.h index 84d887f8f9..89826e7ff5 100644 --- a/openair2/COMMON/f1ap_messages_types.h +++ b/openair2/COMMON/f1ap_messages_types.h @@ -26,6 +26,7 @@ #include #include "common/5g_platform_types.h" #include "common/platform_constants.h" +#include "common/utils/ds/byte_array.h" //-------------------------------------------------------------------------------------------// // Defines to access message fields. @@ -54,7 +55,7 @@ #define F1AP_UL_RRC_MESSAGE(mSGpTR) (mSGpTR)->ittiMsg.f1ap_ul_rrc_message #define F1AP_UE_CONTEXT_SETUP_REQ(mSGpTR) (mSGpTR)->ittiMsg.f1ap_ue_context_setup_req #define F1AP_UE_CONTEXT_SETUP_RESP(mSGpTR) (mSGpTR)->ittiMsg.f1ap_ue_context_setup_resp -#define F1AP_UE_CONTEXT_MODIFICATION_REQ(mSGpTR) (mSGpTR)->ittiMsg.f1ap_ue_context_modification_req +#define F1AP_UE_CONTEXT_MODIFICATION_REQ(mSGpTR) (mSGpTR)->ittiMsg.f1ap_ue_context_mod_req #define F1AP_UE_CONTEXT_MODIFICATION_RESP(mSGpTR) (mSGpTR)->ittiMsg.f1ap_ue_context_modification_resp #define F1AP_UE_CONTEXT_MODIFICATION_FAIL(mSGpTR) (mSGpTR)->ittiMsg.f1ap_ue_context_modification_fail #define F1AP_UE_CONTEXT_MODIFICATION_REQUIRED(mSGpTR) (mSGpTR)->ittiMsg.f1ap_ue_context_modification_required @@ -362,7 +363,6 @@ typedef struct f1ap_ul_rrc_message_s { typedef struct f1ap_up_tnl_s { in_addr_t tl_address; // currently only IPv4 supported uint32_t teid; - uint16_t port; } f1ap_up_tnl_t; typedef enum preemption_capability_e { @@ -375,82 +375,19 @@ typedef enum preemption_vulnerability_e { PREEMPTABLE, } preemption_vulnerability_t; -typedef struct f1ap_qos_characteristics_s { - union { - struct { - long fiveqi; - long qos_priority_level; - } non_dynamic; - struct { - long fiveqi; // -1 -> optional - long qos_priority_level; - long packet_delay_budget; - struct { - long per_scalar; - long per_exponent; - } packet_error_rate; - } dynamic; - }; - fiveQI_t qos_type; -} f1ap_qos_characteristics_t; - -typedef struct f1ap_ngran_allocation_retention_priority_s { - uint16_t priority_level; - preemption_capability_t preemption_capability; - preemption_vulnerability_t preemption_vulnerability; -} f1ap_ngran_allocation_retention_priority_t; - -typedef struct f1ap_qos_flow_level_qos_parameters_s { - f1ap_qos_characteristics_t qos_characteristics; - f1ap_ngran_allocation_retention_priority_t alloc_reten_priority; -} f1ap_qos_flow_level_qos_parameters_t; - -typedef struct f1ap_flows_mapped_to_drb_s { - long qfi; // qos flow identifier - f1ap_qos_flow_level_qos_parameters_t qos_params; -} f1ap_flows_mapped_to_drb_t; - -typedef struct f1ap_drb_information_s { - f1ap_qos_flow_level_qos_parameters_t drb_qos; - f1ap_flows_mapped_to_drb_t *flows_mapped_to_drb; - 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]; - uint8_t up_ul_tnl_length; - f1ap_up_tnl_t up_dl_tnl[2]; - uint8_t up_dl_tnl_length; - f1ap_drb_information_t drb_info; - f1ap_rlc_mode_t rlc_mode; - nssai_t nssai; -} f1ap_drb_to_be_setup_t; -typedef struct f1ap_srb_to_be_setup_s { - long srb_id; - uint8_t lcid; -} f1ap_srb_to_be_setup_t; +typedef struct f1ap_cu_to_du_rrc_info_s { + byte_array_t *cg_configinfo; + byte_array_t *ue_cap; + byte_array_t *meas_config; + byte_array_t *ho_prep_info; +} f1ap_cu_to_du_rrc_info_t; -typedef struct f1ap_rb_failed_to_be_setup_s { - long rb_id; -} f1ap_rb_failed_to_be_setup_t; - -typedef struct f1ap_drb_to_be_released_t { - long rb_id; -} f1ap_drb_to_be_released_t; - -typedef struct cu_to_du_rrc_information_s { - uint8_t * cG_ConfigInfo; - uint32_t cG_ConfigInfo_length; - uint8_t * uE_CapabilityRAT_ContainerList; - uint32_t uE_CapabilityRAT_ContainerList_length; - uint8_t * measConfig; - uint32_t measConfig_length; - uint8_t *handoverPreparationInfo; - uint32_t handoverPreparationInfo_length; -}cu_to_du_rrc_information_t; +typedef struct f1ap_du_to_cu_rrc_info_t { + byte_array_t cell_group_config; + byte_array_t *meas_gap_config; +} f1ap_du_to_cu_rrc_info_t; typedef struct du_to_cu_rrc_information_s { uint8_t * cellGroupConfig; @@ -461,11 +398,6 @@ typedef struct du_to_cu_rrc_information_s { uint32_t requestedP_MaxFR1_length; }du_to_cu_rrc_information_t; -typedef enum QoS_information_e { - NG_RAN_QoS = 0, - EUTRAN_QoS = 1, -} QoS_information_t; - typedef enum ReconfigurationCompl_e { RRCreconf_info_not_present = 0, RRCreconf_failure = 1, @@ -477,39 +409,173 @@ typedef enum TransmActionInd_e { TransmActionInd_RESTART, } TransmActionInd_t; -typedef struct f1ap_ue_context_setup_s { +typedef enum lower_layer_status_e { + LOWER_LAYERS_SUSPEND, + LOWER_LAYERS_RESUME, +} lower_layer_status_t; + +typedef struct f1ap_srb_to_setup_t { + int id; +} f1ap_srb_to_setup_t; + +typedef struct f1ap_srb_setup_t { + int id; + int lcid; +} f1ap_srb_setup_t; + +/// 9.3.1.52 Packet Error Rate +typedef struct f1ap_per_t { + uint8_t scalar; + uint8_t exponent; +} f1ap_per_t; + +// 9.3.1.49 Non-Dynamic 5QI Descriptor +typedef struct f1ap_nondynamic_5qi_t { + int fiveQI; +} f1ap_nondynamic_5qi_t; + +// 9.3.1.47 Dynamic 5QI Descriptor +typedef struct f1ap_dynamic_5qi_t { + int prio; /// QoS Priority Level + int pdb; /// Packet Delay Budget + f1ap_per_t per; /// Packet Error Rate + bool *delay_critical; /// Delay Critical + int *avg_win; /// Averaging Window +} f1ap_dynamic_5qi_t; + +typedef struct f1ap_arp_t { + uint16_t prio; + preemption_capability_t preempt_cap; + preemption_vulnerability_t preempt_vuln; +} f1ap_arp_t; + +// 9.3.1.45 QoS Flow Level QoS Parameters +typedef struct f1ap_qos_flow_param_t { + fiveQI_t qos_type; + union { + f1ap_nondynamic_5qi_t nondyn; + f1ap_dynamic_5qi_t dyn; + }; + f1ap_arp_t arp; +} f1ap_qos_flow_param_t; + +// in 9.2.2.1 Flows Mapped to DRB Item +typedef struct f1ap_drb_flows_mapped_t { + int qfi; + f1ap_qos_flow_param_t param; +} f1ap_drb_flows_mapped_t; + +/// in 9.2.2.1 DRB Info in UE Context Setup Request +typedef struct f1ap_drb_info_nr_t { + f1ap_qos_flow_param_t drb_qos; + nssai_t nssai; + int flows_len; + f1ap_drb_flows_mapped_t *flows; +} f1ap_drb_info_nr_t; + +typedef enum { F1AP_PDCP_SN_12B, F1AP_PDCP_SN_18B } f1ap_pdcp_sn_len_t; +/// in 9.2.2.1 DRB to Be Setup Item IEs +typedef struct f1ap_drb_to_setup_t { + int id; + enum { F1AP_QOS_CHOICE_EUTRAN, F1AP_QOS_CHOICE_NR } qos_choice; + union { + // eutran not implemented + f1ap_drb_info_nr_t nr; + }; + int up_ul_tnl_len; + f1ap_up_tnl_t up_ul_tnl[2]; + f1ap_rlc_mode_t rlc_mode; + f1ap_pdcp_sn_len_t *dl_pdcp_sn_len; // in setup mandatory, in setupmod optional + f1ap_pdcp_sn_len_t *ul_pdcp_sn_len; +} f1ap_drb_to_setup_t; + +typedef struct f1ap_drb_setup_t { + int id; + int *lcid; + int up_dl_tnl_len; + f1ap_up_tnl_t up_dl_tnl[2]; +} f1ap_drb_setup_t; + +typedef struct f1ap_drb_to_release_t { + int id; +} f1ap_drb_to_release_t; + +typedef struct f1ap_ue_context_setup_req_s { uint32_t gNB_CU_ue_id; - uint32_t gNB_DU_ue_id; - // SpCell Info + uint32_t *gNB_DU_ue_id; + plmn_id_t plmn; uint64_t nr_cellid; uint8_t servCellIndex; - uint8_t *cellULConfigured; - uint32_t servCellId; - cu_to_du_rrc_information_t *cu_to_du_rrc_information; - uint8_t cu_to_du_rrc_information_length; - //uint8_t *du_to_cu_rrc_information; - du_to_cu_rrc_information_t *du_to_cu_rrc_information; - uint32_t du_to_cu_rrc_information_length; + + f1ap_cu_to_du_rrc_info_t cu_to_du_rrc_info; + + int srbs_len; + f1ap_srb_to_setup_t *srbs; + + int drbs_len; + f1ap_drb_to_setup_t *drbs; + + byte_array_t *rrc_container; + + uint64_t *gnb_du_ue_agg_mbr_ul; // C-ifDRBSetup +} f1ap_ue_context_setup_req_t; + +typedef struct f1ap_ue_context_setup_resp_s { + uint32_t gNB_CU_ue_id; + uint32_t gNB_DU_ue_id; + + f1ap_du_to_cu_rrc_info_t du_to_cu_rrc_info; + uint16_t *crnti; - f1ap_drb_to_be_setup_t *drbs_to_be_setup; - uint8_t drbs_to_be_setup_length; - f1ap_drb_to_be_setup_t *drbs_to_be_modified; - uint8_t drbs_to_be_modified_length; - QoS_information_t QoS_information_type; - uint8_t drbs_failed_to_be_setup_length; - f1ap_rb_failed_to_be_setup_t *drbs_failed_to_be_setup; - f1ap_srb_to_be_setup_t *srbs_to_be_setup; - uint8_t srbs_to_be_setup_length; - uint8_t srbs_failed_to_be_setup_length; - uint8_t drbs_to_be_released_length; - f1ap_drb_to_be_released_t *drbs_to_be_released; - f1ap_rb_failed_to_be_setup_t *srbs_failed_to_be_setup; - ReconfigurationCompl_t ReconfigComplOutcome; - uint8_t *rrc_container; - int rrc_container_length; + + int drbs_len; + f1ap_drb_setup_t *drbs; + + int srbs_len; + f1ap_srb_setup_t *srbs; +} f1ap_ue_context_setup_resp_t; + +typedef struct f1ap_ue_context_mod_req_t { + uint32_t gNB_CU_ue_id; + uint32_t gNB_DU_ue_id; + + plmn_id_t *plmn; + uint64_t *nr_cellid; + uint8_t *servCellIndex; + + f1ap_cu_to_du_rrc_info_t *cu_to_du_rrc_info; + TransmActionInd_t *transm_action_ind; -} f1ap_ue_context_setup_t, f1ap_ue_context_modif_req_t, f1ap_ue_context_modif_resp_t; + ReconfigurationCompl_t *reconfig_compl; + + byte_array_t *rrc_container; + + int srbs_len; + f1ap_srb_to_setup_t *srbs; // reuse the same type as for setup; there is a + // list for SRB modification + + int drbs_len; + f1ap_drb_to_setup_t *drbs; // as for SRBs + + int drbs_rel_len; + f1ap_drb_to_release_t *drbs_rel; + + lower_layer_status_t *status; +} f1ap_ue_context_mod_req_t; + +typedef struct f1ap_ue_context_mod_resp { + uint32_t gNB_CU_ue_id; + uint32_t gNB_DU_ue_id; + + f1ap_du_to_cu_rrc_info_t *du_to_cu_rrc_info; + + int drbs_len; + f1ap_drb_setup_t *drbs; + + int srbs_len; + f1ap_srb_setup_t *srbs; +} f1ap_ue_context_mod_resp_t; typedef enum F1ap_Cause_e { F1AP_CAUSE_NOTHING, /* No components present */ @@ -541,15 +607,29 @@ typedef struct f1ap_ue_context_modif_refuse_t { long cause_value; } f1ap_ue_context_modif_refuse_t; -typedef struct f1ap_ue_context_release_s { +typedef struct f1ap_ue_context_rel_req_t { uint32_t gNB_CU_ue_id; uint32_t gNB_DU_ue_id; - f1ap_Cause_t cause; - long cause_value; - uint8_t *rrc_container; - int rrc_container_length; - int srb_id; -} f1ap_ue_context_release_req_t, f1ap_ue_context_release_cmd_t, f1ap_ue_context_release_complete_t; + f1ap_Cause_t cause; + long cause_value; +} f1ap_ue_context_rel_req_t; + +typedef struct f1ap_ue_context_rel_cmd_t { + uint32_t gNB_CU_ue_id; + uint32_t gNB_DU_ue_id; + f1ap_Cause_t cause; + long cause_value; + + byte_array_t *rrc_container; + int *srb_id; // C-ifRRCContainer + + uint32_t *old_gNB_DU_ue_id; // if after reestablishment request +} f1ap_ue_context_rel_cmd_t; + +typedef struct f1ap_ue_context_rel_cplt_t { + uint32_t gNB_CU_ue_id; + uint32_t gNB_DU_ue_id; +} f1ap_ue_context_rel_cplt_t; typedef struct f1ap_paging_ind_s { uint16_t ueidentityindexvalue; diff --git a/openair2/F1AP/f1ap_cu_task.c b/openair2/F1AP/f1ap_cu_task.c index 4528a7766f..b7d19b7a6a 100644 --- a/openair2/F1AP/f1ap_cu_task.c +++ b/openair2/F1AP/f1ap_cu_task.c @@ -36,6 +36,7 @@ #include "f1ap_cu_ue_context_management.h" #include "lib/f1ap_rrc_message_transfer.h" #include "lib/f1ap_interface_management.h" +#include "lib/f1ap_ue_context.h" #include "f1ap_cu_paging.h" #include "f1ap_cu_task.h" #include "openair2/RRC/NR/nr_rrc_defs.h" @@ -186,18 +187,19 @@ void *F1AP_CU_task(void *arg) { break; case F1AP_UE_CONTEXT_SETUP_REQ: // from rrc - CU_send_UE_CONTEXT_SETUP_REQUEST(assoc_id, - &F1AP_UE_CONTEXT_SETUP_REQ(received_msg)); + CU_send_UE_CONTEXT_SETUP_REQUEST(assoc_id, &F1AP_UE_CONTEXT_SETUP_REQ(received_msg)); + free_ue_context_setup_req(&F1AP_UE_CONTEXT_SETUP_REQ(received_msg)); break; case F1AP_UE_CONTEXT_MODIFICATION_REQ: - CU_send_UE_CONTEXT_MODIFICATION_REQUEST(assoc_id, - &F1AP_UE_CONTEXT_MODIFICATION_REQ(received_msg)); + CU_send_UE_CONTEXT_MODIFICATION_REQUEST(assoc_id, &F1AP_UE_CONTEXT_MODIFICATION_REQ(received_msg)); + free_ue_context_mod_req(&F1AP_UE_CONTEXT_MODIFICATION_REQ(received_msg)); break; case F1AP_UE_CONTEXT_RELEASE_CMD: // from rrc CU_send_UE_CONTEXT_RELEASE_COMMAND(assoc_id, &F1AP_UE_CONTEXT_RELEASE_CMD(received_msg)); + free_ue_context_rel_cmd(&F1AP_UE_CONTEXT_RELEASE_CMD(received_msg)); break; case F1AP_PAGING_IND: diff --git a/openair2/F1AP/f1ap_cu_ue_context_management.c b/openair2/F1AP/f1ap_cu_ue_context_management.c index f4bffe6144..2d0959eb25 100644 --- a/openair2/F1AP/f1ap_cu_ue_context_management.c +++ b/openair2/F1AP/f1ap_cu_ue_context_management.c @@ -34,6 +34,7 @@ #include "f1ap_encoder.h" #include "f1ap_itti_messaging.h" #include "f1ap_cu_ue_context_management.h" +#include "lib/f1ap_ue_context.h" #include #include "rrc_extern.h" @@ -44,705 +45,40 @@ #include "openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_rc_extern.h" #endif -static void f1ap_write_drb_qos_param(const f1ap_qos_flow_level_qos_parameters_t *drb_qos_in, F1AP_QoSFlowLevelQoSParameters_t *asn1_qosparam) +int CU_send_UE_CONTEXT_SETUP_REQUEST(sctp_assoc_t assoc_id, const f1ap_ue_context_setup_req_t *req) { - int type = drb_qos_in->qos_characteristics.qos_type; + F1AP_F1AP_PDU_t *pdu = encode_ue_context_setup_req(req); - const f1ap_qos_characteristics_t *drb_qos_char_in = &drb_qos_in->qos_characteristics; - 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); - - /* 5QI */ - tmp->fiveQI = drb_qos_char_in->non_dynamic.fiveqi; - } else { - asn1_qosparam->qoS_Characteristics.present = F1AP_QoS_Characteristics_PR_dynamic_5QI; - asn1cCalloc(asn1_qosparam->qoS_Characteristics.choice.dynamic_5QI, tmp); - /* qoSPriorityLevel */ - tmp->qoSPriorityLevel = drb_qos_char_in->dynamic.qos_priority_level; - /* packetDelayBudget */ - tmp->packetDelayBudget = drb_qos_char_in->dynamic.packet_delay_budget; - /* packetErrorRate */ - tmp->packetErrorRate.pER_Scalar = drb_qos_char_in->dynamic.packet_error_rate.per_scalar; - tmp->packetErrorRate.pER_Exponent = drb_qos_char_in->dynamic.packet_error_rate.per_scalar; - - /* OPTIONAL delayCritical */ - // asn1cCallocOne(asn1_qosparam->qoS_Characteristics.choice.dynamic_5QI->delayCritical, 1L); - - /* OPTIONAL averagingWindow */ - // asn1cCallocOne(asn1_qosparam->qoS_Characteristics.choice.dynamic_5QI->averagingWindow, 1L); - - /* OPTIONAL maxDataBurstVolume */ - // asn1cCallocOne(asn1_qosparam->qoS_Characteristics.choice.dynamic_5QI->maxDataBurstVolume, 1L); - } - - { - asn1_qosparam->nGRANallocationRetentionPriority.priorityLevel = drb_qos_in->alloc_reten_priority.priority_level; - asn1_qosparam->nGRANallocationRetentionPriority.pre_emptionCapability = drb_qos_in->alloc_reten_priority.preemption_capability; - asn1_qosparam->nGRANallocationRetentionPriority.pre_emptionVulnerability = - drb_qos_in->alloc_reten_priority.preemption_vulnerability; - } // nGRANallocationRetentionPriority - - /* OPTIONAL */ - /* gBR_QoS_Flow_Information */ - if (0) { - asn1cCalloc(asn1_qosparam->gBR_QoS_Flow_Information, tmp); - asn_long2INTEGER(&tmp->maxFlowBitRateDownlink, 1L); - asn_long2INTEGER(&tmp->maxFlowBitRateUplink, 1L); - asn_long2INTEGER(&tmp->guaranteedFlowBitRateDownlink, 1L); - asn_long2INTEGER(&tmp->guaranteedFlowBitRateUplink, 1L); - - /* OPTIONAL */ - /* maxPacketLossRateDownlink */ - // asn1cCallocOne(asn1_qosparam->gBR_QoS_Flow_Information->maxPacketLossRateDownlink, 1L); - - /* OPTIONAL */ - /* maxPacketLossRateUplink */ - //asn1cCallocOne(asn1_qosparam->gBR_QoS_Flow_Information->maxPacketLossRateUplink, 1L); - } - - /* OPTIONAL */ - /* reflective_QoS_Attribute */ - if (0) { - asn1cCallocOne(asn1_qosparam->reflective_QoS_Attribute, 1L); - } -} - -static void f1ap_write_drb_nssai(const nssai_t *nssai, F1AP_SNSSAI_t *asn1_nssai) -{ - OCTET_STRING_fromBuf(&asn1_nssai->sST, (char *)&nssai->sst, 1); - - /* OPTIONAL */ - if (nssai->sd != 0xffffff) { - char sd_buffer[3]; - INT24_TO_BUFFER(nssai->sd, sd_buffer); - asn1cCalloc(asn1_nssai->sD, sD); - OCTET_STRING_fromBuf(sD, sd_buffer, 3); - } -} - -static void f1ap_write_flows_mapped(const f1ap_flows_mapped_to_drb_t *flows_mapped, F1AP_Flows_Mapped_To_DRB_List_t *asn1_flows_mapped, int n) -{ - for (int k = 0; k < n; k++) { - asn1cSequenceAdd(asn1_flows_mapped->list, F1AP_Flows_Mapped_To_DRB_Item_t, flow_item); - - const f1ap_flows_mapped_to_drb_t *qos_flow_in = flows_mapped + k; - - /* qoSFlowIndicator */ - flow_item->qoSFlowIdentifier = qos_flow_in->qfi; - - /* qoSFlowLevelQoSParameters */ - const f1ap_qos_flow_level_qos_parameters_t *flow_qos_params_in = &qos_flow_in->qos_params; - /* qoS_Characteristics */ - - F1AP_QoS_Characteristics_t *QosParams = &flow_item->qoSFlowLevelQoSParameters.qoS_Characteristics; - 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) { - QosParams->present = F1AP_QoS_Characteristics_PR_non_Dynamic_5QI; - asn1cCalloc(QosParams->choice.non_Dynamic_5QI, tmp); - - /* 5QI */ - tmp->fiveQI = flow_qos_char_in->non_dynamic.fiveqi; - } else { - QosParams->present = F1AP_QoS_Characteristics_PR_dynamic_5QI; - asn1cCalloc(QosParams->choice.dynamic_5QI, tmp); - /* qoSPriorityLevel */ - tmp->qoSPriorityLevel = flow_qos_char_in->dynamic.qos_priority_level; - /* packetDelayBudget */ - tmp->packetDelayBudget = flow_qos_char_in->dynamic.packet_delay_budget; - /* packetErrorRate */ - tmp->packetErrorRate.pER_Scalar = flow_qos_char_in->dynamic.packet_error_rate.per_scalar; - tmp->packetErrorRate.pER_Exponent = flow_qos_char_in->dynamic.packet_error_rate.per_exponent; - - /* OPTIONAL delayCritical */ - //asn1cCallocOne(QosParams->choice.dynamic_5QI->delayCritical, 1); - - /* OPTIONAL averagingWindow */ - //asn1cCallocOne(QosParams->choice.dynamic_5QI->averagingWindow, 1); - - /* OPTIONAL maxDataBurstVolume */ - //asn1cCallocOne(QosParams->choice.dynamic_5QI->maxDataBurstVolume, 1); - } - - /* nGRANallocationRetentionPriority */ - { - flow_item->qoSFlowLevelQoSParameters.nGRANallocationRetentionPriority.priorityLevel = - flow_qos_params_in->alloc_reten_priority.priority_level; - flow_item->qoSFlowLevelQoSParameters.nGRANallocationRetentionPriority.pre_emptionCapability = - flow_qos_params_in->alloc_reten_priority.preemption_capability; - flow_item->qoSFlowLevelQoSParameters.nGRANallocationRetentionPriority.pre_emptionVulnerability = - flow_qos_params_in->alloc_reten_priority.preemption_vulnerability; - } // nGRANallocationRetentionPriority - - /* OPTIONAL */ - /* gBR_QoS_Flow_Information */ - if (0) { - asn1cCalloc(flow_item->qoSFlowLevelQoSParameters.gBR_QoS_Flow_Information, tmp); - asn_long2INTEGER(&tmp->maxFlowBitRateDownlink, 1L); - asn_long2INTEGER(&tmp->maxFlowBitRateUplink, 1L); - asn_long2INTEGER(&tmp->guaranteedFlowBitRateDownlink, 1L); - asn_long2INTEGER(&tmp->guaranteedFlowBitRateUplink, 1L); - - /* OPTIONAL maxPacketLossRateDownlink */ - //asn1cCallocOne(flows_mapped_to_drb_item->qoSFlowLevelQoSParameters.gBR_QoS_Flow_Information->maxPacketLossRateDownlink, 1L); - - /* OPTIONAL maxPacketLossRateUplink */ - //asn1cCallocOne(flows_mapped_to_drb_item->qoSFlowLevelQoSParameters.gBR_QoS_Flow_Information->maxPacketLossRateUplink, 1L); - } - - /* OPTIONAL reflective_QoS_Attribute */ - //asn1cCallocOne(flows_mapped_to_drb_item->qoSFlowLevelQoSParameters.reflective_QoS_Attribute, 1L); - } -} - -int CU_send_UE_CONTEXT_SETUP_REQUEST(sctp_assoc_t assoc_id, f1ap_ue_context_setup_t *f1ap_ue_context_setup_req) -{ - F1AP_F1AP_PDU_t pdu= {0}; - /* Create */ - /* 0. Message Type */ - pdu.present = F1AP_F1AP_PDU_PR_initiatingMessage; - asn1cCalloc(pdu.choice.initiatingMessage, tmp); - tmp->procedureCode = F1AP_ProcedureCode_id_UEContextSetup; - tmp->criticality = F1AP_Criticality_reject; - tmp->value.present = F1AP_InitiatingMessage__value_PR_UEContextSetupRequest; - F1AP_UEContextSetupRequest_t *out = &pdu.choice.initiatingMessage->value.choice.UEContextSetupRequest; - /* mandatory */ - /* c1. GNB_CU_UE_F1AP_ID */ - asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextSetupRequestIEs_t, ie1); - ie1->id = F1AP_ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID; - ie1->criticality = F1AP_Criticality_reject; - ie1->value.present = F1AP_UEContextSetupRequestIEs__value_PR_GNB_CU_UE_F1AP_ID; - ie1->value.choice.GNB_CU_UE_F1AP_ID = f1ap_ue_context_setup_req->gNB_CU_ue_id; - - /* optional */ - /* c2. GNB_DU_UE_F1AP_ID */ - if (f1ap_ue_context_setup_req->gNB_DU_ue_id) { - asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextSetupRequestIEs_t, ie2); - ie2->id = F1AP_ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID; - ie2->criticality = F1AP_Criticality_ignore; - ie2->value.present = F1AP_UEContextSetupRequestIEs__value_PR_GNB_DU_UE_F1AP_ID; - ie2->value.choice.GNB_DU_UE_F1AP_ID = f1ap_ue_context_setup_req->gNB_DU_ue_id; - } - - /* mandatory */ - /* c3. SpCell_ID */ - asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextSetupRequestIEs_t, ie3); - ie3->id = F1AP_ProtocolIE_ID_id_SpCell_ID; - ie3->criticality = F1AP_Criticality_reject; - ie3->value.present = F1AP_UEContextSetupRequestIEs__value_PR_NRCGI; - /* - nRCGI */ - addnRCGI(ie3->value.choice.NRCGI, f1ap_ue_context_setup_req); - /* mandatory */ - /* c4. ServCellIndex */ - asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextSetupRequestIEs_t, ie4); - ie4->id = F1AP_ProtocolIE_ID_id_ServCellIndex; - ie4->criticality = F1AP_Criticality_reject; - ie4->value.present = F1AP_UEContextSetupRequestIEs__value_PR_ServCellIndex; - ie4->value.choice.ServCellIndex = 0; - - /* optional */ - /* c5. CellULConfigured */ - if (0) { - asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextSetupRequestIEs_t, ie5); - ie5->id = F1AP_ProtocolIE_ID_id_SpCellULConfigured; - ie5->criticality = F1AP_Criticality_ignore; - ie5->value.present = F1AP_UEContextSetupRequestIEs__value_PR_CellULConfigured; - ie5->value.choice.CellULConfigured = F1AP_CellULConfigured_ul; - } - - /* mandatory */ - /* c6. CUtoDURRCInformation */ - asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextSetupRequestIEs_t, ie6); - ie6->id = F1AP_ProtocolIE_ID_id_CUtoDURRCInformation; - ie6->criticality = F1AP_Criticality_reject; - ie6->value.present = F1AP_UEContextSetupRequestIEs__value_PR_CUtoDURRCInformation; - - if (f1ap_ue_context_setup_req->cu_to_du_rrc_information!=NULL) { - /* optional */ - /* 6.1 cG_ConfigInfo */ - if(f1ap_ue_context_setup_req->cu_to_du_rrc_information->cG_ConfigInfo_length > 0) { - DevAssert(f1ap_ue_context_setup_req->cu_to_du_rrc_information->cG_ConfigInfo != NULL); - asn1cCalloc(ie6->value.choice.CUtoDURRCInformation.cG_ConfigInfo, cG_ConfigInfo); - OCTET_STRING_fromBuf(cG_ConfigInfo, (const char *)f1ap_ue_context_setup_req->cu_to_du_rrc_information->cG_ConfigInfo, - f1ap_ue_context_setup_req->cu_to_du_rrc_information->cG_ConfigInfo_length); - } - - /* optional */ - /* 6.2 uE_CapabilityRAT_ContainerList */ - if(f1ap_ue_context_setup_req->cu_to_du_rrc_information->uE_CapabilityRAT_ContainerList!=NULL){ - asn1cCalloc(ie6->value.choice.CUtoDURRCInformation.uE_CapabilityRAT_ContainerList, uE_CapabilityRAT_ContainerList ); - OCTET_STRING_fromBuf(uE_CapabilityRAT_ContainerList, (const char *)f1ap_ue_context_setup_req->cu_to_du_rrc_information->uE_CapabilityRAT_ContainerList, - f1ap_ue_context_setup_req->cu_to_du_rrc_information->uE_CapabilityRAT_ContainerList_length); - } - /* optional */ - /* 6.3 measConfig */ - if(f1ap_ue_context_setup_req->cu_to_du_rrc_information->measConfig!=NULL){ - asn1cCalloc(ie6->value.choice.CUtoDURRCInformation.measConfig, measConfig); - OCTET_STRING_fromBuf(measConfig, (const char*)f1ap_ue_context_setup_req->cu_to_du_rrc_information->measConfig, - f1ap_ue_context_setup_req->cu_to_du_rrc_information->measConfig_length); - } - - /* optional */ - /* HandoverPreparationInformation */ - if (f1ap_ue_context_setup_req->cu_to_du_rrc_information->handoverPreparationInfo_length > 0) { - DevAssert(f1ap_ue_context_setup_req->cu_to_du_rrc_information->handoverPreparationInfo != NULL); - F1AP_ProtocolExtensionContainer_10696P60_t *p = calloc(1, sizeof(*p)); - ie6->value.choice.CUtoDURRCInformation.iE_Extensions = (struct F1AP_ProtocolExtensionContainer *)p; - asn1cSequenceAdd(p->list, F1AP_CUtoDURRCInformation_ExtIEs_t, ie_ext); - ie_ext->id = F1AP_ProtocolIE_ID_id_HandoverPreparationInformation; - ie_ext->criticality = F1AP_Criticality_ignore; - ie_ext->extensionValue.present = F1AP_CUtoDURRCInformation_ExtIEs__extensionValue_PR_HandoverPreparationInformation; - OCTET_STRING_fromBuf(&ie_ext->extensionValue.choice.HandoverPreparationInformation, - (const char *)f1ap_ue_context_setup_req->cu_to_du_rrc_information->handoverPreparationInfo, - f1ap_ue_context_setup_req->cu_to_du_rrc_information->handoverPreparationInfo_length); - } - } - - /* optional */ - if (0) { - /* c7. Candidate_SpCell_List */ - asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextSetupRequestIEs_t, ie7); - ie7->id = F1AP_ProtocolIE_ID_id_Candidate_SpCell_List; // 90 - ie7->criticality = F1AP_Criticality_ignore; - ie7->value.present = F1AP_UEContextSetupRequestIEs__value_PR_Candidate_SpCell_List; - - for (int i = 0; i < 1; i++) { - asn1cSequenceAdd(ie7->value.choice.Candidate_SpCell_List.list, F1AP_Candidate_SpCell_ItemIEs_t, candidate_spCell_item_ies); - candidate_spCell_item_ies->id = F1AP_ProtocolIE_ID_id_Candidate_SpCell_Item; // 91 - candidate_spCell_item_ies->criticality = F1AP_Criticality_ignore; - candidate_spCell_item_ies->value.present = F1AP_Candidate_SpCell_ItemIEs__value_PR_Candidate_SpCell_Item; - /* 7.1 Candidate_SpCell_Item */ - F1AP_Candidate_SpCell_Item_t *candidate_spCell_item = &candidate_spCell_item_ies->value.choice.Candidate_SpCell_Item; - /* - candidate_SpCell_ID */ - // FixMe: first cell ??? - addnRCGI(candidate_spCell_item->candidate_SpCell_ID, f1ap_ue_context_setup_req); - /* TODO add correct mcc/mnc */ - } - } - - /* optional */ - /* c8. DRXCycle */ - if (0) { - asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextSetupRequestIEs_t, ie8); - ie8->id = F1AP_ProtocolIE_ID_id_DRXCycle; - ie8->criticality = F1AP_Criticality_ignore; - ie8->value.present = F1AP_UEContextSetupRequestIEs__value_PR_DRXCycle; - /* 8.1 longDRXCycleLength */ - ie8->value.choice.DRXCycle.longDRXCycleLength = F1AP_LongDRXCycleLength_ms10; // enum - - /* optional */ - /* 8.2 shortDRXCycleLength */ - if (0) { - asn1cCallocOne(ie6->value.choice.DRXCycle.shortDRXCycleLength, - F1AP_ShortDRXCycleLength_ms2); // enum - } - - /* optional */ - /* 8.3 shortDRXCycleTimer */ - if (0) { - asn1cCallocOne(ie8->value.choice.DRXCycle.shortDRXCycleTimer, - 123L); - } - } - - /* optional */ - /* c9. ResourceCoordinationTransferContainer */ - if (0) { - asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextSetupRequestIEs_t, ie9); - ie9->id = F1AP_ProtocolIE_ID_id_ResourceCoordinationTransferContainer; - ie9->criticality = F1AP_Criticality_ignore; - ie9->value.present = F1AP_UEContextSetupRequestIEs__value_PR_ResourceCoordinationTransferContainer; - ie9->value.choice.ResourceCoordinationTransferContainer.buf = malloc(4); - ie9->value.choice.ResourceCoordinationTransferContainer.size = 4; - strncpy((char *)ie9->value.choice.ResourceCoordinationTransferContainer.buf, "123", 4); - OCTET_STRING_fromBuf(&ie9->value.choice.ResourceCoordinationTransferContainer, "asdsa1d32sa1d31asd31as", - strlen("asdsa1d32sa1d31asd31as")); - } - - /* optional */ - if (0) { - /* c10. SCell_ToBeSetup_List */ - asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextSetupRequestIEs_t, ie10); - ie10->id = F1AP_ProtocolIE_ID_id_SCell_ToBeSetup_List; - ie10->criticality = F1AP_Criticality_ignore; - ie10->value.present = F1AP_UEContextSetupRequestIEs__value_PR_SCell_ToBeSetup_List; - - for (int i = 0; i < 1; i++) { - asn1cSequenceAdd(ie10->value.choice.SCell_ToBeSetup_List.list, F1AP_SCell_ToBeSetup_ItemIEs_t, scell_toBeSetup_item_ies); - scell_toBeSetup_item_ies->id = F1AP_ProtocolIE_ID_id_SCell_ToBeSetup_Item; // 53 - scell_toBeSetup_item_ies->criticality = F1AP_Criticality_ignore; - scell_toBeSetup_item_ies->value.present = F1AP_SCell_ToBeSetup_ItemIEs__value_PR_SCell_ToBeSetup_Item; - /* 10.1 SCell_ToBeSetup_Item */ - F1AP_SCell_ToBeSetup_Item_t *scell_toBeSetup_item = &scell_toBeSetup_item_ies->value.choice.SCell_ToBeSetup_Item; - /* 10.1.1 sCell_ID */ - addnRCGI(scell_toBeSetup_item->sCell_ID, f1ap_ue_context_setup_req); - /* TODO correct MCC/MNC */ - /* 10.1.2 sCellIndex */ - scell_toBeSetup_item->sCellIndex = 3; // issue here - - /* OPTIONAL */ - /* 10.1.3 sCellULConfigured*/ - if (0) { - asn1cCallocOne(scell_toBeSetup_item->sCellULConfigured, - F1AP_CellULConfigured_ul_and_sul); // enum - } - } - } - - /* mandatory */ - /* c11. SRBs_ToBeSetup_List */ - if(f1ap_ue_context_setup_req->srbs_to_be_setup_length > 0){ - asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextSetupRequestIEs_t, ie11); - ie11->id = F1AP_ProtocolIE_ID_id_SRBs_ToBeSetup_List; - ie11->criticality = F1AP_Criticality_reject; // ? - ie11->value.present = F1AP_UEContextSetupRequestIEs__value_PR_SRBs_ToBeSetup_List; - - for (int i=0; isrbs_to_be_setup_length; i++) { - asn1cSequenceAdd(ie11->value.choice.SRBs_ToBeSetup_List.list, F1AP_SRBs_ToBeSetup_ItemIEs_t, srbs_toBeSetup_item_ies); - srbs_toBeSetup_item_ies->id = F1AP_ProtocolIE_ID_id_SRBs_ToBeSetup_Item; // 73 - srbs_toBeSetup_item_ies->criticality = F1AP_Criticality_reject; - srbs_toBeSetup_item_ies->value.present = F1AP_SRBs_ToBeSetup_ItemIEs__value_PR_SRBs_ToBeSetup_Item; - /* 11.1 SRBs_ToBeSetup_Item */ - F1AP_SRBs_ToBeSetup_Item_t *srbs_toBeSetup_item=&srbs_toBeSetup_item_ies->value.choice.SRBs_ToBeSetup_Item; - /* 11.1.1 sRBID */ - srbs_toBeSetup_item->sRBID = f1ap_ue_context_setup_req->srbs_to_be_setup[i].srb_id; - /* OPTIONAL */ - /* 11.1.2 duplicationIndication */ - asn1cCallocOne(srbs_toBeSetup_item->duplicationIndication, - F1AP_DuplicationIndication_true); // enum - } - } - - /* mandatory */ - /* c12. DRBs_ToBeSetup_List */ - if(f1ap_ue_context_setup_req->drbs_to_be_setup_length){ - asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextSetupRequestIEs_t, ie12); - ie12->id = F1AP_ProtocolIE_ID_id_DRBs_ToBeSetup_List; - ie12->criticality = F1AP_Criticality_reject; - ie12->value.present = F1AP_UEContextSetupRequestIEs__value_PR_DRBs_ToBeSetup_List; - - for (int i = 0; i < f1ap_ue_context_setup_req->drbs_to_be_setup_length; i++) { - const f1ap_drb_to_be_setup_t *drb = &f1ap_ue_context_setup_req->drbs_to_be_setup[i]; - asn1cSequenceAdd(ie12->value.choice.DRBs_ToBeSetup_List.list, F1AP_DRBs_ToBeSetup_ItemIEs_t, drbs_toBeSetup_item_ies); - drbs_toBeSetup_item_ies->id = F1AP_ProtocolIE_ID_id_DRBs_ToBeSetup_Item; - drbs_toBeSetup_item_ies->criticality = F1AP_Criticality_reject; - drbs_toBeSetup_item_ies->value.present = F1AP_DRBs_ToBeSetup_ItemIEs__value_PR_DRBs_ToBeSetup_Item; - /* 12.1 DRBs_ToBeSetup_Item */ - F1AP_DRBs_ToBeSetup_Item_t *drbs_toBeSetup_item=&drbs_toBeSetup_item_ies->value.choice.DRBs_ToBeSetup_Item; - /* 12.1.1 dRBID */ - drbs_toBeSetup_item->dRBID = drb->drb_id; - /* 12.1.2 qoSInformation */ - int some_decide_qos = 0; // BK: Need Check - - if (some_decide_qos) { - drbs_toBeSetup_item->qoSInformation.present = F1AP_QoSInformation_PR_eUTRANQoS; - /* 12.1.2.1 eUTRANQoS */ - asn1cCalloc(drbs_toBeSetup_item->qoSInformation.choice.eUTRANQoS, eUTRANQoS); - /* 12.1.2.1.1 qCI */ - eUTRANQoS->qCI = 254L; - /* 12.1.2.1.2 allocationAndRetentionPriority */ - { - /* 12.1.2.1.2.1 priorityLevel */ - eUTRANQoS->allocationAndRetentionPriority.priorityLevel = F1AP_PriorityLevel_highest; // enum - /* 12.1.2.1.2.2 pre_emptionCapability */ - eUTRANQoS->allocationAndRetentionPriority.pre_emptionCapability = F1AP_Pre_emptionCapability_may_trigger_pre_emption; // enum - /* 12.1.2.1.2.2 pre_emptionVulnerability */ - eUTRANQoS->allocationAndRetentionPriority.pre_emptionVulnerability = F1AP_Pre_emptionVulnerability_not_pre_emptable; // enum - } - - /* OPTIONAL */ - /* 12.1.2.1.3 gbrQosInformation */ - if (0) { - eUTRANQoS->gbrQosInformation = (F1AP_GBR_QosInformation_t *)calloc(1, sizeof(F1AP_GBR_QosInformation_t)); - asn_long2INTEGER(&eUTRANQoS->gbrQosInformation->e_RAB_MaximumBitrateDL, 1L); - asn_long2INTEGER(&eUTRANQoS->gbrQosInformation->e_RAB_MaximumBitrateUL, 1L); - asn_long2INTEGER(&eUTRANQoS->gbrQosInformation->e_RAB_GuaranteedBitrateDL, 1L); - asn_long2INTEGER(&eUTRANQoS->gbrQosInformation->e_RAB_GuaranteedBitrateUL, 1L); - } - } else { - /* 12.1.2 DRB_Information */ - const f1ap_drb_information_t *drb_info = &drb->drb_info; - drbs_toBeSetup_item->qoSInformation.present = F1AP_QoSInformation_PR_choice_extension; - F1AP_QoSInformation_ExtIEs_t *ie = (F1AP_QoSInformation_ExtIEs_t *)calloc(1, sizeof(*ie)); - ie->id = F1AP_ProtocolIE_ID_id_DRB_Information; - ie->criticality = F1AP_Criticality_reject; - ie->value.present = F1AP_QoSInformation_ExtIEs__value_PR_DRB_Information; - F1AP_DRB_Information_t *DRB_Information = &ie->value.choice.DRB_Information; - drbs_toBeSetup_item->qoSInformation.choice.choice_extension = (struct F1AP_ProtocolIE_SingleContainer *)ie; - - /* 12.1.2.1 dRB_QoS */ - f1ap_write_drb_qos_param(&drb_info->drb_qos, &DRB_Information->dRB_QoS); - - /* 12.1.2.2 sNSSAI */ - f1ap_write_drb_nssai(&drb->nssai, &DRB_Information->sNSSAI); - - /* OPTIONAL */ - /* 12.1.2.3 notificationControl */ - if (0) { - asn1cCallocOne(DRB_Information->notificationControl, - F1AP_NotificationControl_active); // enum - } - - /* 12.1.2.4 flows_Mapped_To_DRB_List */ // BK: need verifiy - f1ap_write_flows_mapped(drb_info->flows_mapped_to_drb, &DRB_Information->flows_Mapped_To_DRB_List, drb_info->flows_to_be_setup_length); - } // if some_decide_qos - - /* 12.1.3 uLUPTNLInformation_ToBeSetup_List */ - for (int j = 0; j < f1ap_ue_context_setup_req->drbs_to_be_setup[i].up_ul_tnl_length; j++) { - DevAssert(f1ap_ue_context_setup_req->drbs_to_be_setup[i].up_ul_tnl[j].teid > 0); - /* 12.3.1 ULTunnels_ToBeSetup_Item */ - asn1cSequenceAdd(drbs_toBeSetup_item->uLUPTNLInformation_ToBeSetup_List.list, - F1AP_ULUPTNLInformation_ToBeSetup_Item_t, uLUPTNLInformation_ToBeSetup_Item); - uLUPTNLInformation_ToBeSetup_Item->uLUPTNLInformation.present = F1AP_UPTransportLayerInformation_PR_gTPTunnel; - asn1cCalloc( uLUPTNLInformation_ToBeSetup_Item->uLUPTNLInformation.choice.gTPTunnel, - gTPTunnel); - /* 12.3.1.1.1 transportLayerAddress */ - TRANSPORT_LAYER_ADDRESS_IPv4_TO_BIT_STRING(f1ap_ue_context_setup_req->drbs_to_be_setup[i].up_ul_tnl[j].tl_address, - &gTPTunnel->transportLayerAddress); - /* 12.3.1.1.2 gTP_TEID */ - INT32_TO_OCTET_STRING(f1ap_ue_context_setup_req->drbs_to_be_setup[i].up_ul_tnl[j].teid, - &gTPTunnel->gTP_TEID); - } - - /* 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 F1AP_RLC_MODE_AM: - drbs_toBeSetup_item->rLCMode = F1AP_RLCMode_rlc_am; - break; - 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 */ - /* 12.1.5 ULConfiguration */ - if (0) { - asn1cCalloc(drbs_toBeSetup_item->uLConfiguration, tmp); - tmp->uLUEConfiguration = F1AP_ULUEConfiguration_no_data; - } - - /* OPTIONAL */ - /* 12.1.6 duplicationActivation */ - if (0) { - asn1cCalloc(drbs_toBeSetup_item->duplicationActivation, tmp); - *tmp = F1AP_DuplicationActivation_active; // enum - } - } - } - - /* OPTIONAL */ - /* InactivityMonitoringRequest */ - if (0) { - asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextSetupRequestIEs_t, ie12); - ie12->id = F1AP_ProtocolIE_ID_id_InactivityMonitoringRequest; - ie12->criticality = F1AP_Criticality_reject; - ie12->value.present = F1AP_UEContextSetupRequestIEs__value_PR_InactivityMonitoringRequest; - ie12->value.choice.InactivityMonitoringRequest = F1AP_InactivityMonitoringRequest_true; // 0 - } - - /* OPTIONAL */ - /* RAT_FrequencyPriorityInformation */ - if (0) { - asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextSetupRequestIEs_t, ie13); - ie13->id = F1AP_ProtocolIE_ID_id_RAT_FrequencyPriorityInformation; - ie13->criticality = F1AP_Criticality_reject; - ie13->value.present = F1AP_UEContextSetupRequestIEs__value_PR_RAT_FrequencyPriorityInformation; - int endc = 1; // RK: Get this from somewhere ... - - if (endc) { - ie13->value.choice.RAT_FrequencyPriorityInformation.present = F1AP_RAT_FrequencyPriorityInformation_PR_eNDC; - ie13->value.choice.RAT_FrequencyPriorityInformation.choice.eNDC = 11L; - } else { - ie13->value.choice.RAT_FrequencyPriorityInformation.present = F1AP_RAT_FrequencyPriorityInformation_PR_nGRAN; - ie13->value.choice.RAT_FrequencyPriorityInformation.choice.nGRAN = 11L; - } - } - - /* OPTIONAL */ - /* RRCContainer */ - if(f1ap_ue_context_setup_req->rrc_container_length > 0) { - asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextSetupRequestIEs_t, ie14); - ie14->id = F1AP_ProtocolIE_ID_id_RRCContainer; - ie14->criticality = F1AP_Criticality_ignore; - ie14->value.present = F1AP_UEContextSetupRequestIEs__value_PR_RRCContainer; - OCTET_STRING_fromBuf(&ie14->value.choice.RRCContainer, (const char *)f1ap_ue_context_setup_req->rrc_container, - f1ap_ue_context_setup_req->rrc_container_length); - } - - /* OPTIONAL */ - /* MaskedIMEISV */ - if (0) { - asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextSetupRequestIEs_t, ie15); - ie15->id = F1AP_ProtocolIE_ID_id_MaskedIMEISV; - ie15->criticality = F1AP_Criticality_reject; - ie15->value.present = F1AP_UEContextSetupRequestIEs__value_PR_MaskedIMEISV; - MaskedIMEISV_TO_BIT_STRING(12340000l, &ie15->value.choice.MaskedIMEISV); // size (64) - } - - /* encode */ - uint8_t *buffer=NULL; - uint32_t len=0; - - if (f1ap_encode_pdu(&pdu, &buffer, &len) < 0) { + uint8_t *buffer = NULL; + uint32_t len = 0; + if (f1ap_encode_pdu(pdu, &buffer, &len) < 0) { LOG_E(F1AP, "Failed to encode F1 UE CONTEXT SETUP REQUEST\n"); return -1; } + f1ap_itti_send_sctp_data_req(assoc_id, buffer, len); + ASN_STRUCT_FREE(asn_DEF_F1AP_F1AP_PDU, pdu); + #ifdef E2_AGENT - rrc_gNB_ue_context_t *ue_context_p = rrc_gNB_get_ue_context(RC.nrrrc[0], f1ap_ue_context_setup_req->gNB_CU_ue_id); + rrc_gNB_ue_context_t *ue_context_p = rrc_gNB_get_ue_context(RC.nrrrc[0], req->gNB_CU_ue_id); signal_ue_id(&ue_context_p->ue_context, F1_NETWORK_INTERFACE_TYPE, 0); #endif - // xer_fprint(stdout, &asn_DEF_F1AP_F1AP_PDU, (void *)pdu); - // asn_encode_to_new_buffer_result_t res = { NULL, {0, NULL, NULL} }; - // res = asn_encode_to_new_buffer(NULL, ATS_CANONICAL_XER, &asn_DEF_F1AP_F1AP_PDU, pdu); - // buffer = res.buffer; - // len = res.result.encoded; - // if (res.result.encoded <= 0) { - // LOG_E(F1AP, "ASN1 message encoding failed (%s, %lu)!\n", res.result.failed_type->name, res.result.encoded); - // return -1; - // } - LOG_D(F1AP,"F1AP UEContextSetupRequest Encoded %u bits\n", len); - f1ap_itti_send_sctp_data_req(assoc_id, buffer, len); return 0; } int CU_handle_UE_CONTEXT_SETUP_RESPONSE(instance_t instance, sctp_assoc_t assoc_id, uint32_t stream, F1AP_F1AP_PDU_t *pdu) { - MessageDef *msg_p; - F1AP_UEContextSetupResponse_t *container; - F1AP_UEContextSetupResponseIEs_t *ie; - DevAssert(pdu); - msg_p = itti_alloc_new_message(TASK_DU_F1, 0, F1AP_UE_CONTEXT_SETUP_RESP); - msg_p->ittiMsgHeader.originInstance = assoc_id; - f1ap_ue_context_setup_t *f1ap_ue_context_setup_resp = &F1AP_UE_CONTEXT_SETUP_RESP(msg_p); - container = &pdu->choice.successfulOutcome->value.choice.UEContextSetupResponse; - int i; - /* GNB_CU_UE_F1AP_ID */ - F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextSetupResponseIEs_t, ie, container, - F1AP_ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID, true); - f1ap_ue_context_setup_resp->gNB_CU_ue_id = ie->value.choice.GNB_CU_UE_F1AP_ID; - LOG_D(F1AP, "f1ap_ue_context_setup_resp->gNB_CU_ue_id is: %d \n", f1ap_ue_context_setup_resp->gNB_CU_ue_id); - /* GNB_DU_UE_F1AP_ID */ - F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextSetupResponseIEs_t, ie, container, - F1AP_ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID, true); - f1ap_ue_context_setup_resp->gNB_DU_ue_id = ie->value.choice.GNB_DU_UE_F1AP_ID; - LOG_D(F1AP, "f1ap_ue_context_setup_resp->gNB_DU_ue_id is: %d \n", f1ap_ue_context_setup_resp->gNB_DU_ue_id); - F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextSetupResponseIEs_t, ie, container, F1AP_ProtocolIE_ID_id_C_RNTI, false); - if (ie) { - f1ap_ue_context_setup_resp->crnti = calloc(1, sizeof(uint16_t)); - *f1ap_ue_context_setup_resp->crnti = ie->value.choice.C_RNTI; - } - - // DUtoCURRCInformation - F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextSetupResponseIEs_t, ie, container, - F1AP_ProtocolIE_ID_id_DUtoCURRCInformation, true); - - if (ie == NULL) { - LOG_E(F1AP,"%s %d: ie is a NULL pointer \n",__FILE__,__LINE__); + f1ap_ue_context_setup_resp_t resp = {0}; + if (!decode_ue_context_setup_resp(pdu, &resp)) { + LOG_E(F1AP, "cannot decode F1 UE Context Setup Resp\n"); + free_ue_context_setup_resp(&resp); return -1; } - f1ap_ue_context_setup_resp->du_to_cu_rrc_information = (du_to_cu_rrc_information_t *)calloc(1,sizeof(du_to_cu_rrc_information_t)); - f1ap_ue_context_setup_resp->du_to_cu_rrc_information->cellGroupConfig = (uint8_t *)calloc(1,ie->value.choice.DUtoCURRCInformation.cellGroupConfig.size); - memcpy(f1ap_ue_context_setup_resp->du_to_cu_rrc_information->cellGroupConfig, ie->value.choice.DUtoCURRCInformation.cellGroupConfig.buf, ie->value.choice.DUtoCURRCInformation.cellGroupConfig.size); - f1ap_ue_context_setup_resp->du_to_cu_rrc_information->cellGroupConfig_length = ie->value.choice.DUtoCURRCInformation.cellGroupConfig.size; - // DRBs_Setup_List - F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextSetupResponseIEs_t, ie, container, - F1AP_ProtocolIE_ID_id_DRBs_Setup_List, false); - - if(ie!=NULL) { - f1ap_ue_context_setup_resp->drbs_to_be_setup_length = ie->value.choice.DRBs_Setup_List.list.count; - f1ap_ue_context_setup_resp->drbs_to_be_setup = calloc(f1ap_ue_context_setup_resp->drbs_to_be_setup_length, - sizeof(f1ap_drb_to_be_setup_t)); - AssertFatal(f1ap_ue_context_setup_resp->drbs_to_be_setup, - "could not allocate memory for f1ap_ue_context_setup_resp->drbs_setup\n"); - - for (i = 0; i < f1ap_ue_context_setup_resp->drbs_to_be_setup_length; ++i) { - f1ap_drb_to_be_setup_t *drb_p = &f1ap_ue_context_setup_resp->drbs_to_be_setup[i]; - F1AP_DRBs_Setup_Item_t *drbs_setup_item_p; - drbs_setup_item_p = &((F1AP_DRBs_Setup_ItemIEs_t *)ie->value.choice.DRBs_Setup_List.list.array[i])->value.choice.DRBs_Setup_Item; - drb_p->drb_id = drbs_setup_item_p->dRBID; - // TODO in the following, assume only one UP UL TNL is present. - // this matches/assumes OAI CU/DU implementation, can be up to 2! - drb_p->up_dl_tnl_length = 1; - AssertFatal(drbs_setup_item_p->dLUPTNLInformation_ToBeSetup_List.list.count > 0, - "no DL UP TNL Information in DRBs to be Setup list\n"); - F1AP_DLUPTNLInformation_ToBeSetup_Item_t *dl_up_tnl_info_p = (F1AP_DLUPTNLInformation_ToBeSetup_Item_t *)drbs_setup_item_p->dLUPTNLInformation_ToBeSetup_List.list.array[0]; - F1AP_GTPTunnel_t *dl_up_tnl0 = dl_up_tnl_info_p->dLUPTNLInformation.choice.gTPTunnel; - BIT_STRING_TO_TRANSPORT_LAYER_ADDRESS_IPv4(&dl_up_tnl0->transportLayerAddress, drb_p->up_dl_tnl[0].tl_address); - OCTET_STRING_TO_UINT32(&dl_up_tnl0->gTP_TEID, drb_p->up_dl_tnl[0].teid); - } - } - - // SRBs_FailedToBeSetup_List - F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextSetupResponseIEs_t, ie, container, - F1AP_ProtocolIE_ID_id_SRBs_FailedToBeSetup_List, false); - - if(ie!=NULL) { - f1ap_ue_context_setup_resp->srbs_failed_to_be_setup_length = ie->value.choice.SRBs_FailedToBeSetup_List.list.count; - f1ap_ue_context_setup_resp->srbs_failed_to_be_setup = calloc(f1ap_ue_context_setup_resp->srbs_failed_to_be_setup_length, - sizeof(f1ap_rb_failed_to_be_setup_t)); - AssertFatal(f1ap_ue_context_setup_resp->srbs_failed_to_be_setup, - "could not allocate memory for f1ap_ue_context_setup_resp->srbs_failed_to_be_setup\n"); - - for (i = 0; i < f1ap_ue_context_setup_resp->srbs_failed_to_be_setup_length; ++i) { - f1ap_rb_failed_to_be_setup_t *srb_p = &f1ap_ue_context_setup_resp->srbs_failed_to_be_setup[i]; - srb_p->rb_id = ((F1AP_SRBs_FailedToBeSetup_Item_t *)ie->value.choice.SRBs_FailedToBeSetup_List.list.array[i])->sRBID; - } - } - - // DRBs_FailedToBeSetup_List - F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextSetupResponseIEs_t, ie, container, - F1AP_ProtocolIE_ID_id_DRBs_FailedToBeSetup_List, false); - - if(ie!=NULL) { - f1ap_ue_context_setup_resp->drbs_failed_to_be_setup_length = ie->value.choice.DRBs_FailedToBeSetup_List.list.count; - f1ap_ue_context_setup_resp->drbs_failed_to_be_setup = calloc(f1ap_ue_context_setup_resp->drbs_failed_to_be_setup_length, - sizeof(f1ap_rb_failed_to_be_setup_t)); - AssertFatal(f1ap_ue_context_setup_resp->drbs_failed_to_be_setup, - "could not allocate memory for f1ap_ue_context_setup_resp->drbs_failed_to_be_setup\n"); - - for (i = 0; i < f1ap_ue_context_setup_resp->drbs_failed_to_be_setup_length; ++i) { - f1ap_rb_failed_to_be_setup_t *drb_p = &f1ap_ue_context_setup_resp->drbs_failed_to_be_setup[i]; - drb_p->rb_id = ((F1AP_DRBs_FailedToBeSetup_Item_t *)ie->value.choice.DRBs_FailedToBeSetup_List.list.array[i])->dRBID; - } - } - - // SCell_FailedtoSetup_List - F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextSetupResponseIEs_t, ie, container, - F1AP_ProtocolIE_ID_id_SCell_FailedtoSetup_List, false); - - if(ie!=NULL) { - LOG_E (F1AP, "Not supporting handling of SCell_FailedtoSetup_List \n"); - } - - // SRBs_Setup_List - F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextSetupResponseIEs_t, ie, container, - F1AP_ProtocolIE_ID_id_SRBs_Setup_List, false); - - if(ie!=NULL) { - f1ap_ue_context_setup_resp->srbs_to_be_setup_length = ie->value.choice.SRBs_Setup_List.list.count; - f1ap_ue_context_setup_resp->srbs_to_be_setup = calloc(f1ap_ue_context_setup_resp->srbs_to_be_setup_length, - sizeof(f1ap_srb_to_be_setup_t)); - AssertFatal(f1ap_ue_context_setup_resp->srbs_to_be_setup, - "could not allocate memory for f1ap_ue_context_setup_resp->drbs_setup\n"); - - for (i = 0; i < f1ap_ue_context_setup_resp->srbs_to_be_setup_length; ++i) { - f1ap_srb_to_be_setup_t *srb_p = &f1ap_ue_context_setup_resp->srbs_to_be_setup[i]; - F1AP_SRBs_Setup_Item_t *srbs_setup_item_p; - srbs_setup_item_p = &((F1AP_SRBs_Setup_ItemIEs_t *)ie->value.choice.SRBs_Setup_List.list.array[i])->value.choice.SRBs_Setup_Item; - srb_p->srb_id = srbs_setup_item_p->sRBID; - srb_p->lcid = srbs_setup_item_p->lCID; - } - } - + MessageDef *msg_p = itti_alloc_new_message(TASK_DU_F1, 0, F1AP_UE_CONTEXT_SETUP_RESP); + msg_p->ittiMsgHeader.originInstance = assoc_id; + F1AP_UE_CONTEXT_SETUP_RESP(msg_p) = resp; itti_send_msg_to_task(TASK_RRC_GNB, instance, msg_p); return 0; } @@ -754,762 +90,81 @@ int CU_handle_UE_CONTEXT_SETUP_FAILURE(instance_t instance, sctp_assoc_t assoc_i int CU_handle_UE_CONTEXT_RELEASE_REQUEST(instance_t instance, sctp_assoc_t assoc_id, uint32_t stream, F1AP_F1AP_PDU_t *pdu) { + f1ap_ue_context_rel_req_t req = {0}; + if (!decode_ue_context_rel_req(pdu, &req)) { + LOG_E(F1AP, "cannot decode F1 UE Context Release Request\n"); + free_ue_context_rel_req(&req); + return -1; + } + MessageDef *msg = itti_alloc_new_message(TASK_CU_F1, 0, F1AP_UE_CONTEXT_RELEASE_REQ); msg->ittiMsgHeader.originInstance = assoc_id; - f1ap_ue_context_release_req_t *req = &F1AP_UE_CONTEXT_RELEASE_REQ(msg); - F1AP_UEContextReleaseRequest_t *container; - F1AP_UEContextReleaseRequestIEs_t *ie; - DevAssert(pdu); - container = &pdu->choice.initiatingMessage->value.choice.UEContextReleaseRequest; - /* GNB_CU_UE_F1AP_ID */ - F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextReleaseRequestIEs_t, ie, container, - F1AP_ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID, true); - req->gNB_CU_ue_id = ie->value.choice.GNB_CU_UE_F1AP_ID; - - /* GNB_DU_UE_F1AP_ID */ - F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextReleaseRequestIEs_t, ie, container, - F1AP_ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID, true); - req->gNB_DU_ue_id = ie->value.choice.GNB_DU_UE_F1AP_ID; - - /* Cause */ - F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextReleaseRequestIEs_t, ie, container, - F1AP_ProtocolIE_ID_id_Cause, true); - - switch(ie->value.choice.Cause.present) - { - case F1AP_Cause_PR_radioNetwork: - req->cause = F1AP_CAUSE_RADIO_NETWORK; - req->cause_value = ie->value.choice.Cause.choice.radioNetwork; - break; - case F1AP_Cause_PR_transport: - req->cause = F1AP_CAUSE_TRANSPORT; - req->cause_value = ie->value.choice.Cause.choice.transport; - break; - case F1AP_Cause_PR_protocol: - req->cause = F1AP_CAUSE_PROTOCOL; - req->cause_value = ie->value.choice.Cause.choice.protocol; - break; - case F1AP_Cause_PR_misc: - req->cause = F1AP_CAUSE_MISC; - req->cause_value = ie->value.choice.Cause.choice.misc; - break; - case F1AP_Cause_PR_NOTHING: - default: - req->cause = F1AP_CAUSE_NOTHING; - break; - } - - F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextReleaseRequestIEs_t, ie, container, F1AP_ProtocolIE_ID_id_targetCellsToCancel, false); - if (ie != NULL) { - LOG_W(F1AP, "ignoring list of target cells to cancel in UE Context Release Request: implementation missing\n"); - } - + F1AP_UE_CONTEXT_RELEASE_REQ(msg) = req; itti_send_msg_to_task(TASK_RRC_GNB, instance, msg); - return 0; } -int CU_send_UE_CONTEXT_RELEASE_COMMAND(sctp_assoc_t assoc_id, f1ap_ue_context_release_cmd_t *cmd) +int CU_send_UE_CONTEXT_RELEASE_COMMAND(sctp_assoc_t assoc_id, f1ap_ue_context_rel_cmd_t *cmd) { - F1AP_F1AP_PDU_t pdu= {0}; - F1AP_UEContextReleaseCommand_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_UEContextRelease; - tmp->criticality = F1AP_Criticality_reject; - tmp->value.present = F1AP_InitiatingMessage__value_PR_UEContextReleaseCommand; - out = &tmp->value.choice.UEContextReleaseCommand; - /* mandatory */ - /* c1. GNB_CU_UE_F1AP_ID */ - asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextReleaseCommandIEs_t, ie1); - ie1->id = F1AP_ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID; - ie1->criticality = F1AP_Criticality_reject; - ie1->value.present = F1AP_UEContextReleaseCommandIEs__value_PR_GNB_CU_UE_F1AP_ID; - ie1->value.choice.GNB_CU_UE_F1AP_ID = cmd->gNB_CU_ue_id; - /* mandatory */ - /* c2. GNB_DU_UE_F1AP_ID */ - asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextReleaseCommandIEs_t, ie2); - ie2->id = F1AP_ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID; - ie2->criticality = F1AP_Criticality_reject; - ie2->value.present = F1AP_UEContextReleaseCommandIEs__value_PR_GNB_DU_UE_F1AP_ID; - ie2->value.choice.GNB_DU_UE_F1AP_ID = cmd->gNB_DU_ue_id; - /* mandatory */ - /* c3. Cause */ - asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextReleaseCommandIEs_t, ie3); - ie3->id = F1AP_ProtocolIE_ID_id_Cause; - ie3->criticality = F1AP_Criticality_ignore; - ie3->value.present = F1AP_UEContextReleaseCommandIEs__value_PR_Cause; + F1AP_F1AP_PDU_t *pdu = encode_ue_context_rel_cmd(cmd); - switch (cmd->cause) { - case F1AP_CAUSE_RADIO_NETWORK: - ie3->value.choice.Cause.present = F1AP_Cause_PR_radioNetwork; - ie3->value.choice.Cause.choice.radioNetwork = cmd->cause_value; - break; - - case F1AP_CAUSE_TRANSPORT: - ie3->value.choice.Cause.present = F1AP_Cause_PR_transport; - ie3->value.choice.Cause.choice.transport = cmd->cause_value; - break; - - case F1AP_CAUSE_PROTOCOL: - ie3->value.choice.Cause.present = F1AP_Cause_PR_protocol; - ie3->value.choice.Cause.choice.protocol = cmd->cause_value; - break; - - case F1AP_CAUSE_MISC: - ie3->value.choice.Cause.present = F1AP_Cause_PR_misc; - ie3->value.choice.Cause.choice.misc = cmd->cause_value; - break; - - case F1AP_CAUSE_NOTHING: - default: - ie3->value.choice.Cause.present = F1AP_Cause_PR_NOTHING; - break; - } - - /* optional */ - /* c4. RRCContainer */ - if(cmd->rrc_container!=NULL){ - asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextReleaseCommandIEs_t, ie4); - ie4->id = F1AP_ProtocolIE_ID_id_RRCContainer; - ie4->criticality = F1AP_Criticality_ignore; - ie4->value.present = F1AP_UEContextReleaseCommandIEs__value_PR_RRCContainer; - OCTET_STRING_fromBuf(&ie4->value.choice.RRCContainer, (const char *)cmd->rrc_container, - cmd->rrc_container_length); - - // conditionally have SRBID if RRC Container - asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextReleaseCommandIEs_t, ie5); - ie5->id = F1AP_ProtocolIE_ID_id_SRBID; - ie5->criticality = F1AP_Criticality_ignore; - ie5->value.present = F1AP_UEContextReleaseCommandIEs__value_PR_SRBID; - ie5->value.choice.SRBID = cmd->srb_id; - } - - /* encode */ - if (f1ap_encode_pdu(&pdu, &buffer, &len) < 0) { + uint8_t *buffer = NULL; + uint32_t len = 0; + if (f1ap_encode_pdu(pdu, &buffer, &len) < 0) { LOG_E(F1AP, "Failed to encode F1 context release command\n"); return -1; } f1ap_itti_send_sctp_data_req(assoc_id, buffer, len); + ASN_STRUCT_FREE(asn_DEF_F1AP_F1AP_PDU, pdu); return 0; } int CU_handle_UE_CONTEXT_RELEASE_COMPLETE(instance_t instance, sctp_assoc_t assoc_id, uint32_t stream, F1AP_F1AP_PDU_t *pdu) { - F1AP_UEContextReleaseComplete_t *container; - F1AP_UEContextReleaseCompleteIEs_t *ie; - DevAssert(pdu); - MessageDef *msg_p = itti_alloc_new_message(TASK_DU_F1, 0, F1AP_UE_CONTEXT_RELEASE_COMPLETE); - msg_p->ittiMsgHeader.originInstance = assoc_id; - f1ap_ue_context_release_complete_t *complete = &F1AP_UE_CONTEXT_RELEASE_COMPLETE(msg_p); - container = &pdu->choice.successfulOutcome->value.choice.UEContextReleaseComplete; - /* GNB_CU_UE_F1AP_ID */ - F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextReleaseCompleteIEs_t, ie, container, - F1AP_ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID, true); - complete->gNB_CU_ue_id = ie->value.choice.GNB_CU_UE_F1AP_ID; - /* GNB_DU_UE_F1AP_ID */ - F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextReleaseCompleteIEs_t, ie, container, - F1AP_ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID, true); - complete->gNB_DU_ue_id = ie->value.choice.GNB_DU_UE_F1AP_ID; - - /* Optional*/ - /* CriticalityDiagnostics */ - F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextReleaseCompleteIEs_t, ie, container, - F1AP_ProtocolIE_ID_id_CriticalityDiagnostics, false); - - if (ie) { - // ie->value.choice.CriticalityDiagnostics.procedureCode - // ie->value.choice.CriticalityDiagnostics.triggeringMessage - // ie->value.choice.CriticalityDiagnostics.procedureCriticality - // ie->value.choice.CriticalityDiagnostics.transactionID - // F1AP_CriticalityDiagnostics_IE_List + f1ap_ue_context_rel_cplt_t cplt = {0}; + if (!decode_ue_context_rel_cplt(pdu, &cplt)) { + LOG_E(F1AP, "cannot decode F1 UE Context Release Complete\n"); + free_ue_context_rel_cplt(&cplt); + return -1; } + MessageDef *msg_p = itti_alloc_new_message(TASK_DU_F1, 0, F1AP_UE_CONTEXT_RELEASE_COMPLETE); + msg_p->ittiMsgHeader.originInstance = assoc_id; + F1AP_UE_CONTEXT_RELEASE_COMPLETE(msg_p) = cplt; itti_send_msg_to_task(TASK_RRC_GNB, instance, msg_p); - return 0; } -int CU_send_UE_CONTEXT_MODIFICATION_REQUEST(sctp_assoc_t assoc_id, f1ap_ue_context_modif_req_t *f1ap_ue_context_modification_req) +int CU_send_UE_CONTEXT_MODIFICATION_REQUEST(sctp_assoc_t assoc_id, const f1ap_ue_context_mod_req_t *req) { - F1AP_F1AP_PDU_t pdu= {0}; - F1AP_UEContextModificationRequest_t *out; + F1AP_F1AP_PDU_t *pdu = encode_ue_context_mod_req(req); + 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_UEContextModification; - tmp->criticality = F1AP_Criticality_reject; - tmp->value.present = F1AP_InitiatingMessage__value_PR_UEContextModificationRequest; - out = &tmp->value.choice.UEContextModificationRequest; - /* mandatory */ - /* c1. GNB_CU_UE_F1AP_ID */ - asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextModificationRequestIEs_t, ie1); - ie1->id = F1AP_ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID; - ie1->criticality = F1AP_Criticality_reject; - ie1->value.present = F1AP_UEContextModificationRequestIEs__value_PR_GNB_CU_UE_F1AP_ID; - ie1->value.choice.GNB_CU_UE_F1AP_ID = f1ap_ue_context_modification_req->gNB_CU_ue_id; - /* mandatory */ - /* c2. GNB_DU_UE_F1AP_ID */ - asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextModificationRequestIEs_t, ie2); - ie2->id = F1AP_ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID; - ie2->criticality = F1AP_Criticality_reject; - ie2->value.present = F1AP_UEContextModificationRequestIEs__value_PR_GNB_DU_UE_F1AP_ID; - ie2->value.choice.GNB_DU_UE_F1AP_ID = f1ap_ue_context_modification_req->gNB_DU_ue_id; - - /* optional */ - /* c3. NRCGI */ - if (true) { - asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextModificationRequestIEs_t, ie3); - ie3->id = F1AP_ProtocolIE_ID_id_SpCell_ID; - ie3->criticality = F1AP_Criticality_ignore; - ie3->value.present = F1AP_UEContextModificationRequestIEs__value_PR_NRCGI; - /* - nRCGI */ - - f1ap_served_cell_info_t nrcgi = { - .plmn = f1ap_ue_context_modification_req->plmn, - .nr_cellid = f1ap_ue_context_modification_req->nr_cellid, - }; - addnRCGI(ie3->value.choice.NRCGI, &nrcgi); - } - - /* optional */ - /* c4. ServCellIndex */ - if(0){ - asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextModificationRequestIEs_t, ie4); - ie4->id = F1AP_ProtocolIE_ID_id_ServCellIndex; - ie4->criticality = F1AP_Criticality_reject; - ie4->value.present = F1AP_UEContextModificationRequestIEs__value_PR_ServCellIndex; - ie4->value.choice.ServCellIndex = 5L; - } - - /* optional */ - /* c5. DRXCycle */ - if (0) { - asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextModificationRequestIEs_t, ie5); - ie5->id = F1AP_ProtocolIE_ID_id_DRXCycle; - ie5->criticality = F1AP_Criticality_ignore; - ie5->value.present = F1AP_UEContextModificationRequestIEs__value_PR_DRXCycle; - ie5->value.choice.DRXCycle.longDRXCycleLength = F1AP_LongDRXCycleLength_ms10; // enum - - if (0) { - asn1cCallocOne(ie5->value.choice.DRXCycle.shortDRXCycleLength, - F1AP_ShortDRXCycleLength_ms2); // enum - } - - if (0) { - asn1cCallocOne(ie5->value.choice.DRXCycle.shortDRXCycleTimer, 123L); - } - } - - /* optional */ - /* c6. CUtoDURRCInformation */ - if (f1ap_ue_context_modification_req->cu_to_du_rrc_information!=NULL) { - asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextModificationRequestIEs_t, ie6); - ie6->id = F1AP_ProtocolIE_ID_id_CUtoDURRCInformation; - ie6->criticality = F1AP_Criticality_reject; - ie6->value.present = F1AP_UEContextModificationRequestIEs__value_PR_CUtoDURRCInformation; - /* 6.1 cG_ConfigInfo */ - if(f1ap_ue_context_modification_req->cu_to_du_rrc_information->cG_ConfigInfo!=NULL){ - asn1cCalloc(ie6->value.choice.CUtoDURRCInformation.cG_ConfigInfo, cG_ConfigInfo); - OCTET_STRING_fromBuf(cG_ConfigInfo, (const char *)f1ap_ue_context_modification_req->cu_to_du_rrc_information->cG_ConfigInfo, - f1ap_ue_context_modification_req->cu_to_du_rrc_information->cG_ConfigInfo_length); - } - /* optional */ - /* 6.2 uE_CapabilityRAT_ContainerList */ - if(f1ap_ue_context_modification_req->cu_to_du_rrc_information->uE_CapabilityRAT_ContainerList!=NULL){ - asn1cCalloc(ie6->value.choice.CUtoDURRCInformation.uE_CapabilityRAT_ContainerList, uE_CapabilityRAT_ContainerList ); - OCTET_STRING_fromBuf(uE_CapabilityRAT_ContainerList, (const char *)f1ap_ue_context_modification_req->cu_to_du_rrc_information->uE_CapabilityRAT_ContainerList, - f1ap_ue_context_modification_req->cu_to_du_rrc_information->uE_CapabilityRAT_ContainerList_length) ; - } - /* optional */ - /* 6.3 measConfig */ - if(f1ap_ue_context_modification_req->cu_to_du_rrc_information->measConfig!=NULL){ - asn1cCalloc(ie6->value.choice.CUtoDURRCInformation.measConfig, measConfig); - OCTET_STRING_fromBuf(measConfig, (const char *)f1ap_ue_context_modification_req->cu_to_du_rrc_information->measConfig, - f1ap_ue_context_modification_req->cu_to_du_rrc_information->measConfig_length); - } - } - - /* optional */ - /* c7. TransmissionActionIndicator */ - if (f1ap_ue_context_modification_req->transm_action_ind != NULL) { - asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextModificationRequestIEs_t, ie7); - ie7->id = F1AP_ProtocolIE_ID_id_TransmissionActionIndicator; - ie7->criticality = F1AP_Criticality_ignore; - ie7->value.present = F1AP_UEContextModificationRequestIEs__value_PR_TransmissionActionIndicator; - ie7->value.choice.TransmissionActionIndicator = *f1ap_ue_context_modification_req->transm_action_ind; - // Stop is guaranteed to be 0, by restart might be different from 1 - static_assert((int)F1AP_TransmissionActionIndicator_restart == (int)TransmActionInd_RESTART, - "mismatch of ASN.1 and internal representation\n"); - } - - /* optional */ - /* c8. ResourceCoordinationTransferContainer */ - if (0) { - asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextModificationRequestIEs_t, ie8); - ie8->id = F1AP_ProtocolIE_ID_id_ResourceCoordinationTransferContainer; - ie8->criticality = F1AP_Criticality_ignore; - ie8->value.present = F1AP_UEContextModificationRequestIEs__value_PR_ResourceCoordinationTransferContainer; - OCTET_STRING_fromBuf(&ie8->value.choice.ResourceCoordinationTransferContainer, "asdsa1d32sa1d31asd31as", - strlen("asdsa1d32sa1d31asd31as")); - } - - /* optional */ - /* c7. RRCRconfigurationCompleteIndicator */ - if (f1ap_ue_context_modification_req->ReconfigComplOutcome == RRCreconf_success) { - asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextModificationRequestIEs_t, ie71); - ie71->id = F1AP_ProtocolIE_ID_id_RRCReconfigurationCompleteIndicator; - ie71->criticality = F1AP_Criticality_ignore; - ie71->value.present = F1AP_UEContextModificationRequestIEs__value_PR_RRCReconfigurationCompleteIndicator; - ie71->value.choice.RRCReconfigurationCompleteIndicator = F1AP_RRCReconfigurationCompleteIndicator_true; - } - - /* optional */ - /* c8. RRCContainer */ - if (f1ap_ue_context_modification_req->rrc_container != NULL) { - asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextModificationRequestIEs_t, ie81); - ie81->id = F1AP_ProtocolIE_ID_id_RRCContainer; - ie81->criticality = F1AP_Criticality_ignore; - ie81->value.present = F1AP_UEContextModificationRequestIEs__value_PR_RRCContainer; - OCTET_STRING_fromBuf(&ie81->value.choice.RRCContainer, (const char*)f1ap_ue_context_modification_req->rrc_container, - f1ap_ue_context_modification_req->rrc_container_length); - } - - /* optional */ - /* c9. SCell_ToBeSetupMod_List */ - if(0){ - asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextModificationRequestIEs_t, ie9); - ie9->id = F1AP_ProtocolIE_ID_id_SCell_ToBeSetupMod_List; - ie9->criticality = F1AP_Criticality_ignore; - ie9->value.present = F1AP_UEContextModificationRequestIEs__value_PR_SCell_ToBeSetupMod_List; - - for (int i=0; i<1; i++) { - // - asn1cSequenceAdd(ie9->value.choice.SCell_ToBeSetupMod_List.list, - F1AP_SCell_ToBeSetupMod_ItemIEs_t, scell_toBeSetupMod_item_ies); - scell_toBeSetupMod_item_ies->id = F1AP_ProtocolIE_ID_id_SCell_ToBeSetupMod_Item; - scell_toBeSetupMod_item_ies->criticality = F1AP_Criticality_ignore; - scell_toBeSetupMod_item_ies->value.present = F1AP_SCell_ToBeSetupMod_ItemIEs__value_PR_SCell_ToBeSetupMod_Item; - /* 8.1 SCell_ToBeSetup_Item */ - F1AP_SCell_ToBeSetupMod_Item_t *scell_toBeSetupMod_item= - &scell_toBeSetupMod_item_ies->value.choice.SCell_ToBeSetupMod_Item; - // /* - sCell_ID */ - f1ap_served_cell_info_t hardCoded = {0}; - addnRCGI(scell_toBeSetupMod_item->sCell_ID, &hardCoded); - /* sCellIndex */ - scell_toBeSetupMod_item->sCellIndex = 6; // issue here - } - } - - /* optional */ - /* c10. SCell_ToBeRemoved_List */ - if(0){ - asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextModificationRequestIEs_t, ie10); - ie10->id = F1AP_ProtocolIE_ID_id_SCell_ToBeRemoved_List; - ie10->criticality = F1AP_Criticality_ignore; - ie10->value.present = F1AP_UEContextModificationRequestIEs__value_PR_SCell_ToBeRemoved_List; - - for (int i=0; i<1; i++) { - // - asn1cSequenceAdd(ie10->value.choice.SCell_ToBeRemoved_List.list, - F1AP_SCell_ToBeRemoved_ItemIEs_t, scell_toBeRemoved_item_ies); - scell_toBeRemoved_item_ies = (F1AP_SCell_ToBeRemoved_ItemIEs_t *)calloc(1, sizeof(F1AP_SCell_ToBeRemoved_ItemIEs_t)); - //memset((void *)&scell_toBeRemoved_item_ies, 0, sizeof(F1AP_SCell_ToBeRemoved_ItemIEs_t)); - scell_toBeRemoved_item_ies->id = F1AP_ProtocolIE_ID_id_SCell_ToBeRemoved_Item; - scell_toBeRemoved_item_ies->criticality = F1AP_Criticality_ignore; - scell_toBeRemoved_item_ies->value.present = F1AP_SCell_ToBeRemoved_ItemIEs__value_PR_SCell_ToBeRemoved_Item; - /* 10.1 SCell_ToBeRemoved_Item */ - F1AP_SCell_ToBeRemoved_Item_t *scell_toBeRemoved_item= - &scell_toBeRemoved_item_ies->value.choice.SCell_ToBeRemoved_Item; - /* - sCell_ID */ - f1ap_served_cell_info_t hardCoded = {0}; - addnRCGI(scell_toBeRemoved_item->sCell_ID, &hardCoded); - } - } - - /* mandatory */ - /* c11. SRBs_ToBeSetupMod_List */ - if(f1ap_ue_context_modification_req->srbs_to_be_setup_length > 0){ - asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextModificationRequestIEs_t, ie11); - ie11->id = F1AP_ProtocolIE_ID_id_SRBs_ToBeSetupMod_List; - ie11->criticality = F1AP_Criticality_reject; - ie11->value.present = F1AP_UEContextModificationRequestIEs__value_PR_SRBs_ToBeSetupMod_List; - - for (int i=0; isrbs_to_be_setup_length; i++) { - // - asn1cSequenceAdd(ie11->value.choice.SRBs_ToBeSetupMod_List, F1AP_SRBs_ToBeSetupMod_ItemIEs_t, srbs_toBeSetupMod_item_ies); - srbs_toBeSetupMod_item_ies->id = F1AP_ProtocolIE_ID_id_SRBs_ToBeSetupMod_Item; // 73 - srbs_toBeSetupMod_item_ies->criticality = F1AP_Criticality_reject; - srbs_toBeSetupMod_item_ies->value.present = F1AP_SRBs_ToBeSetupMod_ItemIEs__value_PR_SRBs_ToBeSetupMod_Item; - /* 11.1 SRBs_ToBeSetup_Item */ - F1AP_SRBs_ToBeSetupMod_Item_t *srbs_toBeSetupMod_item=&srbs_toBeSetupMod_item_ies->value.choice.SRBs_ToBeSetupMod_Item; - /* 11.1.1 sRBID */ - srbs_toBeSetupMod_item->sRBID = f1ap_ue_context_modification_req->srbs_to_be_setup[i].srb_id; - /* OPTIONAL */ - /* 11.1.2 duplicationIndication */ - asn1cCallocOne(srbs_toBeSetupMod_item->duplicationIndication, - F1AP_DuplicationIndication_true); // enum - } - } - - /* mandatory */ - /* c12. DRBs_ToBeSetupMod_List */ - if(f1ap_ue_context_modification_req->drbs_to_be_setup_length){ - asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextModificationRequestIEs_t, ie12); - ie12->id = F1AP_ProtocolIE_ID_id_DRBs_ToBeSetupMod_List; - ie12->criticality = F1AP_Criticality_reject; - ie12->value.present = F1AP_UEContextModificationRequestIEs__value_PR_DRBs_ToBeSetupMod_List; - - for (int i = 0; i < f1ap_ue_context_modification_req->drbs_to_be_setup_length; i++) { - const f1ap_drb_to_be_setup_t *drb = &f1ap_ue_context_modification_req->drbs_to_be_setup[i]; - asn1cSequenceAdd(ie12->value.choice.DRBs_ToBeSetupMod_List.list, - F1AP_DRBs_ToBeSetupMod_ItemIEs_t, drbs_toBeSetupMod_item_ies); - drbs_toBeSetupMod_item_ies->id = F1AP_ProtocolIE_ID_id_DRBs_ToBeSetupMod_Item; - drbs_toBeSetupMod_item_ies->criticality = F1AP_Criticality_reject; - drbs_toBeSetupMod_item_ies->value.present = F1AP_DRBs_ToBeSetupMod_ItemIEs__value_PR_DRBs_ToBeSetupMod_Item; - /* 12.1 DRBs_ToBeSetupMod_Item */ - F1AP_DRBs_ToBeSetupMod_Item_t *drbs_toBeSetupMod_item= - &drbs_toBeSetupMod_item_ies->value.choice.DRBs_ToBeSetupMod_Item; - /* dRBID */ - drbs_toBeSetupMod_item->dRBID = drb->drb_id; - /* qoSInformation */ - - if(f1ap_ue_context_modification_req->QoS_information_type == EUTRAN_QoS){ - drbs_toBeSetupMod_item->qoSInformation.present = F1AP_QoSInformation_PR_eUTRANQoS; - drbs_toBeSetupMod_item->qoSInformation.choice.eUTRANQoS = (F1AP_EUTRANQoS_t *)calloc(1, sizeof(F1AP_EUTRANQoS_t)); - drbs_toBeSetupMod_item->qoSInformation.choice.eUTRANQoS->qCI = 253L; - /* uLUPTNLInformation_ToBeSetup_List */ - int maxnoofULTunnels = 1; // 2; - - for (int j=0; juLUPTNLInformation_ToBeSetup_List.list, - F1AP_ULUPTNLInformation_ToBeSetup_Item_t, uLUPTNLInformation_ToBeSetup_Item); - uLUPTNLInformation_ToBeSetup_Item->uLUPTNLInformation.present = F1AP_UPTransportLayerInformation_PR_gTPTunnel; - asn1cCalloc(uLUPTNLInformation_ToBeSetup_Item->uLUPTNLInformation.choice.gTPTunnel, - gTPTunnel); - /* transportLayerAddress */ - TRANSPORT_LAYER_ADDRESS_IPv4_TO_BIT_STRING(1234, &gTPTunnel->transportLayerAddress); - /* gTP_TEID */ - OCTET_STRING_fromBuf(&gTPTunnel->gTP_TEID, "4567", - strlen("4567")); - } - - /* rLCMode */ - drbs_toBeSetupMod_item->rLCMode = F1AP_RLCMode_rlc_um_bidirectional; // enum - - /* OPTIONAL */ - /* ULConfiguration */ - if (0) { - drbs_toBeSetupMod_item->uLConfiguration = (F1AP_ULConfiguration_t *)calloc(1, sizeof(F1AP_ULConfiguration_t)); - } - } //QoS information - - else{ - /* 12.1.2 DRB_Information */ - f1ap_drb_information_t *drb_info_in = &f1ap_ue_context_modification_req->drbs_to_be_setup[i].drb_info; - drbs_toBeSetupMod_item->qoSInformation.present = F1AP_QoSInformation_PR_choice_extension; - F1AP_QoSInformation_ExtIEs_t *ie = (F1AP_QoSInformation_ExtIEs_t *)calloc(1, sizeof(*ie)); - ie->id = F1AP_ProtocolIE_ID_id_DRB_Information; - ie->criticality = F1AP_Criticality_reject; - ie->value.present = F1AP_QoSInformation_ExtIEs__value_PR_DRB_Information; - F1AP_DRB_Information_t *DRB_Information = &ie->value.choice.DRB_Information; - drbs_toBeSetupMod_item->qoSInformation.choice.choice_extension = (struct F1AP_ProtocolIE_SingleContainer *)ie; - - /* 12.1.2.1 dRB_QoS */ - f1ap_write_drb_qos_param(&drb_info_in->drb_qos, &DRB_Information->dRB_QoS); - - /* 12.1.2.2 sNSSAI */ - f1ap_write_drb_nssai(&drb->nssai, &DRB_Information->sNSSAI); - - /* OPTIONAL */ - /* 12.1.2.3 notificationControl */ - if (0) { - asn1cCallocOne(DRB_Information->notificationControl, - F1AP_NotificationControl_active); // enum - } - - /* 12.1.2.4 flows_Mapped_To_DRB_List */ - f1ap_write_flows_mapped(drb_info_in->flows_mapped_to_drb, &DRB_Information->flows_Mapped_To_DRB_List, drb_info_in->flows_to_be_setup_length); - - } //QoS information - - /* 12.1.3 uLUPTNLInformation_ToBeSetup_List */ - for (int j = 0; j < f1ap_ue_context_modification_req->drbs_to_be_setup[i].up_ul_tnl_length; j++) { - /* Use a dummy address and teid for the outgoing GTP-U tunnel (DU) which will be updated once we get the UE context modification response from the DU */ - asn1cSequenceAdd(drbs_toBeSetupMod_item->uLUPTNLInformation_ToBeSetup_List.list, - F1AP_ULUPTNLInformation_ToBeSetup_Item_t, uLUPTNLInformation_ToBeSetup_Item); - uLUPTNLInformation_ToBeSetup_Item->uLUPTNLInformation.present = F1AP_UPTransportLayerInformation_PR_gTPTunnel; - asn1cCalloc( uLUPTNLInformation_ToBeSetup_Item->uLUPTNLInformation.choice.gTPTunnel, - gTPTunnel); - /* 12.3.1.1.1 transportLayerAddress */ - TRANSPORT_LAYER_ADDRESS_IPv4_TO_BIT_STRING(f1ap_ue_context_modification_req->drbs_to_be_setup[i].up_ul_tnl[j].tl_address, - &gTPTunnel->transportLayerAddress); - /* 12.3.1.1.2 gTP_TEID */ - INT32_TO_OCTET_STRING(f1ap_ue_context_modification_req->drbs_to_be_setup[i].up_ul_tnl[j].teid, - &gTPTunnel->gTP_TEID); - } - /* 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 F1AP_RLC_MODE_AM: - drbs_toBeSetupMod_item->rLCMode = F1AP_RLCMode_rlc_am; - break; - 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 */ - /* 12.1.5 ULConfiguration */ - if (0) { - asn1cCalloc(drbs_toBeSetupMod_item->uLConfiguration, tmp); - tmp->uLUEConfiguration = F1AP_ULUEConfiguration_no_data; - } - - /* OPTIONAL */ - /* 12.1.6 duplicationActivation */ - if (0) { - asn1cCalloc(drbs_toBeSetupMod_item->duplicationActivation, tmp); - *tmp = F1AP_DuplicationActivation_active; // enum - } - } - } - - /* optional */ - if(0){ - /* c13. DRBs_ToBeModified_List */ - asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextModificationRequestIEs_t, ie13); - ie13->id = F1AP_ProtocolIE_ID_id_DRBs_ToBeModified_List; - ie13->criticality = F1AP_Criticality_reject; - ie13->value.present = F1AP_UEContextModificationRequestIEs__value_PR_DRBs_ToBeModified_List; - - for (int i=0; i<1; i++) { - // - asn1cSequenceAdd( ie13->value.choice.DRBs_ToBeModified_List.list, - F1AP_DRBs_ToBeModified_ItemIEs_t, drbs_toBeModified_item_ies); - drbs_toBeModified_item_ies->id = F1AP_ProtocolIE_ID_id_DRBs_ToBeModified_Item; - drbs_toBeModified_item_ies->criticality = F1AP_Criticality_reject; - drbs_toBeModified_item_ies->value.present = F1AP_DRBs_ToBeModified_ItemIEs__value_PR_DRBs_ToBeModified_Item; - /* 13.1 SRBs_ToBeModified_Item */ - F1AP_DRBs_ToBeModified_Item_t *drbs_toBeModified_item= - &drbs_toBeModified_item_ies->value.choice.DRBs_ToBeModified_Item; - /* dRBID */ - drbs_toBeModified_item->dRBID = 30L; - /* qoSInformation */ - asn1cCalloc(drbs_toBeModified_item->qoSInformation, tmp); - tmp->present = F1AP_QoSInformation_PR_eUTRANQoS; - tmp->choice.eUTRANQoS = (F1AP_EUTRANQoS_t *)calloc(1, sizeof(F1AP_EUTRANQoS_t)); - tmp->choice.eUTRANQoS->qCI = 254L; - /* ULTunnels_ToBeModified_List */ - int maxnoofULTunnels = 1; // 2; - - for (int j=0; juLUPTNLInformation_ToBeSetup_List.list, - F1AP_ULUPTNLInformation_ToBeSetup_Item_t, uLUPTNLInformation_ToBeSetup_Item); - uLUPTNLInformation_ToBeSetup_Item->uLUPTNLInformation.present = F1AP_UPTransportLayerInformation_PR_gTPTunnel; - asn1cCalloc(uLUPTNLInformation_ToBeSetup_Item->uLUPTNLInformation.choice.gTPTunnel, - gTPTunnel); - TRANSPORT_LAYER_ADDRESS_IPv4_TO_BIT_STRING(1234, &gTPTunnel->transportLayerAddress); - OCTET_STRING_fromBuf(&gTPTunnel->gTP_TEID, "1204", - strlen("1204")); - } - - /* OPTIONAL */ - /* ULConfiguration */ - if (0) { - drbs_toBeModified_item->uLConfiguration = (F1AP_ULConfiguration_t *)calloc(1, sizeof(F1AP_ULConfiguration_t)); - } - } - } - - /* optional */ - if(0){ - /* c14. SRBs_ToBeReleased_List */ - asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextModificationRequestIEs_t, ie14); - ie14->id = F1AP_ProtocolIE_ID_id_SRBs_ToBeReleased_List; - ie14->criticality = F1AP_Criticality_reject; - ie14->value.present = F1AP_UEContextModificationRequestIEs__value_PR_SRBs_ToBeReleased_List; - - for (int i=0; i<1; i++) { - // - asn1cSequenceAdd(ie14->value.choice.SRBs_ToBeReleased_List.list, - F1AP_SRBs_ToBeReleased_ItemIEs_t, srbs_toBeReleased_item_ies); - srbs_toBeReleased_item_ies->id = F1AP_ProtocolIE_ID_id_SRBs_ToBeReleased_Item; - srbs_toBeReleased_item_ies->criticality = F1AP_Criticality_ignore; - srbs_toBeReleased_item_ies->value.present = F1AP_SRBs_ToBeReleased_ItemIEs__value_PR_SRBs_ToBeReleased_Item; - /* 9.1 SRBs_ToBeReleased_Item */ - F1AP_SRBs_ToBeReleased_Item_t *srbs_toBeReleased_item= - &srbs_toBeReleased_item_ies->value.choice.SRBs_ToBeReleased_Item; - /* - sRBID */ - srbs_toBeReleased_item->sRBID = 2L; - } - } - - /* optional */ - if (f1ap_ue_context_modification_req->drbs_to_be_released_length > 0) { - /* c15. DRBs_ToBeReleased_List */ - asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextModificationRequestIEs_t, ie15); - ie15->id = F1AP_ProtocolIE_ID_id_DRBs_ToBeReleased_List; - ie15->criticality = F1AP_Criticality_reject; - ie15->value.present = F1AP_UEContextModificationRequestIEs__value_PR_DRBs_ToBeReleased_List; - - for (int i = 0; i < f1ap_ue_context_modification_req->drbs_to_be_released_length; i++) { - // - asn1cSequenceAdd(ie15->value.choice.DRBs_ToBeReleased_List.list, - F1AP_DRBs_ToBeReleased_ItemIEs_t, drbs_toBeReleased_item_ies); - drbs_toBeReleased_item_ies->id = F1AP_ProtocolIE_ID_id_DRBs_ToBeReleased_Item; - drbs_toBeReleased_item_ies->criticality = F1AP_Criticality_reject; - drbs_toBeReleased_item_ies->value.present = F1AP_DRBs_ToBeReleased_ItemIEs__value_PR_DRBs_ToBeReleased_Item; - /* 14.1 SRBs_ToBeReleased_Item */ - F1AP_DRBs_ToBeReleased_Item_t *drbs_toBeReleased_item= - &drbs_toBeReleased_item_ies->value.choice.DRBs_ToBeReleased_Item; - /* dRBID */ - drbs_toBeReleased_item->dRBID = f1ap_ue_context_modification_req->drbs_to_be_released[i].rb_id; - } - } - - /* encode */ - if (f1ap_encode_pdu(&pdu, &buffer, &len) < 0) { - LOG_E(F1AP, "Failed to encode F1 UE CONTEXT_MODIFICATION REQUEST\n"); + if (f1ap_encode_pdu(pdu, &buffer, &len) < 0) { + LOG_E(F1AP, "Failed to encode F1 UE Context Modification Request\n"); return -1; } + f1ap_itti_send_sctp_data_req(assoc_id, buffer, len); + ASN_STRUCT_FREE(asn_DEF_F1AP_F1AP_PDU, pdu); return 0; } int CU_handle_UE_CONTEXT_MODIFICATION_RESPONSE(instance_t instance, sctp_assoc_t assoc_id, uint32_t stream, F1AP_F1AP_PDU_t *pdu) { - MessageDef *msg_p; - F1AP_UEContextModificationResponse_t *container; - F1AP_UEContextModificationResponseIEs_t *ie; - DevAssert(pdu); - msg_p = itti_alloc_new_message(TASK_DU_F1, 0, F1AP_UE_CONTEXT_MODIFICATION_RESP); + f1ap_ue_context_mod_resp_t resp = {0}; + if (!decode_ue_context_mod_resp(pdu, &resp)) { + LOG_E(F1AP, "cannot decode F1 UE Context Modification Response\n"); + free_ue_context_mod_resp(&resp); + return -1; + } + MessageDef *msg_p = itti_alloc_new_message(TASK_DU_F1, 0, F1AP_UE_CONTEXT_MODIFICATION_RESP); msg_p->ittiMsgHeader.originInstance = assoc_id; - f1ap_ue_context_modif_resp_t *f1ap_ue_context_modification_resp = &F1AP_UE_CONTEXT_MODIFICATION_RESP(msg_p); - container = &pdu->choice.successfulOutcome->value.choice.UEContextModificationResponse; - int i; - - /* GNB_CU_UE_F1AP_ID */ - F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextModificationResponseIEs_t, ie, container, - F1AP_ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID, true); - f1ap_ue_context_modification_resp->gNB_CU_ue_id = ie->value.choice.GNB_CU_UE_F1AP_ID; - - LOG_D(F1AP, "f1ap_ue_context_modif_resp->gNB_CU_ue_id is: %d \n", f1ap_ue_context_modification_resp->gNB_CU_ue_id); - - /* GNB_DU_UE_F1AP_ID */ - F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextModificationResponseIEs_t, ie, container, - F1AP_ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID, true); - f1ap_ue_context_modification_resp->gNB_DU_ue_id = ie->value.choice.GNB_DU_UE_F1AP_ID; - - LOG_D(F1AP, "f1ap_ue_context_modification_resp->gNB_DU_ue_id is: %d \n", f1ap_ue_context_modification_resp->gNB_DU_ue_id); - - // DUtoCURRCInformation - F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextModificationResponseIEs_t, ie, container, - F1AP_ProtocolIE_ID_id_DUtoCURRCInformation, false); - if(ie!=NULL){ - f1ap_ue_context_modification_resp->du_to_cu_rrc_information = (du_to_cu_rrc_information_t *)calloc(1, sizeof(du_to_cu_rrc_information_t)); - f1ap_ue_context_modification_resp->du_to_cu_rrc_information->cellGroupConfig = (uint8_t *)calloc(1,ie->value.choice.DUtoCURRCInformation.cellGroupConfig.size); - - memcpy(f1ap_ue_context_modification_resp->du_to_cu_rrc_information->cellGroupConfig, ie->value.choice.DUtoCURRCInformation.cellGroupConfig.buf, ie->value.choice.DUtoCURRCInformation.cellGroupConfig.size); - f1ap_ue_context_modification_resp->du_to_cu_rrc_information->cellGroupConfig_length = ie->value.choice.DUtoCURRCInformation.cellGroupConfig.size; - } - - // DRBs_SetupMod_List - F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextModificationResponseIEs_t, ie, container, - F1AP_ProtocolIE_ID_id_DRBs_SetupMod_List, false); - if(ie!=NULL){ - f1ap_ue_context_modification_resp->drbs_to_be_setup_length = ie->value.choice.DRBs_SetupMod_List.list.count; - f1ap_ue_context_modification_resp->drbs_to_be_setup = calloc(f1ap_ue_context_modification_resp->drbs_to_be_setup_length, - sizeof(f1ap_drb_to_be_setup_t)); - AssertFatal(f1ap_ue_context_modification_resp->drbs_to_be_setup, - "could not allocate memory for f1ap_ue_context_setup_resp->drbs_setup\n"); - for (i = 0; i < f1ap_ue_context_modification_resp->drbs_to_be_setup_length; ++i) { - f1ap_drb_to_be_setup_t *drb_p = &f1ap_ue_context_modification_resp->drbs_to_be_setup[i]; - F1AP_DRBs_SetupMod_Item_t *drbs_setupmod_item_p; - drbs_setupmod_item_p = &((F1AP_DRBs_SetupMod_ItemIEs_t *)ie->value.choice.DRBs_SetupMod_List.list.array[i])->value.choice.DRBs_SetupMod_Item; - drb_p->drb_id = drbs_setupmod_item_p->dRBID; - // TODO in the following, assume only one UP UL TNL is present. - // this matches/assumes OAI CU/DU implementation, can be up to 2! - drb_p->up_dl_tnl_length = 1; - AssertFatal(drbs_setupmod_item_p->dLUPTNLInformation_ToBeSetup_List.list.count > 0, - "no DL UP TNL Information in DRBs to be Setup list\n"); - F1AP_DLUPTNLInformation_ToBeSetup_Item_t *dl_up_tnl_info_p = (F1AP_DLUPTNLInformation_ToBeSetup_Item_t *)drbs_setupmod_item_p->dLUPTNLInformation_ToBeSetup_List.list.array[0]; - F1AP_GTPTunnel_t *dl_up_tnl0 = dl_up_tnl_info_p->dLUPTNLInformation.choice.gTPTunnel; - BIT_STRING_TO_TRANSPORT_LAYER_ADDRESS_IPv4(&dl_up_tnl0->transportLayerAddress, drb_p->up_dl_tnl[0].tl_address); - OCTET_STRING_TO_UINT32(&dl_up_tnl0->gTP_TEID, drb_p->up_dl_tnl[0].teid); - } - } - // SRBs_FailedToBeSetupMod_List - F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextModificationResponseIEs_t, ie, container, - F1AP_ProtocolIE_ID_id_SRBs_FailedToBeSetupMod_List, false); - if(ie!=NULL){ - f1ap_ue_context_modification_resp->srbs_failed_to_be_setup_length = ie->value.choice.SRBs_FailedToBeSetupMod_List.list.count; - f1ap_ue_context_modification_resp->srbs_failed_to_be_setup = calloc(f1ap_ue_context_modification_resp->srbs_failed_to_be_setup_length, - sizeof(f1ap_rb_failed_to_be_setup_t)); - AssertFatal(f1ap_ue_context_modification_resp->srbs_failed_to_be_setup, - "could not allocate memory for f1ap_ue_context_setup_resp->srbs_failed_to_be_setup\n"); - for (i = 0; i < f1ap_ue_context_modification_resp->srbs_failed_to_be_setup_length; ++i) { - f1ap_rb_failed_to_be_setup_t *srb_p = &f1ap_ue_context_modification_resp->srbs_failed_to_be_setup[i]; - srb_p->rb_id = ((F1AP_SRBs_FailedToBeSetupMod_Item_t *)ie->value.choice.SRBs_FailedToBeSetupMod_List.list.array[i])->sRBID; - } - - } - // DRBs_FailedToBeSetupMod_List - F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextModificationResponseIEs_t, ie, container, - F1AP_ProtocolIE_ID_id_DRBs_FailedToBeSetupMod_List, false); - if(ie!=NULL){ - f1ap_ue_context_modification_resp->drbs_failed_to_be_setup_length = ie->value.choice.DRBs_FailedToBeSetupMod_List.list.count; - f1ap_ue_context_modification_resp->drbs_failed_to_be_setup = calloc(f1ap_ue_context_modification_resp->drbs_failed_to_be_setup_length, - sizeof(f1ap_rb_failed_to_be_setup_t)); - AssertFatal(f1ap_ue_context_modification_resp->drbs_failed_to_be_setup, - "could not allocate memory for f1ap_ue_context_setup_resp->drbs_failed_to_be_setup\n"); - for (i = 0; i < f1ap_ue_context_modification_resp->drbs_failed_to_be_setup_length; ++i) { - f1ap_rb_failed_to_be_setup_t *drb_p = &f1ap_ue_context_modification_resp->drbs_failed_to_be_setup[i]; - drb_p->rb_id = ((F1AP_DRBs_FailedToBeSetupMod_Item_t *)ie->value.choice.DRBs_FailedToBeSetupMod_List.list.array[i])->dRBID; - } - } - - // SCell_FailedtoSetupMod_List - F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextModificationResponseIEs_t, ie, container, - F1AP_ProtocolIE_ID_id_SCell_FailedtoSetupMod_List, false); - if(ie!=NULL){ - LOG_E (F1AP, "Not supporting handling of SCell_FailedtoSetupMod_List \n"); - } - - // SRBs_Setup_List - F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextModificationResponseIEs_t, ie, container, - F1AP_ProtocolIE_ID_id_SRBs_SetupMod_List, false); - if(ie!=NULL){ - f1ap_ue_context_modification_resp->srbs_to_be_setup_length = ie->value.choice.SRBs_SetupMod_List.list.count; - f1ap_ue_context_modification_resp->srbs_to_be_setup = calloc(f1ap_ue_context_modification_resp->srbs_to_be_setup_length, - sizeof(f1ap_srb_to_be_setup_t)); - AssertFatal(f1ap_ue_context_modification_resp->srbs_to_be_setup, - "could not allocate memory for f1ap_ue_context_setup_resp->drbs_setup\n"); - for (i = 0; i < f1ap_ue_context_modification_resp->srbs_to_be_setup_length; ++i) { - f1ap_srb_to_be_setup_t *srb_p = &f1ap_ue_context_modification_resp->srbs_to_be_setup[i]; - F1AP_SRBs_SetupMod_Item_t *srbs_setup_item_p; - srbs_setup_item_p = &((F1AP_SRBs_SetupMod_ItemIEs_t *)ie->value.choice.SRBs_SetupMod_List.list.array[i])->value.choice.SRBs_SetupMod_Item; - srb_p->srb_id = srbs_setup_item_p->sRBID; - srb_p->lcid = srbs_setup_item_p->lCID; - } - } - - itti_send_msg_to_task(TASK_RRC_GNB, instance, msg_p); - return 0; + F1AP_UE_CONTEXT_MODIFICATION_RESP(msg_p) = resp; + itti_send_msg_to_task(TASK_RRC_GNB, instance, msg_p); + return 0; } int CU_handle_UE_CONTEXT_MODIFICATION_FAILURE(instance_t instance, sctp_assoc_t assoc_id, uint32_t stream, F1AP_F1AP_PDU_t *pdu) diff --git a/openair2/F1AP/f1ap_cu_ue_context_management.h b/openair2/F1AP/f1ap_cu_ue_context_management.h index 05e67930b3..0bc1815658 100644 --- a/openair2/F1AP/f1ap_cu_ue_context_management.h +++ b/openair2/F1AP/f1ap_cu_ue_context_management.h @@ -36,8 +36,7 @@ /* * UE Context Setup */ -int CU_send_UE_CONTEXT_SETUP_REQUEST(sctp_assoc_t assoc_id, - f1ap_ue_context_setup_t *f1ap_ue_context_setup_req); +int CU_send_UE_CONTEXT_SETUP_REQUEST(sctp_assoc_t assoc_id, const f1ap_ue_context_setup_req_t *req); int CU_handle_UE_CONTEXT_SETUP_RESPONSE(instance_t instance, sctp_assoc_t assoc_id, uint32_t stream, F1AP_F1AP_PDU_t *pdu); @@ -51,15 +50,14 @@ int CU_handle_UE_CONTEXT_RELEASE_REQUEST(instance_t instance, sctp_assoc_t assoc /* * UE Context Release (gNB-CU initiated) */ -int CU_send_UE_CONTEXT_RELEASE_COMMAND(sctp_assoc_t assoc_id, - f1ap_ue_context_release_cmd_t *cmd); +int CU_send_UE_CONTEXT_RELEASE_COMMAND(sctp_assoc_t assoc_id, f1ap_ue_context_rel_cmd_t *cmd); int CU_handle_UE_CONTEXT_RELEASE_COMPLETE(instance_t instance, sctp_assoc_t assoc_id, uint32_t stream, F1AP_F1AP_PDU_t *pdu); /* * UE Context Modification (gNB-CU initiated) */ -int CU_send_UE_CONTEXT_MODIFICATION_REQUEST(sctp_assoc_t assoc_id, f1ap_ue_context_modif_req_t *f1ap_ue_context_modification_req); +int CU_send_UE_CONTEXT_MODIFICATION_REQUEST(sctp_assoc_t assoc_id, const f1ap_ue_context_mod_req_t *req); int CU_handle_UE_CONTEXT_MODIFICATION_RESPONSE(instance_t instance, sctp_assoc_t assoc_id, uint32_t stream, F1AP_F1AP_PDU_t *pdu); int CU_handle_UE_CONTEXT_MODIFICATION_FAILURE(instance_t instance, sctp_assoc_t assoc_id, uint32_t stream, F1AP_F1AP_PDU_t *pdu); diff --git a/openair2/F1AP/f1ap_du_task.c b/openair2/F1AP/f1ap_du_task.c index c231561eec..94b4befb76 100644 --- a/openair2/F1AP/f1ap_du_task.c +++ b/openair2/F1AP/f1ap_du_task.c @@ -36,6 +36,7 @@ #include "f1ap_du_rrc_message_transfer.h" #include "lib/f1ap_rrc_message_transfer.h" #include "lib/f1ap_interface_management.h" +#include "lib/f1ap_ue_context.h" #include "f1ap_du_task.h" #include @@ -188,6 +189,7 @@ void *F1AP_DU_task(void *arg) { case F1AP_UE_CONTEXT_SETUP_RESP: DU_send_UE_CONTEXT_SETUP_RESPONSE(assoc_id, &F1AP_UE_CONTEXT_SETUP_RESP(msg)); + free_ue_context_setup_resp(&F1AP_UE_CONTEXT_SETUP_RESP(msg)); break; case F1AP_UE_CONTEXT_MODIFICATION_RESP: diff --git a/openair2/F1AP/f1ap_du_ue_context_management.c b/openair2/F1AP/f1ap_du_ue_context_management.c index cd9b2865c9..e09f038864 100644 --- a/openair2/F1AP/f1ap_du_ue_context_management.c +++ b/openair2/F1AP/f1ap_du_ue_context_management.c @@ -34,636 +34,40 @@ #include "f1ap_encoder.h" #include "f1ap_itti_messaging.h" #include "f1ap_du_ue_context_management.h" +#include "lib/f1ap_ue_context.h" #include "openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.h" #include "openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h" #include "openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.h" -static void f1ap_read_drb_qos_param(const F1AP_QoSFlowLevelQoSParameters_t *asn1_qos, f1ap_qos_flow_level_qos_parameters_t *drb_qos) -{ - f1ap_qos_characteristics_t *drb_qos_char = &drb_qos->qos_characteristics; - 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->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->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; - drb_qos_char->dynamic.packet_delay_budget = dRB_QoS_Char->choice.dynamic_5QI->packetDelayBudget; - drb_qos_char->dynamic.packet_error_rate.per_scalar = dRB_QoS_Char->choice.dynamic_5QI->packetErrorRate.pER_Scalar; - drb_qos_char->dynamic.packet_error_rate.per_exponent = dRB_QoS_Char->choice.dynamic_5QI->packetErrorRate.pER_Exponent; - } - - /* nGRANallocationRetentionPriority */ - drb_qos->alloc_reten_priority.priority_level = asn1_qos->nGRANallocationRetentionPriority.priorityLevel; - drb_qos->alloc_reten_priority.preemption_vulnerability = asn1_qos->nGRANallocationRetentionPriority.pre_emptionVulnerability; - drb_qos->alloc_reten_priority.preemption_capability = asn1_qos->nGRANallocationRetentionPriority.pre_emptionVulnerability; -} - -static void f1ap_read_flows_mapped(const F1AP_Flows_Mapped_To_DRB_List_t *asn1_flows_mapped, f1ap_flows_mapped_to_drb_t *flows_mapped, int n) -{ - for (int k = 0; k < n; k++) { - f1ap_flows_mapped_to_drb_t *flows_mapped_to_drb = flows_mapped + k; - const F1AP_Flows_Mapped_To_DRB_Item_t *flows_Mapped_To_Drb = asn1_flows_mapped->list.array[0] + k; - - flows_mapped_to_drb->qfi = flows_Mapped_To_Drb->qoSFlowIdentifier; - - /* QoS-Flow-Level-QoS-Parameters */ - { - f1ap_qos_flow_level_qos_parameters_t *flow_qos = &flows_mapped_to_drb->qos_params; - const F1AP_QoSFlowLevelQoSParameters_t *Flow_QoS = &flows_Mapped_To_Drb->qoSFlowLevelQoSParameters; - - /* QoS Characteristics*/ - f1ap_qos_characteristics_t *flow_qos_char = &flow_qos->qos_characteristics; - 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->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->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; - flow_qos_char->dynamic.packet_delay_budget = Flow_QoS_Char->choice.dynamic_5QI->packetDelayBudget; - flow_qos_char->dynamic.packet_error_rate.per_scalar = Flow_QoS_Char->choice.dynamic_5QI->packetErrorRate.pER_Scalar; - flow_qos_char->dynamic.packet_error_rate.per_exponent = Flow_QoS_Char->choice.dynamic_5QI->packetErrorRate.pER_Exponent; - } - - /* nGRANallocationRetentionPriority */ - flow_qos->alloc_reten_priority.priority_level = Flow_QoS->nGRANallocationRetentionPriority.priorityLevel; - flow_qos->alloc_reten_priority.preemption_vulnerability = Flow_QoS->nGRANallocationRetentionPriority.pre_emptionVulnerability; - flow_qos->alloc_reten_priority.preemption_capability = Flow_QoS->nGRANallocationRetentionPriority.pre_emptionVulnerability; - } - } -} - -static void f1ap_read_drb_nssai(const F1AP_SNSSAI_t *asn1_nssai, nssai_t *nssai) -{ - OCTET_STRING_TO_INT8(&asn1_nssai->sST, nssai->sst); - nssai->sd = 0xffffff; - if (asn1_nssai->sD != NULL) { - BUFFER_TO_INT24(asn1_nssai->sD->buf, nssai->sd); - } -} - int DU_handle_UE_CONTEXT_SETUP_REQUEST(instance_t instance, sctp_assoc_t assoc_id, uint32_t stream, F1AP_F1AP_PDU_t *pdu) { - F1AP_UEContextSetupRequest_t *container; - int i; - DevAssert(pdu); - f1ap_ue_context_setup_t ue_context_setup = {0}; - f1ap_ue_context_setup_t *f1ap_ue_context_setup_req = &ue_context_setup; - container = &pdu->choice.initiatingMessage->value.choice.UEContextSetupRequest; - /* GNB_CU_UE_F1AP_ID */ - F1AP_UEContextSetupRequestIEs_t *ieCU; - F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextSetupRequestIEs_t, ieCU, container, - F1AP_ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID, true); - f1ap_ue_context_setup_req->gNB_CU_ue_id = ieCU->value.choice.GNB_CU_UE_F1AP_ID; - /* optional */ - /* GNB_DU_UE_F1AP_ID */ - F1AP_UEContextSetupRequestIEs_t *ieDU_UE; - F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextSetupRequestIEs_t, ieDU_UE, container, - F1AP_ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID, false); - // this should be optional. At present, the DU uses the RNTI, and hence, this - // value cannot exceed 0xffff (or something below, whatever is a valid - // C-RNTI). So we use a value > 0xffff to mark optionality - f1ap_ue_context_setup_req->gNB_DU_ue_id = -1; // 0xffffffff - if (ieDU_UE != NULL) - f1ap_ue_context_setup_req->gNB_DU_ue_id = ieDU_UE->value.choice.GNB_DU_UE_F1AP_ID; - - /* SpCell_ID */ - F1AP_UEContextSetupRequestIEs_t *ieNet; - F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextSetupRequestIEs_t, ieNet, container, - F1AP_ProtocolIE_ID_id_SpCell_ID, true); - PLMNID_TO_MCC_MNC(&ieNet->value.choice.NRCGI.pLMN_Identity, - f1ap_ue_context_setup_req->plmn.mcc, - f1ap_ue_context_setup_req->plmn.mnc, - f1ap_ue_context_setup_req->plmn.mnc_digit_length); - BIT_STRING_TO_NR_CELL_IDENTITY(&ieNet->value.choice.NRCGI.nRCellIdentity, f1ap_ue_context_setup_req->nr_cellid); - /* ServCellIndex */ - F1AP_UEContextSetupRequestIEs_t *ieCell; - F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextSetupRequestIEs_t, ieCell, container, - F1AP_ProtocolIE_ID_id_ServCellIndex, true); - f1ap_ue_context_setup_req->servCellIndex = ieCell->value.choice.ServCellIndex; - /* optional */ - /* CellULConfigured */ - F1AP_UEContextSetupRequestIEs_t *ieULCell; - F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextSetupRequestIEs_t, ieULCell, container, - F1AP_ProtocolIE_ID_id_SpCellULConfigured, false); // SpCellULConfigured - - if (ieULCell) { - /* correct here */ - f1ap_ue_context_setup_req->cellULConfigured = malloc(sizeof(uint32_t)); - - if (f1ap_ue_context_setup_req->cellULConfigured) - *f1ap_ue_context_setup_req->cellULConfigured = ieULCell->value.choice.CellULConfigured; - } else { - f1ap_ue_context_setup_req->cellULConfigured = NULL; + f1ap_ue_context_setup_req_t req = {0}; + if (!decode_ue_context_setup_req(pdu, &req)) { + LOG_E(F1AP, "cannot decode F1 UE Context Setup Request\n"); + free_ue_context_setup_req(&req); + return -1; } - F1AP_UEContextSetupRequestIEs_t *ieCuRrcInfo; - F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextSetupRequestIEs_t, ieCuRrcInfo, container, - F1AP_ProtocolIE_ID_id_CUtoDURRCInformation, false); - if(ieCuRrcInfo!=NULL){ - f1ap_ue_context_setup_req->cu_to_du_rrc_information = (cu_to_du_rrc_information_t *)calloc(1,sizeof(cu_to_du_rrc_information_t)); - cu_to_du_rrc_information_t *cu2du = f1ap_ue_context_setup_req->cu_to_du_rrc_information; - const F1AP_CUtoDURRCInformation_t *cu2duie = &ieCuRrcInfo->value.choice.CUtoDURRCInformation; - if (cu2duie->cG_ConfigInfo != NULL) { - cu2du->cG_ConfigInfo = malloc_or_fail(cu2duie->cG_ConfigInfo->size); - cu2du->cG_ConfigInfo_length = cu2duie->cG_ConfigInfo->size; - memcpy(cu2du->cG_ConfigInfo, cu2duie->cG_ConfigInfo->buf, cu2du->cG_ConfigInfo_length); - } - if(cu2duie->uE_CapabilityRAT_ContainerList!=NULL){ - cu2du->uE_CapabilityRAT_ContainerList = calloc(1, cu2duie->uE_CapabilityRAT_ContainerList->size); - memcpy(cu2du->uE_CapabilityRAT_ContainerList, - cu2duie->uE_CapabilityRAT_ContainerList->buf, - cu2duie->uE_CapabilityRAT_ContainerList->size); - cu2du->uE_CapabilityRAT_ContainerList_length = cu2duie->uE_CapabilityRAT_ContainerList->size; - LOG_D(F1AP, "Size f1ap_ue_context_setup_req->cu_to_du_rrc_information->uE_CapabilityRAT_ContainerList_length: %d \n", f1ap_ue_context_setup_req->cu_to_du_rrc_information->uE_CapabilityRAT_ContainerList_length); - } - if (cu2duie->iE_Extensions != NULL) { - const F1AP_ProtocolExtensionContainer_10696P60_t *ext = (const F1AP_ProtocolExtensionContainer_10696P60_t *)cu2duie->iE_Extensions; - for (int i = 0; i < ext->list.count; ++i) { - const F1AP_CUtoDURRCInformation_ExtIEs_t *cu2du_info = ext->list.array[i]; - switch (cu2du_info->id) { - case F1AP_ProtocolIE_ID_id_HandoverPreparationInformation: - DevAssert(cu2du_info->extensionValue.present == F1AP_CUtoDURRCInformation_ExtIEs__extensionValue_PR_HandoverPreparationInformation); - const F1AP_HandoverPreparationInformation_t *hopi = &cu2du_info->extensionValue.choice.MeasurementTimingConfiguration; - cu2du->handoverPreparationInfo = calloc_or_fail(1, hopi->size); - memcpy(cu2du->handoverPreparationInfo, hopi->buf, hopi->size); - cu2du->handoverPreparationInfo_length = hopi->size; - break; - default: - LOG_W(F1AP, "unsupported CUtoDURRCInformation_ExtIE %ld encountered, ignoring\n", cu2du_info->id); - break; - } - } - } - } + ue_context_setup_request(&req); + free_ue_context_setup_req(&req); - /* DRB */ - F1AP_UEContextSetupRequestIEs_t *ieDrb; - F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextSetupRequestIEs_t, ieDrb, container, - F1AP_ProtocolIE_ID_id_DRBs_ToBeSetup_List, false); - - if(ieDrb!=NULL) { - f1ap_ue_context_setup_req->drbs_to_be_setup_length = ieDrb->value.choice.DRBs_ToBeSetup_List.list.count; - f1ap_ue_context_setup_req->drbs_to_be_setup = calloc(f1ap_ue_context_setup_req->drbs_to_be_setup_length, - sizeof(f1ap_drb_to_be_setup_t)); - AssertFatal(f1ap_ue_context_setup_req->drbs_to_be_setup, - "could not allocate memory for f1ap_ue_context_setup_req->drbs_to_be_setup\n"); - - for (i = 0; i < f1ap_ue_context_setup_req->drbs_to_be_setup_length; ++i) { - f1ap_drb_to_be_setup_t *drb_p = &f1ap_ue_context_setup_req->drbs_to_be_setup[i]; - F1AP_DRBs_ToBeSetup_Item_t *drbs_tobesetup_item_p = - &((F1AP_DRBs_ToBeSetup_ItemIEs_t *)ieDrb->value.choice.DRBs_ToBeSetup_List.list.array[i])->value.choice.DRBs_ToBeSetup_Item; - drb_p->drb_id = drbs_tobesetup_item_p->dRBID; - /* TODO in the following, assume only one UP UL TNL is present. - * this matches/assumes OAI CU implementation, can be up to 2! */ - drb_p->up_ul_tnl_length = 1; - AssertFatal(drbs_tobesetup_item_p->uLUPTNLInformation_ToBeSetup_List.list.count > 0, - "no UL UP TNL Information in DRBs to be Setup list\n"); - F1AP_ULUPTNLInformation_ToBeSetup_Item_t *ul_up_tnl_info_p = (F1AP_ULUPTNLInformation_ToBeSetup_Item_t *)drbs_tobesetup_item_p->uLUPTNLInformation_ToBeSetup_List.list.array[0]; - F1AP_GTPTunnel_t *ul_up_tnl0 = ul_up_tnl_info_p->uLUPTNLInformation.choice.gTPTunnel; - BIT_STRING_TO_TRANSPORT_LAYER_ADDRESS_IPv4(&ul_up_tnl0->transportLayerAddress, drb_p->up_ul_tnl[0].tl_address); - OCTET_STRING_TO_UINT32(&ul_up_tnl0->gTP_TEID, drb_p->up_ul_tnl[0].teid); - // 3GPP assumes GTP-U is on port 2152, but OAI is configurable - drb_p->up_ul_tnl[0].port = getCxt(instance)->net_config.CUport; - - switch (drbs_tobesetup_item_p->rLCMode) { - 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_tobesetup_item_p->rLCMode); - drb_p->rlc_mode = F1AP_RLC_MODE_UM_BIDIR; - break; - } - - if (drbs_tobesetup_item_p->qoSInformation.present == F1AP_QoSInformation_PR_eUTRANQoS) { - AssertFatal(false, "Decode of eUTRANQoS is not implemented yet"); - } // EUTRAN QoS Information - else { - /* 12.1.2 DRB_Information */ - if (drbs_tobesetup_item_p->qoSInformation.present == F1AP_QoSInformation_PR_choice_extension) { - F1AP_QoSInformation_ExtIEs_t *ie = - (F1AP_QoSInformation_ExtIEs_t *)drbs_tobesetup_item_p->qoSInformation.choice.choice_extension; - if (ie->id == F1AP_ProtocolIE_ID_id_DRB_Information && ie->criticality == F1AP_Criticality_reject - && ie->value.present == F1AP_QoSInformation_ExtIEs__value_PR_DRB_Information) { - - const F1AP_DRB_Information_t *dRB_Info = &ie->value.choice.DRB_Information; - f1ap_drb_information_t *drb_info = &drb_p->drb_info; - - /* QoS-Flow-Level-QoS-Parameters */ - /* QoS Characteristics*/ - f1ap_read_drb_qos_param(&dRB_Info->dRB_QoS, &drb_info->drb_qos); - - // 12.1.2.4 flows_Mapped_To_DRB_List - drb_info->flows_to_be_setup_length = dRB_Info->flows_Mapped_To_DRB_List.list.count; - drb_info->flows_mapped_to_drb = calloc(drb_info->flows_to_be_setup_length, sizeof(f1ap_flows_mapped_to_drb_t)); - AssertFatal(drb_info->flows_mapped_to_drb, "could not allocate memory for drb_p->drb_info.flows_mapped_to_drb\n"); - f1ap_read_flows_mapped(&dRB_Info->flows_Mapped_To_DRB_List, drb_info->flows_mapped_to_drb, drb_info->flows_to_be_setup_length); - - /* S-NSSAI */ - f1ap_read_drb_nssai(&dRB_Info->sNSSAI, &drb_p->nssai); - } - } - } - } - } - - /* SRB */ - F1AP_UEContextSetupRequestIEs_t *ieSrb; - F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextSetupRequestIEs_t, ieSrb, container, - F1AP_ProtocolIE_ID_id_SRBs_ToBeSetup_List, false); - - if(ieSrb != NULL) { - f1ap_ue_context_setup_req->srbs_to_be_setup_length = ieSrb->value.choice.SRBs_ToBeSetup_List.list.count; - f1ap_ue_context_setup_req->srbs_to_be_setup = calloc(f1ap_ue_context_setup_req->srbs_to_be_setup_length, - sizeof(f1ap_srb_to_be_setup_t)); - AssertFatal(f1ap_ue_context_setup_req->srbs_to_be_setup, - "could not allocate memory for f1ap_ue_context_setup_req->srbs_to_be_setup\n"); - - for (i = 0; i < f1ap_ue_context_setup_req->srbs_to_be_setup_length; ++i) { - f1ap_srb_to_be_setup_t *srb_p = &f1ap_ue_context_setup_req->srbs_to_be_setup[i]; - F1AP_SRBs_ToBeSetup_Item_t *srbs_tobesetup_item_p; - srbs_tobesetup_item_p = &((F1AP_SRBs_ToBeSetup_ItemIEs_t *)ieSrb->value.choice.SRBs_ToBeSetup_List.list.array[i])->value.choice.SRBs_ToBeSetup_Item; - srb_p->srb_id = srbs_tobesetup_item_p->sRBID; - } - } - - /* RRCContainer */ - F1AP_UEContextSetupRequestIEs_t *ieRRC; - F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextSetupRequestIEs_t, ieRRC, container, - F1AP_ProtocolIE_ID_id_RRCContainer, false); - - if (ieRRC) { - /* correct here */ - if ( ieRRC->value.choice.RRCContainer.size ) { - f1ap_ue_context_setup_req->rrc_container = malloc(ieRRC->value.choice.RRCContainer.size); - memcpy(f1ap_ue_context_setup_req->rrc_container, - ieRRC->value.choice.RRCContainer.buf, ieRRC->value.choice.RRCContainer.size); - f1ap_ue_context_setup_req->rrc_container_length = ieRRC->value.choice.RRCContainer.size; - } else { - LOG_E(F1AP, " RRCContainer in UEContextSetupRequestIEs size id 0\n"); - } - } - - ue_context_setup_request(f1ap_ue_context_setup_req); return 0; } -int DU_send_UE_CONTEXT_SETUP_RESPONSE(sctp_assoc_t assoc_id, f1ap_ue_context_setup_t *resp) +int DU_send_UE_CONTEXT_SETUP_RESPONSE(sctp_assoc_t assoc_id, f1ap_ue_context_setup_resp_t *resp) { - F1AP_F1AP_PDU_t pdu= {0}; - F1AP_UEContextSetupResponse_t *out; - 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_UEContextSetup; - tmp->criticality = F1AP_Criticality_reject; - tmp->value.present = F1AP_SuccessfulOutcome__value_PR_UEContextSetupResponse; - out = &tmp->value.choice.UEContextSetupResponse; - /* mandatory */ - /* c1. GNB_CU_UE_F1AP_ID */ - asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextSetupResponseIEs_t, ie1); - ie1->id = F1AP_ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID; - ie1->criticality = F1AP_Criticality_reject; - ie1->value.present = F1AP_UEContextSetupResponseIEs__value_PR_GNB_CU_UE_F1AP_ID; - ie1->value.choice.GNB_CU_UE_F1AP_ID = resp->gNB_CU_ue_id; - /* mandatory */ - /* c2. GNB_DU_UE_F1AP_ID */ - asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextSetupResponseIEs_t, ie2); - ie2->id = F1AP_ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID; - ie2->criticality = F1AP_Criticality_reject; - ie2->value.present = F1AP_UEContextSetupResponseIEs__value_PR_GNB_DU_UE_F1AP_ID; - ie2->value.choice.GNB_DU_UE_F1AP_ID = resp->gNB_DU_ue_id; + F1AP_F1AP_PDU_t *pdu = encode_ue_context_setup_resp(resp); - /* mandatory */ - /* c3. DUtoCURRCInformation */ - if(resp->du_to_cu_rrc_information){ - asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextSetupResponseIEs_t, ie3); - ie3->id = F1AP_ProtocolIE_ID_id_DUtoCURRCInformation; - ie3->criticality = F1AP_Criticality_reject; - ie3->value.present = F1AP_UEContextSetupResponseIEs__value_PR_DUtoCURRCInformation; - if(resp->du_to_cu_rrc_information->cellGroupConfig!=NULL){ - /* cellGroupConfig */ - OCTET_STRING_fromBuf(&ie3->value.choice.DUtoCURRCInformation.cellGroupConfig, (const char *)resp->du_to_cu_rrc_information->cellGroupConfig, - resp->du_to_cu_rrc_information->cellGroupConfig_length); - } - - /* OPTIONAL */ - /* measGapConfig */ - if (resp->du_to_cu_rrc_information->measGapConfig!=NULL) { - OCTET_STRING_fromBuf(ie3->value.choice.DUtoCURRCInformation.measGapConfig, (const char *)resp->du_to_cu_rrc_information->measGapConfig, - resp->du_to_cu_rrc_information->measGapConfig_length); - } - - /* OPTIONAL */ - /* requestedP_MaxFR1 */ - if (resp->du_to_cu_rrc_information->requestedP_MaxFR1!=NULL) { - OCTET_STRING_fromBuf(ie3->value.choice.DUtoCURRCInformation.requestedP_MaxFR1, (const char *)resp->du_to_cu_rrc_information->requestedP_MaxFR1, - resp->du_to_cu_rrc_information->requestedP_MaxFR1_length); - } - } - - /* optional */ - /* c4. C_RNTI */ - if (resp->crnti!=NULL) { - asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextSetupResponseIEs_t, ie4); - ie4->id = F1AP_ProtocolIE_ID_id_C_RNTI; - ie4->criticality = F1AP_Criticality_ignore; - ie4->value.present = F1AP_UEContextSetupResponseIEs__value_PR_C_RNTI; - ie4->value.choice.C_RNTI = *resp->crnti; - } - - /* optional */ - /* c5. ResourceCoordinationTransferContainer */ - if (0) { - asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextSetupResponseIEs_t, ie5); - ie5->id = F1AP_ProtocolIE_ID_id_ResourceCoordinationTransferContainer; - ie5->criticality = F1AP_Criticality_ignore; - ie5->value.present = F1AP_UEContextSetupResponseIEs__value_PR_ResourceCoordinationTransferContainer; - OCTET_STRING_fromBuf(&ie5->value.choice.ResourceCoordinationTransferContainer, "asdsa", - strlen("asdsa")); - } - - /* optional */ - /* c6. FullConfiguration */ - if (0) { - asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextSetupResponseIEs_t, ie6); - ie6->id = F1AP_ProtocolIE_ID_id_FullConfiguration; - ie6->criticality = F1AP_Criticality_ignore; - ie6->value.present = F1AP_UEContextSetupResponseIEs__value_PR_FullConfiguration; - ie6->value.choice.FullConfiguration = F1AP_FullConfiguration_full; //enum - } - - /* mandatory */ - /* c7. DRBs_Setup_List */ - if(resp->drbs_to_be_setup_length > 0){ - asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextSetupResponseIEs_t, ie7); - ie7->id = F1AP_ProtocolIE_ID_id_DRBs_Setup_List; - ie7->criticality = F1AP_Criticality_ignore; - ie7->value.present = F1AP_UEContextSetupResponseIEs__value_PR_DRBs_Setup_List; - for (int i=0; i< resp->drbs_to_be_setup_length; i++) { - f1ap_drb_to_be_setup_t *drb = &resp->drbs_to_be_setup[i]; - // - asn1cSequenceAdd(ie7->value.choice.DRBs_Setup_List.list, - F1AP_DRBs_Setup_ItemIEs_t, drbs_setup_item_ies); - drbs_setup_item_ies->id = F1AP_ProtocolIE_ID_id_DRBs_Setup_Item; - drbs_setup_item_ies->criticality = F1AP_Criticality_ignore; - drbs_setup_item_ies->value.present = F1AP_DRBs_Setup_ItemIEs__value_PR_DRBs_Setup_Item; - /* 7.1 DRBs_Setup_Item */ - /* ADD */ - F1AP_DRBs_Setup_Item_t *drbs_setup_item=&drbs_setup_item_ies->value.choice.DRBs_Setup_Item; - /* dRBID */ - drbs_setup_item->dRBID = drb->drb_id; - - /* OPTIONAL */ - /* lCID */ - //drbs_setup_item.lCID = (F1AP_LCID_t *)calloc(1, sizeof(F1AP_LCID_t)); - //drbs_setup_item.lCID = 1L; - - for (int j = 0; j < drb->up_dl_tnl_length; j++) { - const f1ap_up_tnl_t *tnl = &drb->up_dl_tnl[j]; - DevAssert(tnl->teid > 0); - - /* ADD */ - asn1cSequenceAdd(drbs_setup_item->dLUPTNLInformation_ToBeSetup_List.list, - F1AP_DLUPTNLInformation_ToBeSetup_Item_t, dLUPTNLInformation_ToBeSetup_Item); - dLUPTNLInformation_ToBeSetup_Item->dLUPTNLInformation.present = F1AP_UPTransportLayerInformation_PR_gTPTunnel; - /* gTPTunnel */ - asn1cCalloc(dLUPTNLInformation_ToBeSetup_Item->dLUPTNLInformation.choice.gTPTunnel,gTPTunnel); - /* transportLayerAddress */ - TRANSPORT_LAYER_ADDRESS_IPv4_TO_BIT_STRING(tnl->tl_address, &gTPTunnel->transportLayerAddress); - /* gTP_TEID */ - INT32_TO_OCTET_STRING(tnl->teid, &gTPTunnel->gTP_TEID); - } // for j - } // for i - - } - - /* mandatory */ - /* c8. SRBs_FailedToBeSetup_List */ - if(0) { - asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextSetupResponseIEs_t, ie8); - ie8->id = F1AP_ProtocolIE_ID_id_SRBs_FailedToBeSetup_List; - ie8->criticality = F1AP_Criticality_ignore; - ie8->value.present = F1AP_UEContextSetupResponseIEs__value_PR_SRBs_FailedToBeSetup_List; - - for (int i=0; i<1; i++) { - // - asn1cSequenceAdd(ie8->value.choice.SRBs_FailedToBeSetup_List.list, - F1AP_SRBs_FailedToBeSetup_ItemIEs_t, srbs_failedToBeSetup_item_ies); - srbs_failedToBeSetup_item_ies->id = F1AP_ProtocolIE_ID_id_SRBs_FailedToBeSetup_Item; - srbs_failedToBeSetup_item_ies->criticality = F1AP_Criticality_ignore; - srbs_failedToBeSetup_item_ies->value.present = F1AP_SRBs_FailedToBeSetup_ItemIEs__value_PR_SRBs_FailedToBeSetup_Item; - /* 8.1 SRBs_Setup_Item */ - F1AP_SRBs_FailedToBeSetup_Item_t *srbs_failedToBeSetup_item= - &srbs_failedToBeSetup_item_ies->value.choice.SRBs_FailedToBeSetup_Item; - /* sRBID */ - srbs_failedToBeSetup_item->sRBID = 13L; - /* cause */ - asn1cCalloc(srbs_failedToBeSetup_item->cause, tmp); - // dummy value - tmp->present = F1AP_Cause_PR_radioNetwork; - - switch(tmp->present) { - case F1AP_Cause_PR_radioNetwork: - tmp->choice.radioNetwork = F1AP_CauseRadioNetwork_unspecified; - break; - - case F1AP_Cause_PR_transport: - tmp->choice.transport = F1AP_CauseTransport_unspecified; - break; - - case F1AP_Cause_PR_protocol: - tmp->choice.protocol = F1AP_CauseProtocol_unspecified; - break; - - case F1AP_Cause_PR_misc: - tmp->choice.misc = F1AP_CauseMisc_unspecified; - break; - - case F1AP_Cause_PR_NOTHING: - default: - break; - } // switch - } // for i - } - - /* */ - /* c9. DRBs_FailedToBeSetup_List */ - if(0) { - asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextSetupResponseIEs_t, ie9); - ie9->id = F1AP_ProtocolIE_ID_id_DRBs_FailedToBeSetup_List; - ie9->criticality = F1AP_Criticality_ignore; - ie9->value.present = F1AP_UEContextSetupResponseIEs__value_PR_DRBs_FailedToBeSetup_List; - - for (int i=0; i<1; i++) { - asn1cSequenceAdd(ie9->value.choice.DRBs_FailedToBeSetup_List.list, - F1AP_DRBs_FailedToBeSetup_ItemIEs_t, drbs_failedToBeSetup_item_ies); - drbs_failedToBeSetup_item_ies->id = F1AP_ProtocolIE_ID_id_DRBs_FailedToBeSetup_Item; - drbs_failedToBeSetup_item_ies->criticality = F1AP_Criticality_ignore; - drbs_failedToBeSetup_item_ies->value.present = F1AP_DRBs_FailedToBeSetup_ItemIEs__value_PR_DRBs_FailedToBeSetup_Item; - /* 9.1 DRBs_Setup_Item */ - /* ADD */ - F1AP_DRBs_FailedToBeSetup_Item_t *drbs_failedToBeSetup_item= - &drbs_failedToBeSetup_item_ies->value.choice.DRBs_FailedToBeSetup_Item; - /* dRBID */ - drbs_failedToBeSetup_item->dRBID = 14; - /* cause */ - asn1cCalloc(drbs_failedToBeSetup_item->cause,tmp); - // dummy value - tmp->present = F1AP_Cause_PR_radioNetwork; - - switch(tmp->present) { - case F1AP_Cause_PR_radioNetwork: - tmp->choice.radioNetwork = F1AP_CauseRadioNetwork_unspecified; - break; - - case F1AP_Cause_PR_transport: - tmp->choice.transport = F1AP_CauseTransport_unspecified; - break; - - case F1AP_Cause_PR_protocol: - tmp->choice.protocol = F1AP_CauseProtocol_unspecified; - break; - - case F1AP_Cause_PR_misc: - tmp->choice.misc = F1AP_CauseMisc_unspecified; - break; - - case F1AP_Cause_PR_NOTHING: - default: - break; - } // switch - } // for i - } - - // /* */ - /* c10. SCell_FailedtoSetup_List */ - if(0) { - asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextSetupResponseIEs_t, ie10); - ie10->id = F1AP_ProtocolIE_ID_id_SCell_FailedtoSetup_List; - ie10->criticality = F1AP_Criticality_ignore; - ie10->value.present = F1AP_UEContextSetupResponseIEs__value_PR_SCell_FailedtoSetup_List; - - for (int i=0; i<1; i++) { - asn1cSequenceAdd(ie10->value.choice.SCell_FailedtoSetup_List.list, - F1AP_SCell_FailedtoSetup_ItemIEs_t, sCell_FailedtoSetup_item_ies); - sCell_FailedtoSetup_item_ies->id = F1AP_ProtocolIE_ID_id_SCell_FailedtoSetup_Item; - sCell_FailedtoSetup_item_ies->criticality = F1AP_Criticality_ignore; - sCell_FailedtoSetup_item_ies->value.present = F1AP_SCell_FailedtoSetup_ItemIEs__value_PR_SCell_FailedtoSetup_Item; - /* 10.1 DRBs_Setup_Item */ - F1AP_SCell_FailedtoSetup_Item_t *sCell_FailedtoSetup_item= - &sCell_FailedtoSetup_item_ies->value.choice.SCell_FailedtoSetup_Item; - /* sCell_ID */ - AssertFatal(false, "handle correct CellID\n"); - f1ap_served_cell_info_t cellID = {0}; - addnRCGI(sCell_FailedtoSetup_item->sCell_ID, &cellID); - /* cause */ - asn1cCalloc(sCell_FailedtoSetup_item->cause, tmp); - // dummy value - tmp->present = F1AP_Cause_PR_radioNetwork; - - switch(tmp->present) { - case F1AP_Cause_PR_radioNetwork: - tmp->choice.radioNetwork = F1AP_CauseRadioNetwork_unspecified; - break; - - case F1AP_Cause_PR_transport: - tmp->choice.transport = F1AP_CauseTransport_unspecified; - break; - - case F1AP_Cause_PR_protocol: - tmp->choice.protocol = F1AP_CauseProtocol_unspecified; - break; - - case F1AP_Cause_PR_misc: - tmp->choice.misc = F1AP_CauseMisc_unspecified; - break; - - case F1AP_Cause_PR_NOTHING: - default: - break; - } // switch - } // for i - } - - /* mandatory */ - /* c11. SRBs_Setup_List */ - if(resp->srbs_to_be_setup_length > 0){ - asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextSetupResponseIEs_t, ie11); - ie11->id = F1AP_ProtocolIE_ID_id_SRBs_Setup_List; - ie11->criticality = F1AP_Criticality_ignore; - ie11->value.present = F1AP_UEContextSetupResponseIEs__value_PR_SRBs_Setup_List; - - for (int i=0; i< resp->srbs_to_be_setup_length; i++) {// - asn1cSequenceAdd(ie11->value.choice.SRBs_Setup_List.list, - F1AP_SRBs_Setup_ItemIEs_t, srbs_setup_item_ies); - srbs_setup_item_ies->id = F1AP_ProtocolIE_ID_id_SRBs_Setup_Item; - srbs_setup_item_ies->criticality = F1AP_Criticality_ignore; - srbs_setup_item_ies->value.present = F1AP_SRBs_Setup_ItemIEs__value_PR_SRBs_Setup_Item; - /* 11.1 SRBs_Setup_Item */ - /* ADD */ - F1AP_SRBs_Setup_Item_t *srbs_setup_item=&srbs_setup_item_ies->value.choice.SRBs_Setup_Item; - /* sRBID */ - srbs_setup_item->sRBID = resp->srbs_to_be_setup[i].srb_id; - srbs_setup_item->lCID = resp->srbs_to_be_setup[i].lcid; - } - } - - /* Optional */ - /* c12. InactivityMonitoringResponse */ - if (0) { - asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextSetupResponseIEs_t, ie11); - ie11->id = F1AP_ProtocolIE_ID_id_InactivityMonitoringResponse; - ie11->criticality = F1AP_Criticality_ignore; - ie11->value.present = F1AP_UEContextSetupResponseIEs__value_PR_InactivityMonitoringResponse; - ie11->value.choice.InactivityMonitoringResponse = F1AP_InactivityMonitoringResponse_not_supported; - } - - /* Optional */ - /* c13. CriticalityDiagnostics */ - if (0) { - asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextSetupResponseIEs_t, ie12); - ie12->id = F1AP_ProtocolIE_ID_id_CriticalityDiagnostics; - ie12->criticality = F1AP_Criticality_ignore; - ie12->value.present = F1AP_UEContextSetupResponseIEs__value_PR_CriticalityDiagnostics; - asn1cCallocOne(ie12->value.choice.CriticalityDiagnostics.procedureCode, - F1AP_ProcedureCode_id_UEContextSetup); - asn1cCallocOne(ie12->value.choice.CriticalityDiagnostics.triggeringMessage, - F1AP_TriggeringMessage_initiating_message); - asn1cCallocOne(ie12->value.choice.CriticalityDiagnostics.procedureCriticality, - F1AP_Criticality_reject); - asn1cCallocOne(ie12->value.choice.CriticalityDiagnostics.transactionID, - 0); - } - - /* encode */ - if (f1ap_encode_pdu(&pdu, &buffer, &len) < 0) { + uint8_t *buffer = NULL; + uint32_t len = 0; + if (f1ap_encode_pdu(pdu, &buffer, &len) < 0) { LOG_E(F1AP, "Failed to encode F1 UE CONTEXT SETUP RESPONSE\n"); return -1; } f1ap_itti_send_sctp_data_req(assoc_id, buffer, len); + ASN_STRUCT_FREE(asn_DEF_F1AP_F1AP_PDU, pdu); return 0; } @@ -672,757 +76,79 @@ int DU_send_UE_CONTEXT_SETUP_FAILURE(sctp_assoc_t assoc_id) AssertFatal(1==0,"Not implemented yet\n"); } -int DU_send_UE_CONTEXT_RELEASE_REQUEST(sctp_assoc_t assoc_id, f1ap_ue_context_release_req_t *req) +int DU_send_UE_CONTEXT_RELEASE_REQUEST(sctp_assoc_t assoc_id, f1ap_ue_context_rel_req_t *req) { - F1AP_F1AP_PDU_t pdu = {0}; - F1AP_UEContextReleaseRequest_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_UEContextReleaseRequest; - tmp->criticality = F1AP_Criticality_reject; - tmp->value.present = F1AP_InitiatingMessage__value_PR_UEContextReleaseRequest; - out = &tmp->value.choice.UEContextReleaseRequest; - /* mandatory */ - /* c1. GNB_CU_UE_F1AP_ID */ - asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextReleaseRequestIEs_t, ie1); - ie1->id = F1AP_ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID; - ie1->criticality = F1AP_Criticality_reject; - ie1->value.present = F1AP_UEContextReleaseRequestIEs__value_PR_GNB_CU_UE_F1AP_ID; - ie1->value.choice.GNB_CU_UE_F1AP_ID = req->gNB_CU_ue_id; - /* mandatory */ - /* c2. GNB_DU_UE_F1AP_ID */ - asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextReleaseRequestIEs_t, ie2); - ie2->id = F1AP_ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID; - ie2->criticality = F1AP_Criticality_reject; - ie2->value.present = F1AP_UEContextReleaseRequestIEs__value_PR_GNB_DU_UE_F1AP_ID; - ie2->value.choice.GNB_DU_UE_F1AP_ID = req->gNB_DU_ue_id; - /* mandatory */ - /* c3. Cause */ - asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextReleaseRequestIEs_t, ie3); - ie3->id = F1AP_ProtocolIE_ID_id_Cause; - ie3->criticality = F1AP_Criticality_ignore; - ie3->value.present = F1AP_UEContextReleaseRequestIEs__value_PR_Cause; + F1AP_F1AP_PDU_t *pdu = encode_ue_context_rel_req(req); - switch (req->cause) { - case F1AP_CAUSE_RADIO_NETWORK: - ie3->value.choice.Cause.present = F1AP_Cause_PR_radioNetwork; - ie3->value.choice.Cause.choice.radioNetwork = req->cause_value; - break; - - case F1AP_CAUSE_TRANSPORT: - ie3->value.choice.Cause.present = F1AP_Cause_PR_transport; - ie3->value.choice.Cause.choice.transport = req->cause_value; - break; - - case F1AP_CAUSE_PROTOCOL: - ie3->value.choice.Cause.present = F1AP_Cause_PR_protocol; - ie3->value.choice.Cause.choice.protocol = req->cause_value; - break; - - case F1AP_CAUSE_MISC: - ie3->value.choice.Cause.present = F1AP_Cause_PR_misc; - ie3->value.choice.Cause.choice.misc = req->cause_value; - break; - - case F1AP_CAUSE_NOTHING: - default: - ie3->value.choice.Cause.present = F1AP_Cause_PR_NOTHING; - break; - } - - /* encode */ - if (f1ap_encode_pdu(&pdu, &buffer, &len) < 0) { + uint8_t *buffer = NULL; + uint32_t len = 0; + if (f1ap_encode_pdu(pdu, &buffer, &len) < 0) { LOG_E(F1AP, "Failed to encode F1 context release request\n"); return -1; } f1ap_itti_send_sctp_data_req(assoc_id, buffer, len); + ASN_STRUCT_FREE(asn_DEF_F1AP_F1AP_PDU, pdu); return 0; } int DU_handle_UE_CONTEXT_RELEASE_COMMAND(instance_t instance, sctp_assoc_t assoc_id, uint32_t stream, F1AP_F1AP_PDU_t *pdu) { - F1AP_UEContextReleaseCommand_t *container; - F1AP_UEContextReleaseCommandIEs_t *ie; - - f1ap_ue_context_release_req_t ue_context_release = {0}; - f1ap_ue_context_release_req_t *f1ap_ue_context_release_cmd = &ue_context_release; - - DevAssert(pdu); - container = &pdu->choice.initiatingMessage->value.choice.UEContextReleaseCommand; - // GNB_CU_UE_F1AP_ID - F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextReleaseCommandIEs_t, ie, container, - F1AP_ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID, true); - f1ap_ue_context_release_cmd->gNB_CU_ue_id = ie->value.choice.GNB_CU_UE_F1AP_ID; - // GNB_DU_UE_F1AP_ID - F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextReleaseCommandIEs_t, ie, container, - F1AP_ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID, true); - f1ap_ue_context_release_cmd->gNB_DU_ue_id = ie->value.choice.GNB_DU_UE_F1AP_ID; - - // We don't need the Cause - // Optional RRC Container: if present, send to UE - F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextReleaseCommandIEs_t, ie, container, - F1AP_ProtocolIE_ID_id_RRCContainer, false); - - if (ie != NULL) { - f1ap_ue_context_release_cmd->rrc_container = malloc(ie->value.choice.RRCContainer.size); - AssertFatal(f1ap_ue_context_release_cmd->rrc_container != NULL, "out of memory\n"); - memcpy(f1ap_ue_context_release_cmd->rrc_container, ie->value.choice.RRCContainer.buf, ie->value.choice.RRCContainer.size); - f1ap_ue_context_release_cmd->rrc_container_length = ie->value.choice.RRCContainer.size; - - // conditionally have SRB ID if there is RRC container - F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextReleaseCommandIEs_t, ie, container, F1AP_ProtocolIE_ID_id_SRBID, true); - f1ap_ue_context_release_cmd->srb_id = ie->value.choice.SRBID; + f1ap_ue_context_rel_cmd_t cmd = {0}; + if (!decode_ue_context_rel_cmd(pdu, &cmd)) { + LOG_E(F1AP, "cannot decode F1 UE Context Release Command\n"); + free_ue_context_rel_cmd(&cmd); + return -1; } - F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextReleaseCommandIEs_t, ie, container, - F1AP_ProtocolIE_ID_id_Cause, true); - switch (ie->value.choice.Cause.present){ - case F1AP_Cause_PR_radioNetwork: - f1ap_ue_context_release_cmd->cause = F1AP_CAUSE_RADIO_NETWORK; - break; - case F1AP_Cause_PR_transport: - f1ap_ue_context_release_cmd->cause = F1AP_CAUSE_TRANSPORT; - break; - case F1AP_Cause_PR_protocol: - f1ap_ue_context_release_cmd->cause = F1AP_CAUSE_PROTOCOL; - break; - case F1AP_Cause_PR_misc: - f1ap_ue_context_release_cmd->cause = F1AP_CAUSE_MISC; - break; - default: - LOG_W(F1AP, "Unknown cause for UE context release command\n"); - break; - - } - - ue_context_release_command(f1ap_ue_context_release_cmd); + ue_context_release_command(&cmd); + free_ue_context_rel_cmd(&cmd); return 0; } -int DU_send_UE_CONTEXT_RELEASE_COMPLETE(sctp_assoc_t assoc_id, f1ap_ue_context_release_complete_t *complete) +int DU_send_UE_CONTEXT_RELEASE_COMPLETE(sctp_assoc_t assoc_id, f1ap_ue_context_rel_cplt_t *cplt) { - F1AP_F1AP_PDU_t pdu= {0}; - F1AP_UEContextReleaseComplete_t *out; - /* Create */ - /* 0. Message Type */ - pdu.present = F1AP_F1AP_PDU_PR_successfulOutcome; - asn1cCalloc(pdu.choice.successfulOutcome, tmp); - tmp->procedureCode = F1AP_ProcedureCode_id_UEContextRelease; - tmp->criticality = F1AP_Criticality_reject; - tmp->value.present = F1AP_SuccessfulOutcome__value_PR_UEContextReleaseComplete; - out = &tmp->value.choice.UEContextReleaseComplete; - /* mandatory */ - /* c1. GNB_CU_UE_F1AP_ID */ - asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextReleaseCompleteIEs_t, ie1); - ie1->id = F1AP_ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID; - ie1->criticality = F1AP_Criticality_reject; - ie1->value.present = F1AP_UEContextReleaseCompleteIEs__value_PR_GNB_CU_UE_F1AP_ID; - ie1->value.choice.GNB_CU_UE_F1AP_ID = complete->gNB_CU_ue_id; - /* mandatory */ - /* c2. GNB_DU_UE_F1AP_ID */ - asn1cSequenceAdd(out->protocolIEs.list,F1AP_UEContextReleaseCompleteIEs_t, ie2); - ie2->id = F1AP_ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID; - ie2->criticality = F1AP_Criticality_reject; - ie2->value.present = F1AP_UEContextReleaseCompleteIEs__value_PR_GNB_DU_UE_F1AP_ID; - ie2->value.choice.GNB_DU_UE_F1AP_ID = complete->gNB_DU_ue_id; - /* optional -> currently not used */ - /* c3. CriticalityDiagnostics */ - //if (0) { - // ie = (F1AP_UEContextReleaseCompleteIEs_t *)calloc(1, sizeof(F1AP_UEContextReleaseCompleteIEs_t)); - // ie->id = F1AP_ProtocolIE_ID_id_CriticalityDiagnostics; - // ie->criticality = F1AP_Criticality_ignore; - // ie->value.present = F1AP_UEContextReleaseCompleteIEs__value_PR_CriticalityDiagnostics; - // // dummy value - // /* optional */ - // /* procedureCode */ - // if (0) { - // ie->value.choice.CriticalityDiagnostics.procedureCode = (F1AP_ProcedureCode_t *)calloc(1, sizeof(F1AP_ProcedureCode_t)); - // ie->value.choice.CriticalityDiagnostics.procedureCode = 0L; - // } - // /* optional */ - // /* triggeringMessage */ - // if (0) { - // ie->value.choice.CriticalityDiagnostics.triggeringMessage = (F1AP_TriggeringMessage_t *)calloc(1, sizeof(F1AP_TriggeringMessage_t)); - // ie->value.choice.CriticalityDiagnostics.triggeringMessage = (F1AP_TriggeringMessage_t *)F1AP_TriggeringMessage_successful_outcome; - // } - // /* optional */ - // /* procedureCriticality */ - // if (0) { - // ie->value.choice.CriticalityDiagnostics.procedureCriticality = (F1AP_Criticality_t *)calloc(1, sizeof(F1AP_Criticality_t)); - // ie->value.choice.CriticalityDiagnostics.procedureCriticality = F1AP_Criticality_reject; - // } - // /* optional */ - // /* transactionID */ - // if (0) { - // ie->value.choice.CriticalityDiagnostics.transactionID = (F1AP_TransactionID_t *)calloc(1, sizeof(F1AP_TransactionID_t)); - // ie->value.choice.CriticalityDiagnostics.transactionID = 0L; - // } - // /* optional */ - // /* F1AP_CriticalityDiagnostics_IE_List */ - // if (0) { - // for (i=0; - // i<0; - // i++) { - // F1AP_CriticalityDiagnostics_IE_Item_t *criticalityDiagnostics_ie_item = (F1AP_CriticalityDiagnostics_IE_Item_t *)calloc(1, sizeof(F1AP_CriticalityDiagnostics_IE_Item_t));; - // criticalityDiagnostics_ie_item->iECriticality = F1AP_Criticality_reject; - // criticalityDiagnostics_ie_item->iE_ID = 0L; - // criticalityDiagnostics_ie_item->typeOfError = F1AP_TypeOfError_not_understood; - // asn1cSeqAdd(&ie->value.choice.CriticalityDiagnostics.iEsCriticalityDiagnostics->list, - // criticalityDiagnostics_ie_item); - // } - // } - // asn1cSeqAdd(&out->protocolIEs.list, ie); - //} - /* encode */ + F1AP_F1AP_PDU_t *pdu = encode_ue_context_rel_cplt(cplt); + uint8_t *buffer; uint32_t len; - - if (f1ap_encode_pdu(&pdu, &buffer, &len) < 0) { + if (f1ap_encode_pdu(pdu, &buffer, &len) < 0) { LOG_E(F1AP, "Failed to encode F1 context release complete\n"); return -1; } f1ap_itti_send_sctp_data_req(assoc_id, buffer, len); + ASN_STRUCT_FREE(asn_DEF_F1AP_F1AP_PDU, pdu); return 0; } int DU_handle_UE_CONTEXT_MODIFICATION_REQUEST(instance_t instance, sctp_assoc_t assoc_id, uint32_t stream, F1AP_F1AP_PDU_t *pdu) { - F1AP_UEContextModificationRequest_t *container; - int i; - f1ap_ue_context_modif_req_t ue_context_modification = {0}; - f1ap_ue_context_modif_req_t *f1ap_ue_context_modification_req = &ue_context_modification; - container = &pdu->choice.initiatingMessage->value.choice.UEContextModificationRequest; - - /* mandatory */ - /* GNB_CU_UE_F1AP_ID */ - F1AP_UEContextModificationRequestIEs_t *ieCU; - F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextModificationRequestIEs_t, ieCU, container, - F1AP_ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID, true); - f1ap_ue_context_modification_req->gNB_CU_ue_id = ieCU->value.choice.GNB_CU_UE_F1AP_ID; - - /* mandatory */ - /* GNB_DU_UE_F1AP_ID */ - F1AP_UEContextModificationRequestIEs_t *ieDU_UE; - F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextModificationRequestIEs_t, ieDU_UE, container, - F1AP_ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID, true); - f1ap_ue_context_modification_req->gNB_DU_ue_id = ieDU_UE->value.choice.GNB_DU_UE_F1AP_ID; - - /* SRB */ - F1AP_UEContextModificationRequestIEs_t *ieSrb; - F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextModificationRequestIEs_t, ieSrb, container, - F1AP_ProtocolIE_ID_id_SRBs_ToBeSetupMod_List, false); - - F1AP_UEContextModificationRequestIEs_t *ieTxInd; - F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextModificationRequestIEs_t, - ieTxInd, - container, - F1AP_ProtocolIE_ID_id_TransmissionActionIndicator, - false); - - if (ieTxInd != NULL) { - f1ap_ue_context_modification_req->transm_action_ind = calloc_or_fail(1, sizeof(*f1ap_ue_context_modification_req->transm_action_ind)); - *f1ap_ue_context_modification_req->transm_action_ind = ieTxInd->value.choice.TransmissionActionIndicator; - // Stop is guaranteed to be 0, by restart might be different from 1 - static_assert((int)F1AP_TransmissionActionIndicator_restart == (int)TransmActionInd_RESTART, - "mismatch of ASN.1 and internal representation\n"); - } - - if(ieSrb != NULL) { - f1ap_ue_context_modification_req->srbs_to_be_setup_length = ieSrb->value.choice.SRBs_ToBeSetupMod_List.list.count; - f1ap_ue_context_modification_req->srbs_to_be_setup = calloc(f1ap_ue_context_modification_req->srbs_to_be_setup_length, - sizeof(f1ap_srb_to_be_setup_t)); - AssertFatal(f1ap_ue_context_modification_req->srbs_to_be_setup, - "could not allocate memory for f1ap_ue_context_setup_req->srbs_to_be_setup\n"); - - for (i = 0; i < f1ap_ue_context_modification_req->srbs_to_be_setup_length; ++i) { - f1ap_srb_to_be_setup_t *srb_p = &f1ap_ue_context_modification_req->srbs_to_be_setup[i]; - F1AP_SRBs_ToBeSetupMod_Item_t *srbs_tobesetupmod_item_p; - srbs_tobesetupmod_item_p = &((F1AP_SRBs_ToBeSetupMod_ItemIEs_t *)ieSrb->value.choice.SRBs_ToBeSetupMod_List.list.array[i])->value.choice.SRBs_ToBeSetupMod_Item; - srb_p->srb_id = srbs_tobesetupmod_item_p->sRBID; - } - } - - /* DRB */ - F1AP_UEContextModificationRequestIEs_t *ieDrb; - F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextModificationRequestIEs_t, ieDrb, container, - F1AP_ProtocolIE_ID_id_DRBs_ToBeSetupMod_List, false); - - if(ieDrb!=NULL) { - f1ap_ue_context_modification_req->drbs_to_be_setup_length = ieDrb->value.choice.DRBs_ToBeSetupMod_List.list.count; - f1ap_ue_context_modification_req->drbs_to_be_setup = calloc(f1ap_ue_context_modification_req->drbs_to_be_setup_length, - sizeof(f1ap_drb_to_be_setup_t)); - AssertFatal(f1ap_ue_context_modification_req->drbs_to_be_setup, - "could not allocate memory for f1ap_ue_context_setup_req->drbs_to_be_setup\n"); - - for (i = 0; i < f1ap_ue_context_modification_req->drbs_to_be_setup_length; ++i) { - f1ap_drb_to_be_setup_t *drb_p = &f1ap_ue_context_modification_req->drbs_to_be_setup[i]; - F1AP_DRBs_ToBeSetupMod_Item_t *drbs_tobesetupmod_item_p = - &((F1AP_DRBs_ToBeSetupMod_ItemIEs_t *)ieDrb->value.choice.DRBs_ToBeSetupMod_List.list.array[i])->value.choice.DRBs_ToBeSetupMod_Item; - drb_p->drb_id = drbs_tobesetupmod_item_p->dRBID; - /* TODO in the following, assume only one UP UL TNL is present. - * this matches/assumes OAI CU implementation, can be up to 2! */ - drb_p->up_ul_tnl_length = 1; - AssertFatal(drbs_tobesetupmod_item_p->uLUPTNLInformation_ToBeSetup_List.list.count > 0, - "no UL UP TNL Information in DRBs to be Setup list\n"); - F1AP_ULUPTNLInformation_ToBeSetup_Item_t *ul_up_tnl_info_p = (F1AP_ULUPTNLInformation_ToBeSetup_Item_t *)drbs_tobesetupmod_item_p->uLUPTNLInformation_ToBeSetup_List.list.array[0]; - F1AP_GTPTunnel_t *ul_up_tnl0 = ul_up_tnl_info_p->uLUPTNLInformation.choice.gTPTunnel; - BIT_STRING_TO_TRANSPORT_LAYER_ADDRESS_IPv4(&ul_up_tnl0->transportLayerAddress, drb_p->up_ul_tnl[0].tl_address); - OCTET_STRING_TO_UINT32(&ul_up_tnl0->gTP_TEID, drb_p->up_ul_tnl[0].teid); - // 3GPP assumes GTP-U is on port 2152, but OAI is configurable - 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 = 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) { - AssertFatal(false, "Decode of eUTRANQoS is not implemented yet"); - } // EUTRAN QoS Information - else { - /* 12.1.2 DRB_Information */ - if (drbs_tobesetupmod_item_p->qoSInformation.present == F1AP_QoSInformation_PR_choice_extension) { - F1AP_QoSInformation_ExtIEs_t *ie = - (F1AP_QoSInformation_ExtIEs_t *)drbs_tobesetupmod_item_p->qoSInformation.choice.choice_extension; - if (ie->id == F1AP_ProtocolIE_ID_id_DRB_Information && ie->criticality == F1AP_Criticality_reject - && ie->value.present == F1AP_QoSInformation_ExtIEs__value_PR_DRB_Information) { - - const F1AP_DRB_Information_t *dRB_Info = &ie->value.choice.DRB_Information; - f1ap_drb_information_t *drb_info = &drb_p->drb_info; - - /* QoS-Flow-Level-QoS-Parameters */ - /* QoS Characteristics*/ - f1ap_read_drb_qos_param(&dRB_Info->dRB_QoS, &drb_info->drb_qos); - - // 12.1.2.4 flows_Mapped_To_DRB_List - drb_info->flows_to_be_setup_length = dRB_Info->flows_Mapped_To_DRB_List.list.count; - drb_info->flows_mapped_to_drb = calloc(drb_info->flows_to_be_setup_length, sizeof(f1ap_flows_mapped_to_drb_t)); - AssertFatal(drb_info->flows_mapped_to_drb, "could not allocate memory for drb_p->drb_info.flows_mapped_to_drb\n"); - f1ap_read_flows_mapped(&dRB_Info->flows_Mapped_To_DRB_List, drb_info->flows_mapped_to_drb, drb_info->flows_to_be_setup_length); - - /* S-NSSAI */ - f1ap_read_drb_nssai(&dRB_Info->sNSSAI, &drb_p->nssai); - } - } - } - } - } - - F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextModificationRequestIEs_t, ieDrb, container, - F1AP_ProtocolIE_ID_id_DRBs_ToBeReleased_List, false); - if (ieDrb != NULL) { - f1ap_ue_context_modification_req->drbs_to_be_released_length = ieDrb->value.choice.DRBs_ToBeReleased_List.list.count; - f1ap_ue_context_modification_req->drbs_to_be_released = - calloc(f1ap_ue_context_modification_req->drbs_to_be_released_length, sizeof(f1ap_drb_to_be_released_t)); - AssertFatal(f1ap_ue_context_modification_req->drbs_to_be_released, - "could not allocate memory for f1ap_ue_context_released_req->drbs_to_be_released\n"); - for (i = 0; i < f1ap_ue_context_modification_req->drbs_to_be_released_length; ++i) { - F1AP_DRBs_ToBeReleased_ItemIEs_t *tbrel = (F1AP_DRBs_ToBeReleased_ItemIEs_t *)ieDrb->value.choice.DRBs_ToBeReleased_List.list.array[i]; - DevAssert(tbrel->id == F1AP_ProtocolIE_ID_id_DRBs_ToBeReleased_Item); - DevAssert(tbrel->value.present == F1AP_DRBs_ToBeReleased_ItemIEs__value_PR_DRBs_ToBeReleased_Item); - f1ap_ue_context_modification_req->drbs_to_be_released[i].rb_id = tbrel->value.choice.DRBs_ToBeReleased_Item.dRBID; - } - } - - /* RRC Reconfiguration Complete indicator */ - F1AP_UEContextModificationRequestIEs_t *ieReconf; - F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextModificationRequestIEs_t, ieReconf, container, - F1AP_ProtocolIE_ID_id_RRCReconfigurationCompleteIndicator, false); - - if(ieReconf) { - switch(ieReconf->value.choice.RRCReconfigurationCompleteIndicator){ - case F1AP_RRCReconfigurationCompleteIndicator_true: - f1ap_ue_context_modification_req->ReconfigComplOutcome = RRCreconf_success; - break; - - case F1AP_RRCReconfigurationCompleteIndicator_failure: - f1ap_ue_context_modification_req->ReconfigComplOutcome = RRCreconf_failure; - break; - } - } - - /* RRCContainer */ - F1AP_UEContextModificationRequestIEs_t *ieRRC; - F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextModificationRequestIEs_t, ieRRC, container, - F1AP_ProtocolIE_ID_id_RRCContainer, false); - - if (ieRRC) { - /* correct here */ - if ( ieRRC->value.choice.RRCContainer.size ) { - f1ap_ue_context_modification_req->rrc_container = malloc(ieRRC->value.choice.RRCContainer.size); - memcpy(f1ap_ue_context_modification_req->rrc_container, - ieRRC->value.choice.RRCContainer.buf, ieRRC->value.choice.RRCContainer.size); - f1ap_ue_context_modification_req->rrc_container_length = ieRRC->value.choice.RRCContainer.size; - } else { - LOG_E(F1AP, " RRCContainer in UEContextModificationRequestIEs size id 0\n"); - } - } else { - LOG_D(F1AP, "can't find RRCContainer in UEContextModificationRequestIEs by id %ld \n", F1AP_ProtocolIE_ID_id_RRCContainer); - } - - /* CU2DU Information */ - F1AP_UEContextModificationRequestIEs_t *ieCU2DU = NULL; - F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_UEContextModificationRequestIEs_t, - ieCU2DU, - container, - F1AP_ProtocolIE_ID_id_CUtoDURRCInformation, - false); - if (ieCU2DU != NULL) { - f1ap_ue_context_modification_req->cu_to_du_rrc_information = - calloc(1, sizeof(*f1ap_ue_context_modification_req->cu_to_du_rrc_information)); - AssertFatal(f1ap_ue_context_modification_req->cu_to_du_rrc_information != NULL, "out of memory\n"); - cu_to_du_rrc_information_t *cu2du = f1ap_ue_context_modification_req->cu_to_du_rrc_information; - const F1AP_CUtoDURRCInformation_t *cu2duie = &ieCU2DU->value.choice.CUtoDURRCInformation; - if (cu2duie->cG_ConfigInfo != NULL) - LOG_W(F1AP, "UE RNTI %04x: ignoring cg_ConfigInfo, not implemented\n", f1ap_ue_context_modification_req->gNB_DU_ue_id); - if (cu2duie->measConfig != NULL) - LOG_W(F1AP, "UE RNTI %04x: ignoring measConfig, not implemented\n", f1ap_ue_context_modification_req->gNB_DU_ue_id); - if (cu2duie->uE_CapabilityRAT_ContainerList != NULL) { - F1AP_UE_CapabilityRAT_ContainerList_t *uecap = cu2duie->uE_CapabilityRAT_ContainerList; - cu2du->uE_CapabilityRAT_ContainerList = calloc(uecap->size, sizeof(*cu2du->uE_CapabilityRAT_ContainerList)); - AssertFatal(cu2du->uE_CapabilityRAT_ContainerList != NULL, "out of memory\n"); - cu2du->uE_CapabilityRAT_ContainerList_length = uecap->size; - memcpy(cu2du->uE_CapabilityRAT_ContainerList, uecap->buf, uecap->size); - } - } - - ue_context_modification_request(f1ap_ue_context_modification_req); - return 0; -} - -int DU_send_UE_CONTEXT_MODIFICATION_RESPONSE(sctp_assoc_t assoc_id, f1ap_ue_context_modif_resp_t *resp) -{ - F1AP_F1AP_PDU_t pdu= {0}; - F1AP_UEContextModificationResponse_t *out; - 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_UEContextModification; - tmp->criticality = F1AP_Criticality_reject; - tmp->value.present = F1AP_SuccessfulOutcome__value_PR_UEContextModificationResponse; - out = &tmp->value.choice.UEContextModificationResponse; - /* mandatory */ - /* c1. GNB_CU_UE_F1AP_ID */ - asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextModificationResponseIEs_t, ie1); - ie1->id = F1AP_ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID; - ie1->criticality = F1AP_Criticality_reject; - ie1->value.present = F1AP_UEContextModificationResponseIEs__value_PR_GNB_CU_UE_F1AP_ID; - ie1->value.choice.GNB_CU_UE_F1AP_ID = resp->gNB_CU_ue_id; - /* mandatory */ - /* c2. GNB_DU_UE_F1AP_ID */ - asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextModificationResponseIEs_t, ie2); - ie2->id = F1AP_ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID; - ie2->criticality = F1AP_Criticality_reject; - ie2->value.present = F1AP_UEContextModificationResponseIEs__value_PR_GNB_DU_UE_F1AP_ID; - ie2->value.choice.GNB_DU_UE_F1AP_ID = resp->gNB_DU_ue_id; - - /* optional */ - /* c3. ResourceCoordinationTransferContainer */ - if (0) { - asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextModificationResponseIEs_t, ie3); - ie3->id = F1AP_ProtocolIE_ID_id_ResourceCoordinationTransferContainer; - ie3->criticality = F1AP_Criticality_ignore; - ie3->value.present = F1AP_UEContextModificationResponseIEs__value_PR_ResourceCoordinationTransferContainer; - OCTET_STRING_fromBuf(&ie3->value.choice.ResourceCoordinationTransferContainer, "asdsa1d32sa1d31asd31as", - strlen("asdsa1d32sa1d31asd31as")); - } - - /* optional */ - /* c4. DUtoCURRCInformation */ - if(resp->du_to_cu_rrc_information!=NULL){ - asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextModificationResponseIEs_t, ie4); - ie4->id = F1AP_ProtocolIE_ID_id_DUtoCURRCInformation; - ie4->criticality = F1AP_Criticality_reject; - ie4->value.present = F1AP_UEContextModificationResponseIEs__value_PR_DUtoCURRCInformation; - if(resp->du_to_cu_rrc_information->cellGroupConfig!=NULL){ - /* cellGroupConfig */ - OCTET_STRING_fromBuf(&ie4->value.choice.DUtoCURRCInformation.cellGroupConfig, (const char *)resp->du_to_cu_rrc_information->cellGroupConfig, - resp->du_to_cu_rrc_information->cellGroupConfig_length); - } - - /* OPTIONAL */ - /* measGapConfig */ - if (resp->du_to_cu_rrc_information->measGapConfig!=NULL) { - OCTET_STRING_fromBuf(ie4->value.choice.DUtoCURRCInformation.measGapConfig, (const char *)resp->du_to_cu_rrc_information->measGapConfig, - resp->du_to_cu_rrc_information->measGapConfig_length); - } - - /* OPTIONAL */ - /* requestedP_MaxFR1 */ - if (resp->du_to_cu_rrc_information->requestedP_MaxFR1!=NULL) { - OCTET_STRING_fromBuf(ie4->value.choice.DUtoCURRCInformation.requestedP_MaxFR1, (const char *)resp->du_to_cu_rrc_information->requestedP_MaxFR1, - resp->du_to_cu_rrc_information->requestedP_MaxFR1_length); - } - } - - - /* optional */ - /* c5. DRBs_Setup_List */ - if(resp->drbs_to_be_setup_length > 0) { - asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextModificationResponseIEs_t, ie5); - ie5->id = F1AP_ProtocolIE_ID_id_DRBs_SetupMod_List; - ie5->criticality = F1AP_Criticality_ignore; - ie5->value.present = F1AP_UEContextModificationResponseIEs__value_PR_DRBs_SetupMod_List; - for (int i=0; i< resp->drbs_to_be_setup_length; i++) { - asn1cSequenceAdd(ie5->value.choice.DRBs_SetupMod_List.list, F1AP_DRBs_SetupMod_ItemIEs_t, drbs_setupmod_item_ies); - drbs_setupmod_item_ies->id = F1AP_ProtocolIE_ID_id_DRBs_SetupMod_Item; - drbs_setupmod_item_ies->criticality = F1AP_Criticality_ignore; - drbs_setupmod_item_ies->value.present = F1AP_DRBs_SetupMod_ItemIEs__value_PR_DRBs_SetupMod_Item; - /* 7.1 DRBs_Setup_Item */ - /* ADD */ - F1AP_DRBs_SetupMod_Item_t *drbs_setupmod_item=&drbs_setupmod_item_ies->value.choice.DRBs_SetupMod_Item; - /* dRBID */ - drbs_setupmod_item->dRBID = resp->drbs_to_be_setup[i].drb_id; - - for (int j=0; jdrbs_to_be_setup[i].up_dl_tnl_length; j++) { - const f1ap_up_tnl_t *tnl = &resp->drbs_to_be_setup[i].up_dl_tnl[j]; - DevAssert(tnl->teid > 0); - - /* ADD */ - asn1cSequenceAdd(drbs_setupmod_item->dLUPTNLInformation_ToBeSetup_List.list, - F1AP_DLUPTNLInformation_ToBeSetup_Item_t, dLUPTNLInformation_ToBeSetup_Item); - dLUPTNLInformation_ToBeSetup_Item->dLUPTNLInformation.present = F1AP_UPTransportLayerInformation_PR_gTPTunnel; - /* gTPTunnel */ - asn1cCalloc(dLUPTNLInformation_ToBeSetup_Item->dLUPTNLInformation.choice.gTPTunnel,gTPTunnel); - /* transportLayerAddress */ - TRANSPORT_LAYER_ADDRESS_IPv4_TO_BIT_STRING(tnl->tl_address, &gTPTunnel->transportLayerAddress); - /* gTP_TEID */ - INT32_TO_OCTET_STRING(tnl->teid, &gTPTunnel->gTP_TEID); - } // for j - } // for i - } - - /* optional */ - /* c6. DRBs_Modified_List */ - if(resp->drbs_to_be_modified_length > 0){ - asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextModificationResponseIEs_t, ie6); - ie6->id = F1AP_ProtocolIE_ID_id_DRBs_Modified_List; - ie6->criticality = F1AP_Criticality_ignore; - ie6->value.present = F1AP_UEContextModificationResponseIEs__value_PR_DRBs_Modified_List; - - for (int i=0; idrbs_to_be_modified_length; i++) { - asn1cSequenceAdd(ie6->value.choice.DRBs_Modified_List.list, - F1AP_DRBs_Modified_ItemIEs_t, drbs_modified_item_ies); - drbs_modified_item_ies->id = F1AP_ProtocolIE_ID_id_DRBs_Modified_Item; - drbs_modified_item_ies->criticality = F1AP_Criticality_ignore; - drbs_modified_item_ies->value.present = F1AP_DRBs_Modified_ItemIEs__value_PR_DRBs_Modified_Item; - /* DRBs_modified_Item */ - F1AP_DRBs_Modified_Item_t *drbs_modified_item= &drbs_modified_item_ies->value.choice.DRBs_Modified_Item; - /* dRBID */ - drbs_modified_item->dRBID = resp->drbs_to_be_modified[i].drb_id; - - /* ULTunnels_Modified_List */ - for (int j=0; jdrbs_to_be_modified[i].up_dl_tnl_length; j++) { - /* DLTunnels_Modified_Item */ - asn1cSequenceAdd(drbs_modified_item->dLUPTNLInformation_ToBeSetup_List.list, - F1AP_DLUPTNLInformation_ToBeSetup_Item_t, dLUPTNLInformation_ToBeSetup_Item); - asn1cCalloc(dLUPTNLInformation_ToBeSetup_Item, tmp); - tmp->dLUPTNLInformation.present = F1AP_UPTransportLayerInformation_PR_gTPTunnel; - asn1cCalloc(dLUPTNLInformation_ToBeSetup_Item->dLUPTNLInformation.choice.gTPTunnel, gTPTunnel); - /* transportLayerAddress */ - struct sockaddr_in addr= {0}; - inet_pton(AF_INET, getCxt(0)->net_config.DU_f1u_ip_address, &addr.sin_addr.s_addr); - TRANSPORT_LAYER_ADDRESS_IPv4_TO_BIT_STRING(addr.sin_addr.s_addr, &gTPTunnel->transportLayerAddress); - /* gTP_TEID */ - INT32_TO_OCTET_STRING(resp->drbs_to_be_modified[i].up_dl_tnl[j].teid, &gTPTunnel->gTP_TEID); - } - } - } - - /* optional */ - /* c7. SRBs_FailedToBeSetupMod_List */ - if(resp->srbs_failed_to_be_setup_length > 0){ - asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextModificationResponseIEs_t, ie7); - ie7->id = F1AP_ProtocolIE_ID_id_SRBs_FailedToBeSetupMod_List; - ie7->criticality = F1AP_Criticality_reject; - ie7->value.present = F1AP_UEContextModificationResponseIEs__value_PR_SRBs_FailedToBeSetupMod_List; - - for (int i=0; isrbs_to_be_setup_length; i++) { - asn1cSequenceAdd(ie7->value.choice.SRBs_FailedToBeSetupMod_List.list, - F1AP_SRBs_FailedToBeSetupMod_ItemIEs_t, srbs_failedToBeSetupMod_item_ies); - srbs_failedToBeSetupMod_item_ies->id = F1AP_ProtocolIE_ID_id_SRBs_FailedToBeSetupMod_Item; - srbs_failedToBeSetupMod_item_ies->criticality = F1AP_Criticality_ignore; - srbs_failedToBeSetupMod_item_ies->value.present = F1AP_SRBs_FailedToBeSetupMod_ItemIEs__value_PR_SRBs_FailedToBeSetupMod_Item; - /* 9.1 SRBs_FailedToBeSetupMod_Item */ - F1AP_SRBs_FailedToBeSetupMod_Item_t *srbs_failedToBeSetupMod_item= - &srbs_failedToBeSetupMod_item_ies->value.choice.SRBs_FailedToBeSetupMod_Item; - /* - sRBID */ - srbs_failedToBeSetupMod_item->sRBID = resp->srbs_failed_to_be_setup[i].rb_id; - asn1cCalloc(srbs_failedToBeSetupMod_item->cause, tmp); - tmp->present = F1AP_Cause_PR_radioNetwork; - tmp->choice.radioNetwork = F1AP_CauseRadioNetwork_unknown_or_already_allocated_gnb_du_ue_f1ap_id; - } - } - - /* optional */ - /* c8. DRBs_FailedToBeSetupMod_List */ - if(resp->drbs_failed_to_be_setup_length > 0){ - asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextModificationResponseIEs_t, ie8); - ie8->id = F1AP_ProtocolIE_ID_id_DRBs_FailedToBeSetupMod_List; - ie8->criticality = F1AP_Criticality_reject; - ie8->value.present = F1AP_UEContextModificationResponseIEs__value_PR_DRBs_FailedToBeSetupMod_List; - - for (int i=0; idrbs_failed_to_be_setup_length; i++) { - asn1cSequenceAdd(ie8->value.choice.DRBs_FailedToBeSetupMod_List.list, - F1AP_DRBs_FailedToBeSetupMod_ItemIEs_t, drbs_failedToBeSetupMod_item_ies); - drbs_failedToBeSetupMod_item_ies->id = F1AP_ProtocolIE_ID_id_DRBs_FailedToBeSetupMod_Item; - drbs_failedToBeSetupMod_item_ies->criticality = F1AP_Criticality_reject; - drbs_failedToBeSetupMod_item_ies->value.present = F1AP_DRBs_FailedToBeSetupMod_ItemIEs__value_PR_DRBs_FailedToBeSetupMod_Item; - /* DRBs_FailedToBeSetupMod_Item */ - F1AP_DRBs_FailedToBeSetupMod_Item_t *drbs_failedToBeSetupMod_item= - &drbs_failedToBeSetupMod_item_ies->value.choice.DRBs_FailedToBeSetupMod_Item; - /* dRBID */ - drbs_failedToBeSetupMod_item->dRBID = resp->drbs_failed_to_be_setup[i].rb_id; - drbs_failedToBeSetupMod_item->cause = (F1AP_Cause_t *)calloc(1, sizeof(F1AP_Cause_t)); - drbs_failedToBeSetupMod_item->cause->present = F1AP_Cause_PR_radioNetwork; - drbs_failedToBeSetupMod_item->cause->choice.radioNetwork = F1AP_CauseRadioNetwork_unknown_or_already_allocated_gnb_du_ue_f1ap_id; - } - } - - /* optional */ - /* c9. SCell_FailedtoSetupMod_List */ - if(0){ - asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextModificationResponseIEs_t, ie9); - ie9->id = F1AP_ProtocolIE_ID_id_SCell_FailedtoSetupMod_List; - ie9->criticality = F1AP_Criticality_ignore; - ie9->value.present = F1AP_UEContextModificationResponseIEs__value_PR_SCell_FailedtoSetupMod_List; - - for (int i=0; i<1; i++) { - asn1cSequenceAdd(ie9->value.choice.SCell_FailedtoSetupMod_List.list, - F1AP_SCell_FailedtoSetupMod_ItemIEs_t, scell_failedtoSetupMod_item_ies); - scell_failedtoSetupMod_item_ies->id = F1AP_ProtocolIE_ID_id_SCell_FailedtoSetupMod_Item; - scell_failedtoSetupMod_item_ies->criticality = F1AP_Criticality_ignore; - scell_failedtoSetupMod_item_ies->value.present = F1AP_SCell_FailedtoSetupMod_ItemIEs__value_PR_SCell_FailedtoSetupMod_Item; - /* 8.1 SCell_ToBeSetup_Item */ - F1AP_SCell_FailedtoSetupMod_Item_t *scell_failedtoSetupMod_item=&scell_failedtoSetupMod_item_ies->value.choice.SCell_FailedtoSetupMod_Item; - /* - sCell_ID */ - addnRCGI(scell_failedtoSetupMod_item->sCell_ID, &getCxt(0)->setupReq.cell[i].info); - asn1cCalloc(scell_failedtoSetupMod_item->cause, tmp); - tmp->present = F1AP_Cause_PR_radioNetwork; - tmp->choice.radioNetwork = F1AP_CauseRadioNetwork_unknown_or_already_allocated_gnb_du_ue_f1ap_id; - } - } - - /* optional */ - /* c10. DRBs_FailedToBeModified_List */ - if(0){ - asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextModificationResponseIEs_t, ie10); - ie10->id = F1AP_ProtocolIE_ID_id_DRBs_FailedToBeModified_List; - ie10->criticality = F1AP_Criticality_reject; - ie10->value.present = F1AP_UEContextModificationResponseIEs__value_PR_DRBs_FailedToBeModified_List; - - for (int i=0; i<1; i++) { - asn1cSequenceAdd(ie10->value.choice.DRBs_FailedToBeModified_List.list, - F1AP_DRBs_FailedToBeModified_ItemIEs_t, drbs_failedToBeModified_item_ies); - drbs_failedToBeModified_item_ies->id = F1AP_ProtocolIE_ID_id_DRBs_FailedToBeModified_Item; - drbs_failedToBeModified_item_ies->criticality = F1AP_Criticality_reject; - drbs_failedToBeModified_item_ies->value.present = F1AP_DRBs_FailedToBeModified_ItemIEs__value_PR_DRBs_FailedToBeModified_Item; - /* 13.1 DRBs_FailedToBeModified_Item */ - F1AP_DRBs_FailedToBeModified_Item_t *drbs_failedToBeModified_item= - &drbs_failedToBeModified_item_ies->value.choice.DRBs_FailedToBeModified_Item ; - /* dRBID */ - drbs_failedToBeModified_item->dRBID = 30L; - asn1cCalloc(drbs_failedToBeModified_item->cause, tmp); - tmp->present = F1AP_Cause_PR_radioNetwork; - tmp->choice.radioNetwork = F1AP_CauseRadioNetwork_unknown_or_already_allocated_gnb_du_ue_f1ap_id; - } - } - - // /* */ - /* c11. CriticalityDiagnostics */ - if (0) { - asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextModificationResponseIEs_t, ie11); - ie11->id = F1AP_ProtocolIE_ID_id_CriticalityDiagnostics; - ie11->criticality = F1AP_Criticality_ignore; - ie11->value.present = F1AP_UEContextModificationResponseIEs__value_PR_CriticalityDiagnostics; - - // dummy value - /* optional */ - /* procedureCode */ - if (0) { - ie11->value.choice.CriticalityDiagnostics.procedureCode = (F1AP_ProcedureCode_t *)calloc(1, sizeof(F1AP_ProcedureCode_t)); - *ie11->value.choice.CriticalityDiagnostics.procedureCode = 0L; - } - - /* optional */ - /* triggeringMessage */ - if (0) { - ie11->value.choice.CriticalityDiagnostics.triggeringMessage = (F1AP_TriggeringMessage_t *)calloc(1, sizeof(F1AP_TriggeringMessage_t)); - *ie11->value.choice.CriticalityDiagnostics.triggeringMessage = F1AP_TriggeringMessage_successful_outcome; - } - - /* optional */ - /* procedureCriticality */ - if (0) { - ie11->value.choice.CriticalityDiagnostics.procedureCriticality = (F1AP_Criticality_t *)calloc(1, sizeof(F1AP_Criticality_t)); - *ie11->value.choice.CriticalityDiagnostics.procedureCriticality = F1AP_Criticality_reject; - } - - /* optional */ - /* transactionID */ - if (0) { - ie11->value.choice.CriticalityDiagnostics.transactionID = (F1AP_TransactionID_t *)calloc(1, sizeof(F1AP_TransactionID_t)); - *ie11->value.choice.CriticalityDiagnostics.transactionID = 0L; - } - - /* optional */ - /* F1AP_CriticalityDiagnostics_IE_List */ - if (0) { - for (int i=0; i<0; i++) { - asn1cSequenceAdd(ie11->value.choice.CriticalityDiagnostics.iEsCriticalityDiagnostics->list, F1AP_CriticalityDiagnostics_IE_Item_t, criticalityDiagnostics_ie_item); - criticalityDiagnostics_ie_item->iECriticality = F1AP_Criticality_reject; - criticalityDiagnostics_ie_item->iE_ID = 0L; - criticalityDiagnostics_ie_item->typeOfError = F1AP_TypeOfError_not_understood; - } - } - } - /* optional */ - /* c12. SRBs_Setup_List */ - if(resp->srbs_to_be_setup_length > 0){ - asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextModificationResponseIEs_t, ie12); - ie12->id = F1AP_ProtocolIE_ID_id_SRBs_SetupMod_List; - ie12->criticality = F1AP_Criticality_ignore; - ie12->value.present = F1AP_UEContextModificationResponseIEs__value_PR_SRBs_SetupMod_List; - - for (int i=0; i< resp->srbs_to_be_setup_length; i++) {// - asn1cSequenceAdd(ie12->value.choice.SRBs_SetupMod_List.list, - F1AP_SRBs_SetupMod_ItemIEs_t, srbs_setupmod_item_ies); - srbs_setupmod_item_ies->id = F1AP_ProtocolIE_ID_id_SRBs_SetupMod_Item; - srbs_setupmod_item_ies->criticality = F1AP_Criticality_ignore; - srbs_setupmod_item_ies->value.present = F1AP_SRBs_SetupMod_ItemIEs__value_PR_SRBs_SetupMod_Item; - /* 11.1 SRBs_Setup_Item */ - /* ADD */ - F1AP_SRBs_SetupMod_Item_t *srbs_setupmod_item=&srbs_setupmod_item_ies->value.choice.SRBs_SetupMod_Item; - /* sRBID */ - srbs_setupmod_item->sRBID = resp->srbs_to_be_setup[i].srb_id; - srbs_setupmod_item->lCID = resp->srbs_to_be_setup[i].srb_id; - } - } - - /* encode */ - if (f1ap_encode_pdu(&pdu, &buffer, &len) < 0) { - LOG_E(F1AP, "Failed to encode F1 UE CONTEXT MODIFICATION RESPONSE\n"); + f1ap_ue_context_mod_req_t req = {0}; + if (!decode_ue_context_mod_req(pdu, &req)) { + LOG_E(F1AP, "cannot decode F1 UE Context Modification Request\n"); + free_ue_context_mod_req(&req); return -1; } + ue_context_modification_request(&req); + free_ue_context_mod_req(&req); + + return 0; +} + +int DU_send_UE_CONTEXT_MODIFICATION_RESPONSE(sctp_assoc_t assoc_id, f1ap_ue_context_mod_resp_t *resp) +{ + F1AP_F1AP_PDU_t *pdu = encode_ue_context_mod_resp(resp); + + uint8_t *buffer = NULL; + uint32_t len = 0; + if (f1ap_encode_pdu(pdu, &buffer, &len) < 0) { + LOG_E(F1AP, "Failed to encode F1 UE CONTEXT SETUP RESPONSE\n"); + return -1; + } f1ap_itti_send_sctp_data_req(assoc_id, buffer, len); + ASN_STRUCT_FREE(asn_DEF_F1AP_F1AP_PDU, pdu); return 0; } diff --git a/openair2/F1AP/f1ap_du_ue_context_management.h b/openair2/F1AP/f1ap_du_ue_context_management.h index 43663ba538..b6c12de18b 100644 --- a/openair2/F1AP/f1ap_du_ue_context_management.h +++ b/openair2/F1AP/f1ap_du_ue_context_management.h @@ -36,7 +36,7 @@ /* * UE Context Setup */ -int DU_send_UE_CONTEXT_SETUP_RESPONSE(sctp_assoc_t assoc_id, f1ap_ue_context_setup_t *req); +int DU_send_UE_CONTEXT_SETUP_RESPONSE(sctp_assoc_t assoc_id, f1ap_ue_context_setup_resp_t *resp); int DU_handle_UE_CONTEXT_SETUP_REQUEST(instance_t instance, sctp_assoc_t assoc_id, uint32_t stream, F1AP_F1AP_PDU_t *pdu); int DU_send_UE_CONTEXT_SETUP_FAILURE(sctp_assoc_t assoc_id); @@ -45,9 +45,7 @@ int DU_send_UE_CONTEXT_SETUP_FAILURE(sctp_assoc_t assoc_id); /* * UE Context Release Request (gNB-DU initiated) */ -int DU_send_UE_CONTEXT_RELEASE_REQUEST(sctp_assoc_t assoc_id, - f1ap_ue_context_release_req_t *req); - +int DU_send_UE_CONTEXT_RELEASE_REQUEST(sctp_assoc_t assoc_id, f1ap_ue_context_rel_req_t *req); /* * UE Context Release Command (gNB-CU initiated) @@ -57,13 +55,13 @@ int DU_handle_UE_CONTEXT_RELEASE_COMMAND(instance_t instance, sctp_assoc_t assoc /* * UE Context Release Complete (gNB-DU initiated) */ -int DU_send_UE_CONTEXT_RELEASE_COMPLETE(sctp_assoc_t assoc_id, f1ap_ue_context_release_complete_t *complete); +int DU_send_UE_CONTEXT_RELEASE_COMPLETE(sctp_assoc_t assoc_id, f1ap_ue_context_rel_cplt_t *cplt); /* * UE Context Modification (gNB-CU initiated) */ int DU_handle_UE_CONTEXT_MODIFICATION_REQUEST(instance_t instance, sctp_assoc_t assoc_id, uint32_t stream, F1AP_F1AP_PDU_t *pdu); -int DU_send_UE_CONTEXT_MODIFICATION_RESPONSE(sctp_assoc_t assoc_id, f1ap_ue_context_modif_resp_t *resp); +int DU_send_UE_CONTEXT_MODIFICATION_RESPONSE(sctp_assoc_t assoc_id, f1ap_ue_context_mod_resp_t *resp); int DU_send_UE_CONTEXT_MODIFICATION_FAILURE(sctp_assoc_t assoc_id); diff --git a/openair2/F1AP/lib/CMakeLists.txt b/openair2/F1AP/lib/CMakeLists.txt index 0c6137dc30..978f69fb29 100644 --- a/openair2/F1AP/lib/CMakeLists.txt +++ b/openair2/F1AP/lib/CMakeLists.txt @@ -2,8 +2,9 @@ add_library(f1ap_lib OBJECT f1ap_lib_common.c f1ap_rrc_message_transfer.c f1ap_interface_management.c + f1ap_ue_context.c ) -target_link_libraries(f1ap_lib PRIVATE asn1_f1ap) +target_link_libraries(f1ap_lib PRIVATE asn1_f1ap ds) 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 index 0ac1f8d63a..acd6859ad7 100644 --- a/openair2/F1AP/lib/f1ap_interface_management.c +++ b/openair2/F1AP/lib/f1ap_interface_management.c @@ -30,7 +30,7 @@ #include "f1ap_lib_common.h" #include "f1ap_lib_includes.h" #include "f1ap_messages_types.h" -#include "f1ap_lib_extern.h" +#include "lib/f1ap_interface_management.h" F1AP_UE_associatedLogicalF1_ConnectionItem_t encode_f1ap_ue_to_reset(const f1ap_ue_to_reset_t *to_reset) { @@ -156,9 +156,9 @@ bool decode_f1ap_reset(const F1AP_F1AP_PDU_t *pdu, f1ap_reset_t *out) /* Check presence of mandatory IEs */ F1AP_Reset_t *in = &pdu->choice.initiatingMessage->value.choice.Reset; F1AP_ResetIEs_t *ie; - F1AP_LIB_FIND_IE(F1AP_ResetIEs_t, ie, in, F1AP_ProtocolIE_ID_id_TransactionID, true); - F1AP_LIB_FIND_IE(F1AP_ResetIEs_t, ie, in, F1AP_ProtocolIE_ID_id_Cause, true); - F1AP_LIB_FIND_IE(F1AP_ResetIEs_t, ie, in, F1AP_ProtocolIE_ID_id_ResetType, true); + F1AP_LIB_FIND_IE(F1AP_ResetIEs_t, ie, &in->protocolIEs.list, F1AP_ProtocolIE_ID_id_TransactionID, true); + F1AP_LIB_FIND_IE(F1AP_ResetIEs_t, ie, &in->protocolIEs.list, F1AP_ProtocolIE_ID_id_Cause, true); + F1AP_LIB_FIND_IE(F1AP_ResetIEs_t, ie, &in->protocolIEs.list, F1AP_ProtocolIE_ID_id_ResetType, true); /* Loop over all IEs */ for (int i = 0; i < in->protocolIEs.list.count; i++) { @@ -303,7 +303,7 @@ bool decode_f1ap_reset_ack(const struct F1AP_F1AP_PDU *pdu, f1ap_reset_ack_t *ou /* Check presence of mandatory IEs */ F1AP_ResetAcknowledge_t *in = &pdu->choice.successfulOutcome->value.choice.ResetAcknowledge; F1AP_ResetAcknowledgeIEs_t *ie; - F1AP_LIB_FIND_IE(F1AP_ResetAcknowledgeIEs_t, ie, in, F1AP_ProtocolIE_ID_id_TransactionID, true); + F1AP_LIB_FIND_IE(F1AP_ResetAcknowledgeIEs_t, ie, &in->protocolIEs.list, F1AP_ProtocolIE_ID_id_TransactionID, true); /* Loop over all IEs */ for (int i = 0; i < in->protocolIEs.list.count; i++) { @@ -394,11 +394,7 @@ static int read_slice_info(const F1AP_ServedPLMNs_Item_t *plmn, nssai_t *nssai, 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); + nssai[s] = decode_nssai(&sl->sNSSAI); } return ssl->list.count; @@ -418,12 +414,7 @@ static F1AP_ProtocolExtensionContainer_10696P34_t *write_slice_info(int num_ssi, for (int s = 0; s < num_ssi; s++) { asn1cSequenceAdd(slice_support_list->list, F1AP_SliceSupportItem_t, slice); - const nssai_t *n = &nssai[s]; - INT8_TO_OCTET_STRING(n->sst, &slice->sNSSAI.sST); - if (n->sd != 0xffffff) { - asn1cCalloc(slice->sNSSAI.sD, tmp); - INT24_TO_OCTET_STRING(n->sd, tmp); - } + slice->sNSSAI = encode_nssai(&nssai[s]); } return p; @@ -822,9 +813,9 @@ bool decode_f1ap_setup_request(const F1AP_F1AP_PDU_t *pdu, f1ap_setup_req_t *out /* 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); + F1AP_LIB_FIND_IE(F1AP_F1SetupRequestIEs_t, ie, &in->protocolIEs.list, F1AP_ProtocolIE_ID_id_TransactionID, true); + F1AP_LIB_FIND_IE(F1AP_F1SetupRequestIEs_t, ie, &in->protocolIEs.list, F1AP_ProtocolIE_ID_id_gNB_DU_ID, true); + F1AP_LIB_FIND_IE(F1AP_F1SetupRequestIEs_t, ie, &in->protocolIEs.list, 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"); @@ -1095,8 +1086,8 @@ bool decode_f1ap_setup_response(const F1AP_F1AP_PDU_t *pdu, f1ap_setup_resp_t *o /* 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); + F1AP_LIB_FIND_IE(F1AP_F1SetupResponseIEs_t, ie, &in->protocolIEs.list, F1AP_ProtocolIE_ID_id_TransactionID, true); + F1AP_LIB_FIND_IE(F1AP_F1SetupResponseIEs_t, ie, &in->protocolIEs.list, 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]; @@ -1306,8 +1297,8 @@ bool decode_f1ap_setup_failure(const F1AP_F1AP_PDU_t *pdu, f1ap_setup_failure_t 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); + F1AP_LIB_FIND_IE(F1AP_F1SetupFailureIEs_t, ie, &in->protocolIEs.list, F1AP_ProtocolIE_ID_id_TransactionID, true); + F1AP_LIB_FIND_IE(F1AP_F1SetupFailureIEs_t, ie, &in->protocolIEs.list, 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]; @@ -1503,7 +1494,7 @@ bool decode_f1ap_du_configuration_update(const F1AP_F1AP_PDU_t *pdu, f1ap_gnb_du 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); + F1AP_LIB_FIND_IE(F1AP_GNBDUConfigurationUpdateIEs_t, ie, &in->protocolIEs.list, 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"); @@ -1760,7 +1751,7 @@ bool decode_f1ap_cu_configuration_update(const F1AP_F1AP_PDU_t *pdu, f1ap_gnb_cu /* 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); + F1AP_LIB_FIND_IE(F1AP_GNBCUConfigurationUpdateIEs_t, ie, &in->protocolIEs.list, 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]; @@ -1912,7 +1903,7 @@ bool decode_f1ap_cu_configuration_update_acknowledge(const F1AP_F1AP_PDU_t *pdu, 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); + F1AP_LIB_FIND_IE(F1AP_GNBCUConfigurationUpdateAcknowledgeIEs_t, ie, &in->protocolIEs.list, 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]; @@ -2088,7 +2079,7 @@ bool decode_f1ap_du_configuration_update_acknowledge(const F1AP_F1AP_PDU_t *pdu, 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); + F1AP_LIB_FIND_IE(F1AP_GNBDUConfigurationUpdateAcknowledgeIEs_t, ie, &in->protocolIEs.list, 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]; diff --git a/openair2/F1AP/lib/f1ap_lib_common.c b/openair2/F1AP/lib/f1ap_lib_common.c index e32f7e6779..0e1d07a71d 100644 --- a/openair2/F1AP/lib/f1ap_lib_common.c +++ b/openair2/F1AP/lib/f1ap_lib_common.c @@ -25,7 +25,7 @@ #include "OCTET_STRING.h" #include "common/utils/utils.h" #include "common/utils/assertions.h" -#include "common/utils/utils.h" +#include "common/utils/oai_asn1.h" bool eq_f1ap_plmn(const plmn_id_t *a, const plmn_id_t *b) { @@ -115,6 +115,28 @@ uint8_t *cp_octet_string(const OCTET_STRING_t *os, int *len) return buf; } +F1AP_SNSSAI_t encode_nssai(const nssai_t *nssai) +{ + F1AP_SNSSAI_t enc = {0}; + INT8_TO_OCTET_STRING(nssai->sst, &enc.sST); + // see 23.003 sec. 28.4.2: 0xffffff means "no SD" + if (nssai->sd != 0xffffff) { + asn1cCalloc(enc.sD, tmp); + INT24_TO_OCTET_STRING(nssai->sd, tmp); + } + return enc; +} + +nssai_t decode_nssai(const F1AP_SNSSAI_t *nssai) +{ + // see 23.003 sec. 28.4.2: 0xffffff means "no SD" + nssai_t dec = { .sd = 0xffffff, }; + OCTET_STRING_TO_INT8(&nssai->sST, dec.sst); + if (nssai->sD != NULL) + OCTET_STRING_TO_INT24(nssai->sD, dec.sd); + return dec; +} + F1AP_Cause_t encode_f1ap_cause(f1ap_Cause_t cause, long cause_value) { F1AP_Cause_t f1_cause = {0}; diff --git a/openair2/F1AP/lib/f1ap_lib_common.h b/openair2/F1AP/lib/f1ap_lib_common.h index 8a3ddfba4a..b49fad88c1 100644 --- a/openair2/F1AP/lib/f1ap_lib_common.h +++ b/openair2/F1AP/lib/f1ap_lib_common.h @@ -27,40 +27,51 @@ #include #include "openair3/UTILS/conversions.h" #include "common/5g_platform_types.h" +#include "common/utils/ds/byte_array.h" #include "F1AP_Cause.h" +#include "F1AP_SNSSAI.h" #include "f1ap_messages_types.h" #ifdef ENABLE_TESTS - #define PRINT_ERROR(...) fprintf(stderr, ##__VA_ARGS__) + #define PRINT_ERROR(fmt, ...) fprintf(stderr, "%s:%d: " fmt, __FILE__, __LINE__, ##__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; \ - } \ +#define _F1_EQ_CHECK_GENERIC(condition, fmt, ...) \ + do { \ + if (!(condition)) { \ + PRINT_ERROR("Equality condition '%s' failed: " fmt " != " fmt "\n", #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); +#define _F1_CHECK_EXP(EXP) \ + do { \ + if (!(EXP)) { \ + PRINT_ERROR("Failed at " #EXP "\n"); \ + return false; \ + } \ + } while (0) + +#define _F1_EQ_CHECK_OPTIONAL_IE(A, B, FIELD, EQ_MACRO) \ + do { \ + _F1_CHECK_EXP(((A)->FIELD && (B)->FIELD) || (!(A)->FIELD && !(B)->FIELD)); \ + if ((A)->FIELD && (B)->FIELD) \ + EQ_MACRO(*(A)->FIELD, *(B)->FIELD); \ + } while (0) + /* 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) \ +#define F1AP_LIB_FIND_IE(IE_TYPE, ie, IE_LIST, IE_ID, mandatory) \ do { \ ie = NULL; \ - for (IE_TYPE **ptr = container->protocolIEs.list.array; \ - ptr < &container->protocolIEs.list.array[container->protocolIEs.list.count]; \ - ptr++) { \ + for (IE_TYPE **ptr = (IE_LIST)->array; ptr < &(IE_LIST)->array[(IE_LIST)->count]; ptr++) { \ if ((*ptr)->id == IE_ID) { \ ie = *ptr; \ break; \ @@ -72,6 +83,29 @@ } \ } while (0) +#define CP_OPT_BYTE_ARRAY(dst, src) \ + do { \ + if (src) { \ + dst = calloc_or_fail(1, sizeof(*dst)); \ + *(dst) = copy_byte_array(*(src)); \ + } \ + } while (0) + +#define FREE_OPT_BYTE_ARRAY(a) \ + do { \ + if (a) { \ + free_byte_array(*(a)); \ + } \ + free(a); \ + } while (0) + +/* similar to asn1cCallocOne(), duplicated to not confuse with asn.1 types */ +#define _F1_MALLOC(VaR, VaLue) \ + do { \ + VaR = malloc_or_fail(sizeof(*VaR)); \ + *VaR = VaLue; \ + } while (0) + bool eq_f1ap_plmn(const plmn_id_t *a, const plmn_id_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); @@ -85,6 +119,9 @@ bool eq_f1ap_tx_bandwidth(const struct f1ap_transmission_bandwidth_t *a, const s struct OCTET_STRING; uint8_t *cp_octet_string(const struct OCTET_STRING *os, int *len); +F1AP_SNSSAI_t encode_nssai(const nssai_t *nssai); +nssai_t decode_nssai(const F1AP_SNSSAI_t *nssai); + F1AP_Cause_t encode_f1ap_cause(f1ap_Cause_t cause, long cause_value); bool decode_f1ap_cause(F1AP_Cause_t f1_cause, f1ap_Cause_t *cause, long *cause_value); diff --git a/openair2/F1AP/lib/f1ap_lib_extern.h b/openair2/F1AP/lib/f1ap_lib_extern.h deleted file mode 100644 index f95b685540..0000000000 --- a/openair2/F1AP/lib/f1ap_lib_extern.h +++ /dev/null @@ -1,27 +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 - */ - -#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/lib/f1ap_lib_includes.h b/openair2/F1AP/lib/f1ap_lib_includes.h index 267e7243e7..3f039bf6f0 100644 --- a/openair2/F1AP/lib/f1ap_lib_includes.h +++ b/openair2/F1AP/lib/f1ap_lib_includes.h @@ -41,5 +41,11 @@ #include "F1AP_SibtypetobeupdatedListItem.h" #include "F1AP_UnsuccessfulOutcome.h" #include "F1AP_UE-associatedLogicalF1-ConnectionListRes.h" +#include "F1AP_ULUPTNLInformation-ToBeSetup-Item.h" +#include "F1AP_GTPTunnel.h" +#include "F1AP_Flows-Mapped-To-DRB-Item.h" +#include "F1AP_NonDynamic5QIDescriptor.h" +#include "F1AP_Dynamic5QIDescriptor.h" +#include "F1AP_DLUPTNLInformation-ToBeSetup-Item.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 index 5fc9e2d622..c2f6e780aa 100644 --- a/openair2/F1AP/lib/f1ap_rrc_message_transfer.c +++ b/openair2/F1AP/lib/f1ap_rrc_message_transfer.c @@ -114,26 +114,27 @@ bool decode_initial_ul_rrc_message_transfer(const F1AP_F1AP_PDU_t *pdu, f1ap_ini memset(out, 0, sizeof(*out)); F1AP_InitialULRRCMessageTransfer_t *container = &pdu->choice.initiatingMessage->value.choice.InitialULRRCMessageTransfer; + F1AP_ProtocolIE_Container_10659P31_t *pIEs = &container->protocolIEs; F1AP_InitialULRRCMessageTransferIEs_t *ie; - F1AP_LIB_FIND_IE(F1AP_InitialULRRCMessageTransferIEs_t, ie, container, F1AP_ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID, true); + F1AP_LIB_FIND_IE(F1AP_InitialULRRCMessageTransferIEs_t, ie, &pIEs->list, 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); + F1AP_LIB_FIND_IE(F1AP_InitialULRRCMessageTransferIEs_t, ie, &pIEs->list, 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); + F1AP_LIB_FIND_IE(F1AP_InitialULRRCMessageTransferIEs_t, ie, &pIEs->list, 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); + F1AP_LIB_FIND_IE(F1AP_InitialULRRCMessageTransferIEs_t, ie, &pIEs->list, 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); + F1AP_LIB_FIND_IE(F1AP_InitialULRRCMessageTransferIEs_t, ie, &pIEs->list, 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); + F1AP_LIB_FIND_IE(F1AP_InitialULRRCMessageTransferIEs_t, ie, &pIEs->list, F1AP_ProtocolIE_ID_id_TransactionID, true); out->transaction_id = ie->value.choice.TransactionID; return true; @@ -258,19 +259,20 @@ bool decode_ul_rrc_message_transfer(const F1AP_F1AP_PDU_t *pdu, f1ap_ul_rrc_mess DevAssert(pdu != NULL); F1AP_ULRRCMessageTransfer_t *container = &pdu->choice.initiatingMessage->value.choice.ULRRCMessageTransfer; + F1AP_ProtocolIE_Container_10659P33_t *pIEs = &container->protocolIEs; 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); + F1AP_LIB_FIND_IE(F1AP_ULRRCMessageTransferIEs_t, ie, &pIEs->list, 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); + F1AP_LIB_FIND_IE(F1AP_ULRRCMessageTransferIEs_t, ie, &pIEs->list, 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); + F1AP_LIB_FIND_IE(F1AP_ULRRCMessageTransferIEs_t, ie, &pIEs->list, 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); + F1AP_LIB_FIND_IE(F1AP_ULRRCMessageTransferIEs_t, ie, &pIEs->list, F1AP_ProtocolIE_ID_id_RRCContainer, true); out->rrc_container = cp_octet_string(&ie->value.choice.RRCContainer, &out->rrc_container_length); return true; @@ -392,30 +394,31 @@ bool decode_dl_rrc_message_transfer(const F1AP_F1AP_PDU_t *pdu, f1ap_dl_rrc_mess DevAssert(pdu != NULL); F1AP_DLRRCMessageTransfer_t *container = &pdu->choice.initiatingMessage->value.choice.DLRRCMessageTransfer; + F1AP_ProtocolIE_Container_10659P32_t *pIEs = &container->protocolIEs; 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); + F1AP_LIB_FIND_IE(F1AP_DLRRCMessageTransferIEs_t, ie, &pIEs->list, 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); + F1AP_LIB_FIND_IE(F1AP_DLRRCMessageTransferIEs_t, ie, &pIEs->list, 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); + F1AP_LIB_FIND_IE(F1AP_DLRRCMessageTransferIEs_t, ie, &pIEs->list, 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); + F1AP_LIB_FIND_IE(F1AP_DLRRCMessageTransferIEs_t, ie, &pIEs->list, 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); + F1AP_LIB_FIND_IE(F1AP_DLRRCMessageTransferIEs_t, ie, &pIEs->list, 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); + F1AP_LIB_FIND_IE(F1AP_DLRRCMessageTransferIEs_t, ie, &pIEs->list, F1AP_ProtocolIE_ID_id_RRCContainer, true); out->rrc_container = cp_octet_string(&ie->value.choice.RRCContainer, &out->rrc_container_length); return true; diff --git a/openair2/F1AP/lib/f1ap_ue_context.c b/openair2/F1AP/lib/f1ap_ue_context.c new file mode 100644 index 0000000000..a1b5531c2b --- /dev/null +++ b/openair2/F1AP/lib/f1ap_ue_context.c @@ -0,0 +1,2468 @@ +/* + * 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_ue_context.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" +#include "common/utils/ds/byte_array.h" + +static F1AP_CUtoDURRCInformation_t encode_cu_to_du_rrc_info(const f1ap_cu_to_du_rrc_info_t *cu2du) +{ + F1AP_CUtoDURRCInformation_t enc = {0}; + + /* optional: cG_ConfigInfo */ + if (cu2du->cg_configinfo) { + asn1cCalloc(enc.cG_ConfigInfo, cG_ConfigInfo); + const byte_array_t *ba = cu2du->cg_configinfo; + OCTET_STRING_fromBuf(cG_ConfigInfo, (const char *)ba->buf, ba->len); + } + + /* optional: uE_CapabilityRAT_ContainerList */ + if (cu2du->ue_cap) { + asn1cCalloc(enc.uE_CapabilityRAT_ContainerList, uE_CapabilityRAT_ContainerList); + const byte_array_t *ba = cu2du->ue_cap; + OCTET_STRING_fromBuf(uE_CapabilityRAT_ContainerList, (const char *)ba->buf, ba->len); + } + + /* optional: measConfig */ + if (cu2du->meas_config) { + asn1cCalloc(enc.measConfig, measConfig); + const byte_array_t *ba = cu2du->meas_config; + OCTET_STRING_fromBuf(measConfig, (const char *)ba->buf, ba->len); + } + + /* optional: HandoverPreparationInformation */ + if (cu2du->ho_prep_info) { + F1AP_ProtocolExtensionContainer_10696P60_t *p = calloc_or_fail(1, sizeof(*p)); + enc.iE_Extensions = (struct F1AP_ProtocolExtensionContainer *)p; + asn1cSequenceAdd(p->list, F1AP_CUtoDURRCInformation_ExtIEs_t, ie_ext); + ie_ext->id = F1AP_ProtocolIE_ID_id_HandoverPreparationInformation; + ie_ext->criticality = F1AP_Criticality_ignore; + ie_ext->extensionValue.present = F1AP_CUtoDURRCInformation_ExtIEs__extensionValue_PR_HandoverPreparationInformation; + const byte_array_t *ba = cu2du->ho_prep_info; + F1AP_HandoverPreparationInformation_t *hpi = &ie_ext->extensionValue.choice.HandoverPreparationInformation; + OCTET_STRING_fromBuf(hpi, (const char *)ba->buf, ba->len); + } + return enc; +} + +static bool decode_cu_to_du_rrc_info(f1ap_cu_to_du_rrc_info_t *dec, const F1AP_CUtoDURRCInformation_t *cu2du) +{ + if (cu2du->cG_ConfigInfo) { + dec->cg_configinfo = calloc_or_fail(1, sizeof(*dec->cg_configinfo)); + const F1AP_CG_ConfigInfo_t *cgci = cu2du->cG_ConfigInfo; + *dec->cg_configinfo = create_byte_array(cgci->size, (uint8_t*)cgci->buf); + } + if (cu2du->uE_CapabilityRAT_ContainerList) { + dec->ue_cap = calloc_or_fail(1, sizeof(*dec->ue_cap)); + const F1AP_UE_CapabilityRAT_ContainerList_t *l = cu2du->uE_CapabilityRAT_ContainerList; + *dec->ue_cap = create_byte_array(l->size, (uint8_t*)l->buf); + } + if (cu2du->measConfig) { + dec->meas_config = calloc_or_fail(1, sizeof(*dec->meas_config)); + const F1AP_MeasConfig_t *mc = cu2du->measConfig; + *dec->meas_config = create_byte_array(mc->size, (uint8_t*)mc->buf); + } + if (cu2du->iE_Extensions) { + const F1AP_ProtocolExtensionContainer_10696P60_t *ext = (const F1AP_ProtocolExtensionContainer_10696P60_t *)cu2du->iE_Extensions; + for (int i = 0; i < ext->list.count; ++i) { + const F1AP_CUtoDURRCInformation_ExtIEs_t *cu2du_info_ext = ext->list.array[i]; + switch (cu2du_info_ext->id) { + case F1AP_ProtocolIE_ID_id_HandoverPreparationInformation: + dec->ho_prep_info = calloc_or_fail(1, sizeof(*dec->ho_prep_info)); + const F1AP_HandoverPreparationInformation_t *hopi = &cu2du_info_ext->extensionValue.choice.HandoverPreparationInformation; + *dec->ho_prep_info = create_byte_array(hopi->size, (uint8_t*) hopi->buf); + break; + default: + PRINT_ERROR("received unsupported F1AP CUtoDURRCInfo extension container %ld\n", cu2du_info_ext->id); + } + } + } + return true; +} + +static f1ap_cu_to_du_rrc_info_t cp_cu_to_du_rrc_info(const f1ap_cu_to_du_rrc_info_t *src) +{ + f1ap_cu_to_du_rrc_info_t dst = {0}; + CP_OPT_BYTE_ARRAY(dst.cg_configinfo, src->cg_configinfo); + CP_OPT_BYTE_ARRAY(dst.ue_cap, src->ue_cap); + CP_OPT_BYTE_ARRAY(dst.meas_config, src->meas_config); + CP_OPT_BYTE_ARRAY(dst.ho_prep_info, src->ho_prep_info); + return dst; +} + +static bool eq_ba(const byte_array_t a, const byte_array_t b) +{ + return eq_byte_array(&a, &b); +} + +static bool eq_cu_to_du_rrc_info(const f1ap_cu_to_du_rrc_info_t *a, const f1ap_cu_to_du_rrc_info_t *b) +{ + _F1_EQ_CHECK_OPTIONAL_IE(a, b, cg_configinfo, eq_ba); + _F1_EQ_CHECK_OPTIONAL_IE(a, b, ue_cap, eq_ba); + _F1_EQ_CHECK_OPTIONAL_IE(a, b, meas_config, eq_ba); + _F1_EQ_CHECK_OPTIONAL_IE(a, b, ho_prep_info, eq_ba); + return true; +} + +static void free_cu_to_du_rrc_info(f1ap_cu_to_du_rrc_info_t *cu2du) +{ + FREE_OPT_BYTE_ARRAY(cu2du->cg_configinfo); + FREE_OPT_BYTE_ARRAY(cu2du->ue_cap); + FREE_OPT_BYTE_ARRAY(cu2du->meas_config); + FREE_OPT_BYTE_ARRAY(cu2du->ho_prep_info); +} + +static F1AP_DUtoCURRCInformation_t encode_du_to_cu_rrc_info(const f1ap_du_to_cu_rrc_info_t *du2cu) +{ + F1AP_DUtoCURRCInformation_t enc = {0}; + + /* mandatory: cellGroupConfig */ + const byte_array_t *ba = &du2cu->cell_group_config; + OCTET_STRING_fromBuf(&enc.cellGroupConfig, (const char *)ba->buf, ba->len); + + /* optional: MeasGapConfig */ + if (du2cu->meas_gap_config) { + ba = du2cu->meas_gap_config; + asn1cCalloc(enc.measGapConfig, measGapConfig); + OCTET_STRING_fromBuf(measGapConfig, (const char *)ba->buf, ba->len); + } + + return enc; +} + +static bool decode_du_to_cu_rrc_info(f1ap_du_to_cu_rrc_info_t *dec, const F1AP_DUtoCURRCInformation_t *du2cu) +{ + const F1AP_CellGroupConfig_t *cgc = &du2cu->cellGroupConfig; + dec->cell_group_config = create_byte_array(cgc->size, (uint8_t *)cgc->buf); + + if (du2cu->measGapConfig) { + const F1AP_MeasGapConfig_t *mgc = du2cu->measGapConfig; + dec->meas_gap_config = calloc_or_fail(1, sizeof(*dec->meas_gap_config)); + *dec->meas_gap_config = create_byte_array(mgc->size, (uint8_t *)mgc->buf); + } + return true; +} + +static f1ap_du_to_cu_rrc_info_t cp_du_to_cu_rrc_info(const f1ap_du_to_cu_rrc_info_t *src) +{ + f1ap_du_to_cu_rrc_info_t cp = {0}; + cp.cell_group_config = copy_byte_array(src->cell_group_config); + CP_OPT_BYTE_ARRAY(cp.meas_gap_config, src->meas_gap_config); + return cp; +} + +static bool eq_du_to_cu_rrc_info(const f1ap_du_to_cu_rrc_info_t *a, const f1ap_du_to_cu_rrc_info_t *b) +{ + _F1_CHECK_EXP(eq_byte_array(&a->cell_group_config, &b->cell_group_config)); + _F1_EQ_CHECK_OPTIONAL_IE(a, b, meas_gap_config, eq_ba); + return true; +} + +static void free_du_to_cu_rrc_info(f1ap_du_to_cu_rrc_info_t *du2cu) +{ + free_byte_array(du2cu->cell_group_config); + FREE_OPT_BYTE_ARRAY(du2cu->meas_gap_config); +} + +/* \brief Encode SRB-ToBeSetup List, for UE Context Setup Request, from + * f1ap_srb_to_setup_t. */ +static F1AP_SRBs_ToBeSetup_List_t encode_srbs_to_setup(int n, const f1ap_srb_to_setup_t *srbs) +{ + F1AP_SRBs_ToBeSetup_List_t list = {0}; + for (int i = 0; i < n; ++i) { + asn1cSequenceAdd(list, F1AP_SRBs_ToBeSetup_ItemIEs_t, itie); + itie->id = F1AP_ProtocolIE_ID_id_SRBs_ToBeSetup_Item; + itie->criticality = F1AP_Criticality_reject; + itie->value.present = F1AP_SRBs_ToBeSetup_ItemIEs__value_PR_SRBs_ToBeSetup_Item; + itie->value.choice.SRBs_ToBeSetup_Item.sRBID = srbs[i].id; + } + return list; +} + +/* \brief Encode SRB-ToBeSetupMod List, for UE context Modification Request, + * from f1ap_srb_to_setup_t. The ToBeSetup/ToBeSetupMod lists are basically the + * same in both cases, but the asn1c types are different. */ +static F1AP_SRBs_ToBeSetupMod_List_t encode_srbs_to_setupmod(int n, const f1ap_srb_to_setup_t *srbs) +{ + F1AP_SRBs_ToBeSetupMod_List_t list = {0}; + for (int i = 0; i < n; ++i) { + asn1cSequenceAdd(list, F1AP_SRBs_ToBeSetupMod_ItemIEs_t, itie); + itie->id = F1AP_ProtocolIE_ID_id_SRBs_ToBeSetupMod_Item; + itie->criticality = F1AP_Criticality_reject; + itie->value.present = F1AP_SRBs_ToBeSetupMod_ItemIEs__value_PR_SRBs_ToBeSetupMod_Item; + itie->value.choice.SRBs_ToBeSetupMod_Item.sRBID = srbs[i].id; + } + return list; +} + +/* \brief Decode SRB-ToBeSetup List, from UE Context Setup Request, into + * f1ap_srb_to_setup_t. */ +static bool decode_srbs_to_setup(const F1AP_SRBs_ToBeSetup_List_t *f1ap, int *n, f1ap_srb_to_setup_t **out) +{ + DevAssert(out != NULL); + *out = NULL; + int count = *n = f1ap->list.count; + if (count == 0) + return true; + + f1ap_srb_to_setup_t *srbs = *out = calloc_or_fail(count, sizeof(*srbs)); + for (int i = 0; i < count; ++i) { + const F1AP_SRBs_ToBeSetup_ItemIEs_t *itie = (F1AP_SRBs_ToBeSetup_ItemIEs_t *)f1ap->list.array[i]; + _F1_EQ_CHECK_LONG(itie->id, F1AP_ProtocolIE_ID_id_SRBs_ToBeSetup_Item); + _F1_EQ_CHECK_INT(itie->value.present, F1AP_SRBs_ToBeSetup_ItemIEs__value_PR_SRBs_ToBeSetup_Item); + srbs[i].id = itie->value.choice.SRBs_ToBeSetup_Item.sRBID; + } + + return true; +} + +/* \brief Decode SRB-ToBeSetupMod List, from UE Context Modification Request, + * into f1ap_srb_to_setup_t. The ToBeSetup/ToBeSetupMod lists are basically the + * same, but the asn1c types are different. */ +static bool decode_srbs_to_setupmod(const F1AP_SRBs_ToBeSetupMod_List_t *f1ap, int *n, f1ap_srb_to_setup_t **out) +{ + DevAssert(out != NULL); + *out = NULL; + int count = *n = f1ap->list.count; + if (count == 0) + return true; + + f1ap_srb_to_setup_t *srbs = *out = calloc_or_fail(count, sizeof(*srbs)); + for (int i = 0; i < count; ++i) { + const F1AP_SRBs_ToBeSetupMod_ItemIEs_t *itie = (F1AP_SRBs_ToBeSetupMod_ItemIEs_t *)f1ap->list.array[i]; + _F1_EQ_CHECK_LONG(itie->id, F1AP_ProtocolIE_ID_id_SRBs_ToBeSetupMod_Item); + _F1_EQ_CHECK_INT(itie->value.present, F1AP_SRBs_ToBeSetupMod_ItemIEs__value_PR_SRBs_ToBeSetupMod_Item); + srbs[i].id = itie->value.choice.SRBs_ToBeSetupMod_Item.sRBID; + } + + return true; +} + +static f1ap_srb_to_setup_t cp_srb_to_setup(const f1ap_srb_to_setup_t *orig) +{ + f1ap_srb_to_setup_t cp = { + .id = orig->id, + }; + return cp; +} + +static bool eq_srb_to_setup(const f1ap_srb_to_setup_t *a, const f1ap_srb_to_setup_t *b) +{ + _F1_EQ_CHECK_INT(a->id, b->id); + return true; +} + +static void free_srb_to_setup(f1ap_srb_to_setup_t *srbs) +{ + // nothing to free +} + +static F1AP_SRBs_Setup_List_t encode_srbs_setup(int n, const f1ap_srb_setup_t *srbs) +{ + F1AP_SRBs_Setup_List_t list = {0}; + for (int i = 0; i < n; ++i) { + asn1cSequenceAdd(list, F1AP_SRBs_Setup_ItemIEs_t, itie); + itie->id = F1AP_ProtocolIE_ID_id_SRBs_Setup_Item; + itie->criticality = F1AP_Criticality_ignore; + itie->value.present = F1AP_SRBs_Setup_ItemIEs__value_PR_SRBs_Setup_Item; + F1AP_SRBs_Setup_Item_t *it = &itie->value.choice.SRBs_Setup_Item; + it->sRBID = srbs[i].id; + it->lCID = srbs[i].lcid; + } + return list; +} + +static F1AP_SRBs_SetupMod_List_t encode_srbs_setupmod(int n, const f1ap_srb_setup_t *srbs) +{ + F1AP_SRBs_SetupMod_List_t list = {0}; + for (int i = 0; i < n; ++i) { + asn1cSequenceAdd(list, F1AP_SRBs_SetupMod_ItemIEs_t, itie); + itie->id = F1AP_ProtocolIE_ID_id_SRBs_SetupMod_Item; + itie->criticality = F1AP_Criticality_ignore; + itie->value.present = F1AP_SRBs_SetupMod_ItemIEs__value_PR_SRBs_SetupMod_Item; + F1AP_SRBs_SetupMod_Item_t *it = &itie->value.choice.SRBs_SetupMod_Item; + it->sRBID = srbs[i].id; + it->lCID = srbs[i].lcid; + } + return list; +} + +static bool decode_srbs_setup(const F1AP_SRBs_Setup_List_t *f1ap, int *n, f1ap_srb_setup_t **out) +{ + DevAssert(out != NULL); + *out = NULL; + int count = *n = f1ap->list.count; + if (count == 0) + return true; + + f1ap_srb_setup_t *srbs = *out = calloc_or_fail(count, sizeof(*srbs)); + for (int i = 0; i < count; ++i) { + const F1AP_SRBs_Setup_ItemIEs_t *itie = (F1AP_SRBs_Setup_ItemIEs_t *)f1ap->list.array[i]; + _F1_EQ_CHECK_LONG(itie->id, F1AP_ProtocolIE_ID_id_SRBs_Setup_Item); + _F1_EQ_CHECK_INT(itie->value.present, F1AP_SRBs_Setup_ItemIEs__value_PR_SRBs_Setup_Item); + const F1AP_SRBs_Setup_Item_t *it = &itie->value.choice.SRBs_Setup_Item; + srbs[i].id = it->sRBID; + srbs[i].lcid = it->lCID; + } + return true; +} + +static bool decode_srbs_setupmod(const F1AP_SRBs_SetupMod_List_t *f1ap, int *n, f1ap_srb_setup_t **out) +{ + DevAssert(out != NULL); + *out = NULL; + int count = *n = f1ap->list.count; + if (count == 0) + return true; + + f1ap_srb_setup_t *srbs = *out = calloc_or_fail(count, sizeof(*srbs)); + for (int i = 0; i < count; ++i) { + const F1AP_SRBs_SetupMod_ItemIEs_t *itie = (F1AP_SRBs_SetupMod_ItemIEs_t *)f1ap->list.array[i]; + _F1_EQ_CHECK_LONG(itie->id, F1AP_ProtocolIE_ID_id_SRBs_SetupMod_Item); + _F1_EQ_CHECK_INT(itie->value.present, F1AP_SRBs_SetupMod_ItemIEs__value_PR_SRBs_SetupMod_Item); + const F1AP_SRBs_SetupMod_Item_t *it = &itie->value.choice.SRBs_SetupMod_Item; + srbs[i].id = it->sRBID; + srbs[i].lcid = it->lCID; + } + return true; +} + +static f1ap_srb_setup_t cp_srb_setup(const f1ap_srb_setup_t *orig) +{ + f1ap_srb_setup_t cp = {.id = orig->id, .lcid = orig->lcid}; + return cp; +} + +static bool eq_srb_setup(const f1ap_srb_setup_t *a, const f1ap_srb_setup_t *b) +{ + _F1_EQ_CHECK_INT(a->id, b->id); + _F1_EQ_CHECK_INT(a->lcid, b->lcid); + return true; +} + +static void free_srb_setup(f1ap_srb_setup_t *srbs) +{ + // nothing to free +} + +static F1AP_QoSFlowLevelQoSParameters_t encode_qos_flow_param(const f1ap_qos_flow_param_t *p) +{ + F1AP_QoSFlowLevelQoSParameters_t f1ap = {0}; + + if (p->qos_type == NON_DYNAMIC) { + f1ap.qoS_Characteristics.present = F1AP_QoS_Characteristics_PR_non_Dynamic_5QI; + asn1cCalloc(f1ap.qoS_Characteristics.choice.non_Dynamic_5QI, nd); + nd->fiveQI = p->nondyn.fiveQI; + } else { + DevAssert(p->qos_type == DYNAMIC); + f1ap.qoS_Characteristics.present = F1AP_QoS_Characteristics_PR_dynamic_5QI; + asn1cCalloc(f1ap.qoS_Characteristics.choice.dynamic_5QI, d); + + d->qoSPriorityLevel = p->dyn.prio; + d->packetDelayBudget = p->dyn.pdb; + d->packetErrorRate.pER_Scalar = p->dyn.per.scalar; + d->packetErrorRate.pER_Exponent = p->dyn.per.exponent; + + if (p->dyn.delay_critical) { + e_F1AP_Dynamic5QIDescriptor__delayCritical v = *p->dyn.delay_critical + ? F1AP_Dynamic5QIDescriptor__delayCritical_delay_critical + : F1AP_Dynamic5QIDescriptor__delayCritical_non_delay_critical; + asn1cCallocOne(d->delayCritical, v); + } + + if (p->dyn.avg_win) + asn1cCallocOne(d->averagingWindow, *p->dyn.avg_win); + } + + F1AP_NGRANAllocationAndRetentionPriority_t *arp = &f1ap.nGRANallocationRetentionPriority; + arp->priorityLevel = p->arp.prio; + arp->pre_emptionCapability = p->arp.preempt_cap; + arp->pre_emptionVulnerability = p->arp.preempt_vuln; + return f1ap; +} + +static bool decode_qos_flow_param(const F1AP_QoSFlowLevelQoSParameters_t *f1ap, f1ap_qos_flow_param_t *out) +{ + if (f1ap->qoS_Characteristics.present == F1AP_QoS_Characteristics_PR_non_Dynamic_5QI) { + out->qos_type = NON_DYNAMIC; + const F1AP_NonDynamic5QIDescriptor_t *nondyn = f1ap->qoS_Characteristics.choice.non_Dynamic_5QI; + out->nondyn.fiveQI = nondyn->fiveQI; + } else { + _F1_EQ_CHECK_INT(f1ap->qoS_Characteristics.present, F1AP_QoS_Characteristics_PR_dynamic_5QI); + const F1AP_Dynamic5QIDescriptor_t *d = f1ap->qoS_Characteristics.choice.dynamic_5QI; + out->qos_type = DYNAMIC; + out->dyn.prio = d->qoSPriorityLevel; + out->dyn.pdb = d->packetDelayBudget; + out->dyn.per.scalar = d->packetErrorRate.pER_Scalar; + out->dyn.per.exponent = d->packetErrorRate.pER_Exponent; + + if (d->delayCritical) { + bool v = *d->delayCritical == F1AP_Dynamic5QIDescriptor__delayCritical_delay_critical; + _F1_MALLOC(out->dyn.delay_critical, v); + } + + if (d->averagingWindow) + _F1_MALLOC(out->dyn.avg_win, *d->averagingWindow); + } + + const F1AP_NGRANAllocationAndRetentionPriority_t *arp = &f1ap->nGRANallocationRetentionPriority; + out->arp.prio = arp->priorityLevel; + out->arp.preempt_cap = arp->pre_emptionCapability; + out->arp.preempt_vuln = arp->pre_emptionVulnerability; + return true; +} + +static f1ap_qos_flow_param_t cp_qos_flow_param(const f1ap_qos_flow_param_t *orig) +{ + f1ap_qos_flow_param_t cp = { + .qos_type = orig->qos_type, + // dyn/nondyn below + .arp = orig->arp, + }; + if (cp.qos_type == NON_DYNAMIC) { + cp.nondyn.fiveQI = orig->nondyn.fiveQI; + } else { + DevAssert(cp.qos_type == DYNAMIC); + f1ap_dynamic_5qi_t *cpdyn = &cp.dyn; + const f1ap_dynamic_5qi_t *odyn = &orig->dyn; + cpdyn->prio = odyn->prio; + cpdyn->pdb = odyn->pdb; + cpdyn->per.scalar = odyn->per.scalar; + cpdyn->per.exponent = odyn->per.exponent; + if (odyn->delay_critical) + _F1_MALLOC(cpdyn->delay_critical, *odyn->delay_critical); + if (odyn->avg_win) + _F1_MALLOC(cpdyn->avg_win, *odyn->avg_win); + } + return cp; +} + +static bool eq_qos_flow_param(const f1ap_qos_flow_param_t *a, const f1ap_qos_flow_param_t *b) +{ + _F1_EQ_CHECK_INT(a->qos_type, b->qos_type); + if (a->qos_type == NON_DYNAMIC) { + _F1_EQ_CHECK_INT(a->nondyn.fiveQI, b->nondyn.fiveQI); + } else { + DevAssert(a->qos_type == DYNAMIC); + DevAssert(b->qos_type == DYNAMIC); + const f1ap_dynamic_5qi_t *adyn = &a->dyn, *bdyn = &b->dyn; + _F1_EQ_CHECK_INT(adyn->prio, bdyn->prio); + _F1_EQ_CHECK_INT(adyn->pdb, bdyn->pdb); + _F1_EQ_CHECK_INT(adyn->per.scalar, bdyn->per.scalar); + _F1_EQ_CHECK_INT(adyn->per.exponent, bdyn->per.exponent); + _F1_EQ_CHECK_OPTIONAL_IE(adyn, bdyn, delay_critical, _F1_EQ_CHECK_INT); + _F1_EQ_CHECK_OPTIONAL_IE(adyn, bdyn, avg_win, _F1_EQ_CHECK_INT); + } + _F1_EQ_CHECK_INT(a->arp.prio, b->arp.prio); + _F1_EQ_CHECK_INT(a->arp.preempt_cap, b->arp.preempt_cap); + _F1_EQ_CHECK_INT(a->arp.preempt_vuln, b->arp.preempt_vuln); + return true; +} + +static void free_qos_flow_param(f1ap_qos_flow_param_t *p) +{ + if (p->qos_type == NON_DYNAMIC) { + // nothing to free + } else { + DevAssert(p->qos_type == DYNAMIC); + free(p->dyn.delay_critical); + free(p->dyn.avg_win); + } + // arp: nothing to free +} + +static F1AP_DRB_Information_t encode_drb_info_nr(const f1ap_drb_info_nr_t *drb) +{ + F1AP_DRB_Information_t f1ap = {0}; + + f1ap.dRB_QoS = encode_qos_flow_param(&drb->drb_qos); + f1ap.sNSSAI = encode_nssai(&drb->nssai); + + for (int i = 0; i < drb->flows_len; ++i) { + asn1cSequenceAdd(f1ap.flows_Mapped_To_DRB_List.list, F1AP_Flows_Mapped_To_DRB_Item_t, it); + it->qoSFlowIdentifier = drb->flows[i].qfi; + it->qoSFlowLevelQoSParameters = encode_qos_flow_param(&drb->flows[i].param); + } + + return f1ap; +} + +static bool decode_drb_info_nr(const F1AP_DRB_Information_t *f1ap, f1ap_drb_info_nr_t *out) +{ + _F1_CHECK_EXP(decode_qos_flow_param(&f1ap->dRB_QoS, &out->drb_qos)); + out->nssai = decode_nssai(&f1ap->sNSSAI); + out->flows_len = f1ap->flows_Mapped_To_DRB_List.list.count; + out->flows = calloc_or_fail(out->flows_len, sizeof(*out->flows)); + for (int i = 0; i < out->flows_len; ++i) { + const F1AP_Flows_Mapped_To_DRB_Item_t *it = f1ap->flows_Mapped_To_DRB_List.list.array[i]; + out->flows[i].qfi = it->qoSFlowIdentifier; + _F1_CHECK_EXP(decode_qos_flow_param(&it->qoSFlowLevelQoSParameters, &out->flows[i].param)); + } + return true; +} + +static f1ap_drb_info_nr_t cp_drb_info_nr(const f1ap_drb_info_nr_t *orig) +{ + f1ap_drb_info_nr_t cp = { + .drb_qos = cp_qos_flow_param(&orig->drb_qos), + .nssai = orig->nssai, + .flows_len = orig->flows_len, + // flows below + }; + cp.flows = calloc_or_fail(cp.flows_len, sizeof(*cp.flows)); + for (int i = 0; i < cp.flows_len; ++i) { + cp.flows[i].qfi = orig->flows[i].qfi; + cp.flows[i].param = cp_qos_flow_param(&orig->flows[i].param); + } + return cp; +} + +static bool eq_drb_info_nr(const f1ap_drb_info_nr_t *a, const f1ap_drb_info_nr_t *b) +{ + _F1_CHECK_EXP(eq_qos_flow_param(&a->drb_qos, &b->drb_qos)); + _F1_EQ_CHECK_INT(a->nssai.sst, b->nssai.sst); + _F1_EQ_CHECK_INT(a->nssai.sd, b->nssai.sd); + _F1_EQ_CHECK_INT(a->flows_len, b->flows_len); + for (int i = 0; i < a->flows_len; ++i) { + _F1_EQ_CHECK_INT(a->flows[i].qfi, b->flows[i].qfi); + _F1_CHECK_EXP(eq_qos_flow_param(&a->flows[i].param, &b->flows[i].param)); + } + return true; +} + +static void free_drb_info_nr(f1ap_drb_info_nr_t *p) +{ + free_qos_flow_param(&p->drb_qos); + // nssai: nothing + for (int i = 0; i < p->flows_len; ++i) + free_qos_flow_param(&p->flows[i].param); + free(p->flows); +} + +static F1AP_RLCMode_t rlc_mode_to_asn1(f1ap_rlc_mode_t mode) +{ + switch (mode) { + case F1AP_RLC_MODE_AM: + return F1AP_RLCMode_rlc_am; + case F1AP_RLC_MODE_UM_BIDIR: + return F1AP_RLCMode_rlc_um_bidirectional; + default: + break; + } + AssertFatal(false, "unsupported RLC Mode %d received\n", mode); + return F1AP_RLCMode_rlc_am; // won't be reached +} + +static bool rlc_mode_from_asn1(F1AP_RLCMode_t mode, f1ap_rlc_mode_t *out) +{ + switch (mode) { + case F1AP_RLCMode_rlc_am: + *out = F1AP_RLC_MODE_AM; + return true; + case F1AP_RLCMode_rlc_um_bidirectional: + *out = F1AP_RLC_MODE_UM_BIDIR; + return true; + default: + PRINT_ERROR("unsupported RLC Mode %ld received: setting AM\n", mode); + break; + } + return false; +} + +static F1AP_UPTransportLayerInformation_t encode_up_tnl(const f1ap_up_tnl_t *tnl) +{ + F1AP_UPTransportLayerInformation_t tnl_info = { .present = F1AP_UPTransportLayerInformation_PR_gTPTunnel, }; + asn1cCalloc(tnl_info.choice.gTPTunnel, gtp_tnl); + TRANSPORT_LAYER_ADDRESS_IPv4_TO_BIT_STRING(tnl->tl_address, >p_tnl->transportLayerAddress); + INT32_TO_OCTET_STRING(tnl->teid, >p_tnl->gTP_TEID); + return tnl_info; +} + +static bool decode_up_tnl(const F1AP_UPTransportLayerInformation_t *tnl_info, f1ap_up_tnl_t *out) +{ + _F1_EQ_CHECK_INT(tnl_info->present, F1AP_UPTransportLayerInformation_PR_gTPTunnel); + const F1AP_GTPTunnel_t *gtp_tnl = tnl_info->choice.gTPTunnel; + BIT_STRING_TO_TRANSPORT_LAYER_ADDRESS_IPv4(>p_tnl->transportLayerAddress, out->tl_address); + OCTET_STRING_TO_UINT32(>p_tnl->gTP_TEID, out->teid); + return true; +} + +static f1ap_up_tnl_t cp_up_tnl(const f1ap_up_tnl_t *orig) +{ + f1ap_up_tnl_t cp = { .teid = orig->teid, }; + memcpy(&cp.tl_address, &orig->tl_address, sizeof(orig->tl_address)); + return cp; +} + +static bool eq_up_tnl(const f1ap_up_tnl_t *a, const f1ap_up_tnl_t *b) +{ + if (memcmp(&a->tl_address, &b->tl_address, sizeof(a->tl_address)) != 0) { + PRINT_ERROR("tl_address mismatch\n"); + return false; + } + _F1_EQ_CHECK_INT(a->teid, b->teid); + return true; +} + +static void free_up_tnl(const f1ap_up_tnl_t *tnl) +{ + // nothing to free +} + +/* Encode a DRBs_ToSetup list for UE Context Setup Request, from f1ap_drb_to_setup_t. */ +static F1AP_DRBs_ToBeSetup_List_t encode_drbs_to_setup(int n, const f1ap_drb_to_setup_t *drbs) +{ + F1AP_DRBs_ToBeSetup_List_t list = {0}; + for (int i = 0; i < n; ++i) { + const f1ap_drb_to_setup_t *drb = &drbs[i]; + asn1cSequenceAdd(list, F1AP_DRBs_ToBeSetup_ItemIEs_t, itie); + itie->id = F1AP_ProtocolIE_ID_id_DRBs_ToBeSetup_Item; + itie->criticality = F1AP_Criticality_reject; + itie->value.present = F1AP_DRBs_ToBeSetup_ItemIEs__value_PR_DRBs_ToBeSetup_Item; + + F1AP_DRBs_ToBeSetup_Item_t *it = &itie->value.choice.DRBs_ToBeSetup_Item; + it->dRBID = drb->id; + AssertFatal(drb->qos_choice == F1AP_QOS_CHOICE_NR, "only NR QoS choice implemented\n"); + it->qoSInformation.present = F1AP_QoSInformation_PR_choice_extension; + F1AP_QoSInformation_ExtIEs_t *qos_ext_ie = calloc_or_fail(1, sizeof(*qos_ext_ie)); + it->qoSInformation.choice.choice_extension = (struct F1AP_ProtocolIE_SingleContainer *)qos_ext_ie; + qos_ext_ie->id = F1AP_ProtocolIE_ID_id_DRB_Information; + qos_ext_ie->criticality = F1AP_Criticality_reject; + qos_ext_ie->value.present = F1AP_QoSInformation_ExtIEs__value_PR_DRB_Information; + qos_ext_ie->value.choice.DRB_Information = encode_drb_info_nr(&drb->nr); + + /* 12.1.3 uLUPTNLInformation_ToBeSetup_List */ + for (int j = 0; j < drb->up_ul_tnl_len; j++) { + DevAssert(drb->up_ul_tnl[j].teid > 0); + asn1cSequenceAdd(it->uLUPTNLInformation_ToBeSetup_List.list, F1AP_ULUPTNLInformation_ToBeSetup_Item_t, tnl_it); + tnl_it->uLUPTNLInformation = encode_up_tnl(&drb->up_ul_tnl[j]); + } + + it->rLCMode = rlc_mode_to_asn1(drb->rlc_mode); + + F1AP_ProtocolExtensionContainer_10696P82_t *ext = calloc_or_fail(1, sizeof(*ext)); + it->iE_Extensions = (struct F1AP_ProtocolExtensionContainer *)ext; + asn1cSequenceAdd(ext->list, F1AP_DRBs_ToBeSetup_ItemExtIEs_t, ext_ie); + ext_ie->id = F1AP_ProtocolIE_ID_id_DLPDCPSNLength; + ext_ie->criticality = F1AP_Criticality_ignore; + ext_ie->extensionValue.present = F1AP_DRBs_ToBeSetup_ItemExtIEs__extensionValue_PR_PDCPSNLength; + AssertFatal(drb->dl_pdcp_sn_len != NULL, "dl_pdcp_sn_len required for setup\n"); + ext_ie->extensionValue.choice.PDCPSNLength = *drb->dl_pdcp_sn_len; + + if (drb->ul_pdcp_sn_len) { + asn1cSequenceAdd(ext->list, F1AP_DRBs_ToBeSetup_ItemExtIEs_t, ext_ie); + ext_ie->id = F1AP_ProtocolIE_ID_id_ULPDCPSNLength; + ext_ie->criticality = F1AP_Criticality_ignore; + ext_ie->extensionValue.present = F1AP_DRBs_ToBeSetup_ItemExtIEs__extensionValue_PR_PDCPSNLength_1; + ext_ie->extensionValue.choice.PDCPSNLength_1 = *drb->ul_pdcp_sn_len; + } + } + return list; +} + +/* Encode a DRBs_ToBeSetupMod list for UE Context Modification Request, from + * f1ap_drb_to_setup_t. The ToBeSetup/ToBeSetupMod lists are almost the same + * (with the exception that one field is optional in the latter), so that we + * can reuse the internal types, but the asn1c types are different. */ +static F1AP_DRBs_ToBeSetupMod_List_t encode_drbs_to_setupmod(int n, const f1ap_drb_to_setup_t *drbs) +{ + F1AP_DRBs_ToBeSetupMod_List_t list = {0}; + for (int i = 0; i < n; ++i) { + const f1ap_drb_to_setup_t *drb = &drbs[i]; + asn1cSequenceAdd(list, F1AP_DRBs_ToBeSetupMod_ItemIEs_t, itie); + itie->id = F1AP_ProtocolIE_ID_id_DRBs_ToBeSetupMod_Item; + itie->criticality = F1AP_Criticality_reject; + itie->value.present = F1AP_DRBs_ToBeSetupMod_ItemIEs__value_PR_DRBs_ToBeSetupMod_Item; + + F1AP_DRBs_ToBeSetupMod_Item_t *it = &itie->value.choice.DRBs_ToBeSetupMod_Item; + it->dRBID = drb->id; + AssertFatal(drb->qos_choice == F1AP_QOS_CHOICE_NR, "only NR QoS choice implemented\n"); + it->qoSInformation.present = F1AP_QoSInformation_PR_choice_extension; + F1AP_QoSInformation_ExtIEs_t *qos_ext_ie = calloc_or_fail(1, sizeof(*qos_ext_ie)); + it->qoSInformation.choice.choice_extension = (struct F1AP_ProtocolIE_SingleContainer *)qos_ext_ie; + qos_ext_ie->id = F1AP_ProtocolIE_ID_id_DRB_Information; + qos_ext_ie->criticality = F1AP_Criticality_reject; + qos_ext_ie->value.present = F1AP_QoSInformation_ExtIEs__value_PR_DRB_Information; + qos_ext_ie->value.choice.DRB_Information = encode_drb_info_nr(&drb->nr); + + /* 12.1.3 uLUPTNLInformation_ToBeSetupMod_List */ + for (int j = 0; j < drb->up_ul_tnl_len; j++) { + DevAssert(drb->up_ul_tnl[j].teid > 0); + asn1cSequenceAdd(it->uLUPTNLInformation_ToBeSetup_List.list, F1AP_ULUPTNLInformation_ToBeSetup_Item_t, tnl_it); + tnl_it->uLUPTNLInformation = encode_up_tnl(&drb->up_ul_tnl[j]); + } + + it->rLCMode = rlc_mode_to_asn1(drb->rlc_mode); + + if (!drb->dl_pdcp_sn_len && !drb->ul_pdcp_sn_len) + continue; + + F1AP_ProtocolExtensionContainer_10696P83_t *ext = calloc_or_fail(1, sizeof(*ext)); + it->iE_Extensions = (struct F1AP_ProtocolExtensionContainer *)ext; + if (drb->dl_pdcp_sn_len) { + asn1cSequenceAdd(ext->list, F1AP_DRBs_ToBeSetupMod_ItemExtIEs_t, ext_ie); + ext_ie->id = F1AP_ProtocolIE_ID_id_DLPDCPSNLength; + ext_ie->criticality = F1AP_Criticality_ignore; + ext_ie->extensionValue.present = F1AP_DRBs_ToBeSetupMod_ItemExtIEs__extensionValue_PR_PDCPSNLength; + ext_ie->extensionValue.choice.PDCPSNLength = *drb->dl_pdcp_sn_len; + } + + if (drb->ul_pdcp_sn_len) { + asn1cSequenceAdd(ext->list, F1AP_DRBs_ToBeSetupMod_ItemExtIEs_t, ext_ie); + ext_ie->id = F1AP_ProtocolIE_ID_id_ULPDCPSNLength; + ext_ie->criticality = F1AP_Criticality_ignore; + ext_ie->extensionValue.present = F1AP_DRBs_ToBeSetupMod_ItemExtIEs__extensionValue_PR_PDCPSNLength_1; + ext_ie->extensionValue.choice.PDCPSNLength_1 = *drb->ul_pdcp_sn_len; + } + } + return list; +} + +/* \brief Decode DRBS-ToBeSetup list from UE Context Setup request, into + * f1ap_drb_to_setup_t. */ +static bool decode_drbs_to_setup(const F1AP_DRBs_ToBeSetup_List_t *f1ap, int *n, f1ap_drb_to_setup_t **out) +{ + DevAssert(out != NULL); + *out = NULL; + int count = *n = f1ap->list.count; + if (count == 0) + return true; + + f1ap_drb_to_setup_t *drbs = *out = calloc_or_fail(count, sizeof(*drbs)); + for (int i = 0; i < count; ++i) { + const F1AP_DRBs_ToBeSetup_ItemIEs_t *itie = (const F1AP_DRBs_ToBeSetup_ItemIEs_t *)f1ap->list.array[i]; + _F1_EQ_CHECK_LONG(itie->id, F1AP_ProtocolIE_ID_id_DRBs_ToBeSetup_Item); + _F1_EQ_CHECK_INT(itie->value.present, F1AP_DRBs_ToBeSetup_ItemIEs__value_PR_DRBs_ToBeSetup_Item); + const F1AP_DRBs_ToBeSetup_Item_t *it = &itie->value.choice.DRBs_ToBeSetup_Item; + + f1ap_drb_to_setup_t *drb = &drbs[i]; + drb->id = it->dRBID; + + _F1_EQ_CHECK_INT(it->qoSInformation.present, F1AP_QoSInformation_PR_choice_extension); + const F1AP_QoSInformation_ExtIEs_t *qos_ext = (F1AP_QoSInformation_ExtIEs_t *)it->qoSInformation.choice.choice_extension; + _F1_EQ_CHECK_LONG(qos_ext->id, F1AP_ProtocolIE_ID_id_DRB_Information); + _F1_EQ_CHECK_INT(qos_ext->value.present, F1AP_QoSInformation_ExtIEs__value_PR_DRB_Information); + drb->qos_choice = F1AP_QOS_CHOICE_NR; + _F1_CHECK_EXP(decode_drb_info_nr(&qos_ext->value.choice.DRB_Information, &drb->nr)); + + drb->up_ul_tnl_len = it->uLUPTNLInformation_ToBeSetup_List.list.count; + _F1_EQ_CHECK_GENERIC(drb->up_ul_tnl_len > 0 && drb->up_ul_tnl_len <= 2, "%d", drb->up_ul_tnl_len, 1); + for (int j = 0; j < drb->up_ul_tnl_len; ++j) { + const F1AP_ULUPTNLInformation_ToBeSetup_Item_t *it_tnl = it->uLUPTNLInformation_ToBeSetup_List.list.array[j]; + _F1_CHECK_EXP(decode_up_tnl(&it_tnl->uLUPTNLInformation, &drb->up_ul_tnl[j])); + } + + _F1_CHECK_EXP(rlc_mode_from_asn1(it->rLCMode, &drb->rlc_mode)); + + _F1_CHECK_EXP(it->iE_Extensions); // PDCP SN length is under extension, is mandatory + const F1AP_ProtocolExtensionContainer_10696P82_t *ext = (const F1AP_ProtocolExtensionContainer_10696P82_t *)it->iE_Extensions; + const F1AP_DRBs_ToBeSetup_ItemExtIEs_t *ie; + F1AP_LIB_FIND_IE(F1AP_DRBs_ToBeSetup_ItemExtIEs_t, ie, &ext->list, F1AP_ProtocolIE_ID_id_DLPDCPSNLength, true); + + for (int j = 0; j < ext->list.count; ++j) { + ie = ext->list.array[j]; + AssertError(ie != NULL, return false, "ext->list.array[j] is NULL"); + switch (ie->id) { + case F1AP_ProtocolIE_ID_id_DLPDCPSNLength: + _F1_EQ_CHECK_INT(ie->extensionValue.present, F1AP_DRBs_ToBeSetup_ItemExtIEs__extensionValue_PR_PDCPSNLength); + _F1_MALLOC(drb->dl_pdcp_sn_len, ie->extensionValue.choice.PDCPSNLength); + break; + case F1AP_ProtocolIE_ID_id_ULPDCPSNLength: + _F1_EQ_CHECK_INT(ie->extensionValue.present, F1AP_DRBs_ToBeSetup_ItemExtIEs__extensionValue_PR_PDCPSNLength_1); + _F1_MALLOC(drb->ul_pdcp_sn_len, ie->extensionValue.choice.PDCPSNLength_1); + break; + default: + PRINT_ERROR("F1AP_ProtocolIE_ID_id %ld unknown, skipping\n", ie->id); + break; + } + } + } + + return true; +} + +/* \brief Decode DRBS-ToBeSetupMod list from UE Context Modification Request, into + * f1ap_drb_to_setup_t. The ToBeSetup/ToBeSetupMod lists are almost the same + * (except for some optional types in the latter), so we reuse the internal + * representation, but the asn1c types are different. */ +static bool decode_drbs_to_setupmod(const F1AP_DRBs_ToBeSetupMod_List_t *f1ap, int *n, f1ap_drb_to_setup_t **out) +{ + DevAssert(out != NULL); + *out = NULL; + int count = *n = f1ap->list.count; + if (count == 0) + return true; + + f1ap_drb_to_setup_t *drbs = *out = calloc_or_fail(count, sizeof(*drbs)); + for (int i = 0; i < count; ++i) { + const F1AP_DRBs_ToBeSetupMod_ItemIEs_t *itie = (const F1AP_DRBs_ToBeSetupMod_ItemIEs_t *)f1ap->list.array[i]; + _F1_EQ_CHECK_LONG(itie->id, F1AP_ProtocolIE_ID_id_DRBs_ToBeSetupMod_Item); + _F1_EQ_CHECK_INT(itie->value.present, F1AP_DRBs_ToBeSetupMod_ItemIEs__value_PR_DRBs_ToBeSetupMod_Item); + const F1AP_DRBs_ToBeSetupMod_Item_t *it = &itie->value.choice.DRBs_ToBeSetupMod_Item; + + f1ap_drb_to_setup_t *drb = &drbs[i]; + drb->id = it->dRBID; + + _F1_EQ_CHECK_INT(it->qoSInformation.present, F1AP_QoSInformation_PR_choice_extension); + const F1AP_QoSInformation_ExtIEs_t *qos_ext = (F1AP_QoSInformation_ExtIEs_t *)it->qoSInformation.choice.choice_extension; + _F1_EQ_CHECK_LONG(qos_ext->id, F1AP_ProtocolIE_ID_id_DRB_Information); + _F1_EQ_CHECK_INT(qos_ext->value.present, F1AP_QoSInformation_ExtIEs__value_PR_DRB_Information); + drb->qos_choice = F1AP_QOS_CHOICE_NR; + _F1_CHECK_EXP(decode_drb_info_nr(&qos_ext->value.choice.DRB_Information, &drb->nr)); + + drb->up_ul_tnl_len = it->uLUPTNLInformation_ToBeSetup_List.list.count; + _F1_EQ_CHECK_GENERIC(drb->up_ul_tnl_len > 0 && drb->up_ul_tnl_len <= 2, "%d", drb->up_ul_tnl_len, 1); + for (int j = 0; j < drb->up_ul_tnl_len; ++j) { + const F1AP_ULUPTNLInformation_ToBeSetup_Item_t *it_tnl = it->uLUPTNLInformation_ToBeSetup_List.list.array[j]; + _F1_CHECK_EXP(decode_up_tnl(&it_tnl->uLUPTNLInformation, &drb->up_ul_tnl[j])); + } + + _F1_CHECK_EXP(rlc_mode_from_asn1(it->rLCMode, &drb->rlc_mode)); + + if (!it->iE_Extensions) + continue; + const F1AP_ProtocolExtensionContainer_10696P83_t *ext = (const F1AP_ProtocolExtensionContainer_10696P83_t *)it->iE_Extensions; + const F1AP_DRBs_ToBeSetupMod_ItemExtIEs_t *ie; + + for (int j = 0; j < ext->list.count; ++j) { + ie = ext->list.array[j]; + AssertError(ie != NULL, return false, "ext->list.array[j] is NULL"); + switch (ie->id) { + case F1AP_ProtocolIE_ID_id_DLPDCPSNLength: + _F1_EQ_CHECK_INT(ie->extensionValue.present, F1AP_DRBs_ToBeSetupMod_ItemExtIEs__extensionValue_PR_PDCPSNLength); + _F1_MALLOC(drb->dl_pdcp_sn_len, ie->extensionValue.choice.PDCPSNLength); + break; + case F1AP_ProtocolIE_ID_id_ULPDCPSNLength: + _F1_EQ_CHECK_INT(ie->extensionValue.present, F1AP_DRBs_ToBeSetupMod_ItemExtIEs__extensionValue_PR_PDCPSNLength_1); + _F1_MALLOC(drb->ul_pdcp_sn_len, ie->extensionValue.choice.PDCPSNLength_1); + break; + default: + PRINT_ERROR("F1AP_ProtocolIE_ID_id %ld unknown, skipping\n", ie->id); + break; + } + } + } + + return true; +} + +static f1ap_drb_to_setup_t cp_drb_to_setup(const f1ap_drb_to_setup_t *orig) +{ + f1ap_drb_to_setup_t cp = { + .id = orig->id, + .qos_choice = orig->qos_choice, + // nr below + .up_ul_tnl_len = orig->up_ul_tnl_len, + .up_ul_tnl[0] = cp_up_tnl(&orig->up_ul_tnl[0]), + .up_ul_tnl[1] = cp_up_tnl(&orig->up_ul_tnl[1]), + .rlc_mode = orig->rlc_mode, + // dl_pdcp_sn_len below + // ul_pdcp_sn_len below + }; + AssertFatal(cp.qos_choice == F1AP_QOS_CHOICE_NR, "only NR QoS choice implemented\n"); + if (orig->qos_choice == F1AP_QOS_CHOICE_NR) + cp.nr = cp_drb_info_nr(&orig->nr); + if (orig->dl_pdcp_sn_len) { + _F1_MALLOC(cp.dl_pdcp_sn_len, *orig->dl_pdcp_sn_len); + } + if (orig->ul_pdcp_sn_len) { + _F1_MALLOC(cp.ul_pdcp_sn_len, *orig->ul_pdcp_sn_len); + } + return cp; +} + +static bool eq_drb_to_setup(const f1ap_drb_to_setup_t *a, const f1ap_drb_to_setup_t *b) +{ + _F1_EQ_CHECK_INT(a->id, b->id); + _F1_EQ_CHECK_INT(a->qos_choice, b->qos_choice); + AssertFatal(a->qos_choice == F1AP_QOS_CHOICE_NR, "only NR QoS choice implemented\n"); + if (a->qos_choice == F1AP_QOS_CHOICE_NR) + eq_drb_info_nr(&a->nr, &b->nr); + _F1_EQ_CHECK_INT(a->up_ul_tnl_len, b->up_ul_tnl_len); + for (int i = 0; i < a->up_ul_tnl_len; ++i) { + _F1_CHECK_EXP(eq_up_tnl(&a->up_ul_tnl[i], &b->up_ul_tnl[i])); + } + _F1_EQ_CHECK_INT(a->rlc_mode, b->rlc_mode); + _F1_EQ_CHECK_OPTIONAL_IE(a, b, dl_pdcp_sn_len, _F1_EQ_CHECK_INT); + _F1_EQ_CHECK_OPTIONAL_IE(a, b, ul_pdcp_sn_len, _F1_EQ_CHECK_INT); + return true; +} + +static void free_drb_to_setup(f1ap_drb_to_setup_t *drb) +{ + if (drb->qos_choice == F1AP_QOS_CHOICE_NR) + free_drb_info_nr(&drb->nr); + for (int i = 0; i < drb->up_ul_tnl_len; ++i) + free_up_tnl(&drb->up_ul_tnl[i]); + free(drb->dl_pdcp_sn_len); + free(drb->ul_pdcp_sn_len); +} + +static F1AP_DRBs_Setup_List_t encode_drbs_setup(int n, const f1ap_drb_setup_t *drbs) +{ + F1AP_DRBs_Setup_List_t list = {0}; + for (int i = 0; i < n; ++i) { + const f1ap_drb_setup_t *drb = &drbs[i]; + asn1cSequenceAdd(list, F1AP_DRBs_Setup_ItemIEs_t, itie); + itie->id = F1AP_ProtocolIE_ID_id_DRBs_Setup_Item; + itie->criticality = F1AP_Criticality_ignore; + itie->value.present = F1AP_DRBs_Setup_ItemIEs__value_PR_DRBs_Setup_Item; + + F1AP_DRBs_Setup_Item_t *it = &itie->value.choice.DRBs_Setup_Item; + it->dRBID = drb->id; + if (drb->lcid) + asn1cCallocOne(it->lCID, *drb->lcid); + for (int j = 0; j < drb->up_dl_tnl_len; ++j) { + DevAssert(drb->up_dl_tnl[j].teid > 0); + asn1cSequenceAdd(it->dLUPTNLInformation_ToBeSetup_List.list, F1AP_DLUPTNLInformation_ToBeSetup_Item_t, tnl_it); + tnl_it->dLUPTNLInformation = encode_up_tnl(&drb->up_dl_tnl[j]); + } + } + return list; +} + +static F1AP_DRBs_SetupMod_List_t encode_drbs_setupmod(int n, const f1ap_drb_setup_t *drbs) +{ + F1AP_DRBs_SetupMod_List_t list = {0}; + for (int i = 0; i < n; ++i) { + const f1ap_drb_setup_t *drb = &drbs[i]; + asn1cSequenceAdd(list, F1AP_DRBs_SetupMod_ItemIEs_t, itie); + itie->id = F1AP_ProtocolIE_ID_id_DRBs_SetupMod_Item; + itie->criticality = F1AP_Criticality_ignore; + itie->value.present = F1AP_DRBs_SetupMod_ItemIEs__value_PR_DRBs_SetupMod_Item; + + F1AP_DRBs_SetupMod_Item_t *it = &itie->value.choice.DRBs_SetupMod_Item; + it->dRBID = drb->id; + if (drb->lcid) + asn1cCallocOne(it->lCID, *drb->lcid); + for (int j = 0; j < drb->up_dl_tnl_len; ++j) { + DevAssert(drb->up_dl_tnl[j].teid > 0); + asn1cSequenceAdd(it->dLUPTNLInformation_ToBeSetup_List.list, F1AP_DLUPTNLInformation_ToBeSetup_Item_t, tnl_it); + tnl_it->dLUPTNLInformation = encode_up_tnl(&drb->up_dl_tnl[j]); + } + } + return list; +} + +static bool decode_drbs_setup(const F1AP_DRBs_Setup_List_t *f1ap, int *n, f1ap_drb_setup_t **out) +{ + DevAssert(out != NULL); + *out = NULL; + int count = *n = f1ap->list.count; + if (count == 0) + return true; + + f1ap_drb_setup_t *drbs = *out = calloc_or_fail(count, sizeof(*drbs)); + for (int i = 0; i < count; ++i) { + const F1AP_DRBs_Setup_ItemIEs_t *itie = (const F1AP_DRBs_Setup_ItemIEs_t *)f1ap->list.array[i]; + _F1_EQ_CHECK_LONG(itie->id, F1AP_ProtocolIE_ID_id_DRBs_Setup_Item); + _F1_EQ_CHECK_INT(itie->value.present, F1AP_DRBs_Setup_ItemIEs__value_PR_DRBs_Setup_Item); + const F1AP_DRBs_Setup_Item_t *it = &itie->value.choice.DRBs_Setup_Item; + + f1ap_drb_setup_t *drb = &drbs[i]; + drb->id = it->dRBID; + if (it->lCID) + _F1_MALLOC(drb->lcid, *it->lCID); + + drb->up_dl_tnl_len = it->dLUPTNLInformation_ToBeSetup_List.list.count; + _F1_EQ_CHECK_GENERIC(drb->up_dl_tnl_len > 0 && drb->up_dl_tnl_len <= 2, "%d", drb->up_dl_tnl_len, 1); + for (int j = 0; j < drb->up_dl_tnl_len; ++j) { + F1AP_DLUPTNLInformation_ToBeSetup_Item_t *it_tnl = it->dLUPTNLInformation_ToBeSetup_List.list.array[j]; + _F1_CHECK_EXP(decode_up_tnl(&it_tnl->dLUPTNLInformation, &drb->up_dl_tnl[j])); + } + } + + return true; +} + +static bool decode_drbs_setupmod(const F1AP_DRBs_SetupMod_List_t *f1ap, int *n, f1ap_drb_setup_t **out) +{ + DevAssert(out != NULL); + *out = NULL; + int count = *n = f1ap->list.count; + if (count == 0) + return true; + + f1ap_drb_setup_t *drbs = *out = calloc_or_fail(count, sizeof(*drbs)); + for (int i = 0; i < count; ++i) { + const F1AP_DRBs_SetupMod_ItemIEs_t *itie = (const F1AP_DRBs_SetupMod_ItemIEs_t *)f1ap->list.array[i]; + _F1_EQ_CHECK_LONG(itie->id, F1AP_ProtocolIE_ID_id_DRBs_SetupMod_Item); + _F1_EQ_CHECK_INT(itie->value.present, F1AP_DRBs_SetupMod_ItemIEs__value_PR_DRBs_SetupMod_Item); + const F1AP_DRBs_SetupMod_Item_t *it = &itie->value.choice.DRBs_SetupMod_Item; + + f1ap_drb_setup_t *drb = &drbs[i]; + drb->id = it->dRBID; + if (it->lCID) + _F1_MALLOC(drb->lcid, *it->lCID); + + drb->up_dl_tnl_len = it->dLUPTNLInformation_ToBeSetup_List.list.count; + _F1_EQ_CHECK_GENERIC(drb->up_dl_tnl_len > 0 && drb->up_dl_tnl_len <= 2, "%d", drb->up_dl_tnl_len, 1); + for (int j = 0; j < drb->up_dl_tnl_len; ++j) { + F1AP_DLUPTNLInformation_ToBeSetup_Item_t *it_tnl = it->dLUPTNLInformation_ToBeSetup_List.list.array[j]; + _F1_CHECK_EXP(decode_up_tnl(&it_tnl->dLUPTNLInformation, &drb->up_dl_tnl[j])); + } + } + + return true; +} + +static f1ap_drb_setup_t cp_drb_setup(const f1ap_drb_setup_t *orig) +{ + f1ap_drb_setup_t cp = { + .id = orig->id, + .up_dl_tnl_len = orig->up_dl_tnl_len, + .up_dl_tnl[0] = cp_up_tnl(&orig->up_dl_tnl[0]), + .up_dl_tnl[1] = cp_up_tnl(&orig->up_dl_tnl[1]), + }; + if (orig->lcid) + _F1_MALLOC(cp.lcid, *orig->lcid); + return cp; +} + +static bool eq_drb_setup(const f1ap_drb_setup_t *a, const f1ap_drb_setup_t *b) +{ + _F1_EQ_CHECK_INT(a->id, b->id); + _F1_EQ_CHECK_OPTIONAL_IE(a, b, lcid, _F1_EQ_CHECK_INT); + _F1_EQ_CHECK_INT(a->up_dl_tnl_len, b->up_dl_tnl_len); + for (int i = 0; i < a->up_dl_tnl_len; ++i) + _F1_CHECK_EXP(eq_up_tnl(&a->up_dl_tnl[i], &b->up_dl_tnl[i])); + return true; +} + +static void free_drb_setup(f1ap_drb_setup_t *drb) +{ + free(drb->lcid); +} + +static F1AP_DRBs_ToBeReleased_List_t encode_drbs_to_release(int n, const f1ap_drb_to_release_t *drbs) +{ + F1AP_DRBs_ToBeReleased_List_t list = {0}; + for (int i = 0; i < n; i++) { + asn1cSequenceAdd(list, F1AP_DRBs_ToBeReleased_ItemIEs_t, itie); + itie->id = F1AP_ProtocolIE_ID_id_DRBs_ToBeReleased_Item; + itie->criticality = F1AP_Criticality_reject; + itie->value.present = F1AP_DRBs_ToBeReleased_ItemIEs__value_PR_DRBs_ToBeReleased_Item; + itie->value.choice.DRBs_ToBeReleased_Item.dRBID = drbs[i].id; + } + return list; +} + +static bool decode_drbs_to_release(const F1AP_DRBs_ToBeReleased_List_t *f1ap, int *n, f1ap_drb_to_release_t **out) +{ + DevAssert(out != NULL); + *out = NULL; + int count = *n = f1ap->list.count; + if (count == 0) + return true; + + f1ap_drb_to_release_t *drbs = *out = calloc_or_fail(count, sizeof(*drbs)); + for (int i = 0; i < count; ++i) { + const F1AP_DRBs_ToBeReleased_ItemIEs_t *itie = (F1AP_DRBs_ToBeReleased_ItemIEs_t *)f1ap->list.array[i]; + _F1_EQ_CHECK_LONG(itie->id, F1AP_ProtocolIE_ID_id_DRBs_ToBeReleased_Item); + _F1_EQ_CHECK_INT(itie->value.present, F1AP_DRBs_ToBeReleased_ItemIEs__value_PR_DRBs_ToBeReleased_Item); + drbs[i].id = itie->value.choice.DRBs_ToBeReleased_Item.dRBID; + } + + return true; +} + +static f1ap_drb_to_release_t cp_drb_to_release(const f1ap_drb_to_release_t *orig) +{ + f1ap_drb_to_release_t cp = { + .id = orig->id, + }; + return cp; +} + +static bool eq_drb_to_release(const f1ap_drb_to_release_t *a, const f1ap_drb_to_release_t *b) +{ + _F1_EQ_CHECK_INT(a->id, b->id); + return true; +} + +static void free_drb_to_release(f1ap_drb_to_release_t *drb) +{ + // nothing to free +} + +/** + * @brief Encode F1 UE context setup request to ASN.1 + */ +F1AP_F1AP_PDU_t *encode_ue_context_setup_req(const f1ap_ue_context_setup_req_t *req) +{ + F1AP_F1AP_PDU_t *pdu = calloc_or_fail(1, sizeof(*pdu)); + + /* Message Type */ + pdu->present = F1AP_F1AP_PDU_PR_initiatingMessage; + asn1cCalloc(pdu->choice.initiatingMessage, tmp); + tmp->procedureCode = F1AP_ProcedureCode_id_UEContextSetup; + tmp->criticality = F1AP_Criticality_reject; + tmp->value.present = F1AP_InitiatingMessage__value_PR_UEContextSetupRequest; + F1AP_UEContextSetupRequest_t *out = &tmp->value.choice.UEContextSetupRequest; + + /* mandatory: GNB_CU_UE_F1AP_ID */ + asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextSetupRequestIEs_t, ie1); + ie1->id = F1AP_ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID; + ie1->criticality = F1AP_Criticality_reject; + ie1->value.present = F1AP_UEContextSetupRequestIEs__value_PR_GNB_CU_UE_F1AP_ID; + ie1->value.choice.GNB_CU_UE_F1AP_ID = req->gNB_CU_ue_id; + + /* optional: GNB_DU_UE_F1AP_ID */ + if (req->gNB_DU_ue_id) { + asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextSetupRequestIEs_t, ie); + ie->id = F1AP_ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID; + ie->criticality = F1AP_Criticality_ignore; + ie->value.present = F1AP_UEContextSetupRequestIEs__value_PR_GNB_DU_UE_F1AP_ID; + ie->value.choice.GNB_DU_UE_F1AP_ID = *req->gNB_DU_ue_id; + } + + /* mandatory: SpCell ID/NRCGI */ + asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextSetupRequestIEs_t, ie3); + ie3->id = F1AP_ProtocolIE_ID_id_SpCell_ID; + ie3->criticality = F1AP_Criticality_reject; + ie3->value.present = F1AP_UEContextSetupRequestIEs__value_PR_NRCGI; + F1AP_NRCGI_t *nrcgi = &ie3->value.choice.NRCGI; + const plmn_id_t *plmn = &req->plmn; + MCC_MNC_TO_PLMNID(plmn->mcc,plmn->mnc,plmn->mnc_digit_length, &nrcgi->pLMN_Identity); + NR_CELL_ID_TO_BIT_STRING(req->nr_cellid, &nrcgi->nRCellIdentity); + + /* mandatory: ServCellIndox */ + asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextSetupRequestIEs_t, ie4); + ie4->id = F1AP_ProtocolIE_ID_id_ServCellIndex; + ie4->criticality = F1AP_Criticality_reject; + ie4->value.present = F1AP_UEContextSetupRequestIEs__value_PR_ServCellIndex; + ie4->value.choice.ServCellIndex = req->servCellIndex; + + /* mandatory: CUtoDURRCInformation */ + asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextSetupRequestIEs_t, ie6); + ie6->id = F1AP_ProtocolIE_ID_id_CUtoDURRCInformation; + ie6->criticality = F1AP_Criticality_reject; + ie6->value.present = F1AP_UEContextSetupRequestIEs__value_PR_CUtoDURRCInformation; + ie6->value.choice.CUtoDURRCInformation = encode_cu_to_du_rrc_info(&req->cu_to_du_rrc_info); + + /* optional: SRB to be setup list */ + if (req->srbs_len > 0) { + asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextSetupRequestIEs_t, ie); + ie->id = F1AP_ProtocolIE_ID_id_SRBs_ToBeSetup_List; + ie->criticality = F1AP_Criticality_reject; + ie->value.present = F1AP_UEContextSetupRequestIEs__value_PR_SRBs_ToBeSetup_List; + ie->value.choice.SRBs_ToBeSetup_List = encode_srbs_to_setup(req->srbs_len, req->srbs); + } + + /* optional: DRB to be setup list */ + if (req->drbs_len > 0) { + asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextSetupRequestIEs_t, ie); + ie->id = F1AP_ProtocolIE_ID_id_DRBs_ToBeSetup_List; + ie->criticality = F1AP_Criticality_reject; + ie->value.present = F1AP_UEContextSetupRequestIEs__value_PR_DRBs_ToBeSetup_List; + ie->value.choice.DRBs_ToBeSetup_List = encode_drbs_to_setup(req->drbs_len, req->drbs); + } + + /* optional: RRC container */ + if (req->rrc_container) { + asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextSetupRequestIEs_t, ie); + ie->id = F1AP_ProtocolIE_ID_id_RRCContainer; + ie->criticality = F1AP_Criticality_ignore; + ie->value.present = F1AP_UEContextSetupRequestIEs__value_PR_RRCContainer; + OCTET_STRING_fromBuf(&ie->value.choice.RRCContainer, (const char *)req->rrc_container->buf, req->rrc_container->len); + } + + /* conditional if DRB setup list: gNB-DU UE Aggregate Maximum Bit Rate Uplink */ + if (req->gnb_du_ue_agg_mbr_ul) { + asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextSetupRequestIEs_t, ie); + ie->id = F1AP_ProtocolIE_ID_id_GNB_DU_UE_AMBR_UL; + ie->criticality = F1AP_Criticality_ignore; + ie->value.present = F1AP_UEContextSetupRequestIEs__value_PR_BitRate; + asn_long2INTEGER(&ie->value.choice.BitRate, *req->gnb_du_ue_agg_mbr_ul); + } + + return pdu; +} + +/** + * @brief Decode F1 UE Context Setup Request + */ +bool decode_ue_context_setup_req(const F1AP_F1AP_PDU_t *pdu, f1ap_ue_context_setup_req_t *out) +{ + DevAssert(out != NULL); + memset(out, 0, sizeof(*out)); + + F1AP_UEContextSetupRequest_t *in = &pdu->choice.initiatingMessage->value.choice.UEContextSetupRequest; + F1AP_UEContextSetupRequestIEs_t *ie; + + F1AP_LIB_FIND_IE(F1AP_UEContextSetupRequestIEs_t, ie, &in->protocolIEs.list, F1AP_ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID, true); + F1AP_LIB_FIND_IE(F1AP_UEContextSetupRequestIEs_t, ie, &in->protocolIEs.list, F1AP_ProtocolIE_ID_id_SpCell_ID, true); + F1AP_LIB_FIND_IE(F1AP_UEContextSetupRequestIEs_t, ie, &in->protocolIEs.list, F1AP_ProtocolIE_ID_id_ServCellIndex, true); + F1AP_LIB_FIND_IE(F1AP_UEContextSetupRequestIEs_t, ie, &in->protocolIEs.list, F1AP_ProtocolIE_ID_id_CUtoDURRCInformation, true); + + for (int i = 0; i < in->protocolIEs.list.count; ++i) { + ie = in->protocolIEs.list.array[i]; + AssertError(ie != NULL, return false, "in->protocolIEs.list.array[i] is NULL"); + switch (ie->id) { + case F1AP_ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID: + _F1_EQ_CHECK_INT(ie->value.present, F1AP_UEContextSetupRequestIEs__value_PR_GNB_CU_UE_F1AP_ID); + out->gNB_CU_ue_id = ie->value.choice.GNB_CU_UE_F1AP_ID; + break; + case F1AP_ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID: + _F1_EQ_CHECK_INT(ie->value.present, F1AP_UEContextSetupRequestIEs__value_PR_GNB_DU_UE_F1AP_ID); + _F1_MALLOC(out->gNB_DU_ue_id, ie->value.choice.GNB_DU_UE_F1AP_ID); + break; + case F1AP_ProtocolIE_ID_id_SpCell_ID: { + _F1_EQ_CHECK_INT(ie->value.present, F1AP_UEContextSetupRequestIEs__value_PR_NRCGI); + const F1AP_NRCGI_t *nrcgi = &ie->value.choice.NRCGI; + PLMNID_TO_MCC_MNC(&nrcgi->pLMN_Identity, out->plmn.mcc, out->plmn.mnc, out->plmn.mnc_digit_length); + BIT_STRING_TO_NR_CELL_IDENTITY(&nrcgi->nRCellIdentity, out->nr_cellid); + } break; + case F1AP_ProtocolIE_ID_id_ServCellIndex: + _F1_EQ_CHECK_INT(ie->value.present, F1AP_UEContextSetupRequestIEs__value_PR_ServCellIndex); + out->servCellIndex = ie->value.choice.ServCellIndex; + break; + case F1AP_ProtocolIE_ID_id_CUtoDURRCInformation: + _F1_EQ_CHECK_INT(ie->value.present, F1AP_UEContextSetupRequestIEs__value_PR_CUtoDURRCInformation); + _F1_CHECK_EXP(decode_cu_to_du_rrc_info(&out->cu_to_du_rrc_info, &ie->value.choice.CUtoDURRCInformation)); + break; + case F1AP_ProtocolIE_ID_id_SRBs_ToBeSetup_List: + _F1_EQ_CHECK_INT(ie->value.present, F1AP_UEContextSetupRequestIEs__value_PR_SRBs_ToBeSetup_List); + _F1_CHECK_EXP(decode_srbs_to_setup(&ie->value.choice.SRBs_ToBeSetup_List, &out->srbs_len, &out->srbs)); + break; + case F1AP_ProtocolIE_ID_id_DRBs_ToBeSetup_List: + _F1_EQ_CHECK_INT(ie->value.present, F1AP_UEContextSetupRequestIEs__value_PR_DRBs_ToBeSetup_List); + { + // gNB-DU UE Aggregate Maximum Bit Rate Uplink is C-ifDRBSetup + // below, check that gNB-DU UE AMBR UL IE is present if we have DRB + // setup, as required by the spec, or return false otherwise (like in + // the beginning of the function) + F1AP_UEContextSetupRequestIEs_t *check_ie; + F1AP_LIB_FIND_IE(F1AP_UEContextSetupRequestIEs_t, check_ie, &in->protocolIEs.list, F1AP_ProtocolIE_ID_id_GNB_DU_UE_AMBR_UL, true); + } + _F1_CHECK_EXP(decode_drbs_to_setup(&ie->value.choice.DRBs_ToBeSetup_List, &out->drbs_len, &out->drbs)); + break; + case F1AP_ProtocolIE_ID_id_RRCContainer: + _F1_EQ_CHECK_INT(ie->value.present, F1AP_UEContextSetupRequestIEs__value_PR_RRCContainer); + out->rrc_container = malloc_or_fail(sizeof(*out->rrc_container)); + { + OCTET_STRING_t *os = &ie->value.choice.RRCContainer; + *out->rrc_container = create_byte_array(os->size, os->buf); + } + break; + case F1AP_ProtocolIE_ID_id_GNB_DU_UE_AMBR_UL: + _F1_EQ_CHECK_INT(ie->value.present, F1AP_UEContextSetupRequestIEs__value_PR_BitRate); + out->gnb_du_ue_agg_mbr_ul = malloc_or_fail(sizeof(*out->gnb_du_ue_agg_mbr_ul)); + asn_INTEGER2uint64(&ie->value.choice.BitRate, out->gnb_du_ue_agg_mbr_ul); + break; + default: + PRINT_ERROR("F1AP_ProtocolIE_ID_id %ld unknown, skipping\n", ie->id); + break; + } + } + + return true; +} + +/** + * @brief F1 UE Context Setup Request deep copy + */ +f1ap_ue_context_setup_req_t cp_ue_context_setup_req(const f1ap_ue_context_setup_req_t *orig) +{ + /* copy all mandatory fields that are not dynamic memory */ + f1ap_ue_context_setup_req_t cp = { + .gNB_CU_ue_id = orig->gNB_CU_ue_id, + .plmn = orig->plmn, + .nr_cellid = orig->nr_cellid, + .servCellIndex = orig->servCellIndex, + .cu_to_du_rrc_info = cp_cu_to_du_rrc_info(&orig->cu_to_du_rrc_info), + }; + if (orig->gNB_DU_ue_id) + _F1_MALLOC(cp.gNB_DU_ue_id, *orig->gNB_DU_ue_id); + if (orig->srbs_len > 0 && orig->srbs) { + cp.srbs = calloc_or_fail(orig->srbs_len, sizeof(*cp.srbs)); + cp.srbs_len = orig->srbs_len; + for (int i = 0; i < cp.srbs_len; ++i) + cp.srbs[i] = cp_srb_to_setup(&orig->srbs[i]); + } + if (orig->drbs_len > 0 && orig->drbs) { + cp.drbs = calloc_or_fail(orig->drbs_len, sizeof(*cp.drbs)); + cp.drbs_len = orig->drbs_len; + for (int i = 0; i < cp.drbs_len; ++i) + cp.drbs[i] = cp_drb_to_setup(&orig->drbs[i]); + } + CP_OPT_BYTE_ARRAY(cp.rrc_container, orig->rrc_container); + if (orig->gnb_du_ue_agg_mbr_ul) + _F1_MALLOC(cp.gnb_du_ue_agg_mbr_ul, *orig->gnb_du_ue_agg_mbr_ul); + return cp; +} + +/** + * @brief F1 UE Context Setup Request equality check + */ +bool eq_ue_context_setup_req(const f1ap_ue_context_setup_req_t *a, const f1ap_ue_context_setup_req_t *b) +{ + _F1_EQ_CHECK_INT(a->gNB_CU_ue_id, b->gNB_CU_ue_id); + _F1_EQ_CHECK_OPTIONAL_IE(a, b, gNB_DU_ue_id, _F1_EQ_CHECK_INT); + _F1_CHECK_EXP(eq_f1ap_plmn(&a->plmn, &b->plmn)); + _F1_EQ_CHECK_LONG(a->nr_cellid, b->nr_cellid); + _F1_EQ_CHECK_INT(a->servCellIndex, b->servCellIndex); + _F1_CHECK_EXP(eq_cu_to_du_rrc_info(&a->cu_to_du_rrc_info, &b->cu_to_du_rrc_info)); + + _F1_EQ_CHECK_INT(a->srbs_len, b->srbs_len); + _F1_CHECK_EXP(a->srbs_len == 0 || (a->srbs && b->srbs)); + for (int i = 0; i < a->srbs_len; ++i) + _F1_CHECK_EXP(eq_srb_to_setup(&a->srbs[i], &b->srbs[i])); + + _F1_EQ_CHECK_INT(a->drbs_len, b->drbs_len); + _F1_CHECK_EXP(a->drbs_len == 0 || (a->drbs && b->drbs)); + for (int i = 0; i < a->drbs_len; ++i) + _F1_CHECK_EXP(eq_drb_to_setup(&a->drbs[i], &b->drbs[i])); + + _F1_EQ_CHECK_OPTIONAL_IE(a, b, rrc_container, eq_ba); + + _F1_EQ_CHECK_OPTIONAL_IE(a, b, gnb_du_ue_agg_mbr_ul, _F1_EQ_CHECK_LONG); + return true; +} + +/** + * @brief Free Allocated F1 UE Context Setup Request + */ +void free_ue_context_setup_req(f1ap_ue_context_setup_req_t *req) +{ + free(req->gNB_DU_ue_id); + free_cu_to_du_rrc_info(&req->cu_to_du_rrc_info); + for (int i = 0; i < req->srbs_len; ++i) + free_srb_to_setup(&req->srbs[i]); + free(req->srbs); + for (int i = 0; i < req->drbs_len; ++i) + free_drb_to_setup(&req->drbs[i]); + free(req->drbs); + FREE_OPT_BYTE_ARRAY(req->rrc_container); + free(req->gnb_du_ue_agg_mbr_ul); +} + +/** + * @brief Encode F1 UE context setup response to ASN.1 + */ +F1AP_F1AP_PDU_t *encode_ue_context_setup_resp(const f1ap_ue_context_setup_resp_t *msg) +{ + F1AP_F1AP_PDU_t *pdu = calloc_or_fail(1, sizeof(*pdu)); + + /* Message Type */ + pdu->present = F1AP_F1AP_PDU_PR_successfulOutcome; + asn1cCalloc(pdu->choice.successfulOutcome, tmp); + tmp->procedureCode = F1AP_ProcedureCode_id_UEContextSetup; + tmp->criticality = F1AP_Criticality_reject; + tmp->value.present = F1AP_SuccessfulOutcome__value_PR_UEContextSetupResponse; + F1AP_UEContextSetupResponse_t *out = &tmp->value.choice.UEContextSetupResponse; + + /* mandatory: GNB_CU_UE_F1AP_ID */ + asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextSetupResponseIEs_t, ie1); + ie1->id = F1AP_ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID; + ie1->criticality = F1AP_Criticality_reject; + ie1->value.present = F1AP_UEContextSetupResponseIEs__value_PR_GNB_CU_UE_F1AP_ID; + ie1->value.choice.GNB_CU_UE_F1AP_ID = msg->gNB_CU_ue_id; + + /* mandatory: GNB_DU_UE_F1AP_ID */ + asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextSetupResponseIEs_t, ie2); + ie2->id = F1AP_ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID; + ie2->criticality = F1AP_Criticality_reject; + ie2->value.present = F1AP_UEContextSetupResponseIEs__value_PR_GNB_DU_UE_F1AP_ID; + ie2->value.choice.GNB_DU_UE_F1AP_ID = msg->gNB_DU_ue_id; + + /* mandatory: DUtoCURRCInformation */ + asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextSetupResponseIEs_t, ie3); + ie3->id = F1AP_ProtocolIE_ID_id_DUtoCURRCInformation; + ie3->criticality = F1AP_Criticality_reject; + ie3->value.present = F1AP_UEContextSetupResponseIEs__value_PR_DUtoCURRCInformation; + ie3->value.choice.DUtoCURRCInformation = encode_du_to_cu_rrc_info(&msg->du_to_cu_rrc_info); + + /* optional: C-RNTI */ + if (msg->crnti) { + asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextSetupResponseIEs_t, ie4); + ie4->id = F1AP_ProtocolIE_ID_id_C_RNTI; + ie4->criticality = F1AP_Criticality_ignore; + ie4->value.present = F1AP_UEContextSetupResponseIEs__value_PR_C_RNTI; + ie4->value.choice.C_RNTI = *msg->crnti; + } + + /* optional: DRB Setup List */ + if (msg->drbs_len > 0) { + asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextSetupResponseIEs_t, ie7); + ie7->id = F1AP_ProtocolIE_ID_id_DRBs_Setup_List; + ie7->criticality = F1AP_Criticality_ignore; + ie7->value.present = F1AP_UEContextSetupResponseIEs__value_PR_DRBs_Setup_List; + ie7->value.choice.DRBs_Setup_List = encode_drbs_setup(msg->drbs_len, msg->drbs); + } + + /* optional: SRB Setup List */ + if (msg->srbs_len > 0) { + asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextSetupResponseIEs_t, ie11); + ie11->id = F1AP_ProtocolIE_ID_id_SRBs_Setup_List; + ie11->criticality = F1AP_Criticality_ignore; + ie11->value.present = F1AP_UEContextSetupResponseIEs__value_PR_SRBs_Setup_List; + ie11->value.choice.SRBs_Setup_List = encode_srbs_setup(msg->srbs_len, msg->srbs); + } + + return pdu; +} + +/** + * @brief Decode F1 UE Context Setup Response + */ +bool decode_ue_context_setup_resp(const struct F1AP_F1AP_PDU *pdu, f1ap_ue_context_setup_resp_t *out) +{ + DevAssert(out != NULL); + memset(out, 0, sizeof(*out)); + + F1AP_UEContextSetupResponse_t *in = &pdu->choice.successfulOutcome->value.choice.UEContextSetupResponse; + F1AP_UEContextSetupResponseIEs_t *ie; + + F1AP_LIB_FIND_IE(F1AP_UEContextSetupResponseIEs_t, ie, &in->protocolIEs.list, F1AP_ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID, true); + F1AP_LIB_FIND_IE(F1AP_UEContextSetupResponseIEs_t, ie, &in->protocolIEs.list, F1AP_ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID, true); + F1AP_LIB_FIND_IE(F1AP_UEContextSetupResponseIEs_t, ie, &in->protocolIEs.list, F1AP_ProtocolIE_ID_id_DUtoCURRCInformation, true); + + for (int i = 0; i < in->protocolIEs.list.count; ++i) { + ie = in->protocolIEs.list.array[i]; + AssertError(ie != NULL, return false, "in->protocolIEs.list.array[i] is NULL"); + switch (ie->id) { + case F1AP_ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID: + _F1_EQ_CHECK_INT(ie->value.present, F1AP_UEContextSetupResponseIEs__value_PR_GNB_CU_UE_F1AP_ID); + out->gNB_CU_ue_id = ie->value.choice.GNB_CU_UE_F1AP_ID; + break; + case F1AP_ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID: + _F1_EQ_CHECK_INT(ie->value.present, F1AP_UEContextSetupResponseIEs__value_PR_GNB_DU_UE_F1AP_ID); + out->gNB_DU_ue_id = ie->value.choice.GNB_DU_UE_F1AP_ID; + break; + case F1AP_ProtocolIE_ID_id_DUtoCURRCInformation: + _F1_EQ_CHECK_INT(ie->value.present, F1AP_UEContextSetupResponseIEs__value_PR_DUtoCURRCInformation); + _F1_CHECK_EXP(decode_du_to_cu_rrc_info(&out->du_to_cu_rrc_info, &ie->value.choice.DUtoCURRCInformation)); + break; + case F1AP_ProtocolIE_ID_id_C_RNTI: + _F1_EQ_CHECK_INT(ie->value.present, F1AP_UEContextSetupResponseIEs__value_PR_C_RNTI); + _F1_MALLOC(out->crnti, ie->value.choice.C_RNTI); + break; + case F1AP_ProtocolIE_ID_id_DRBs_Setup_List: + _F1_EQ_CHECK_INT(ie->value.present, F1AP_UEContextSetupResponseIEs__value_PR_DRBs_Setup_List); + _F1_CHECK_EXP(decode_drbs_setup(&ie->value.choice.DRBs_Setup_List, &out->drbs_len, &out->drbs)); + break; + case F1AP_ProtocolIE_ID_id_SRBs_Setup_List: + _F1_EQ_CHECK_INT(ie->value.present, F1AP_UEContextSetupResponseIEs__value_PR_SRBs_Setup_List); + _F1_CHECK_EXP(decode_srbs_setup(&ie->value.choice.SRBs_Setup_List, &out->srbs_len, &out->srbs)); + break; + default: + PRINT_ERROR("F1AP_ProtocolIE_ID_id %ld unknown, skipping\n", ie->id); + break; + } + } + + return true; +} + +/** + * @brief F1 UE Context Setup Response deep copy + */ +f1ap_ue_context_setup_resp_t cp_ue_context_setup_resp(const f1ap_ue_context_setup_resp_t *orig) +{ + f1ap_ue_context_setup_resp_t cp = { + .gNB_CU_ue_id = orig->gNB_CU_ue_id, + .gNB_DU_ue_id = orig->gNB_DU_ue_id, + .du_to_cu_rrc_info = cp_du_to_cu_rrc_info(&orig->du_to_cu_rrc_info), + // crnti below + .drbs_len = orig->drbs_len, + // drbs below + .srbs_len = orig->srbs_len, + // srbs below + }; + if (orig->crnti) + _F1_MALLOC(cp.crnti, *orig->crnti); + if (orig->drbs_len > 0 && orig->drbs) { + cp.drbs = calloc_or_fail(orig->drbs_len, sizeof(*cp.drbs)); + cp.drbs_len = orig->drbs_len; + for (int i = 0; i < cp.drbs_len; ++i) + cp.drbs[i] = cp_drb_setup(&orig->drbs[i]); + } + if (orig->srbs_len > 0 && orig->srbs) { + cp.srbs = calloc_or_fail(orig->srbs_len, sizeof(*cp.srbs)); + cp.srbs_len = orig->srbs_len; + for (int i = 0; i < cp.srbs_len; ++i) + cp.srbs[i] = cp_srb_setup(&orig->srbs[i]); + } + return cp; +} + +/** + * @brief F1 UE Context Setup Response equality check + */ +bool eq_ue_context_setup_resp(const f1ap_ue_context_setup_resp_t *a, const f1ap_ue_context_setup_resp_t *b) +{ + _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_CHECK_EXP(eq_du_to_cu_rrc_info(&a->du_to_cu_rrc_info, &b->du_to_cu_rrc_info)); + _F1_EQ_CHECK_OPTIONAL_IE(a, b, crnti, _F1_EQ_CHECK_INT); + + _F1_EQ_CHECK_INT(a->drbs_len, b->drbs_len); + _F1_CHECK_EXP(a->drbs_len == 0 || (a->drbs && b->drbs)); + for (int i = 0; i < a->drbs_len; ++i) + _F1_CHECK_EXP(eq_drb_setup(&a->drbs[i], &b->drbs[i])); + + _F1_EQ_CHECK_INT(a->srbs_len, b->srbs_len); + _F1_CHECK_EXP(a->srbs_len == 0 || (a->srbs && b->srbs)); + for (int i = 0; i < a->srbs_len; ++i) + _F1_CHECK_EXP(eq_srb_setup(&a->srbs[i], &b->srbs[i])); + + return true; +} + +/** + * @brief Free Allocated F1 UE Context Setup Response + */ +void free_ue_context_setup_resp(f1ap_ue_context_setup_resp_t *resp) +{ + free_du_to_cu_rrc_info(&resp->du_to_cu_rrc_info); + free(resp->crnti); + for (int i = 0; i < resp->drbs_len; ++i) + free_drb_setup(&resp->drbs[i]); + free(resp->drbs); + for (int i = 0; i < resp->srbs_len; ++i) + free_srb_setup(&resp->srbs[i]); + free(resp->srbs); +} + +/** + * @brief Encode F1 UE context modification request to ASN.1 + */ +F1AP_F1AP_PDU_t *encode_ue_context_mod_req(const f1ap_ue_context_mod_req_t *req) +{ + F1AP_F1AP_PDU_t *pdu = calloc_or_fail(1, sizeof(*pdu)); + + /* Message Type */ + pdu->present = F1AP_F1AP_PDU_PR_initiatingMessage; + asn1cCalloc(pdu->choice.initiatingMessage, tmp); + tmp->procedureCode = F1AP_ProcedureCode_id_UEContextModification; + tmp->criticality = F1AP_Criticality_reject; + tmp->value.present = F1AP_InitiatingMessage__value_PR_UEContextModificationRequest; + F1AP_UEContextModificationRequest_t *out = &tmp->value.choice.UEContextModificationRequest; + + /* mandatory: GNB_CU_UE_F1AP_ID */ + asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextModificationRequestIEs_t, ie1); + ie1->id = F1AP_ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID; + ie1->criticality = F1AP_Criticality_reject; + ie1->value.present = F1AP_UEContextModificationRequestIEs__value_PR_GNB_CU_UE_F1AP_ID; + ie1->value.choice.GNB_CU_UE_F1AP_ID = req->gNB_CU_ue_id; + + /* mandatory: GNB_DU_UE_F1AP_ID */ + asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextModificationRequestIEs_t, ie2); + ie2->id = F1AP_ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID; + ie2->criticality = F1AP_Criticality_reject; + ie2->value.present = F1AP_UEContextModificationRequestIEs__value_PR_GNB_DU_UE_F1AP_ID; + ie2->value.choice.GNB_DU_UE_F1AP_ID = req->gNB_DU_ue_id; + + /* optional: SpCellID/NRCGI */ + if (req->plmn) { + DevAssert(req->nr_cellid); + asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextModificationRequestIEs_t, ie3); + ie3->id = F1AP_ProtocolIE_ID_id_SpCell_ID; + ie3->criticality = F1AP_Criticality_ignore; + ie3->value.present = F1AP_UEContextModificationRequestIEs__value_PR_NRCGI; + F1AP_NRCGI_t *nrcgi = &ie3->value.choice.NRCGI; + const plmn_id_t *plmn = req->plmn; + MCC_MNC_TO_PLMNID(plmn->mcc, plmn->mnc, plmn->mnc_digit_length, &nrcgi->pLMN_Identity); + NR_CELL_ID_TO_BIT_STRING(*req->nr_cellid, &nrcgi->nRCellIdentity); + } + + /* optional: ServCellIndex */ + if (req->servCellIndex) { + asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextModificationRequestIEs_t, ie4); + ie4->id = F1AP_ProtocolIE_ID_id_ServCellIndex; + ie4->criticality = F1AP_Criticality_reject; + ie4->value.present = F1AP_UEContextModificationRequestIEs__value_PR_ServCellIndex; + ie4->value.choice.ServCellIndex = *req->servCellIndex; + } + + /* optional: CUtoDURRCInformation */ + if (req->cu_to_du_rrc_info) { + asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextModificationRequestIEs_t, ie6); + ie6->id = F1AP_ProtocolIE_ID_id_CUtoDURRCInformation; + ie6->criticality = F1AP_Criticality_reject; + ie6->value.present = F1AP_UEContextModificationRequestIEs__value_PR_CUtoDURRCInformation; + ie6->value.choice.CUtoDURRCInformation = encode_cu_to_du_rrc_info(req->cu_to_du_rrc_info); + } + + /* optional: TransmissionActionIndicator */ + if (req->transm_action_ind) { + asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextModificationRequestIEs_t, ie7); + ie7->id = F1AP_ProtocolIE_ID_id_TransmissionActionIndicator; + ie7->criticality = F1AP_Criticality_ignore; + ie7->value.present = F1AP_UEContextModificationRequestIEs__value_PR_TransmissionActionIndicator; + ie7->value.choice.TransmissionActionIndicator = *req->transm_action_ind; + // Stop is guaranteed to be 0, by restart might be different from 1 + static_assert((int)F1AP_TransmissionActionIndicator_restart == (int)TransmActionInd_RESTART, + "mismatch of ASN.1 and internal representation\n"); + } + + /* optional: RRCRconfigurationCompleteIndicator */ + if (req->reconfig_compl) { + asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextModificationRequestIEs_t, ie71); + ie71->id = F1AP_ProtocolIE_ID_id_RRCReconfigurationCompleteIndicator; + ie71->criticality = F1AP_Criticality_ignore; + ie71->value.present = F1AP_UEContextModificationRequestIEs__value_PR_RRCReconfigurationCompleteIndicator; + ie71->value.choice.RRCReconfigurationCompleteIndicator = *req->reconfig_compl == RRCreconf_success + ? F1AP_RRCReconfigurationCompleteIndicator_true + : F1AP_RRCReconfigurationCompleteIndicator_failure; + } + + /* optional: RRC container */ + if (req->rrc_container) { + asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextModificationRequestIEs_t, ie81); + ie81->id = F1AP_ProtocolIE_ID_id_RRCContainer; + ie81->criticality = F1AP_Criticality_ignore; + ie81->value.present = F1AP_UEContextModificationRequestIEs__value_PR_RRCContainer; + OCTET_STRING_fromBuf(&ie81->value.choice.RRCContainer, (const char *)req->rrc_container->buf, req->rrc_container->len); + } + + /* optional: SRBs_ToBeSetupMod */ + if (req->srbs_len > 0) { + DevAssert(req->srbs); + asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextModificationRequestIEs_t, ie11); + ie11->id = F1AP_ProtocolIE_ID_id_SRBs_ToBeSetupMod_List; + ie11->criticality = F1AP_Criticality_reject; + ie11->value.present = F1AP_UEContextModificationRequestIEs__value_PR_SRBs_ToBeSetupMod_List; + ie11->value.choice.SRBs_ToBeSetupMod_List = encode_srbs_to_setupmod(req->srbs_len, req->srbs); + } + + /* optional: DRBs_ToBeSetupMod */ + if (req->drbs_len > 0) { + DevAssert(req->drbs); + asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextModificationRequestIEs_t, ie12); + ie12->id = F1AP_ProtocolIE_ID_id_DRBs_ToBeSetupMod_List; + ie12->criticality = F1AP_Criticality_reject; + ie12->value.present = F1AP_UEContextModificationRequestIEs__value_PR_DRBs_ToBeSetupMod_List; + ie12->value.choice.DRBs_ToBeSetupMod_List = encode_drbs_to_setupmod(req->drbs_len, req->drbs); + } + + /* optional: DRBs_ToBeReleased */ + if (req->drbs_rel_len > 0) { + asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextModificationRequestIEs_t, ie15); + ie15->id = F1AP_ProtocolIE_ID_id_DRBs_ToBeReleased_List; + ie15->criticality = F1AP_Criticality_reject; + ie15->value.present = F1AP_UEContextModificationRequestIEs__value_PR_DRBs_ToBeReleased_List; + ie15->value.choice.DRBs_ToBeReleased_List = encode_drbs_to_release(req->drbs_rel_len, req->drbs_rel); + } + + /* optional: Lower Layer Presence Status Change */ + if (req->status) { + asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextModificationRequestIEs_t, ie17); + ie17->id = F1AP_ProtocolIE_ID_id_LowerLayerPresenceStatusChange; + ie17->criticality = F1AP_Criticality_ignore; + ie17->value.present = F1AP_UEContextModificationRequestIEs__value_PR_LowerLayerPresenceStatusChange; + ie17->value.choice.LowerLayerPresenceStatusChange = *req->status == LOWER_LAYERS_SUSPEND + ? F1AP_LowerLayerPresenceStatusChange_suspend_lower_layers + : F1AP_LowerLayerPresenceStatusChange_resume_lower_layers; + } + return pdu; +} + +/** + * @brief Decode F1 UE Context Modification Request + */ +bool decode_ue_context_mod_req(const F1AP_F1AP_PDU_t *pdu, f1ap_ue_context_mod_req_t *out) +{ + DevAssert(out != NULL); + memset(out, 0, sizeof(*out)); + + F1AP_UEContextModificationRequest_t *in = &pdu->choice.initiatingMessage->value.choice.UEContextModificationRequest; + F1AP_UEContextModificationRequestIEs_t *ie; + F1AP_LIB_FIND_IE(F1AP_UEContextModificationRequestIEs_t, ie, &in->protocolIEs.list, F1AP_ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID, true); + F1AP_LIB_FIND_IE(F1AP_UEContextModificationRequestIEs_t, ie, &in->protocolIEs.list, F1AP_ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID, true); + + for (int i = 0; i < in->protocolIEs.list.count; ++i) { + ie = in->protocolIEs.list.array[i]; + AssertError(ie != NULL, return false, "in->protocolIEs.list.array[i] is NULL"); + switch (ie->id) { + case F1AP_ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID: + _F1_EQ_CHECK_INT(ie->value.present, F1AP_UEContextModificationRequestIEs__value_PR_GNB_CU_UE_F1AP_ID); + out->gNB_CU_ue_id = ie->value.choice.GNB_CU_UE_F1AP_ID; + break; + case F1AP_ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID: + _F1_EQ_CHECK_INT(ie->value.present, F1AP_UEContextModificationRequestIEs__value_PR_GNB_DU_UE_F1AP_ID); + out->gNB_DU_ue_id = ie->value.choice.GNB_DU_UE_F1AP_ID; + break; + case F1AP_ProtocolIE_ID_id_SpCell_ID: { + _F1_EQ_CHECK_INT(ie->value.present, F1AP_UEContextModificationRequestIEs__value_PR_NRCGI); + const F1AP_NRCGI_t *nrcgi = &ie->value.choice.NRCGI; + out->plmn = malloc_or_fail(sizeof(*out->plmn)); + PLMNID_TO_MCC_MNC(&nrcgi->pLMN_Identity, out->plmn->mcc, out->plmn->mnc, out->plmn->mnc_digit_length); + out->nr_cellid = malloc_or_fail(sizeof(*out->nr_cellid)); + BIT_STRING_TO_NR_CELL_IDENTITY(&nrcgi->nRCellIdentity, *out->nr_cellid); + } break; + case F1AP_ProtocolIE_ID_id_ServCellIndex: + _F1_EQ_CHECK_INT(ie->value.present, F1AP_UEContextModificationRequestIEs__value_PR_ServCellIndex); + _F1_MALLOC(out->servCellIndex, ie->value.choice.ServCellIndex); + break; + case F1AP_ProtocolIE_ID_id_CUtoDURRCInformation: + _F1_EQ_CHECK_INT(ie->value.present, F1AP_UEContextModificationRequestIEs__value_PR_CUtoDURRCInformation); + out->cu_to_du_rrc_info = calloc(1, sizeof(*out->cu_to_du_rrc_info)); + _F1_CHECK_EXP(decode_cu_to_du_rrc_info(out->cu_to_du_rrc_info, &ie->value.choice.CUtoDURRCInformation)); + break; + case F1AP_ProtocolIE_ID_id_TransmissionActionIndicator: + _F1_EQ_CHECK_INT(ie->value.present, F1AP_UEContextModificationRequestIEs__value_PR_TransmissionActionIndicator); + { + TransmActionInd_t v = ie->value.choice.TransmissionActionIndicator == F1AP_TransmissionActionIndicator_stop + ? TransmActionInd_STOP + : TransmActionInd_RESTART; + _F1_MALLOC(out->transm_action_ind, v); + } + break; + case F1AP_ProtocolIE_ID_id_RRCReconfigurationCompleteIndicator: + _F1_EQ_CHECK_INT(ie->value.present, F1AP_UEContextModificationRequestIEs__value_PR_RRCReconfigurationCompleteIndicator); + { + ReconfigurationCompl_t v = + ie->value.choice.RRCReconfigurationCompleteIndicator == F1AP_RRCReconfigurationCompleteIndicator_true + ? RRCreconf_success + : RRCreconf_failure; + _F1_MALLOC(out->reconfig_compl, v); + } + break; + case F1AP_ProtocolIE_ID_id_RRCContainer: + _F1_EQ_CHECK_INT(ie->value.present, F1AP_UEContextModificationRequestIEs__value_PR_RRCContainer); + out->rrc_container = malloc_or_fail(sizeof(*out->rrc_container)); + { + OCTET_STRING_t *os = &ie->value.choice.RRCContainer; + *out->rrc_container = create_byte_array(os->size, os->buf); + } + break; + case F1AP_ProtocolIE_ID_id_SRBs_ToBeSetupMod_List: + _F1_EQ_CHECK_INT(ie->value.present, F1AP_UEContextModificationRequestIEs__value_PR_SRBs_ToBeSetupMod_List); + _F1_CHECK_EXP(decode_srbs_to_setupmod(&ie->value.choice.SRBs_ToBeSetupMod_List, &out->srbs_len, &out->srbs)); + break; + case F1AP_ProtocolIE_ID_id_DRBs_ToBeSetupMod_List: + _F1_EQ_CHECK_INT(ie->value.present, F1AP_UEContextModificationRequestIEs__value_PR_DRBs_ToBeSetupMod_List); + _F1_CHECK_EXP(decode_drbs_to_setupmod(&ie->value.choice.DRBs_ToBeSetupMod_List, &out->drbs_len, &out->drbs)); + break; + case F1AP_ProtocolIE_ID_id_DRBs_ToBeReleased_List: + _F1_EQ_CHECK_INT(ie->value.present, F1AP_UEContextModificationRequestIEs__value_PR_DRBs_ToBeReleased_List); + _F1_CHECK_EXP(decode_drbs_to_release(&ie->value.choice.DRBs_ToBeReleased_List, &out->drbs_rel_len, &out->drbs_rel)); + break; + case F1AP_ProtocolIE_ID_id_LowerLayerPresenceStatusChange: + _F1_EQ_CHECK_INT(ie->value.present, F1AP_UEContextModificationRequestIEs__value_PR_LowerLayerPresenceStatusChange); + { + lower_layer_status_t v = ie->value.choice.LowerLayerPresenceStatusChange == F1AP_LowerLayerPresenceStatusChange_suspend_lower_layers + ? LOWER_LAYERS_SUSPEND : LOWER_LAYERS_RESUME; + _F1_MALLOC(out->status, v); + } + break; + default: + PRINT_ERROR("F1AP_ProtocolIE_ID_id %ld unknown, skipping\n", ie->id); + break; + } + } + + return true; +} + +/** + * @brief F1 UE Context Modification Request deep copy + */ +f1ap_ue_context_mod_req_t cp_ue_context_mod_req(const f1ap_ue_context_mod_req_t *orig) +{ + f1ap_ue_context_mod_req_t cp = { + .gNB_CU_ue_id = orig->gNB_CU_ue_id, + .gNB_DU_ue_id = orig->gNB_DU_ue_id, + // .plmn, .nr_cellid, .servCellIndex below + // .cu_to_du_rrc_info below + // .transm_action_ind below + // .reconfig_compl below + // .rrc_container below + .srbs_len = orig->srbs_len, + // .srbs below + .drbs_len = orig->drbs_len, + // .drbs below + // .status below + }; + + if (orig->plmn) + _F1_MALLOC(cp.plmn, *orig->plmn); + if (orig->nr_cellid) + _F1_MALLOC(cp.nr_cellid, *orig->nr_cellid); + if (orig->servCellIndex) + _F1_MALLOC(cp.servCellIndex, *orig->servCellIndex); + if (orig->cu_to_du_rrc_info) + _F1_MALLOC(cp.cu_to_du_rrc_info, cp_cu_to_du_rrc_info(orig->cu_to_du_rrc_info)); + if (orig->transm_action_ind) + _F1_MALLOC(cp.transm_action_ind, *orig->transm_action_ind); + if (orig->reconfig_compl) + _F1_MALLOC(cp.reconfig_compl, *orig->reconfig_compl); + CP_OPT_BYTE_ARRAY(cp.rrc_container, orig->rrc_container); + if (orig->srbs_len > 0) { + DevAssert(orig->srbs); + cp.srbs = calloc_or_fail(orig->srbs_len, sizeof(*cp.srbs)); + cp.srbs_len = orig->srbs_len; + for (int i = 0; i < cp.srbs_len; ++i) + cp.srbs[i] = cp_srb_to_setup(&orig->srbs[i]); + } + if (orig->drbs_len > 0) { + DevAssert(orig->drbs); + cp.drbs = calloc_or_fail(orig->drbs_len, sizeof(*cp.drbs)); + cp.drbs_len = orig->drbs_len; + for (int i = 0; i < cp.drbs_len; ++i) + cp.drbs[i] = cp_drb_to_setup(&orig->drbs[i]); + } + if (orig->drbs_rel_len > 0) { + DevAssert(orig->drbs_rel); + cp.drbs_rel = calloc_or_fail(orig->drbs_rel_len, sizeof(*cp.drbs_rel)); + cp.drbs_rel_len = orig->drbs_rel_len; + for (int i = 0; i < cp.drbs_rel_len; ++i) + cp.drbs_rel[i] = cp_drb_to_release(&orig->drbs_rel[i]); + } + if (orig->status) + _F1_MALLOC(cp.status, *orig->status); + return cp; +} + +/** + * @brief F1 UE Context Modification Request equality check + */ +bool eq_ue_context_mod_req(const f1ap_ue_context_mod_req_t *a, const f1ap_ue_context_mod_req_t *b) +{ + _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_CHECK_EXP((a->plmn && b->plmn) || (!a->plmn && !b->plmn)); + _F1_CHECK_EXP(!a->plmn || eq_f1ap_plmn(a->plmn, b->plmn)); + _F1_EQ_CHECK_OPTIONAL_IE(a, b, nr_cellid, _F1_EQ_CHECK_LONG); + _F1_EQ_CHECK_OPTIONAL_IE(a, b, servCellIndex, _F1_EQ_CHECK_INT); + _F1_CHECK_EXP((a->cu_to_du_rrc_info && b->cu_to_du_rrc_info) || (!a->cu_to_du_rrc_info && !b->cu_to_du_rrc_info)); + _F1_CHECK_EXP(!a->cu_to_du_rrc_info || eq_cu_to_du_rrc_info(a->cu_to_du_rrc_info, b->cu_to_du_rrc_info)); + _F1_EQ_CHECK_OPTIONAL_IE(a, b, transm_action_ind, _F1_EQ_CHECK_INT); + _F1_EQ_CHECK_OPTIONAL_IE(a, b, reconfig_compl, _F1_EQ_CHECK_INT); + _F1_EQ_CHECK_OPTIONAL_IE(a, b, rrc_container, eq_ba); + + _F1_EQ_CHECK_INT(a->srbs_len, b->srbs_len); + _F1_CHECK_EXP(a->srbs_len == 0 || (a->srbs && b->srbs)); + for (int i = 0; i < a->srbs_len; ++i) + _F1_CHECK_EXP(eq_srb_to_setup(&a->srbs[i], &b->srbs[i])); + + _F1_EQ_CHECK_INT(a->drbs_len, b->drbs_len); + _F1_CHECK_EXP(a->drbs_len == 0 || (a->drbs && b->drbs)); + for (int i = 0; i < a->drbs_len; ++i) + _F1_CHECK_EXP(eq_drb_to_setup(&a->drbs[i], &b->drbs[i])); + + _F1_EQ_CHECK_INT(a->drbs_rel_len, b->drbs_rel_len); + _F1_CHECK_EXP(a->drbs_rel_len == 0 || (a->drbs_rel_len && b->drbs_rel_len)); + for (int i = 0; i < a->drbs_rel_len; ++i) + _F1_CHECK_EXP(eq_drb_to_release(&a->drbs_rel[i], &b->drbs_rel[i])); + + _F1_EQ_CHECK_OPTIONAL_IE(a, b, status, _F1_EQ_CHECK_INT); + return true; +} + +/** + * @brief Free Allocated F1 UE Context Modification Request + */ +void free_ue_context_mod_req(f1ap_ue_context_mod_req_t *req) +{ + free(req->plmn); + free(req->nr_cellid); + free(req->servCellIndex); + if (req->cu_to_du_rrc_info) + free_cu_to_du_rrc_info(req->cu_to_du_rrc_info); + free(req->cu_to_du_rrc_info); + free(req->transm_action_ind); + free(req->reconfig_compl); + FREE_OPT_BYTE_ARRAY(req->rrc_container); + for (int i = 0; i < req->srbs_len; ++i) + free_srb_to_setup(&req->srbs[i]); + free(req->srbs); + for (int i = 0; i < req->drbs_len; ++i) + free_drb_to_setup(&req->drbs[i]); + free(req->drbs); + for (int i = 0; i < req->drbs_rel_len; ++i) + free_drb_to_release(&req->drbs_rel[i]); + free(req->drbs_rel); + free(req->status); +} + +/** + * @brief Encode F1 UE context modification response to ASN.1 + */ +F1AP_F1AP_PDU_t *encode_ue_context_mod_resp(const f1ap_ue_context_mod_resp_t *msg) +{ + F1AP_F1AP_PDU_t *pdu = calloc_or_fail(1, sizeof(*pdu)); + + /* Message Type */ + pdu->present = F1AP_F1AP_PDU_PR_successfulOutcome; + asn1cCalloc(pdu->choice.successfulOutcome, tmp); + tmp->procedureCode = F1AP_ProcedureCode_id_UEContextModification; + tmp->criticality = F1AP_Criticality_reject; + tmp->value.present = F1AP_SuccessfulOutcome__value_PR_UEContextModificationResponse; + F1AP_UEContextModificationResponse_t *out = &tmp->value.choice.UEContextModificationResponse; + + /* mandatory: GNB_CU_UE_F1AP_ID */ + asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextModificationResponseIEs_t, ie1); + ie1->id = F1AP_ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID; + ie1->criticality = F1AP_Criticality_reject; + ie1->value.present = F1AP_UEContextModificationResponseIEs__value_PR_GNB_CU_UE_F1AP_ID; + ie1->value.choice.GNB_CU_UE_F1AP_ID = msg->gNB_CU_ue_id; + + /* mandatory: GNB_DU_UE_F1AP_ID */ + asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextModificationResponseIEs_t, ie2); + ie2->id = F1AP_ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID; + ie2->criticality = F1AP_Criticality_reject; + ie2->value.present = F1AP_UEContextModificationResponseIEs__value_PR_GNB_DU_UE_F1AP_ID; + ie2->value.choice.GNB_DU_UE_F1AP_ID = msg->gNB_DU_ue_id; + + /* optional: DUtoCURRCInformation */ + if (msg->du_to_cu_rrc_info != NULL) { + asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextModificationResponseIEs_t, ie4); + ie4->id = F1AP_ProtocolIE_ID_id_DUtoCURRCInformation; + ie4->criticality = F1AP_Criticality_reject; + ie4->value.present = F1AP_UEContextModificationResponseIEs__value_PR_DUtoCURRCInformation; + ie4->value.choice.DUtoCURRCInformation = encode_du_to_cu_rrc_info(msg->du_to_cu_rrc_info); + } + + /* optional: DRBs_Setup_List */ + if (msg->drbs_len > 0) { + asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextModificationResponseIEs_t, ie5); + ie5->id = F1AP_ProtocolIE_ID_id_DRBs_SetupMod_List; + ie5->criticality = F1AP_Criticality_ignore; + ie5->value.present = F1AP_UEContextModificationResponseIEs__value_PR_DRBs_SetupMod_List; + ie5->value.choice.DRBs_SetupMod_List = encode_drbs_setupmod(msg->drbs_len, msg->drbs); + } + + if (msg->srbs_len > 0) { + asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextModificationResponseIEs_t, ie12); + ie12->id = F1AP_ProtocolIE_ID_id_SRBs_SetupMod_List; + ie12->criticality = F1AP_Criticality_ignore; + ie12->value.present = F1AP_UEContextModificationResponseIEs__value_PR_SRBs_SetupMod_List; + ie12->value.choice.SRBs_SetupMod_List = encode_srbs_setupmod(msg->srbs_len, msg->srbs); + } + + return pdu; +} + +/** + * @brief Decode F1 UE Context modification Response + */ +bool decode_ue_context_mod_resp(const struct F1AP_F1AP_PDU *pdu, f1ap_ue_context_mod_resp_t *out) +{ + DevAssert(out != NULL); + memset(out, 0, sizeof(*out)); + + F1AP_UEContextModificationResponse_t *in = &pdu->choice.successfulOutcome->value.choice.UEContextModificationResponse; + F1AP_UEContextModificationResponseIEs_t *ie; + + F1AP_LIB_FIND_IE(F1AP_UEContextModificationResponseIEs_t, ie, &in->protocolIEs.list, F1AP_ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID, true); + F1AP_LIB_FIND_IE(F1AP_UEContextModificationResponseIEs_t, ie, &in->protocolIEs.list, F1AP_ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID, true); + + for (int i = 0; i < in->protocolIEs.list.count; ++i) { + ie = in->protocolIEs.list.array[i]; + AssertError(ie != NULL, return false, "in->protocolIEs.list.array[i] is NULL"); + switch (ie->id) { + case F1AP_ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID: + _F1_EQ_CHECK_INT(ie->value.present, F1AP_UEContextModificationResponseIEs__value_PR_GNB_CU_UE_F1AP_ID); + out->gNB_CU_ue_id = ie->value.choice.GNB_CU_UE_F1AP_ID; + break; + case F1AP_ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID: + _F1_EQ_CHECK_INT(ie->value.present, F1AP_UEContextModificationResponseIEs__value_PR_GNB_DU_UE_F1AP_ID); + out->gNB_DU_ue_id = ie->value.choice.GNB_DU_UE_F1AP_ID; + break; + case F1AP_ProtocolIE_ID_id_DUtoCURRCInformation: + _F1_EQ_CHECK_INT(ie->value.present, F1AP_UEContextModificationResponseIEs__value_PR_DUtoCURRCInformation); + out->du_to_cu_rrc_info = calloc(1, sizeof(*out->du_to_cu_rrc_info)); + _F1_CHECK_EXP(decode_du_to_cu_rrc_info(out->du_to_cu_rrc_info, &ie->value.choice.DUtoCURRCInformation)); + break; + case F1AP_ProtocolIE_ID_id_DRBs_SetupMod_List: + _F1_EQ_CHECK_INT(ie->value.present, F1AP_UEContextModificationResponseIEs__value_PR_DRBs_SetupMod_List); + _F1_CHECK_EXP(decode_drbs_setupmod(&ie->value.choice.DRBs_SetupMod_List, &out->drbs_len, &out->drbs)); + break; + case F1AP_ProtocolIE_ID_id_SRBs_SetupMod_List: + _F1_EQ_CHECK_INT(ie->value.present, F1AP_UEContextModificationResponseIEs__value_PR_SRBs_SetupMod_List); + _F1_CHECK_EXP(decode_srbs_setupmod(&ie->value.choice.SRBs_SetupMod_List, &out->srbs_len, &out->srbs)); + break; + default: + PRINT_ERROR("F1AP_ProtocolIE_ID_id %ld unknown, skipping\n", ie->id); + break; + } + } + + return true; +} + +/** + * @brief F1 UE Context modification Response deep copy + */ +f1ap_ue_context_mod_resp_t cp_ue_context_mod_resp(const f1ap_ue_context_mod_resp_t *orig) +{ + f1ap_ue_context_mod_resp_t cp = { + .gNB_CU_ue_id = orig->gNB_CU_ue_id, + .gNB_DU_ue_id = orig->gNB_DU_ue_id, + // du_to_cu_rrc_info + .drbs_len = orig->drbs_len, + // drbs below + .srbs_len = orig->srbs_len, + // srbs below + }; + + if (orig->du_to_cu_rrc_info) { + f1ap_du_to_cu_rrc_info_t du2cu = cp_du_to_cu_rrc_info(orig->du_to_cu_rrc_info); + _F1_MALLOC(cp.du_to_cu_rrc_info, du2cu); + } + + if (orig->drbs_len > 0) { + DevAssert(orig->drbs); + cp.drbs = calloc_or_fail(orig->drbs_len, sizeof(*cp.drbs)); + cp.drbs_len = orig->drbs_len; + for (int i = 0; i < cp.drbs_len; ++i) + cp.drbs[i] = cp_drb_setup(&orig->drbs[i]); + } + + if (orig->srbs_len > 0) { + DevAssert(orig->srbs); + cp.srbs = calloc_or_fail(orig->srbs_len, sizeof(*cp.srbs)); + cp.srbs_len = orig->srbs_len; + for (int i = 0; i < cp.srbs_len; ++i) + cp.srbs[i] = cp_srb_setup(&orig->srbs[i]); + } + + return cp; +} + +/** + * @brief F1 UE Context modification Response equality check + */ +bool eq_ue_context_mod_resp(const f1ap_ue_context_mod_resp_t *a, const f1ap_ue_context_mod_resp_t *b) +{ + _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_OPTIONAL_IE(a, b, du_to_cu_rrc_info, eq_du_to_cu_rrc_info); + _F1_CHECK_EXP((a->du_to_cu_rrc_info && b->du_to_cu_rrc_info) || (!a->du_to_cu_rrc_info && !b->du_to_cu_rrc_info)); + _F1_CHECK_EXP(!a->du_to_cu_rrc_info || eq_du_to_cu_rrc_info(a->du_to_cu_rrc_info, b->du_to_cu_rrc_info)); + + _F1_CHECK_EXP(a->drbs_len == 0 || (a->drbs && b->drbs)); + for (int i = 0; i < a->drbs_len; ++i) + _F1_CHECK_EXP(eq_drb_setup(&a->drbs[i], &b->drbs[i])); + + _F1_EQ_CHECK_INT(a->srbs_len, b->srbs_len); + _F1_CHECK_EXP(a->srbs_len == 0 || (a->srbs && b->srbs)); + for (int i = 0; i < a->srbs_len; ++i) + _F1_CHECK_EXP(eq_srb_setup(&a->srbs[i], &b->srbs[i])); + + return true; +} + +/** + * @brief Free Allocated F1 UE Context modification Response + */ +void free_ue_context_mod_resp(f1ap_ue_context_mod_resp_t *resp) +{ + if (resp->du_to_cu_rrc_info) + free_du_to_cu_rrc_info(resp->du_to_cu_rrc_info); + free(resp->du_to_cu_rrc_info); + for (int i = 0; i < resp->drbs_len; ++i) + free_drb_setup(&resp->drbs[i]); + free(resp->drbs); + for (int i = 0; i < resp->srbs_len; ++i) + free_srb_setup(&resp->srbs[i]); + free(resp->srbs); +} + +/* + * @brief Encode F1 UE context release request to ASN.1 + */ +struct F1AP_F1AP_PDU *encode_ue_context_rel_req(const f1ap_ue_context_rel_req_t *msg) +{ + F1AP_F1AP_PDU_t *pdu = calloc_or_fail(1, sizeof(*pdu)); + + /* Message Type */ + pdu->present = F1AP_F1AP_PDU_PR_initiatingMessage; + asn1cCalloc(pdu->choice.initiatingMessage, tmp); + tmp->procedureCode = F1AP_ProcedureCode_id_UEContextReleaseRequest; + tmp->criticality = F1AP_Criticality_reject; + tmp->value.present = F1AP_InitiatingMessage__value_PR_UEContextReleaseRequest; + F1AP_UEContextReleaseRequest_t *out = &tmp->value.choice.UEContextReleaseRequest; + + /* mandatory: GNB_CU_UE_F1AP_ID */ + asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextReleaseRequestIEs_t, ie1); + ie1->id = F1AP_ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID; + ie1->criticality = F1AP_Criticality_reject; + ie1->value.present = F1AP_UEContextReleaseRequestIEs__value_PR_GNB_CU_UE_F1AP_ID; + ie1->value.choice.GNB_CU_UE_F1AP_ID = msg->gNB_CU_ue_id; + + /* mandatory: GNB_DU_UE_F1AP_ID */ + asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextReleaseRequestIEs_t, ie2); + ie2->id = F1AP_ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID; + ie2->criticality = F1AP_Criticality_reject; + ie2->value.present = F1AP_UEContextReleaseRequestIEs__value_PR_GNB_DU_UE_F1AP_ID; + ie2->value.choice.GNB_DU_UE_F1AP_ID = msg->gNB_DU_ue_id; + + /* mandatory: Cause */ + asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextReleaseRequestIEs_t, ie3); + ie3->id = F1AP_ProtocolIE_ID_id_Cause; + ie3->criticality = F1AP_Criticality_ignore; + ie3->value.present = F1AP_UEContextReleaseRequestIEs__value_PR_Cause; + ie3->value.choice.Cause = encode_f1ap_cause(msg->cause, msg->cause_value); + + return pdu; +} + +/** + * @brief Decode F1 UE Context Release Request + */ +bool decode_ue_context_rel_req(const struct F1AP_F1AP_PDU *pdu, f1ap_ue_context_rel_req_t *out) +{ + DevAssert(out != NULL); + memset(out, 0, sizeof(*out)); + + F1AP_UEContextReleaseRequest_t *in = &pdu->choice.initiatingMessage->value.choice.UEContextReleaseRequest; + F1AP_UEContextReleaseRequestIEs_t *ie; + F1AP_LIB_FIND_IE(F1AP_UEContextReleaseRequestIEs_t, ie, &in->protocolIEs.list, F1AP_ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID, true); + F1AP_LIB_FIND_IE(F1AP_UEContextReleaseRequestIEs_t, ie, &in->protocolIEs.list, F1AP_ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID, true); + F1AP_LIB_FIND_IE(F1AP_UEContextReleaseRequestIEs_t, ie, &in->protocolIEs.list, F1AP_ProtocolIE_ID_id_Cause, true); + + for (int i = 0; i < in->protocolIEs.list.count; ++i) { + ie = in->protocolIEs.list.array[i]; + AssertError(ie != NULL, return false, "in->protocolIEs.list.array[i] is NULL"); + switch (ie->id) { + case F1AP_ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID: + _F1_EQ_CHECK_INT(ie->value.present, F1AP_UEContextReleaseRequestIEs__value_PR_GNB_CU_UE_F1AP_ID); + out->gNB_CU_ue_id = ie->value.choice.GNB_CU_UE_F1AP_ID; + break; + case F1AP_ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID: + _F1_EQ_CHECK_INT(ie->value.present, F1AP_UEContextReleaseRequestIEs__value_PR_GNB_DU_UE_F1AP_ID); + out->gNB_DU_ue_id = ie->value.choice.GNB_DU_UE_F1AP_ID; + break; + case F1AP_ProtocolIE_ID_id_Cause: + _F1_EQ_CHECK_INT(ie->value.present, F1AP_UEContextReleaseRequestIEs__value_PR_Cause); + _F1_CHECK_EXP(decode_f1ap_cause(ie->value.choice.Cause, &out->cause, &out->cause_value)); + break; + default: + PRINT_ERROR("F1AP_ProtocolIE_ID_id %ld unknown, skipping\n", ie->id); + break; + } + } + + return true; +} + +/** + * @brief F1 UE Context Release Request deep copy + */ +f1ap_ue_context_rel_req_t cp_ue_context_rel_req(const f1ap_ue_context_rel_req_t *orig) +{ + f1ap_ue_context_rel_req_t cp = { + .gNB_CU_ue_id = orig->gNB_CU_ue_id, + .gNB_DU_ue_id = orig->gNB_DU_ue_id, + .cause = orig->cause, + .cause_value = orig->cause_value, + }; + return cp; +} + +/** + * @brief F1 UE Context Release Request equality check + */ +bool eq_ue_context_rel_req(const f1ap_ue_context_rel_req_t *a, const f1ap_ue_context_rel_req_t *b) +{ + _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->cause, b->cause); + _F1_EQ_CHECK_LONG(a->cause_value, b->cause_value); + return true; +} + +/** + * @brief Free Allocated F1 UE Context Release Request + */ +void free_ue_context_rel_req(f1ap_ue_context_rel_req_t *req) +{ + // nothing to free +} + +/* + * @brief Encode F1 UE context release command to ASN.1 + */ +struct F1AP_F1AP_PDU *encode_ue_context_rel_cmd(const f1ap_ue_context_rel_cmd_t *cmd) +{ + F1AP_F1AP_PDU_t *pdu = calloc_or_fail(1, sizeof(*pdu)); + + /* Message Type */ + pdu->present = F1AP_F1AP_PDU_PR_initiatingMessage; + asn1cCalloc(pdu->choice.initiatingMessage, tmp); + tmp->procedureCode = F1AP_ProcedureCode_id_UEContextRelease; + tmp->criticality = F1AP_Criticality_reject; + tmp->value.present = F1AP_InitiatingMessage__value_PR_UEContextReleaseCommand; + F1AP_UEContextReleaseCommand_t *out = &tmp->value.choice.UEContextReleaseCommand; + + /* mandatory: GNB_CU_UE_F1AP_ID */ + asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextReleaseCommandIEs_t, ie1); + ie1->id = F1AP_ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID; + ie1->criticality = F1AP_Criticality_reject; + ie1->value.present = F1AP_UEContextReleaseCommandIEs__value_PR_GNB_CU_UE_F1AP_ID; + ie1->value.choice.GNB_CU_UE_F1AP_ID = cmd->gNB_CU_ue_id; + + /* mandatory: GNB_DU_UE_F1AP_ID */ + asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextReleaseCommandIEs_t, ie2); + ie2->id = F1AP_ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID; + ie2->criticality = F1AP_Criticality_reject; + ie2->value.present = F1AP_UEContextReleaseCommandIEs__value_PR_GNB_DU_UE_F1AP_ID; + ie2->value.choice.GNB_DU_UE_F1AP_ID = cmd->gNB_DU_ue_id; + + /* mandatory: Cause */ + asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextReleaseCommandIEs_t, ie3); + ie3->id = F1AP_ProtocolIE_ID_id_Cause; + ie3->criticality = F1AP_Criticality_ignore; + ie3->value.present = F1AP_UEContextReleaseCommandIEs__value_PR_Cause; + ie3->value.choice.Cause = encode_f1ap_cause(cmd->cause, cmd->cause_value); + + /* optional: RRC Container */ + if (cmd->rrc_container != NULL) { + asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextReleaseCommandIEs_t, ie4); + ie4->id = F1AP_ProtocolIE_ID_id_RRCContainer; + ie4->criticality = F1AP_Criticality_ignore; + ie4->value.present = F1AP_UEContextReleaseCommandIEs__value_PR_RRCContainer; + const byte_array_t *ba = cmd->rrc_container; + OCTET_STRING_fromBuf(&ie4->value.choice.RRCContainer, (const char *)ba->buf, ba->len); + + // conditionally have SRBID if RRC Container + AssertFatal(cmd->srb_id != NULL, "UEContextReleaseCommand SRB-ID C-ifRRCContainer violated\n"); + asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextReleaseCommandIEs_t, ie5); + ie5->id = F1AP_ProtocolIE_ID_id_SRBID; + ie5->criticality = F1AP_Criticality_ignore; + ie5->value.present = F1AP_UEContextReleaseCommandIEs__value_PR_SRBID; + ie5->value.choice.SRBID = *cmd->srb_id; + } + + if (cmd->old_gNB_DU_ue_id != NULL) { + asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextReleaseCommandIEs_t, ie5); + ie5->id = F1AP_ProtocolIE_ID_id_oldgNB_DU_UE_F1AP_ID; + ie5->criticality = F1AP_Criticality_ignore; + ie5->value.present = F1AP_UEContextReleaseCommandIEs__value_PR_GNB_DU_UE_F1AP_ID_1; + ie5->value.choice.GNB_DU_UE_F1AP_ID_1 = *cmd->old_gNB_DU_ue_id; + } + + return pdu; +} + +/** + * @brief Decode F1 UE Context Release Command + */ +bool decode_ue_context_rel_cmd(const struct F1AP_F1AP_PDU *pdu, f1ap_ue_context_rel_cmd_t *out) +{ + DevAssert(out != NULL); + memset(out, 0, sizeof(*out)); + + F1AP_UEContextReleaseCommand_t *in = &pdu->choice.initiatingMessage->value.choice.UEContextReleaseCommand; + F1AP_UEContextReleaseCommandIEs_t *ie; + F1AP_LIB_FIND_IE(F1AP_UEContextReleaseCommandIEs_t, ie, &in->protocolIEs.list, F1AP_ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID, true); + F1AP_LIB_FIND_IE(F1AP_UEContextReleaseCommandIEs_t, ie, &in->protocolIEs.list, F1AP_ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID, true); + F1AP_LIB_FIND_IE(F1AP_UEContextReleaseCommandIEs_t, ie, &in->protocolIEs.list, F1AP_ProtocolIE_ID_id_Cause, true); + + for (int i = 0; i < in->protocolIEs.list.count; ++i) { + ie = in->protocolIEs.list.array[i]; + AssertError(ie != NULL, return false, "in->protocolIEs.list.array[i] is NULL"); + switch (ie->id) { + case F1AP_ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID: + _F1_EQ_CHECK_INT(ie->value.present, F1AP_UEContextReleaseCommandIEs__value_PR_GNB_CU_UE_F1AP_ID); + out->gNB_CU_ue_id = ie->value.choice.GNB_CU_UE_F1AP_ID; + break; + case F1AP_ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID: + _F1_EQ_CHECK_INT(ie->value.present, F1AP_UEContextReleaseCommandIEs__value_PR_GNB_DU_UE_F1AP_ID); + out->gNB_DU_ue_id = ie->value.choice.GNB_DU_UE_F1AP_ID; + break; + case F1AP_ProtocolIE_ID_id_Cause: + _F1_EQ_CHECK_INT(ie->value.present, F1AP_UEContextReleaseCommandIEs__value_PR_Cause); + _F1_CHECK_EXP(decode_f1ap_cause(ie->value.choice.Cause, &out->cause, &out->cause_value)); + break; + case F1AP_ProtocolIE_ID_id_RRCContainer: + _F1_EQ_CHECK_INT(ie->value.present, F1AP_UEContextReleaseCommandIEs__value_PR_RRCContainer); + out->rrc_container = malloc_or_fail(sizeof(*out->rrc_container)); + { + OCTET_STRING_t *os = &ie->value.choice.RRCContainer; + *out->rrc_container = create_byte_array(os->size, os->buf); + } + break; + case F1AP_ProtocolIE_ID_id_SRBID: + _F1_EQ_CHECK_INT(ie->value.present, F1AP_UEContextReleaseCommandIEs__value_PR_SRBID); + { + // SRB-ID + F1AP_UEContextReleaseCommandIEs_t *check_ie; + F1AP_LIB_FIND_IE(F1AP_UEContextReleaseCommandIEs_t, check_ie, &in->protocolIEs.list, F1AP_ProtocolIE_ID_id_RRCContainer, true); + } + _F1_MALLOC(out->srb_id, ie->value.choice.SRBID); + break; + case F1AP_ProtocolIE_ID_id_oldgNB_DU_UE_F1AP_ID: + _F1_EQ_CHECK_INT(ie->value.present, F1AP_UEContextReleaseCommandIEs__value_PR_GNB_DU_UE_F1AP_ID_1); + _F1_MALLOC(out->old_gNB_DU_ue_id, ie->value.choice.GNB_DU_UE_F1AP_ID_1); + break; + default: + PRINT_ERROR("F1AP_ProtocolIE_ID_id %ld unknown, skipping\n", ie->id); + break; + } + } + + return true; +} + +/** + * @brief F1 UE Context Release Command deep copy + */ +f1ap_ue_context_rel_cmd_t cp_ue_context_rel_cmd(const f1ap_ue_context_rel_cmd_t *orig) +{ + f1ap_ue_context_rel_cmd_t cp = { + .gNB_CU_ue_id = orig->gNB_CU_ue_id, + .gNB_DU_ue_id = orig->gNB_DU_ue_id, + .cause = orig->cause, + .cause_value = orig->cause_value, + }; + CP_OPT_BYTE_ARRAY(cp.rrc_container, orig->rrc_container); + if (orig->rrc_container) { + AssertFatal(orig->srb_id != NULL, "UEContextReleaseCommand SRB-ID C-ifRRCContainer violated\n"); + _F1_MALLOC(cp.srb_id, *orig->srb_id); + } + if (orig->old_gNB_DU_ue_id) + _F1_MALLOC(cp.old_gNB_DU_ue_id, *orig->old_gNB_DU_ue_id); + return cp; +} + +/** + * @brief F1 UE Context Release Command equality check + */ +bool eq_ue_context_rel_cmd(const f1ap_ue_context_rel_cmd_t *a, const f1ap_ue_context_rel_cmd_t *b) +{ + _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->cause, b->cause); + _F1_EQ_CHECK_LONG(a->cause_value, b->cause_value); + _F1_EQ_CHECK_OPTIONAL_IE(a, b, rrc_container, eq_ba); + _F1_EQ_CHECK_OPTIONAL_IE(a, b, srb_id, _F1_EQ_CHECK_INT); + _F1_EQ_CHECK_OPTIONAL_IE(a, b, old_gNB_DU_ue_id, _F1_EQ_CHECK_INT); + return true; +} + +/** + * @brief Free Allocated F1 UE Context Release Command + */ +void free_ue_context_rel_cmd(f1ap_ue_context_rel_cmd_t *cmd) +{ + FREE_OPT_BYTE_ARRAY(cmd->rrc_container); + free(cmd->srb_id); + free(cmd->old_gNB_DU_ue_id); +} + +/* + * @brief Encode F1 UE context release complete to ASN.1 + */ +struct F1AP_F1AP_PDU *encode_ue_context_rel_cplt(const f1ap_ue_context_rel_cplt_t *cplt) +{ + F1AP_F1AP_PDU_t *pdu = calloc_or_fail(1, sizeof(*pdu)); + + /* Message Type */ + pdu->present = F1AP_F1AP_PDU_PR_successfulOutcome; + asn1cCalloc(pdu->choice.successfulOutcome, tmp); + tmp->procedureCode = F1AP_ProcedureCode_id_UEContextRelease; + tmp->criticality = F1AP_Criticality_reject; + tmp->value.present = F1AP_SuccessfulOutcome__value_PR_UEContextReleaseComplete; + F1AP_UEContextReleaseComplete_t *out = &tmp->value.choice.UEContextReleaseComplete; + + /* mandatory: GNB_CU_UE_F1AP_ID */ + asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextReleaseCompleteIEs_t, ie1); + ie1->id = F1AP_ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID; + ie1->criticality = F1AP_Criticality_reject; + ie1->value.present = F1AP_UEContextReleaseCompleteIEs__value_PR_GNB_CU_UE_F1AP_ID; + ie1->value.choice.GNB_CU_UE_F1AP_ID = cplt->gNB_CU_ue_id; + + /* mandatory: GNB_DU_UE_F1AP_ID */ + asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextReleaseCompleteIEs_t, ie2); + ie2->id = F1AP_ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID; + ie2->criticality = F1AP_Criticality_reject; + ie2->value.present = F1AP_UEContextReleaseCompleteIEs__value_PR_GNB_DU_UE_F1AP_ID; + ie2->value.choice.GNB_DU_UE_F1AP_ID = cplt->gNB_DU_ue_id; + + return pdu; +} + +/** + * @brief Decode F1 UE Context Release Complete + */ +bool decode_ue_context_rel_cplt(const struct F1AP_F1AP_PDU *pdu, f1ap_ue_context_rel_cplt_t *out) +{ + DevAssert(out != NULL); + memset(out, 0, sizeof(*out)); + + F1AP_UEContextReleaseComplete_t *in = &pdu->choice.successfulOutcome->value.choice.UEContextReleaseComplete; + F1AP_UEContextReleaseCompleteIEs_t *ie; + F1AP_LIB_FIND_IE(F1AP_UEContextReleaseCompleteIEs_t, ie, &in->protocolIEs.list, F1AP_ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID, true); + F1AP_LIB_FIND_IE(F1AP_UEContextReleaseCompleteIEs_t, ie, &in->protocolIEs.list, F1AP_ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID, true); + + for (int i = 0; i < in->protocolIEs.list.count; ++i) { + ie = in->protocolIEs.list.array[i]; + AssertError(ie != NULL, return false, "in->protocolIEs.list.array[i] is NULL"); + switch (ie->id) { + case F1AP_ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID: + _F1_EQ_CHECK_INT(ie->value.present, F1AP_UEContextReleaseCompleteIEs__value_PR_GNB_CU_UE_F1AP_ID); + out->gNB_CU_ue_id = ie->value.choice.GNB_CU_UE_F1AP_ID; + break; + case F1AP_ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID: + _F1_EQ_CHECK_INT(ie->value.present, F1AP_UEContextReleaseCompleteIEs__value_PR_GNB_DU_UE_F1AP_ID); + out->gNB_DU_ue_id = ie->value.choice.GNB_DU_UE_F1AP_ID; + break; + default: + PRINT_ERROR("F1AP_ProtocolIE_ID_id %ld unknown, skipping\n", ie->id); + break; + } + } + + return true; +} + +/** + * @brief F1 UE Context Release Complete deep copy + */ +f1ap_ue_context_rel_cplt_t cp_ue_context_rel_cplt(const f1ap_ue_context_rel_cplt_t *orig) +{ + f1ap_ue_context_rel_cplt_t cp = { + .gNB_CU_ue_id = orig->gNB_CU_ue_id, + .gNB_DU_ue_id = orig->gNB_DU_ue_id, + }; + return cp; +} + +/** + * @brief F1 UE Context Release Complete equality check + */ +bool eq_ue_context_rel_cplt(const f1ap_ue_context_rel_cplt_t *a, const f1ap_ue_context_rel_cplt_t *b) +{ + _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); + return true; +} + +/** + * @brief Free Allocated F1 UE Context Release Complete + */ +void free_ue_context_rel_cplt(f1ap_ue_context_rel_cplt_t *cplt) +{ + // nothing to free +} diff --git a/openair2/F1AP/lib/f1ap_ue_context.h b/openair2/F1AP/lib/f1ap_ue_context.h new file mode 100644 index 0000000000..0e82e82a85 --- /dev/null +++ b/openair2/F1AP/lib/f1ap_ue_context.h @@ -0,0 +1,72 @@ +/* + * 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_UE_CONTEXT_SETUP_REQ_H_ +#define F1AP_UE_CONTEXT_SETUP_REQ_H_ + +#include +#include "f1ap_messages_types.h" + +struct F1AP_F1AP_PDU; + +struct F1AP_F1AP_PDU *encode_ue_context_setup_req(const f1ap_ue_context_setup_req_t *msg); +bool decode_ue_context_setup_req(const struct F1AP_F1AP_PDU *pdu, f1ap_ue_context_setup_req_t *out); +f1ap_ue_context_setup_req_t cp_ue_context_setup_req(const f1ap_ue_context_setup_req_t *orig); +bool eq_ue_context_setup_req(const f1ap_ue_context_setup_req_t *a, const f1ap_ue_context_setup_req_t *b); +void free_ue_context_setup_req(f1ap_ue_context_setup_req_t *req); + +struct F1AP_F1AP_PDU *encode_ue_context_setup_resp(const f1ap_ue_context_setup_resp_t *msg); +bool decode_ue_context_setup_resp(const struct F1AP_F1AP_PDU *pdu, f1ap_ue_context_setup_resp_t *out); +f1ap_ue_context_setup_resp_t cp_ue_context_setup_resp(const f1ap_ue_context_setup_resp_t *orig); +bool eq_ue_context_setup_resp(const f1ap_ue_context_setup_resp_t *a, const f1ap_ue_context_setup_resp_t *b); +void free_ue_context_setup_resp(f1ap_ue_context_setup_resp_t *resp); + +struct F1AP_F1AP_PDU *encode_ue_context_mod_req(const f1ap_ue_context_mod_req_t *msg); +bool decode_ue_context_mod_req(const struct F1AP_F1AP_PDU *pdu, f1ap_ue_context_mod_req_t *out); +f1ap_ue_context_mod_req_t cp_ue_context_mod_req(const f1ap_ue_context_mod_req_t *orig); +bool eq_ue_context_mod_req(const f1ap_ue_context_mod_req_t *a, const f1ap_ue_context_mod_req_t *b); +void free_ue_context_mod_req(f1ap_ue_context_mod_req_t *req); + +struct F1AP_F1AP_PDU *encode_ue_context_mod_resp(const f1ap_ue_context_mod_resp_t *msg); +bool decode_ue_context_mod_resp(const struct F1AP_F1AP_PDU *pdu, f1ap_ue_context_mod_resp_t *out); +f1ap_ue_context_mod_resp_t cp_ue_context_mod_resp(const f1ap_ue_context_mod_resp_t *orig); +bool eq_ue_context_mod_resp(const f1ap_ue_context_mod_resp_t *a, const f1ap_ue_context_mod_resp_t *b); +void free_ue_context_mod_resp(f1ap_ue_context_mod_resp_t *resp); + +struct F1AP_F1AP_PDU *encode_ue_context_rel_req(const f1ap_ue_context_rel_req_t *msg); +bool decode_ue_context_rel_req(const struct F1AP_F1AP_PDU *pdu, f1ap_ue_context_rel_req_t *out); +f1ap_ue_context_rel_req_t cp_ue_context_rel_req(const f1ap_ue_context_rel_req_t *orig); +bool eq_ue_context_rel_req(const f1ap_ue_context_rel_req_t *a, const f1ap_ue_context_rel_req_t *b); +void free_ue_context_rel_req(f1ap_ue_context_rel_req_t *req); + +struct F1AP_F1AP_PDU *encode_ue_context_rel_cmd(const f1ap_ue_context_rel_cmd_t *msg); +bool decode_ue_context_rel_cmd(const struct F1AP_F1AP_PDU *pdu, f1ap_ue_context_rel_cmd_t *out); +f1ap_ue_context_rel_cmd_t cp_ue_context_rel_cmd(const f1ap_ue_context_rel_cmd_t *orig); +bool eq_ue_context_rel_cmd(const f1ap_ue_context_rel_cmd_t *a, const f1ap_ue_context_rel_cmd_t *b); +void free_ue_context_rel_cmd(f1ap_ue_context_rel_cmd_t *cmd); + +struct F1AP_F1AP_PDU *encode_ue_context_rel_cplt(const f1ap_ue_context_rel_cplt_t *msg); +bool decode_ue_context_rel_cplt(const struct F1AP_F1AP_PDU *pdu, f1ap_ue_context_rel_cplt_t *out); +f1ap_ue_context_rel_cplt_t cp_ue_context_rel_cplt(const f1ap_ue_context_rel_cplt_t *orig); +bool eq_ue_context_rel_cplt(const f1ap_ue_context_rel_cplt_t *a, const f1ap_ue_context_rel_cplt_t *b); +void free_ue_context_rel_cplt(f1ap_ue_context_rel_cplt_t *cplt); + +#endif /* F1AP_UE_CONTEXT_SETUP_REQ_H_ */ diff --git a/openair2/F1AP/tests/CMakeLists.txt b/openair2/F1AP/tests/CMakeLists.txt index a73334051a..396e86d513 100644 --- a/openair2/F1AP/tests/CMakeLists.txt +++ b/openair2/F1AP/tests/CMakeLists.txt @@ -1,6 +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 f1ap_lib ds) 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 index cbb5955fe9..ebf90fc648 100644 --- a/openair2/F1AP/tests/f1ap_lib_test.c +++ b/openair2/F1AP/tests/f1ap_lib_test.c @@ -31,6 +31,7 @@ #include #include #include +#include #include "common/utils/assertions.h" #include "common/utils/utils.h" @@ -38,8 +39,10 @@ #include "f1ap_messages_types.h" #include "F1AP_F1AP-PDU.h" -#include "f1ap_lib_extern.h" +#include "lib/f1ap_lib_common.h" +#include "lib/f1ap_rrc_message_transfer.h" #include "lib/f1ap_interface_management.h" +#include "lib/f1ap_ue_context.h" void exit_function(const char *file, const char *function, const int line, const char *s, const int assert) { @@ -718,6 +721,551 @@ static void test_f1ap_cu_configuration_update_acknowledge(void) // No free needed } +static byte_array_t get_test_ba(const char *s) +{ + byte_array_t ba = { + .len = strlen(s) + 1, /* binary data: needs to include null-byte of strdup() */ + .buf = (uint8_t *) strdup(s), + }; + return ba; +} + +static byte_array_t *get_malloced_test_ba(const char *s) +{ + byte_array_t *ba = calloc_or_fail(1, sizeof(*ba)); + *ba = get_test_ba(s); + return ba; +} + +static void test_f1ap_ue_context_setup_request() +{ + plmn_id_t plmn = { .mcc = 001, .mnc = 01, .mnc_digit_length = 2 }; + f1ap_ue_context_setup_req_t orig = { + .gNB_CU_ue_id = 12, + //.gNB_DU_ue_id below + .plmn = plmn, + .nr_cellid = 132, + .servCellIndex = 1, + //.cu_to_du_rrc_info below + //.srbs below + //.drbs below + //gnb_du_ue_agg_mbr_ul below + }; + _F1_MALLOC(orig.gNB_DU_ue_id, 13); + orig.cu_to_du_rrc_info.cg_configinfo = get_malloced_test_ba("CG-CONFIGINFO"); + orig.cu_to_du_rrc_info.ue_cap = get_malloced_test_ba("UE CAP"); + orig.cu_to_du_rrc_info.meas_config = get_malloced_test_ba("UE MEASUREMENT CONFIGURATION"); + orig.cu_to_du_rrc_info.ho_prep_info = get_malloced_test_ba("PREPARATION DATA FOR HANDOVER"); + orig.srbs_len = 2; + orig.srbs = calloc_or_fail(orig.srbs_len, sizeof(*orig.srbs)); + for (int i = 0; i < orig.srbs_len; ++i) + orig.srbs[i].id = 1 + i; + + orig.drbs_len = 2; + orig.drbs = calloc_or_fail(orig.drbs_len, sizeof(*orig.drbs)); + f1ap_drb_to_setup_t *drb1 = &orig.drbs[0]; + drb1->id = 4; + drb1->qos_choice = F1AP_QOS_CHOICE_NR; + f1ap_arp_t arp = { 1, MAY_TRIGGER_PREEMPTION, PREEMPTABLE, }; + drb1->nr.drb_qos.qos_type = NON_DYNAMIC; + drb1->nr.drb_qos.nondyn.fiveQI = 3; + drb1->nr.drb_qos.arp = arp; + drb1->nr.nssai = (nssai_t) {.sst = 1, .sd = 123}; + drb1->nr.flows_len = 1; + f1ap_drb_flows_mapped_t *flow = drb1->nr.flows = calloc_or_fail(drb1->nr.flows_len, sizeof(*flow)); + flow->qfi = 2; + flow->param.qos_type = NON_DYNAMIC; + flow->param.nondyn.fiveQI = 3; + flow->param.arp = arp; + drb1->up_ul_tnl_len = 1; + inet_pton(AF_INET, "192.168.40.23", &drb1->up_ul_tnl[0].tl_address); + drb1->up_ul_tnl[0].teid = 0x11223344; + drb1->rlc_mode = F1AP_RLC_MODE_UM_BIDIR; + _F1_MALLOC(drb1->dl_pdcp_sn_len, F1AP_PDCP_SN_18B); + _F1_MALLOC(drb1->ul_pdcp_sn_len, F1AP_PDCP_SN_18B); + + f1ap_drb_to_setup_t *drb2 = &orig.drbs[1]; + drb2->id = 12; + drb2->qos_choice = F1AP_QOS_CHOICE_NR; + drb2->nr.drb_qos.qos_type = DYNAMIC; + f1ap_dynamic_5qi_t *dyn = &drb2->nr.drb_qos.dyn; + dyn->prio = 4; + dyn->pdb = 1000; + dyn->per.scalar = 4; + dyn->per.exponent = 8; + _F1_MALLOC(dyn->delay_critical, true); + _F1_MALLOC(dyn->avg_win, 3000); + f1ap_arp_t arp2 = { 13, SHALL_NOT_TRIGGER_PREEMPTION, NOT_PREEMPTABLE, }; + drb2->nr.drb_qos.arp = arp2; + drb2->nr.nssai = (nssai_t) {.sst = 2, .sd = 0xffffff}; + drb2->nr.flows_len = 2; + f1ap_drb_flows_mapped_t *flow2 = drb2->nr.flows = calloc_or_fail(drb2->nr.flows_len, sizeof(*flow2)); + flow2[0].qfi = 4; + flow2[0].param.qos_type = DYNAMIC; + flow2[0].param.dyn.prio = 4; + flow2[0].param.dyn.pdb = 999; + flow2[0].param.dyn.per.scalar = 4; + flow2[0].param.dyn.per.exponent = 8; + flow2[0].param.arp = arp2; + flow2[1].qfi = 5; + flow2[1].param.qos_type = NON_DYNAMIC; + flow2[1].param.nondyn.fiveQI = 3; + flow2[1].param.arp = arp; + drb2->up_ul_tnl_len = 2; + inet_pton(AF_INET, "10.0.0.2", &drb2->up_ul_tnl[0].tl_address); + drb2->up_ul_tnl[0].teid = 0x1234; + inet_pton(AF_INET, "10.0.0.2", &drb2->up_ul_tnl[1].tl_address); + drb2->up_ul_tnl[1].teid = 0x1235; + drb2->rlc_mode = F1AP_RLC_MODE_AM; + _F1_MALLOC(drb2->dl_pdcp_sn_len, F1AP_PDCP_SN_12B); + _F1_MALLOC(drb2->ul_pdcp_sn_len, F1AP_PDCP_SN_12B); + + orig.rrc_container = get_malloced_test_ba("RRC container"); + + _F1_MALLOC(orig.gnb_du_ue_agg_mbr_ul, 5LL * 1000 * 1000 * 1000); + + F1AP_F1AP_PDU_t *f1enc = encode_ue_context_setup_req(&orig); + F1AP_F1AP_PDU_t *f1dec = f1ap_encode_decode(f1enc); + f1ap_msg_free(f1enc); + + f1ap_ue_context_setup_req_t decoded = {0}; + bool ret = decode_ue_context_setup_req(f1dec, &decoded); + AssertFatal(ret, "decode_ue_context_setup_req(): could not decode message\n"); + f1ap_msg_free(f1dec); + + ret = eq_ue_context_setup_req(&orig, &decoded); + AssertFatal(ret, "eq_ue_context_setup_req(): decoded message doesn't match\n"); + char ip_ret[100]; + inet_ntop(AF_INET, &decoded.drbs[0].up_ul_tnl[0].tl_address, ip_ret, sizeof(ip_ret)); + printf("%s\n", ip_ret); + inet_ntop(AF_INET, &decoded.drbs[1].up_ul_tnl[0].tl_address, ip_ret, sizeof(ip_ret)); + printf("%s\n", ip_ret); + free_ue_context_setup_req(&decoded); + + f1ap_ue_context_setup_req_t cp = cp_ue_context_setup_req(&orig); + ret = eq_ue_context_setup_req(&orig, &cp); + AssertFatal(ret, "eq_ue_context_setup_req(): copied message doesn't match\n"); + free_ue_context_setup_req(&orig); + free_ue_context_setup_req(&cp); + + printf("%s() successful\n", __func__); +} + +static void test_f1ap_ue_context_setup_request_simple() +{ + plmn_id_t plmn = { .mcc = 001, .mnc = 01, .mnc_digit_length = 2 }; + f1ap_ue_context_setup_req_t orig = { + .gNB_CU_ue_id = 12, + .plmn = plmn, + .nr_cellid = 132, + .servCellIndex = 1, + //.cu_to_du_rrc_info: all fields optional, intentionally left empty + // rest is optional and intentionally left empty + // .gnb_du_ue_agg_mbr_ul is C-ifDRBSetup => no DRB => no IE + }; + F1AP_F1AP_PDU_t *f1enc = encode_ue_context_setup_req(&orig); + F1AP_F1AP_PDU_t *f1dec = f1ap_encode_decode(f1enc); + f1ap_msg_free(f1enc); + + f1ap_ue_context_setup_req_t decoded = {0}; + bool ret = decode_ue_context_setup_req(f1dec, &decoded); + AssertFatal(ret, "decode_ue_context_setup_req(): could not decode message\n"); + f1ap_msg_free(f1dec); + + ret = eq_ue_context_setup_req(&orig, &decoded); + AssertFatal(ret, "eq_ue_context_setup_req(): decoded message doesn't match\n"); + free_ue_context_setup_req(&decoded); + + f1ap_ue_context_setup_req_t cp = cp_ue_context_setup_req(&orig); + ret = eq_ue_context_setup_req(&orig, &cp); + AssertFatal(ret, "eq_ue_context_setup_req(): copied message doesn't match\n"); + free_ue_context_setup_req(&orig); + free_ue_context_setup_req(&cp); + + printf("%s() successful\n", __func__); +} + +static void test_f1ap_ue_context_setup_response() +{ + f1ap_ue_context_setup_resp_t orig = { + .gNB_CU_ue_id = 12, + .gNB_DU_ue_id = 13, + //.du_to_cu_rrc_info below + //.crnti below + //.drbs below + //.srbs below + }; + + orig.du_to_cu_rrc_info.cell_group_config = get_test_ba("CELL GROUP CONFIG"); + orig.du_to_cu_rrc_info.meas_gap_config = get_malloced_test_ba("MGC"); + + _F1_MALLOC(orig.crnti, 0x1234); + + orig.drbs_len = 2; + orig.drbs = calloc_or_fail(orig.drbs_len, sizeof(*orig.drbs)); + f1ap_drb_setup_t *drb1 = &orig.drbs[0]; + drb1->id = 12; + _F1_MALLOC(drb1->lcid, 12); + drb1->up_dl_tnl_len = 2; + inet_pton(AF_INET, "192.168.40.23", &drb1->up_dl_tnl[0].tl_address); + drb1->up_dl_tnl[0].teid = 0x11223344; + inet_pton(AF_INET, "192.168.40.23", &drb1->up_dl_tnl[1].tl_address); + drb1->up_dl_tnl[1].teid = 0x11223345; + f1ap_drb_setup_t *drb2 = &orig.drbs[1]; + drb2->id = 13; + _F1_MALLOC(drb2->lcid, 13); + drb2->up_dl_tnl_len = 2; + inet_pton(AF_INET, "192.168.50.23", &drb2->up_dl_tnl[0].tl_address); + drb2->up_dl_tnl[0].teid = 0x21223354; + inet_pton(AF_INET, "192.168.50.23", &drb2->up_dl_tnl[1].tl_address); + drb2->up_dl_tnl[1].teid = 0x21223355; + + orig.srbs_len = 2; + orig.srbs = calloc_or_fail(orig.srbs_len, sizeof(*orig.srbs)); + for (int i = 0; i < orig.srbs_len; ++i) { + orig.srbs[i].id = 1 + i; + orig.srbs[i].lcid = 1+i+10; + } + + F1AP_F1AP_PDU_t *f1enc = encode_ue_context_setup_resp(&orig); + F1AP_F1AP_PDU_t *f1dec = f1ap_encode_decode(f1enc); + f1ap_msg_free(f1enc); + + f1ap_ue_context_setup_resp_t decoded = {0}; + bool ret = decode_ue_context_setup_resp(f1dec, &decoded); + AssertFatal(ret, "decode_ue_context_setup_resp(): could not decode message\n"); + f1ap_msg_free(f1dec); + + ret = eq_ue_context_setup_resp(&orig, &decoded); + AssertFatal(ret, "eq_ue_context_setup_resp(): decoded message doesn't match\n"); + free_ue_context_setup_resp(&decoded); + + f1ap_ue_context_setup_resp_t cp = cp_ue_context_setup_resp(&orig); + ret = eq_ue_context_setup_resp(&orig, &cp); + AssertFatal(ret, "eq_ue_context_setup_resp(): copied message doesn't match\n"); + free_ue_context_setup_resp(&orig); + free_ue_context_setup_resp(&cp); + + printf("%s() successful\n", __func__); +} + +static void test_f1ap_ue_context_setup_response_simple() +{ + f1ap_ue_context_setup_resp_t orig = { + .gNB_CU_ue_id = 12, + .gNB_DU_ue_id = 13, + .du_to_cu_rrc_info.cell_group_config = get_test_ba("small cg"), + // rest is optional and intentionally left empty + }; + + F1AP_F1AP_PDU_t *f1enc = encode_ue_context_setup_resp(&orig); + F1AP_F1AP_PDU_t *f1dec = f1ap_encode_decode(f1enc); + f1ap_msg_free(f1enc); + + f1ap_ue_context_setup_resp_t decoded = {0}; + bool ret = decode_ue_context_setup_resp(f1dec, &decoded); + AssertFatal(ret, "decode_ue_context_setup_resp(): could not decode message\n"); + f1ap_msg_free(f1dec); + + ret = eq_ue_context_setup_resp(&orig, &decoded); + AssertFatal(ret, "eq_ue_context_setup_resp(): decoded message doesn't match\n"); + free_ue_context_setup_resp(&decoded); + + f1ap_ue_context_setup_resp_t cp = cp_ue_context_setup_resp(&orig); + ret = eq_ue_context_setup_resp(&orig, &cp); + AssertFatal(ret, "eq_ue_context_setup_resp(): copied message doesn't match\n"); + free_ue_context_setup_resp(&orig); + free_ue_context_setup_resp(&cp); + + printf("%s() successful\n", __func__); +} + +static void test_f1ap_ue_context_modification_request() +{ + f1ap_ue_context_mod_req_t orig = { + .gNB_CU_ue_id = 1111, + .gNB_DU_ue_id = 2222, + // rest below + }; + plmn_id_t plmn = { .mcc = 999, .mnc = 101, .mnc_digit_length = 3 }; + _F1_MALLOC(orig.plmn, plmn); + _F1_MALLOC(orig.nr_cellid, 1532); + _F1_MALLOC(orig.servCellIndex, 3); + + f1ap_cu_to_du_rrc_info_t cu2du = { + .cg_configinfo = get_malloced_test_ba("Modified"), + .ue_cap = get_malloced_test_ba("UE forgot to send earlier"), + .meas_config = get_malloced_test_ba("with updates from another cell"), + .ho_prep_info = get_malloced_test_ba("prepare to ho soon!"), + }; + _F1_MALLOC(orig.cu_to_du_rrc_info, cu2du); + + orig.rrc_container = get_malloced_test_ba("important RRC message!!"); + + orig.srbs_len = 1; + orig.srbs = calloc_or_fail(orig.srbs_len, sizeof(*orig.srbs)); + orig.srbs[0].id = 1; + + orig.drbs_len = 1; + orig.drbs = calloc_or_fail(orig.drbs_len, sizeof(*orig.drbs)); + f1ap_drb_to_setup_t *drb1 = &orig.drbs[0]; + drb1->id = 4; + drb1->qos_choice = F1AP_QOS_CHOICE_NR; + f1ap_arp_t arp = { 2, SHALL_NOT_TRIGGER_PREEMPTION, NOT_PREEMPTABLE, }; + drb1->nr.drb_qos.qos_type = NON_DYNAMIC; + drb1->nr.drb_qos.nondyn.fiveQI = 8; + drb1->nr.drb_qos.arp = arp; + drb1->nr.nssai = (nssai_t) {.sst = 2, .sd = 0xffffff}; + drb1->nr.flows_len = 1; + f1ap_drb_flows_mapped_t *flow = drb1->nr.flows = calloc_or_fail(drb1->nr.flows_len, sizeof(*flow)); + flow->qfi = 2; + flow->param.qos_type = NON_DYNAMIC; + flow->param.nondyn.fiveQI = 9; + flow->param.arp = arp; + drb1->up_ul_tnl_len = 1; + inet_pton(AF_INET, "8.8.8.8", &drb1->up_ul_tnl[0].tl_address); + drb1->up_ul_tnl[0].teid = 0x9876541; + drb1->rlc_mode = F1AP_RLC_MODE_AM; + _F1_MALLOC(drb1->dl_pdcp_sn_len, F1AP_PDCP_SN_12B); + _F1_MALLOC(drb1->ul_pdcp_sn_len, F1AP_PDCP_SN_18B); + + orig.drbs_rel_len = 3; + orig.drbs_rel = calloc_or_fail(orig.drbs_rel_len, sizeof(*orig.drbs_rel)); + orig.drbs_rel[0].id = 13; + orig.drbs_rel[1].id = 4; + orig.drbs_rel[2].id = 19; + + _F1_MALLOC(orig.status, LOWER_LAYERS_RESUME); + + F1AP_F1AP_PDU_t *f1enc = encode_ue_context_mod_req(&orig); + F1AP_F1AP_PDU_t *f1dec = f1ap_encode_decode(f1enc); + f1ap_msg_free(f1enc); + + f1ap_ue_context_mod_req_t decoded = {0}; + bool ret = decode_ue_context_mod_req(f1dec, &decoded); + AssertFatal(ret, "decode_ue_context_mod_req(): could not decode message\n"); + f1ap_msg_free(f1dec); + + ret = eq_ue_context_mod_req(&orig, &decoded); + AssertFatal(ret, "eq_ue_context_mod_req(): decoded message doesn't match\n"); + free_ue_context_mod_req(&decoded); + + f1ap_ue_context_mod_req_t cp = cp_ue_context_mod_req(&orig); + ret = eq_ue_context_mod_req(&orig, &cp); + AssertFatal(ret, "eq_ue_context_mod_req(): copied message doesn't match\n"); + free_ue_context_mod_req(&orig); + free_ue_context_mod_req(&cp); + + printf("%s() successful\n", __func__); +} + +static void test_f1ap_ue_context_modification_request_simple() +{ + f1ap_ue_context_mod_req_t orig = { + .gNB_CU_ue_id = 1111, + .gNB_DU_ue_id = 2222, + // rest is optional and intentionally left out + }; + + F1AP_F1AP_PDU_t *f1enc = encode_ue_context_mod_req(&orig); + F1AP_F1AP_PDU_t *f1dec = f1ap_encode_decode(f1enc); + f1ap_msg_free(f1enc); + + f1ap_ue_context_mod_req_t decoded = {0}; + bool ret = decode_ue_context_mod_req(f1dec, &decoded); + AssertFatal(ret, "decode_ue_context_mod_req(): could not decode message\n"); + f1ap_msg_free(f1dec); + + ret = eq_ue_context_mod_req(&orig, &decoded); + AssertFatal(ret, "eq_ue_context_mod_req(): decoded message doesn't match\n"); + free_ue_context_mod_req(&decoded); + + f1ap_ue_context_mod_req_t cp = cp_ue_context_mod_req(&orig); + ret = eq_ue_context_mod_req(&orig, &cp); + AssertFatal(ret, "eq_ue_context_mod_req(): copied message doesn't match\n"); + free_ue_context_mod_req(&orig); + free_ue_context_mod_req(&cp); + + printf("%s() successful\n", __func__); +} + +static void test_f1ap_ue_context_modification_response() +{ + f1ap_ue_context_mod_resp_t orig = { + .gNB_CU_ue_id = 9876, + .gNB_DU_ue_id = 5432, + // rest below + }; + + f1ap_du_to_cu_rrc_info_t cu2du = { + .cell_group_config = get_test_ba("update for the cellgroupconfig, extra long"), + .meas_gap_config = get_malloced_test_ba("new and shiny MeAs GaP cOnFiG"), + }; + _F1_MALLOC(orig.du_to_cu_rrc_info, cu2du); + + orig.drbs_len = 1; + orig.drbs = calloc_or_fail(orig.drbs_len, sizeof(*orig.drbs)); + f1ap_drb_setup_t *drb1 = &orig.drbs[0]; + drb1->id = 4; + _F1_MALLOC(drb1->lcid, 7); + drb1->up_dl_tnl_len = 1; + inet_pton(AF_INET, "127.0.0.1", &drb1->up_dl_tnl[0].tl_address); + drb1->up_dl_tnl[0].teid = 0xcafe; + + orig.srbs_len = 2; + orig.srbs = calloc_or_fail(orig.srbs_len, sizeof(*orig.srbs)); + orig.srbs[0].id = 1; + orig.srbs[0].lcid = 1; + orig.srbs[1].id = 2; + orig.srbs[1].lcid = 2; + + F1AP_F1AP_PDU_t *f1enc = encode_ue_context_mod_resp(&orig); + F1AP_F1AP_PDU_t *f1dec = f1ap_encode_decode(f1enc); + f1ap_msg_free(f1enc); + + f1ap_ue_context_mod_resp_t decoded = {0}; + bool ret = decode_ue_context_mod_resp(f1dec, &decoded); + AssertFatal(ret, "decode_ue_context_mod_resp(): could not decode message\n"); + f1ap_msg_free(f1dec); + + ret = eq_ue_context_mod_resp(&orig, &decoded); + AssertFatal(ret, "eq_ue_context_mod_resp(): decoded message doesn't match\n"); + free_ue_context_mod_resp(&decoded); + + f1ap_ue_context_mod_resp_t cp = cp_ue_context_mod_resp(&orig); + ret = eq_ue_context_mod_resp(&orig, &cp); + AssertFatal(ret, "eq_ue_context_mod_resp(): copied message doesn't match\n"); + free_ue_context_mod_resp(&orig); + free_ue_context_mod_resp(&cp); + + printf("%s() successful\n", __func__); +} + +static void test_f1ap_ue_context_modification_response_simple() +{ + f1ap_ue_context_mod_resp_t orig = { + .gNB_CU_ue_id = 9876, + .gNB_DU_ue_id = 5432, + // rest is optional and intentionally left out + }; + + F1AP_F1AP_PDU_t *f1enc = encode_ue_context_mod_resp(&orig); + F1AP_F1AP_PDU_t *f1dec = f1ap_encode_decode(f1enc); + f1ap_msg_free(f1enc); + + f1ap_ue_context_mod_resp_t decoded = {0}; + bool ret = decode_ue_context_mod_resp(f1dec, &decoded); + AssertFatal(ret, "decode_ue_context_mod_resp(): could not decode message\n"); + f1ap_msg_free(f1dec); + + ret = eq_ue_context_mod_resp(&orig, &decoded); + AssertFatal(ret, "eq_ue_context_mod_resp(): decoded message doesn't match\n"); + free_ue_context_mod_resp(&decoded); + + f1ap_ue_context_mod_resp_t cp = cp_ue_context_mod_resp(&orig); + ret = eq_ue_context_mod_resp(&orig, &cp); + AssertFatal(ret, "eq_ue_context_mod_resp(): copied message doesn't match\n"); + free_ue_context_mod_resp(&orig); + free_ue_context_mod_resp(&cp); + + printf("%s() successful\n", __func__); +} + +static void test_f1ap_ue_context_release_request() +{ + f1ap_ue_context_rel_req_t orig = { + .gNB_CU_ue_id = 1111, + .gNB_DU_ue_id = 2222, + .cause = F1AP_CAUSE_MISC, + .cause_value = 3, + }; + + F1AP_F1AP_PDU_t *f1enc = encode_ue_context_rel_req(&orig); + F1AP_F1AP_PDU_t *f1dec = f1ap_encode_decode(f1enc); + f1ap_msg_free(f1enc); + + f1ap_ue_context_rel_req_t decoded = {0}; + bool ret = decode_ue_context_rel_req(f1dec, &decoded); + AssertFatal(ret, "decode_ue_context_rel_req(): could not decode message\n"); + f1ap_msg_free(f1dec); + + ret = eq_ue_context_rel_req(&orig, &decoded); + AssertFatal(ret, "eq_ue_context_rel_req(): decoded message doesn't match\n"); + free_ue_context_rel_req(&decoded); + + f1ap_ue_context_rel_req_t cp = cp_ue_context_rel_req(&orig); + ret = eq_ue_context_rel_req(&orig, &cp); + AssertFatal(ret, "eq_ue_context_rel_req(): copied message doesn't match\n"); + free_ue_context_rel_req(&orig); + free_ue_context_rel_req(&cp); + + printf("%s() successful\n", __func__); +} + +static void test_f1ap_ue_context_release_command() +{ + f1ap_ue_context_rel_cmd_t orig = { + .gNB_CU_ue_id = 1111, + .gNB_DU_ue_id = 2222, + .cause = F1AP_CAUSE_RADIO_NETWORK, + .cause_value = 2, + }; + + orig.rrc_container = get_malloced_test_ba("some reject message"); + _F1_MALLOC(orig.srb_id, 1); + _F1_MALLOC(orig.old_gNB_DU_ue_id, 3333); + + F1AP_F1AP_PDU_t *f1enc = encode_ue_context_rel_cmd(&orig); + F1AP_F1AP_PDU_t *f1dec = f1ap_encode_decode(f1enc); + f1ap_msg_free(f1enc); + + f1ap_ue_context_rel_cmd_t decoded = {0}; + bool ret = decode_ue_context_rel_cmd(f1dec, &decoded); + AssertFatal(ret, "decode_ue_context_rel_cmd(): could not decode message\n"); + f1ap_msg_free(f1dec); + + ret = eq_ue_context_rel_cmd(&orig, &decoded); + AssertFatal(ret, "eq_ue_context_rel_cmd(): decoded message doesn't match\n"); + free_ue_context_rel_cmd(&decoded); + + f1ap_ue_context_rel_cmd_t cp = cp_ue_context_rel_cmd(&orig); + ret = eq_ue_context_rel_cmd(&orig, &cp); + AssertFatal(ret, "eq_ue_context_rel_cmd(): copied message doesn't match\n"); + free_ue_context_rel_cmd(&orig); + free_ue_context_rel_cmd(&cp); + + printf("%s() successful\n", __func__); +} + +static void test_f1ap_ue_context_release_complete() +{ + f1ap_ue_context_rel_cplt_t orig = { + .gNB_CU_ue_id = 1111, + .gNB_DU_ue_id = 2222, + }; + + F1AP_F1AP_PDU_t *f1enc = encode_ue_context_rel_cplt(&orig); + F1AP_F1AP_PDU_t *f1dec = f1ap_encode_decode(f1enc); + f1ap_msg_free(f1enc); + + f1ap_ue_context_rel_cplt_t decoded = {0}; + bool ret = decode_ue_context_rel_cplt(f1dec, &decoded); + AssertFatal(ret, "decode_ue_context_rel_cplt(): could not decode message\n"); + f1ap_msg_free(f1dec); + + ret = eq_ue_context_rel_cplt(&orig, &decoded); + AssertFatal(ret, "eq_ue_context_rel_cplt(): decoded message doesn't match\n"); + free_ue_context_rel_cplt(&decoded); + + f1ap_ue_context_rel_cplt_t cp = cp_ue_context_rel_cplt(&orig); + ret = eq_ue_context_rel_cplt(&orig, &cp); + AssertFatal(ret, "eq_ue_context_rel_cplt(): copied message doesn't match\n"); + free_ue_context_rel_cplt(&orig); + free_ue_context_rel_cplt(&cp); + + printf("%s() successful\n", __func__); +} + int main() { test_initial_ul_rrc_message_transfer(); @@ -733,5 +1281,16 @@ int main() test_f1ap_cu_configuration_update(); test_f1ap_cu_configuration_update_acknowledge(); test_f1ap_du_configuration_update_acknowledge(); + test_f1ap_ue_context_setup_request(); + test_f1ap_ue_context_setup_request_simple(); + test_f1ap_ue_context_setup_response(); + test_f1ap_ue_context_setup_response_simple(); + test_f1ap_ue_context_modification_request(); + test_f1ap_ue_context_modification_request_simple(); + test_f1ap_ue_context_modification_response(); + test_f1ap_ue_context_modification_response_simple(); + test_f1ap_ue_context_release_request(); + test_f1ap_ue_context_release_command(); + test_f1ap_ue_context_release_complete(); return 0; } diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c index dfe4cfeea2..09734d8215 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c @@ -195,7 +195,7 @@ void gNB_dlsch_ulsch_scheduler(module_id_t module_idP, frame_t frame, slot_t slo } bool wait_prach_completed = gNB->num_scheduled_prach_rx >= NUM_PRACH_RX_FOR_NOISE_ESTIMATE; - if (wait_prach_completed && (slot == 0) && (frame & 127) == 0) { + if ((wait_prach_completed || get_softmodem_params()->phy_test) && (slot == 0) && (frame & 127) == 0) { char stats_output[32656] = {0}; dump_mac_stats(gNB, stats_output, sizeof(stats_output), true); LOG_I(NR_MAC, "Frame.Slot %d.%d\n%s\n", frame, slot, stats_output); diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c index a447d9f91c..48fabb45e8 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c @@ -3124,7 +3124,7 @@ void nr_mac_trigger_release_complete(gNB_MAC_INST *mac, int rnti) // du_remove_f1_ue_data() (and also while sending the message to RRC) NR_SCHED_UNLOCK(&mac->sched_lock); f1_ue_data_t ue_data = du_get_f1_ue_data(rnti); - f1ap_ue_context_release_complete_t complete = { + f1ap_ue_context_rel_cplt_t complete = { .gNB_CU_ue_id = ue_data.secondary_ue, .gNB_DU_ue_id = rnti, }; @@ -3385,7 +3385,7 @@ bool nr_mac_request_release_ue(const gNB_MAC_INST *nrmac, int rnti) return false; } f1_ue_data_t ue_data = du_get_f1_ue_data(rnti); - f1ap_ue_context_release_req_t request = { + f1ap_ue_context_rel_req_t request = { .gNB_CU_ue_id = ue_data.secondary_ue, .gNB_DU_ue_id = rnti, .cause = F1AP_CAUSE_RADIO_NETWORK, 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 5d7642c815..9c6559ad10 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c +++ b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c @@ -31,7 +31,9 @@ #include "NR_CG-ConfigInfo.h" #include "openair3/ocp-gtpu/gtp_itf.h" #include "openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.h" +#include "lib/f1ap_rrc_message_transfer.h" #include "lib/f1ap_interface_management.h" +#include "lib/f1ap_ue_context.h" #include "executables/softmodem-common.h" @@ -221,19 +223,19 @@ void gnb_du_configuration_update_acknowledge(const f1ap_gnb_du_configuration_upd LOG_I(MAC, "received gNB-DU configuration update acknowledge\n"); } -static NR_RLC_BearerConfig_t *get_bearerconfig_from_srb(const f1ap_srb_to_be_setup_t *srb, +static NR_RLC_BearerConfig_t *get_bearerconfig_from_srb(const f1ap_srb_to_setup_t *srb, const nr_rlc_configuration_t *rlc_config) { - long priority = srb->srb_id == 2 ? 3 : 1; // see 38.331 sec 9.2.1 + long priority = srb->id == 2 ? 3 : 1; // see 38.331 sec 9.2.1 e_NR_LogicalChannelConfig__ul_SpecificParameters__bucketSizeDuration bucket = NR_LogicalChannelConfig__ul_SpecificParameters__bucketSizeDuration_ms5; - return get_SRB_RLC_BearerConfig(get_lcid_from_srbid(srb->srb_id), priority, bucket, rlc_config); + return get_SRB_RLC_BearerConfig(get_lcid_from_srbid(srb->id), priority, bucket, rlc_config); } static int handle_ue_context_srbs_setup(NR_UE_info_t *UE, int srbs_len, - const f1ap_srb_to_be_setup_t *req_srbs, - f1ap_srb_to_be_setup_t **resp_srbs, + const f1ap_srb_to_setup_t *req_srbs, + f1ap_srb_setup_t **resp_srbs, NR_CellGroupConfig_t *cellGroupConfig, const nr_rlc_configuration_t *rlc_config) { @@ -242,15 +244,15 @@ static int handle_ue_context_srbs_setup(NR_UE_info_t *UE, *resp_srbs = calloc(srbs_len, sizeof(**resp_srbs)); AssertFatal(*resp_srbs != NULL, "out of memory\n"); for (int i = 0; i < srbs_len; i++) { - const f1ap_srb_to_be_setup_t *srb = &req_srbs[i]; + const f1ap_srb_to_setup_t *srb = &req_srbs[i]; NR_RLC_BearerConfig_t *rlc_BearerConfig = get_bearerconfig_from_srb(srb, rlc_config); - nr_rlc_add_srb(UE->rnti, srb->srb_id, rlc_BearerConfig); + nr_rlc_add_srb(UE->rnti, srb->id, rlc_BearerConfig); int priority = rlc_BearerConfig->mac_LogicalChannelConfig->ul_SpecificParameters->priority; nr_lc_config_t c = {.lcid = rlc_BearerConfig->logicalChannelIdentity, .priority = priority}; nr_mac_add_lcid(&UE->UE_sched_ctrl, &c); - (*resp_srbs)[i].srb_id = srb->srb_id; + (*resp_srbs)[i].id = srb->id; (*resp_srbs)[i].lcid = c.lcid; if (rlc_BearerConfig->logicalChannelIdentity == 1) { @@ -267,12 +269,12 @@ static int handle_ue_context_srbs_setup(NR_UE_info_t *UE, return srbs_len; } -static NR_RLC_BearerConfig_t *get_bearerconfig_from_drb(const f1ap_drb_to_be_setup_t *drb, +static NR_RLC_BearerConfig_t *get_bearerconfig_from_drb(const f1ap_drb_to_setup_t *drb, const nr_rlc_configuration_t *rlc_config) { 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, rlc_config); + return get_DRB_RLC_BearerConfig(get_lcid_from_drbid(drb->id), drb->id, rlc_conf, priority, rlc_config); } static int get_non_dynamic_priority(int fiveqi) @@ -284,20 +286,20 @@ static int get_non_dynamic_priority(int fiveqi) return 0; } -static NR_QoS_config_t get_qos_config(const f1ap_qos_characteristics_t *qos_char) +static NR_QoS_config_t get_qos_config(const f1ap_qos_flow_param_t *qos) { NR_QoS_config_t qos_c = {0}; - switch (qos_char->qos_type) { + switch (qos->qos_type) { case DYNAMIC: - qos_c.priority = qos_char->dynamic.qos_priority_level; - qos_c.fiveQI = qos_char->dynamic.fiveqi > 0 ? qos_char->dynamic.fiveqi : 0; + qos_c.priority = qos->dyn.prio; + qos_c.fiveQI = 0; // does not exist for non-dynamic break; case NON_DYNAMIC: - qos_c.fiveQI = qos_char->non_dynamic.fiveqi; - qos_c.priority = get_non_dynamic_priority(qos_char->non_dynamic.fiveqi); + qos_c.fiveQI = qos->nondyn.fiveQI; + qos_c.priority = get_non_dynamic_priority(qos_c.fiveQI); break; default: - AssertFatal(false, "illegal QoS type %d\n", qos_char->qos_type); + AssertFatal(false, "illegal QoS type %d\n", qos->qos_type); break; } return qos_c; @@ -305,8 +307,8 @@ static NR_QoS_config_t get_qos_config(const f1ap_qos_characteristics_t *qos_char static int handle_ue_context_drbs_setup(NR_UE_info_t *UE, int drbs_len, - const f1ap_drb_to_be_setup_t *req_drbs, - f1ap_drb_to_be_setup_t **resp_drbs, + const f1ap_drb_to_setup_t *req_drbs, + f1ap_drb_setup_t **resp_drbs, NR_CellGroupConfig_t *cellGroupConfig, const nr_rlc_configuration_t *rlc_config) { @@ -318,32 +320,35 @@ static int handle_ue_context_drbs_setup(NR_UE_info_t *UE, *resp_drbs = calloc(drbs_len, sizeof(**resp_drbs)); AssertFatal(*resp_drbs != NULL, "out of memory\n"); for (int i = 0; i < drbs_len; i++) { - const f1ap_drb_to_be_setup_t *drb = &req_drbs[i]; - f1ap_drb_to_be_setup_t *resp_drb = &(*resp_drbs)[i]; + const f1ap_drb_to_setup_t *drb = &req_drbs[i]; + AssertFatal(drb->qos_choice == F1AP_QOS_CHOICE_NR, "only NR QoS supported\n"); + f1ap_drb_setup_t *resp_drb = &(*resp_drbs)[i]; NR_RLC_BearerConfig_t *rlc_BearerConfig = get_bearerconfig_from_drb(drb, rlc_config); - nr_rlc_add_drb(UE->rnti, drb->drb_id, rlc_BearerConfig); + nr_rlc_add_drb(UE->rnti, drb->id, rlc_BearerConfig); - nr_lc_config_t c = {.lcid = rlc_BearerConfig->logicalChannelIdentity, .nssai = drb->nssai}; + nr_lc_config_t c = {.lcid = rlc_BearerConfig->logicalChannelIdentity, .nssai = drb->nr.nssai}; int prio = 100; - for (int q = 0; q < drb->drb_info.flows_to_be_setup_length; ++q) { - c.qos_config[q] = get_qos_config(&drb->drb_info.flows_mapped_to_drb[q].qos_params.qos_characteristics); + for (int q = 0; q < drb->nr.flows_len; ++q) { + c.qos_config[q] = get_qos_config(&drb->nr.flows[q].param); prio = min(prio, c.qos_config[q].priority); } c.priority = prio; nr_mac_add_lcid(&UE->UE_sched_ctrl, &c); - *resp_drb = *drb; + resp_drb->id = drb->id; + resp_drb->lcid = malloc_or_fail(sizeof(*resp_drb->lcid)); + *resp_drb->lcid = c.lcid; // just put same number of tunnels in DL as in UL - DevAssert(drb->up_ul_tnl_length == 1); - resp_drb->up_dl_tnl_length = drb->up_ul_tnl_length; + DevAssert(drb->up_ul_tnl_len == 1); + resp_drb->up_dl_tnl_len = drb->up_ul_tnl_len; if (f1inst >= 0) { // we actually use F1-U int qfi = -1; // don't put PDU session marker in GTP gtpv1u_gnb_create_tunnel_resp_t resp_f1 = {0}; int ret = drb_gtpu_create(f1inst, UE->rnti, - drb->drb_id, - drb->drb_id, + drb->id, + drb->id, qfi, drb->up_ul_tnl[0].tl_address, drb->up_ul_tnl[0].teid, @@ -365,7 +370,7 @@ static int handle_ue_context_drbs_setup(NR_UE_info_t *UE, static int handle_ue_context_drbs_release(NR_UE_info_t *UE, int drbs_len, - const f1ap_drb_to_be_released_t *req_drbs, + const f1ap_drb_to_release_t *req_drbs, NR_CellGroupConfig_t *cellGroupConfig) { DevAssert(req_drbs != NULL && cellGroupConfig != NULL); @@ -377,9 +382,9 @@ static int handle_ue_context_drbs_release(NR_UE_info_t *UE, /* Note: the actual GTP tunnels are already removed in the F1AP message * decoding */ for (int i = 0; i < drbs_len; i++) { - const f1ap_drb_to_be_released_t *drb = &req_drbs[i]; + const f1ap_drb_to_release_t *drb = &req_drbs[i]; - long lcid = get_lcid_from_drbid(drb->rb_id); + long lcid = get_lcid_from_drbid(drb->id); int idx = 0; while (idx < cellGroupConfig->rlc_BearerToAddModList->list.count) { const NR_RLC_BearerConfig_t *bc = cellGroupConfig->rlc_BearerToAddModList->list.array[idx]; @@ -391,7 +396,7 @@ static int handle_ue_context_drbs_release(NR_UE_info_t *UE, nr_mac_remove_lcid(&UE->UE_sched_ctrl, lcid); nr_rlc_release_entity(UE->rnti, lcid); if (f1inst >= 0) - newGtpuDeleteOneTunnel(f1inst, UE->rnti, drb->rb_id); + newGtpuDeleteOneTunnel(f1inst, UE->rnti, drb->id); asn_sequence_del(&cellGroupConfig->rlc_BearerToAddModList->list, idx, 1); long *plcid = malloc(sizeof(*plcid)); AssertFatal(plcid, "out of memory\n"); @@ -599,34 +604,29 @@ static NR_UE_info_t *create_new_UE(gNB_MAC_INST *mac, uint32_t cu_id, const NR_C return UE; } -void ue_context_setup_request(const f1ap_ue_context_setup_t *req) +void ue_context_setup_request(const f1ap_ue_context_setup_req_t *req) { const bool is_SA = IS_SA_MODE(get_softmodem_params()); gNB_MAC_INST *mac = RC.nrmac[0]; - /* response has same type as request... */ - f1ap_ue_context_setup_t resp = { + + f1ap_ue_context_setup_resp_t resp = { .gNB_CU_ue_id = req->gNB_CU_ue_id, - .gNB_DU_ue_id = req->gNB_DU_ue_id, }; - /* gNB-DU UE ID is optional. As of now, the F1AP module fills -1 (on uint, so - * 0xffffffff), but the DU uses the RNTI, so check if it's a legal RNTI in - * which case we consider; if not, assume no DU UE ID given */ - bool ue_id_provided = resp.gNB_DU_ue_id > 0 && resp.gNB_DU_ue_id < 0xffff; + bool ue_id_provided = req->gNB_DU_ue_id != NULL; - NR_UE_NR_Capability_t *ue_cap = NULL; + const f1ap_cu_to_du_rrc_info_t *cu2du = &req->cu_to_du_rrc_info; NR_CG_ConfigInfo_t *cg_configinfo = NULL; - if (req->cu_to_du_rrc_information != NULL) { - const cu_to_du_rrc_information_t *cu2du = req->cu_to_du_rrc_information; - if (cu2du->cG_ConfigInfo != NULL) - cg_configinfo = get_cg_config_info(cu2du->cG_ConfigInfo, cu2du->cG_ConfigInfo_length); - if (cu2du->handoverPreparationInfo != NULL) { - ue_cap = get_ue_nr_cap_from_ho_prep_info(cu2du->handoverPreparationInfo, cu2du->handoverPreparationInfo_length); - } else if (cu2du->uE_CapabilityRAT_ContainerList != NULL) { - ue_cap = get_ue_nr_cap(req->gNB_DU_ue_id, cu2du->uE_CapabilityRAT_ContainerList, cu2du->uE_CapabilityRAT_ContainerList_length); - } - AssertFatal(cu2du->measConfig == NULL, "MeasConfig not handled\n"); + if (cu2du->cg_configinfo != NULL) + cg_configinfo = get_cg_config_info(cu2du->cg_configinfo->buf, cu2du->cg_configinfo->len); + NR_UE_NR_Capability_t *ue_cap = NULL; + if (cu2du->ho_prep_info != NULL) { + ue_cap = get_ue_nr_cap_from_ho_prep_info(cu2du->ho_prep_info->buf, cu2du->ho_prep_info->len); + } else if (cu2du->ue_cap != NULL) { + ue_cap = get_ue_nr_cap(*req->gNB_DU_ue_id, cu2du->ue_cap->buf, cu2du->ue_cap->len); } + AssertFatal(cu2du->meas_config == NULL, "MeasConfig not handled\n"); + /* 38.473: "For DC operation, the CG-ConfigInfo IE shall be included in the CU * to DU RRC Information IE at the gNB acting as secondary node" As of now, * we only handle NSA => we check we have CG-ConfigInfo if not SA or have SA @@ -639,36 +639,29 @@ void ue_context_setup_request(const f1ap_ue_context_setup_t *req) if (!ue_id_provided) { UE = create_new_UE(mac, req->gNB_CU_ue_id, cg_configinfo); resp.gNB_DU_ue_id = UE->rnti; - resp.crnti = &UE->rnti; + resp.crnti = malloc_or_fail(sizeof(*resp.crnti)); + *resp.crnti = UE->rnti; } else { DevAssert(is_SA); - UE = find_nr_UE(&mac->UE_info, req->gNB_DU_ue_id); + UE = find_nr_UE(&mac->UE_info, *req->gNB_DU_ue_id); } AssertFatal(UE, "no UE found or could not be created, but UE Context Setup Failed not implemented\n"); + resp.gNB_DU_ue_id = UE->rnti; NR_CellGroupConfig_t *new_CellGroup = clone_CellGroupConfig(UE->CellGroup); - if (req->srbs_to_be_setup_length > 0) { - resp.srbs_to_be_setup_length = handle_ue_context_srbs_setup(UE, - req->srbs_to_be_setup_length, - req->srbs_to_be_setup, - &resp.srbs_to_be_setup, - new_CellGroup, - &mac->rlc_config); + if (req->srbs_len > 0) { + resp.srbs_len = handle_ue_context_srbs_setup(UE, req->srbs_len, req->srbs, &resp.srbs, new_CellGroup, &mac->rlc_config); } - if (req->drbs_to_be_setup_length > 0) { - resp.drbs_to_be_setup_length = handle_ue_context_drbs_setup(UE, - req->drbs_to_be_setup_length, - req->drbs_to_be_setup, - &resp.drbs_to_be_setup, - new_CellGroup, - &mac->rlc_config); + if (req->drbs_len > 0) { + resp.drbs_len = + handle_ue_context_drbs_setup(UE, req->drbs_len, req->drbs, &resp.drbs, new_CellGroup, &mac->rlc_config); } if (req->rrc_container != NULL) { logical_chan_id_t id = 1; - nr_rlc_srb_recv_sdu(req->gNB_DU_ue_id, id, req->rrc_container, req->rrc_container_length); + nr_rlc_srb_recv_sdu(UE->rnti, id, req->rrc_container->buf, req->rrc_container->len); } NR_ServingCellConfigCommon_t *scc = mac->common_channels[0].ServingCellConfigCommon; @@ -691,14 +684,12 @@ void ue_context_setup_request(const f1ap_ue_context_setup_t *req) } } - resp.du_to_cu_rrc_information = calloc(1, sizeof(du_to_cu_rrc_information_t)); - AssertFatal(resp.du_to_cu_rrc_information != NULL, "out of memory\n"); - resp.du_to_cu_rrc_information->cellGroupConfig = calloc(1,1024); - AssertFatal(resp.du_to_cu_rrc_information->cellGroupConfig != NULL, "out of memory\n"); + byte_array_t cgc = { .buf = calloc_or_fail(1,1024) }; asn_enc_rval_t enc_rval = - uper_encode_to_buffer(&asn_DEF_NR_CellGroupConfig, NULL, new_CellGroup, resp.du_to_cu_rrc_information->cellGroupConfig, 1024); + uper_encode_to_buffer(&asn_DEF_NR_CellGroupConfig, NULL, new_CellGroup, cgc.buf, 1024); AssertFatal(enc_rval.encoded > 0, "Could not encode CellGroup, failed element %s\n", enc_rval.failed_type->name); - resp.du_to_cu_rrc_information->cellGroupConfig_length = (enc_rval.encoded + 7) >> 3; + cgc.len = (enc_rval.encoded + 7) >> 3; + resp.du_to_cu_rrc_info.cell_group_config = cgc; ASN_STRUCT_FREE(asn_DEF_NR_CellGroupConfig, UE->CellGroup); UE->CellGroup = new_CellGroup; @@ -707,35 +698,29 @@ void ue_context_setup_request(const f1ap_ue_context_setup_t *req) NR_SCHED_UNLOCK(&mac->sched_lock); - /* some sanity checks, since we use the same type for request and response */ - DevAssert(resp.cu_to_du_rrc_information == NULL); - DevAssert(resp.du_to_cu_rrc_information != NULL); - DevAssert(resp.rrc_container == NULL && resp.rrc_container_length == 0); - - mac->mac_rrc.ue_context_setup_response(req, &resp); + mac->mac_rrc.ue_context_setup_response(&resp); /* free the memory we allocated above */ - free(resp.srbs_to_be_setup); - free(resp.drbs_to_be_setup); - free(resp.du_to_cu_rrc_information->cellGroupConfig); - free(resp.du_to_cu_rrc_information); + free_ue_context_setup_resp(&resp); + ASN_STRUCT_FREE(asn_DEF_NR_CG_ConfigInfo, cg_configinfo); } -void ue_context_modification_request(const f1ap_ue_context_modif_req_t *req) +void ue_context_modification_request(const f1ap_ue_context_mod_req_t *req) { gNB_MAC_INST *mac = RC.nrmac[0]; - f1ap_ue_context_modif_resp_t resp = { + f1ap_ue_context_mod_resp_t resp = { .gNB_CU_ue_id = req->gNB_CU_ue_id, .gNB_DU_ue_id = req->gNB_DU_ue_id, }; NR_UE_NR_Capability_t *ue_cap = NULL; - if (req->cu_to_du_rrc_information != NULL) { - AssertFatal(req->cu_to_du_rrc_information->cG_ConfigInfo == NULL, "CG-ConfigInfo not handled\n"); - ue_cap = get_ue_nr_cap(req->gNB_DU_ue_id, - req->cu_to_du_rrc_information->uE_CapabilityRAT_ContainerList, - req->cu_to_du_rrc_information->uE_CapabilityRAT_ContainerList_length); - AssertFatal(req->cu_to_du_rrc_information->measConfig == NULL, "MeasConfig not handled\n"); + if (req->cu_to_du_rrc_info != NULL) { + AssertFatal(req->cu_to_du_rrc_info->cg_configinfo == NULL, "CG-ConfigInfo not handled\n"); + if (req->cu_to_du_rrc_info->ue_cap) { + byte_array_t *b = req->cu_to_du_rrc_info->ue_cap; + ue_cap = get_ue_nr_cap(req->gNB_DU_ue_id, b->buf, b->len); + } + AssertFatal(req->cu_to_du_rrc_info->meas_config == NULL, "MeasConfig not handled\n"); } NR_SCHED_LOCK(&mac->sched_lock); @@ -748,39 +733,28 @@ void ue_context_modification_request(const f1ap_ue_context_modif_req_t *req) NR_CellGroupConfig_t *new_CellGroup = clone_CellGroupConfig(UE->CellGroup); - if (req->srbs_to_be_setup_length > 0) { - resp.srbs_to_be_setup_length = handle_ue_context_srbs_setup(UE, - req->srbs_to_be_setup_length, - req->srbs_to_be_setup, - &resp.srbs_to_be_setup, - new_CellGroup, - &mac->rlc_config); + if (req->srbs_len > 0) { + resp.srbs_len = handle_ue_context_srbs_setup(UE, req->srbs_len, req->srbs, &resp.srbs, new_CellGroup, &mac->rlc_config); } - if (req->drbs_to_be_setup_length > 0) { - resp.drbs_to_be_setup_length = handle_ue_context_drbs_setup(UE, - req->drbs_to_be_setup_length, - req->drbs_to_be_setup, - &resp.drbs_to_be_setup, - new_CellGroup, - &mac->rlc_config); + if (req->drbs_len > 0) { + resp.drbs_len = handle_ue_context_drbs_setup(UE, req->drbs_len, req->drbs, &resp.drbs, new_CellGroup, &mac->rlc_config); } - if (req->drbs_to_be_released_length > 0) { - resp.drbs_to_be_released_length = - handle_ue_context_drbs_release(UE, req->drbs_to_be_released_length, req->drbs_to_be_released, new_CellGroup); + if (req->drbs_rel_len > 0) { + handle_ue_context_drbs_release(UE, req->drbs_rel_len, req->drbs_rel, new_CellGroup); } if (req->rrc_container != NULL) { logical_chan_id_t id = 1; - nr_rlc_srb_recv_sdu(req->gNB_DU_ue_id, id, req->rrc_container, req->rrc_container_length); + nr_rlc_srb_recv_sdu(req->gNB_DU_ue_id, id, req->rrc_container->buf, req->rrc_container->len); } NR_ServingCellConfigCommon_t *scc = mac->common_channels[0].ServingCellConfigCommon; - if (req->ReconfigComplOutcome != RRCreconf_info_not_present && req->ReconfigComplOutcome != RRCreconf_success) { + if (req->reconfig_compl && *req->reconfig_compl != RRCreconf_success) { LOG_E(NR_MAC, "RRC reconfiguration outcome unsuccessful, but no rollback mechanism implemented to come back to old configuration\n"); - } else if (req->ReconfigComplOutcome == RRCreconf_success) { + } else if (req->reconfig_compl) { LOG_I(NR_MAC, "DU received confirmation of successful RRC Reconfiguration\n"); if (UE->reconfigSpCellConfig) { // in case of reestablishment, the spCellConfig had to be released @@ -806,19 +780,17 @@ void ue_context_modification_request(const f1ap_ue_context_modif_req_t *req) update_cellGroupConfig(new_CellGroup, UE->uid, UE->capability, &mac->radio_config, scc); } - if (req->srbs_to_be_setup_length > 0 || req->drbs_to_be_setup_length > 0 || req->drbs_to_be_released_length > 0 - || ue_cap != NULL) { - resp.du_to_cu_rrc_information = calloc(1, sizeof(du_to_cu_rrc_information_t)); - AssertFatal(resp.du_to_cu_rrc_information != NULL, "out of memory\n"); - resp.du_to_cu_rrc_information->cellGroupConfig = calloc(1, 1024); - AssertFatal(resp.du_to_cu_rrc_information->cellGroupConfig != NULL, "out of memory\n"); + if (req->srbs_len > 0 || req->drbs_len > 0 || req->drbs_rel_len > 0 || ue_cap != NULL) { + resp.du_to_cu_rrc_info = calloc_or_fail(1, sizeof(du_to_cu_rrc_information_t)); + byte_array_t cgc = { .buf = calloc_or_fail(1, 1024) }; asn_enc_rval_t enc_rval = uper_encode_to_buffer(&asn_DEF_NR_CellGroupConfig, NULL, new_CellGroup, - resp.du_to_cu_rrc_information->cellGroupConfig, + cgc.buf, 1024); AssertFatal(enc_rval.encoded > 0, "Could not encode CellGroup, failed element %s\n", enc_rval.failed_type->name); - resp.du_to_cu_rrc_information->cellGroupConfig_length = (enc_rval.encoded + 7) >> 3; + cgc.len = (enc_rval.encoded + 7) >> 3; + resp.du_to_cu_rrc_info->cell_group_config = cgc; ASN_STRUCT_FREE(asn_DEF_NR_CellGroupConfig, UE->CellGroup); UE->CellGroup = new_CellGroup; @@ -833,20 +805,10 @@ void ue_context_modification_request(const f1ap_ue_context_modif_req_t *req) } NR_SCHED_UNLOCK(&mac->sched_lock); - /* some sanity checks, since we use the same type for request and response */ - DevAssert(resp.cu_to_du_rrc_information == NULL); - // resp.du_to_cu_rrc_information can be either NULL or not - DevAssert(resp.rrc_container == NULL && resp.rrc_container_length == 0); - - mac->mac_rrc.ue_context_modification_response(req, &resp); + mac->mac_rrc.ue_context_modification_response(&resp); /* free the memory we allocated above */ - free(resp.srbs_to_be_setup); - free(resp.drbs_to_be_setup); - if (resp.du_to_cu_rrc_information != NULL) { - free(resp.du_to_cu_rrc_information->cellGroupConfig); - free(resp.du_to_cu_rrc_information); - } + free_ue_context_mod_resp(&resp); } void ue_context_modification_confirm(const f1ap_ue_context_modif_confirm_t *confirm) @@ -891,7 +853,7 @@ void ue_context_modification_refuse(const f1ap_ue_context_modif_refuse_t *refuse NR_SCHED_UNLOCK(&mac->sched_lock); - f1ap_ue_context_release_req_t request = { + f1ap_ue_context_rel_req_t request = { .gNB_CU_ue_id = refuse->gNB_CU_ue_id, .gNB_DU_ue_id = refuse->gNB_DU_ue_id, .cause = F1AP_CAUSE_RADIO_NETWORK, @@ -900,7 +862,7 @@ void ue_context_modification_refuse(const f1ap_ue_context_modif_refuse_t *refuse mac->mac_rrc.ue_context_release_request(&request); } -void ue_context_release_command(const f1ap_ue_context_release_cmd_t *cmd) +void ue_context_release_command(const f1ap_ue_context_rel_cmd_t *cmd) { /* mark UE as to be deleted after PUSCH failure */ gNB_MAC_INST *mac = RC.nrmac[0]; @@ -908,7 +870,7 @@ void ue_context_release_command(const f1ap_ue_context_release_cmd_t *cmd) NR_UE_info_t *UE = find_nr_UE(&mac->UE_info, cmd->gNB_DU_ue_id); if (UE == NULL) { NR_SCHED_UNLOCK(&mac->sched_lock); - f1ap_ue_context_release_complete_t complete = { + f1ap_ue_context_rel_cplt_t complete = { .gNB_CU_ue_id = cmd->gNB_CU_ue_id, .gNB_DU_ue_id = cmd->gNB_DU_ue_id, }; @@ -920,14 +882,15 @@ void ue_context_release_command(const f1ap_ue_context_release_cmd_t *cmd) if (f1inst >= 0) newGtpuDeleteAllTunnels(f1inst, cmd->gNB_DU_ue_id); - if (UE->UE_sched_ctrl.ul_failure || cmd->rrc_container_length == 0) { + if (UE->UE_sched_ctrl.ul_failure || !cmd->rrc_container) { /* The UE is already not connected anymore or we have nothing to forward*/ nr_mac_release_ue(mac, cmd->gNB_DU_ue_id); nr_mac_trigger_release_complete(mac, cmd->gNB_DU_ue_id); - } else { + } else if (cmd->rrc_container && cmd->srb_id){ /* UE is in sync: forward release message and mark to be deleted * after UL failure */ - nr_rlc_srb_recv_sdu(cmd->gNB_DU_ue_id, cmd->srb_id, cmd->rrc_container, cmd->rrc_container_length); + byte_array_t *rrc_cont = cmd->rrc_container; + nr_rlc_srb_recv_sdu(cmd->gNB_DU_ue_id, *cmd->srb_id, rrc_cont->buf, rrc_cont->len); nr_mac_trigger_release_timer(&UE->UE_sched_ctrl, UE->current_UL_BWP.scs); } NR_SCHED_UNLOCK(&mac->sched_lock); diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.h b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.h index e9aceb1192..1ba31f8e80 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.h +++ b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.h @@ -32,11 +32,11 @@ void f1_setup_response(const f1ap_setup_resp_t *resp); void f1_setup_failure(const f1ap_setup_failure_t *failure); void gnb_du_configuration_update_acknowledge(const f1ap_gnb_du_configuration_update_acknowledge_t *ack); NR_CellGroupConfig_t *clone_CellGroupConfig(const NR_CellGroupConfig_t *orig); -void ue_context_setup_request(const f1ap_ue_context_setup_t *req); -void ue_context_modification_request(const f1ap_ue_context_modif_req_t *req); +void ue_context_setup_request(const f1ap_ue_context_setup_req_t *req); +void ue_context_modification_request(const f1ap_ue_context_mod_req_t *req); void ue_context_modification_confirm(const f1ap_ue_context_modif_confirm_t *confirm); void ue_context_modification_refuse(const f1ap_ue_context_modif_refuse_t *refuse); -void ue_context_release_command(const f1ap_ue_context_release_cmd_t *cmd); +void ue_context_release_command(const f1ap_ue_context_rel_cmd_t *cmd); void dl_rrc_message_transfer(const f1ap_dl_rrc_message_t *dl_rrc); diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul.h b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul.h index 1e416f01f9..23dda86dfb 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul.h +++ b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul.h @@ -31,12 +31,11 @@ typedef void (*f1_reset_acknowledge_cu_initiated_func_t)(const f1ap_reset_ack_t typedef void (*f1_setup_request_func_t)(const f1ap_setup_req_t* req); typedef void (*gnb_du_configuration_update_t)(const f1ap_gnb_du_configuration_update_t *upd); -typedef void (*ue_context_setup_response_func_t)(const f1ap_ue_context_setup_t* req, const f1ap_ue_context_setup_t *resp); -typedef void (*ue_context_modification_response_func_t)(const f1ap_ue_context_modif_req_t *req, - const f1ap_ue_context_modif_resp_t *resp); +typedef void (*ue_context_setup_response_func_t)(const f1ap_ue_context_setup_resp_t *resp); +typedef void (*ue_context_modification_response_func_t)(const f1ap_ue_context_mod_resp_t *resp); typedef void (*ue_context_modification_required_func_t)(const f1ap_ue_context_modif_required_t *t); -typedef void (*ue_context_release_request_func_t)(const f1ap_ue_context_release_req_t* req); -typedef void (*ue_context_release_complete_func_t)(const f1ap_ue_context_release_complete_t *complete); +typedef void (*ue_context_release_request_func_t)(const f1ap_ue_context_rel_req_t* req); +typedef void (*ue_context_release_complete_func_t)(const f1ap_ue_context_rel_cplt_t *complete); typedef void (*initial_ul_rrc_message_transfer_func_t)(module_id_t module_id, const f1ap_initial_ul_rrc_message_t *ul_rrc); 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 e687991a5e..cf6c5b2563 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_direct.c +++ b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_direct.c @@ -23,8 +23,9 @@ #include "intertask_interface.h" #include "mac_rrc_ul.h" -#include "f1ap_lib_extern.h" +#include "lib/f1ap_rrc_message_transfer.h" #include "lib/f1ap_interface_management.h" +#include "lib/f1ap_ue_context.h" static void f1_reset_du_initiated_direct(const f1ap_reset_t *reset) { @@ -58,96 +59,19 @@ static void gnb_du_configuration_update_direct(const f1ap_gnb_du_configuration_u itti_send_msg_to_task(TASK_RRC_GNB, 0, msg); } -static void ue_context_setup_response_direct(const f1ap_ue_context_setup_t *req, const f1ap_ue_context_setup_t *resp) +static void ue_context_setup_response_direct(const f1ap_ue_context_setup_resp_t *resp) { - DevAssert(req->drbs_to_be_setup_length == resp->drbs_to_be_setup_length); - - (void) req; /* we don't need the request -- it is to set up GTP in F1 case */ MessageDef *msg = itti_alloc_new_message (TASK_MAC_GNB, 0, F1AP_UE_CONTEXT_SETUP_RESP); msg->ittiMsgHeader.originInstance = -1; // means monolithic - f1ap_ue_context_setup_t *f1ap_msg = &F1AP_UE_CONTEXT_SETUP_RESP(msg); - /* copy all fields, but reallocate memory buffers! */ - *f1ap_msg = *resp; - - if (resp->srbs_to_be_setup_length > 0) { - DevAssert(resp->srbs_to_be_setup != NULL); - f1ap_msg->srbs_to_be_setup_length = resp->srbs_to_be_setup_length; - f1ap_msg->srbs_to_be_setup = calloc(f1ap_msg->srbs_to_be_setup_length, sizeof(*f1ap_msg->srbs_to_be_setup)); - for (int i = 0; i < f1ap_msg->srbs_to_be_setup_length; ++i) - f1ap_msg->srbs_to_be_setup[i] = resp->srbs_to_be_setup[i]; - } - if (resp->drbs_to_be_setup_length > 0) { - DevAssert(resp->drbs_to_be_setup != NULL); - f1ap_msg->drbs_to_be_setup_length = resp->drbs_to_be_setup_length; - f1ap_msg->drbs_to_be_setup = calloc(f1ap_msg->drbs_to_be_setup_length, sizeof(*f1ap_msg->drbs_to_be_setup)); - for (int i = 0; i < f1ap_msg->drbs_to_be_setup_length; ++i) - f1ap_msg->drbs_to_be_setup[i] = resp->drbs_to_be_setup[i]; - } - - f1ap_msg->du_to_cu_rrc_information = malloc(sizeof(*resp->du_to_cu_rrc_information)); - AssertFatal(f1ap_msg->du_to_cu_rrc_information != NULL, "out of memory\n"); - f1ap_msg->du_to_cu_rrc_information_length = resp->du_to_cu_rrc_information_length; - du_to_cu_rrc_information_t *du2cu = f1ap_msg->du_to_cu_rrc_information; - du2cu->cellGroupConfig_length = resp->du_to_cu_rrc_information->cellGroupConfig_length; - du2cu->cellGroupConfig = calloc(du2cu->cellGroupConfig_length, sizeof(*du2cu->cellGroupConfig)); - AssertFatal(du2cu->cellGroupConfig != NULL, "out of memory\n"); - memcpy(du2cu->cellGroupConfig, resp->du_to_cu_rrc_information->cellGroupConfig, du2cu->cellGroupConfig_length); - + F1AP_UE_CONTEXT_SETUP_RESP(msg) = cp_ue_context_setup_resp(resp); itti_send_msg_to_task(TASK_RRC_GNB, 0, msg); } -static void ue_context_modification_response_direct(const f1ap_ue_context_modif_req_t *req, - const f1ap_ue_context_modif_resp_t *resp) +static void ue_context_modification_response_direct(const f1ap_ue_context_mod_resp_t *resp) { - (void)req; /* we don't need the request -- it is to set up GTP in F1 case */ MessageDef *msg = itti_alloc_new_message(TASK_MAC_GNB, 0, F1AP_UE_CONTEXT_MODIFICATION_RESP); msg->ittiMsgHeader.originInstance = -1; // means monolithic - f1ap_ue_context_modif_resp_t *f1ap_msg = &F1AP_UE_CONTEXT_MODIFICATION_RESP(msg); - - f1ap_msg->gNB_CU_ue_id = resp->gNB_CU_ue_id; - f1ap_msg->gNB_DU_ue_id = resp->gNB_DU_ue_id; - f1ap_msg->plmn = resp->plmn; - f1ap_msg->nr_cellid = resp->nr_cellid; - f1ap_msg->servCellIndex = resp->servCellIndex; - AssertFatal(resp->cellULConfigured == NULL, "not handled\n"); - f1ap_msg->servCellId = resp->servCellId; - - DevAssert(resp->cu_to_du_rrc_information == NULL && resp->cu_to_du_rrc_information_length == 0); - if (resp->du_to_cu_rrc_information) { - f1ap_msg->du_to_cu_rrc_information = malloc(sizeof(*resp->du_to_cu_rrc_information)); - AssertFatal(f1ap_msg->du_to_cu_rrc_information != NULL, "out of memory\n"); - f1ap_msg->du_to_cu_rrc_information_length = resp->du_to_cu_rrc_information_length; - du_to_cu_rrc_information_t *du2cu = f1ap_msg->du_to_cu_rrc_information; - du2cu->cellGroupConfig_length = resp->du_to_cu_rrc_information->cellGroupConfig_length; - du2cu->cellGroupConfig = calloc(du2cu->cellGroupConfig_length, sizeof(*du2cu->cellGroupConfig)); - AssertFatal(du2cu->cellGroupConfig != NULL, "out of memory\n"); - memcpy(du2cu->cellGroupConfig, resp->du_to_cu_rrc_information->cellGroupConfig, du2cu->cellGroupConfig_length); - } - - if (resp->drbs_to_be_setup_length > 0) { - DevAssert(resp->drbs_to_be_setup != NULL); - f1ap_msg->drbs_to_be_setup_length = resp->drbs_to_be_setup_length; - f1ap_msg->drbs_to_be_setup = calloc(f1ap_msg->drbs_to_be_setup_length, sizeof(*f1ap_msg->drbs_to_be_setup)); - for (int i = 0; i < f1ap_msg->drbs_to_be_setup_length; ++i) - f1ap_msg->drbs_to_be_setup[i] = resp->drbs_to_be_setup[i]; - } - - DevAssert(resp->drbs_to_be_modified == NULL && resp->drbs_to_be_modified_length == 0); - f1ap_msg->QoS_information_type = resp->QoS_information_type; - AssertFatal(resp->drbs_failed_to_be_setup_length == 0 && resp->drbs_failed_to_be_setup == NULL, "not implemented yet\n"); - - if (resp->srbs_to_be_setup_length > 0) { - DevAssert(resp->srbs_to_be_setup != NULL); - f1ap_msg->srbs_to_be_setup_length = resp->srbs_to_be_setup_length; - f1ap_msg->srbs_to_be_setup = calloc(f1ap_msg->srbs_to_be_setup_length, sizeof(*f1ap_msg->srbs_to_be_setup)); - for (int i = 0; i < f1ap_msg->srbs_to_be_setup_length; ++i) - f1ap_msg->srbs_to_be_setup[i] = resp->srbs_to_be_setup[i]; - } - - AssertFatal(resp->srbs_failed_to_be_setup_length == 0 && resp->srbs_failed_to_be_setup == NULL, "not implemented yet\n"); - - DevAssert(resp->rrc_container == NULL && resp->rrc_container_length == 0); - + F1AP_UE_CONTEXT_MODIFICATION_RESP(msg) = cp_ue_context_mod_resp(resp); itti_send_msg_to_task(TASK_RRC_GNB, 0, msg); } @@ -177,21 +101,19 @@ static void ue_context_modification_required_direct(const f1ap_ue_context_modif_ itti_send_msg_to_task(TASK_RRC_GNB, 0, msg); } -static void ue_context_release_request_direct(const f1ap_ue_context_release_req_t* req) +static void ue_context_release_request_direct(const f1ap_ue_context_rel_req_t* req) { MessageDef *msg = itti_alloc_new_message(TASK_MAC_GNB, 0, F1AP_UE_CONTEXT_RELEASE_REQ); msg->ittiMsgHeader.originInstance = -1; // means monolithic - f1ap_ue_context_release_req_t *f1ap_msg = &F1AP_UE_CONTEXT_RELEASE_REQ(msg); - *f1ap_msg = *req; + F1AP_UE_CONTEXT_RELEASE_REQ(msg) = cp_ue_context_rel_req(req); itti_send_msg_to_task(TASK_RRC_GNB, 0, msg); } -static void ue_context_release_complete_direct(const f1ap_ue_context_release_complete_t *complete) +static void ue_context_release_complete_direct(const f1ap_ue_context_rel_cplt_t *complete) { MessageDef *msg = itti_alloc_new_message(TASK_MAC_GNB, 0, F1AP_UE_CONTEXT_RELEASE_COMPLETE); msg->ittiMsgHeader.originInstance = -1; // means monolithic - f1ap_ue_context_release_complete_t *f1ap_msg = &F1AP_UE_CONTEXT_RELEASE_COMPLETE(msg); - *f1ap_msg = *complete; + F1AP_UE_CONTEXT_RELEASE_COMPLETE(msg) = cp_ue_context_rel_cplt(complete); itti_send_msg_to_task(TASK_RRC_GNB, 0, 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 81373e0bc9..19bf8039b6 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_f1ap.c +++ b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_f1ap.c @@ -29,8 +29,9 @@ #include "mac_rrc_ul.h" -#include "f1ap_lib_extern.h" +#include "lib/f1ap_rrc_message_transfer.h" #include "lib/f1ap_interface_management.h" +#include "lib/f1ap_ue_context.h" static f1ap_net_config_t read_DU_IP_config(const eth_params_t* f1_params, const char *f1u_ip_addr) { @@ -85,80 +86,17 @@ static void gnb_du_configuration_update_f1ap(const f1ap_gnb_du_configuration_upd itti_send_msg_to_task(TASK_DU_F1, 0, msg); } -static void ue_context_setup_response_f1ap(const f1ap_ue_context_setup_t *req, const f1ap_ue_context_setup_t *resp) +static void ue_context_setup_response_f1ap(const f1ap_ue_context_setup_resp_t *resp) { - DevAssert(req->drbs_to_be_setup_length == resp->drbs_to_be_setup_length); - - DevAssert(req->srbs_to_be_setup_length == resp->srbs_to_be_setup_length); MessageDef *msg = itti_alloc_new_message (TASK_MAC_GNB, 0, F1AP_UE_CONTEXT_SETUP_RESP); - f1ap_ue_context_setup_t *f1ap_msg = &F1AP_UE_CONTEXT_SETUP_RESP(msg); - /* copy all fields, but reallocate rrc_containers! */ - *f1ap_msg = *resp; - - if (resp->srbs_to_be_setup_length > 0) { - DevAssert(resp->srbs_to_be_setup != NULL); - f1ap_msg->srbs_to_be_setup_length = resp->srbs_to_be_setup_length; - f1ap_msg->srbs_to_be_setup = calloc(f1ap_msg->srbs_to_be_setup_length, sizeof(*f1ap_msg->srbs_to_be_setup)); - for (int i = 0; i < f1ap_msg->srbs_to_be_setup_length; ++i) - f1ap_msg->srbs_to_be_setup[i] = resp->srbs_to_be_setup[i]; - } - if (resp->drbs_to_be_setup_length > 0) { - DevAssert(resp->drbs_to_be_setup != NULL); - f1ap_msg->drbs_to_be_setup_length = resp->drbs_to_be_setup_length; - f1ap_msg->drbs_to_be_setup = calloc(f1ap_msg->drbs_to_be_setup_length, sizeof(*f1ap_msg->drbs_to_be_setup)); - for (int i = 0; i < f1ap_msg->drbs_to_be_setup_length; ++i) - f1ap_msg->drbs_to_be_setup[i] = resp->drbs_to_be_setup[i]; - } - if (resp->crnti) { - f1ap_msg->crnti = calloc(1, sizeof(uint16_t)); - *f1ap_msg->crnti = *resp->crnti; - } - - f1ap_msg->du_to_cu_rrc_information = malloc(sizeof(*resp->du_to_cu_rrc_information)); - AssertFatal(f1ap_msg->du_to_cu_rrc_information != NULL, "out of memory\n"); - f1ap_msg->du_to_cu_rrc_information_length = resp->du_to_cu_rrc_information_length; - du_to_cu_rrc_information_t *du2cu = f1ap_msg->du_to_cu_rrc_information; - du2cu->cellGroupConfig_length = resp->du_to_cu_rrc_information->cellGroupConfig_length; - du2cu->cellGroupConfig = calloc(du2cu->cellGroupConfig_length, sizeof(*du2cu->cellGroupConfig)); - AssertFatal(du2cu->cellGroupConfig != NULL, "out of memory\n"); - memcpy(du2cu->cellGroupConfig, resp->du_to_cu_rrc_information->cellGroupConfig, du2cu->cellGroupConfig_length); - + F1AP_UE_CONTEXT_SETUP_RESP(msg) = cp_ue_context_setup_resp(resp); itti_send_msg_to_task(TASK_DU_F1, 0, msg); } -static void ue_context_modification_response_f1ap(const f1ap_ue_context_modif_req_t *req, const f1ap_ue_context_modif_resp_t *resp) +static void ue_context_modification_response_f1ap(const f1ap_ue_context_mod_resp_t *resp) { MessageDef *msg = itti_alloc_new_message(TASK_MAC_GNB, 0, F1AP_UE_CONTEXT_MODIFICATION_RESP); - f1ap_ue_context_modif_resp_t *f1ap_msg = &F1AP_UE_CONTEXT_MODIFICATION_RESP(msg); - /* copy all fields, but reallocate rrc_containers! */ - *f1ap_msg = *resp; - - if (resp->srbs_to_be_setup_length > 0) { - DevAssert(resp->srbs_to_be_setup != NULL); - f1ap_msg->srbs_to_be_setup_length = resp->srbs_to_be_setup_length; - f1ap_msg->srbs_to_be_setup = calloc(f1ap_msg->srbs_to_be_setup_length, sizeof(*f1ap_msg->srbs_to_be_setup)); - for (int i = 0; i < f1ap_msg->srbs_to_be_setup_length; ++i) - f1ap_msg->srbs_to_be_setup[i] = resp->srbs_to_be_setup[i]; - } - if (resp->drbs_to_be_setup_length > 0) { - DevAssert(resp->drbs_to_be_setup != NULL); - f1ap_msg->drbs_to_be_setup_length = resp->drbs_to_be_setup_length; - f1ap_msg->drbs_to_be_setup = calloc(f1ap_msg->drbs_to_be_setup_length, sizeof(*f1ap_msg->drbs_to_be_setup)); - for (int i = 0; i < f1ap_msg->drbs_to_be_setup_length; ++i) - f1ap_msg->drbs_to_be_setup[i] = resp->drbs_to_be_setup[i]; - } - - if (resp->du_to_cu_rrc_information != NULL) { - f1ap_msg->du_to_cu_rrc_information = calloc(1, sizeof(*resp->du_to_cu_rrc_information)); - AssertFatal(f1ap_msg->du_to_cu_rrc_information != NULL, "out of memory\n"); - f1ap_msg->du_to_cu_rrc_information_length = resp->du_to_cu_rrc_information_length; - du_to_cu_rrc_information_t *du2cu = f1ap_msg->du_to_cu_rrc_information; - du2cu->cellGroupConfig_length = resp->du_to_cu_rrc_information->cellGroupConfig_length; - du2cu->cellGroupConfig = calloc(du2cu->cellGroupConfig_length, sizeof(*du2cu->cellGroupConfig)); - AssertFatal(du2cu->cellGroupConfig != NULL, "out of memory\n"); - memcpy(du2cu->cellGroupConfig, resp->du_to_cu_rrc_information->cellGroupConfig, du2cu->cellGroupConfig_length); - } - + F1AP_UE_CONTEXT_MODIFICATION_RESP(msg) = cp_ue_context_mod_resp(resp); itti_send_msg_to_task(TASK_DU_F1, 0, msg); } @@ -187,21 +125,19 @@ static void ue_context_modification_required_f1ap(const f1ap_ue_context_modif_re itti_send_msg_to_task(TASK_DU_F1, 0, msg); } -static void ue_context_release_request_f1ap(const f1ap_ue_context_release_req_t* req) +static void ue_context_release_request_f1ap(const f1ap_ue_context_rel_req_t* req) { MessageDef *msg = itti_alloc_new_message(TASK_MAC_GNB, 0, F1AP_UE_CONTEXT_RELEASE_REQ); - f1ap_ue_context_release_req_t *f1ap_msg = &F1AP_UE_CONTEXT_RELEASE_REQ(msg); - *f1ap_msg = *req; + F1AP_UE_CONTEXT_RELEASE_REQ(msg) = cp_ue_context_rel_req(req); itti_send_msg_to_task(TASK_DU_F1, 0, msg); } -static void ue_context_release_complete_f1ap(const f1ap_ue_context_release_complete_t *complete) +static void ue_context_release_complete_f1ap(const f1ap_ue_context_rel_cplt_t *complete) { newGtpuDeleteAllTunnels(0, complete->gNB_DU_ue_id); MessageDef *msg = itti_alloc_new_message(TASK_MAC_GNB, 0, F1AP_UE_CONTEXT_RELEASE_COMPLETE); - f1ap_ue_context_release_complete_t *f1ap_msg = &F1AP_UE_CONTEXT_RELEASE_COMPLETE(msg); - *f1ap_msg = *complete; + F1AP_UE_CONTEXT_RELEASE_COMPLETE(msg) = cp_ue_context_rel_cplt(complete); itti_send_msg_to_task(TASK_DU_F1, 0, msg); } diff --git a/openair2/LAYER2/NR_MAC_gNB/main.c b/openair2/LAYER2/NR_MAC_gNB/main.c index 0acc6fe0d2..fb932c83a3 100644 --- a/openair2/LAYER2/NR_MAC_gNB/main.c +++ b/openair2/LAYER2/NR_MAC_gNB/main.c @@ -63,6 +63,7 @@ #include "nr_pdcp/nr_pdcp_oai_api.h" #include "nr_rlc/nr_rlc_oai_api.h" #include "openair2/F1AP/f1ap_ids.h" +#include "openair2/F1AP/lib/f1ap_interface_management.h" #include "seq_arr.h" #include "system.h" #include "time_meas.h" @@ -342,6 +343,9 @@ void mac_top_destroy_gNB(gNB_MAC_INST *mac) for (int i = 0; i < sizeofArray(UE_info->access_ue_list); ++i) if (UE_info->access_ue_list[i]) delete_nr_ue_data(UE_info->access_ue_list[i], cc, &UE_info->uid_allocator); + if (mac->f1_config.setup_resp) + free_f1ap_setup_response(mac->f1_config.setup_resp); + free(mac->f1_config.setup_resp); } void nr_mac_send_f1_setup_req(void) diff --git a/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c b/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c index 41ace5014b..4246cc65aa 100644 --- a/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c +++ b/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c @@ -3524,7 +3524,7 @@ NR_CellGroupConfig_t *get_initial_cellGroupConfig(int uid, void update_cellGroupConfig(NR_CellGroupConfig_t *cellGroupConfig, const int uid, - NR_UE_NR_Capability_t *uecap, + const NR_UE_NR_Capability_t *uecap, const nr_mac_config_t *configuration, const NR_ServingCellConfigCommon_t *scc) { @@ -3969,7 +3969,6 @@ NR_CellGroupConfig_t *get_default_secondaryCellGroup(const NR_ServingCellConfigC NR_PUCCH_CSI_Resource_t *pucchcsires1 = calloc(1, sizeof(*pucchcsires1)); pucchcsires1->uplinkBandwidthPartId = bwp->bwp_Id; pucchcsires1->pucch_Resource = 2; - config_csi_meas_report(csi_MeasConfig, servingcellconfigcommon, pucchcsires1, @@ -3979,9 +3978,14 @@ NR_CellGroupConfig_t *get_default_secondaryCellGroup(const NR_ServingCellConfigC bwp->bwp_Id, uid, curr_bwp); + // this is the same resource as pucchcsires1, but duplicated to avoid + // double free when releasing the CellGroupConfig + NR_PUCCH_CSI_Resource_t *pucchcsires2 = calloc(1, sizeof(*pucchcsires2)); + pucchcsires2->uplinkBandwidthPartId = bwp->bwp_Id; + pucchcsires2->pucch_Resource = 2; config_rsrp_meas_report(csi_MeasConfig, servingcellconfigcommon, - pucchcsires1, + pucchcsires2, do_csirs, bwp->bwp_Id + 10, uid, diff --git a/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.h b/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.h index cdb4f5b792..bdf56a3310 100644 --- a/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.h +++ b/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.h @@ -89,7 +89,7 @@ NR_CellGroupConfig_t *get_initial_cellGroupConfig(int uid, const nr_rlc_configuration_t *default_rlc_config); void update_cellGroupConfig(NR_CellGroupConfig_t *cellGroupConfig, const int uid, - NR_UE_NR_Capability_t *uecap, + const NR_UE_NR_Capability_t *uecap, const nr_mac_config_t *configuration, const NR_ServingCellConfigCommon_t *scc); void free_cellGroupConfig(NR_CellGroupConfig_t *cellGroupConfig); diff --git a/openair2/RRC/NR/mac_rrc_dl.h b/openair2/RRC/NR/mac_rrc_dl.h index d6937591b5..4bd106d679 100644 --- a/openair2/RRC/NR/mac_rrc_dl.h +++ b/openair2/RRC/NR/mac_rrc_dl.h @@ -33,11 +33,11 @@ typedef void (*f1_setup_failure_func_t)(sctp_assoc_t assoc_id, const f1ap_setup_ typedef void (*gnb_du_configuration_update_ack_func_t)(sctp_assoc_t assoc_id, const f1ap_gnb_du_configuration_update_acknowledge_t *ack); -typedef void (*ue_context_setup_request_func_t)(sctp_assoc_t assoc_id, const f1ap_ue_context_setup_t *req); -typedef void (*ue_context_modification_request_func_t)(sctp_assoc_t assoc_id, const f1ap_ue_context_modif_req_t *req); +typedef void (*ue_context_setup_request_func_t)(sctp_assoc_t assoc_id, const f1ap_ue_context_setup_req_t *req); +typedef void (*ue_context_modification_request_func_t)(sctp_assoc_t assoc_id, const f1ap_ue_context_mod_req_t *req); typedef void (*ue_context_modification_confirm_func_t)(sctp_assoc_t assoc_id, const f1ap_ue_context_modif_confirm_t *confirm); typedef void (*ue_context_modification_refuse_func_t)(sctp_assoc_t assoc_id, const f1ap_ue_context_modif_refuse_t *refuse); -typedef void (*ue_context_release_command_func_t)(sctp_assoc_t assoc_id, const f1ap_ue_context_release_cmd_t *cmd); +typedef void (*ue_context_release_command_func_t)(sctp_assoc_t assoc_id, const f1ap_ue_context_rel_cmd_t *cmd); typedef void (*dl_rrc_message_transfer_func_t)(sctp_assoc_t assoc_id, const f1ap_dl_rrc_message_t *dl_rrc); diff --git a/openair2/RRC/NR/mac_rrc_dl_direct.c b/openair2/RRC/NR/mac_rrc_dl_direct.c index 4f8d45ac8c..83c1130fcb 100644 --- a/openair2/RRC/NR/mac_rrc_dl_direct.c +++ b/openair2/RRC/NR/mac_rrc_dl_direct.c @@ -58,13 +58,13 @@ static void gnb_du_configuration_update_ack_direct(sctp_assoc_t assoc_id, const gnb_du_configuration_update_acknowledge(ack); } -static void ue_context_setup_request_direct(sctp_assoc_t assoc_id, const f1ap_ue_context_setup_t *req) +static void ue_context_setup_request_direct(sctp_assoc_t assoc_id, const f1ap_ue_context_setup_req_t *req) { AssertFatal(assoc_id == -1, "illegal assoc_id %d\n", assoc_id); ue_context_setup_request(req); } -static void ue_context_modification_request_direct(sctp_assoc_t assoc_id, const f1ap_ue_context_modif_req_t *req) +static void ue_context_modification_request_direct(sctp_assoc_t assoc_id, const f1ap_ue_context_mod_req_t *req) { AssertFatal(assoc_id == -1, "illegal assoc_id %d\n", assoc_id); ue_context_modification_request(req); @@ -82,7 +82,7 @@ static void ue_context_modification_refuse_direct(sctp_assoc_t assoc_id, const f ue_context_modification_refuse(refuse); } -static void ue_context_release_command_direct(sctp_assoc_t assoc_id, const f1ap_ue_context_release_cmd_t *cmd) +static void ue_context_release_command_direct(sctp_assoc_t assoc_id, const f1ap_ue_context_rel_cmd_t *cmd) { AssertFatal(assoc_id == -1, "illegal assoc_id %d\n", assoc_id); ue_context_release_command(cmd); diff --git a/openair2/RRC/NR/mac_rrc_dl_f1ap.c b/openair2/RRC/NR/mac_rrc_dl_f1ap.c index 9fef2dea58..37cb6d70f9 100644 --- a/openair2/RRC/NR/mac_rrc_dl_f1ap.c +++ b/openair2/RRC/NR/mac_rrc_dl_f1ap.c @@ -30,8 +30,9 @@ #include "intertask_interface.h" #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" +#include "lib/f1ap_rrc_message_transfer.h" +#include "lib/f1ap_interface_management.h" +#include "lib/f1ap_ue_context.h" static void f1_reset_cu_initiated_f1ap(sctp_assoc_t assoc_id, const f1ap_reset_t *reset) { @@ -75,116 +76,19 @@ static void gnb_du_configuration_update_ack_f1ap(sctp_assoc_t assoc_id, const f1 itti_send_msg_to_task(TASK_CU_F1, 0, msg); } -static void ue_context_setup_request_f1ap(sctp_assoc_t assoc_id, const f1ap_ue_context_setup_t *req) +static void ue_context_setup_request_f1ap(sctp_assoc_t assoc_id, const f1ap_ue_context_setup_req_t *req) { MessageDef *msg = itti_alloc_new_message(TASK_RRC_GNB, 0, F1AP_UE_CONTEXT_SETUP_REQ); msg->ittiMsgHeader.originInstance = assoc_id; - f1ap_ue_context_setup_t *f1ap_msg = &F1AP_UE_CONTEXT_SETUP_REQ(msg); - *f1ap_msg = *req; - if (req->cu_to_du_rrc_information != NULL) { - f1ap_msg->cu_to_du_rrc_information = calloc(1, sizeof(*f1ap_msg->cu_to_du_rrc_information)); - AssertFatal(f1ap_msg->cu_to_du_rrc_information != NULL, "out of memory\n"); - const cu_to_du_rrc_information_t *du2cu_req = req->cu_to_du_rrc_information; - if (req->cu_to_du_rrc_information->cG_ConfigInfo != NULL) { - cu_to_du_rrc_information_t* du2cu_new = f1ap_msg->cu_to_du_rrc_information; - du2cu_new->cG_ConfigInfo_length = du2cu_req->cG_ConfigInfo_length; - du2cu_new->cG_ConfigInfo = malloc_or_fail(du2cu_new->cG_ConfigInfo_length); - memcpy(du2cu_new->cG_ConfigInfo, du2cu_req->cG_ConfigInfo, du2cu_new->cG_ConfigInfo_length); - } - AssertFatal(req->cu_to_du_rrc_information->measConfig == NULL && req->cu_to_du_rrc_information->measConfig_length == 0, "cg_ConfigInfo not implemented\n"); - if (req->cu_to_du_rrc_information->uE_CapabilityRAT_ContainerList != NULL) { - cu_to_du_rrc_information_t* du2cu_new = f1ap_msg->cu_to_du_rrc_information; - DevAssert(du2cu_req->uE_CapabilityRAT_ContainerList_length > 0); - du2cu_new->uE_CapabilityRAT_ContainerList_length = du2cu_req->uE_CapabilityRAT_ContainerList_length; - du2cu_new->uE_CapabilityRAT_ContainerList = malloc(du2cu_new->uE_CapabilityRAT_ContainerList_length); - AssertFatal(du2cu_new->uE_CapabilityRAT_ContainerList != NULL, "out of memory\n"); - memcpy(du2cu_new->uE_CapabilityRAT_ContainerList, du2cu_req->uE_CapabilityRAT_ContainerList, du2cu_new->uE_CapabilityRAT_ContainerList_length); - } - if (req->cu_to_du_rrc_information->handoverPreparationInfo != NULL) { - cu_to_du_rrc_information_t *du2cu_new = f1ap_msg->cu_to_du_rrc_information; - DevAssert(du2cu_req->handoverPreparationInfo_length > 0); - du2cu_new->handoverPreparationInfo_length = du2cu_req->handoverPreparationInfo_length; - du2cu_new->handoverPreparationInfo = malloc_or_fail(du2cu_new->handoverPreparationInfo_length); - memcpy(du2cu_new->handoverPreparationInfo, du2cu_req->handoverPreparationInfo, du2cu_new->handoverPreparationInfo_length); - } - } - if (req->drbs_to_be_setup_length > 0) { - int n = req->drbs_to_be_setup_length; - f1ap_msg->drbs_to_be_setup_length = n; - f1ap_msg->drbs_to_be_setup = calloc(n, sizeof(*f1ap_msg->drbs_to_be_setup)); - AssertFatal(f1ap_msg->drbs_to_be_setup != NULL, "out of memory\n"); - memcpy(f1ap_msg->drbs_to_be_setup, req->drbs_to_be_setup, n * sizeof(*f1ap_msg->drbs_to_be_setup)); - } - if (req->srbs_to_be_setup_length > 0) { - int n = req->srbs_to_be_setup_length; - f1ap_msg->srbs_to_be_setup_length = n; - f1ap_msg->srbs_to_be_setup = calloc(n, sizeof(*f1ap_msg->srbs_to_be_setup)); - AssertFatal(f1ap_msg->srbs_to_be_setup != NULL, "out of memory\n"); - memcpy(f1ap_msg->srbs_to_be_setup, req->srbs_to_be_setup, n * sizeof(*f1ap_msg->srbs_to_be_setup)); - } - if (req->rrc_container_length > 0) { - f1ap_msg->rrc_container = calloc(req->rrc_container_length, sizeof(*f1ap_msg->rrc_container)); - AssertFatal(f1ap_msg->rrc_container != NULL, "out of memory\n"); - f1ap_msg->rrc_container_length = req->rrc_container_length; - memcpy(f1ap_msg->rrc_container, req->rrc_container, req->rrc_container_length); - } + F1AP_UE_CONTEXT_SETUP_REQ(msg) = cp_ue_context_setup_req(req); itti_send_msg_to_task(TASK_CU_F1, 0, msg); } -static void ue_context_modification_request_f1ap(sctp_assoc_t assoc_id, const f1ap_ue_context_modif_req_t *req) +static void ue_context_modification_request_f1ap(sctp_assoc_t assoc_id, const f1ap_ue_context_mod_req_t *req) { MessageDef *msg = itti_alloc_new_message(TASK_RRC_GNB, 0, F1AP_UE_CONTEXT_MODIFICATION_REQ); msg->ittiMsgHeader.originInstance = assoc_id; - f1ap_ue_context_modif_req_t *f1ap_msg = &F1AP_UE_CONTEXT_MODIFICATION_REQ(msg); - *f1ap_msg = *req; - if (req->cu_to_du_rrc_information != NULL) { - f1ap_msg->cu_to_du_rrc_information = calloc(1, sizeof(*f1ap_msg->cu_to_du_rrc_information)); - AssertFatal(f1ap_msg->cu_to_du_rrc_information != NULL, "out of memory\n"); - AssertFatal(req->cu_to_du_rrc_information->cG_ConfigInfo == NULL && req->cu_to_du_rrc_information->cG_ConfigInfo_length == 0, "cg_ConfigInfo not implemented\n"); - AssertFatal(req->cu_to_du_rrc_information->measConfig == NULL && req->cu_to_du_rrc_information->measConfig_length == 0, "cg_ConfigInfo not implemented\n"); - if (req->cu_to_du_rrc_information->uE_CapabilityRAT_ContainerList != NULL) { - const cu_to_du_rrc_information_t *du2cu_req = req->cu_to_du_rrc_information; - cu_to_du_rrc_information_t* du2cu_new = f1ap_msg->cu_to_du_rrc_information; - DevAssert(du2cu_req->uE_CapabilityRAT_ContainerList_length > 0); - du2cu_new->uE_CapabilityRAT_ContainerList_length = du2cu_req->uE_CapabilityRAT_ContainerList_length; - du2cu_new->uE_CapabilityRAT_ContainerList = malloc(du2cu_new->uE_CapabilityRAT_ContainerList_length); - AssertFatal(du2cu_new->uE_CapabilityRAT_ContainerList != NULL, "out of memory\n"); - memcpy(du2cu_new->uE_CapabilityRAT_ContainerList, du2cu_req->uE_CapabilityRAT_ContainerList, du2cu_new->uE_CapabilityRAT_ContainerList_length); - } - } - AssertFatal(req->drbs_to_be_modified_length == 0, "drbs_to_be_modified not supported yet\n"); - if (req->drbs_to_be_setup_length > 0) { - int n = req->drbs_to_be_setup_length; - f1ap_msg->drbs_to_be_setup_length = n; - f1ap_msg->drbs_to_be_setup = calloc(n, sizeof(*f1ap_msg->drbs_to_be_setup)); - AssertFatal(f1ap_msg->drbs_to_be_setup != NULL, "out of memory\n"); - memcpy(f1ap_msg->drbs_to_be_setup, req->drbs_to_be_setup, n * sizeof(*f1ap_msg->drbs_to_be_setup)); - } - if (req->srbs_to_be_setup_length > 0) { - int n = req->srbs_to_be_setup_length; - f1ap_msg->srbs_to_be_setup_length = n; - f1ap_msg->srbs_to_be_setup = calloc(n, sizeof(*f1ap_msg->srbs_to_be_setup)); - AssertFatal(f1ap_msg->srbs_to_be_setup != NULL, "out of memory\n"); - memcpy(f1ap_msg->srbs_to_be_setup, req->srbs_to_be_setup, n * sizeof(*f1ap_msg->srbs_to_be_setup)); - } - if (req->drbs_to_be_released_length > 0) { - int n = req->drbs_to_be_released_length; - f1ap_msg->drbs_to_be_released_length = n; - f1ap_msg->drbs_to_be_released = calloc(n, sizeof(*f1ap_msg->drbs_to_be_released)); - AssertFatal(f1ap_msg->drbs_to_be_released != NULL, "out of memory\n"); - memcpy(f1ap_msg->drbs_to_be_released, req->drbs_to_be_released, n * sizeof(*f1ap_msg->drbs_to_be_released)); - } - if (req->rrc_container_length > 0) { - f1ap_msg->rrc_container = calloc(req->rrc_container_length, sizeof(*f1ap_msg->rrc_container)); - AssertFatal(f1ap_msg->rrc_container != NULL, "out of memory\n"); - f1ap_msg->rrc_container_length = req->rrc_container_length; - memcpy(f1ap_msg->rrc_container, req->rrc_container, req->rrc_container_length); - } - if (req->transm_action_ind != NULL) { - f1ap_msg->transm_action_ind = malloc(sizeof *f1ap_msg->transm_action_ind); - AssertFatal(f1ap_msg->transm_action_ind != NULL, "out of memory\n"); - *f1ap_msg->transm_action_ind = *req->transm_action_ind; - } + F1AP_UE_CONTEXT_MODIFICATION_REQ(msg) = cp_ue_context_mod_req(req); itti_send_msg_to_task(TASK_CU_F1, 0, msg); } @@ -215,18 +119,11 @@ static void ue_context_modification_refuse_f1ap(sctp_assoc_t assoc_id, const f1a itti_send_msg_to_task(TASK_CU_F1, 0, msg); } -static void ue_context_release_command_f1ap(sctp_assoc_t assoc_id, const f1ap_ue_context_release_cmd_t *cmd) +static void ue_context_release_command_f1ap(sctp_assoc_t assoc_id, const f1ap_ue_context_rel_cmd_t *cmd) { MessageDef *message_p = itti_alloc_new_message (TASK_RRC_GNB, 0, F1AP_UE_CONTEXT_RELEASE_CMD); message_p->ittiMsgHeader.originInstance = assoc_id; - f1ap_ue_context_release_cmd_t *msg = &F1AP_UE_CONTEXT_RELEASE_CMD(message_p); - *msg = *cmd; - if (cmd->rrc_container_length > 0) { - msg->rrc_container = calloc(cmd->rrc_container_length, sizeof(*msg->rrc_container)); - AssertFatal(msg->rrc_container != NULL, "out of memory\n"); - msg->rrc_container_length = cmd->rrc_container_length; - memcpy(msg->rrc_container, cmd->rrc_container, cmd->rrc_container_length); - } + F1AP_UE_CONTEXT_RELEASE_CMD(message_p) = cp_ue_context_rel_cmd(cmd); itti_send_msg_to_task (TASK_CU_F1, 0, message_p); } diff --git a/openair2/RRC/NR/nr_rrc_proto.h b/openair2/RRC/NR/nr_rrc_proto.h index 3a4fed6411..094f1791c1 100644 --- a/openair2/RRC/NR/nr_rrc_proto.h +++ b/openair2/RRC/NR/nr_rrc_proto.h @@ -44,7 +44,7 @@ #define SRB2 2 void rrc_add_nsa_user(gNB_RRC_INST *rrc, x2ap_ENDC_sgnb_addition_req_t *m, sctp_assoc_t assoc_id); -void rrc_add_nsa_user_resp(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, const f1ap_ue_context_setup_t *resp); +void rrc_add_nsa_user_resp(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, const f1ap_ue_context_setup_resp_t *resp); void rrc_release_nsa_user(gNB_RRC_INST *rrc, rrc_gNB_ue_context_t *ue_context); void rrc_remove_nsa_user_context(gNB_RRC_INST *rrc, rrc_gNB_ue_context_t *ue_context); @@ -106,15 +106,13 @@ int rrc_gNB_generate_pcch_msg(sctp_assoc_t assoc_id, const NR_SIB1_t *sib, uint3 void rrc_gNB_generate_UeContextSetupRequest(const gNB_RRC_INST *rrc, rrc_gNB_ue_context_t *const ue_context_pP, - int n_drbs, - const f1ap_drb_to_be_setup_t *drbs); + const e1ap_bearer_setup_resp_t *resp); void rrc_gNB_generate_UeContextModificationRequest(const gNB_RRC_INST *rrc, rrc_gNB_ue_context_t *const ue_context_pP, - int n_drbs, - const f1ap_drb_to_be_setup_t *drbs, + const e1ap_bearer_setup_resp_t *resp, int n_rel_drbs, - const f1ap_drb_to_be_released_t *rel_drbs); + const f1ap_drb_to_release_t *rel_drbs); void free_RRCReconfiguration_params(nr_rrc_reconfig_param_t params); @@ -123,6 +121,6 @@ byte_array_t rrc_gNB_encode_RRCReconfiguration(gNB_RRC_INST *rrc, gNB_RRC_UE_t * nr_rrc_reconfig_param_t get_RRCReconfiguration_params(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, uint8_t srb_reest_bitmap, bool drb_reestablish); pdusession_level_qos_parameter_t *get_qos_characteristics(const int qfi, rrc_pdu_session_param_t *pduSession); -f1ap_qos_characteristics_t get_qos_char_from_qos_flow_param(const pdusession_level_qos_parameter_t *qos_param); +f1ap_qos_flow_param_t get_qos_char_from_qos_flow_param(const pdusession_level_qos_parameter_t *qos_param); void openair_rrc_gNB_configuration(gNB_RRC_INST *rrc, gNB_RrcConfigurationReq *configuration); #endif diff --git a/openair2/RRC/NR/rrc_gNB.c b/openair2/RRC/NR/rrc_gNB.c index 520dc469d0..8c04754df7 100644 --- a/openair2/RRC/NR/rrc_gNB.c +++ b/openair2/RRC/NR/rrc_gNB.c @@ -78,8 +78,9 @@ #include "oai_asn1.h" #include "openair2/F1AP/f1ap_common.h" #include "openair2/F1AP/f1ap_ids.h" -#include "openair2/F1AP/lib/f1ap_lib_extern.h" -#include "lib/f1ap_interface_management.h" +#include "openair2/F1AP/lib/f1ap_rrc_message_transfer.h" +#include "openair2/F1AP/lib/f1ap_interface_management.h" +#include "openair2/F1AP/lib/f1ap_ue_context.h" #include "rrc_gNB_NGAP.h" #include "rrc_gNB_du.h" #include "rrc_gNB_mobility.h" @@ -112,7 +113,7 @@ mui_t rrc_gNB_mui = 0; typedef struct deliver_ue_ctxt_release_data_t { gNB_RRC_INST *rrc; - f1ap_ue_context_release_cmd_t *release_cmd; + f1ap_ue_context_rel_cmd_t *release_cmd; sctp_assoc_t assoc_id; } deliver_ue_ctxt_release_data_t; @@ -120,8 +121,8 @@ static void rrc_deliver_ue_ctxt_release_cmd(void *deliver_pdu_data, ue_id_t ue_i { DevAssert(deliver_pdu_data != NULL); deliver_ue_ctxt_release_data_t *data = deliver_pdu_data; - data->release_cmd->rrc_container = (uint8_t*) buf; - data->release_cmd->rrc_container_length = size; + byte_array_t rrc_cont = {.buf = (uint8_t *)buf, .len = size}; + data->release_cmd->rrc_container = &rrc_cont; data->rrc->mac_rrc.ue_context_release_command(data->assoc_id, data->release_cmd); } @@ -891,6 +892,7 @@ static void cuup_notify_reestablishment(gNB_RRC_INST *rrc, gNB_RRC_UE_t *ue_p) /* Send E1 Bearer Context Modification Request (3GPP TS 38.463) */ sctp_assoc_t assoc_id = get_existing_cuup_for_ue(rrc, ue_p); rrc->cucp_cuup.bearer_context_mod(assoc_id, &req); + free_e1ap_context_mod_request(&req); } /** @@ -1546,7 +1548,7 @@ static void handle_ueCapabilityInformation(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, ue_cap_info->criticalExtensions.choice.ueCapabilityInformation->ue_CapabilityRAT_ContainerList; /* Encode UE-CapabilityRAT-ContainerList for sending to the DU */ - free(UE->ue_cap_buffer.buf); + FREE_AND_ZERO_BYTE_ARRAY(UE->ue_cap_buffer); UE->ue_cap_buffer.len = uper_encode_to_new_buffer(&asn_DEF_NR_UE_CapabilityRAT_ContainerList, NULL, ue_CapabilityRAT_ContainerList, @@ -1774,12 +1776,14 @@ static void handle_rrcReconfigurationComplete(gNB_RRC_INST *rrc, gNB_RRC_UE_t *U f1_ue_data_t ue_data = cu_get_f1_ue_data(UE->rrc_ue_id); RETURN_IF_INVALID_ASSOC_ID(ue_data.du_assoc_id); - f1ap_ue_context_modif_req_t ue_context_modif_req = { + ReconfigurationCompl_t rc = RRCreconf_success; + f1ap_ue_context_mod_req_t req = { .gNB_CU_ue_id = UE->rrc_ue_id, .gNB_DU_ue_id = ue_data.secondary_ue, - .ReconfigComplOutcome = RRCreconf_success, + .reconfig_compl = &rc, }; - rrc->mac_rrc.ue_context_modification_request(ue_data.du_assoc_id, &ue_context_modif_req); + rrc->mac_rrc.ue_context_modification_request(ue_data.du_assoc_id, &req); + /* nothing to be freed */ } static void rrc_gNB_generate_UECapabilityEnquiry(gNB_RRC_INST *rrc, gNB_RRC_UE_t *ue) @@ -1996,10 +2000,10 @@ void rrc_gNB_process_dc_overall_timeout(const module_id_t gnb_mod_idP, x2ap_ENDC /* \brief fill E1 bearer modification's DRB from F1 DRB * \param drb_e1 pointer to a DRB inside an E1 bearer modification message * \param drb_f1 pointer to a DRB inside an F1 UE Ctxt modification Response */ -static void fill_e1_bearer_modif(DRB_nGRAN_to_mod_t *drb_e1, const f1ap_drb_to_be_setup_t *drb_f1) +static void fill_e1_bearer_modif(DRB_nGRAN_to_mod_t *drb_e1, const f1ap_drb_setup_t *drb_f1) { - drb_e1->id = drb_f1->drb_id; - drb_e1->numDlUpParam = drb_f1->up_dl_tnl_length; + drb_e1->id = drb_f1->id; + drb_e1->numDlUpParam = drb_f1->up_dl_tnl_len; drb_e1->DlUpParamList[0].tl_info.tlAddress = drb_f1->up_dl_tnl[0].tl_address; drb_e1->DlUpParamList[0].tl_info.teId = drb_f1->up_dl_tnl[0].teid; } @@ -2016,20 +2020,20 @@ static gtpu_tunnel_t f1u_gtp_update(uint32_t teid, const in_addr_t addr) /** * @brief Update DRB TEID information in RRC storage from received DRB list */ -static void store_du_f1u_tunnel(const f1ap_drb_to_be_setup_t *drbs, int n, gNB_RRC_UE_t *ue) +static void store_du_f1u_tunnel(const f1ap_drb_setup_t *drbs, int n, gNB_RRC_UE_t *ue) { for (int i = 0; i < n; i++) { - const f1ap_drb_to_be_setup_t *drb_f1 = &drbs[i]; - AssertFatal(drb_f1->up_dl_tnl_length == 1, "can handle only one UP param\n"); - AssertFatal(drb_f1->drb_id < MAX_DRBS_PER_UE, "illegal DRB ID %ld\n", drb_f1->drb_id); - drb_t *drb = get_drb(ue, drb_f1->drb_id); + const f1ap_drb_setup_t *drb_f1 = &drbs[i]; + AssertFatal(drb_f1->up_dl_tnl_len == 1, "can handle only one UP param\n"); + AssertFatal(drb_f1->id < MAX_DRBS_PER_UE, "illegal DRB ID %d\n", drb_f1->id); + drb_t *drb = get_drb(ue, drb_f1->id); drb->du_tunnel_config = f1u_gtp_update(drb_f1->up_dl_tnl[0].teid, drb_f1->up_dl_tnl[0].tl_address); } } /* \brief use list of DRBs and send the corresponding bearer update message via * E1 to the CU of this UE. Also updates TEID info internally */ -static void e1_send_bearer_updates(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, int n, f1ap_drb_to_be_setup_t *drbs) +static void e1_send_bearer_updates(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, int n, f1ap_drb_setup_t *drbs) { // Quit bearer updates if no CU-UP is associated if (!is_cuup_associated(rrc)) { @@ -2043,10 +2047,10 @@ static void e1_send_bearer_updates(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, int n, f }; for (int i = 0; i < n; i++) { - const f1ap_drb_to_be_setup_t *drb_f1 = &drbs[i]; - rrc_pdu_session_param_t *pdu_ue = find_pduSession_from_drbId(UE, drb_f1->drb_id); + const f1ap_drb_setup_t *drb_f1 = &drbs[i]; + rrc_pdu_session_param_t *pdu_ue = find_pduSession_from_drbId(UE, drb_f1->id); if (pdu_ue == NULL) { - LOG_E(RRC, "UE %d: UE Context Modif Response: no PDU session for DRB ID %ld\n", UE->rrc_ue_id, drb_f1->drb_id); + LOG_E(RRC, "UE %d: UE Context Modif Response: no PDU session for DRB ID %d\n", UE->rrc_ue_id, drb_f1->id); continue; } pdu_session_to_mod_t *pdu_e1 = find_or_next_pdu_session(&req, pdu_ue->param.pdusession_id); @@ -2071,7 +2075,7 @@ static void e1_send_bearer_updates(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, int n, f static void rrc_CU_process_ue_context_setup_response(MessageDef *msg_p, instance_t instance) { - f1ap_ue_context_setup_t *resp = &F1AP_UE_CONTEXT_SETUP_RESP(msg_p); + f1ap_ue_context_setup_resp_t *resp = &F1AP_UE_CONTEXT_SETUP_RESP(msg_p); gNB_RRC_INST *rrc = RC.nrrrc[instance]; rrc_gNB_ue_context_t *ue_context_p = rrc_gNB_get_ue_context(rrc, resp->gNB_CU_ue_id); if (!ue_context_p) { @@ -2082,11 +2086,9 @@ static void rrc_CU_process_ue_context_setup_response(MessageDef *msg_p, instance UE->f1_ue_context_active = true; NR_CellGroupConfig_t *cellGroupConfig = NULL; - asn_dec_rval_t dec_rval = uper_decode_complete(NULL, - &asn_DEF_NR_CellGroupConfig, - (void **)&cellGroupConfig, - (uint8_t *)resp->du_to_cu_rrc_information->cellGroupConfig, - resp->du_to_cu_rrc_information->cellGroupConfig_length); + byte_array_t *cgc = &resp->du_to_cu_rrc_info.cell_group_config; + asn_dec_rval_t dec_rval = + uper_decode_complete(NULL, &asn_DEF_NR_CellGroupConfig, (void **)&cellGroupConfig, (uint8_t *)cgc->buf, cgc->len); AssertFatal(dec_rval.code == RC_OK && dec_rval.consumed > 0, "Cell group config decode error\n"); if (UE->masterCellGroup) { @@ -2102,16 +2104,16 @@ static void rrc_CU_process_ue_context_setup_response(MessageDef *msg_p, instance return; } - if (resp->drbs_to_be_setup_length > 0) { + if (resp->drbs_len > 0) { int num_drb = get_number_active_drbs(UE); - DevAssert(num_drb == 0 || num_drb == resp->drbs_to_be_setup_length); + DevAssert(num_drb == 0 || num_drb == resp->drbs_len); /* Note: we would ideally check that SRB2 is acked, but at least LiteOn DU * seems buggy and does not ack, so simply check that locally we activated */ AssertFatal(UE->Srb[1].Active && UE->Srb[2].Active, "SRBs 1 and 2 must be active during DRB Establishment"); - store_du_f1u_tunnel(resp->drbs_to_be_setup, resp->drbs_to_be_setup_length, UE); + store_du_f1u_tunnel(resp->drbs, resp->drbs_len, UE); if (num_drb == 0) - e1_send_bearer_updates(rrc, UE, resp->drbs_to_be_setup_length, resp->drbs_to_be_setup); + e1_send_bearer_updates(rrc, UE, resp->drbs_len, resp->drbs); else cuup_notify_reestablishment(rrc, UE); } @@ -2132,7 +2134,7 @@ static void rrc_CU_process_ue_context_setup_response(MessageDef *msg_p, instance static void rrc_CU_process_ue_context_release_request(MessageDef *msg_p, sctp_assoc_t assoc_id) { const int instance = 0; - f1ap_ue_context_release_req_t *req = &F1AP_UE_CONTEXT_RELEASE_REQ(msg_p); + f1ap_ue_context_rel_req_t *req = &F1AP_UE_CONTEXT_RELEASE_REQ(msg_p); gNB_RRC_INST *rrc = RC.nrrrc[instance]; rrc_gNB_ue_context_t *ue_context_p = rrc_gNB_get_ue_context(rrc, req->gNB_CU_ue_id); // TODO what happens if no AMF connected? should also handle, set an_release true @@ -2141,12 +2143,12 @@ static void rrc_CU_process_ue_context_release_request(MessageDef *msg_p, sctp_as LOG_W(RRC, "could not find UE context for CU UE ID %u: auto-generate release command\n", req->gNB_CU_ue_id); uint8_t buffer[NR_RRC_BUF_SIZE] = {0}; int size = do_NR_RRCRelease(buffer, NR_RRC_BUF_SIZE, rrc_gNB_get_next_transaction_identifier(0)); - f1ap_ue_context_release_cmd_t ue_context_release_cmd = { + f1ap_ue_context_rel_cmd_t ue_context_release_cmd = { .gNB_CU_ue_id = req->gNB_CU_ue_id, .gNB_DU_ue_id = req->gNB_DU_ue_id, .cause = F1AP_CAUSE_RADIO_NETWORK, .cause_value = 10, // 10 = F1AP_CauseRadioNetwork_normal_release - .srb_id = srbid, + .srb_id = &srbid, // C-ifRRCContainer => is added below }; deliver_ue_ctxt_release_data_t data = {.rrc = rrc, .release_cmd = &ue_context_release_cmd}; nr_pdcp_data_req_srb(req->gNB_CU_ue_id, srbid, rrc_gNB_mui++, size, buffer, rrc_deliver_ue_ctxt_release_cmd, &data); @@ -2162,12 +2164,11 @@ static void rrc_CU_process_ue_context_release_request(MessageDef *msg_p, sctp_as // ongoing; free the UE, and remove the HO context. LOG_W(NR_RRC, "UE %d: release request from source DU ID %ld during HO, marking HO as complete\n", UE->rrc_ue_id, source_ctx->du->setup_req->gNB_DU_id); RETURN_IF_INVALID_ASSOC_ID(source_ctx->du->assoc_id); - f1ap_ue_context_release_cmd_t cmd = { + f1ap_ue_context_rel_cmd_t cmd = { .gNB_CU_ue_id = UE->rrc_ue_id, .gNB_DU_ue_id = source_ctx->du_ue_id, .cause = F1AP_CAUSE_RADIO_NETWORK, .cause_value = 5, // 5 = F1AP_CauseRadioNetwork_interaction_with_other_procedure - .srb_id = DL_SCH_LCID_DCCH, }; rrc->mac_rrc.ue_context_release_command(assoc_id, &cmd); nr_rrc_finalize_ho(UE); @@ -2189,6 +2190,7 @@ static void rrc_delete_ue_data(gNB_RRC_UE_t *UE) ASN_STRUCT_FREE(asn_DEF_NR_UE_NR_Capability, UE->UE_Capability_nr); ASN_STRUCT_FREE(asn_DEF_NR_CellGroupConfig, UE->masterCellGroup); ASN_STRUCT_FREE(asn_DEF_NR_MeasResults, UE->measResults); + FREE_AND_ZERO_BYTE_ARRAY(UE->ue_cap_buffer); free_MeasConfig(UE->measConfig); } @@ -2207,7 +2209,7 @@ void rrc_remove_ue(gNB_RRC_INST *rrc, rrc_gNB_ue_context_t *ue_context_p) static void rrc_CU_process_ue_context_release_complete(MessageDef *msg_p) { const int instance = 0; - f1ap_ue_context_release_complete_t *complete = &F1AP_UE_CONTEXT_RELEASE_COMPLETE(msg_p); + f1ap_ue_context_rel_cplt_t *complete = &F1AP_UE_CONTEXT_RELEASE_COMPLETE(msg_p); gNB_RRC_INST *rrc = RC.nrrrc[instance]; rrc_gNB_ue_context_t *ue_context_p = rrc_gNB_get_ue_context(rrc, complete->gNB_CU_ue_id); if (!ue_context_p) { @@ -2229,7 +2231,7 @@ static void rrc_CU_process_ue_context_release_complete(MessageDef *msg_p) static void rrc_CU_process_ue_context_modification_response(MessageDef *msg_p, instance_t instance) { - f1ap_ue_context_modif_resp_t *resp = &F1AP_UE_CONTEXT_MODIFICATION_RESP(msg_p); + f1ap_ue_context_mod_resp_t *resp = &F1AP_UE_CONTEXT_MODIFICATION_RESP(msg_p); gNB_RRC_INST *rrc = RC.nrrrc[instance]; rrc_gNB_ue_context_t *ue_context_p = rrc_gNB_get_ue_context(rrc, resp->gNB_CU_ue_id); if (!ue_context_p) { @@ -2238,18 +2240,16 @@ static void rrc_CU_process_ue_context_modification_response(MessageDef *msg_p, i } gNB_RRC_UE_t *UE = &ue_context_p->ue_context; - if (resp->drbs_to_be_setup_length > 0) { - store_du_f1u_tunnel(resp->drbs_to_be_setup, resp->drbs_to_be_setup_length, UE); - e1_send_bearer_updates(rrc, UE, resp->drbs_to_be_setup_length, resp->drbs_to_be_setup); + if (resp->drbs_len > 0) { + store_du_f1u_tunnel(resp->drbs, resp->drbs_len, UE); + e1_send_bearer_updates(rrc, UE, resp->drbs_len, resp->drbs); } - if (resp->du_to_cu_rrc_information != NULL && resp->du_to_cu_rrc_information->cellGroupConfig != NULL) { + if (resp->du_to_cu_rrc_info) { NR_CellGroupConfig_t *cellGroupConfig = NULL; - asn_dec_rval_t dec_rval = uper_decode_complete(NULL, - &asn_DEF_NR_CellGroupConfig, - (void **)&cellGroupConfig, - (uint8_t *)resp->du_to_cu_rrc_information->cellGroupConfig, - resp->du_to_cu_rrc_information->cellGroupConfig_length); + byte_array_t *cgc = &resp->du_to_cu_rrc_info->cell_group_config; + asn_dec_rval_t dec_rval = + uper_decode_complete(NULL, &asn_DEF_NR_CellGroupConfig, (void **)&cellGroupConfig, (uint8_t *)cgc->buf, cgc->len); AssertFatal(dec_rval.code == RC_OK && dec_rval.consumed > 0, "Cell group config decode error\n"); if (UE->masterCellGroup) { @@ -2364,18 +2364,26 @@ pdusession_level_qos_parameter_t *get_qos_characteristics(const int qfi, rrc_pdu } /* \bref return F1AP QoS characteristics based on Qos flow parameters */ -f1ap_qos_characteristics_t get_qos_char_from_qos_flow_param(const pdusession_level_qos_parameter_t *qos_param) +f1ap_qos_flow_param_t get_qos_char_from_qos_flow_param(const pdusession_level_qos_parameter_t *qos_param) { - f1ap_qos_characteristics_t qos_char = {0}; + f1ap_qos_flow_param_t qos_char = {0}; 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; + qos_char.dyn.prio = qos_param->qos_priority; + qos_char.dyn.pdb = 100; // TODO + qos_char.dyn.per.scalar = 10; // TODO + qos_char.dyn.per.exponent = 100; // TODO } else { 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; + qos_char.nondyn.fiveQI = qos_param->fiveQI; } + const ngap_allocation_retention_priority_t *a = &qos_param->allocation_retention_priority; + qos_char.arp.prio = a->priority_level; + qos_char.arp.preempt_cap = a->pre_emp_capability == NGAP_PRE_EMPTION_CAPABILITY_MAY_TRIGGER_PREEMPTION + ? MAY_TRIGGER_PREEMPTION + : SHALL_NOT_TRIGGER_PREEMPTION; + qos_char.arp.preempt_vuln = + a->pre_emp_vulnerability == NGAP_PRE_EMPTION_VULNERABILITY_PREEMPTABLE ? PREEMPTABLE : NOT_PREEMPTABLE; return qos_char; } @@ -2385,38 +2393,52 @@ static int fill_drb_to_be_setup_from_e1_resp(const gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, const pdu_session_setup_t *pduSession, int numPduSession, - f1ap_drb_to_be_setup_t drbs[32]) + f1ap_drb_to_setup_t drbs[32]) { int nb_drb = 0; for (int p = 0; p < numPduSession; ++p) { - rrc_pdu_session_param_t *RRC_pduSession = find_pduSession(UE, pduSession[p].id, false); - DevAssert(RRC_pduSession); + rrc_pdu_session_param_t *pdu = find_pduSession(UE, pduSession[p].id, false); + DevAssert(pdu); for (int i = 0; i < pduSession[p].numDRBSetup; i++) { 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 ? F1AP_RLC_MODE_UM_BIDIR : F1AP_RLC_MODE_AM; - drb->up_ul_tnl[0].tl_address = drb_config->UpParamList[0].tl_info.tlAddress; - drb->up_ul_tnl[0].port = rrc->eth_params_s.my_portd; - drb->up_ul_tnl[0].teid = drb_config->UpParamList[0].tl_info.teId; - drb->up_ul_tnl_length = 1; + drb_t *rrc_drb = get_drb(UE, pduSession[p].DRBnGRanList[i].id); + DevAssert(rrc_drb); + + f1ap_drb_to_setup_t *drb = &drbs[nb_drb]; + drb->id = rrc_drb->drb_id; + + drb->qos_choice = F1AP_QOS_CHOICE_NR; /* pass QoS info to MAC */ int nb_qos_flows = drb_config->numQosFlowSetup; AssertFatal(nb_qos_flows > 0, "must map at least one flow to a DRB\n"); - drb->drb_info.flows_to_be_setup_length = nb_qos_flows; - drb->drb_info.flows_mapped_to_drb = calloc(nb_qos_flows, sizeof(f1ap_flows_mapped_to_drb_t)); - AssertFatal(drb->drb_info.flows_mapped_to_drb, "could not allocate memory\n"); + drb->nr.flows_len = nb_qos_flows; + drb->nr.flows = calloc_or_fail(nb_qos_flows, sizeof(*drb->nr.flows)); for (int j = 0; j < nb_qos_flows; j++) { - drb->drb_info.flows_mapped_to_drb[j].qfi = drb_config->qosFlows[j].qfi; - pdusession_level_qos_parameter_t *in_qos_char = get_qos_characteristics(drb_config->qosFlows[j].qfi, RRC_pduSession); - drb->drb_info.flows_mapped_to_drb[j].qos_params.qos_characteristics = get_qos_char_from_qos_flow_param(in_qos_char); + int qfi = drb_config->qosFlows[j].qfi; + /* find the QoS characteristics stored at RRC based on QFI returned + * from E1. We expect this to correspond to a QFI we passed to E1 + * previously, so we expect it to exist. */ + pdusession_level_qos_parameter_t *qos_param = get_qos_characteristics(qfi, pdu); + DevAssert(qos_param); + f1ap_drb_flows_mapped_t *flow = &drb->nr.flows[j]; + flow->qfi = qfi; + flow->param = get_qos_char_from_qos_flow_param(qos_param); } /* the DRB QoS parameters: we just reuse the ones from the first flow */ - drb->drb_info.drb_qos = drb->drb_info.flows_mapped_to_drb[0].qos_params; + drb->nr.drb_qos = drb->nr.flows[0].param; /* pass NSSAI info to MAC */ - drb->nssai = RRC_pduSession->param.nssai; + drb->nr.nssai = pdu->param.nssai; + + drb->up_ul_tnl[0].tl_address = drb_config->UpParamList[0].tl_info.tlAddress; + drb->up_ul_tnl[0].teid = drb_config->UpParamList[0].tl_info.teId; + drb->up_ul_tnl_len = 1; + drb->rlc_mode = rrc->configuration.um_on_default_drb ? F1AP_RLC_MODE_UM_BIDIR : F1AP_RLC_MODE_AM; + drb->dl_pdcp_sn_len = malloc_or_fail(sizeof(*drb->dl_pdcp_sn_len)); + *drb->dl_pdcp_sn_len = rrc_drb->pdcp_config.pdcp_SN_SizeDL == 1 ? F1AP_PDCP_SN_18B : F1AP_PDCP_SN_12B; + drb->ul_pdcp_sn_len = malloc_or_fail(sizeof(*drb->ul_pdcp_sn_len)); + *drb->ul_pdcp_sn_len = rrc_drb->pdcp_config.pdcp_SN_SizeUL == 1 ? F1AP_PDCP_SN_18B : F1AP_PDCP_SN_12B; nb_drb++; } @@ -2462,14 +2484,10 @@ void rrc_gNB_process_e1_bearer_context_setup_resp(e1ap_bearer_setup_resp_t *resp } } - /* Instruction towards the DU for DRB configuration and tunnel creation */ - f1ap_drb_to_be_setup_t drbs[32]; // maximum DRB can be 32 - int nb_drb = fill_drb_to_be_setup_from_e1_resp(rrc, UE, resp->pduSession, resp->numPDUSessions, drbs); - if (!UE->f1_ue_context_active) - rrc_gNB_generate_UeContextSetupRequest(rrc, ue_context_p, nb_drb, drbs); + rrc_gNB_generate_UeContextSetupRequest(rrc, ue_context_p, resp); else - rrc_gNB_generate_UeContextModificationRequest(rrc, ue_context_p, nb_drb, drbs, 0, NULL); + rrc_gNB_generate_UeContextModificationRequest(rrc, ue_context_p, resp, 0, NULL); } /** @brief E1AP Bearer Context Setup Failure processing on CU-CP */ @@ -2744,10 +2762,12 @@ void *rrc_gnb_task(void *args_p) { case F1AP_UE_CONTEXT_SETUP_RESP: rrc_CU_process_ue_context_setup_response(msg_p, instance); + free_ue_context_setup_resp(&F1AP_UE_CONTEXT_SETUP_RESP(msg_p)); break; case F1AP_UE_CONTEXT_MODIFICATION_RESP: rrc_CU_process_ue_context_modification_response(msg_p, instance); + free_ue_context_mod_resp(&F1AP_UE_CONTEXT_MODIFICATION_RESP(msg_p)); break; case F1AP_UE_CONTEXT_MODIFICATION_REQUIRED: @@ -2756,10 +2776,12 @@ void *rrc_gnb_task(void *args_p) { case F1AP_UE_CONTEXT_RELEASE_REQ: rrc_CU_process_ue_context_release_request(msg_p, msg_p->ittiMsgHeader.originInstance); + free_ue_context_rel_req(&F1AP_UE_CONTEXT_RELEASE_REQ(msg_p)); break; case F1AP_UE_CONTEXT_RELEASE_COMPLETE: rrc_CU_process_ue_context_release_complete(msg_p); + free_ue_context_rel_cplt(&F1AP_UE_CONTEXT_RELEASE_COMPLETE(msg_p)); break; case F1AP_LOST_CONNECTION: @@ -2894,12 +2916,13 @@ void rrc_gNB_generate_RRCRelease(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE) LOG_UE_DL_EVENT(UE, "Send RRC Release\n"); f1_ue_data_t ue_data = cu_get_f1_ue_data(UE->rrc_ue_id); RETURN_IF_INVALID_ASSOC_ID(ue_data.du_assoc_id); - f1ap_ue_context_release_cmd_t ue_context_release_cmd = { + int srbid = 1; + f1ap_ue_context_rel_cmd_t ue_context_release_cmd = { .gNB_CU_ue_id = UE->rrc_ue_id, .gNB_DU_ue_id = ue_data.secondary_ue, .cause = F1AP_CAUSE_RADIO_NETWORK, .cause_value = 10, // 10 = F1AP_CauseRadioNetwork_normal_release - .srb_id = DL_SCH_LCID_DCCH, + .srb_id = &srbid, // C-ifRRCContainer => is added below }; deliver_ue_ctxt_release_data_t data = {.rrc = rrc, .release_cmd = &ue_context_release_cmd, .assoc_id = ue_data.du_assoc_id}; nr_pdcp_data_req_srb(UE->rrc_ue_id, DL_SCH_LCID_DCCH, rrc_gNB_mui++, size, buffer, rrc_deliver_ue_ctxt_release_cmd, &data); @@ -3000,8 +3023,7 @@ int rrc_gNB_generate_pcch_msg(sctp_assoc_t assoc_id, const NR_SIB1_t *sib1, uint //----------------------------------------------------------------------------- void rrc_gNB_generate_UeContextSetupRequest(const gNB_RRC_INST *rrc, rrc_gNB_ue_context_t *const ue_context_pP, - int n_drbs, - const f1ap_drb_to_be_setup_t *drbs) + const e1ap_bearer_setup_resp_t *resp) //----------------------------------------------------------------------------- { gNB_RRC_UE_t *ue_p = &ue_context_pP->ue_context; @@ -3009,47 +3031,56 @@ void rrc_gNB_generate_UeContextSetupRequest(const gNB_RRC_INST *rrc, AssertFatal(!NODE_IS_DU(rrc->node_type), "illegal node type DU!\n"); - cu_to_du_rrc_information_t cu2du = {0}; - cu_to_du_rrc_information_t *cu2du_p = NULL; - if (ue_p->ue_cap_buffer.len > 0 && ue_p->ue_cap_buffer.buf != NULL) { - cu2du_p = &cu2du; - cu2du.uE_CapabilityRAT_ContainerList = ue_p->ue_cap_buffer.buf; - cu2du.uE_CapabilityRAT_ContainerList_length = ue_p->ue_cap_buffer.len; + f1ap_cu_to_du_rrc_info_t cu2du = {0}; + if (ue_p->ue_cap_buffer.len > 0) { + cu2du.ue_cap = malloc_or_fail(sizeof(byte_array_t)); + *cu2du.ue_cap = copy_byte_array(ue_p->ue_cap_buffer); } int nb_srb = 1; - f1ap_srb_to_be_setup_t srbs[1] = {{.srb_id = 2, .lcid = 2}}; - activate_srb(ue_p, 2); + f1ap_srb_to_setup_t *srbs = calloc_or_fail(nb_srb, sizeof(*srbs)); + srbs[0].id = 2; + activate_srb(ue_p, srbs[0].id); + + /* Instruction towards the DU for DRB configuration and tunnel creation */ + f1ap_drb_to_setup_t *drbs = calloc_or_fail(32, sizeof(*drbs)); // maximum DRB can be 32 + int n_drbs = fill_drb_to_be_setup_from_e1_resp(rrc, ue_p, resp->pduSession, resp->numPDUSessions, drbs); + + /* gNB-DU UE Aggregate Maximum Bit Rate Uplink is C- ifDRBSetup */ + uint64_t *agg_mbr = malloc_or_fail(sizeof(*agg_mbr)); + *agg_mbr = 1000000000 /* bps */; - /* the callback will fill the UE context setup request and forward it */ f1_ue_data_t ue_data = cu_get_f1_ue_data(ue_p->rrc_ue_id); RETURN_IF_INVALID_ASSOC_ID(ue_data.du_assoc_id); - f1ap_ue_context_setup_t ue_context_setup_req = { + uint32_t *du_ue_id = malloc_or_fail(sizeof(*du_ue_id)); + *du_ue_id = ue_data.secondary_ue; + f1ap_ue_context_setup_req_t ue_context_setup_req = { .gNB_CU_ue_id = ue_p->rrc_ue_id, - .gNB_DU_ue_id = ue_data.secondary_ue, + .gNB_DU_ue_id = du_ue_id, .plmn.mcc = rrc->configuration.plmn[0].mcc, .plmn.mnc = rrc->configuration.plmn[0].mnc, .plmn.mnc_digit_length = rrc->configuration.plmn[0].mnc_digit_length, .nr_cellid = rrc->nr_cellid, - .servCellId = 0, /* TODO: correct value? */ - .srbs_to_be_setup_length = nb_srb, - .srbs_to_be_setup = srbs, - .drbs_to_be_setup_length = n_drbs, - .drbs_to_be_setup = (f1ap_drb_to_be_setup_t *)drbs, - .cu_to_du_rrc_information = cu2du_p, + .servCellIndex = 0, /* TODO: correct value? */ + .srbs_len = nb_srb, + .srbs = srbs, + .drbs_len = n_drbs, + .drbs = drbs, + .cu_to_du_rrc_info = cu2du, + .gnb_du_ue_agg_mbr_ul = agg_mbr, }; rrc->mac_rrc.ue_context_setup_request(ue_data.du_assoc_id, &ue_context_setup_req); + free_ue_context_setup_req(&ue_context_setup_req); LOG_I(RRC, "UE %d trigger UE context setup request with %d DRBs\n", ue_p->rrc_ue_id, n_drbs); } //----------------------------------------------------------------------------- void rrc_gNB_generate_UeContextModificationRequest(const gNB_RRC_INST *rrc, rrc_gNB_ue_context_t *const ue_context_pP, - int n_drbs, - const f1ap_drb_to_be_setup_t *drbs, + const e1ap_bearer_setup_resp_t *resp, int n_rel_drbs, - const f1ap_drb_to_be_released_t *rel_drbs) + const f1ap_drb_to_release_t *rel_drbs) //----------------------------------------------------------------------------- { gNB_RRC_UE_t *ue_p = &ue_context_pP->ue_context; @@ -3058,30 +3089,32 @@ void rrc_gNB_generate_UeContextModificationRequest(const gNB_RRC_INST *rrc, AssertFatal(!NODE_IS_DU(rrc->node_type), "illegal node type DU!\n"); - cu_to_du_rrc_information_t cu2du = {0}; - cu_to_du_rrc_information_t *cu2du_p = NULL; - if (ue_p->ue_cap_buffer.len > 0 && ue_p->ue_cap_buffer.buf != NULL) { - cu2du_p = &cu2du; - cu2du.uE_CapabilityRAT_ContainerList = ue_p->ue_cap_buffer.buf; - cu2du.uE_CapabilityRAT_ContainerList_length = ue_p->ue_cap_buffer.len; + f1ap_cu_to_du_rrc_info_t *cu2du = NULL; + if (ue_p->ue_cap_buffer.len > 0) { + cu2du = calloc_or_fail(1, sizeof(*cu2du)); + cu2du->ue_cap = calloc_or_fail(1, sizeof(*cu2du->ue_cap)); + *cu2du->ue_cap = copy_byte_array(ue_p->ue_cap_buffer); } + /* Instruction towards the DU for DRB configuration and tunnel creation */ + f1ap_drb_to_setup_t *drbs = calloc_or_fail(32, sizeof(*drbs)); // maximum DRB can be 32 + int n_drbs = fill_drb_to_be_setup_from_e1_resp(rrc, ue_p, resp->pduSession, resp->numPDUSessions, drbs); + f1_ue_data_t ue_data = cu_get_f1_ue_data(ue_p->rrc_ue_id); RETURN_IF_INVALID_ASSOC_ID(ue_data.du_assoc_id); - f1ap_ue_context_modif_req_t ue_context_modif_req = { + f1ap_ue_context_mod_req_t ue_context_modif_req = { .gNB_CU_ue_id = ue_p->rrc_ue_id, .gNB_DU_ue_id = ue_data.secondary_ue, - .plmn.mcc = rrc->configuration.plmn[0].mcc, - .plmn.mnc = rrc->configuration.plmn[0].mnc, - .plmn.mnc_digit_length = rrc->configuration.plmn[0].mnc_digit_length, - .nr_cellid = rrc->nr_cellid, - .servCellId = 0, /* TODO: correct value? */ - .drbs_to_be_setup_length = n_drbs, - .drbs_to_be_setup = (f1ap_drb_to_be_setup_t *)drbs, - .drbs_to_be_released_length = n_rel_drbs, - .drbs_to_be_released = (f1ap_drb_to_be_released_t *)rel_drbs, - .cu_to_du_rrc_information = cu2du_p, + .drbs_len = n_drbs, + .drbs = drbs, + .drbs_rel_len = n_rel_drbs, + .drbs_rel = (f1ap_drb_to_release_t *)rel_drbs, + .cu_to_du_rrc_info = cu2du, }; rrc->mac_rrc.ue_context_modification_request(ue_data.du_assoc_id, &ue_context_modif_req); + // avoid attempt to release rel_drbs + ue_context_modif_req.drbs_rel_len = 0; + ue_context_modif_req.drbs_rel = NULL; + free_ue_context_mod_req(&ue_context_modif_req); LOG_I(RRC, "UE %d trigger UE context modification request with %d DRBs\n", ue_p->rrc_ue_id, n_drbs); } diff --git a/openair2/RRC/NR/rrc_gNB_du.c b/openair2/RRC/NR/rrc_gNB_du.c index a650a03604..868a7fb64a 100644 --- a/openair2/RRC/NR/rrc_gNB_du.c +++ b/openair2/RRC/NR/rrc_gNB_du.c @@ -437,6 +437,7 @@ void rrc_gNB_process_f1_setup_req(f1ap_setup_req_t *req, sctp_assoc_t assoc_id) if (rrc->node_name != NULL) resp.gNB_CU_name = strdup(rrc->node_name); rrc->mac_rrc.f1_setup_response(assoc_id, &resp); + free_f1ap_setup_response(&resp); /* we need to setup one default UE for phy-test and do-ra modes in the MAC */ if (get_softmodem_params()->phy_test > 0 || get_softmodem_params()->do_ra > 0) @@ -600,9 +601,12 @@ void rrc_CU_process_f1_lost_connection(gNB_RRC_INST *rrc, f1ap_lost_connection_t ASN_STRUCT_FREE(asn_DEF_NR_MIB, du->mib); ASN_STRUCT_FREE(asn_DEF_NR_SIB1, du->sib1); ASN_STRUCT_FREE(asn_DEF_NR_MeasurementTimingConfiguration, du->mtc); - /* TODO: free setup request */ + if (du->setup_req) + free_f1ap_setup_request(du->setup_req); + free(du->setup_req); nr_rrc_du_container_t *removed = RB_REMOVE(rrc_du_tree, &rrc->dus, du); DevAssert(removed != NULL); + free(du); rrc->num_dus--; int num = invalidate_du_connections(rrc, assoc_id); diff --git a/openair2/RRC/NR/rrc_gNB_mobility.c b/openair2/RRC/NR/rrc_gNB_mobility.c index 647f253989..85c9597371 100644 --- a/openair2/RRC/NR/rrc_gNB_mobility.c +++ b/openair2/RRC/NR/rrc_gNB_mobility.c @@ -31,6 +31,7 @@ #include "rrc_gNB_UE_context.h" #include "openair2/LAYER2/NR_MAC_COMMON/nr_mac.h" #include "openair2/F1AP/f1ap_ids.h" +#include "openair2/F1AP/lib/f1ap_ue_context.h" #include "MESSAGES/asn1_msg.h" #include "nr_pdcp/nr_pdcp_oai_api.h" #include "openair3/SECU/key_nas_deriver.h" @@ -61,7 +62,7 @@ static void free_ho_ctx(nr_handover_context_t *ho_ctx) free(ho_ctx); } -static int fill_drb_to_be_setup(const gNB_RRC_INST *rrc, gNB_RRC_UE_t *ue, f1ap_drb_to_be_setup_t drbs[MAX_DRBS_PER_UE]) +static int fill_drb_to_be_setup(const gNB_RRC_INST *rrc, gNB_RRC_UE_t *ue, f1ap_drb_to_setup_t drbs[MAX_DRBS_PER_UE]) { int nb_drb = 0; for (int i = 0; i < MAX_DRBS_PER_UE; ++i) { @@ -69,34 +70,38 @@ static int fill_drb_to_be_setup(const gNB_RRC_INST *rrc, gNB_RRC_UE_t *ue, f1ap_ if (rrc_drb->status == DRB_INACTIVE) continue; - f1ap_drb_to_be_setup_t *drb = &drbs[nb_drb]; + f1ap_drb_to_setup_t *drb = &drbs[nb_drb]; nb_drb++; - drb->drb_id = rrc_drb->drb_id; - drb->rlc_mode = rrc->configuration.um_on_default_drb ? F1AP_RLC_MODE_UM_BIDIR : F1AP_RLC_MODE_AM; - memcpy(&drb->up_ul_tnl[0].tl_address, &rrc_drb->cuup_tunnel_config.addr.buffer, sizeof(uint8_t) * 4); - drb->up_ul_tnl[0].port = rrc->eth_params_s.my_portd; - drb->up_ul_tnl[0].teid = rrc_drb->cuup_tunnel_config.teid; - drb->up_ul_tnl_length = 1; - /* fetch an existing PDU session for this DRB */ - rrc_pdu_session_param_t *pdu = find_pduSession_from_drbId(ue, drb->drb_id); - AssertFatal(pdu != NULL, "no PDU session for DRB ID %ld\n", drb->drb_id); - drb->nssai = pdu->param.nssai; - + rrc_pdu_session_param_t *pdu = find_pduSession_from_drbId(ue, rrc_drb->drb_id); + AssertFatal(pdu != NULL, "no PDU session for DRB ID %d\n", rrc_drb->drb_id); // for the moment, we only support one QoS flow. Put a reminder in case // this changes AssertFatal(pdu->param.nb_qos == 1, "only 1 Qos flow supported\n"); - drb->drb_info.flows_to_be_setup_length = 1; - drb->drb_info.flows_mapped_to_drb = calloc_or_fail(1, sizeof(drb->drb_info.flows_mapped_to_drb[0])); - AssertFatal(drb->drb_info.flows_mapped_to_drb, "could not allocate memory\n"); int qfi = rrc_drb->cnAssociation.sdap_config.mappedQoS_FlowsToAdd[0]; - DevAssert(qfi > 0); - drb->drb_info.flows_mapped_to_drb[0].qfi = qfi; - pdusession_level_qos_parameter_t *in_qos_char = get_qos_characteristics(qfi, pdu); - drb->drb_info.flows_mapped_to_drb[0].qos_params.qos_characteristics = get_qos_char_from_qos_flow_param(in_qos_char); + pdusession_level_qos_parameter_t *qos_param = get_qos_characteristics(qfi, pdu); + drb->id = rrc_drb->drb_id; + + drb->qos_choice = F1AP_QOS_CHOICE_NR; + drb->nr.nssai = pdu->param.nssai; + drb->nr.flows_len = 1; + drb->nr.flows = calloc_or_fail(1, sizeof(*drb->nr.flows)); + DevAssert(qfi > 0); + drb->nr.flows[0].qfi = qfi; + drb->nr.flows[0].param = get_qos_char_from_qos_flow_param(qos_param); /* the DRB QoS parameters: we just reuse the ones from the first flow */ - drb->drb_info.drb_qos = drb->drb_info.flows_mapped_to_drb[0].qos_params; + drb->nr.drb_qos = drb->nr.flows[0].param; + + memcpy(&drb->up_ul_tnl[0].tl_address, &rrc_drb->cuup_tunnel_config.addr.buffer, sizeof(uint8_t) * 4); + drb->up_ul_tnl[0].teid = rrc_drb->cuup_tunnel_config.teid; + drb->up_ul_tnl_len = 1; + + drb->rlc_mode = rrc->configuration.um_on_default_drb ? F1AP_RLC_MODE_UM_BIDIR : F1AP_RLC_MODE_AM; + drb->dl_pdcp_sn_len = malloc_or_fail(sizeof(*drb->dl_pdcp_sn_len)); + *drb->dl_pdcp_sn_len = rrc_drb->pdcp_config.pdcp_SN_SizeDL == 1 ? F1AP_PDCP_SN_18B : F1AP_PDCP_SN_12B; + drb->ul_pdcp_sn_len = malloc_or_fail(sizeof(*drb->ul_pdcp_sn_len)); + *drb->ul_pdcp_sn_len = rrc_drb->pdcp_config.pdcp_SN_SizeUL == 1 ? F1AP_PDCP_SN_18B : F1AP_PDCP_SN_12B;; } return nb_drb; } @@ -168,32 +173,38 @@ static void nr_initiate_handover(const gNB_RRC_INST *rrc, target_du->assoc_id, target_du->setup_req->cell[0].info.nr_pci); - cu_to_du_rrc_information_t cu2du = { - .handoverPreparationInfo = ho_prep_info->buf, - .handoverPreparationInfo_length = ho_prep_info->len, - }; - - f1ap_drb_to_be_setup_t drbs[MAX_DRBS_PER_UE] = {0}; + f1ap_drb_to_setup_t *drbs = calloc_or_fail(MAX_DRBS_PER_UE, sizeof(*drbs)); int nb_drb = fill_drb_to_be_setup(rrc, ue, drbs); - f1ap_srb_to_be_setup_t srbs[2] = {{.srb_id = 1, .lcid = 1}, {.srb_id = 2, .lcid = 2}}; + int nb_srb = 2; + f1ap_srb_to_setup_t *srbs = calloc_or_fail(nb_srb, sizeof(*srbs)); + srbs[0].id = 1; + srbs[1].id = 2; + + byte_array_t *hpi = malloc_or_fail(sizeof(*hpi)); + *hpi = copy_byte_array(*ho_prep_info); + + uint64_t *ue_agg_mbr = malloc_or_fail(sizeof(*ue_agg_mbr)); + *ue_agg_mbr = 1000000000 /*bps*/; + f1ap_served_cell_info_t *cell_info = &target_du->setup_req->cell[0].info; RETURN_IF_INVALID_ASSOC_ID(target_du->assoc_id); - f1ap_ue_context_setup_t ue_context_setup_req = { + f1ap_ue_context_setup_req_t ue_context_setup_req = { .gNB_CU_ue_id = ue->rrc_ue_id, - .gNB_DU_ue_id = 0, /* TODO: this should be optional! */ .plmn.mcc = cell_info->plmn.mcc, .plmn.mnc = cell_info->plmn.mnc, .plmn.mnc_digit_length = cell_info->plmn.mnc_digit_length, .nr_cellid = cell_info->nr_cellid, - .servCellId = 0, // TODO: correct value? - .srbs_to_be_setup_length = 2, - .srbs_to_be_setup = srbs, - .drbs_to_be_setup_length = nb_drb, - .drbs_to_be_setup = drbs, - .cu_to_du_rrc_information = &cu2du, + .servCellIndex = 0, // TODO: correct value? + .srbs_len = nb_srb, + .srbs = srbs, + .drbs_len = nb_drb, + .drbs = drbs, + .cu_to_du_rrc_info.ho_prep_info = hpi, + .gnb_du_ue_agg_mbr_ul = ue_agg_mbr, }; rrc->mac_rrc.ue_context_setup_request(target_du->assoc_id, &ue_context_setup_req); + free_ue_context_setup_req(&ue_context_setup_req); } /* @@ -214,15 +225,15 @@ void nr_rrc_trigger_n2_ho(gNB_RRC_INST *rrc, int nr_cgi, uint8_t *ho_prep_info, typedef struct deliver_ue_ctxt_modification_data_t { gNB_RRC_INST *rrc; - f1ap_ue_context_modif_req_t *modification_req; + f1ap_ue_context_mod_req_t *modification_req; sctp_assoc_t assoc_id; } deliver_ue_ctxt_modification_data_t; static void rrc_deliver_ue_ctxt_modif_req(void *deliver_pdu_data, ue_id_t ue_id, int srb_id, char *buf, int size, int sdu_id) { DevAssert(deliver_pdu_data != NULL); deliver_ue_ctxt_modification_data_t *data = deliver_pdu_data; - data->modification_req->rrc_container = (uint8_t*)buf; - data->modification_req->rrc_container_length = size; + byte_array_t ba = {.buf = (uint8_t *) buf, .len = size}; + data->modification_req->rrc_container = &ba; data->rrc->mac_rrc.ue_context_modification_request(data->assoc_id, data->modification_req); } static void rrc_gNB_trigger_reconfiguration_for_handover(gNB_RRC_INST *rrc, gNB_RRC_UE_t *ue, uint8_t *rrc_reconf, int rrc_reconf_len) @@ -231,12 +242,9 @@ static void rrc_gNB_trigger_reconfiguration_for_handover(gNB_RRC_INST *rrc, gNB_ TransmActionInd_t transmission_action_indicator = TransmActionInd_STOP; RETURN_IF_INVALID_ASSOC_ID(ue_data.du_assoc_id); - f1ap_ue_context_modif_req_t ue_context_modif_req = { + f1ap_ue_context_mod_req_t ue_context_modif_req = { .gNB_CU_ue_id = ue->rrc_ue_id, .gNB_DU_ue_id = ue_data.secondary_ue, - .plmn = rrc->configuration.plmn[0], - .nr_cellid = rrc->nr_cellid, // TODO target cell ID - .servCellId = 0, // TODO: correct value? .transm_action_ind = &transmission_action_indicator, }; deliver_ue_ctxt_modification_data_t data = {.rrc = rrc, @@ -277,6 +285,7 @@ static void nr_rrc_f1_ho_acknowledge(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE) DevAssert(UE->ho_context->source != NULL); rrc_gNB_trigger_reconfiguration_for_handover(rrc, UE, buffer.buf, buffer.len); LOG_A(NR_RRC, "HO acknowledged: Send reconfiguration for UE %u/RNTI %04x...\n", UE->rrc_ue_id, UE->rnti); + free_byte_array(buffer); /* Re-establish SRB2 according to clause 5.3.5.6.3 of 3GPP TS 38.331 * (SRB1 is re-established with RRCReestablishment message) @@ -299,12 +308,11 @@ static void nr_rrc_f1_ho_complete(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE) nr_ho_source_cu_t *source_ctx = UE->ho_context->source; DevAssert(source_ctx != NULL); RETURN_IF_INVALID_ASSOC_ID(source_ctx->du->assoc_id); - f1ap_ue_context_release_cmd_t cmd = { + f1ap_ue_context_rel_cmd_t cmd = { .gNB_CU_ue_id = UE->rrc_ue_id, .gNB_DU_ue_id = source_ctx->du_ue_id, .cause = F1AP_CAUSE_RADIO_NETWORK, .cause_value = 5, // 5 = F1AP_CauseRadioNetwork_interaction_with_other_procedure - .srb_id = DL_SCH_LCID_DCCH, }; rrc->mac_rrc.ue_context_release_command(source_ctx->du->assoc_id, &cmd); LOG_I(NR_RRC, "UE %d Handover: trigger release on DU assoc_id %d\n", UE->rrc_ue_id, source_ctx->du->assoc_id); @@ -315,12 +323,11 @@ static void nr_rrc_cancel_f1_ho(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE) DevAssert(UE->ho_context != NULL); nr_ho_target_cu_t *target_ctx = UE->ho_context->target; DevAssert(target_ctx != NULL); - f1ap_ue_context_release_cmd_t cmd = { + f1ap_ue_context_rel_cmd_t cmd = { .gNB_CU_ue_id = UE->rrc_ue_id, .gNB_DU_ue_id = target_ctx->du_ue_id, .cause = F1AP_CAUSE_RADIO_NETWORK, // better .cause_value = 5, // 5 = F1AP_CauseRadioNetwork_interaction_with_other_procedure - .srb_id = DL_SCH_LCID_DCCH, }; rrc->mac_rrc.ue_context_release_command(target_ctx->du->assoc_id, &cmd); } diff --git a/openair2/RRC/NR/rrc_gNB_nsa.c b/openair2/RRC/NR/rrc_gNB_nsa.c index 8ac172a21e..d0cc63062b 100644 --- a/openair2/RRC/NR/rrc_gNB_nsa.c +++ b/openair2/RRC/NR/rrc_gNB_nsa.c @@ -71,18 +71,13 @@ #include "xer_decoder.h" #include "xer_encoder.h" #include "f1ap_common.h" +#include "lib/f1ap_ue_context.h" // In case of phy-test and do-ra mode, read UE capabilities directly from file // and put it into a CG-ConfigInfo field static int cg_config_info_from_ue_cap_file(uint32_t maxlen, uint8_t buf[maxlen]) { - NR_CG_ConfigInfo_t *cgci = calloc_or_fail(1, sizeof(*cgci)); - cgci->criticalExtensions.present = NR_CG_ConfigInfo__criticalExtensions_PR_c1; - cgci->criticalExtensions.choice.c1 = calloc_or_fail(1, sizeof(*cgci->criticalExtensions.choice.c1)); - cgci->criticalExtensions.choice.c1->present = NR_CG_ConfigInfo__criticalExtensions__c1_PR_cg_ConfigInfo; - NR_CG_ConfigInfo_IEs_t *cgci_ies = calloc_or_fail(1, sizeof(*cgci_ies)); - cgci->criticalExtensions.choice.c1->choice.cg_ConfigInfo = cgci_ies; - + OCTET_STRING_t *os_cap = NULL; if (uecap_file != NULL) { LOG_I(NR_RRC, "creating CG-ConfigInfo from UE capability file %s\n", uecap_file); @@ -103,14 +98,22 @@ static int cg_config_info_from_ue_cap_file(uint32_t maxlen, uint8_t buf[maxlen]) DevAssert(dec_rval.code == RC_OK); //xer_fprint(stdout, &asn_DEF_NR_UE_NR_Capability, cap); - OCTET_STRING_t *os_cap = calloc_or_fail(1, sizeof(*os_cap)); + os_cap = calloc_or_fail(1, sizeof(*os_cap)); os_cap->size = uper_encode_to_new_buffer(&asn_DEF_NR_UE_NR_Capability, NULL, cap, (void **)&os_cap->buf); - cgci_ies->ue_CapabilityInfo = os_cap; } + NR_CG_ConfigInfo_t *cgci = calloc_or_fail(1, sizeof(*cgci)); + cgci->criticalExtensions.present = NR_CG_ConfigInfo__criticalExtensions_PR_c1; + cgci->criticalExtensions.choice.c1 = calloc_or_fail(1, sizeof(*cgci->criticalExtensions.choice.c1)); + cgci->criticalExtensions.choice.c1->present = NR_CG_ConfigInfo__criticalExtensions__c1_PR_cg_ConfigInfo; + NR_CG_ConfigInfo_IEs_t *cgci_ies = calloc_or_fail(1, sizeof(*cgci_ies)); + cgci->criticalExtensions.choice.c1->choice.cg_ConfigInfo = cgci_ies; + cgci_ies->ue_CapabilityInfo = os_cap; + //xer_fprint(stdout, &asn_DEF_NR_CG_ConfigInfo, cgci); asn_enc_rval_t rval = uper_encode_to_buffer(&asn_DEF_NR_CG_ConfigInfo, NULL, cgci, buf, maxlen); DevAssert(rval.encoded > 0); + ASN_STRUCT_FREE(asn_DEF_NR_CG_ConfigInfo, cgci); return (rval.encoded + 7) >> 3; } @@ -137,18 +140,16 @@ void rrc_add_nsa_user(gNB_RRC_INST *rrc, x2ap_ENDC_sgnb_addition_req_t *m, sctp_ nr_pdcp_entity_security_keys_and_algos_t security_parameters = {0}; uint8_t tmp[1024]; - uint8_t *cgci_buf = NULL; - uint32_t cgci_len = 0; + byte_array_t cgci = {0}; if (get_softmodem_params()->phy_test == 1 || get_softmodem_params()->do_ra == 1) { DevAssert(m == NULL); UE->rb_config = get_default_rbconfig(10 /* EPS bearer ID */, 1 /* drb ID */, NR_CipheringAlgorithm_nea0, NR_SecurityConfig__keyToUse_master, &rrc->pdcp_config); - cgci_len = cg_config_info_from_ue_cap_file(sizeof tmp, tmp); - DevAssert(cgci_len > 0); - cgci_buf = tmp; + int len = cg_config_info_from_ue_cap_file(sizeof tmp, tmp); + DevAssert(len > 0); + cgci = create_byte_array(len, tmp); } else { DevAssert(m != NULL); - cgci_buf = m->rrc_buffer; - cgci_len = m->rrc_buffer_size; + cgci = create_byte_array(m->rrc_buffer_size, m->rrc_buffer); /* TODO: handle more than one bearer */ if (m->nb_e_rabs_tobeadded != 1) { @@ -272,25 +273,24 @@ void rrc_add_nsa_user(gNB_RRC_INST *rrc, x2ap_ENDC_sgnb_addition_req_t *m, sctp_ UE->rb_config->drb_ToAddModList, &security_parameters); - cu_to_du_rrc_information_t cu2du = { - .cG_ConfigInfo = cgci_buf, - .cG_ConfigInfo_length = cgci_len, - }; /* assumption: only a single bearer, see above */ NR_DRB_ToAddModList_t *rb_list = UE->rb_config->drb_ToAddModList; AssertFatal(rb_list->list.count == 1, "can only handle one bearer for NSA/phy-test/do-ra, but has %d\n", rb_list->list.count); int drb_id = rb_list->list.array[0]->drb_Identity; - f1ap_flows_mapped_to_drb_t *flow = calloc(1, sizeof(f1ap_flows_mapped_to_drb_t)); - flow->qos_params.qos_characteristics.qos_type = NON_DYNAMIC; - flow->qfi = flow->qos_params.qos_characteristics.non_dynamic.fiveqi = 9; - f1ap_drb_to_be_setup_t drbs = { - .drb_id = drb_id, - .rlc_mode = F1AP_RLC_MODE_UM_BIDIR, // hardcoded keep it backwards compatible for now - // rrc->configuration.um_on_default_drb ? F1AP_RLC_MODE_UM_BIDIR : F1AP_RLC_MODE_AM, - .up_ul_tnl_length = 1, - .drb_info.flows_to_be_setup_length = 1, - .drb_info.flows_mapped_to_drb = flow, - }; + f1ap_drb_to_setup_t *drb = calloc_or_fail(1, sizeof(*drb)); + drb->id = drb_id; + // hardcoded keep it backwards compatible for now + // rrc->configuration.um_on_default_drb ? F1AP_RLC_MODE_UM_BIDIR : F1AP_RLC_MODE_AM, + drb->rlc_mode = F1AP_RLC_MODE_UM_BIDIR; + drb->up_ul_tnl_len = 1; + drb->qos_choice = F1AP_QOS_CHOICE_NR; // we don't have EUTRAN yet, "approximate" it + drb->nr.flows_len = 1; + f1ap_drb_flows_mapped_t *flow = drb->nr.flows = calloc_or_fail(drb->nr.flows_len, sizeof(*flow)); + flow->qfi = 9; + flow->param.qos_type = NON_DYNAMIC; + flow->param.nondyn.fiveQI = 9; + flow->param.arp.prio = 5; + // Note: E1 support for NSA/phy-test/do-ra not implemented yet instance_t f1inst = get_f1_gtp_instance(); if (f1inst >= 0) { @@ -305,25 +305,30 @@ void rrc_add_nsa_user(gNB_RRC_INST *rrc, x2ap_ENDC_sgnb_addition_req_t *m, sctp_ gtpv1u_gnb_create_tunnel_resp_t resp = {0}; int ret = gtpv1u_create_ngu_tunnel(f1inst, &req, &resp, NULL, NULL); AssertFatal(ret == 0, "gtpv1u_create_ngu_tunnel failed: ret %d\n", ret); - drbs.up_ul_tnl[0].port = rrc->eth_params_s.my_portd; - memcpy(&drbs.up_ul_tnl[0].tl_address, &resp.gnb_addr.buffer, 4); - drbs.up_ul_tnl[0].teid = resp.gnb_NGu_teid[0]; + memcpy(&drb->up_ul_tnl[0].tl_address, &resp.gnb_addr.buffer, 4); + drb->up_ul_tnl[0].teid = resp.gnb_NGu_teid[0]; + drb->up_ul_tnl_len = 1; } - f1ap_ue_context_setup_t req = { + uint64_t *ue_agg_mbr_ul = malloc_or_fail(sizeof(*ue_agg_mbr_ul)); + *ue_agg_mbr_ul = 1000000000; + byte_array_t *cg_configinfo = malloc_or_fail(sizeof(*cg_configinfo)); + *cg_configinfo = cgci; + f1ap_ue_context_setup_req_t req = { .gNB_CU_ue_id = UE->rrc_ue_id, - .gNB_DU_ue_id = 0xffffffff, /* not known yet */ .plmn.mcc = rrc->configuration.plmn[0].mcc, .plmn.mnc = rrc->configuration.plmn[0].mnc, .plmn.mnc_digit_length = rrc->configuration.plmn[0].mnc_digit_length, .nr_cellid = rrc->nr_cellid, - .servCellId = 0, - .drbs_to_be_setup_length = 1, - .drbs_to_be_setup = &drbs, - .cu_to_du_rrc_information = &cu2du, + .servCellIndex = 0, + .drbs_len = 1, + .drbs = drb, + .cu_to_du_rrc_info.cg_configinfo = cg_configinfo, + .gnb_du_ue_agg_mbr_ul = ue_agg_mbr_ul, }; f1_ue_data_t ue_data = cu_get_f1_ue_data(UE->rrc_ue_id); RETURN_IF_INVALID_ASSOC_ID(ue_data.du_assoc_id); rrc->mac_rrc.ue_context_setup_request(ue_data.du_assoc_id, &req); + free_ue_context_setup_req(&req); } static NR_RRCReconfiguration_IEs_t *get_default_reconfig(const NR_CellGroupConfig_t *secondaryCellGroup) @@ -382,7 +387,7 @@ static NR_CG_Config_t *generate_CG_Config(const NR_RRCReconfiguration_t *reconfi return cg_Config; } -void rrc_add_nsa_user_resp(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, const f1ap_ue_context_setup_t *resp) +void rrc_add_nsa_user_resp(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, const f1ap_ue_context_setup_resp_t *resp) { DevAssert(resp->crnti != NULL); /* we did not fill any DU-related ID info in rrc_add_nsa_user() */ @@ -397,12 +402,12 @@ void rrc_add_nsa_user_resp(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, const f1ap_ue_co if (f1inst >= 0) { // Note: E1 support for NSA/phy-test/do-ra not implemented yet // so set up GTP from here - for (int i = 0; i < resp->drbs_to_be_setup_length; ++i) { - f1ap_drb_to_be_setup_t *drb = &resp->drbs_to_be_setup[i]; - DevAssert(drb->up_dl_tnl_length == 1); + for (int i = 0; i < resp->drbs_len; ++i) { + f1ap_drb_setup_t *drb = &resp->drbs[i]; + DevAssert(drb->up_dl_tnl_len == 1); in_addr_t addr = drb->up_dl_tnl[0].tl_address; uint32_t teid = drb->up_dl_tnl[0].teid; - GtpuUpdateTunnelOutgoingAddressAndTeid(f1inst, UE->rrc_ue_id, drb->drb_id, addr, teid); + GtpuUpdateTunnelOutgoingAddressAndTeid(f1inst, UE->rrc_ue_id, drb->id, addr, teid); } } @@ -412,6 +417,7 @@ void rrc_add_nsa_user_resp(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, const f1ap_ue_co reconfig->criticalExtensions.choice.rrcReconfiguration = get_default_reconfig(UE->masterCellGroup); NR_CG_Config_t *CG_Config = generate_CG_Config(reconfig, UE->rb_config); + ASN_STRUCT_FREE(asn_DEF_NR_RRCReconfiguration, reconfig); if (get_softmodem_params()->phy_test > 0 || get_softmodem_params()->do_ra > 0) { /* we are done, no X2 answer necessary */ @@ -461,7 +467,7 @@ void rrc_release_nsa_user(gNB_RRC_INST *rrc, rrc_gNB_ue_context_t *ue_context) gNB_RRC_UE_t *UE = &ue_context->ue_context; f1_ue_data_t ue_data = cu_get_f1_ue_data(UE->rrc_ue_id); RETURN_IF_INVALID_ASSOC_ID(ue_data.du_assoc_id); - f1ap_ue_context_release_cmd_t cmd = { + f1ap_ue_context_rel_cmd_t cmd = { .gNB_CU_ue_id = UE->rrc_ue_id, .gNB_DU_ue_id = ue_data.secondary_ue, .cause = F1AP_CAUSE_RADIO_NETWORK, diff --git a/openair2/RRC/NR/rrc_gNB_radio_bearers.c b/openair2/RRC/NR/rrc_gNB_radio_bearers.c index 7bed45ee64..5112029f87 100644 --- a/openair2/RRC/NR/rrc_gNB_radio_bearers.c +++ b/openair2/RRC/NR/rrc_gNB_radio_bearers.c @@ -58,6 +58,7 @@ rrc_pdu_session_param_t *find_pduSession(gNB_RRC_UE_t *ue, int id, bool create) rrc_pdu_session_param_t *find_pduSession_from_drbId(gNB_RRC_UE_t *ue, int drb_id) { + DevAssert(drb_id > 0 && drb_id <= 32); const drb_t *drb = &ue->established_drbs[drb_id - 1]; if (drb->status == DRB_INACTIVE) { LOG_E(NR_RRC, "UE %d: DRB %d inactive\n", ue->rrc_ue_id, drb_id);