diff --git a/CMakeLists.txt b/CMakeLists.txt index 5d37670c34..b00ca296cd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -453,6 +453,9 @@ target_include_directories(f1ap PUBLIC F1AP_DIR) target_link_libraries(f1ap PUBLIC asn1_f1ap GTPV1U) target_link_libraries(f1ap PRIVATE ngap nr_rrc HASHTABLE f1ap_lib) target_include_directories(f1ap PRIVATE ${F1AP_DIR}/lib) +if(E2_AGENT) + target_compile_definitions(f1ap PRIVATE E2_AGENT) +endif() # LPP ############## diff --git a/openair2/E2AP/RAN_FUNCTION/CMakeLists.txt b/openair2/E2AP/RAN_FUNCTION/CMakeLists.txt index 27497ae873..35699bc15a 100644 --- a/openair2/E2AP/RAN_FUNCTION/CMakeLists.txt +++ b/openair2/E2AP/RAN_FUNCTION/CMakeLists.txt @@ -1,4 +1,44 @@ +set(UE_ID_COMMON_E2SM_SRCS + ../flexric/src/sm/rc_sm/ie/asn/AMFPointer.c + ../flexric/src/sm/rc_sm/ie/asn/AMFRegionID.c + ../flexric/src/sm/rc_sm/ie/asn/AMFSetID.c + ../flexric/src/sm/rc_sm/ie/asn/AMF-UE-NGAP-ID.c + ../flexric/src/sm/rc_sm/ie/asn/ENB-ID.c + ../flexric/src/sm/rc_sm/ie/asn/ENB-UE-X2AP-ID-Extension.c + ../flexric/src/sm/rc_sm/ie/asn/ENB-UE-X2AP-ID.c + ../flexric/src/sm/rc_sm/ie/asn/GlobalENB-ID.c + ../flexric/src/sm/rc_sm/ie/asn/GlobalGNB-ID.c + ../flexric/src/sm/rc_sm/ie/asn/GlobalNgENB-ID.c + ../flexric/src/sm/rc_sm/ie/asn/GlobalNGRANNodeID.c + ../flexric/src/sm/rc_sm/ie/asn/GNB-CU-CP-UE-E1AP-ID.c + ../flexric/src/sm/rc_sm/ie/asn/GNB-CU-UE-F1AP-ID.c + ../flexric/src/sm/rc_sm/ie/asn/GNB-ID.c + ../flexric/src/sm/rc_sm/ie/asn/GUAMI.c + ../flexric/src/sm/rc_sm/ie/asn/GUMMEI.c + ../flexric/src/sm/rc_sm/ie/asn/MME-Code.c + ../flexric/src/sm/rc_sm/ie/asn/MME-Group-ID.c + ../flexric/src/sm/rc_sm/ie/asn/MME-UE-S1AP-ID.c + ../flexric/src/sm/rc_sm/ie/asn/NGENB-CU-UE-W1AP-ID.c + ../flexric/src/sm/rc_sm/ie/asn/NgENB-ID.c + ../flexric/src/sm/rc_sm/ie/asn/NG-RANnodeUEXnAPID.c + ../flexric/src/sm/rc_sm/ie/asn/PLMNIdentity.c + ../flexric/src/sm/rc_sm/ie/asn/RANUEID.c + ../flexric/src/sm/rc_sm/ie/asn/UEID-ENB.c + ../flexric/src/sm/rc_sm/ie/asn/UEID-EN-GNB.c + ../flexric/src/sm/rc_sm/ie/asn/UEID-GNB-CU-CP-E1AP-ID-Item.c + ../flexric/src/sm/rc_sm/ie/asn/UEID-GNB-CU-CP-E1AP-ID-List.c + ../flexric/src/sm/rc_sm/ie/asn/UEID-GNB-CU-CP-F1AP-ID-Item.c + ../flexric/src/sm/rc_sm/ie/asn/UEID-GNB-CU-F1AP-ID-List.c + ../flexric/src/sm/rc_sm/ie/asn/UEID-GNB-CU-UP.c + ../flexric/src/sm/rc_sm/ie/asn/UEID-GNB-DU.c + ../flexric/src/sm/rc_sm/ie/asn/UEID-GNB.c + ../flexric/src/sm/rc_sm/ie/asn/UEID.c + ../flexric/src/sm/rc_sm/ie/asn/UEID-NG-ENB-DU.c + ../flexric/src/sm/rc_sm/ie/asn/UEID-NG-ENB.c +) + add_library(e2_ran_func_cuup STATIC + ${UE_ID_COMMON_E2SM_SRCS} init_ran_func.c read_setup_ran.c O-RAN/ran_e2sm_ue_id.c @@ -13,11 +53,12 @@ add_library(e2_ran_func_cuup STATIC ../flexric/test/rnd/fill_rnd_data_tc.c ) -target_link_libraries(e2_ran_func_cuup PUBLIC asn1_nr_rrc nr_rrc asn1_nr_rrc_hdrs e2_time_obj kpm_ric_info_common_obj 3gpp_derived_ie_obj e2sm_rc_ir_obj sm_common_ie_obj ds alg) +target_link_libraries(e2_ran_func_cuup PUBLIC asn1_nr_rrc nr_rrc asn1_nr_rrc_hdrs e2_time_obj kpm_ric_info_common_obj 3gpp_derived_ie_obj e2sm_rc_ir_obj sm_common_ie_obj ds alg sm_common_enc_asn_obj_rc 3gpp_derived_ie_enc_asn_obj_rc) target_compile_definitions(e2_ran_func_cuup PUBLIC ${E2AP_VERSION} ${KPM_VERSION} NGRAN_GNB_CUUP) add_library(e2_ran_func_du_cucp_cuup STATIC + ${UE_ID_COMMON_E2SM_SRCS} init_ran_func.c read_setup_ran.c O-RAN/ran_e2sm_ue_id.c @@ -36,7 +77,7 @@ add_library(e2_ran_func_du_cucp_cuup STATIC ../flexric/test/rnd/fill_rnd_data_tc.c ) -target_link_libraries(e2_ran_func_du_cucp_cuup PUBLIC asn1_nr_rrc nr_rrc asn1_nr_rrc_hdrs e2_time_obj kpm_ric_info_common_obj 3gpp_derived_ie_obj e2sm_rc_ir_obj sm_common_ie_obj ds) +target_link_libraries(e2_ran_func_du_cucp_cuup PUBLIC asn1_nr_rrc nr_rrc asn1_nr_rrc_hdrs e2_time_obj kpm_ric_info_common_obj 3gpp_derived_ie_obj e2sm_rc_ir_obj sm_common_ie_obj ds sm_common_enc_asn_obj_rc 3gpp_derived_ie_enc_asn_obj_rc) target_compile_definitions(e2_ran_func_du_cucp_cuup PUBLIC ${E2AP_VERSION} ${KPM_VERSION} NGRAN_GNB_DU NGRAN_GNB_CUCP NGRAN_GNB_CUUP) # Current implementation: diff --git a/openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_rc.c b/openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_rc.c index 908107c891..4dfddf6253 100644 --- a/openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_rc.c +++ b/openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_rc.c @@ -26,6 +26,7 @@ #include "../../flexric/src/sm/rc_sm/ie/ir/lst_ran_param.h" #include "../../flexric/src/sm/rc_sm/ie/ir/ran_param_list.h" #include "../../flexric/src/agent/e2_agent_api.h" +#include "openair2/E2AP/flexric/src/lib/sm/enc/enc_ue_id.h" #include #include @@ -53,37 +54,60 @@ static void init_once_rc(void) init_rc_subs_data(&rc_subs_data); } -static void fill_rc_ev_trig(ran_func_def_ev_trig_t* ev_trig) +static seq_ev_trg_style_t fill_ev_tr_format_4(const char *ev_style_name) { - // Sequence of EVENT TRIGGER styles - // [1 - 63] - ev_trig->sz_seq_ev_trg_style = 1; - ev_trig->seq_ev_trg_style = calloc(ev_trig->sz_seq_ev_trg_style, sizeof(seq_ev_trg_style_t)); - assert(ev_trig->seq_ev_trg_style != NULL && "Memory exhausted"); - - seq_ev_trg_style_t* ev_trig_style = &ev_trig->seq_ev_trg_style[0]; + seq_ev_trg_style_t ev_trig_style = {0}; // RIC Event Trigger Style Type // Mandatory // 9.3.3 - // 6.2.2.2. - // INTEGER - ev_trig_style->style = 4; + ev_trig_style.style = 4; // RIC Event Trigger Style Name // Mandatory // 9.3.4 - // 6.2.2.3 - //PrintableString(SIZE(1..150,...)) - const char ev_style_name[] = "UE Information Change"; - ev_trig_style->name = cp_str_to_ba(ev_style_name); + ev_trig_style.name = cp_str_to_ba(ev_style_name); // RIC Event Trigger Format Type // Mandatory // 9.3.5 - // 6.2.2.4. - // INTEGER - ev_trig_style->format = FORMAT_4_E2SM_RC_EV_TRIGGER_FORMAT; + ev_trig_style.format = FORMAT_4_E2SM_RC_EV_TRIGGER_FORMAT; + + return ev_trig_style; +} + +static seq_ev_trg_style_t fill_ev_tr_format_1(const char *ev_style_name) +{ + seq_ev_trg_style_t ev_trig_style = {0}; + + // RIC Event Trigger Style Type + // Mandatory + // 9.3.3 + ev_trig_style.style = 1; + + // RIC Event Trigger Style Name + // Mandatory + // 9.3.4 + ev_trig_style.name = cp_str_to_ba(ev_style_name); + + // RIC Event Trigger Format Type + // Mandatory + // 9.3.5 + ev_trig_style.format = FORMAT_1_E2SM_RC_EV_TRIGGER_FORMAT; + + return ev_trig_style; +} + +static void fill_rc_ev_trig(ran_func_def_ev_trig_t* ev_trig) +{ + // Sequence of EVENT TRIGGER styles + // [1 - 63] + ev_trig->sz_seq_ev_trg_style = 2; + ev_trig->seq_ev_trg_style = calloc(ev_trig->sz_seq_ev_trg_style, sizeof(seq_ev_trg_style_t)); + assert(ev_trig->seq_ev_trg_style != NULL && "Memory exhausted"); + + ev_trig->seq_ev_trg_style[0] = fill_ev_tr_format_1("Message Event"); + ev_trig->seq_ev_trg_style[1] = fill_ev_tr_format_4("UE Information Change"); // Sequence of RAN Parameters for L2 Variables // [0 - 65535] @@ -106,82 +130,141 @@ static void fill_rc_ev_trig(ran_func_def_ev_trig_t* ev_trig) ev_trig->seq_ran_param_id_cell = NULL; } -static void fill_rc_report(ran_func_def_report_t* report) +static seq_report_sty_t fill_report_style_4(const char *report_name) { - // Sequence of REPORT styles - // [1 - 63] - report->sz_seq_report_sty = 1; - report->seq_report_sty = calloc(report->sz_seq_report_sty, sizeof(seq_report_sty_t)); - assert(report->seq_report_sty != NULL && "Memory exhausted"); + seq_report_sty_t report_style = {0}; - seq_report_sty_t* report_style = &report->seq_report_sty[0]; - - // RIC Report Style Type + // RIC Report Style Type // Mandatory // 9.3.3 - // 6.2.2.2. - // INTEGER - report_style->report_type = 4; + report_style.report_type = 4; // RIC Report Style Name // Mandatory // 9.3.4 - // 6.2.2.3. - // PrintableString(SIZE(1..150,...)) - const char report_name[] = "UE Information"; - report_style->name = cp_str_to_ba(report_name); + report_style.name = cp_str_to_ba(report_name); // Supported RIC Event Trigger Style Type // Mandatory // 9.3.3 - // 6.2.2.2. - // INTEGER - report_style->ev_trig_type = FORMAT_4_E2SM_RC_EV_TRIGGER_FORMAT; + report_style.ev_trig_type = FORMAT_4_E2SM_RC_EV_TRIGGER_FORMAT; // RIC Report Action Format Type // Mandatory // 9.3.5 - // 6.2.2.4. - // INTEGER - report_style->act_frmt_type = FORMAT_1_E2SM_RC_ACT_DEF; + report_style.act_frmt_type = FORMAT_1_E2SM_RC_ACT_DEF; // RIC Indication Header Format Type // Mandatory // 9.3.5 - // 6.2.2.4. - // INTEGER - report_style->ind_hdr_type = FORMAT_1_E2SM_RC_IND_HDR; + report_style.ind_hdr_type = FORMAT_1_E2SM_RC_IND_HDR; // RIC Indication Message Format Type // Mandatory // 9.3.5 - // 6.2.2.4. - // INTEGER - report_style->ind_msg_type = FORMAT_2_E2SM_RC_IND_MSG; + report_style.ind_msg_type = FORMAT_2_E2SM_RC_IND_MSG; // Sequence of RAN Parameters Supported // [0 - 65535] - report_style->sz_seq_ran_param = 1; - report_style->ran_param = calloc(report_style->sz_seq_ran_param, sizeof(seq_ran_param_3_t)); - assert(report_style->ran_param != NULL && "Memory exhausted"); + report_style.sz_seq_ran_param = 1; + report_style.ran_param = calloc(report_style.sz_seq_ran_param, sizeof(seq_ran_param_3_t)); + assert(report_style.ran_param != NULL && "Memory exhausted"); // RAN Parameter ID // Mandatory // 9.3.8 // [1- 4294967295] - report_style->ran_param[0].id = E2SM_RC_RS4_RRC_STATE_CHANGED_TO; + report_style.ran_param[0].id = E2SM_RC_RS4_RRC_STATE_CHANGED_TO; // RAN Parameter Name // Mandatory // 9.3.9 // [1-150] - const char ran_param_name[] = "RRC State"; - report_style->ran_param[0].name = cp_str_to_ba(ran_param_name); + const char ran_param_name[] = "RRC State Changed To"; + report_style.ran_param[0].name = cp_str_to_ba(ran_param_name); // RAN Parameter Definition // Optional // 9.3.51 - report_style->ran_param[0].def = NULL; + report_style.ran_param[0].def = NULL; + + return report_style; +} + +static seq_report_sty_t fill_report_style_1(const char *report_name) +{ + seq_report_sty_t report_style = {0}; + + // RIC Report Style Type + // Mandatory + // 9.3.3 + report_style.report_type = 1; + + // RIC Report Style Name + // Mandatory + // 9.3.4 + report_style.name = cp_str_to_ba(report_name); + + // Supported RIC Event Trigger Style Type + // Mandatory + // 9.3.3 + report_style.ev_trig_type = FORMAT_1_E2SM_RC_EV_TRIGGER_FORMAT; + + // RIC Report Action Format Type + // Mandatory + // 9.3.5 + report_style.act_frmt_type = FORMAT_1_E2SM_RC_ACT_DEF; + + // RIC Indication Header Format Type + // Mandatory + // 9.3.5 + report_style.ind_hdr_type = FORMAT_1_E2SM_RC_IND_HDR; + + // RIC Indication Message Format Type + // Mandatory + // 9.3.5 + report_style.ind_msg_type = FORMAT_1_E2SM_RC_IND_MSG; + + // Sequence of RAN Parameters Supported + // [0 - 65535] + report_style.sz_seq_ran_param = 2; + report_style.ran_param = calloc_or_fail(report_style.sz_seq_ran_param, sizeof(seq_ran_param_3_t)); + + // RAN Parameter ID + // Mandatory + // 9.3.8 + // [1- 4294967295] + report_style.ran_param[0].id = E2SM_RC_RS1_RRC_MESSAGE; + report_style.ran_param[1].id = E2SM_RC_RS1_UE_ID; + + // RAN Parameter Name + // Mandatory + // 9.3.9 + // [1-150] + const char ran_param_name_0[] = "RRC Message"; + report_style.ran_param[0].name = cp_str_to_ba(ran_param_name_0); + const char ran_param_name_1[] = "UE ID"; + report_style.ran_param[1].name = cp_str_to_ba(ran_param_name_1); + + // RAN Parameter Definition + // Optional + // 9.3.51 + report_style.ran_param[0].def = NULL; + report_style.ran_param[1].def = NULL; + + return report_style; +} + +static void fill_rc_report(ran_func_def_report_t* report) +{ + // Sequence of REPORT styles + // [1 - 63] + report->sz_seq_report_sty = 2; + report->seq_report_sty = calloc(report->sz_seq_report_sty, sizeof(seq_report_sty_t)); + assert(report->seq_report_sty != NULL && "Memory exhausted"); + + report->seq_report_sty[0] = fill_report_style_1("Message Copy"); + report->seq_report_sty[1] = fill_report_style_4("UE Information"); } static void fill_rc_control(ran_func_def_ctrl_t* ctrl) @@ -476,7 +559,7 @@ void read_rc_setup_sm(void* data) DevAssert(ret == 0); } -static seq_ran_param_t fill_rrc_state_change_seq_ran(const rc_sm_rrc_state_e rrc_state) +static seq_ran_param_t fill_rrc_state_change_seq_ran(const rrc_state_e2sm_rc_e rrc_state) { seq_ran_param_t seq_ran_param = {0}; @@ -490,14 +573,15 @@ static seq_ran_param_t fill_rrc_state_change_seq_ran(const rc_sm_rrc_state_e rrc return seq_ran_param; } -static rc_ind_data_t* fill_ue_rrc_state_change(const gNB_RRC_UE_t *rrc_ue_context, const rc_sm_rrc_state_e rrc_state) +static rc_ind_data_t* fill_ue_rrc_state_change(const gNB_RRC_UE_t *rrc_ue_context, const rrc_state_e2sm_rc_e rrc_state, const uint16_t cond_id) { rc_ind_data_t* rc_ind = calloc(1, sizeof(rc_ind_data_t)); assert(rc_ind != NULL && "Memory exhausted"); // Generate Indication Header rc_ind->hdr.format = FORMAT_1_E2SM_RC_IND_HDR; - rc_ind->hdr.frmt_1.ev_trigger_id = NULL; + rc_ind->hdr.frmt_1.ev_trigger_id = malloc_or_fail(sizeof(uint32_t)); + *rc_ind->hdr.frmt_1.ev_trigger_id = cond_id; // Generate Indication Message rc_ind->msg.format = FORMAT_2_E2SM_RC_IND_MSG; @@ -531,21 +615,95 @@ static void send_aper_ric_ind(const uint32_t ric_req_id, rc_ind_data_t* rc_ind_d printf("[E2 AGENT] Event for RIC request ID %d generated\n", ric_req_id); } -static void check_rrc_state(const gNB_RRC_UE_t *rrc_ue_context, const rc_sm_rrc_state_e rrc_state, const uint32_t ric_req_id, const e2sm_rc_ev_trg_frmt_4_t *frmt_4) +static rc_ind_data_t* fill_ue_id(const gNB_RRC_UE_t *rrc_ue_context, const uint16_t cond_id) +{ + rc_ind_data_t* rc_ind = malloc_or_fail(sizeof(rc_ind_data_t)); + + // Generate Indication Header + rc_ind->hdr.format = FORMAT_1_E2SM_RC_IND_HDR; + rc_ind->hdr.frmt_1.ev_trigger_id = malloc_or_fail(sizeof(uint32_t)); + *rc_ind->hdr.frmt_1.ev_trigger_id = cond_id; + + // Generate Indication Message + rc_ind->msg.format = FORMAT_1_E2SM_RC_IND_MSG; + + // Initialize RAN Parameter + rc_ind->msg.frmt_1.sz_seq_ran_param = 1; + rc_ind->msg.frmt_1.seq_ran_param = calloc_or_fail(rc_ind->msg.frmt_1.sz_seq_ran_param, sizeof(seq_ran_param_t)); + + // Fill the RAN Parameter details for UE ID + rc_ind->msg.frmt_1.seq_ran_param[0].ran_param_id = E2SM_RC_RS1_UE_ID; + rc_ind->msg.frmt_1.seq_ran_param[0].ran_param_val.type = ELEMENT_KEY_FLAG_FALSE_RAN_PARAMETER_VAL_TYPE; + rc_ind->msg.frmt_1.seq_ran_param[0].ran_param_val.flag_false = malloc_or_fail(sizeof(ran_parameter_value_t)); + rc_ind->msg.frmt_1.seq_ran_param[0].ran_param_val.flag_false->type = OCTET_STRING_RAN_PARAMETER_VALUE; + + const ngran_node_t node_type = get_e2_node_type(); + ue_id_e2sm_t ue_id_data = fill_ue_id_data[node_type](rrc_ue_context, 0, 0); + + UEID_t enc_ue_id_data = enc_ue_id_asn(&ue_id_data); + + const enum asn_transfer_syntax syntax = ATS_ALIGNED_BASIC_PER; + asn_encode_to_new_buffer_result_t res = asn_encode_to_new_buffer(NULL, syntax, &asn_DEF_UEID, &enc_ue_id_data); + assert(res.buffer != NULL && res.result.encoded > 0 && "[E2 agent] Failed to encode UE ID."); + byte_array_t ba = {.buf = res.buffer, .len = res.result.encoded}; + + rc_ind->msg.frmt_1.seq_ran_param[0].ran_param_val.flag_false->octet_str_ran = copy_byte_array(ba); + + // Call Process ID + rc_ind->proc_id = NULL; + + free_ue_id_e2sm(&ue_id_data); + ASN_STRUCT_RESET(asn_DEF_UEID, &enc_ue_id_data); + free(res.buffer); + + return rc_ind; +} + +static void check_ue_id_cond(const gNB_RRC_UE_t *rrc_ue_context, const uint16_t class, const uint32_t msg_id, const uint32_t ric_req_id, const e2sm_rc_ev_trg_frmt_1_t *frmt_1) +{ + for (size_t i = 0; i < frmt_1->sz_msg_ev_trg; i++) { + msg_ev_trg_t *ev_item = &frmt_1->msg_ev_trg[i]; + if ((ev_item->msg_type == RRC_MSG_MSG_TYPE_EV_TRG && ev_item->rrc_msg.type == NR_RRC_MESSAGE_ID && ev_item->rrc_msg.nr == class && ev_item->rrc_msg.rrc_msg_id == msg_id) // rrcSetupComplete + || (ev_item->msg_type == NETWORK_INTERFACE_MSG_TYPE_EV_TRG && ev_item->net.ni_type == class)) { // "F1 UE Context Setup Request", but in the subscription the class (F1) can only be specified which translates to any F1 msg + rc_ind_data_t* rc_ind_data = fill_ue_id(rrc_ue_context, ev_item->ev_trigger_cond_id); + send_aper_ric_ind(ric_req_id, rc_ind_data); + } + } +} + +void signal_ue_id(const gNB_RRC_UE_t *rrc_ue_context, const uint16_t class, const uint32_t msg_id) +{ + pthread_mutex_lock(&rc_mutex); + if (rc_subs_data.rs1_param4.data == NULL) { + pthread_mutex_unlock(&rc_mutex); + return; + } + + const size_t num_subs = seq_arr_size(&rc_subs_data.rs1_param4); + for (size_t sub_idx = 0; sub_idx < num_subs; sub_idx++) { + const ran_param_data_t data = *(const ran_param_data_t *)seq_arr_at(&rc_subs_data.rs1_param4, sub_idx); + check_ue_id_cond(rrc_ue_context, class, msg_id, data.ric_req_id, &data.ev_tr.frmt_1); + } + + pthread_mutex_unlock(&rc_mutex); +} + +static void check_rrc_state(const gNB_RRC_UE_t *rrc_ue_context, const rrc_state_e2sm_rc_e rrc_state, const uint32_t ric_req_id, const e2sm_rc_ev_trg_frmt_4_t *frmt_4) { for (size_t i = 0; i < frmt_4->sz_ue_info_chng; i++) { + const uint16_t cond_id = frmt_4->ue_info_chng[i].ev_trig_cond_id; const rrc_state_lst_t *rrc_elem = &frmt_4->ue_info_chng[i].rrc_state; for (size_t j = 0; j < rrc_elem->sz_rrc_state; j++) { const rrc_state_e2sm_rc_e ev_tr_rrc_state = rrc_elem->state_chng_to[j].state_chngd_to; - if (ev_tr_rrc_state == (rrc_state_e2sm_rc_e)rrc_state || ev_tr_rrc_state == ANY_RRC_STATE_E2SM_RC) { - rc_ind_data_t* rc_ind_data = fill_ue_rrc_state_change(rrc_ue_context, rrc_state); + if (ev_tr_rrc_state == rrc_state || ev_tr_rrc_state == ANY_RRC_STATE_E2SM_RC) { + rc_ind_data_t* rc_ind_data = fill_ue_rrc_state_change(rrc_ue_context, rrc_state, cond_id); send_aper_ric_ind(ric_req_id, rc_ind_data); } } } } -void signal_rrc_state_changed_to(const gNB_RRC_UE_t *rrc_ue_context, const rc_sm_rrc_state_e rrc_state) +void signal_rrc_state_changed_to(const gNB_RRC_UE_t *rrc_ue_context, const rrc_state_e2sm_rc_e rrc_state) { pthread_mutex_lock(&rc_mutex); if (rc_subs_data.rs4_param202.data == NULL) { @@ -562,6 +720,67 @@ void signal_rrc_state_changed_to(const gNB_RRC_UE_t *rrc_ue_context, const rc_sm pthread_mutex_unlock(&rc_mutex); } +static rc_ind_data_t* fill_rrc_msg_copy(const byte_array_t rrc_ba, const uint16_t cond_id) +{ + rc_ind_data_t* rc_ind = malloc_or_fail(sizeof(rc_ind_data_t)); + + // Generate Indication Header + rc_ind->hdr.format = FORMAT_1_E2SM_RC_IND_HDR; + rc_ind->hdr.frmt_1.ev_trigger_id = malloc_or_fail(sizeof(uint32_t)); + *rc_ind->hdr.frmt_1.ev_trigger_id = cond_id; + + // Generate Indication Message + rc_ind->msg.format = FORMAT_1_E2SM_RC_IND_MSG; + + // Sequence of + // RAN Parameter + rc_ind->msg.frmt_1.sz_seq_ran_param = 1; + rc_ind->msg.frmt_1.seq_ran_param = calloc_or_fail(rc_ind->msg.frmt_1.sz_seq_ran_param, sizeof(seq_ran_param_t)); + + rc_ind->msg.frmt_1.seq_ran_param[0].ran_param_id = E2SM_RC_RS1_RRC_MESSAGE; + rc_ind->msg.frmt_1.seq_ran_param[0].ran_param_val.type = ELEMENT_KEY_FLAG_FALSE_RAN_PARAMETER_VAL_TYPE; + rc_ind->msg.frmt_1.seq_ran_param[0].ran_param_val.flag_false = malloc_or_fail(sizeof(ran_parameter_value_t)); + rc_ind->msg.frmt_1.seq_ran_param[0].ran_param_val.flag_false->type = OCTET_STRING_RAN_PARAMETER_VALUE; + + rc_ind->msg.frmt_1.seq_ran_param[0].ran_param_val.flag_false->octet_str_ran = copy_byte_array(rrc_ba); + + // Call Process ID + rc_ind->proc_id = NULL; + + return rc_ind; +} + +static void check_rrc_msg_copy(const nr_rrc_class_e nr_channel, const uint32_t rrc_msg_id, const byte_array_t rrc_ba, const uint32_t ric_req_id, const e2sm_rc_ev_trg_frmt_1_t *frmt_1) +{ + for (size_t i = 0; i < frmt_1->sz_msg_ev_trg; i++) { + if (frmt_1->msg_ev_trg[i].msg_type != RRC_MSG_MSG_TYPE_EV_TRG) + continue; + if (frmt_1->msg_ev_trg[i].rrc_msg.type != NR_RRC_MESSAGE_ID) + continue; + if (frmt_1->msg_ev_trg[i].rrc_msg.nr == nr_channel && frmt_1->msg_ev_trg[i].rrc_msg.rrc_msg_id == rrc_msg_id) { + rc_ind_data_t* rc_ind_data = fill_rrc_msg_copy(rrc_ba, frmt_1->msg_ev_trg[i].ev_trigger_cond_id); + send_aper_ric_ind(ric_req_id, rc_ind_data); + } + } +} + +void signal_rrc_msg(const nr_rrc_class_e nr_channel, const uint32_t rrc_msg_id, const byte_array_t rrc_ba) +{ + pthread_mutex_lock(&rc_mutex); + if (rc_subs_data.rs1_param3.data == NULL) { + pthread_mutex_unlock(&rc_mutex); + return; + } + + const size_t num_subs = seq_arr_size(&rc_subs_data.rs1_param3); + for (size_t sub_idx = 0; sub_idx < num_subs; sub_idx++) { + const ran_param_data_t data = *(const ran_param_data_t *)seq_arr_at(&rc_subs_data.rs1_param3, sub_idx); + check_rrc_msg_copy(nr_channel, rrc_msg_id, rrc_ba, data.ric_req_id, &data.ev_tr.frmt_1); + } + + pthread_mutex_unlock(&rc_mutex); +} + static void free_aperiodic_subscription(uint32_t ric_req_id) { remove_rc_subs_data(&rc_subs_data, ric_req_id); @@ -572,6 +791,14 @@ static seq_arr_t *get_sa(const e2sm_rc_event_trigger_t *ev_tr, const uint32_t ra seq_arr_t *sa = NULL; switch (ev_tr->format) { + case FORMAT_1_E2SM_RC_EV_TRIGGER_FORMAT: + if (ran_param_id == E2SM_RC_RS1_RRC_MESSAGE) { + sa = &rc_subs_data.rs1_param3; + } else if (ran_param_id == E2SM_RC_RS1_UE_ID) { + sa = &rc_subs_data.rs1_param4; + } + break; + case FORMAT_4_E2SM_RC_EV_TRIGGER_FORMAT: if (ran_param_id == E2SM_RC_RS4_RRC_STATE_CHANGED_TO) { sa = &rc_subs_data.rs4_param202; diff --git a/openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_rc_extern.h b/openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_rc_extern.h index bd7f6e8bda..a56d82f7d2 100644 --- a/openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_rc_extern.h +++ b/openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_rc_extern.h @@ -23,8 +23,14 @@ #define RAN_FUNC_SM_RAN_CTRL_EXTERN_AGENT_H #include "openair2/RRC/NR/nr_rrc_defs.h" +#include "openair2/E2AP/flexric/src/lib/3gpp/ie/rrc_msg_id.h" +#include "openair2/E2AP/flexric/src/lib/3gpp/ie/network_interface_type.h" +#include "openair2/E2AP/flexric/src/sm/rc_sm/ie/ir/rrc_state.h" -typedef enum { RC_SM_RRC_CONNECTED, RC_SM_RRC_INACTIVE, RC_SM_RRC_IDLE, RC_SM_RRC_ANY } rc_sm_rrc_state_e; -void signal_rrc_state_changed_to(const gNB_RRC_UE_t *rrc_ue_context, const rc_sm_rrc_state_e rrc_state); +void signal_rrc_msg(const nr_rrc_class_e nr_channel, const uint32_t rrc_msg_id, const byte_array_t rrc_ba); + +void signal_ue_id(const gNB_RRC_UE_t *rrc_ue_context, const uint16_t class, const uint32_t msg_id); + +void signal_rrc_state_changed_to(const gNB_RRC_UE_t *rrc_ue_context, const rrc_state_e2sm_rc_e rrc_state); #endif diff --git a/openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_rc_subs.c b/openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_rc_subs.c index 9d37a89fd8..1a134d24da 100644 --- a/openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_rc_subs.c +++ b/openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_rc_subs.c @@ -41,6 +41,8 @@ void init_rc_subs_data(rc_subs_data_t *rc_subs_data) { pthread_mutex_lock(&rc_mutex); // Initialize sequence array + seq_arr_init(&rc_subs_data->rs1_param3, sizeof(ran_param_data_t)); + seq_arr_init(&rc_subs_data->rs1_param4, sizeof(ran_param_data_t)); seq_arr_init(&rc_subs_data->rs4_param202, sizeof(ran_param_data_t)); pthread_mutex_unlock(&rc_mutex); } @@ -57,9 +59,27 @@ void remove_rc_subs_data(rc_subs_data_t *rc_subs_data, uint32_t ric_req_id) { pthread_mutex_lock(&rc_mutex); /* find the sequence element that matches RIC request ID */ - elm_arr_t elm = find_if(&rc_subs_data->rs4_param202, (void *)&ric_req_id, eq_int); - ran_param_data_t *data = elm.it; - free_e2sm_rc_event_trigger(&data->ev_tr); - seq_arr_erase(&rc_subs_data->rs4_param202, elm.it); + elm_arr_t elm_rs1_param3 = find_if(&rc_subs_data->rs1_param3, (void *)&ric_req_id, eq_int); + ran_param_data_t *data_rs1_param3 = elm_rs1_param3.it; + if (data_rs1_param3 != NULL) { + free_e2sm_rc_event_trigger(&data_rs1_param3->ev_tr); + seq_arr_erase(&rc_subs_data->rs1_param3, elm_rs1_param3.it); + } + + /* find the sequence element that matches RIC request ID */ + elm_arr_t elm_rs1_param4 = find_if(&rc_subs_data->rs1_param4, (void *)&ric_req_id, eq_int); + ran_param_data_t *data_rs1_param4 = elm_rs1_param4.it; + if (data_rs1_param4 != NULL) { + free_e2sm_rc_event_trigger(&data_rs1_param4->ev_tr); + seq_arr_erase(&rc_subs_data->rs1_param4, elm_rs1_param4.it); + } + + /* find the sequence element that matches RIC request ID */ + elm_arr_t elm_rs4_param202 = find_if(&rc_subs_data->rs4_param202, (void *)&ric_req_id, eq_int); + ran_param_data_t *data_rs4_param202 = elm_rs4_param202.it; + if (data_rs4_param202 != NULL) { + free_e2sm_rc_event_trigger(&data_rs4_param202->ev_tr); + seq_arr_erase(&rc_subs_data->rs4_param202, elm_rs4_param202.it); + } pthread_mutex_unlock(&rc_mutex); } diff --git a/openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_rc_subs.h b/openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_rc_subs.h index 80fc7e5706..6caad6c3f3 100644 --- a/openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_rc_subs.h +++ b/openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_rc_subs.h @@ -25,66 +25,14 @@ #include "openair2/E2AP/flexric/src/sm/rc_sm/ie/rc_data_ie.h" #include "common/utils/ds/seq_arr.h" -typedef enum { // 8.2.1 RAN Parameters for Report Service Style 1 - E2SM_RC_RS1_UE_EVENT_ID = 1, - E2SM_RC_RS1_NI_MESSAGE = 2, - E2SM_RC_RS1_RRC_MESSAGE = 3, - E2SM_RC_RS1_UE_ID = 4, - E2SM_RC_RS1_OLD_AMF_UE_NGAP_ID = 5, - E2SM_RC_RS1_CELL_GLOBAL_ID = 6, - - END_E2SM_RC_RS1_RAN_PARAM_ID -} report_style_1_ran_param_id_e; - -typedef enum { // 8.2.2 RAN Parameters for Report Service Style 2 - E2SM_RC_RS2_CURRENT_UE_ID = 1, - E2SM_RC_RS2_OLD_UE_ID = 2, - E2SM_RC_RS2_CURRENT_RRC_STATE = 3, - E2SM_RC_RS2_OLD_RRC_STATE = 4, - E2SM_RC_RS2_UE_CONTEXT_INFORMATION_CONTAINER = 5, - E2SM_RC_RS2_CELL_GLOBAL_ID = 6, - E2SM_RC_RS2_UE_INFORMATION = 7, - - END_E2SM_RC_RS2_RAN_PARAM_ID -} report_style_2_ran_param_id_e; - -typedef enum { // 8.2.3 RAN Parameters for Report Service Style 3 - E2SM_RC_RS3_CELL_CONTEXT_INFORMATION = 1, - E2SM_RC_RS3_CELL_DELETED = 2, - E2SM_RC_RS3_NEIGHBOUR_RELATION_TABLE = 3, - - END_E2SM_RC_RS3_RAN_PARAM_ID -} report_style_3_ran_param_id_e; - -typedef enum { // 8.2.4 RAN Parameters for Report Service Style 4 - E2SM_RC_RS4_UL_MAC_CE = 100, - E2SM_RC_RS4_DL_MAC_CE = 101, - E2SM_RC_RS4_DL_BUFFER_OCCUPANCY = 102, - E2SM_RC_RS4_CURRENT_RRC_STATE = 201, - E2SM_RC_RS4_RRC_STATE_CHANGED_TO = 202, - E2SM_RC_RS4_RRC_MESSAGE = 203, - E2SM_RC_RS4_OLD_UE_ID = 300, - E2SM_RC_RS4_CURRENT_UE_ID = 301, - E2SM_RC_RS4_NI_MESSAGE = 302, - E2SM_RC_RS4_CELL_GLOBAL_ID = 400, - - END_E2SM_RC_RS4_RAN_PARAM_ID -} report_style_4_ran_param_id_e; - -typedef enum { // 8.2.5 RAN Parameters for Report Service Style 5 - E2SM_RC_RS5_UE_CONTEXT_INFORMATION = 1, - E2SM_RC_RS5_CELL_CONTEXT_INFORMATION = 2, - E2SM_RC_RS5_NEIGHBOUR_RELATION_TABLE = 3, - - END_E2SM_RC_RS5_RAN_PARAM_ID -} report_style_5_ran_param_id_e; - typedef struct ran_param_data { uint32_t ric_req_id; e2sm_rc_event_trigger_t ev_tr; } ran_param_data_t; typedef struct { + seq_arr_t rs1_param3; // E2SM_RC_RS1_RRC_MESSAGE + seq_arr_t rs1_param4; // E2SM_RC_RS1_UE_ID seq_arr_t rs4_param202; // E2SM_RC_RS4_RRC_STATE_CHANGED_TO } rc_subs_data_t; diff --git a/openair2/E2AP/README.md b/openair2/E2AP/README.md index abcfaa1ac0..9b2b2716fb 100644 --- a/openair2/E2AP/README.md +++ b/openair2/E2AP/README.md @@ -144,6 +144,7 @@ From O-RAN.WG3.E2SM-KPM-version specification, we implemented: We support RC v1.03. Uses ASN.1 encoding. From ORAN.WG3.E2SM-RC-v01.03 specification, we implemented: + * REPORT Service Style 1 ("Message copy" - section 7.4.2) - aperiodic subscription for "RRC Message" and "UE ID" * REPORT Service Style 4 ("UE Information" - section 7.4.5) - aperiodic subscription for "UE RRC State Change" * CONTROL Service Style 1 ("Radio Bearer Control" - section 7.6.2) - "QoS flow mapping configuration" (e.g creating a new DRB) @@ -216,7 +217,7 @@ e2_agent = { ``` Note: we assume that each UE has only 1 DRB; CU-UP does not store the slices, therefore "coarse filtering" is used - * start the RC monitor xApp - aperiodic subscription for "UE RRC State Change" + * start the RC monitor xApp - aperiodic subscriptions for "UE RRC State Change", "RRC Message" copy (`RRC Reconfiguration`, `Measurement Report`, `Security Mode Complete`, `RRC Setup Complete`), and "UE ID" when `RRC Setup Complete` and/or `F1 UE Context Setup Request` detected ```bash cd flexric ./build/examples/xApp/c/monitor/xapp_rc_moni diff --git a/openair2/E2AP/flexric b/openair2/E2AP/flexric index beabdd072c..2638b58e20 160000 --- a/openair2/E2AP/flexric +++ b/openair2/E2AP/flexric @@ -1 +1 @@ -Subproject commit beabdd072ca9e381d4d27c9fbc6bb19382817489 +Subproject commit 2638b58e201ab15200d0e02c6225e9aac35ab51b diff --git a/openair2/F1AP/f1ap_cu_ue_context_management.c b/openair2/F1AP/f1ap_cu_ue_context_management.c index f72ac3c588..d171afaacb 100644 --- a/openair2/F1AP/f1ap_cu_ue_context_management.c +++ b/openair2/F1AP/f1ap_cu_ue_context_management.c @@ -39,6 +39,11 @@ #include "rrc_extern.h" #include "openair2/RRC/NR/rrc_gNB_NGAP.h" +#ifdef E2_AGENT +#include "openair2/RRC/NR/rrc_gNB_UE_context.h" +#include "openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_rc_extern.h" +#endif + static void f1ap_write_drb_qos_param(const f1ap_qos_flow_level_qos_parameters_t *drb_qos_in, F1AP_QoSFlowLevelQoSParameters_t *asn1_qosparam) { int type = drb_qos_in->qos_characteristics.qos_type; @@ -587,6 +592,11 @@ int CU_send_UE_CONTEXT_SETUP_REQUEST(sctp_assoc_t assoc_id, f1ap_ue_context_setu return -1; } +#ifdef E2_AGENT + rrc_gNB_ue_context_t *ue_context_p = rrc_gNB_get_ue_context(RC.nrrrc[0], f1ap_ue_context_setup_req->gNB_CU_ue_id); + signal_ue_id(&ue_context_p->ue_context, F1_NETWORK_INTERFACE_TYPE, 0); +#endif + // xer_fprint(stdout, &asn_DEF_F1AP_F1AP_PDU, (void *)pdu); // asn_encode_to_new_buffer_result_t res = { NULL, {0, NULL, NULL} }; // res = asn_encode_to_new_buffer(NULL, ATS_CANONICAL_XER, &asn_DEF_F1AP_F1AP_PDU, pdu); diff --git a/openair2/RRC/NR/nr_rrc_proto.h b/openair2/RRC/NR/nr_rrc_proto.h index 7dd2fff8a3..f20a5e12a2 100644 --- a/openair2/RRC/NR/nr_rrc_proto.h +++ b/openair2/RRC/NR/nr_rrc_proto.h @@ -110,7 +110,6 @@ bool trigger_bearer_setup(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, int n, pdusession int rrc_gNB_generate_pcch_msg(sctp_assoc_t assoc_id, const NR_SIB1_t *sib, uint32_t tmsi, uint8_t paging_drx); -void nr_rrc_transfer_protected_rrc_message(const gNB_RRC_INST *rrc, const gNB_RRC_UE_t *ue_p, uint8_t srb_id, const uint8_t* buffer, int size); /** @}*/ /* UE Management Procedures */ diff --git a/openair2/RRC/NR/rrc_gNB.c b/openair2/RRC/NR/rrc_gNB.c index b5d682fb44..7eef21c810 100644 --- a/openair2/RRC/NR/rrc_gNB.c +++ b/openair2/RRC/NR/rrc_gNB.c @@ -97,6 +97,12 @@ #ifdef E2_AGENT #include "openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_rc_extern.h" +#define E2_AGENT_SIGNAL_DL_DCCH_RRC_MSG(BUF, LEN, ID) \ + do { \ + byte_array_t buffer_ba = {.len = LEN}; \ + buffer_ba.buf = (uint8_t *)BUF; \ + signal_rrc_msg(DL_DCCH_NR_RRC_CLASS, ID, buffer_ba); \ + } while (0) #endif mui_t rrc_gNB_mui = 0; @@ -184,11 +190,12 @@ static void rrc_deliver_dl_rrc_message(void *deliver_pdu_data, ue_id_t ue_id, in data->rrc->mac_rrc.dl_rrc_message_transfer(data->assoc_id, data->dl_rrc); } -void nr_rrc_transfer_protected_rrc_message(const gNB_RRC_INST *rrc, - const gNB_RRC_UE_t *ue_p, - uint8_t srb_id, - const uint8_t *buffer, - int size) +static void nr_rrc_transfer_protected_rrc_message(const gNB_RRC_INST *rrc, + const gNB_RRC_UE_t *ue_p, + uint8_t srb_id, + const uint32_t message_id, + const uint8_t *buffer, + int size) { DevAssert(size > 0); f1_ue_data_t ue_data = cu_get_f1_ue_data(ue_p->rrc_ue_id); @@ -202,6 +209,10 @@ void nr_rrc_transfer_protected_rrc_message(const gNB_RRC_INST *rrc, (unsigned char *const)buffer, rrc_deliver_dl_rrc_message, &data); + +#ifdef E2_AGENT + E2_AGENT_SIGNAL_DL_DCCH_RRC_MSG(buffer, size, message_id); +#endif } ///---------------------------------------------------------------------------------------------------------------/// @@ -571,7 +582,8 @@ static void rrc_gNB_generate_dedicatedRRCReconfiguration(gNB_RRC_INST *rrc, gNB_ DevAssert(size > 0 && size <= sizeof(buffer)); LOG_UE_DL_EVENT(ue_p, "Generate RRCReconfiguration (bytes %d, xid %d)\n", size, xid); - nr_rrc_transfer_protected_rrc_message(rrc, ue_p, DL_SCH_LCID_DCCH, buffer, size); + const uint32_t msg_id = NR_DL_DCCH_MessageType__c1_PR_rrcReconfiguration; + nr_rrc_transfer_protected_rrc_message(rrc, ue_p, DL_SCH_LCID_DCCH, msg_id, buffer, size); } void rrc_gNB_modify_dedicatedRRCReconfiguration(gNB_RRC_INST *rrc, gNB_RRC_UE_t *ue_p) @@ -680,7 +692,8 @@ void rrc_gNB_modify_dedicatedRRCReconfiguration(gNB_RRC_INST *rrc, gNB_RRC_UE_t clear_nas_pdu(&ue_p->pduSession[i].param.nas_pdu); LOG_I(NR_RRC, "UE %d: Generate RRCReconfiguration (bytes %d)\n", ue_p->rrc_ue_id, size); - nr_rrc_transfer_protected_rrc_message(rrc, ue_p, DL_SCH_LCID_DCCH, buffer, size); + const uint32_t msg_id = NR_DL_DCCH_MessageType__c1_PR_rrcReconfiguration; + nr_rrc_transfer_protected_rrc_message(rrc, ue_p, DL_SCH_LCID_DCCH, msg_id, buffer, size); } //----------------------------------------------------------------------------- @@ -732,7 +745,8 @@ void rrc_gNB_generate_dedicatedRRCReconfiguration_release(gNB_RRC_INST *rrc, } LOG_I(NR_RRC, "UE %d: Generate NR_RRCReconfiguration (bytes %d)\n", ue_p->rrc_ue_id, size); - nr_rrc_transfer_protected_rrc_message(rrc, ue_p, DL_SCH_LCID_DCCH, buffer, size); + const uint32_t msg_id = NR_DL_DCCH_MessageType__c1_PR_rrcReconfiguration; + nr_rrc_transfer_protected_rrc_message(rrc, ue_p, DL_SCH_LCID_DCCH, msg_id, buffer, size); } static void fill_security_info(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, security_information_t *secInfo) @@ -887,6 +901,10 @@ static void rrc_gNB_generate_RRCReestablishment(rrc_gNB_ue_context_t *ue_context deliver_dl_rrc_message_data_t data = {.rrc = rrc, .dl_rrc = &dl_rrc, .assoc_id = ue_data.du_assoc_id}; nr_pdcp_data_req_srb(ue_p->rrc_ue_id, DL_SCH_LCID_DCCH, rrc_gNB_mui++, size, (unsigned char *const)buffer, rrc_deliver_dl_rrc_message, &data); +#ifdef E2_AGENT + E2_AGENT_SIGNAL_DL_DCCH_RRC_MSG(buffer, size, NR_DL_DCCH_MessageType__c1_PR_rrcReestablishment); +#endif + /* RRCReestablishment has been generated, let's enable ciphering now. */ security_parameters.ciphering_algorithm = ue_p->ciphering_algorithm; /* SRBs */ @@ -987,7 +1005,8 @@ static void rrc_gNB_process_RRCReestablishmentComplete(gNB_RRC_INST *rrc, gNB_RR ue_p->rrc_ue_id, ue_p->rnti, size); - nr_rrc_transfer_protected_rrc_message(rrc, ue_p, DL_SCH_LCID_DCCH, buffer, size); + const uint32_t msg_id = NR_DL_DCCH_MessageType__c1_PR_rrcReconfiguration; + nr_rrc_transfer_protected_rrc_message(rrc, ue_p, DL_SCH_LCID_DCCH, msg_id, buffer, size); } //----------------------------------------------------------------------------- @@ -1008,7 +1027,8 @@ int nr_rrc_reconfiguration_req(gNB_RRC_INST *rrc, gNB_RRC_UE_t *ue_p, const int uint8_t buffer[NR_RRC_BUF_SIZE]; int size = do_RRCReconfiguration(ue_p, buffer, NR_RRC_BUF_SIZE, xid, NULL, NULL, NULL, NULL, NULL, NULL, masterCellGroup); - nr_rrc_transfer_protected_rrc_message(rrc, ue_p, DL_SCH_LCID_DCCH, buffer, size); + const uint32_t msg_id = NR_DL_DCCH_MessageType__c1_PR_rrcReconfiguration; + nr_rrc_transfer_protected_rrc_message(rrc, ue_p, DL_SCH_LCID_DCCH, msg_id, buffer, size); return 0; } @@ -1442,7 +1462,8 @@ void rrc_forward_ue_nas_message(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE) uint32_t length = do_NR_DLInformationTransfer(buffer, sizeof(buffer), xid, UE->nas_pdu.length, UE->nas_pdu.buffer); LOG_DUMPMSG(NR_RRC, DEBUG_RRC, buffer, length, "[MSG] RRC DL Information Transfer\n"); rb_id_t srb_id = UE->Srb[2].Active ? DL_SCH_LCID_DCCH1 : DL_SCH_LCID_DCCH; - nr_rrc_transfer_protected_rrc_message(rrc, UE, srb_id, buffer, length); + const uint32_t msg_id = NR_DL_DCCH_MessageType__c1_PR_dlInformationTransfer; + nr_rrc_transfer_protected_rrc_message(rrc, UE, srb_id, msg_id, buffer, length); // no need to free UE->nas_pdu.buffer, do_NR_DLInformationTransfer() did that UE->nas_pdu.buffer = NULL; UE->nas_pdu.length = 0; @@ -1626,6 +1647,11 @@ static void handle_rrcSetupComplete(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, const N } } +#ifdef E2_AGENT + const uint32_t msg_id = NR_UL_DCCH_MessageType__c1_PR_rrcSetupComplete; + signal_ue_id(UE, UL_DCCH_NR_RRC_CLASS, msg_id); +#endif + rrc_gNB_process_RRCSetupComplete(rrc, UE, setup_complete->criticalExtensions.choice.rrcSetupComplete); return; } @@ -1698,7 +1724,8 @@ static void rrc_gNB_generate_UECapabilityEnquiry(gNB_RRC_INST *rrc, gNB_RRC_UE_t AssertFatal(!NODE_IS_DU(rrc->node_type), "illegal node type DU!\n"); - nr_rrc_transfer_protected_rrc_message(rrc, ue, DL_SCH_LCID_DCCH, buffer, size); + const uint32_t msg_id = NR_DL_DCCH_MessageType__c1_PR_ueCapabilityEnquiry; + nr_rrc_transfer_protected_rrc_message(rrc, ue, DL_SCH_LCID_DCCH, msg_id, buffer, size); } static int rrc_gNB_decode_dcch(gNB_RRC_INST *rrc, const f1ap_ul_rrc_message_t *msg) @@ -1732,6 +1759,13 @@ static int rrc_gNB_decode_dcch(gNB_RRC_INST *rrc, const f1ap_ul_rrc_message_t *m } if (ul_dcch_msg->message.present == NR_UL_DCCH_MessageType_PR_c1) { +#ifdef E2_AGENT + // 38.331 Sec 6.2.1: message index of UL-DCCH-Message + const uint32_t rrc_msg_id = ul_dcch_msg->message.choice.c1->present; + byte_array_t buffer_ba = {.len = msg->rrc_container_length}; + buffer_ba.buf = msg->rrc_container; + signal_rrc_msg(UL_DCCH_NR_RRC_CLASS, rrc_msg_id, buffer_ba); +#endif switch (ul_dcch_msg->message.choice.c1->present) { case NR_UL_DCCH_MessageType__c1_PR_NOTHING: LOG_I(NR_RRC, "Received PR_NOTHING on UL-DCCH-Message\n"); @@ -2726,7 +2760,8 @@ void rrc_gNB_generate_SecurityModeCommand(gNB_RRC_INST *rrc, gNB_RRC_UE_t *ue_p) LOG_DUMPMSG(NR_RRC, DEBUG_RRC, (char *)buffer, size, "[MSG] RRC Security Mode Command\n"); LOG_I(NR_RRC, "UE %u Logical Channel DL-DCCH, Generate SecurityModeCommand (bytes %d)\n", ue_p->rrc_ue_id, size); - nr_rrc_transfer_protected_rrc_message(rrc, ue_p, DL_SCH_LCID_DCCH, buffer, size); + const uint32_t msg_id = NR_DL_DCCH_MessageType__c1_PR_securityModeCommand; + nr_rrc_transfer_protected_rrc_message(rrc, ue_p, DL_SCH_LCID_DCCH, msg_id, buffer, size); } //----------------------------------------------------------------------------- @@ -2751,6 +2786,10 @@ void rrc_gNB_generate_RRCRelease(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE) }; 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); + +#ifdef E2_AGENT + E2_AGENT_SIGNAL_DL_DCCH_RRC_MSG(buffer, size, NR_DL_DCCH_MessageType__c1_PR_rrcRelease); +#endif } int rrc_gNB_generate_pcch_msg(sctp_assoc_t assoc_id, const NR_SIB1_t *sib1, uint32_t tmsi, uint8_t paging_drx) diff --git a/openair2/RRC/NR/rrc_gNB_NGAP.c b/openair2/RRC/NR/rrc_gNB_NGAP.c index e7ceb9beba..846889f841 100644 --- a/openair2/RRC/NR/rrc_gNB_NGAP.c +++ b/openair2/RRC/NR/rrc_gNB_NGAP.c @@ -550,7 +550,7 @@ int rrc_gNB_process_NGAP_INITIAL_CONTEXT_SETUP_REQ(MessageDef *msg_p, instance_t } #ifdef E2_AGENT - signal_rrc_state_changed_to(UE, RC_SM_RRC_CONNECTED); + signal_rrc_state_changed_to(UE, RRC_CONNECTED_RRC_STATE_E2SM_RC); #endif return 0; @@ -1267,7 +1267,7 @@ int rrc_gNB_process_NGAP_UE_CONTEXT_RELEASE_COMMAND(MessageDef *msg_p, instance_ gNB_RRC_UE_t *UE = &ue_context_p->ue_context; UE->an_release = true; #ifdef E2_AGENT - signal_rrc_state_changed_to(UE, RC_SM_RRC_IDLE); + signal_rrc_state_changed_to(UE, RRC_IDLE_RRC_STATE_E2SM_RC); #endif /* a UE might not be associated to a CU-UP if it never requested a PDU diff --git a/openair2/RRC/NR/rrc_gNB_mobility.c b/openair2/RRC/NR/rrc_gNB_mobility.c index a6f4acb953..db1c4bb904 100644 --- a/openair2/RRC/NR/rrc_gNB_mobility.c +++ b/openair2/RRC/NR/rrc_gNB_mobility.c @@ -36,6 +36,10 @@ #include "openair3/SECU/key_nas_deriver.h" #include "openair2/RRC/NR/rrc_gNB_NGAP.h" +#ifdef E2_AGENT +#include "openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_rc_extern.h" +#endif + typedef enum { HO_CTX_BOTH, HO_CTX_SOURCE, HO_CTX_TARGET } ho_ctx_type_t; static nr_handover_context_t *alloc_ho_ctx(ho_ctx_type_t type) { @@ -242,6 +246,12 @@ static void rrc_gNB_trigger_reconfiguration_for_handover(gNB_RRC_INST *rrc, gNB_ (unsigned char *const)rrc_reconf, rrc_deliver_ue_ctxt_modif_req, &data); +#ifdef E2_AGENT + uint32_t message_id = NR_DL_DCCH_MessageType__c1_PR_rrcReconfiguration; + byte_array_t buffer_ba = {.len = rrc_reconf_len}; + buffer_ba.buf = rrc_reconf; + signal_rrc_msg(DL_DCCH_NR_RRC_CLASS, message_id, buffer_ba); +#endif } static void nr_rrc_f1_ho_acknowledge(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, uint8_t *rrc_reconf_buf, uint32_t rrc_reconf_len)