Commit 8957cfef authored by Konstantinos Alexandris's avatar Konstantinos Alexandris Committed by Robert Schmidt

Add HO trigger function via FlexRAN controller (OAI + FlexRAN handler)

parent 5e148d43
...@@ -32,6 +32,7 @@ message flexran_message { ...@@ -32,6 +32,7 @@ message flexran_message {
flex_rrc_triggering rrc_triggering = 18; flex_rrc_triggering rrc_triggering = 18;
flex_ul_mac_config ul_mac_config_msg = 19; flex_ul_mac_config ul_mac_config_msg = 19;
flex_disconnect disconnect_msg = 20; flex_disconnect disconnect_msg = 20;
flex_ho_command ho_command_msg = 21;
} }
} }
...@@ -192,6 +193,12 @@ message flex_rrc_triggering { ...@@ -192,6 +193,12 @@ message flex_rrc_triggering {
optional flex_measurement_info meas_info = 3; 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 // UE state change message
// //
......
...@@ -34,6 +34,7 @@ enum flex_type { ...@@ -34,6 +34,7 @@ enum flex_type {
//Controller command messages //Controller command messages
FLPT_DL_MAC_CONFIG = 13; FLPT_DL_MAC_CONFIG = 13;
FLPT_HO_COMMAND = 21;
// UE state change messages // UE state change messages
FLPT_UE_STATE_CHANGE = 14; FLPT_UE_STATE_CHANGE = 14;
......
...@@ -837,8 +837,59 @@ int flexran_agent_rrc_reconfiguration(mid_t mod_id, const void *params, Protocol ...@@ -837,8 +837,59 @@ int flexran_agent_rrc_reconfiguration(mid_t mod_id, const void *params, Protocol
return 0; 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 // TODO
return 0; return 0;
} }
......
...@@ -138,8 +138,11 @@ int flexran_agent_destroy_agent_reconfiguration(Protocol__FlexranMessage *msg); ...@@ -138,8 +138,11 @@ int flexran_agent_destroy_agent_reconfiguration(Protocol__FlexranMessage *msg);
/* rrc triggering measurement message constructor and destructor */ /* 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_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 */ /* FlexRAN protocol message dispatcher function */
Protocol__FlexranMessage* flexran_agent_handle_message (mid_t mod_id, Protocol__FlexranMessage* flexran_agent_handle_message (mid_t mod_id,
......
...@@ -56,6 +56,9 @@ flexran_agent_message_decoded_callback agent_messages_callback[][3] = { ...@@ -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_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_reconfiguration, 0, 0}, /*PROTOCOL__FLEXRAN_MESSAGE__MSG_AGENT_RECONFIGURATION_MSG*/
{flexran_agent_rrc_reconfiguration, 0, 0}, /*PROTOCOL__FLEXRAN_MESSAGE__MSG_RRC_TRIGGERING_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[] = { flexran_agent_message_destruction_callback message_destruction_callback[] = {
......
...@@ -1446,6 +1446,16 @@ int flexran_call_rrc_reconfiguration (mid_t mod_id, rnti_t rnti) { ...@@ -1446,6 +1446,16 @@ int flexran_call_rrc_reconfiguration (mid_t mod_id, rnti_t rnti) {
return 0; 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 */ /* RRC Getters */
LTE_MeasId_t flexran_get_rrc_pcell_measid(mid_t mod_id, rnti_t rnti) { 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); ...@@ -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 */ /* Call RRC Reconfiguration wrapper function */
int flexran_call_rrc_reconfiguration (mid_t mod_id, rnti_t rnti); 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*/ /*Get primary cell measuremeant id flexRAN*/
LTE_MeasId_t flexran_get_rrc_pcell_measid(mid_t mod_id, rnti_t rnti); LTE_MeasId_t flexran_get_rrc_pcell_measid(mid_t mod_id, rnti_t rnti);
......
...@@ -4817,6 +4817,99 @@ void rrc_eNB_handover_cancel( ...@@ -4817,6 +4817,99 @@ void rrc_eNB_handover_cancel(
S1AP_CAUSE_RADIO_NETWORK, s1_cause); 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 void
check_handovers( check_handovers(
protocol_ctxt_t *const ctxt_pP protocol_ctxt_t *const ctxt_pP
......
...@@ -612,6 +612,12 @@ rrc_eNB_generate_HandoverPreparationInformation( ...@@ -612,6 +612,12 @@ rrc_eNB_generate_HandoverPreparationInformation(
//LTE_PhysCellId_t targetPhyId //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 void
check_handovers( check_handovers(
protocol_ctxt_t *const ctxt_pP protocol_ctxt_t *const ctxt_pP
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment