From dfaf9dd6301ad70d871d6c68154c94004fa11951 Mon Sep 17 00:00:00 2001 From: Shrinish Donde Date: Fri, 14 Mar 2025 19:27:06 +0100 Subject: [PATCH] RAN Control REPORT Style 1: "RRC Message" support Send the copy of the following RRC messages to a xApp, if subscribed beforehand: - DL-DCCH -> any - UL-DCCH -> any Co-authored-by: Tano Bischoff Co-authored-by: Khanh Toan Pham Co-authored-by: Theodoros Tsourdinis Co-authored-by: Miguel Fuentes Co-authored-by: Teodora Vladic Co-authored-by: Robert Schmidt --- .../E2AP/RAN_FUNCTION/O-RAN/ran_func_rc.c | 159 +++++++++++++++++- .../RAN_FUNCTION/O-RAN/ran_func_rc_extern.h | 3 + .../RAN_FUNCTION/O-RAN/ran_func_rc_subs.c | 19 ++- .../RAN_FUNCTION/O-RAN/ran_func_rc_subs.h | 1 + openair2/RRC/NR/rrc_gNB.c | 50 +++++- openair2/RRC/NR/rrc_gNB_mobility.c | 10 ++ 6 files changed, 226 insertions(+), 16 deletions(-) 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 99b03f2583..903a3c56b3 100644 --- a/openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_rc.c +++ b/openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_rc.c @@ -75,15 +75,38 @@ static seq_ev_trg_style_t fill_ev_tr_format_4(const char *ev_style_name) 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 = 1; + 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_4("UE Information Change"); + 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] @@ -167,15 +190,76 @@ static seq_report_sty_t fill_report_style_4(const char *report_name) 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 = 1; + 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; + + // 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); + + // RAN Parameter Definition + // Optional + // 9.3.51 + report_style.ran_param[0].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 = 1; + 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_4("UE Information"); + 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) @@ -558,6 +642,67 @@ void signal_rrc_state_changed_to(const gNB_RRC_UE_t *rrc_ue_context, const rrc_s 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); @@ -568,6 +713,12 @@ 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; + } + 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 5f9633453b..83b933639e 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,11 @@ #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/sm/rc_sm/ie/ir/rrc_state.h" +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_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..9e993a8c2e 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,7 @@ 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->rs4_param202, sizeof(ran_param_data_t)); pthread_mutex_unlock(&rc_mutex); } @@ -57,9 +58,19 @@ 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_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 702e08511e..dff9224db2 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 @@ -31,6 +31,7 @@ typedef struct ran_param_data { } ran_param_data_t; typedef struct { + seq_arr_t rs1_param3; // E2SM_RC_RS1_RRC_MESSAGE seq_arr_t rs4_param202; // E2SM_RC_RS4_RRC_STATE_CHANGED_TO } rc_subs_data_t; diff --git a/openair2/RRC/NR/rrc_gNB.c b/openair2/RRC/NR/rrc_gNB.c index 22bf766716..cfb6c499a3 100644 --- a/openair2/RRC/NR/rrc_gNB.c +++ b/openair2/RRC/NR/rrc_gNB.c @@ -98,6 +98,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; @@ -188,6 +194,7 @@ static void rrc_deliver_dl_rrc_message(void *deliver_pdu_data, ue_id_t ue_id, in 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) { @@ -203,6 +210,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 } ///---------------------------------------------------------------------------------------------------------------/// @@ -572,7 +583,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) @@ -681,7 +693,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); } //----------------------------------------------------------------------------- @@ -733,7 +746,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) @@ -888,6 +902,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 */ @@ -988,7 +1006,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); } //----------------------------------------------------------------------------- @@ -1009,7 +1028,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; } @@ -1443,7 +1463,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; @@ -1695,7 +1716,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) @@ -1729,6 +1751,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"); @@ -2722,7 +2751,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); } //----------------------------------------------------------------------------- @@ -2747,6 +2777,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_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)