From 8957cfef78f3bb6b61cbb317b3c5099fd23f3219 Mon Sep 17 00:00:00 2001 From: Konstantinos Alexandris <konstantinos.alexandris@eurecom.fr> Date: Mon, 20 May 2019 17:51:02 +0200 Subject: [PATCH] Add HO trigger function via FlexRAN controller (OAI + FlexRAN handler) --- openair2/ENB_APP/MESSAGES/V2/flexran.proto | 7 ++ openair2/ENB_APP/MESSAGES/V2/header.proto | 1 + openair2/ENB_APP/flexran_agent_common.c | 53 +++++++++++- openair2/ENB_APP/flexran_agent_common.h | 5 +- openair2/ENB_APP/flexran_agent_handler.c | 3 + openair2/ENB_APP/flexran_agent_ran_api.c | 10 +++ openair2/ENB_APP/flexran_agent_ran_api.h | 3 + openair2/RRC/LTE/rrc_eNB.c | 93 ++++++++++++++++++++++ openair2/RRC/LTE/rrc_proto.h | 6 ++ 9 files changed, 179 insertions(+), 2 deletions(-) diff --git a/openair2/ENB_APP/MESSAGES/V2/flexran.proto b/openair2/ENB_APP/MESSAGES/V2/flexran.proto index 840e53f616..86f2e9329f 100644 --- a/openair2/ENB_APP/MESSAGES/V2/flexran.proto +++ b/openair2/ENB_APP/MESSAGES/V2/flexran.proto @@ -32,6 +32,7 @@ message flexran_message { flex_rrc_triggering rrc_triggering = 18; flex_ul_mac_config ul_mac_config_msg = 19; flex_disconnect disconnect_msg = 20; + flex_ho_command ho_command_msg = 21; } } @@ -192,6 +193,12 @@ message flex_rrc_triggering { optional flex_measurement_info meas_info = 3; } +message flex_ho_command { + optional flex_header header = 1; + optional uint32 rnti = 2; + optional uint32 target_phy_cell_id = 3; +} + // // UE state change message // diff --git a/openair2/ENB_APP/MESSAGES/V2/header.proto b/openair2/ENB_APP/MESSAGES/V2/header.proto index c91d2e2c09..41b2b37f7a 100644 --- a/openair2/ENB_APP/MESSAGES/V2/header.proto +++ b/openair2/ENB_APP/MESSAGES/V2/header.proto @@ -34,6 +34,7 @@ enum flex_type { //Controller command messages FLPT_DL_MAC_CONFIG = 13; + FLPT_HO_COMMAND = 21; // UE state change messages FLPT_UE_STATE_CHANGE = 14; diff --git a/openair2/ENB_APP/flexran_agent_common.c b/openair2/ENB_APP/flexran_agent_common.c index 9f932dd3c7..757a796233 100644 --- a/openair2/ENB_APP/flexran_agent_common.c +++ b/openair2/ENB_APP/flexran_agent_common.c @@ -837,8 +837,59 @@ int flexran_agent_rrc_reconfiguration(mid_t mod_id, const void *params, Protocol return 0; } +int flexran_agent_rrc_trigger_handover(mid_t mod_id, const void *params, Protocol__FlexranMessage **msg) { + Protocol__FlexranMessage *input = (Protocol__FlexranMessage *)params; + Protocol__FlexHoCommand *ho_command = input->ho_command_msg; + + int rnti_found = 0; + + // Set the proper values using FlexRAN API (protected with mutex ?) + if (!flexran_agent_get_rrc_xface(mod_id)) { + LOG_E(FLEXRAN_AGENT, "%s(): no RRC present, aborting\n", __func__); + return -1; + } + + int num_ue = flexran_get_rrc_num_ues(mod_id); + if (num_ue == 0) + return 0; + + if (!ho_command->has_rnti) { + LOG_E(FLEXRAN_AGENT, "%s(): no UE rnti is present, aborting\n", __func__); + return -1; + } + + if (!ho_command->has_target_phy_cell_id) { + LOG_E(FLEXRAN_AGENT, "%s(): no target physical cell id is present, aborting\n", __func__); + return -1; + } + + rnti_t rntis[num_ue]; + flexran_get_rrc_rnti_list(mod_id, rntis, num_ue); + for (int i = 0; i < num_ue; i++) { + const rnti_t rnti = rntis[i]; + if (ho_command->rnti == rnti) { + rnti_found = 1; + // Call the proper wrapper in FlexRAN API + if (flexran_call_rrc_trigger_handover(mod_id, ho_command->rnti, ho_command->target_phy_cell_id) < 0) { + LOG_E(FLEXRAN_AGENT, "Error in handovering user %d\n", i); + } + break; + } + } + + if (!rnti_found) + return -1; + + *msg = NULL; + return 0; +} + +int flexran_agent_destroy_rrc_reconfiguration(Protocol__FlexranMessage *msg) { + // TODO + return 0; +} -int flexran_agent_destroy_rrc_measurement(Protocol__FlexranMessage *msg) { +int flexran_agent_destroy_rrc_trigger_handover(Protocol__FlexranMessage *msg) { // TODO return 0; } diff --git a/openair2/ENB_APP/flexran_agent_common.h b/openair2/ENB_APP/flexran_agent_common.h index aad77635f2..f116eb6591 100644 --- a/openair2/ENB_APP/flexran_agent_common.h +++ b/openair2/ENB_APP/flexran_agent_common.h @@ -138,8 +138,11 @@ int flexran_agent_destroy_agent_reconfiguration(Protocol__FlexranMessage *msg); /* rrc triggering measurement message constructor and destructor */ int flexran_agent_rrc_reconfiguration(mid_t mod_id, const void *params, Protocol__FlexranMessage **msg); -int flexran_agent_destroy_rrc_measurement(Protocol__FlexranMessage *msg); +int flexran_agent_destroy_rrc_reconfiguration(Protocol__FlexranMessage *msg); +/* rrc triggering handover command message constructor and destructor */ +int flexran_agent_rrc_trigger_handover(mid_t mod_id, const void *params, Protocol__FlexranMessage **msg); +int flexran_agent_destroy_rrc_trigger_handover(Protocol__FlexranMessage *msg); /* FlexRAN protocol message dispatcher function */ Protocol__FlexranMessage* flexran_agent_handle_message (mid_t mod_id, diff --git a/openair2/ENB_APP/flexran_agent_handler.c b/openair2/ENB_APP/flexran_agent_handler.c index 7112d1fe36..65663e20a8 100644 --- a/openair2/ENB_APP/flexran_agent_handler.c +++ b/openair2/ENB_APP/flexran_agent_handler.c @@ -56,6 +56,9 @@ flexran_agent_message_decoded_callback agent_messages_callback[][3] = { {flexran_agent_control_delegation, 0, 0}, /*PROTOCOL__FLEXRAN_MESSAGE__MSG_CONTROL_DELEGATION_MSG*/ {flexran_agent_reconfiguration, 0, 0}, /*PROTOCOL__FLEXRAN_MESSAGE__MSG_AGENT_RECONFIGURATION_MSG*/ {flexran_agent_rrc_reconfiguration, 0, 0}, /*PROTOCOL__FLEXRAN_MESSAGE__MSG_RRC_TRIGGERING_MSG*/ + {0, 0, 0}, /*PROTOCOL__FLEXRAN_MESSAGE__MSG_UL_MAC_CONFIG_MSG*/ + {0, 0, 0}, /*PROTOCOL__FLEXRAN_MESSAGE__MSG_DISCONNECT_MSG*/ + {flexran_agent_rrc_trigger_handover, 0, 0}, /*PROTOCOL__FLEXRAN_MESSAGE__MSG_HO_COMMAND_MSG*/ }; flexran_agent_message_destruction_callback message_destruction_callback[] = { diff --git a/openair2/ENB_APP/flexran_agent_ran_api.c b/openair2/ENB_APP/flexran_agent_ran_api.c index 5b067cea55..cd91e73a7c 100644 --- a/openair2/ENB_APP/flexran_agent_ran_api.c +++ b/openair2/ENB_APP/flexran_agent_ran_api.c @@ -1446,6 +1446,16 @@ int flexran_call_rrc_reconfiguration (mid_t mod_id, rnti_t rnti) { return 0; } +int flexran_call_rrc_trigger_handover (mid_t mod_id, rnti_t rnti, int target_cell_id) { + if (!rrc_is_present(mod_id)) return -1; + protocol_ctxt_t ctxt; + memset(&ctxt, 0, sizeof(ctxt)); + struct rrc_eNB_ue_context_s* ue_context_p = rrc_eNB_get_ue_context(RC.rrc[mod_id], rnti); + if (!ue_context_p) return -1; + PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, mod_id, ENB_FLAG_YES, ue_context_p->ue_context.rnti, flexran_get_current_frame(mod_id), flexran_get_current_subframe (mod_id), mod_id); + return flexran_rrc_eNB_trigger_handover(mod_id, &ctxt, ue_context_p, target_cell_id); +} + /* RRC Getters */ LTE_MeasId_t flexran_get_rrc_pcell_measid(mid_t mod_id, rnti_t rnti) { diff --git a/openair2/ENB_APP/flexran_agent_ran_api.h b/openair2/ENB_APP/flexran_agent_ran_api.h index aabd327638..d3229bd462 100644 --- a/openair2/ENB_APP/flexran_agent_ran_api.h +++ b/openair2/ENB_APP/flexran_agent_ran_api.h @@ -501,6 +501,9 @@ uint32_t flexran_get_pdcp_rx_oo(mid_t mod_id, uint16_t uid, lcid_t lcid); /* Call RRC Reconfiguration wrapper function */ int flexran_call_rrc_reconfiguration (mid_t mod_id, rnti_t rnti); +/* Call RRC to trigger handover wrapper function */ +int flexran_call_rrc_trigger_handover (mid_t mod_id, rnti_t rnti, int target_cell_id); + /*Get primary cell measuremeant id flexRAN*/ LTE_MeasId_t flexran_get_rrc_pcell_measid(mid_t mod_id, rnti_t rnti); diff --git a/openair2/RRC/LTE/rrc_eNB.c b/openair2/RRC/LTE/rrc_eNB.c index f82f7a42a9..fd308caebe 100644 --- a/openair2/RRC/LTE/rrc_eNB.c +++ b/openair2/RRC/LTE/rrc_eNB.c @@ -4817,6 +4817,99 @@ void rrc_eNB_handover_cancel( S1AP_CAUSE_RADIO_NETWORK, s1_cause); } + +int +flexran_rrc_eNB_trigger_handover (int mod_id, + const protocol_ctxt_t *const ctxt_pP, + rrc_eNB_ue_context_t *ue_context_pP, + int target_cell_id) { + +uint32_t earfcn_dl; +uint8_t KeNB_star[32] = { 0 }; +int cell_found = 0; + + /* Check if eNB id belongs to the supported ones-Extend for multiple carrieres */ + + for (int i=0; i < RC.rrc[mod_id]->num_neigh_cells; i++) { + if (RC.rrc[mod_id]->neigh_cells_id[i][0] == target_cell_id) { + cell_found = 1; + break; + } + } + + /* Check if eNB id was found */ + + if (!cell_found) + return -1; + + /* Handover process is following */ + + /* if X2AP is disabled, do nothing */ + if (!is_x2ap_enabled()) + return -1; + + LOG_D(RRC, "Handover is triggered by FlexRAN controller...\n"); + + /* if the UE is not in handover mode, start handover procedure */ + if (ue_context_pP->ue_context.Status != RRC_HO_EXECUTION) { + MessageDef *msg; + LOG_I(RRC, "Send HO preparation message at frame %d and subframe %d \n", ctxt_pP->frame, ctxt_pP->subframe); + /* Check memory leakage for handover info */ + //if (ue_context_pP->ue_context.handover_info) { + //free(ue_context_pP->ue_context.handover_info); + //} + ue_context_pP->ue_context.handover_info = CALLOC(1, sizeof(*(ue_context_pP->ue_context.handover_info))); + ue_context_pP->ue_context.Status = RRC_HO_EXECUTION; + ue_context_pP->ue_context.handover_info->state = HO_REQUEST; + /* HO Preparation message */ + msg = itti_alloc_new_message(TASK_RRC_ENB, X2AP_HANDOVER_REQ); + rrc_eNB_generate_HandoverPreparationInformation( + ue_context_pP, + X2AP_HANDOVER_REQ(msg).rrc_buffer, + &X2AP_HANDOVER_REQ(msg).rrc_buffer_size); + X2AP_HANDOVER_REQ(msg).rnti = ctxt_pP->rnti; + X2AP_HANDOVER_REQ(msg).target_physCellId = target_cell_id; + X2AP_HANDOVER_REQ(msg).ue_gummei.mcc = ue_context_pP->ue_context.ue_gummei.mcc; + X2AP_HANDOVER_REQ(msg).ue_gummei.mnc = ue_context_pP->ue_context.ue_gummei.mnc; + X2AP_HANDOVER_REQ(msg).ue_gummei.mnc_len = ue_context_pP->ue_context.ue_gummei.mnc_len; + X2AP_HANDOVER_REQ(msg).ue_gummei.mme_code = ue_context_pP->ue_context.ue_gummei.mme_code; + X2AP_HANDOVER_REQ(msg).ue_gummei.mme_group_id = ue_context_pP->ue_context.ue_gummei.mme_group_id; + // Don't know how to get this ID? + X2AP_HANDOVER_REQ(msg).mme_ue_s1ap_id = ue_context_pP->ue_context.mme_ue_s1ap_id; + X2AP_HANDOVER_REQ(msg).security_capabilities = ue_context_pP->ue_context.security_capabilities; + // compute keNB* + earfcn_dl = (uint32_t)to_earfcn_DL(RC.rrc[ctxt_pP->module_id]->carrier[0].eutra_band, RC.rrc[ctxt_pP->module_id]->carrier[0].dl_CarrierFreq, + RC.rrc[ctxt_pP->module_id]->carrier[0].N_RB_DL); + derive_keNB_star(ue_context_pP->ue_context.kenb, X2AP_HANDOVER_REQ(msg).target_physCellId, earfcn_dl, true, KeNB_star); + memcpy(X2AP_HANDOVER_REQ(msg).kenb, KeNB_star, 32); + X2AP_HANDOVER_REQ(msg).kenb_ncc = ue_context_pP->ue_context.kenb_ncc; + //X2AP_HANDOVER_REQ(msg).ue_ambr=ue_context_pP->ue_context.ue_ambr; + X2AP_HANDOVER_REQ(msg).nb_e_rabs_tobesetup = ue_context_pP->ue_context.setup_e_rabs; + + for (int i=0; i<ue_context_pP->ue_context.setup_e_rabs; i++) { + X2AP_HANDOVER_REQ(msg).e_rabs_tobesetup[i].e_rab_id = ue_context_pP->ue_context.e_rab[i].param.e_rab_id; + X2AP_HANDOVER_REQ(msg).e_rabs_tobesetup[i].eNB_addr = ue_context_pP->ue_context.e_rab[i].param.sgw_addr; + X2AP_HANDOVER_REQ(msg).e_rabs_tobesetup[i].gtp_teid = ue_context_pP->ue_context.e_rab[i].param.gtp_teid; + X2AP_HANDOVER_REQ(msg).e_rab_param[i].qos.qci = ue_context_pP->ue_context.e_rab[i].param.qos.qci; + X2AP_HANDOVER_REQ(msg).e_rab_param[i].qos.allocation_retention_priority.priority_level = ue_context_pP->ue_context.e_rab[i].param.qos.allocation_retention_priority.priority_level; + X2AP_HANDOVER_REQ(msg).e_rab_param[i].qos.allocation_retention_priority.pre_emp_capability = ue_context_pP->ue_context.e_rab[i].param.qos.allocation_retention_priority.pre_emp_capability; + X2AP_HANDOVER_REQ(msg).e_rab_param[i].qos.allocation_retention_priority.pre_emp_vulnerability = ue_context_pP->ue_context.e_rab[i].param.qos.allocation_retention_priority.pre_emp_vulnerability; + } + + /* TODO: don't do that, X2AP should find the target by itself */ + //X2AP_HANDOVER_REQ(msg).target_mod_id = 0; + LOG_I(RRC, + "[eNB %d] Frame %d: potential handover preparation: store the information in an intermediate structure in case of failure\n", + ctxt_pP->module_id, ctxt_pP->frame); + itti_send_msg_to_task(TASK_X2AP, ENB_MODULE_ID_TO_INSTANCE(ctxt_pP->module_id), msg); + } else { + LOG_D(RRC, "[eNB %d] Frame %d: Ignoring MeasReport from UE %x as Handover is in progress... \n", ctxt_pP->module_id, ctxt_pP->frame, + ctxt_pP->rnti); + } + + return 0; +} + void check_handovers( protocol_ctxt_t *const ctxt_pP diff --git a/openair2/RRC/LTE/rrc_proto.h b/openair2/RRC/LTE/rrc_proto.h index 8aa0125c0e..e7e5e71d80 100644 --- a/openair2/RRC/LTE/rrc_proto.h +++ b/openair2/RRC/LTE/rrc_proto.h @@ -612,6 +612,12 @@ rrc_eNB_generate_HandoverPreparationInformation( //LTE_PhysCellId_t targetPhyId ); +int +flexran_rrc_eNB_trigger_handover (int mod_id, + const protocol_ctxt_t *const ctxt_pP, + rrc_eNB_ue_context_t *ue_context_pP, + int target_cell_id); + void check_handovers( protocol_ctxt_t *const ctxt_pP -- GitLab