nr: improve x2/rrc for ENDC

This commit introduces several enhancements in X2AP and RRC to deal
with ENDC. The main goal is to deal with UE's on/off and with various
errors.

The following work is included:

    - DC prep and DC overall X2 timers
    - X2 messages for UE release and DC timers' timeout

Open problems:

    - what to do when the UE sends an scg Failure? This commit removes
      the UE. And this removal may not be correctly done
    - UE removal in the gNB's PHY layer (a next commit is coming,
      but it is hackish and will need a rework)
This commit is contained in:
Cedric Roux
2020-09-22 11:57:31 +02:00
parent 5372a3478a
commit 4236ff2b3e
103 changed files with 1235 additions and 160 deletions
+64 -38
View File
@@ -305,7 +305,9 @@ void x2ap_eNB_handle_register_eNB(instance_t instance,
x2ap_id_manager_init(&new_instance->id_manager);
x2ap_timers_init(&new_instance->timers,
x2ap_register_eNB->t_reloc_prep,
x2ap_register_eNB->tx2_reloc_overall);
x2ap_register_eNB->tx2_reloc_overall,
x2ap_register_eNB->t_dc_prep,
x2ap_register_eNB->t_dc_overall);
for (int i = 0; i< x2ap_register_eNB->num_cc; i++) {
new_instance->eutra_band[i] = x2ap_register_eNB->eutra_band[i];
@@ -476,7 +478,10 @@ void x2ap_eNB_handle_sgNB_add_req(instance_t instance,
}
/* id_source is ue_id, id_target is unknown yet */
x2ap_set_ids(id_manager, ue_id, x2ap_ENDC_sgnb_addition_req->rnti, ue_id, -1);
x2ap_id_set_state(id_manager, ue_id, X2ID_STATE_NSA_PREPARE);
x2ap_id_set_state(id_manager, ue_id, X2ID_STATE_NSA_ENB_PREPARE);
x2ap_set_dc_prep_timer(id_manager, ue_id,
x2ap_timer_get_tti(&instance_p->timers));
x2ap_id_set_target(id_manager, ue_id, x2ap_eNB_data);
x2ap_eNB_generate_ENDC_x2_SgNB_addition_request(instance_p, x2ap_ENDC_sgnb_addition_req,
x2ap_eNB_data, ue_id);
@@ -498,9 +503,6 @@ void x2ap_gNB_trigger_sgNB_add_req_ack(instance_t instance,
x2ap_eNB_instance_t *instance_p;
x2ap_eNB_data_t *target;
int ue_id;
/*int source_assoc_id = x2ap_ENDC_sgnb_addition_req_ACK->source_assoc_id;
int id_source;
int id_target;*/
instance_p = x2ap_eNB_get_instance(instance);
DevAssert(instance_p != NULL);
@@ -514,22 +516,15 @@ void x2ap_gNB_trigger_sgNB_add_req_ack(instance_t instance,
X2AP_ERROR("could not allocate a new X2AP UE ID\n");
exit(1);
}
/* id_source is ue_id, id_target is unknown yet */
x2ap_set_ids(id_manager, ue_id, x2ap_ENDC_sgnb_addition_req_ACK->rnti, ue_id,
x2ap_ENDC_sgnb_addition_req_ACK->MeNB_ue_x2_id);
x2ap_id_set_state(id_manager, ue_id, X2ID_STATE_SOURCE_OVERALL);
/*target = x2ap_get_eNB(NULL, source_assoc_id, 0);
DevAssert(target != NULL);*/
// rnti is a new information, save it
/*ue_id = x2ap_handover_req_ack->x2_id_target;
id_source = x2ap_id_get_id_source(&instance_p->id_manager, ue_id);
id_target = ue_id;
x2ap_set_ids(&instance_p->id_manager, ue_id, x2ap_handover_req_ack->rnti, id_source, id_target);*/
/* id_Source is MeNB_ue_x2_id, id_target is rnti (rnti is SgNB_ue_x2_id) */
x2ap_set_ids(id_manager, ue_id,
x2ap_ENDC_sgnb_addition_req_ACK->SgNB_ue_x2_id,
x2ap_ENDC_sgnb_addition_req_ACK->MeNB_ue_x2_id,
x2ap_ENDC_sgnb_addition_req_ACK->SgNB_ue_x2_id);
x2ap_id_set_state(id_manager, ue_id, X2ID_STATE_NSA_GNB_OVERALL);
x2ap_set_dc_overall_timer(id_manager, ue_id,
x2ap_timer_get_tti(&instance_p->timers));
x2ap_id_set_target(id_manager, ue_id, target);
x2ap_gNB_generate_ENDC_x2_SgNB_addition_request_ACK(instance_p, target,
x2ap_ENDC_sgnb_addition_req_ACK, ue_id);
@@ -540,27 +535,24 @@ void x2ap_gNB_trigger_sgNB_add_req_ack(instance_t instance,
* @param : IN instance, IN x2ap_reconf_complete
**/
static
void x2ap_eNB_trigger_sgnb_reconfiguration_complete(instance_t instance,
x2ap_ENDC_reconf_complete_t *x2ap_reconf_complete)
void x2ap_eNB_trigger_sgnb_reconfiguration_complete(instance_t instance,
x2ap_ENDC_reconf_complete_t *x2ap_reconf_complete)
{
x2ap_eNB_instance_t *instance_p = NULL;
x2ap_eNB_data_t *target = NULL;
int id_source = -1;
int id_target = -1;
LTE_PhysCellId_t target_pci;
x2ap_eNB_instance_t *instance_p;
x2ap_eNB_data_t *target;
int id_source;
int id_target;
instance_p = x2ap_eNB_get_instance(instance);
DevAssert(instance_p != NULL);
DevAssert(x2ap_reconf_complete != NULL);
target_pci = x2ap_reconf_complete->target_physCellId;
target = x2ap_is_eNB_pci_in_list(target_pci);
target = x2ap_get_eNB(NULL,x2ap_reconf_complete->gnb_x2_assoc_id, 0);
DevAssert(target != NULL);
id_source = x2ap_reconf_complete->MeNB_ue_x2_id;
id_target = x2ap_reconf_complete->SgNB_ue_x2_id;
x2ap_eNB_generate_ENDC_x2_SgNB_reconfiguration_complete(instance_p, target, id_source, id_target);
}
@@ -589,6 +581,34 @@ void x2ap_eNB_ue_context_release(instance_t instance,
x2ap_release_id(&instance_p->id_manager, ue_id);
}
static
void x2ap_eNB_handle_sgNB_release_request(instance_t instance,
x2ap_ENDC_sgnb_release_request_t *x2ap_release_req)
{
x2ap_eNB_instance_t *instance_p;
x2ap_eNB_data_t *target;
instance_p = x2ap_eNB_get_instance(instance);
DevAssert(instance_p != NULL);
DevAssert(x2ap_release_req != NULL);
if (x2ap_release_req->rnti == -1 ||
x2ap_release_req->assoc_id == -1) {
X2AP_WARN("x2ap_eNB_handle_sgNB_release_request: bad rnti or assoc_id, do not send release request to gNB\n");
return;
}
target = x2ap_get_eNB(NULL, x2ap_release_req->assoc_id, 0);
DevAssert(target != NULL);
/* id_source is not used by oai's gNB so it's not big deal. For
* interoperability with other gNBs things may need to be refined.
*/
x2ap_eNB_generate_ENDC_x2_SgNB_release_request(instance_p, target,
0, x2ap_release_req->rnti,
x2ap_release_req->cause);
}
void *x2ap_task(void *arg) {
MessageDef *received_msg = NULL;
int result;
@@ -640,10 +660,16 @@ void *x2ap_task(void *arg) {
LOG_I(X2AP, "Received elements for X2AP_ENDC_SGNB_ADDITION_REQ_ACK \n");
break;
case X2AP_ENDC_SGNB_RECONF_COMPLETE:
x2ap_eNB_trigger_sgnb_reconfiguration_complete(ITTI_MESSAGE_GET_INSTANCE(received_msg),
&X2AP_ENDC_SGNB_RECONF_COMPLETE(received_msg));
break;
case X2AP_ENDC_SGNB_RECONF_COMPLETE:
x2ap_eNB_trigger_sgnb_reconfiguration_complete(ITTI_MESSAGE_GET_INSTANCE(received_msg),
&X2AP_ENDC_SGNB_RECONF_COMPLETE(received_msg));
break;
case X2AP_ENDC_SGNB_RELEASE_REQUEST:
x2ap_eNB_handle_sgNB_release_request(ITTI_MESSAGE_GET_INSTANCE(received_msg),
&X2AP_ENDC_SGNB_RELEASE_REQUEST(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);
+12
View File
@@ -69,6 +69,14 @@ static int x2ap_eNB_decode_initiating_message(X2AP_X2AP_PDU_t *pdu)
X2AP_INFO("X2AP_ProcedureCode_id_sgNBReconfigurationCompletion message!\n");
break;
case X2AP_ProcedureCode_id_meNBinitiatedSgNBRelease:
X2AP_INFO("X2AP_ProcedureCode_id_meNBinitiatedSgNBRelease message!\n");
break;
case X2AP_ProcedureCode_id_sgNBinitiatedSgNBRelease:
X2AP_INFO("X2AP_ProcedureCode_id_sgNBinitiatedSgNBRelease message!\n");
break;
default:
X2AP_ERROR("Unknown procedure ID (%d) for initiating message\n",
(int)pdu->choice.initiatingMessage.procedureCode);
@@ -103,6 +111,10 @@ static int x2ap_eNB_decode_successful_outcome(X2AP_X2AP_PDU_t *pdu)
X2AP_INFO("x2ap_eNB_decode_successfuloutcome_message!\n");
break;
case X2AP_ProcedureCode_id_meNBinitiatedSgNBRelease:
X2AP_INFO("meNBinitiatedSgNBRelease successful outcome!\n");
break;
default:
X2AP_ERROR("Unknown procedure ID (%d) for successfull outcome message\n",
(int)pdu->choice.successfulOutcome.procedureCode);
+226 -5
View File
@@ -1668,8 +1668,6 @@ int x2ap_gNB_generate_ENDC_x2_SgNB_addition_request_ACK( x2ap_eNB_instance_t *in
uint32_t len;
int ret = 0;
int MeNB_UE_X2AP_id = x2ap_sgnb_addition_req_ACK->MeNB_ue_x2_id;
int SgNB_UE_X2AP_id = ue_id;
int e_rabs_admitted_tobeadded = x2ap_sgnb_addition_req_ACK->nb_e_rabs_admitted_tobeadded;
long int pDCPatSgNB = X2AP_EN_DC_ResourceConfiguration__pDCPatSgNB_present;
long int mCGresources = X2AP_EN_DC_ResourceConfiguration__mCGresources_not_present;
@@ -1694,7 +1692,7 @@ int x2ap_gNB_generate_ENDC_x2_SgNB_addition_request_ACK( x2ap_eNB_instance_t *in
ie->id = X2AP_ProtocolIE_ID_id_MeNB_UE_X2AP_ID;
ie->criticality= X2AP_Criticality_reject;
ie->value.present = X2AP_SgNBAdditionRequestAcknowledge_IEs__value_PR_UE_X2AP_ID;
ie->value.choice.UE_X2AP_ID = MeNB_UE_X2AP_id; //x2ap_id_get_id_source(&instance_p->id_manager, ue_id);
ie->value.choice.UE_X2AP_ID = x2ap_id_get_id_source(&instance_p->id_manager, ue_id);
ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
// SgNB_UE_X2AP_id
@@ -1702,7 +1700,7 @@ int x2ap_gNB_generate_ENDC_x2_SgNB_addition_request_ACK( x2ap_eNB_instance_t *in
ie->id = X2AP_ProtocolIE_ID_id_SgNB_UE_X2AP_ID;
ie->criticality= X2AP_Criticality_reject;
ie->value.present = X2AP_SgNBAdditionRequestAcknowledge_IEs__value_PR_SgNB_UE_X2AP_ID;
ie->value.choice.UE_X2AP_ID = SgNB_UE_X2AP_id; //x2ap_id_get_id_source(&instance_p->id_manager, ue_id);
ie->value.choice.UE_X2AP_ID = x2ap_id_get_id_target(&instance_p->id_manager, ue_id);
ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
ie = (X2AP_SgNBAdditionRequestAcknowledge_IEs_t *)calloc(1, sizeof(X2AP_SgNBAdditionRequestAcknowledge_IEs_t));
@@ -1792,7 +1790,7 @@ int x2ap_eNB_generate_ENDC_x2_SgNB_reconfiguration_complete(
ie->id = X2AP_ProtocolIE_ID_id_MeNB_UE_X2AP_ID;
ie->criticality= X2AP_Criticality_reject;
ie->value.present = X2AP_SgNBReconfigurationComplete_IEs__value_PR_UE_X2AP_ID;
ie->value.choice.UE_X2AP_ID = ue_id; //x2ap_id_get_id_source(&instance_p->id_manager, ue_id);
ie->value.choice.UE_X2AP_ID = x2ap_id_get_id_source(&instance_p->id_manager, ue_id);
ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
ie = (X2AP_SgNBReconfigurationComplete_IEs_t *)calloc(1, sizeof(X2AP_SgNBReconfigurationComplete_IEs_t));
@@ -1821,3 +1819,226 @@ int x2ap_eNB_generate_ENDC_x2_SgNB_reconfiguration_complete(
return ret;
}
int x2ap_eNB_generate_ENDC_x2_SgNB_release_request(
x2ap_eNB_instance_t *instance_p, x2ap_eNB_data_t *x2ap_eNB_data_p,
int x2_id_source, int x2_id_target, x2ap_cause_t cause)
{
X2AP_X2AP_PDU_t pdu;
X2AP_SgNBReleaseRequest_t *out;
X2AP_SgNBReleaseRequest_IEs_t *ie;
uint8_t *buffer;
uint32_t len;
int ret = 0;
DevAssert(instance_p != NULL);
DevAssert(x2ap_eNB_data_p != NULL);
memset(&pdu, 0, sizeof(pdu));
pdu.present = X2AP_X2AP_PDU_PR_initiatingMessage;
pdu.choice.initiatingMessage.procedureCode = X2AP_ProcedureCode_id_meNBinitiatedSgNBRelease;
pdu.choice.initiatingMessage.criticality = X2AP_Criticality_ignore;
pdu.choice.initiatingMessage.value.present = X2AP_InitiatingMessage__value_PR_SgNBReleaseRequest;
out = &pdu.choice.initiatingMessage.value.choice.SgNBReleaseRequest;
ie = (X2AP_SgNBReleaseRequest_IEs_t *)calloc(1, sizeof(X2AP_SgNBReleaseRequest_IEs_t));
ie->id = X2AP_ProtocolIE_ID_id_MeNB_UE_X2AP_ID;
ie->criticality= X2AP_Criticality_reject;
ie->value.present = X2AP_SgNBReleaseRequest_IEs__value_PR_UE_X2AP_ID;
ie->value.choice.UE_X2AP_ID = x2_id_source;
ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
if (x2_id_target != -1) {
ie = (X2AP_SgNBReleaseRequest_IEs_t *)calloc(1, sizeof(X2AP_SgNBReleaseRequest_IEs_t));
ie->id = X2AP_ProtocolIE_ID_id_SgNB_UE_X2AP_ID;
ie->criticality= X2AP_Criticality_reject;
ie->value.present = X2AP_SgNBReleaseRequest_IEs__value_PR_SgNB_UE_X2AP_ID;
ie->value.choice.SgNB_UE_X2AP_ID = x2_id_target;
ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
}
ie = (X2AP_SgNBReleaseRequest_IEs_t *)calloc(1, sizeof(X2AP_SgNBReleaseRequest_IEs_t));
ie->id = X2AP_ProtocolIE_ID_id_Cause;
ie->criticality= X2AP_Criticality_ignore;
ie->value.present = X2AP_SgNBReleaseRequest_IEs__value_PR_Cause;
switch (cause) {
case X2AP_CAUSE_T_DC_PREP_TIMEOUT:
ie->value.choice.Cause.present = X2AP_Cause_PR_radioNetwork;
ie->value.choice.Cause.choice.radioNetwork = X2AP_CauseRadioNetwork_tDCprep_expiry;
break;
case X2AP_CAUSE_RADIO_CONNECTION_WITH_UE_LOST:
ie->value.choice.Cause.present = X2AP_Cause_PR_radioNetwork;
ie->value.choice.Cause.choice.radioNetwork = X2AP_CauseRadioNetwork_radio_connection_with_UE_lost;
break;
default:
X2AP_ERROR("%s: unhandled cause %d\n", __FUNCTION__, cause);
exit(1);
}
ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
if (x2ap_eNB_encode_pdu(&pdu, &buffer, &len) < 0) {
X2AP_ERROR("Failed to encode ENDC X2 SgNB_release_request message\n");
return -1;
}
x2ap_eNB_itti_send_sctp_data_req(instance_p->instance, x2ap_eNB_data_p->assoc_id, buffer, len, 0);
return ret;
}
int x2ap_gNB_generate_ENDC_x2_SgNB_release_request_acknowledge(
x2ap_eNB_instance_t *instance_p, x2ap_eNB_data_t *x2ap_eNB_data_p,
int menb_ue_x2ap_id, int sgnb_ue_x2ap_id)
{
X2AP_X2AP_PDU_t pdu;
X2AP_SgNBReleaseRequestAcknowledge_t *out;
X2AP_SgNBReleaseRequestAcknowledge_IEs_t *ie;
uint8_t *buffer;
uint32_t len;
int ret = 0;
DevAssert(instance_p != NULL);
DevAssert(x2ap_eNB_data_p != NULL);
x2ap_eNB_data_p->state = X2AP_ENB_STATE_WAITING;
memset(&pdu, 0, sizeof(pdu));
pdu.present = X2AP_X2AP_PDU_PR_successfulOutcome;
pdu.choice.successfulOutcome.procedureCode = X2AP_ProcedureCode_id_meNBinitiatedSgNBRelease;
pdu.choice.successfulOutcome.criticality = X2AP_Criticality_ignore;
pdu.choice.successfulOutcome.value.present = X2AP_SuccessfulOutcome__value_PR_SgNBReleaseRequestAcknowledge;
out = &pdu.choice.successfulOutcome.value.choice.SgNBReleaseRequestAcknowledge;
ie = (X2AP_SgNBReleaseRequestAcknowledge_IEs_t *)calloc(1, sizeof(X2AP_SgNBReleaseRequestAcknowledge_IEs_t));
ie->id = X2AP_ProtocolIE_ID_id_MeNB_UE_X2AP_ID;
ie->criticality= X2AP_Criticality_ignore;
ie->value.present = X2AP_SgNBReleaseRequestAcknowledge_IEs__value_PR_UE_X2AP_ID;
ie->value.choice.UE_X2AP_ID = menb_ue_x2ap_id;
ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
ie = (X2AP_SgNBReleaseRequestAcknowledge_IEs_t *)calloc(1, sizeof(X2AP_SgNBReleaseRequestAcknowledge_IEs_t));
ie->id = X2AP_ProtocolIE_ID_id_SgNB_UE_X2AP_ID;
ie->criticality= X2AP_Criticality_ignore;
ie->value.present = X2AP_SgNBReleaseRequestAcknowledge_IEs__value_PR_SgNB_UE_X2AP_ID;
ie->value.choice.SgNB_UE_X2AP_ID = sgnb_ue_x2ap_id;
ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
if (x2ap_eNB_encode_pdu(&pdu, &buffer, &len) < 0) {
X2AP_ERROR("Failed to encode ENDC X2 SgNB Release Request Acknowledge\n");
return -1;
}
x2ap_eNB_itti_send_sctp_data_req(instance_p->instance, x2ap_eNB_data_p->assoc_id, buffer, len, 0);
return ret;
}
int x2ap_eNB_generate_ENDC_x2_SgNB_release_required(
x2ap_eNB_instance_t *instance_p, x2ap_eNB_data_t *x2ap_eNB_data_p,
int x2_id_source, int x2_id_target, x2ap_cause_t cause)
{
X2AP_X2AP_PDU_t pdu;
X2AP_SgNBReleaseRequired_t *out;
X2AP_SgNBReleaseRequired_IEs_t *ie;
uint8_t *buffer;
uint32_t len;
int ret = 0;
DevAssert(instance_p != NULL);
DevAssert(x2ap_eNB_data_p != NULL);
/* Prepare the X2AP message to encode */
memset(&pdu, 0, sizeof(pdu));
pdu.present = X2AP_X2AP_PDU_PR_initiatingMessage;
pdu.choice.initiatingMessage.procedureCode = X2AP_ProcedureCode_id_sgNBinitiatedSgNBRelease;
pdu.choice.initiatingMessage.criticality = X2AP_Criticality_reject;
pdu.choice.initiatingMessage.value.present = X2AP_InitiatingMessage__value_PR_SgNBReleaseRequired;
out = &pdu.choice.initiatingMessage.value.choice.SgNBReleaseRequired;
ie = (X2AP_SgNBReleaseRequired_IEs_t *)calloc(1, sizeof(X2AP_SgNBReleaseRequired_IEs_t));
ie->id = X2AP_ProtocolIE_ID_id_MeNB_UE_X2AP_ID;
ie->criticality= X2AP_Criticality_reject;
ie->value.present = X2AP_SgNBReleaseRequired_IEs__value_PR_UE_X2AP_ID;
ie->value.choice.UE_X2AP_ID = x2_id_source;
ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
ie = (X2AP_SgNBReleaseRequired_IEs_t *)calloc(1, sizeof(X2AP_SgNBReleaseRequired_IEs_t));
ie->id = X2AP_ProtocolIE_ID_id_SgNB_UE_X2AP_ID;
ie->criticality= X2AP_Criticality_reject;
ie->value.present = X2AP_SgNBReleaseRequired_IEs__value_PR_SgNB_UE_X2AP_ID;
ie->value.choice.SgNB_UE_X2AP_ID = x2_id_target;
ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
ie = (X2AP_SgNBReleaseRequired_IEs_t *)calloc(1, sizeof(X2AP_SgNBReleaseRequired_IEs_t));
ie->id = X2AP_ProtocolIE_ID_id_Cause;
ie->criticality= X2AP_Criticality_ignore;
ie->value.present = X2AP_SgNBReleaseRequired_IEs__value_PR_Cause;
switch (cause) {
case X2AP_CAUSE_T_DC_OVERALL_TIMEOUT:
ie->value.choice.Cause.present = X2AP_Cause_PR_radioNetwork;
ie->value.choice.Cause.choice.radioNetwork = X2AP_CauseRadioNetwork_tDCoverall_expiry;
break;
default:
X2AP_ERROR("%s: unhandled cause %d\n", __FUNCTION__, cause);
exit(1);
}
ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
if (x2ap_eNB_encode_pdu(&pdu, &buffer, &len) < 0) {
X2AP_ERROR("Failed to encode ENDC X2 SgNB_release_request message\n");
return -1;
}
x2ap_eNB_itti_send_sctp_data_req(instance_p->instance, x2ap_eNB_data_p->assoc_id, buffer, len, 0);
return ret;
}
int x2ap_gNB_generate_ENDC_x2_SgNB_release_confirm(
x2ap_eNB_instance_t *instance_p, x2ap_eNB_data_t *x2ap_eNB_data_p,
int menb_ue_x2ap_id, int sgnb_ue_x2ap_id)
{
X2AP_X2AP_PDU_t pdu;
X2AP_SgNBReleaseConfirm_t *out;
X2AP_SgNBReleaseConfirm_IEs_t *ie;
uint8_t *buffer;
uint32_t len;
int ret = 0;
DevAssert(instance_p != NULL);
DevAssert(x2ap_eNB_data_p != NULL);
memset(&pdu, 0, sizeof(pdu));
pdu.present = X2AP_X2AP_PDU_PR_successfulOutcome;
pdu.choice.successfulOutcome.procedureCode = X2AP_ProcedureCode_id_sgNBinitiatedSgNBRelease;
pdu.choice.successfulOutcome.criticality = X2AP_Criticality_reject;
pdu.choice.successfulOutcome.value.present = X2AP_SuccessfulOutcome__value_PR_SgNBReleaseConfirm;
out = &pdu.choice.successfulOutcome.value.choice.SgNBReleaseConfirm;
ie = (X2AP_SgNBReleaseConfirm_IEs_t *)calloc(1, sizeof(X2AP_SgNBReleaseConfirm_IEs_t));
ie->id = X2AP_ProtocolIE_ID_id_MeNB_UE_X2AP_ID;
ie->criticality= X2AP_Criticality_ignore;
ie->value.present = X2AP_SgNBReleaseConfirm_IEs__value_PR_UE_X2AP_ID;
ie->value.choice.UE_X2AP_ID = menb_ue_x2ap_id;
ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
ie = (X2AP_SgNBReleaseConfirm_IEs_t *)calloc(1, sizeof(X2AP_SgNBReleaseConfirm_IEs_t));
ie->id = X2AP_ProtocolIE_ID_id_SgNB_UE_X2AP_ID;
ie->criticality= X2AP_Criticality_ignore;
ie->value.present = X2AP_SgNBReleaseConfirm_IEs__value_PR_SgNB_UE_X2AP_ID;
ie->value.choice.SgNB_UE_X2AP_ID = sgnb_ue_x2ap_id;
ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
if (x2ap_eNB_encode_pdu(&pdu, &buffer, &len) < 0) {
X2AP_ERROR("Failed to encode ENDC X2 SgNB Release Request Acknowledge\n");
return -1;
}
x2ap_eNB_itti_send_sctp_data_req(instance_p->instance, x2ap_eNB_data_p->assoc_id, buffer, len, 0);
return ret;
}
@@ -77,4 +77,16 @@ int x2ap_gNB_generate_ENDC_x2_SgNB_addition_request_ACK( x2ap_eNB_instance_t *in
int x2ap_eNB_generate_ENDC_x2_SgNB_reconfiguration_complete(
x2ap_eNB_instance_t *instance_p, x2ap_eNB_data_t *x2ap_eNB_data_p, int ue_id, int SgNB_ue_id);
int x2ap_eNB_generate_ENDC_x2_SgNB_release_request(x2ap_eNB_instance_t *instance_p, x2ap_eNB_data_t *x2ap_eNB_data_p,
int x2_id_source, int x2_id_target, x2ap_cause_t cause);
int x2ap_gNB_generate_ENDC_x2_SgNB_release_request_acknowledge(x2ap_eNB_instance_t *instance_p, x2ap_eNB_data_t *x2ap_eNB_data_p,
int menb_ue_x2ap_id, int sgnb_ue_x2ap_id);
int x2ap_eNB_generate_ENDC_x2_SgNB_release_required(x2ap_eNB_instance_t *instance_p, x2ap_eNB_data_t *x2ap_eNB_data_p,
int x2_id_source, int x2_id_target, x2ap_cause_t cause);
int x2ap_gNB_generate_ENDC_x2_SgNB_release_confirm(x2ap_eNB_instance_t *instance_p, x2ap_eNB_data_t *x2ap_eNB_data_p,
int menb_ue_x2ap_id, int sgnb_ue_x2ap_id);
#endif /* X2AP_ENB_GENERATE_MESSAGES_H_ */
+293 -55
View File
@@ -132,6 +132,29 @@ int x2ap_gNB_handle_ENDC_sGNB_reconfiguration_complete (instance_t instance,
uint32_t stream,
X2AP_X2AP_PDU_t *pdu);
static
int x2ap_gNB_handle_ENDC_sGNB_release_request(instance_t instance,
uint32_t assoc_id,
uint32_t stream,
X2AP_X2AP_PDU_t *pdu);
static
int x2ap_gNB_handle_ENDC_sGNB_release_request_acknowledge(instance_t instance,
uint32_t assoc_id,
uint32_t stream,
X2AP_X2AP_PDU_t *pdu);
static
int x2ap_gNB_handle_ENDC_sGNB_release_required(instance_t instance,
uint32_t assoc_id,
uint32_t stream,
X2AP_X2AP_PDU_t *pdu);
static
int x2ap_gNB_handle_ENDC_sGNB_release_confirm(instance_t instance,
uint32_t assoc_id,
uint32_t stream,
X2AP_X2AP_PDU_t *pdu);
/* Handlers matrix. Only eNB related procedure present here. Placement of callback functions according to X2AP_ProcedureCode.h */
x2ap_message_decoded_callback x2ap_messages_callback[][3] = {
@@ -166,8 +189,9 @@ x2ap_message_decoded_callback x2ap_messages_callback[][3] = {
{ x2ap_gNB_handle_ENDC_sGNB_reconfiguration_complete, 0, 0 }, /*X2AP_ProcedureCode_id_sgNBReconfigurationCompletion*/
{ 0, 0, 0 },
{ 0, 0, 0 },
{ 0, 0, 0 },
{ 0, 0, 0 },
{ x2ap_gNB_handle_ENDC_sGNB_release_request, x2ap_gNB_handle_ENDC_sGNB_release_request_acknowledge, 0 }, /* meNBinitiatedSgNBRelease */
{ x2ap_gNB_handle_ENDC_sGNB_release_required, x2ap_gNB_handle_ENDC_sGNB_release_confirm, 0 }, /* sgNBinitiatedSgNBRelease */
{ 0, 0, 0 },
{ 0, 0, 0 },
{ 0, 0, 0 },
@@ -1641,8 +1665,6 @@ int x2ap_gNB_handle_ENDC_sGNB_addition_request (instance_t instance,
uint32_t stream,
X2AP_X2AP_PDU_t *pdu)
{
X2AP_SgNBAdditionRequest_t *x2SgNBAdditionRequest;
X2AP_SgNBAdditionRequest_IEs_t *ie;
@@ -1823,6 +1845,8 @@ int x2ap_eNB_handle_ENDC_sGNB_addition_response (instance_t instance,
//Allocate an ITTI X2AP_SGNB_ADDITION_REQ message instead
msg = itti_alloc_new_message(TASK_X2AP, X2AP_ENDC_SGNB_ADDITION_REQ_ACK);
X2AP_ENDC_SGNB_ADDITION_REQ_ACK(msg).gnb_x2_assoc_id = assoc_id;
/* X2AP_ProtocolIE_ID_id_MeNB_UE_X2AP_ID */
X2AP_FIND_PROTOCOLIE_BY_ID(X2AP_SgNBAdditionRequestAcknowledge_IEs_t, ie, x2SgNBAdditionRequest_ack,
X2AP_ProtocolIE_ID_id_MeNB_UE_X2AP_ID, true);
@@ -1923,6 +1947,9 @@ int x2ap_eNB_handle_ENDC_sGNB_addition_response (instance_t instance,
itti_send_msg_to_task(TASK_RRC_ENB, instance_p->instance, msg);
/* remove UE from x2, DC preparation is over */
x2ap_release_id(&instance_p->id_manager, ue_id);
return 0;
}
@@ -1930,78 +1957,289 @@ static
int x2ap_gNB_handle_ENDC_sGNB_reconfiguration_complete (instance_t instance,
uint32_t assoc_id,
uint32_t stream,
X2AP_X2AP_PDU_t *pdu) {
X2AP_X2AP_PDU_t *pdu)
{
X2AP_SgNBReconfigurationComplete_t *x2SgNBReconfigurationComplete;
X2AP_SgNBReconfigurationComplete_IEs_t *ie;
X2AP_SgNBReconfigurationComplete_t *x2SgNBReconfigurationComplete;
X2AP_SgNBReconfigurationComplete_IEs_t *ie;
x2ap_eNB_instance_t *instance_p;
x2ap_eNB_data_t *x2ap_eNB_data;
MessageDef *msg;
x2ap_eNB_instance_t *instance_p;
x2ap_eNB_data_t *x2ap_eNB_data;
MessageDef *msg;
int id_target;
int ue_id;
DevAssert (pdu != NULL);
x2SgNBReconfigurationComplete = &pdu->choice.initiatingMessage.value.choice.SgNBReconfigurationComplete;
DevAssert (pdu != NULL);
x2SgNBReconfigurationComplete = &pdu->choice.initiatingMessage.value.choice.SgNBReconfigurationComplete;
/*if (stream == 0) {
X2AP_ERROR ("Received new x2 SgNB Addition request on stream == 0\n");
// TODO: send a x2 failure response
return 0;
}*/
/*if (stream == 0) {
X2AP_ERROR ("Received new x2 SgNB Addition request on stream == 0\n");
// TODO: send a x2 failure response
return 0;
}*/
X2AP_DEBUG ("Received X2 SgNB Reconfiguration complete message\n");
X2AP_DEBUG ("Received X2 SgNB Reconfiguration complete message\n");
x2ap_eNB_data = x2ap_get_eNB(NULL, assoc_id, 0);
DevAssert(x2ap_eNB_data != NULL);
x2ap_eNB_data = x2ap_get_eNB(NULL, assoc_id, 0);
DevAssert(x2ap_eNB_data != NULL);
X2AP_INFO("X2AP Association id: %d \n",assoc_id);
X2AP_INFO("X2AP Association id: %d \n",assoc_id);
instance_p = x2ap_eNB_get_instance(instance);
DevAssert(instance_p != NULL);
instance_p = x2ap_eNB_get_instance(instance);
DevAssert(instance_p != NULL);
//Allocate an ITTI X2AP_sGNB_reconfiguration_complete message
msg = itti_alloc_new_message(TASK_X2AP, X2AP_ENDC_SGNB_RECONF_COMPLETE);
//Allocate an ITTI X2AP_sGNB_reconfiguration_complete message
msg = itti_alloc_new_message(TASK_X2AP, X2AP_ENDC_SGNB_RECONF_COMPLETE);
/* X2AP_ProtocolIE_ID_id_MeNB_UE_X2AP_ID */
X2AP_FIND_PROTOCOLIE_BY_ID(X2AP_SgNBReconfigurationComplete_IEs_t, ie, x2SgNBReconfigurationComplete,
X2AP_ProtocolIE_ID_id_MeNB_UE_X2AP_ID, true);
if (ie == NULL ) {
X2AP_ERROR("%s %d: ie is a NULL pointer \n",__FILE__,__LINE__);
return -1;
}
/* X2AP_ProtocolIE_ID_id_MeNB_UE_X2AP_ID */
X2AP_FIND_PROTOCOLIE_BY_ID(X2AP_SgNBReconfigurationComplete_IEs_t, ie, x2SgNBReconfigurationComplete,
X2AP_ProtocolIE_ID_id_MeNB_UE_X2AP_ID, true);
if (ie == NULL ) {
X2AP_ERROR("%s %d: ie is a NULL pointer \n",__FILE__,__LINE__);
return -1;
}
X2AP_ENDC_SGNB_RECONF_COMPLETE(msg).MeNB_ue_x2_id = ie->value.choice.UE_X2AP_ID;
X2AP_ENDC_SGNB_RECONF_COMPLETE(msg).MeNB_ue_x2_id = ie->value.choice.UE_X2AP_ID;
/* X2AP_ProtocolIE_ID_id_SgNB_UE_X2AP_ID */
X2AP_FIND_PROTOCOLIE_BY_ID(X2AP_SgNBReconfigurationComplete_IEs_t, ie, x2SgNBReconfigurationComplete,
X2AP_ProtocolIE_ID_id_SgNB_UE_X2AP_ID, true);
if (ie == NULL ) {
X2AP_ERROR("%s %d: ie is a NULL pointer \n",__FILE__,__LINE__);
return -1;
}
/* X2AP_ProtocolIE_ID_id_SgNB_UE_X2AP_ID */
X2AP_FIND_PROTOCOLIE_BY_ID(X2AP_SgNBReconfigurationComplete_IEs_t, ie, x2SgNBReconfigurationComplete,
X2AP_ProtocolIE_ID_id_SgNB_UE_X2AP_ID, true);
if (ie == NULL ) {
X2AP_ERROR("%s %d: ie is a NULL pointer \n",__FILE__,__LINE__);
return -1;
}
X2AP_ENDC_SGNB_RECONF_COMPLETE(msg).SgNB_ue_x2_id = ie->value.choice.SgNB_UE_X2AP_ID;
id_target = ie->value.choice.SgNB_UE_X2AP_ID;
X2AP_ENDC_SGNB_RECONF_COMPLETE(msg).SgNB_ue_x2_id = id_target;
ue_id = x2ap_find_id_from_id_target(&instance_p->id_manager, id_target);
if (ue_id == -1) {
X2AP_WARN("incorrect/unknown X2AP IDs for UE (SgNB_UE_X2AP_ID %d), ignoring sGNB reconfiguration complete\n",
id_target);
itti_free(ITTI_MSG_ORIGIN_ID(msg), msg);
return 0;
}
X2AP_FIND_PROTOCOLIE_BY_ID(X2AP_SgNBReconfigurationComplete_IEs_t, ie, x2SgNBReconfigurationComplete,
X2AP_ProtocolIE_ID_id_ResponseInformationSgNBReconfComp, true);
if (ie == NULL ) {
X2AP_ERROR("%s %d: ie is a NULL pointer \n",__FILE__,__LINE__);
return -1;
}
X2AP_FIND_PROTOCOLIE_BY_ID(X2AP_SgNBReconfigurationComplete_IEs_t, ie, x2SgNBReconfigurationComplete,
X2AP_ProtocolIE_ID_id_ResponseInformationSgNBReconfComp, true);
if (ie == NULL ) {
X2AP_ERROR("%s %d: ie is a NULL pointer \n",__FILE__,__LINE__);
return -1;
}
if(ie->value.choice.ResponseInformationSgNBReconfComp.present == X2AP_ResponseInformationSgNBReconfComp_PR_success_SgNBReconfComp){
X2AP_ENDC_SGNB_RECONF_COMPLETE(msg).reconf_response = X2AP_RECONF_RESPONSE_SUCCESS;
}
else {
X2AP_ENDC_SGNB_RECONF_COMPLETE(msg).reconf_response = X2AP_RECONF_RESPONSE_REJECT;
}
if (ie->value.choice.ResponseInformationSgNBReconfComp.present != X2AP_ResponseInformationSgNBReconfComp_PR_success_SgNBReconfComp){
X2AP_ERROR("%s %d: fatal: unsuccessfulSgNB Reconfiguration Complete\n",__FILE__,__LINE__);
exit(1);
}
itti_send_msg_to_task(TASK_RRC_GNB, instance_p->instance, msg);
x2ap_release_id(&instance_p->id_manager, ue_id);
itti_send_msg_to_task(TASK_RRC_GNB, instance_p->instance, msg);
return 0;
return 0;
}
static
int x2ap_gNB_handle_ENDC_sGNB_release_request(instance_t instance,
uint32_t assoc_id,
uint32_t stream,
X2AP_X2AP_PDU_t *pdu)
{
/* the logic in this function is the following: when receiving a release
* request, the UE may exist in X2. Or not. If it's not in X2, it can
* nevertheless be in RRC.
* The release request message may contain the gNB id. Or not. It's better
* to look for the UE using the gNB rather than the eNB id. So if we have
* the gNB id we use it. If not, we use the eNB id.
*/
X2AP_SgNBReleaseRequest_t *req;
X2AP_SgNBReleaseRequest_IEs_t *ie;
x2ap_eNB_instance_t *instance_p;
x2ap_eNB_data_t *x2ap_eNB_data;
MessageDef *msg;
int id_source;
int id_target;
int rnti;
int ue_id;
DevAssert (pdu != NULL);
req = &pdu->choice.initiatingMessage.value.choice.SgNBReleaseRequest;
/*if (stream == 0) {
X2AP_ERROR ("Received new x2 SgNB Addition request on stream == 0\n");
// TODO: send a x2 failure response
return 0;
}*/
X2AP_DEBUG ("Received X2 SgNB Release Request message\n");
x2ap_eNB_data = x2ap_get_eNB(NULL, assoc_id, 0);
DevAssert(x2ap_eNB_data != NULL);
X2AP_INFO("X2AP Association id: %d \n",assoc_id);
instance_p = x2ap_eNB_get_instance(instance);
DevAssert(instance_p != NULL);
/* X2AP_ProtocolIE_ID_id_MeNB_UE_X2AP_ID */
X2AP_FIND_PROTOCOLIE_BY_ID(X2AP_SgNBReleaseRequest_IEs_t, ie, req,
X2AP_ProtocolIE_ID_id_MeNB_UE_X2AP_ID, true);
if (ie == NULL ) {
X2AP_ERROR("%s %d: ie is a NULL pointer \n",__FILE__,__LINE__);
return -1;
}
id_source = ie->value.choice.UE_X2AP_ID;
/* X2AP_ProtocolIE_ID_id_SgNB_UE_X2AP_ID */
X2AP_FIND_PROTOCOLIE_BY_ID(X2AP_SgNBReleaseRequest_IEs_t, ie, req,
X2AP_ProtocolIE_ID_id_SgNB_UE_X2AP_ID, false);
if (ie != NULL)
id_target = ie->value.choice.SgNB_UE_X2AP_ID;
else
id_target = -1;
/* find ue_id, preferably from id_target if id_target is known */
ue_id = -1;
if (id_target != -1)
ue_id = x2ap_find_id_from_id_target(&instance_p->id_manager, id_target);
if (ue_id == -1)
ue_id = x2ap_find_id_from_id_source(&instance_p->id_manager, id_source);
if (ue_id == -1) {
X2AP_WARN("%s %d: no UE found for id_source %d id_target %d\n",
__FILE__, __LINE__, id_source, id_target);
}
/* the UE may not exist in X2 anymore but exist in RRC
* in which case its rnti is simply the id_target
*/
if (ue_id != -1) {
rnti = x2ap_id_get_rnti(&instance_p->id_manager, ue_id);
/* remove ue_id */
x2ap_release_id(&instance_p->id_manager, ue_id);
} else {
rnti = id_target;
}
if (rnti != -1) {
msg = itti_alloc_new_message(TASK_X2AP, X2AP_ENDC_SGNB_RELEASE_REQUEST);
X2AP_ENDC_SGNB_RELEASE_REQUEST(msg).rnti = rnti;
itti_send_msg_to_task(TASK_RRC_GNB, instance_p->instance, msg);
}
/* this call should maybe not be here, we should check that the
* SgNB Release Request message has been executed properly
*/
x2ap_gNB_generate_ENDC_x2_SgNB_release_request_acknowledge(instance_p, x2ap_eNB_data,
id_source,
rnti != -1 ? rnti : 0);
return 0;
}
static
int x2ap_gNB_handle_ENDC_sGNB_release_request_acknowledge(instance_t instance,
uint32_t assoc_id,
uint32_t stream,
X2AP_X2AP_PDU_t *pdu)
{
/* nothing to do - may change at some point */
X2AP_INFO("received release request acknowledge\n");
return 0;
}
static
int x2ap_gNB_handle_ENDC_sGNB_release_required(instance_t instance,
uint32_t assoc_id,
uint32_t stream,
X2AP_X2AP_PDU_t *pdu)
{
/* the logic in this function is the following: when receiving a release
* required we don't care about the UE in X2. We simply send a message
* to RRC with the SgNB id (which is SgNB's RNTI). RRC will look for the
* UE using this RNTI and deal with it. In the meanwhile the X2 layer
* immediately replies with "release confirm" no matter what happens
* in RRC.
*/
X2AP_SgNBReleaseRequired_t *req;
X2AP_SgNBReleaseRequired_IEs_t *ie;
x2ap_eNB_instance_t *instance_p;
x2ap_eNB_data_t *x2ap_eNB_data;
MessageDef *msg;
int id_source;
int id_target;
int gnb_rnti;
DevAssert (pdu != NULL);
req = &pdu->choice.initiatingMessage.value.choice.SgNBReleaseRequired;
/*if (stream == 0) {
X2AP_ERROR ("Received new x2 SgNB Addition request on stream == 0\n");
// TODO: send a x2 failure response
return 0;
}*/
X2AP_DEBUG ("Received X2 SgNB Release Required message\n");
x2ap_eNB_data = x2ap_get_eNB(NULL, assoc_id, 0);
DevAssert(x2ap_eNB_data != NULL);
X2AP_INFO("X2AP Association id: %d \n",assoc_id);
instance_p = x2ap_eNB_get_instance(instance);
DevAssert(instance_p != NULL);
/* X2AP_ProtocolIE_ID_id_MeNB_UE_X2AP_ID */
X2AP_FIND_PROTOCOLIE_BY_ID(X2AP_SgNBReleaseRequired_IEs_t, ie, req,
X2AP_ProtocolIE_ID_id_MeNB_UE_X2AP_ID, true);
if (ie == NULL ) {
X2AP_ERROR("%s %d: ie is a NULL pointer \n",__FILE__,__LINE__);
return -1;
}
id_source = ie->value.choice.UE_X2AP_ID;
/* X2AP_ProtocolIE_ID_id_SgNB_UE_X2AP_ID */
X2AP_FIND_PROTOCOLIE_BY_ID(X2AP_SgNBReleaseRequired_IEs_t, ie, req,
X2AP_ProtocolIE_ID_id_SgNB_UE_X2AP_ID, true);
if (ie == NULL ) {
X2AP_ERROR("%s %d: ie is a NULL pointer \n",__FILE__,__LINE__);
return -1;
}
id_target = ie->value.choice.SgNB_UE_X2AP_ID;
gnb_rnti = id_target;
msg = itti_alloc_new_message(TASK_X2AP, X2AP_ENDC_SGNB_RELEASE_REQUIRED);
X2AP_ENDC_SGNB_RELEASE_REQUIRED(msg).gnb_rnti = gnb_rnti;
itti_send_msg_to_task(TASK_RRC_ENB, instance_p->instance, msg);
/* this call should maybe not be here, we should check that the
* SgNB Release Required message has been executed properly
*/
x2ap_gNB_generate_ENDC_x2_SgNB_release_confirm(instance_p, x2ap_eNB_data,
id_source, id_target);
return 0;
}
static
int x2ap_gNB_handle_ENDC_sGNB_release_confirm(instance_t instance,
uint32_t assoc_id,
uint32_t stream,
X2AP_X2AP_PDU_t *pdu)
{
/* nothing to do - may change at some point */
X2AP_INFO("received release confirm\n");
return 0;
}
+20
View File
@@ -70,6 +70,16 @@ int x2ap_find_id_from_id_source(x2ap_id_manager *m, int id_source)
return -1;
}
int x2ap_find_id_from_id_target(x2ap_id_manager *m, int id_target)
{
int i;
for (i = 0; i < X2AP_MAX_IDS; i++)
if (m->ids[i].rnti != -1 &&
m->ids[i].id_target == id_target)
return i;
return -1;
}
int x2ap_find_id_from_rnti(x2ap_id_manager *m, int rnti)
{
int i;
@@ -107,6 +117,16 @@ void x2ap_set_reloc_overall_timer(x2ap_id_manager *m, int ue_id, uint64_t time)
m->ids[ue_id].tx2_reloc_overall_start = time;
}
void x2ap_set_dc_prep_timer(x2ap_id_manager *m, int ue_id, uint64_t time)
{
m->ids[ue_id].t_dc_prep_start = time;
}
void x2ap_set_dc_overall_timer(x2ap_id_manager *m, int ue_id, uint64_t time)
{
m->ids[ue_id].t_dc_overall_start = time;
}
int x2ap_id_get_id_source(x2ap_id_manager *m, int ue_id)
{
return m->ids[ue_id].id_source;
+7 -1
View File
@@ -38,7 +38,8 @@ typedef enum {
X2ID_STATE_SOURCE_PREPARE,
X2ID_STATE_SOURCE_OVERALL,
X2ID_STATE_TARGET,
X2ID_STATE_NSA_PREPARE,
X2ID_STATE_NSA_ENB_PREPARE,
X2ID_STATE_NSA_GNB_OVERALL,
} x2id_state_t;
typedef struct {
@@ -55,6 +56,8 @@ typedef struct {
/* timers */
uint64_t t_reloc_prep_start;
uint64_t tx2_reloc_overall_start;
uint64_t t_dc_prep_start;
uint64_t t_dc_overall_start;
} x2ap_id;
typedef struct {
@@ -66,6 +69,7 @@ int x2ap_allocate_new_id(x2ap_id_manager *m);
void x2ap_release_id(x2ap_id_manager *m, int id);
int x2ap_find_id(x2ap_id_manager *, int id_source, int id_target);
int x2ap_find_id_from_id_source(x2ap_id_manager *, int id_source);
int x2ap_find_id_from_id_target(x2ap_id_manager *, int id_source);
int x2ap_find_id_from_rnti(x2ap_id_manager *, int rnti);
void x2ap_set_ids(x2ap_id_manager *m, int ue_id, int rnti, int id_source, int id_target);
void x2ap_id_set_state(x2ap_id_manager *m, int ue_id, x2id_state_t state);
@@ -73,6 +77,8 @@ void x2ap_id_set_state(x2ap_id_manager *m, int ue_id, x2id_state_t state);
void x2ap_id_set_target(x2ap_id_manager *m, int ue_id, void *target);
void x2ap_set_reloc_prep_timer(x2ap_id_manager *m, int ue_id, uint64_t time);
void x2ap_set_reloc_overall_timer(x2ap_id_manager *m, int ue_id, uint64_t time);
void x2ap_set_dc_prep_timer(x2ap_id_manager *m, int ue_id, uint64_t time);
void x2ap_set_dc_overall_timer(x2ap_id_manager *m, int ue_id, uint64_t time);
int x2ap_id_get_id_source(x2ap_id_manager *m, int ue_id);
int x2ap_id_get_id_target(x2ap_id_manager *m, int ue_id);
int x2ap_id_get_rnti(x2ap_id_manager *m, int ue_id);
+63 -5
View File
@@ -28,11 +28,17 @@
#include "x2ap_eNB_management_procedures.h"
#include "x2ap_eNB_generate_messages.h"
void x2ap_timers_init(x2ap_timers_t *t, int t_reloc_prep, int tx2_reloc_overall)
void x2ap_timers_init(x2ap_timers_t *t,
int t_reloc_prep,
int tx2_reloc_overall,
int t_dc_prep,
int t_dc_overall)
{
t->tti = 0;
t->t_reloc_prep = t_reloc_prep;
t->tx2_reloc_overall = tx2_reloc_overall;
t->t_dc_prep = t_dc_prep;
t->t_dc_overall = t_dc_overall;
}
void x2ap_check_timers(instance_t instance)
@@ -59,14 +65,17 @@ void x2ap_check_timers(instance_t instance)
for (i = 0; i < X2AP_MAX_IDS; i++) {
if (m->ids[i].rnti == -1) continue;
x2_ongoing++;
if (m->ids[i].state == X2ID_STATE_SOURCE_PREPARE ||
m->ids[i].state == X2ID_STATE_SOURCE_OVERALL)
x2_ongoing++;
if (m->ids[i].state == X2ID_STATE_SOURCE_PREPARE &&
t->tti > m->ids[i].t_reloc_prep_start + t->t_reloc_prep) {
LOG_I(X2AP, "X2 timeout reloc prep\n");
/* t_reloc_prep timed out */
cause = X2AP_T_RELOC_PREP_TIMEOUT;
goto timeout;
goto lte_handover_timeout;
}
if (m->ids[i].state == X2ID_STATE_SOURCE_OVERALL &&
@@ -74,13 +83,62 @@ void x2ap_check_timers(instance_t instance)
LOG_I(X2AP, "X2 timeout reloc overall\n");
/* tx2_reloc_overall timed out */
cause = X2AP_TX2_RELOC_OVERALL_TIMEOUT;
goto timeout;
goto lte_handover_timeout;
}
if (m->ids[i].state == X2ID_STATE_NSA_ENB_PREPARE &&
t->tti > m->ids[i].t_dc_prep_start + t->t_dc_prep) {
int id_source;
int id_target;
LOG_I(X2AP, "X2 timeout DC prep\n");
/* t_dc_prep timed out */
target = x2ap_id_get_target(m, i);
id_source = x2ap_id_get_id_source(m, i);
id_target = x2ap_id_get_id_target(m, i);
x2ap_eNB_generate_ENDC_x2_SgNB_release_request(instance_p, target,
id_source, id_target,
X2AP_CAUSE_T_DC_PREP_TIMEOUT);
/* inform RRC of timeout */
msg = itti_alloc_new_message(TASK_X2AP, X2AP_ENDC_DC_PREP_TIMEOUT);
X2AP_ENDC_DC_PREP_TIMEOUT(msg).rnti = x2ap_id_get_rnti(m, i);
itti_send_msg_to_task(TASK_RRC_ENB, instance_p->instance, msg);
/* remove UE from X2AP */
x2ap_release_id(m, i);
continue;
}
if (m->ids[i].state == X2ID_STATE_NSA_GNB_OVERALL &&
t->tti > m->ids[i].t_dc_overall_start + t->t_dc_overall) {
int id_source;
int id_target;
LOG_I(X2AP, "X2 timeout DC overall\n");
/* t_dc_overall timed out */
target = x2ap_id_get_target(m, i);
id_source = x2ap_id_get_id_source(m, i);
id_target = x2ap_id_get_id_target(m, i);
x2ap_eNB_generate_ENDC_x2_SgNB_release_required(instance_p, target,
id_source, id_target, X2AP_CAUSE_T_DC_OVERALL_TIMEOUT);
/* inform RRC of timeout */
msg = itti_alloc_new_message(TASK_X2AP, X2AP_ENDC_DC_OVERALL_TIMEOUT);
X2AP_ENDC_DC_OVERALL_TIMEOUT(msg).rnti = x2ap_id_get_rnti(m, i);
itti_send_msg_to_task(TASK_RRC_GNB, instance_p->instance, msg);
/* remove UE from X2AP */
x2ap_release_id(m, i);
continue;
}
/* no timeout -> check next UE */
continue;
timeout:
lte_handover_timeout:
/* inform target about timeout */
target = x2ap_id_get_target(m, i);
x2ap_eNB_generate_x2_handover_cancel(instance_p, target, i, cause);
+7 -1
View File
@@ -36,9 +36,15 @@ typedef struct {
/* timer values (unit: TTI, ie. millisecond when in realtime) */
int t_reloc_prep;
int tx2_reloc_overall;
int t_dc_prep;
int t_dc_overall;
} x2ap_timers_t;
void x2ap_timers_init(x2ap_timers_t *t, int t_reloc_prep, int tx2_reloc_overall);
void x2ap_timers_init(x2ap_timers_t *t,
int t_reloc_prep,
int tx2_reloc_overall,
int t_dc_prep,
int t_dc_overall);
void x2ap_check_timers(instance_t instance);
uint64_t x2ap_timer_get_tti(x2ap_timers_t *t);