Add HO trigger function via FlexRAN controller (OAI + FlexRAN handler)
This commit is contained in:
committed by
Robert Schmidt
parent
5e148d439a
commit
8957cfef78
@@ -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
|
||||
//
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 flexran_agent_destroy_rrc_measurement(Protocol__FlexranMessage *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_trigger_handover(Protocol__FlexranMessage *msg) {
|
||||
// TODO
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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[] = {
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user