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:
Robert Schmidt
2025-06-30 18:40:02 +02:00
39 changed files with 3975 additions and 3608 deletions
+1 -1
View File
@@ -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"
+7 -7
View File
@@ -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)
+192 -112
View File
@@ -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;
+6 -4
View File
@@ -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);
+2
View File
@@ -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 -1
View File
@@ -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}
+18 -27
View File
@@ -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];
+23 -1
View File
@@ -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};
+47 -10
View File
@@ -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);
-27
View File
@@ -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_ */
+6
View File
@@ -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_ */
+19 -16
View File
@@ -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
+72
View File
@@ -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 -1
View File
@@ -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})
+560 -1
View File
@@ -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;
}
+1 -1
View File
@@ -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,
+103 -140
View File
@@ -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);
+4 -5
View File
@@ -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);
+10 -88
View File
@@ -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);
}
+10 -74
View File
@@ -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);
}
+4
View File
@@ -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)
+7 -3
View File
@@ -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,
+1 -1
View File
@@ -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);
+3 -3
View File
@@ -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);
+3 -3
View File
@@ -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);
+9 -112
View File
@@ -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);
}
+5 -7
View File
@@ -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
View File
@@ -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);
}
+5 -1
View File
@@ -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);
+54 -47
View File
@@ -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);
}
+51 -45
View File
@@ -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,
+1
View File
@@ -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);