X2AP MOBILITY PROCEDURES (X2AP HANDOVER REQUEST/REQUEST ACK)
S1AP PATH SWITCH REQUEST/REQUEST ACK/FAILURE RRC MEASUREMENT REPORT MINOR CHANGES IN MAC LAYER
This commit is contained in:
@@ -19,6 +19,13 @@
|
||||
* contact@openairinterface.org
|
||||
*/
|
||||
|
||||
/*! \file x2ap_eNB.c
|
||||
* \brief x2ap tasks for eNB
|
||||
* \author Konstantinos Alexandris <Konstantinos.Alexandris@eurecom.fr>, Cedric Roux <Cedric.Roux@eurecom.fr>, Navid Nikaein <Navid.Nikaein@eurecom.fr>
|
||||
* \date 2018
|
||||
* \version 1.0
|
||||
*/
|
||||
|
||||
#include <pthread.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
@@ -64,6 +71,13 @@ void x2ap_eNB_register_eNB(x2ap_eNB_instance_t *instance_p,
|
||||
uint32_t enb_port_for_X2C,
|
||||
int multi_sd);
|
||||
|
||||
static
|
||||
void x2ap_eNB_handle_handover_req(instance_t instance,
|
||||
x2ap_handover_req_t *x2ap_handover_req);
|
||||
|
||||
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_sctp_data_ind(instance_t instance, sctp_data_ind_t *sctp_data_ind) {
|
||||
@@ -405,6 +419,62 @@ void x2ap_eNB_handle_sctp_init_msg_multi_cnf(
|
||||
}
|
||||
}
|
||||
|
||||
static
|
||||
void x2ap_eNB_handle_handover_req(instance_t instance,
|
||||
x2ap_handover_req_t *x2ap_handover_req)
|
||||
{
|
||||
/* TODO: remove this hack (the goal is to find the correct
|
||||
* eNodeB structure for the target) - we need a proper way for RRC
|
||||
* and X2AP to identify eNodeBs
|
||||
* RRC knows about mod_id and X2AP knows about eNB_id (eNB_ID in
|
||||
* the configuration file)
|
||||
* as far as I understand.. CROUX
|
||||
*/
|
||||
x2ap_eNB_instance_t *instance_p;
|
||||
x2ap_eNB_data_t *target;
|
||||
|
||||
int target_enb_id = x2ap_handover_req->target_physCellId;
|
||||
|
||||
instance_p = x2ap_eNB_pci_get_instance(target_enb_id);
|
||||
DevAssert(instance_p != NULL);
|
||||
|
||||
//instance_p = x2ap_eNB_get_instance(instance);
|
||||
//DevAssert(instance_p != NULL);
|
||||
|
||||
target = x2ap_is_eNB_id_in_list(instance_p->eNB_id);
|
||||
DevAssert(target != NULL);
|
||||
|
||||
/* store rnti at index 0 */
|
||||
//x2id_to_source_rnti[0] = x2ap_handover_req->source_rnti;
|
||||
x2ap_eNB_generate_x2_handover_request(target, x2ap_handover_req);
|
||||
}
|
||||
|
||||
static
|
||||
void x2ap_eNB_handle_handover_req_ack(instance_t instance,
|
||||
x2ap_handover_req_ack_t *x2ap_handover_req_ack)
|
||||
{
|
||||
/* TODO: remove this hack (the goal is to find the correct
|
||||
* eNodeB structure for the other end) - we need a proper way for RRC
|
||||
* and X2AP to identify eNodeBs
|
||||
* RRC knows about mod_id and X2AP knows about eNB_id (eNB_ID in
|
||||
* the configuration file)
|
||||
* as far as I understand.. CROUX
|
||||
*/
|
||||
x2ap_eNB_instance_t *instance_p;
|
||||
x2ap_eNB_data_t *target;
|
||||
int target_enb_id = x2ap_handover_req_ack->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_handover_request_ack(target, x2ap_handover_req_ack);
|
||||
//x2ap_eNB_generate_x2_handover_req_ack(instance_p, target, x2ap_handover_req_ack->source_x2id,
|
||||
//x2ap_handover_req_ack->rrc_buffer, x2ap_handover_req_ack->rrc_buffer_size);
|
||||
}
|
||||
|
||||
void *x2ap_task(void *arg)
|
||||
{
|
||||
MessageDef *received_msg = NULL;
|
||||
@@ -429,6 +499,16 @@ void *x2ap_task(void *arg)
|
||||
&X2AP_REGISTER_ENB_REQ(received_msg));
|
||||
break;
|
||||
|
||||
case X2AP_HANDOVER_REQ:
|
||||
x2ap_eNB_handle_handover_req(ITTI_MESSAGE_GET_INSTANCE(received_msg),
|
||||
&X2AP_HANDOVER_REQ(received_msg));
|
||||
break;
|
||||
|
||||
case X2AP_HANDOVER_REQ_ACK:
|
||||
x2ap_eNB_handle_handover_req_ack(ITTI_MESSAGE_GET_INSTANCE(received_msg),
|
||||
&X2AP_HANDOVER_REQ_ACK(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);
|
||||
|
||||
@@ -19,6 +19,13 @@
|
||||
* contact@openairinterface.org
|
||||
*/
|
||||
|
||||
/*! \file x2ap_eNB.h
|
||||
* \brief x2ap tasks for eNB
|
||||
* \author Konstantinos Alexandris <Konstantinos.Alexandris@eurecom.fr>, Cedric Roux <Cedric.Roux@eurecom.fr>, Navid Nikaein <Navid.Nikaein@eurecom.fr>
|
||||
* \date 2018
|
||||
* \version 1.0
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
|
||||
|
||||
@@ -19,6 +19,13 @@
|
||||
* contact@openairinterface.org
|
||||
*/
|
||||
|
||||
/*! \file x2ap_eNB_decoder.c
|
||||
* \brief x2ap decoder procedures for eNB
|
||||
* \author Konstantinos Alexandris <Konstantinos.Alexandris@eurecom.fr>, Cedric Roux <Cedric.Roux@eurecom.fr>, Navid Nikaein <Navid.Nikaein@eurecom.fr>
|
||||
* \date 2018
|
||||
* \version 1.0
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "assertions.h"
|
||||
@@ -33,7 +40,12 @@ static int x2ap_eNB_decode_initiating_message(X2AP_X2AP_PDU_t *pdu)
|
||||
switch(pdu->choice.initiatingMessage.procedureCode) {
|
||||
|
||||
case X2AP_ProcedureCode_id_x2Setup:
|
||||
asn_encode_to_new_buffer(NULL, ATS_CANONICAL_XER, &asn_DEF_X2AP_X2AP_PDU, 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_handoverPreparation:
|
||||
//asn_encode_to_new_buffer(NULL, ATS_CANONICAL_XER, &asn_DEF_X2AP_X2AP_PDU, pdu);
|
||||
X2AP_INFO("x2ap_eNB_decode_initiating_message!\n");
|
||||
break;
|
||||
|
||||
@@ -54,7 +66,12 @@ static int x2ap_eNB_decode_successful_outcome(X2AP_X2AP_PDU_t *pdu)
|
||||
|
||||
switch(pdu->choice.successfulOutcome.procedureCode) {
|
||||
case X2AP_ProcedureCode_id_x2Setup:
|
||||
asn_encode_to_new_buffer(NULL, ATS_CANONICAL_XER, &asn_DEF_X2AP_X2AP_PDU, pdu);
|
||||
//asn_encode_to_new_buffer(NULL, ATS_CANONICAL_XER, &asn_DEF_X2AP_X2AP_PDU, pdu);
|
||||
X2AP_INFO("x2ap_eNB_decode_successfuloutcome_message!\n");
|
||||
break;
|
||||
|
||||
case X2AP_ProcedureCode_id_handoverPreparation:
|
||||
//asn_encode_to_new_buffer(NULL, ATS_CANONICAL_XER, &asn_DEF_X2AP_X2AP_PDU, pdu);
|
||||
X2AP_INFO("x2ap_eNB_decode_successfuloutcome_message!\n");
|
||||
break;
|
||||
|
||||
@@ -73,7 +90,7 @@ static int x2ap_eNB_decode_unsuccessful_outcome(X2AP_X2AP_PDU_t *pdu)
|
||||
|
||||
switch(pdu->choice.unsuccessfulOutcome.procedureCode) {
|
||||
case X2AP_ProcedureCode_id_x2Setup:
|
||||
asn_encode_to_new_buffer(NULL, ATS_CANONICAL_XER, &asn_DEF_X2AP_X2AP_PDU, pdu);
|
||||
//asn_encode_to_new_buffer(NULL, ATS_CANONICAL_XER, &asn_DEF_X2AP_X2AP_PDU, pdu);
|
||||
X2AP_INFO("x2ap_eNB_decode_unsuccessfuloutcome_message!\n");
|
||||
break;
|
||||
|
||||
@@ -99,8 +116,9 @@ int x2ap_eNB_decode_pdu(X2AP_X2AP_PDU_t *pdu, const uint8_t *const buffer, uint3
|
||||
length,
|
||||
0,
|
||||
0);
|
||||
|
||||
xer_fprint(stdout, &asn_DEF_X2AP_X2AP_PDU, pdu);
|
||||
if (asn1_xer_print) {
|
||||
xer_fprint(stdout, &asn_DEF_X2AP_X2AP_PDU, pdu);
|
||||
}
|
||||
|
||||
if (dec_ret.code != RC_OK) {
|
||||
X2AP_ERROR("Failed to decode pdu\n");
|
||||
|
||||
@@ -19,6 +19,13 @@
|
||||
* contact@openairinterface.org
|
||||
*/
|
||||
|
||||
/*! \file x2ap_eNB_decoder.h
|
||||
* \brief x2ap decoder procedures for eNB
|
||||
* \author Konstantinos Alexandris <Konstantinos.Alexandris@eurecom.fr>, Cedric Roux <Cedric.Roux@eurecom.fr>, Navid Nikaein <Navid.Nikaein@eurecom.fr>
|
||||
* \date 2018
|
||||
* \version 1.0
|
||||
*/
|
||||
|
||||
#ifndef X2AP_ENB_DECODER_H_
|
||||
#define X2AP_ENB_DECODER_H_
|
||||
|
||||
|
||||
@@ -19,6 +19,13 @@
|
||||
* contact@openairinterface.org
|
||||
*/
|
||||
|
||||
/*! \file x2ap_eNB_defs.h
|
||||
* \brief x2ap struct definitions for eNB
|
||||
* \author Konstantinos Alexandris <Konstantinos.Alexandris@eurecom.fr>, Cedric Roux <Cedric.Roux@eurecom.fr>, Navid Nikaein <Navid.Nikaein@eurecom.fr>
|
||||
* \date 2018
|
||||
* \version 1.0
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "queue.h"
|
||||
@@ -156,6 +163,7 @@ typedef struct x2ap_eNB_instance_s {
|
||||
uint32_t downlink_frequency[MAX_NUM_CCs];
|
||||
int32_t uplink_frequency_offset[MAX_NUM_CCs];
|
||||
uint32_t Nid_cell[MAX_NUM_CCs];
|
||||
uint32_t Nid_target_cell[MAX_NUM_CCs];
|
||||
int16_t N_RB_DL[MAX_NUM_CCs];
|
||||
lte_frame_type_t frame_type[MAX_NUM_CCs];
|
||||
uint32_t fdd_earfcn_DL[MAX_NUM_CCs];
|
||||
|
||||
@@ -19,6 +19,13 @@
|
||||
* contact@openairinterface.org
|
||||
*/
|
||||
|
||||
/*! \file x2ap_eNB_encoder.c
|
||||
* \brief x2ap encoder procedures for eNB
|
||||
* \author Konstantinos Alexandris <Konstantinos.Alexandris@eurecom.fr>, Cedric Roux <Cedric.Roux@eurecom.fr>, Navid Nikaein <Navid.Nikaein@eurecom.fr>
|
||||
* \date 2018
|
||||
* \version 1.0
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
|
||||
@@ -19,6 +19,13 @@
|
||||
* contact@openairinterface.org
|
||||
*/
|
||||
|
||||
/*! \file x2ap_eNB_encoder.h
|
||||
* \brief x2ap encoder procedures for eNB
|
||||
* \author Konstantinos Alexandris <Konstantinos.Alexandris@eurecom.fr>, Cedric Roux <Cedric.Roux@eurecom.fr>, Navid Nikaein <Navid.Nikaein@eurecom.fr>
|
||||
* \date 2018
|
||||
* \version 1.0
|
||||
*/
|
||||
|
||||
#ifndef X2AP_ENB_ENCODER_H_
|
||||
#define X2AP_ENB_ENCODER_H_
|
||||
|
||||
|
||||
@@ -19,12 +19,22 @@
|
||||
* contact@openairinterface.org
|
||||
*/
|
||||
|
||||
/*! \file x2ap_eNB_generate_messages.c
|
||||
* \brief x2ap procedures for eNB
|
||||
* \author Konstantinos Alexandris <Konstantinos.Alexandris@eurecom.fr>, Cedric Roux <Cedric.Roux@eurecom.fr>, Navid Nikaein <Navid.Nikaein@eurecom.fr>
|
||||
* \date 2018
|
||||
* \version 1.0
|
||||
*/
|
||||
|
||||
#include "intertask_interface.h"
|
||||
|
||||
#include "X2AP_LastVisitedCell-Item.h"
|
||||
|
||||
#include "x2ap_common.h"
|
||||
#include "x2ap_eNB.h"
|
||||
#include "x2ap_eNB_generate_messages.h"
|
||||
#include "x2ap_eNB_encoder.h"
|
||||
#include "x2ap_eNB_decoder.h"
|
||||
|
||||
#include "x2ap_eNB_itti_messaging.h"
|
||||
|
||||
@@ -403,3 +413,314 @@ int x2ap_eNB_set_cause (X2AP_Cause_t * cause_p,
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int x2ap_eNB_generate_x2_handover_request (x2ap_eNB_data_t *x2ap_eNB_data_p,
|
||||
x2ap_handover_req_t *x2ap_handover_req)
|
||||
{
|
||||
|
||||
X2AP_X2AP_PDU_t pdu;
|
||||
X2AP_HandoverRequest_t *out;
|
||||
X2AP_HandoverRequest_IEs_t *ie;
|
||||
X2AP_E_RABs_ToBeSetup_ItemIEs_t *e_RABS_ToBeSetup_ItemIEs;
|
||||
X2AP_E_RABs_ToBeSetup_Item_t *e_RABs_ToBeSetup_Item;
|
||||
X2AP_LastVisitedCell_Item_t *lastVisitedCell_Item;
|
||||
|
||||
x2ap_eNB_instance_t *instance_p;
|
||||
|
||||
uint8_t *buffer;
|
||||
uint32_t len;
|
||||
int ret = 0;
|
||||
|
||||
DevAssert(x2ap_eNB_data_p != NULL);
|
||||
|
||||
/* get the eNB instance */
|
||||
instance_p = x2ap_eNB_data_p->x2ap_eNB_instance;
|
||||
|
||||
DevAssert(instance_p != NULL);
|
||||
|
||||
|
||||
/* Prepare the X2AP handover message to encode */
|
||||
memset(&pdu, 0, sizeof(pdu));
|
||||
pdu.present = X2AP_X2AP_PDU_PR_initiatingMessage;
|
||||
pdu.choice.initiatingMessage.procedureCode = X2AP_ProcedureCode_id_handoverPreparation;
|
||||
pdu.choice.initiatingMessage.criticality = X2AP_Criticality_reject;
|
||||
pdu.choice.initiatingMessage.value.present = X2AP_InitiatingMessage__value_PR_HandoverRequest;
|
||||
out = &pdu.choice.initiatingMessage.value.choice.HandoverRequest;
|
||||
|
||||
/* mandatory */
|
||||
ie = (X2AP_HandoverRequest_IEs_t *)calloc(1, sizeof(X2AP_HandoverRequest_IEs_t));
|
||||
ie->id = X2AP_ProtocolIE_ID_id_Old_eNB_UE_X2AP_ID;
|
||||
ie->criticality = X2AP_Criticality_reject;
|
||||
ie->value.present = X2AP_HandoverRequest_IEs__value_PR_UE_X2AP_ID;
|
||||
ie->value.choice.UE_X2AP_ID = x2ap_handover_req->old_eNB_ue_x2ap_id;
|
||||
ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
|
||||
|
||||
/* mandatory */
|
||||
ie = (X2AP_HandoverRequest_IEs_t *)calloc(1, sizeof(X2AP_HandoverRequest_IEs_t));
|
||||
ie->id = X2AP_ProtocolIE_ID_id_Cause;
|
||||
ie->criticality = X2AP_Criticality_ignore;
|
||||
ie->value.present = X2AP_HandoverRequest_IEs__value_PR_Cause;
|
||||
ie->value.choice.Cause.present = X2AP_Cause_PR_radioNetwork;
|
||||
ie->value.choice.Cause.choice.radioNetwork = X2AP_CauseRadioNetwork_handover_desirable_for_radio_reasons;
|
||||
ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
|
||||
|
||||
/* mandatory */
|
||||
ie = (X2AP_HandoverRequest_IEs_t *)calloc(1, sizeof(X2AP_HandoverRequest_IEs_t));
|
||||
ie->id = X2AP_ProtocolIE_ID_id_TargetCell_ID;
|
||||
ie->criticality = X2AP_Criticality_reject;
|
||||
ie->value.present = X2AP_HandoverRequest_IEs__value_PR_ECGI;
|
||||
MCC_MNC_TO_PLMNID(instance_p->mcc, instance_p->mnc, instance_p->mnc_digit_length,
|
||||
&ie->value.choice.ECGI.pLMN_Identity);
|
||||
MACRO_ENB_ID_TO_CELL_IDENTITY(instance_p->eNB_id, 0, &ie->value.choice.ECGI.eUTRANcellIdentifier);
|
||||
ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
|
||||
|
||||
/* mandatory */
|
||||
ie = (X2AP_HandoverRequest_IEs_t *)calloc(1, sizeof(X2AP_HandoverRequest_IEs_t));
|
||||
ie->id = X2AP_ProtocolIE_ID_id_GUMMEI_ID;
|
||||
ie->criticality = X2AP_Criticality_reject;
|
||||
ie->value.present = X2AP_HandoverRequest_IEs__value_PR_GUMMEI;
|
||||
MCC_MNC_TO_PLMNID(instance_p->mcc, instance_p->mnc, instance_p->mnc_digit_length,
|
||||
&ie->value.choice.GUMMEI.gU_Group_ID.pLMN_Identity);
|
||||
//@TODO: consider to update these values
|
||||
INT16_TO_OCTET_STRING(x2ap_handover_req->ue_gummei.mme_group_id, &ie->value.choice.GUMMEI.gU_Group_ID.mME_Group_ID);
|
||||
MME_CODE_TO_OCTET_STRING(x2ap_handover_req->ue_gummei.mme_code, &ie->value.choice.GUMMEI.mME_Code);
|
||||
ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
|
||||
|
||||
/* mandatory */
|
||||
ie = (X2AP_HandoverRequest_IEs_t *)calloc(1, sizeof(X2AP_HandoverRequest_IEs_t));
|
||||
ie->id = X2AP_ProtocolIE_ID_id_UE_ContextInformation;
|
||||
ie->criticality = X2AP_Criticality_reject;
|
||||
ie->value.present = X2AP_HandoverRequest_IEs__value_PR_UE_ContextInformation;
|
||||
//@TODO: consider to update this value
|
||||
ie->value.choice.UE_ContextInformation.mME_UE_S1AP_ID = x2ap_handover_req->mme_ue_s1ap_id;
|
||||
|
||||
KENB_STAR_TO_BIT_STRING(x2ap_handover_req->kenb,&ie->value.choice.UE_ContextInformation.aS_SecurityInformation.key_eNodeB_star);
|
||||
|
||||
if (x2ap_handover_req->kenb_ncc >=0) { // Check this condition
|
||||
ie->value.choice.UE_ContextInformation.aS_SecurityInformation.nextHopChainingCount = x2ap_handover_req->kenb_ncc;
|
||||
}
|
||||
else {
|
||||
ie->value.choice.UE_ContextInformation.aS_SecurityInformation.nextHopChainingCount = 1;
|
||||
}
|
||||
|
||||
ENCRALG_TO_BIT_STRING(x2ap_handover_req->security_capabilities.encryption_algorithms,
|
||||
&ie->value.choice.UE_ContextInformation.uESecurityCapabilities.encryptionAlgorithms);
|
||||
|
||||
INTPROTALG_TO_BIT_STRING(x2ap_handover_req->security_capabilities.integrity_algorithms,
|
||||
&ie->value.choice.UE_ContextInformation.uESecurityCapabilities.integrityProtectionAlgorithms);
|
||||
|
||||
//@TODO: update with proper UEAMPR
|
||||
UEAGMAXBITRTD_TO_ASN_PRIMITIVES(3L,&ie->value.choice.UE_ContextInformation.uEaggregateMaximumBitRate.uEaggregateMaximumBitRateDownlink);
|
||||
UEAGMAXBITRTU_TO_ASN_PRIMITIVES(6L,&ie->value.choice.UE_ContextInformation.uEaggregateMaximumBitRate.uEaggregateMaximumBitRateUplink);
|
||||
{
|
||||
for (int i=0;i<x2ap_handover_req->nb_e_rabs_tobesetup;i++) {
|
||||
e_RABS_ToBeSetup_ItemIEs = (X2AP_E_RABs_ToBeSetup_ItemIEs_t *)calloc(1,sizeof(X2AP_E_RABs_ToBeSetup_ItemIEs_t));
|
||||
e_RABS_ToBeSetup_ItemIEs->id = X2AP_ProtocolIE_ID_id_E_RABs_ToBeSetup_Item;
|
||||
e_RABS_ToBeSetup_ItemIEs->criticality = X2AP_Criticality_ignore;
|
||||
e_RABS_ToBeSetup_ItemIEs->value.present = X2AP_E_RABs_ToBeSetup_ItemIEs__value_PR_E_RABs_ToBeSetup_Item;
|
||||
e_RABs_ToBeSetup_Item = &e_RABS_ToBeSetup_ItemIEs->value.choice.E_RABs_ToBeSetup_Item;
|
||||
{
|
||||
e_RABs_ToBeSetup_Item->e_RAB_ID = x2ap_handover_req->e_rabs_tobesetup[i].e_rab_id;
|
||||
e_RABs_ToBeSetup_Item->e_RAB_Level_QoS_Parameters.qCI = x2ap_handover_req->e_rab_param[i].qos.qci;
|
||||
e_RABs_ToBeSetup_Item->e_RAB_Level_QoS_Parameters.allocationAndRetentionPriority.priorityLevel = x2ap_handover_req->e_rab_param[i].qos.allocation_retention_priority.priority_level;
|
||||
e_RABs_ToBeSetup_Item->e_RAB_Level_QoS_Parameters.allocationAndRetentionPriority.pre_emptionCapability = x2ap_handover_req->e_rab_param[i].qos.allocation_retention_priority.pre_emp_capability;
|
||||
e_RABs_ToBeSetup_Item->e_RAB_Level_QoS_Parameters.allocationAndRetentionPriority.pre_emptionVulnerability = x2ap_handover_req->e_rab_param[i].qos.allocation_retention_priority.pre_emp_vulnerability;
|
||||
e_RABs_ToBeSetup_Item->uL_GTPtunnelEndpoint.transportLayerAddress.size = (uint8_t)(x2ap_handover_req->e_rabs_tobesetup[i].eNB_addr.length/8);
|
||||
e_RABs_ToBeSetup_Item->uL_GTPtunnelEndpoint.transportLayerAddress.bits_unused = x2ap_handover_req->e_rabs_tobesetup[i].eNB_addr.length%8;
|
||||
e_RABs_ToBeSetup_Item->uL_GTPtunnelEndpoint.transportLayerAddress.buf =
|
||||
calloc(1,e_RABs_ToBeSetup_Item->uL_GTPtunnelEndpoint.transportLayerAddress.size);
|
||||
|
||||
memcpy (e_RABs_ToBeSetup_Item->uL_GTPtunnelEndpoint.transportLayerAddress.buf,
|
||||
x2ap_handover_req->e_rabs_tobesetup[i].eNB_addr.buffer,
|
||||
e_RABs_ToBeSetup_Item->uL_GTPtunnelEndpoint.transportLayerAddress.size);
|
||||
|
||||
INT32_TO_OCTET_STRING(x2ap_handover_req->e_rabs_tobesetup[i].gtp_teid,&e_RABs_ToBeSetup_Item->uL_GTPtunnelEndpoint.gTP_TEID);
|
||||
}
|
||||
ASN_SEQUENCE_ADD(&ie->value.choice.UE_ContextInformation.e_RABs_ToBeSetup_List.list, e_RABS_ToBeSetup_ItemIEs);
|
||||
}
|
||||
}
|
||||
|
||||
OCTET_STRING_fromBuf(&ie->value.choice.UE_ContextInformation.rRC_Context, (char*) x2ap_handover_req->rrc_buffer, x2ap_handover_req->rrc_buffer_size);
|
||||
|
||||
ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
|
||||
|
||||
/* mandatory */
|
||||
ie = (X2AP_HandoverRequest_IEs_t *)calloc(1, sizeof(X2AP_HandoverRequest_IEs_t));
|
||||
ie->id = X2AP_ProtocolIE_ID_id_UE_HistoryInformation;
|
||||
ie->criticality = X2AP_Criticality_ignore;
|
||||
ie->value.present = X2AP_HandoverRequest_IEs__value_PR_UE_HistoryInformation;
|
||||
//@TODO: consider to update this value
|
||||
{
|
||||
lastVisitedCell_Item = (X2AP_LastVisitedCell_Item_t *)calloc(1, sizeof(X2AP_LastVisitedCell_Item_t));
|
||||
lastVisitedCell_Item->present = X2AP_LastVisitedCell_Item_PR_e_UTRAN_Cell;
|
||||
MCC_MNC_TO_PLMNID(instance_p->mcc, instance_p->mnc, instance_p->mnc_digit_length,
|
||||
&lastVisitedCell_Item->choice.e_UTRAN_Cell.global_Cell_ID.pLMN_Identity);
|
||||
MACRO_ENB_ID_TO_CELL_IDENTITY(0, 0, &lastVisitedCell_Item->choice.e_UTRAN_Cell.global_Cell_ID.eUTRANcellIdentifier);
|
||||
lastVisitedCell_Item->choice.e_UTRAN_Cell.cellType.cell_Size = X2AP_Cell_Size_small;
|
||||
lastVisitedCell_Item->choice.e_UTRAN_Cell.time_UE_StayedInCell = 2;
|
||||
ASN_SEQUENCE_ADD(&ie->value.choice.UE_HistoryInformation.list, lastVisitedCell_Item);
|
||||
}
|
||||
|
||||
ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
|
||||
|
||||
if (x2ap_eNB_encode_pdu(&pdu, &buffer, &len) < 0) {
|
||||
X2AP_ERROR("Failed to encode X2 handover request\n");
|
||||
abort();
|
||||
return -1;
|
||||
}
|
||||
|
||||
MSC_LOG_TX_MESSAGE (MSC_X2AP_SRC_ENB, MSC_X2AP_TARGET_ENB, NULL, 0, "0 X2Handover/initiatingMessage assoc_id %u", x2ap_eNB_data_p->assoc_id);
|
||||
|
||||
x2ap_eNB_itti_send_sctp_data_req(instance_p->instance, x2ap_eNB_data_p->assoc_id, buffer, len, 1);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
|
||||
X2AP_X2AP_PDU_t pdu;
|
||||
X2AP_HandoverRequestAcknowledge_t *out;
|
||||
X2AP_HandoverRequestAcknowledge_IEs_t *ie;
|
||||
X2AP_E_RABs_Admitted_ItemIEs_t *e_RABS_Admitted_ItemIEs;
|
||||
X2AP_E_RABs_Admitted_Item_t *e_RABs_Admitted_Item;
|
||||
|
||||
x2ap_eNB_instance_t *instance_p;
|
||||
|
||||
uint8_t *buffer;
|
||||
uint32_t len;
|
||||
int ret = 0;
|
||||
|
||||
DevAssert(x2ap_eNB_data_p != NULL);
|
||||
|
||||
/* get the eNB instance */
|
||||
instance_p = x2ap_eNB_data_p->x2ap_eNB_instance;
|
||||
|
||||
DevAssert(instance_p != NULL);
|
||||
|
||||
/* Prepare the X2AP handover message to encode */
|
||||
memset(&pdu, 0, sizeof(pdu));
|
||||
pdu.present = X2AP_X2AP_PDU_PR_successfulOutcome;
|
||||
pdu.choice.successfulOutcome.procedureCode = X2AP_ProcedureCode_id_handoverPreparation;
|
||||
pdu.choice.successfulOutcome.criticality = X2AP_Criticality_reject;
|
||||
pdu.choice.successfulOutcome.value.present = X2AP_SuccessfulOutcome__value_PR_HandoverRequestAcknowledge;
|
||||
out = &pdu.choice.successfulOutcome.value.choice.HandoverRequestAcknowledge;
|
||||
|
||||
/* mandatory */
|
||||
ie = (X2AP_HandoverRequestAcknowledge_IEs_t *)calloc(1, sizeof(X2AP_HandoverRequestAcknowledge_IEs_t));
|
||||
ie->id = X2AP_ProtocolIE_ID_id_Old_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;
|
||||
ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
|
||||
|
||||
/* mandatory */
|
||||
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;
|
||||
ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
|
||||
|
||||
/* mandatory */
|
||||
ie = (X2AP_HandoverRequestAcknowledge_IEs_t *)calloc(1, sizeof(X2AP_HandoverRequestAcknowledge_IEs_t));
|
||||
ie->id = X2AP_ProtocolIE_ID_id_E_RABs_Admitted_List;
|
||||
ie->criticality = X2AP_Criticality_ignore;
|
||||
ie->value.present = X2AP_HandoverRequestAcknowledge_IEs__value_PR_E_RABs_Admitted_List;
|
||||
|
||||
{
|
||||
for (int i=0;i<x2ap_handover_req_ack->nb_e_rabs_tobesetup;i++) {
|
||||
e_RABS_Admitted_ItemIEs = (X2AP_E_RABs_Admitted_ItemIEs_t *)calloc(1,sizeof(X2AP_E_RABs_Admitted_ItemIEs_t));
|
||||
e_RABS_Admitted_ItemIEs->id = X2AP_ProtocolIE_ID_id_E_RABs_Admitted_Item;
|
||||
e_RABS_Admitted_ItemIEs->criticality = X2AP_Criticality_ignore;
|
||||
e_RABS_Admitted_ItemIEs->value.present = X2AP_E_RABs_Admitted_ItemIEs__value_PR_E_RABs_Admitted_Item;
|
||||
e_RABs_Admitted_Item = &e_RABS_Admitted_ItemIEs->value.choice.E_RABs_Admitted_Item;
|
||||
{
|
||||
e_RABs_Admitted_Item->e_RAB_ID = x2ap_handover_req_ack->e_rabs_tobesetup[i].e_rab_id;
|
||||
}
|
||||
ASN_SEQUENCE_ADD(&ie->value.choice.E_RABs_Admitted_List.list, e_RABS_Admitted_ItemIEs);
|
||||
}
|
||||
}
|
||||
|
||||
ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
|
||||
|
||||
/* mandatory */
|
||||
ie = (X2AP_HandoverRequestAcknowledge_IEs_t *)calloc(1, sizeof(X2AP_HandoverRequestAcknowledge_IEs_t));
|
||||
ie->id = X2AP_ProtocolIE_ID_id_TargeteNBtoSource_eNBTransparentContainer;
|
||||
ie->criticality = X2AP_Criticality_ignore;
|
||||
ie->value.present = X2AP_HandoverRequestAcknowledge_IEs__value_PR_TargeteNBtoSource_eNBTransparentContainer;
|
||||
|
||||
OCTET_STRING_fromBuf(&ie->value.choice.TargeteNBtoSource_eNBTransparentContainer, (char*) x2ap_handover_req_ack->rrc_buffer, x2ap_handover_req_ack->rrc_buffer_size);
|
||||
|
||||
ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
|
||||
|
||||
if (x2ap_eNB_encode_pdu(&pdu, &buffer, &len) < 0) {
|
||||
X2AP_ERROR("Failed to encode X2 handover response\n");
|
||||
abort();
|
||||
return -1;
|
||||
}
|
||||
|
||||
MSC_LOG_TX_MESSAGE (MSC_X2AP_SRC_ENB, MSC_X2AP_TARGET_ENB, NULL, 0, "0 X2Handover/successfulOutcome assoc_id %u", x2ap_eNB_data_p->assoc_id);
|
||||
|
||||
x2ap_eNB_itti_send_sctp_data_req(instance_p->instance, x2ap_eNB_data_p->assoc_id, buffer, len, 1);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int x2ap_eNB_generate_x2_ue_context_release (x2ap_eNB_data_t *x2ap_eNB_data_p)
|
||||
{
|
||||
|
||||
X2AP_X2AP_PDU_t pdu;
|
||||
X2AP_UEContextRelease_t *out;
|
||||
X2AP_UEContextRelease_IEs_t *ie;
|
||||
|
||||
x2ap_eNB_instance_t *instance_p;
|
||||
|
||||
uint8_t *buffer;
|
||||
uint32_t len;
|
||||
int ret = 0;
|
||||
|
||||
DevAssert(x2ap_eNB_data_p != NULL);
|
||||
|
||||
/* get the eNB instance */
|
||||
instance_p = x2ap_eNB_data_p->x2ap_eNB_instance;
|
||||
|
||||
DevAssert(instance_p != NULL);
|
||||
|
||||
/* Prepare the X2AP ue context relase message to encode */
|
||||
memset(&pdu, 0, sizeof(pdu));
|
||||
pdu.present = X2AP_X2AP_PDU_PR_initiatingMessage;
|
||||
pdu.choice.initiatingMessage.procedureCode = X2AP_ProcedureCode_id_uEContextRelease;
|
||||
pdu.choice.initiatingMessage.criticality = X2AP_Criticality_ignore;
|
||||
pdu.choice.initiatingMessage.value.present = X2AP_InitiatingMessage__value_PR_UEContextRelease;
|
||||
out = &pdu.choice.initiatingMessage.value.choice.UEContextRelease;
|
||||
|
||||
/* mandatory */
|
||||
ie = (X2AP_UEContextRelease_IEs_t *)calloc(1, sizeof(X2AP_UEContextRelease_IEs_t));
|
||||
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;
|
||||
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;
|
||||
ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
|
||||
|
||||
if (x2ap_eNB_encode_pdu(&pdu, &buffer, &len) < 0) {
|
||||
X2AP_ERROR("Failed to encode X2 UE Context Release\n");
|
||||
abort();
|
||||
return -1;
|
||||
}
|
||||
|
||||
MSC_LOG_TX_MESSAGE (MSC_X2AP_SRC_ENB, MSC_X2AP_TARGET_ENB, NULL, 0, "0 X2UEContextRelease/initiatingMessage assoc_id %u", x2ap_eNB_data_p->assoc_id);
|
||||
|
||||
x2ap_eNB_itti_send_sctp_data_req(instance_p->instance, x2ap_eNB_data_p->assoc_id, buffer, len, 1);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -19,6 +19,13 @@
|
||||
* contact@openairinterface.org
|
||||
*/
|
||||
|
||||
/*! \file x2ap_eNB_generate_messages.h
|
||||
* \brief x2ap procedures for eNB
|
||||
* \author Konstantinos Alexandris <Konstantinos.Alexandris@eurecom.fr>, Cedric Roux <Cedric.Roux@eurecom.fr>, Navid Nikaein <Navid.Nikaein@eurecom.fr>
|
||||
* \date 2018
|
||||
* \version 1.0
|
||||
*/
|
||||
|
||||
#ifndef X2AP_ENB_GENERATE_MESSAGES_H_
|
||||
#define X2AP_ENB_GENERATE_MESSAGES_H_
|
||||
|
||||
@@ -26,9 +33,9 @@
|
||||
#include "x2ap_common.h"
|
||||
|
||||
int x2ap_eNB_generate_x2_setup_request(x2ap_eNB_instance_t *instance_p,
|
||||
x2ap_eNB_data_t *x2ap_enb_data_p);
|
||||
x2ap_eNB_data_t *x2ap_eNB_data_p);
|
||||
|
||||
int x2ap_eNB_generate_x2_setup_response(x2ap_eNB_data_t *x2ap_enb_data_p);
|
||||
int x2ap_eNB_generate_x2_setup_response(x2ap_eNB_data_t *x2ap_eNB_data_p);
|
||||
|
||||
int x2ap_eNB_generate_x2_setup_failure(instance_t instance,
|
||||
uint32_t assoc_id,
|
||||
@@ -40,5 +47,12 @@ int x2ap_eNB_set_cause (X2AP_Cause_t * cause_p,
|
||||
X2AP_Cause_PR cause_type,
|
||||
long cause_value);
|
||||
|
||||
int x2ap_eNB_generate_x2_handover_request (x2ap_eNB_data_t *x2ap_eNB_data_p,
|
||||
x2ap_handover_req_t *x2ap_handover_req);
|
||||
|
||||
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);
|
||||
#endif /* X2AP_ENB_GENERATE_MESSAGES_H_ */
|
||||
|
||||
|
||||
@@ -18,6 +18,14 @@
|
||||
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||
* contact@openairinterface.org
|
||||
*/
|
||||
|
||||
/*! \file x2ap_eNB_handler.c
|
||||
* \brief x2ap handler procedures for eNB
|
||||
* \author Konstantinos Alexandris <Konstantinos.Alexandris@eurecom.fr>, Cedric Roux <Cedric.Roux@eurecom.fr>, Navid Nikaein <Navid.Nikaein@eurecom.fr>
|
||||
* \date 2018
|
||||
* \version 1.0
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "intertask_interface.h"
|
||||
@@ -52,9 +60,20 @@ int x2ap_eNB_handle_x2_setup_failure (instance_t instance,
|
||||
uint32_t stream,
|
||||
X2AP_X2AP_PDU_t *pdu);
|
||||
|
||||
static
|
||||
int x2ap_eNB_handle_handover_preparation (instance_t instance,
|
||||
uint32_t assoc_id,
|
||||
uint32_t stream,
|
||||
X2AP_X2AP_PDU_t *pdu);
|
||||
static
|
||||
int x2ap_eNB_handle_handover_response (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] = {
|
||||
{ 0, 0, 0 }, /* handoverPreparation */
|
||||
{ x2ap_eNB_handle_handover_preparation, x2ap_eNB_handle_handover_response, 0 }, /* handoverPreparation */
|
||||
{ 0, 0, 0 }, /* handoverCancel */
|
||||
{ 0, 0, 0 }, /* loadIndication */
|
||||
{ 0, 0, 0 }, /* errorIndication */
|
||||
@@ -143,41 +162,105 @@ int x2ap_eNB_handle_message(instance_t instance, uint32_t assoc_id, int32_t stre
|
||||
const uint8_t *const data, const uint32_t data_length)
|
||||
{
|
||||
X2AP_X2AP_PDU_t pdu;
|
||||
int ret;
|
||||
int ret = 0;
|
||||
|
||||
DevAssert(data != NULL);
|
||||
|
||||
memset(&pdu, 0, sizeof(pdu));
|
||||
|
||||
//printf("Data length received: %d\n", data_length);
|
||||
|
||||
if (x2ap_eNB_decode_pdu(&pdu, data, data_length) < 0) {
|
||||
X2AP_ERROR("Failed to decode PDU\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Checking procedure Code and direction of message */
|
||||
if (pdu.choice.initiatingMessage.procedureCode > sizeof(x2ap_messages_callback) / (3 * sizeof(
|
||||
x2ap_message_decoded_callback))
|
||||
|| (pdu.present > X2AP_X2AP_PDU_PR_unsuccessfulOutcome)) {
|
||||
X2AP_ERROR("[SCTP %d] Either procedureCode %ld or direction %d exceed expected\n",
|
||||
assoc_id, pdu.choice.initiatingMessage.procedureCode, pdu.present);
|
||||
ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_X2AP_X2AP_PDU, &pdu);
|
||||
return -1;
|
||||
}
|
||||
switch (pdu.present) {
|
||||
|
||||
/* No handler present.
|
||||
* This can mean not implemented or no procedure for eNB (wrong direction).
|
||||
*/
|
||||
if (x2ap_messages_callback[pdu.choice.initiatingMessage.procedureCode][pdu.present - 1] == NULL) {
|
||||
X2AP_ERROR("[SCTP %d] No handler for procedureCode %ld in %s\n",
|
||||
assoc_id, pdu.choice.initiatingMessage.procedureCode,
|
||||
x2ap_direction2String(pdu.present - 1));
|
||||
ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_X2AP_X2AP_PDU, &pdu);
|
||||
return -1;
|
||||
}
|
||||
case X2AP_X2AP_PDU_PR_initiatingMessage:
|
||||
/* Checking procedure Code and direction of message */
|
||||
if (pdu.choice.initiatingMessage.procedureCode > sizeof(x2ap_messages_callback) / (3 * sizeof(
|
||||
x2ap_message_decoded_callback))) {
|
||||
//|| (pdu.present > X2AP_X2AP_PDU_PR_unsuccessfulOutcome)) {
|
||||
X2AP_ERROR("[SCTP %d] Either procedureCode %ld exceed expected\n",
|
||||
assoc_id, pdu.choice.initiatingMessage.procedureCode);
|
||||
ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_X2AP_X2AP_PDU, &pdu);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Calling the right handler */
|
||||
ret = (*x2ap_messages_callback[pdu.choice.initiatingMessage.procedureCode][pdu.present - 1])
|
||||
/* No handler present.
|
||||
* This can mean not implemented or no procedure for eNB (wrong direction).
|
||||
*/
|
||||
if (x2ap_messages_callback[pdu.choice.initiatingMessage.procedureCode][pdu.present - 1] == NULL) {
|
||||
X2AP_ERROR("[SCTP %d] No handler for procedureCode %ld in %s\n",
|
||||
assoc_id, pdu.choice.initiatingMessage.procedureCode,
|
||||
x2ap_direction2String(pdu.present - 1));
|
||||
ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_X2AP_X2AP_PDU, &pdu);
|
||||
return -1;
|
||||
}
|
||||
/* Calling the right handler */
|
||||
ret = (*x2ap_messages_callback[pdu.choice.initiatingMessage.procedureCode][pdu.present - 1])
|
||||
(instance, assoc_id, stream, &pdu);
|
||||
break;
|
||||
|
||||
case X2AP_X2AP_PDU_PR_successfulOutcome:
|
||||
/* Checking procedure Code and direction of message */
|
||||
if (pdu.choice.successfulOutcome.procedureCode > sizeof(x2ap_messages_callback) / (3 * sizeof(
|
||||
x2ap_message_decoded_callback))) {
|
||||
//|| (pdu.present > X2AP_X2AP_PDU_PR_unsuccessfulOutcome)) {
|
||||
X2AP_ERROR("[SCTP %d] Either procedureCode %ld exceed expected\n",
|
||||
assoc_id, pdu.choice.successfulOutcome.procedureCode);
|
||||
ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_X2AP_X2AP_PDU, &pdu);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* No handler present.
|
||||
* This can mean not implemented or no procedure for eNB (wrong direction).
|
||||
*/
|
||||
if (x2ap_messages_callback[pdu.choice.successfulOutcome.procedureCode][pdu.present - 1] == NULL) {
|
||||
X2AP_ERROR("[SCTP %d] No handler for procedureCode %ld in %s\n",
|
||||
assoc_id, pdu.choice.successfulOutcome.procedureCode,
|
||||
x2ap_direction2String(pdu.present - 1));
|
||||
ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_X2AP_X2AP_PDU, &pdu);
|
||||
return -1;
|
||||
}
|
||||
/* Calling the right handler */
|
||||
ret = (*x2ap_messages_callback[pdu.choice.successfulOutcome.procedureCode][pdu.present - 1])
|
||||
(instance, assoc_id, stream, &pdu);
|
||||
break;
|
||||
|
||||
case X2AP_X2AP_PDU_PR_unsuccessfulOutcome:
|
||||
/* Checking procedure Code and direction of message */
|
||||
if (pdu.choice.unsuccessfulOutcome.procedureCode > sizeof(x2ap_messages_callback) / (3 * sizeof(
|
||||
x2ap_message_decoded_callback))) {
|
||||
//|| (pdu.present > X2AP_X2AP_PDU_PR_unsuccessfulOutcome)) {
|
||||
X2AP_ERROR("[SCTP %d] Either procedureCode %ld exceed expected\n",
|
||||
assoc_id, pdu.choice.unsuccessfulOutcome.procedureCode);
|
||||
ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_X2AP_X2AP_PDU, &pdu);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* No handler present.
|
||||
* This can mean not implemented or no procedure for eNB (wrong direction).
|
||||
*/
|
||||
if (x2ap_messages_callback[pdu.choice.unsuccessfulOutcome.procedureCode][pdu.present - 1] == NULL) {
|
||||
X2AP_ERROR("[SCTP %d] No handler for procedureCode %ld in %s\n",
|
||||
assoc_id, pdu.choice.unsuccessfulOutcome.procedureCode,
|
||||
x2ap_direction2String(pdu.present - 1));
|
||||
ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_X2AP_X2AP_PDU, &pdu);
|
||||
return -1;
|
||||
}
|
||||
/* Calling the right handler */
|
||||
ret = (*x2ap_messages_callback[pdu.choice.unsuccessfulOutcome.procedureCode][pdu.present - 1])
|
||||
(instance, assoc_id, stream, &pdu);
|
||||
break;
|
||||
|
||||
default:
|
||||
X2AP_ERROR("[SCTP %d] Direction %d exceed expected\n",
|
||||
assoc_id, pdu.present);
|
||||
break;
|
||||
}
|
||||
|
||||
ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_X2AP_X2AP_PDU, &pdu);
|
||||
return ret;
|
||||
}
|
||||
@@ -191,6 +274,7 @@ x2ap_eNB_handle_x2_setup_request(instance_t instance,
|
||||
|
||||
X2AP_X2SetupRequest_t *x2SetupRequest;
|
||||
X2AP_X2SetupRequest_IEs_t *ie;
|
||||
ServedCells__Member *servedCellMember;
|
||||
|
||||
x2ap_eNB_data_t *x2ap_eNB_data;
|
||||
uint32_t eNB_id = 0;
|
||||
@@ -283,6 +367,17 @@ x2ap_eNB_handle_x2_setup_request(instance_t instance,
|
||||
*/
|
||||
}
|
||||
|
||||
/* Set proper pci */
|
||||
X2AP_FIND_PROTOCOLIE_BY_ID(X2AP_X2SetupRequest_IEs_t, ie, x2SetupRequest,
|
||||
X2AP_ProtocolIE_ID_id_ServedCells, true);
|
||||
if (ie->value.choice.ServedCells.list.count > 0) {
|
||||
x2ap_eNB_data->x2ap_eNB_instance->num_cc = ie->value.choice.ServedCells.list.count;
|
||||
for (int i=0; i<ie->value.choice.ServedCells.list.count;i++) {
|
||||
servedCellMember = (ServedCells__Member *)ie->value.choice.ServedCells.list.array[i];
|
||||
x2ap_eNB_data->x2ap_eNB_instance->Nid_target_cell[i] = servedCellMember->servedCellInfo.pCI;
|
||||
}
|
||||
}
|
||||
|
||||
return x2ap_eNB_generate_x2_setup_response(x2ap_eNB_data);
|
||||
}
|
||||
|
||||
@@ -295,6 +390,7 @@ int x2ap_eNB_handle_x2_setup_response(instance_t instance,
|
||||
|
||||
X2AP_X2SetupResponse_t *x2SetupResponse;
|
||||
X2AP_X2SetupResponse_IEs_t *ie;
|
||||
ServedCells__Member *servedCellMember;
|
||||
|
||||
x2ap_eNB_data_t *x2ap_eNB_data;
|
||||
uint32_t eNB_id = 0;
|
||||
@@ -367,6 +463,17 @@ int x2ap_eNB_handle_x2_setup_response(instance_t instance,
|
||||
*/
|
||||
}
|
||||
|
||||
/* Set proper pci */
|
||||
X2AP_FIND_PROTOCOLIE_BY_ID(X2AP_X2SetupResponse_IEs_t, ie, x2SetupResponse,
|
||||
X2AP_ProtocolIE_ID_id_ServedCells, true);
|
||||
if (ie->value.choice.ServedCells.list.count > 0) {
|
||||
x2ap_eNB_data->x2ap_eNB_instance->num_cc = ie->value.choice.ServedCells.list.count;
|
||||
for (int i=0; i<ie->value.choice.ServedCells.list.count;i++) {
|
||||
servedCellMember = (ServedCells__Member *)ie->value.choice.ServedCells.list.array[i];
|
||||
x2ap_eNB_data->x2ap_eNB_instance->Nid_target_cell[i] = servedCellMember->servedCellInfo.pCI;
|
||||
}
|
||||
}
|
||||
|
||||
/* Optionaly set the target eNB name */
|
||||
|
||||
/* The association is now ready as source and target eNBs know parameters of each other.
|
||||
@@ -430,3 +537,165 @@ int x2ap_eNB_handle_x2_setup_failure(instance_t instance,
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static
|
||||
int x2ap_eNB_handle_handover_preparation (instance_t instance,
|
||||
uint32_t assoc_id,
|
||||
uint32_t stream,
|
||||
X2AP_X2AP_PDU_t *pdu)
|
||||
{
|
||||
|
||||
X2AP_HandoverRequest_t *x2HandoverRequest;
|
||||
X2AP_HandoverRequest_IEs_t *ie;
|
||||
|
||||
X2AP_E_RABs_ToBeSetup_ItemIEs_t *e_RABS_ToBeSetup_ItemIEs;
|
||||
X2AP_E_RABs_ToBeSetup_Item_t *e_RABs_ToBeSetup_Item;
|
||||
|
||||
x2ap_eNB_data_t *x2ap_eNB_data;
|
||||
MessageDef *msg;
|
||||
|
||||
DevAssert (pdu != NULL);
|
||||
x2HandoverRequest = &pdu->choice.initiatingMessage.value.choice.HandoverRequest;
|
||||
|
||||
if (stream == 0) {
|
||||
X2AP_ERROR ("Received new x2 handover request on stream == 0\n");
|
||||
/* TODO: send a x2 failure response */
|
||||
return 0;
|
||||
}
|
||||
|
||||
X2AP_DEBUG ("Received a new X2 handover request\n");
|
||||
|
||||
x2ap_eNB_data = x2ap_get_eNB(NULL, assoc_id, 0);
|
||||
DevAssert(x2ap_eNB_data != NULL);
|
||||
|
||||
msg = itti_alloc_new_message(TASK_X2AP, X2AP_HANDOVER_REQ);
|
||||
|
||||
X2AP_FIND_PROTOCOLIE_BY_ID(X2AP_HandoverRequest_IEs_t, ie, x2HandoverRequest,
|
||||
X2AP_ProtocolIE_ID_id_Old_eNB_UE_X2AP_ID, true);
|
||||
//X2AP_HANDOVER_REQ(msg).source_rnti = ctxt_pP->rnti;
|
||||
//X2AP_HANDOVER_REQ(m).source_x2id = x2HandoverRequest->old_eNB_UE_X2AP_ID;
|
||||
X2AP_HANDOVER_REQ(msg).old_eNB_ue_x2ap_id = ie->value.choice.UE_X2AP_ID;
|
||||
|
||||
//X2AP_HANDOVER_REQ(msg).target_physCellId = measResults2->measResultNeighCells->choice.
|
||||
//measResultListEUTRA.list.array[ncell_index]->physCellId;
|
||||
X2AP_FIND_PROTOCOLIE_BY_ID(X2AP_HandoverRequest_IEs_t, ie, x2HandoverRequest,
|
||||
X2AP_ProtocolIE_ID_id_GUMMEI_ID, true);
|
||||
|
||||
TBCD_TO_MCC_MNC(&ie->value.choice.ECGI.pLMN_Identity, X2AP_HANDOVER_REQ(msg).ue_gummei.mcc,
|
||||
X2AP_HANDOVER_REQ(msg).ue_gummei.mnc, X2AP_HANDOVER_REQ(msg).ue_gummei.mnc_len);
|
||||
OCTET_STRING_TO_INT8(&ie->value.choice.GUMMEI.mME_Code, X2AP_HANDOVER_REQ(msg).ue_gummei.mme_code);
|
||||
OCTET_STRING_TO_INT16(&ie->value.choice.GUMMEI.gU_Group_ID.mME_Group_ID, X2AP_HANDOVER_REQ(msg).ue_gummei.mme_group_id);
|
||||
|
||||
X2AP_FIND_PROTOCOLIE_BY_ID(X2AP_HandoverRequest_IEs_t, ie, x2HandoverRequest,
|
||||
X2AP_ProtocolIE_ID_id_UE_ContextInformation, true);
|
||||
|
||||
X2AP_HANDOVER_REQ(msg).mme_ue_s1ap_id = ie->value.choice.UE_ContextInformation.mME_UE_S1AP_ID;
|
||||
|
||||
X2AP_HANDOVER_REQ(msg).target_mod_id = x2ap_eNB_data->x2ap_eNB_instance->eNB_id;
|
||||
|
||||
X2AP_HANDOVER_REQ(msg).security_capabilities.encryption_algorithms =
|
||||
BIT_STRING_to_uint16(&ie->value.choice.UE_ContextInformation.uESecurityCapabilities.encryptionAlgorithms);
|
||||
X2AP_HANDOVER_REQ(msg).security_capabilities.integrity_algorithms =
|
||||
BIT_STRING_to_uint16(&ie->value.choice.UE_ContextInformation.uESecurityCapabilities.integrityProtectionAlgorithms);
|
||||
|
||||
//X2AP_HANDOVER_REQ(msg).ue_ambr=ue_context_pP->ue_context.ue_ambr;
|
||||
|
||||
if ((ie->value.choice.UE_ContextInformation.aS_SecurityInformation.key_eNodeB_star.buf) &&
|
||||
(ie->value.choice.UE_ContextInformation.aS_SecurityInformation.key_eNodeB_star.size == 32)) {
|
||||
memcpy(X2AP_HANDOVER_REQ(msg).kenb, ie->value.choice.UE_ContextInformation.aS_SecurityInformation.key_eNodeB_star.buf, 32);
|
||||
X2AP_HANDOVER_REQ(msg).kenb_ncc = ie->value.choice.UE_ContextInformation.aS_SecurityInformation.nextHopChainingCount;
|
||||
} else {
|
||||
X2AP_WARN ("Size of eNB key star does not match the expected value\n");
|
||||
}
|
||||
|
||||
if (ie->value.choice.UE_ContextInformation.e_RABs_ToBeSetup_List.list.count > 0) {
|
||||
|
||||
X2AP_HANDOVER_REQ(msg).nb_e_rabs_tobesetup = ie->value.choice.UE_ContextInformation.e_RABs_ToBeSetup_List.list.count;
|
||||
|
||||
for (int i=0;i<ie->value.choice.UE_ContextInformation.e_RABs_ToBeSetup_List.list.count;i++) {
|
||||
e_RABS_ToBeSetup_ItemIEs = (X2AP_E_RABs_ToBeSetup_ItemIEs_t *) ie->value.choice.UE_ContextInformation.e_RABs_ToBeSetup_List.list.array[i];
|
||||
e_RABs_ToBeSetup_Item = &e_RABS_ToBeSetup_ItemIEs->value.choice.E_RABs_ToBeSetup_Item;
|
||||
|
||||
X2AP_HANDOVER_REQ(msg).e_rabs_tobesetup[i].e_rab_id = e_RABs_ToBeSetup_Item->e_RAB_ID ;
|
||||
|
||||
memcpy(X2AP_HANDOVER_REQ(msg).e_rabs_tobesetup[i].eNB_addr.buffer,
|
||||
e_RABs_ToBeSetup_Item->uL_GTPtunnelEndpoint.transportLayerAddress.buf,
|
||||
e_RABs_ToBeSetup_Item->uL_GTPtunnelEndpoint.transportLayerAddress.size);
|
||||
|
||||
X2AP_HANDOVER_REQ(msg).e_rabs_tobesetup[i].eNB_addr.length =
|
||||
e_RABs_ToBeSetup_Item->uL_GTPtunnelEndpoint.transportLayerAddress.size * 8 - e_RABs_ToBeSetup_Item->uL_GTPtunnelEndpoint.transportLayerAddress.bits_unused;
|
||||
|
||||
OCTET_STRING_TO_INT32(&e_RABs_ToBeSetup_Item->uL_GTPtunnelEndpoint.gTP_TEID,
|
||||
X2AP_HANDOVER_REQ(msg).e_rabs_tobesetup[i].gtp_teid);
|
||||
|
||||
X2AP_HANDOVER_REQ(msg).e_rab_param[i].qos.qci = e_RABs_ToBeSetup_Item->e_RAB_Level_QoS_Parameters.qCI;
|
||||
X2AP_HANDOVER_REQ(msg).e_rab_param[i].qos.allocation_retention_priority.priority_level = e_RABs_ToBeSetup_Item->e_RAB_Level_QoS_Parameters.allocationAndRetentionPriority.priorityLevel;
|
||||
X2AP_HANDOVER_REQ(msg).e_rab_param[i].qos.allocation_retention_priority.pre_emp_capability = e_RABs_ToBeSetup_Item->e_RAB_Level_QoS_Parameters.allocationAndRetentionPriority.pre_emptionCapability;
|
||||
X2AP_HANDOVER_REQ(msg).e_rab_param[i].qos.allocation_retention_priority.pre_emp_vulnerability = e_RABs_ToBeSetup_Item->e_RAB_Level_QoS_Parameters.allocationAndRetentionPriority.pre_emptionVulnerability;
|
||||
}
|
||||
|
||||
}
|
||||
else {
|
||||
X2AP_ERROR ("Can't decode the e_RABs_ToBeSetup_List \n");
|
||||
}
|
||||
|
||||
X2AP_RRC_Context_t *c = &ie->value.choice.UE_ContextInformation.rRC_Context;
|
||||
|
||||
if (c->size > 1024 /* TODO: this is the size of rrc_buffer in struct x2ap_handover_req_ack_s*/)
|
||||
{ printf("%s:%d: fatal: buffer too big\n", __FILE__, __LINE__); abort(); }
|
||||
|
||||
memcpy(X2AP_HANDOVER_REQ_ACK(msg).rrc_buffer, c->buf, c->size);
|
||||
X2AP_HANDOVER_REQ_ACK(msg).rrc_buffer_size = c->size;
|
||||
|
||||
itti_send_msg_to_task(TASK_RRC_ENB, x2ap_eNB_data->x2ap_eNB_instance->instance, msg);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static
|
||||
int x2ap_eNB_handle_handover_response (instance_t instance,
|
||||
uint32_t assoc_id,
|
||||
uint32_t stream,
|
||||
X2AP_X2AP_PDU_t *pdu)
|
||||
{
|
||||
X2AP_HandoverRequestAcknowledge_t *x2HandoverRequestAck;
|
||||
X2AP_HandoverRequestAcknowledge_IEs_t *ie;
|
||||
|
||||
x2ap_eNB_data_t *x2ap_eNB_data;
|
||||
MessageDef *msg;
|
||||
|
||||
DevAssert (pdu != NULL);
|
||||
x2HandoverRequestAck = &pdu->choice.successfulOutcome.value.choice.HandoverRequestAcknowledge;
|
||||
|
||||
if (stream == 0) {
|
||||
X2AP_ERROR ("Received new x2 handover response on stream == 0\n");
|
||||
/* TODO: send a x2 failure response */
|
||||
return 0;
|
||||
}
|
||||
|
||||
X2AP_DEBUG ("Received a new X2 handover response\n");
|
||||
|
||||
x2ap_eNB_data = x2ap_get_eNB(NULL, assoc_id, 0);
|
||||
DevAssert(x2ap_eNB_data != NULL);
|
||||
|
||||
|
||||
msg = itti_alloc_new_message(TASK_X2AP, X2AP_HANDOVER_REQ_ACK);
|
||||
/* TODO: fill the message */
|
||||
//extern int x2id_to_source_rnti[1];
|
||||
//X2AP_HANDOVER_REQ_ACK(m).source_x2id = x2HandoverRequestAck->old_eNB_UE_X2AP_ID;
|
||||
//X2AP_HANDOVER_REQ_ACK(m).source_rnti = x2id_to_source_rnti[x2HandoverRequestAck->old_eNB_UE_X2AP_ID];
|
||||
|
||||
X2AP_FIND_PROTOCOLIE_BY_ID(X2AP_HandoverRequestAcknowledge_IEs_t, ie, x2HandoverRequestAck,
|
||||
X2AP_ProtocolIE_ID_id_TargeteNBtoSource_eNBTransparentContainer, true);
|
||||
|
||||
X2AP_TargeteNBtoSource_eNBTransparentContainer_t *c = &ie->value.choice.TargeteNBtoSource_eNBTransparentContainer;
|
||||
|
||||
if (c->size > 1024 /* TODO: this is the size of rrc_buffer in struct x2ap_handover_req_ack_s*/)
|
||||
{ printf("%s:%d: fatal: buffer too big\n", __FILE__, __LINE__); abort(); }
|
||||
|
||||
memcpy(X2AP_HANDOVER_REQ_ACK(msg).rrc_buffer, c->buf, c->size);
|
||||
X2AP_HANDOVER_REQ_ACK(msg).rrc_buffer_size = c->size;
|
||||
|
||||
itti_send_msg_to_task(TASK_RRC_ENB, x2ap_eNB_data->x2ap_eNB_instance->instance, msg);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -19,6 +19,13 @@
|
||||
* contact@openairinterface.org
|
||||
*/
|
||||
|
||||
/*! \file x2ap_eNB_handler.h
|
||||
* \brief x2ap handler procedures for eNB
|
||||
* \author Konstantinos Alexandris <Konstantinos.Alexandris@eurecom.fr>, Cedric Roux <Cedric.Roux@eurecom.fr>, Navid Nikaein <Navid.Nikaein@eurecom.fr>
|
||||
* \date 2018
|
||||
* \version 1.0
|
||||
*/
|
||||
|
||||
#ifndef X2AP_ENB_HANDLERS_H_
|
||||
#define X2AP_ENB_HANDLERS_H_
|
||||
|
||||
|
||||
@@ -19,6 +19,13 @@
|
||||
* contact@openairinterface.org
|
||||
*/
|
||||
|
||||
/*! \file x2ap_eNB_itti_messaging.c
|
||||
* \brief x2ap tasks for eNB
|
||||
* \author Konstantinos Alexandris <Konstantinos.Alexandris@eurecom.fr>, Cedric Roux <Cedric.Roux@eurecom.fr>, Navid Nikaein <Navid.Nikaein@eurecom.fr>
|
||||
* \date 2018
|
||||
* \version 1.0
|
||||
*/
|
||||
|
||||
#include "intertask_interface.h"
|
||||
|
||||
#include "x2ap_eNB_itti_messaging.h"
|
||||
|
||||
@@ -19,6 +19,13 @@
|
||||
* contact@openairinterface.org
|
||||
*/
|
||||
|
||||
/*! \file x2ap_eNB_itti_messaging.h
|
||||
* \brief x2ap tasks for eNB
|
||||
* \author Konstantinos Alexandris <Konstantinos.Alexandris@eurecom.fr>, Cedric Roux <Cedric.Roux@eurecom.fr>, Navid Nikaein <Navid.Nikaein@eurecom.fr>
|
||||
* \date 2018
|
||||
* \version 1.0
|
||||
*/
|
||||
|
||||
#ifndef X2AP_ENB_ITTI_MESSAGING_H_
|
||||
#define X2AP_ENB_ITTI_MESSAGING_H_
|
||||
|
||||
|
||||
@@ -19,6 +19,13 @@
|
||||
* contact@openairinterface.org
|
||||
*/
|
||||
|
||||
/*! \file x2ap_eNB_management_procedures.c
|
||||
* \brief x2ap tasks for eNB
|
||||
* \author Konstantinos Alexandris <Konstantinos.Alexandris@eurecom.fr>, Cedric Roux <Cedric.Roux@eurecom.fr>, Navid Nikaein <Navid.Nikaein@eurecom.fr>
|
||||
* \date 2018
|
||||
* \version 1.0
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
@@ -162,6 +169,22 @@ x2ap_eNB_instance_t *x2ap_eNB_get_instance(instance_t instance)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
x2ap_eNB_instance_t *x2ap_eNB_pci_get_instance(uint32_t pci)
|
||||
{
|
||||
x2ap_eNB_instance_t *temp = NULL;
|
||||
|
||||
STAILQ_FOREACH(temp, &x2ap_eNB_internal_data.x2ap_eNB_instances_head,
|
||||
x2ap_eNB_entries) {
|
||||
for (int i=0; i<temp->num_cc;i++) {
|
||||
if (temp->Nid_target_cell[i] == pci) {
|
||||
/* Matching occurence */
|
||||
return temp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/// utility functions
|
||||
|
||||
|
||||
@@ -19,6 +19,13 @@
|
||||
* contact@openairinterface.org
|
||||
*/
|
||||
|
||||
/*! \file x2ap_eNB_management_procedures.h
|
||||
* \brief x2ap tasks for eNB
|
||||
* \author Konstantinos Alexandris <Konstantinos.Alexandris@eurecom.fr>, Cedric Roux <Cedric.Roux@eurecom.fr>, Navid Nikaein <Navid.Nikaein@eurecom.fr>
|
||||
* \date 2018
|
||||
* \version 1.0
|
||||
*/
|
||||
|
||||
#ifndef X2AP_ENB_MANAGEMENT_PROCEDURES_H_
|
||||
#define X2AP_ENB_MANAGEMENT_PROCEDURES_H
|
||||
|
||||
@@ -30,6 +37,8 @@ void x2ap_eNB_insert_new_instance(x2ap_eNB_instance_t *new_instance_p);
|
||||
|
||||
x2ap_eNB_instance_t *x2ap_eNB_get_instance(uint8_t mod_id);
|
||||
|
||||
x2ap_eNB_instance_t *x2ap_eNB_pci_get_instance(uint32_t pci);
|
||||
|
||||
uint16_t x2ap_eNB_fetch_add_global_cnx_id(void);
|
||||
|
||||
void x2ap_eNB_prepare_internal_data(void);
|
||||
|
||||
Reference in New Issue
Block a user