Commit 52a52eef authored by Konstantinos Alexandris's avatar Konstantinos Alexandris Committed by Cedric Roux
Browse files

X2AP UE Context Release (generate/handle message), Release eNB resources

parent 4b5c4211
......@@ -40,3 +40,6 @@ MESSAGE_DEF(X2AP_DEREGISTERED_ENB_IND , MESSAGE_PRIORITY_MED, x2ap_der
/* handover messages X2AP <-> RRC */
MESSAGE_DEF(X2AP_HANDOVER_REQ , MESSAGE_PRIORITY_MED, x2ap_handover_req_t , x2ap_handover_req)
MESSAGE_DEF(X2AP_HANDOVER_REQ_ACK , MESSAGE_PRIORITY_MED, x2ap_handover_req_ack_t , x2ap_handover_req_ack)
/* handover messages X2AP <-> S1AP */
MESSAGE_DEF(X2AP_UE_CONTEXT_RELEASE , MESSAGE_PRIORITY_MED, x2ap_ue_context_release_t , x2ap_ue_context_release)
......@@ -33,11 +33,20 @@
#define X2AP_HANDOVER_REQ_ACK(mSGpTR) (mSGpTR)->ittiMsg.x2ap_handover_req_ack
#define X2AP_REGISTER_ENB_CNF(mSGpTR) (mSGpTR)->ittiMsg.x2ap_register_enb_cnf
#define X2AP_DEREGISTERED_ENB_IND(mSGpTR) (mSGpTR)->ittiMsg.x2ap_deregistered_enb_ind
#define X2AP_UE_CONTEXT_RELEASE(mSGpTR) (mSGpTR)->ittiMsg.x2ap_ue_context_release
#define X2AP_MAX_NB_ENB_IP_ADDRESS 2
// eNB application layer -> X2AP messages
/* X2AP UE CONTEXT RELEASE */
typedef struct x2ap_ue_context_release_s {
int old_eNB_ue_x2ap_id;
int new_eNB_ue_x2ap_id;
int target_mod_id;
} x2ap_ue_context_release_t;
typedef struct x2ap_register_enb_req_s {
/* Unique eNB_id to identify the eNB within EPC.
* For macro eNB ids this field should be 20 bits long.
......
......@@ -343,7 +343,8 @@ typedef enum HO_STATE_e {
HO_COMPLETE, // initiated by the target eNB
HO_REQUEST,
HO_ACK,
HO_CONFIGURED
HO_CONFIGURED,
HO_RELEASE
} HO_STATE_t;
typedef enum SL_TRIGGER_e {
......
......@@ -4223,6 +4223,42 @@ void rrc_eNB_process_handoverCommand(
ue_context->ue_context.handover_info->size = size;
}
void rrc_eNB_handover_ue_context_release(
protocol_ctxt_t *const ctxt_pP,
struct rrc_eNB_ue_context_s *ue_context_p) {
int e_rab = 0;
//MessageDef *msg_release_p = NULL;
MessageDef *msg_delete_tunnels_p = NULL;
uint32_t eNB_ue_s1ap_id = ue_context_p->ue_context.eNB_ue_s1ap_id;
//msg_release_p = itti_alloc_new_message(TASK_RRC_ENB, S1AP_UE_CONTEXT_RELEASE);
//itti_send_msg_to_task(TASK_S1AP, ctxt_pP->module_id, msg_release_p);
s1ap_ue_context_release(ctxt_pP->instance, ue_context_p->ue_context.eNB_ue_s1ap_id);
//MSC_LOG_TX_MESSAGE(MSC_RRC_ENB, MSC_GTPU_ENB, NULL,0, "0 GTPV1U_ENB_DELETE_TUNNEL_REQ rnti %x ", eNB_ue_s1ap_id);
msg_delete_tunnels_p = itti_alloc_new_message(TASK_RRC_ENB, GTPV1U_ENB_DELETE_TUNNEL_REQ);
memset(&GTPV1U_ENB_DELETE_TUNNEL_REQ(msg_delete_tunnels_p), 0, sizeof(GTPV1U_ENB_DELETE_TUNNEL_REQ(msg_delete_tunnels_p)));
GTPV1U_ENB_DELETE_TUNNEL_REQ(msg_delete_tunnels_p).rnti = ue_context_p->ue_context.rnti;
for (e_rab = 0; e_rab < ue_context_p->ue_context.nb_of_e_rabs; e_rab++) {
GTPV1U_ENB_DELETE_TUNNEL_REQ(msg_delete_tunnels_p).eps_bearer_id[GTPV1U_ENB_DELETE_TUNNEL_REQ(msg_delete_tunnels_p).num_erab++] =
ue_context_p->ue_context.enb_gtp_ebi[e_rab];
// erase data
ue_context_p->ue_context.enb_gtp_teid[e_rab] = 0;
memset(&ue_context_p->ue_context.enb_gtp_addrs[e_rab], 0, sizeof(ue_context_p->ue_context.enb_gtp_addrs[e_rab]));
ue_context_p->ue_context.enb_gtp_ebi[e_rab] = 0;
}
itti_send_msg_to_task(TASK_GTPV1_U, ctxt_pP->module_id, msg_delete_tunnels_p);
struct rrc_ue_s1ap_ids_s *rrc_ue_s1ap_ids = NULL;
rrc_ue_s1ap_ids = rrc_eNB_S1AP_get_ue_ids(RC.rrc[ctxt_pP->module_id], 0, eNB_ue_s1ap_id);
if (rrc_ue_s1ap_ids != NULL) {
rrc_eNB_S1AP_remove_ue_ids(RC.rrc[ctxt_pP->module_id], rrc_ue_s1ap_ids);
}
}
#if 0
//-----------------------------------------------------------------------------
void
......@@ -7990,6 +8026,14 @@ void rrc_subframe_process(protocol_ctxt_t *const ctxt_pP, const int CC_id)
}
}
if (ue_context_p->ue_context.handover_info != NULL) {
if (ue_context_p->ue_context.handover_info->state == HO_RELEASE) {
ue_to_be_removed = ue_context_p;
rrc_eNB_handover_ue_context_release(ctxt_pP, ue_context_p);
break; //break RB_FOREACH (why to break ?)
}
}
pthread_mutex_lock(&rrc_release_freelist);
if (rrc_release_info.num_UEs > 0) {
......@@ -8161,6 +8205,9 @@ void *rrc_enb_process_itti_msg(void *notUsed) {
SRB_INFO *srb_info_p;
int CC_id;
protocol_ctxt_t ctxt;
// memset(&ctxt, 0, sizeof(ctxt));
// Wait for a message
itti_receive_msg(TASK_RRC_ENB, &msg_p);
msg_name_p = ITTI_MSG_NAME(msg_p);
......@@ -8278,7 +8325,8 @@ void *rrc_enb_process_itti_msg(void *notUsed) {
//LOG_I(RRC, "[eNB %d] Received message %s, not processed because procedure not synched\n",
//instance, msg_name_p);
if (rrc_eNB_get_ue_context(RC.rrc[instance], GTPV1U_ENB_DELETE_TUNNEL_RESP(msg_p).rnti)
&& rrc_eNB_get_ue_context(RC.rrc[instance], GTPV1U_ENB_DELETE_TUNNEL_RESP(msg_p).rnti)->ue_context.ue_release_timer_rrc > 0) {
&& rrc_eNB_get_ue_context(RC.rrc[instance], GTPV1U_ENB_DELETE_TUNNEL_RESP(msg_p).rnti)->ue_context.ue_release_timer_rrc > 0
&& rrc_eNB_get_ue_context(RC.rrc[instance], GTPV1U_ENB_DELETE_TUNNEL_RESP(msg_p).rnti)->ue_context.handover_info->state != HO_RELEASE) {
rrc_eNB_get_ue_context(RC.rrc[instance], GTPV1U_ENB_DELETE_TUNNEL_RESP(msg_p).rnti)->ue_context.ue_release_timer_rrc =
rrc_eNB_get_ue_context(RC.rrc[instance], GTPV1U_ENB_DELETE_TUNNEL_RESP(msg_p).rnti)->ue_context.ue_release_timer_thres_rrc;
}
......@@ -8310,6 +8358,19 @@ void *rrc_enb_process_itti_msg(void *notUsed) {
break;
}
case X2AP_UE_CONTEXT_RELEASE: {
struct rrc_eNB_ue_context_s *ue_context_p = NULL;
ue_context_p = rrc_eNB_get_ue_context(RC.rrc[instance], ctxt.rnti);
LOG_I(RRC, "[eNB %d] source eNB receives the X2 UE CONTEXT RELEASE %s at frame %d subframe %d \n", instance, msg_name_p,
ctxt.frame,ctxt.subframe);
DevAssert(ue_context_p != NULL);
if (ue_context_p->ue_context.handover_info->state != HO_COMPLETE) abort();
ue_context_p->ue_context.handover_info->state = HO_RELEASE;
break;
}
/* Messages from eNB app */
case RRC_CONFIGURATION_REQ:
LOG_I(RRC, "[eNB %d] Received %s : %p\n", instance, msg_name_p,&RRC_CONFIGURATION_REQ(msg_p));
......
......@@ -2087,9 +2087,60 @@ int rrc_eNB_process_S1AP_PATH_SWITCH_REQ_ACK (MessageDef *msg_p, const char *msg
/* Security key */
ue_context_p->ue_context.next_hop_chain_count=S1AP_PATH_SWITCH_REQ_ACK (msg_p).next_hop_chain_count;
memcpy ( ue_context_p->ue_context.next_security_key,
S1AP_PATH_SWITCH_REQ_ACK (msg_p).next_security_key,
SECURITY_KEY_LENGTH);
S1AP_PATH_SWITCH_REQ_ACK (msg_p).next_security_key,
SECURITY_KEY_LENGTH);
rrc_eNB_send_X2AP_UE_CONTEXT_RELEASE(&ctxt, ue_context_p);
return (0);
}
}
int rrc_eNB_send_X2AP_UE_CONTEXT_RELEASE(const protocol_ctxt_t* const ctxt_pP, rrc_eNB_ue_context_t* const ue_context_pP) {
MessageDef *msg_p = NULL;
msg_p = itti_alloc_new_message (TASK_RRC_ENB, X2AP_UE_CONTEXT_RELEASE);
X2AP_UE_CONTEXT_RELEASE (msg_p).old_eNB_ue_x2ap_id = 0;
X2AP_UE_CONTEXT_RELEASE (msg_p).new_eNB_ue_x2ap_id = 0;
X2AP_UE_CONTEXT_RELEASE (msg_p).target_mod_id = ue_context_pP->ue_context.handover_info->modid_t;
itti_send_msg_to_task (TASK_X2AP, ctxt_pP->instance, msg_p);
return (0);
}
int s1ap_ue_context_release(instance_t instance, const uint32_t eNB_ue_s1ap_id){
s1ap_eNB_instance_t *s1ap_eNB_instance_p = NULL;
struct s1ap_eNB_ue_context_s *ue_context_p = NULL;
s1ap_eNB_instance_p = s1ap_eNB_get_instance(instance);
DevAssert(s1ap_eNB_instance_p != NULL);
if ((ue_context_p = s1ap_eNB_get_ue_context(s1ap_eNB_instance_p,
eNB_ue_s1ap_id)) == NULL) {
/* The context for this eNB ue s1ap id doesn't exist in the map of eNB UEs */
LOG_W(RRC,"Failed to find ue context associated with eNB ue s1ap id: %u\n",
eNB_ue_s1ap_id);
return -1;
}
// release UE context
struct s1ap_eNB_ue_context_s *ue_context2_p = NULL;
if ((ue_context2_p = RB_REMOVE(s1ap_ue_map, &s1ap_eNB_instance_p->s1ap_ue_head, ue_context_p))
!= NULL) {
LOG_W(RRC,"Removed UE context eNB_ue_s1ap_id %u\n",
ue_context2_p->eNB_ue_s1ap_id);
s1ap_eNB_free_ue_context(ue_context2_p);
} else {
LOG_W(RRC,"Removing UE context eNB_ue_s1ap_id %u: did not find context\n",
ue_context_p->eNB_ue_s1ap_id);
}
/*RB_FOREACH(ue_context_p, s1ap_ue_map, &s1ap_eNB_instance_p->s1ap_ue_head) {
S1AP_WARN("in s1ap_ue_map: UE context eNB_ue_s1ap_id %u mme_ue_s1ap_id %u state %u\n",
ue_context_p->eNB_ue_s1ap_id, ue_context_p->mme_ue_s1ap_id,
ue_context_p->ue_state);
}*/
return 0;
}
......@@ -270,4 +270,8 @@ int rrc_eNB_send_PATH_SWITCH_REQ(const protocol_ctxt_t *const ctxt_pP,
rrc_eNB_ue_context_t *const ue_context_pP);
int rrc_eNB_process_S1AP_PATH_SWITCH_REQ_ACK (MessageDef *msg_p, const char *msg_name, instance_t instance);
int rrc_eNB_send_X2AP_UE_CONTEXT_RELEASE(const protocol_ctxt_t* const ctxt_pP, rrc_eNB_ue_context_t* const ue_context_pP);
int s1ap_ue_context_release(instance_t instance, const uint32_t eNB_ue_s1ap_id);
#endif /* RRC_ENB_S1AP_H_ */
......@@ -79,6 +79,11 @@ static
void x2ap_eNB_handle_handover_req_ack(instance_t instance,
x2ap_handover_req_ack_t *x2ap_handover_req_ack);
static
void x2ap_eNB_handle_ue_context_release(instance_t instance,
x2ap_ue_context_release_t *x2ap_ue_context_release);
static
void x2ap_eNB_handle_sctp_data_ind(instance_t instance, sctp_data_ind_t *sctp_data_ind) {
int result;
......@@ -423,6 +428,23 @@ void x2ap_eNB_handle_handover_req_ack(instance_t instance,
//x2ap_handover_req_ack->rrc_buffer, x2ap_handover_req_ack->rrc_buffer_size);
}
static
void x2ap_eNB_handle_ue_context_release(instance_t instance,
x2ap_ue_context_release_t *x2ap_ue_context_release)
{
x2ap_eNB_instance_t *instance_p;
x2ap_eNB_data_t *target;
int target_enb_id = x2ap_ue_context_release->target_mod_id;
instance_p = x2ap_eNB_get_instance(instance);
DevAssert(instance_p != NULL);
target = x2ap_is_eNB_id_in_list(target_enb_id);
DevAssert(target != NULL);
x2ap_eNB_generate_x2_ue_context_release(target, x2ap_ue_context_release);
}
void *x2ap_task(void *arg) {
MessageDef *received_msg = NULL;
int result;
......@@ -454,6 +476,11 @@ void *x2ap_task(void *arg) {
&X2AP_HANDOVER_REQ_ACK(received_msg));
break;
case X2AP_UE_CONTEXT_RELEASE:
x2ap_eNB_handle_ue_context_release(ITTI_MESSAGE_GET_INSTANCE(received_msg),
&X2AP_UE_CONTEXT_RELEASE(received_msg));
break;
case SCTP_INIT_MSG_MULTI_CNF:
x2ap_eNB_handle_sctp_init_msg_multi_cnf(ITTI_MESSAGE_GET_INSTANCE(received_msg),
&received_msg->ittiMsg.sctp_init_msg_multi_cnf);
......
......@@ -48,6 +48,10 @@ static int x2ap_eNB_decode_initiating_message(X2AP_X2AP_PDU_t *pdu)
//asn_encode_to_new_buffer(NULL, ATS_CANONICAL_XER, &asn_DEF_X2AP_X2AP_PDU, pdu);
X2AP_INFO("x2ap_eNB_decode_initiating_message!\n");
break;
case X2AP_ProcedureCode_id_uEContextRelease:
//asn_encode_to_new_buffer(NULL, ATS_CANONICAL_XER, &asn_DEF_X2AP_X2AP_PDU, pdu);
X2AP_INFO("x2ap_eNB_decode_initiating_message!\n");
break;
default:
X2AP_ERROR("Unknown procedure ID (%d) for initiating message\n",
......
......@@ -619,8 +619,8 @@ int x2ap_eNB_generate_x2_handover_request_ack (x2ap_eNB_data_t *x2ap_eNB_data_p,
ie = (X2AP_HandoverRequestAcknowledge_IEs_t *)calloc(1, sizeof(X2AP_HandoverRequestAcknowledge_IEs_t));
ie->id = X2AP_ProtocolIE_ID_id_New_eNB_UE_X2AP_ID;
ie->criticality = X2AP_Criticality_ignore;
ie->value.present = X2AP_HandoverRequestAcknowledge_IEs__value_PR_UE_X2AP_ID;
ie->value.choice.UE_X2AP_ID = 0;
ie->value.present = X2AP_HandoverRequestAcknowledge_IEs__value_PR_UE_X2AP_ID_1;
ie->value.choice.UE_X2AP_ID_1 = 0;
ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
/* mandatory */
......@@ -668,7 +668,7 @@ int x2ap_eNB_generate_x2_handover_request_ack (x2ap_eNB_data_t *x2ap_eNB_data_p,
return ret;
}
int x2ap_eNB_generate_x2_ue_context_release (x2ap_eNB_data_t *x2ap_eNB_data_p)
int x2ap_eNB_generate_x2_ue_context_release (x2ap_eNB_data_t *x2ap_eNB_data_p, x2ap_ue_context_release_t *x2ap_ue_context_release)
{
X2AP_X2AP_PDU_t pdu;
......@@ -701,15 +701,15 @@ int x2ap_eNB_generate_x2_ue_context_release (x2ap_eNB_data_t *x2ap_eNB_data_p)
ie->id = X2AP_ProtocolIE_ID_id_Old_eNB_UE_X2AP_ID;
ie->criticality = X2AP_Criticality_reject;
ie->value.present = X2AP_UEContextRelease_IEs__value_PR_UE_X2AP_ID;
ie->value.choice.UE_X2AP_ID = 0;
ie->value.choice.UE_X2AP_ID = x2ap_ue_context_release->old_eNB_ue_x2ap_id;
ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
/* mandatory */
ie = (X2AP_UEContextRelease_IEs_t *)calloc(1, sizeof(X2AP_UEContextRelease_IEs_t));
ie->id = X2AP_ProtocolIE_ID_id_New_eNB_UE_X2AP_ID;
ie->criticality = X2AP_Criticality_reject;
ie->value.present = X2AP_UEContextRelease_IEs__value_PR_UE_X2AP_ID;
ie->value.choice.UE_X2AP_ID = 0;
ie->value.present = X2AP_UEContextRelease_IEs__value_PR_UE_X2AP_ID_1;
ie->value.choice.UE_X2AP_ID_1 = x2ap_ue_context_release->new_eNB_ue_x2ap_id;
ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
if (x2ap_eNB_encode_pdu(&pdu, &buffer, &len) < 0) {
......
......@@ -53,6 +53,7 @@ int x2ap_eNB_generate_x2_handover_request (x2ap_eNB_data_t *x2ap_eNB_data_p,
int x2ap_eNB_generate_x2_handover_request_ack (x2ap_eNB_data_t *x2ap_eNB_data_p,
x2ap_handover_req_ack_t *x2ap_handover_req_ack);
int x2ap_eNB_generate_x2_ue_context_release (x2ap_eNB_data_t *x2ap_eNB_data_p);
int x2ap_eNB_generate_x2_ue_context_release (x2ap_eNB_data_t *x2ap_eNB_data_p,
x2ap_ue_context_release_t *x2ap_ue_context_release);
#endif /* X2AP_ENB_GENERATE_MESSAGES_H_ */
......@@ -71,6 +71,12 @@ int x2ap_eNB_handle_handover_response (instance_t instance,
uint32_t stream,
X2AP_X2AP_PDU_t *pdu);
static
int x2ap_eNB_handle_ue_context_release (instance_t instance,
uint32_t assoc_id,
uint32_t stream,
X2AP_X2AP_PDU_t *pdu);
/* Handlers matrix. Only eNB related procedure present here */
x2ap_message_decoded_callback x2ap_messages_callback[][3] = {
{ x2ap_eNB_handle_handover_preparation, x2ap_eNB_handle_handover_response, 0 }, /* handoverPreparation */
......@@ -78,7 +84,7 @@ x2ap_message_decoded_callback x2ap_messages_callback[][3] = {
{ 0, 0, 0 }, /* loadIndication */
{ 0, 0, 0 }, /* errorIndication */
{ 0, 0, 0 }, /* snStatusTransfer */
{ 0, 0, 0 }, /* uEContextRelease */
{ x2ap_eNB_handle_ue_context_release, 0, 0 }, /* uEContextRelease */
{ x2ap_eNB_handle_x2_setup_request, x2ap_eNB_handle_x2_setup_response, x2ap_eNB_handle_x2_setup_failure }, /* x2Setup */
{ 0, 0, 0 }, /* reset */
{ 0, 0, 0 }, /* eNBConfigurationUpdate */
......@@ -726,3 +732,47 @@ int x2ap_eNB_handle_handover_response (instance_t instance,
itti_send_msg_to_task(TASK_RRC_ENB, x2ap_eNB_data->x2ap_eNB_instance->instance, msg);
return 0;
}
static
int x2ap_eNB_handle_ue_context_release (instance_t instance,
uint32_t assoc_id,
uint32_t stream,
X2AP_X2AP_PDU_t *pdu)
{
X2AP_UEContextRelease_t *x2UEContextRelease;
X2AP_UEContextRelease_IEs_t *ie;
x2ap_eNB_data_t *x2ap_eNB_data;
MessageDef *msg;
DevAssert (pdu != NULL);
x2UEContextRelease = &pdu->choice.initiatingMessage.value.choice.UEContextRelease;
if (stream == 0) {
X2AP_ERROR ("Received new x2 ue context release on stream == 0\n");
/* TODO: send a x2 failure response */
return 0;
}
X2AP_DEBUG ("Received a new X2 ue context release\n");
x2ap_eNB_data = x2ap_get_eNB(NULL, assoc_id, 0);
DevAssert(x2ap_eNB_data != NULL);
msg = itti_alloc_new_message(TASK_X2AP, X2AP_UE_CONTEXT_RELEASE);
X2AP_FIND_PROTOCOLIE_BY_ID(X2AP_UEContextRelease_IEs_t, ie, x2UEContextRelease,
X2AP_ProtocolIE_ID_id_Old_eNB_UE_X2AP_ID, true);
X2AP_UE_CONTEXT_RELEASE(msg).old_eNB_ue_x2ap_id = ie->value.choice.UE_X2AP_ID;
X2AP_FIND_PROTOCOLIE_BY_ID(X2AP_UEContextRelease_IEs_t, ie, x2UEContextRelease,
X2AP_ProtocolIE_ID_id_New_eNB_UE_X2AP_ID, true);
X2AP_UE_CONTEXT_RELEASE(msg).new_eNB_ue_x2ap_id = ie->value.choice.UE_X2AP_ID;
itti_send_msg_to_task(TASK_RRC_ENB, x2ap_eNB_data->x2ap_eNB_instance->instance, msg);
return 0;
}
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