Merge remote-tracking branch 'origin/f1-refactor-ue-context' into integration_2025_wk26 (!3488)
Refactor F1 UE context messages, add unit tests Add encoder+decoder+util functions for F1 UE context messages, and use them in the stack. The overall goal is to unit test encoder+decoder (to be sure that what we send is what we receive), and remove any memory leaks related to F1 handling. Messages that have a unit test: - F1 UE context setup request/response - F1 UE context modification request/response - F1 UE context release request/command/complete This MR removes almost all remaining memory leaks that are observable in a "standard" configuration, running SISO in RFsim. In RFsim (without channel modelling), there are only two memory leaks shown in asan, one in L1, and one in NGAP.
This commit is contained in:
@@ -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"
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
#include <netinet/sctp.h>
|
||||
#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_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;
|
||||
|
||||
@@ -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:
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -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);
|
||||
|
||||
|
||||
@@ -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 <openair3/ocp-gtpu/gtp_itf.h>
|
||||
|
||||
@@ -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:
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -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);
|
||||
|
||||
|
||||
|
||||
@@ -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}
|
||||
|
||||
@@ -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];
|
||||
|
||||
@@ -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};
|
||||
|
||||
@@ -27,12 +27,14 @@
|
||||
#include <stdio.h>
|
||||
#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
|
||||
@@ -40,11 +42,7 @@
|
||||
#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__); \
|
||||
PRINT_ERROR("Equality condition '%s' failed: " fmt " != " fmt "\n", #condition, ##__VA_ARGS__); \
|
||||
return false; \
|
||||
} \
|
||||
} while (0)
|
||||
@@ -53,14 +51,27 @@
|
||||
#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);
|
||||
|
||||
|
||||
@@ -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_ */
|
||||
@@ -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_ */
|
||||
|
||||
@@ -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;
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -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 <stdbool.h>
|
||||
#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_ */
|
||||
@@ -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})
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
+151
-118
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
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,
|
||||
.up_ul_tnl_length = 1,
|
||||
.drb_info.flows_to_be_setup_length = 1,
|
||||
.drb_info.flows_mapped_to_drb = flow,
|
||||
};
|
||||
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,
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user