diff --git a/cmake_targets/CMakeLists.txt b/cmake_targets/CMakeLists.txt index dee34ef05df10ec5208400ab41c1b7ef23fa6213..732cfd289e2e2f1bd887ef2682e93f91c8605e57 100644 --- a/cmake_targets/CMakeLists.txt +++ b/cmake_targets/CMakeLists.txt @@ -469,7 +469,6 @@ endif(${X2AP_RELEASE} STREQUAL "R8") add_definitions(-DX2AP_VERSION=${X2AP_VERSION}) set(X2AP_ASN_DIR ${X2AP_DIR}/MESSAGES/ASN1/${X2AP_RELEASE}) set(X2AP_C_DIR ${asn1_generated_dir}/X2AP_${X2AP_RELEASE}) - # Warning: if you modify ASN.1 source file to generate new C files, cmake should be re-run instead of make execute_process(COMMAND ${OPENAIR_CMAKE}/tools/make_asn1c_includes.sh "${X2AP_C_DIR}" "${X2AP_ASN_DIR}/${X2AP_ASN_FILES}" "X2AP_" -fno-include-deps RESULT_VARIABLE ret) diff --git a/openair2/COMMON/x2ap_messages_def.h b/openair2/COMMON/x2ap_messages_def.h index c588753ca8b8fbb42c1c32b3c7ed0163d7bde66f..6c2d56a942079e3f56dca5f966317470c0e226e5 100644 --- a/openair2/COMMON/x2ap_messages_def.h +++ b/openair2/COMMON/x2ap_messages_def.h @@ -47,3 +47,6 @@ MESSAGE_DEF(X2AP_HANDOVER_CANCEL , MESSAGE_PRIORITY_MED, x2ap_han /* handover messages X2AP <-> S1AP */ MESSAGE_DEF(X2AP_UE_CONTEXT_RELEASE , MESSAGE_PRIORITY_MED, x2ap_ue_context_release_t , x2ap_ue_context_release) + +/*Senb bearer addition messages X2AP <-> RRC */ +MESSAGE_DEF(X2AP_SENB_ADDITION_REQ , MESSAGE_PRIORITY_MED, x2ap_senb_addition_req_t , x2ap_senb_addition_req) diff --git a/openair2/COMMON/x2ap_messages_types.h b/openair2/COMMON/x2ap_messages_types.h index 5f2a95f576611df8596103ee9652e94127cb08a7..e502191d2b9b5eef4175c9bc02f811efb578c4c8 100644 --- a/openair2/COMMON/x2ap_messages_types.h +++ b/openair2/COMMON/x2ap_messages_types.h @@ -28,16 +28,16 @@ //-------------------------------------------------------------------------------------------// // Defines to access message fields. -#define X2AP_REGISTER_ENB_REQ(mSGpTR) (mSGpTR)->ittiMsg.x2ap_register_enb_req -#define X2AP_SETUP_REQ(mSGpTR) (mSGpTR)->ittiMsg.x2ap_setup_req -#define X2AP_SETUP_RESP(mSGpTR) (mSGpTR)->ittiMsg.x2ap_setup_resp -#define X2AP_HANDOVER_REQ(mSGpTR) (mSGpTR)->ittiMsg.x2ap_handover_req -#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_HANDOVER_CANCEL(mSGpTR) (mSGpTR)->ittiMsg.x2ap_handover_cancel - +#define X2AP_REGISTER_ENB_REQ(mSGpTR) (mSGpTR)->ittiMsg.x2ap_register_enb_req +#define X2AP_SETUP_REQ(mSGpTR) (mSGpTR)->ittiMsg.x2ap_setup_req +#define X2AP_SETUP_RESP(mSGpTR) (mSGpTR)->ittiMsg.x2ap_setup_resp +#define X2AP_HANDOVER_REQ(mSGpTR) (mSGpTR)->ittiMsg.x2ap_handover_req +#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_HANDOVER_CANCEL(mSGpTR) (mSGpTR)->ittiMsg.x2ap_handover_cancel +#define X2AP_SENB_ADDITION_REQ(mSGpTR) (mSGpTR)->ittiMsg.x2ap_senb_addition_req #define X2AP_MAX_NB_ENB_IP_ADDRESS 2 @@ -236,4 +236,71 @@ typedef struct x2ap_handover_req_ack_s { uint32_t mme_ue_s1ap_id; } x2ap_handover_req_ack_t; +typedef struct x2ap_senb_addition_req_s { + + /* MeNB UE X2AP ID*/ + int x2_MeNB_UE_id; + + /*SCG Bearer option*/ + security_capabilities_t UE_security_capabilities; + + /*SCG Bearer option*/ + uint8_t SeNB_security_key[256]; + + /*SeNB UE aggregate maximum bitrate */ + ambr_t SeNB_ue_ambr; + + uint8_t total_nb_e_rabs_tobeadded; + + uint8_t nb_sCG_e_rabs_tobeadded; + + uint8_t nb_split_e_rabs_tobeadded; + + /*list of total e_rabs (SCG or split) to be added*/ + //e_rab_setup_t total_e_rabs_tobeadded[S1AP_MAX_E_RAB]; + + /* list of SCG e_rab to be added by RRC layers */ + e_rab_setup_t e_sCG_rabs_tobeadded[S1AP_MAX_E_RAB]; + + /* list of split e_rab to be added by RRC layers */ + e_rab_setup_t e_split_rabs_tobeadded[S1AP_MAX_E_RAB]; + + /* list of SCG e_rab to be added by RRC layers */ + e_rab_t e_sCG_rab_param[S1AP_MAX_E_RAB]; + + /* list of split e_rab to be added by RRC layers */ + e_rab_t e_split_rab_param[S1AP_MAX_E_RAB]; + + /*Used for the MeNB to SeNB Container to include the SCG-ConfigInfo as per 36.331*/ + uint8_t rrc_buffer[1024 /* arbitrary, big enough */]; + + int rrc_buffer_size; + +}x2ap_senb_addition_req_t; + + + + +//Panos: Have to see what should be the additional/different elements comparing to handover req ack +typedef struct x2ap_senb_addition_req_ack_s { + + int MeNB_UE_X2_id; + + int SeNB_UE_X2_id; + + uint8_t nb_sCG_e_rabs_tobeadded; + + uint8_t nb_split_e_rabs_tobeadded; + + /* list of SCG e_rab to be added by RRC layers */ + e_rab_setup_t e_sCG_rabs_tobeadded[S1AP_MAX_E_RAB]; + + /* list of split e_rab to be added by RRC layers */ + e_rab_setup_t e_split_rabs_tobeadded[S1AP_MAX_E_RAB]; + + uint8_t rrc_buffer[1024 /* arbitrary, big enough */]; + int rrc_buffer_size; + +} x2ap_senb_addition_req_ack_t; + #endif /* X2AP_MESSAGES_TYPES_H_ */ diff --git a/openair2/X2AP/MESSAGES/ASN1/R15/x2ap-15.1.0.asn1 b/openair2/X2AP/MESSAGES/ASN1/R15/x2ap-15.1.0.asn1 index 04de5ca5c5eefa62031d5df7cbd28429a57a67d9..e8a053a12c855b3b5bdd1af71aeaa5b3a9901979 100644 --- a/openair2/X2AP/MESSAGES/ASN1/R15/x2ap-15.1.0.asn1 +++ b/openair2/X2AP/MESSAGES/ASN1/R15/x2ap-15.1.0.asn1 @@ -4010,7 +4010,7 @@ NRNeighbour-Information-ExtIEs X2AP-PROTOCOL-EXTENSION ::= { ... } -CellAssistanceInformation ::= CHOICE { +CellAssistanceInformation ::= CHOICE { limited-list Limited-list, full-list ENUMERATED {allServedNRcells, ...}, ... @@ -6094,7 +6094,7 @@ SgNBResourceCoordinationInformationExtIEs X2AP-PROTOCOL-EXTENSION ::= { ... } -SgNB-UE-X2AP-ID ::= INTEGER (0..4294967295) +SgNB-UE-X2AP-ID ::= INTEGER (0..4294967295) SIPTOBearerDeactivationIndication ::= ENUMERATED { true, diff --git a/openair2/X2AP/x2ap_eNB.c b/openair2/X2AP/x2ap_eNB.c index 8b11e469b2d03f1e86b74c8a94bf55778ab9a1d6..54b0020296b1f7057f0d56f11ae81cb515a96f6e 100644 --- a/openair2/X2AP/x2ap_eNB.c +++ b/openair2/X2AP/x2ap_eNB.c @@ -151,7 +151,8 @@ void x2ap_eNB_handle_sctp_association_resp(instance_t instance, sctp_new_associa printf("x2ap_eNB_handle_sctp_association_resp at 4\n"); dump_trees(); /* Prepare new x2 Setup Request */ - x2ap_eNB_generate_x2_setup_request(instance_p, x2ap_enb_data_p); + x2ap_eNB_generate_ENDC_x2_setup_request(instance_p, x2ap_enb_data_p); + //x2ap_eNB_generate_x2_setup_request(instance_p, x2ap_enb_data_p); } static diff --git a/openair2/X2AP/x2ap_eNB_decoder.c b/openair2/X2AP/x2ap_eNB_decoder.c index 3604aa03c8a75420b4638dd70967ddba52745e00..c7fc98763a656e0f97b06c76a197c1042c22cba7 100644 --- a/openair2/X2AP/x2ap_eNB_decoder.c +++ b/openair2/X2AP/x2ap_eNB_decoder.c @@ -59,6 +59,10 @@ static int x2ap_eNB_decode_initiating_message(X2AP_X2AP_PDU_t *pdu) X2AP_INFO("x2ap_eNB_decode_initiating_message!\n"); break; + case X2AP_ProcedureCode_id_endcX2Setup: + X2AP_INFO("X2AP_ProcedureCode_id_endcX2Setup message!\n"); + break; + default: X2AP_ERROR("Unknown procedure ID (%d) for initiating message\n", (int)pdu->choice.initiatingMessage.procedureCode); @@ -85,6 +89,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_endcX2Setup: + X2AP_INFO("x2ap_eNB_decode_successfuloutcome_message!\n"); + break; + default: X2AP_ERROR("Unknown procedure ID (%d) for successfull outcome message\n", (int)pdu->choice.successfulOutcome.procedureCode); @@ -126,9 +134,9 @@ int x2ap_eNB_decode_pdu(X2AP_X2AP_PDU_t *pdu, const uint8_t *const buffer, uint3 length, 0, 0); - if (asn1_xer_print) { + //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"); diff --git a/openair2/X2AP/x2ap_eNB_defs.h b/openair2/X2AP/x2ap_eNB_defs.h index 03d8216b5666a0904fac6492c264384eef0862bd..6ab62ebf98fff24817fad7838ca9bb120aded4b6 100644 --- a/openair2/X2AP/x2ap_eNB_defs.h +++ b/openair2/X2AP/x2ap_eNB_defs.h @@ -175,6 +175,12 @@ typedef struct x2ap_eNB_instance_s { uint32_t fdd_earfcn_UL[MAX_NUM_CCs]; uint32_t subframeAssignment[MAX_NUM_CCs]; uint32_t specialSubframe[MAX_NUM_CCs]; + +//#ifdef Rel15 + uint32_t tdd_nRARFCN[MAX_NUM_CCs]; + int16_t nr_SCS[MAX_NUM_CCs]; +//#endif + int num_cc; net_ip_address_t target_enb_x2_ip_address[X2AP_MAX_NB_ENB_IP_ADDRESS]; diff --git a/openair2/X2AP/x2ap_eNB_encoder.c b/openair2/X2AP/x2ap_eNB_encoder.c index 8b1c030d35d0b14d588475cf317d450f2fa3e686..392206e4d730653e76dfea07c299860347aaa625 100644 --- a/openair2/X2AP/x2ap_eNB_encoder.c +++ b/openair2/X2AP/x2ap_eNB_encoder.c @@ -44,9 +44,9 @@ int x2ap_eNB_encode_pdu(X2AP_X2AP_PDU_t *pdu, uint8_t **buffer, uint32_t *len) DevAssert(buffer != NULL); DevAssert(len != NULL); - if (asn1_xer_print) { + //if (asn1_xer_print) { xer_fprint(stdout, &asn_DEF_X2AP_X2AP_PDU, (void *)pdu); - } + //} encoded = aper_encode_to_new_buffer(&asn_DEF_X2AP_X2AP_PDU, 0, pdu, (void **)buffer); diff --git a/openair2/X2AP/x2ap_eNB_generate_messages.c b/openair2/X2AP/x2ap_eNB_generate_messages.c index 38ebd732ac390c02832b9f9645c67b96e63fd84e..be3002c197f9728ea94e3da5eea6a233d8e5500f 100644 --- a/openair2/X2AP/x2ap_eNB_generate_messages.c +++ b/openair2/X2AP/x2ap_eNB_generate_messages.c @@ -323,6 +323,10 @@ int x2ap_eNB_generate_x2_setup_response(x2ap_eNB_instance_t *instance_p, x2ap_eN &servedCellMember->servedCellInfo.cellId.eUTRANcellIdentifier); INT16_TO_OCTET_STRING(instance_p->tac, &servedCellMember->servedCellInfo.tAC); + X2AP_INFO("TAC: %d -> %02x%02x\n", instance_p->tac, + servedCellMember->servedCellInfo.tAC.buf[0], + servedCellMember->servedCellInfo.tAC.buf[1]); + plmn = (X2AP_PLMN_Identity_t *)calloc(1,sizeof(X2AP_PLMN_Identity_t)); { MCC_MNC_TO_PLMNID(instance_p->mcc, instance_p->mnc, instance_p->mnc_digit_length, plmn); @@ -993,3 +997,519 @@ int x2ap_eNB_generate_x2_handover_cancel (x2ap_eNB_instance_t *instance_p, x2ap_ return ret; } + +int x2ap_eNB_generate_senb_addition_request (x2ap_eNB_instance_t *instance_p, x2ap_eNB_data_t *x2ap_eNB_data_p + /* TODO: pass needed parameters */) +{ + X2AP_X2AP_PDU_t pdu; + X2AP_SeNBAdditionRequest_t *out; + X2AP_SeNBAdditionRequest_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 SeNB Addition Request message to encode */ + memset(&pdu, 0, sizeof(pdu)); + pdu.present = X2AP_X2AP_PDU_PR_initiatingMessage; + pdu.choice.initiatingMessage.procedureCode = X2AP_ProcedureCode_id_seNBAdditionPreparation; + pdu.choice.initiatingMessage.criticality = X2AP_Criticality_reject; + pdu.choice.initiatingMessage.value.present = X2AP_InitiatingMessage__value_PR_SeNBAdditionRequest; + out = &pdu.choice.initiatingMessage.value.choice.SeNBAdditionRequest; + + /* id-MeNB-UE-X2AP-ID - mandatory - criticality reject */ + ie = (X2AP_SeNBAdditionRequest_IEs_t *)calloc(1, sizeof(X2AP_SeNBAdditionRequest_IEs_t)); + ie->id = X2AP_ProtocolIE_ID_id_MeNB_UE_X2AP_ID; + ie->criticality = X2AP_Criticality_reject; + ie->value.present = X2AP_ProtocolIE_ID_id_MeNB_UE_X2AP_ID; + ie->value.choice.UE_X2AP_ID = 0; /* TODO */ + ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie); + + /* id-UE-SecurityCapabilities - conditional - criticality reject */ + /* TODO */ + + /* id-SeNBSecurityKey - conditional - criticality reject */ + /* TODO */ + + /* id-SeNBUEAggregateMaximumBitRate - mandatory - criticality reject */ + ie = (X2AP_SeNBAdditionRequest_IEs_t *)calloc(1, sizeof(X2AP_SeNBAdditionRequest_IEs_t)); + ie->id = X2AP_ProtocolIE_ID_id_SeNBUEAggregateMaximumBitRate; + ie->criticality = X2AP_Criticality_reject; + ie->value.present = X2AP_ProtocolIE_ID_id_SeNBUEAggregateMaximumBitRate; + if (asn_imax2INTEGER(&ie->value.choice.UEAggregateMaximumBitRate.uEaggregateMaximumBitRateDownlink, 0) != 0) { /* TODO: right value */ + LOG_E(X2AP, "%s:%d:%s: fatal asn1 error\n", __FILE__, __LINE__, __FUNCTION__); + exit(1); + } + if (asn_imax2INTEGER(&ie->value.choice.UEAggregateMaximumBitRate.uEaggregateMaximumBitRateUplink, 0) != 0) { /* TODO: right value */ + LOG_E(X2AP, "%s:%d:%s: fatal asn1 error\n", __FILE__, __LINE__, __FUNCTION__); + exit(1); + } + ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie); + + /* id-ServingPLMN - optional - criticality ignore */ + /* TODO */ + + /* id-E-RABs-ToBeAdded-List - mandatory - criticality reject */ + ie = (X2AP_SeNBAdditionRequest_IEs_t *)calloc(1, sizeof(X2AP_SeNBAdditionRequest_IEs_t)); + ie->id = X2AP_ProtocolIE_ID_id_SeNBUEAggregateMaximumBitRate; + ie->criticality = X2AP_Criticality_reject; + ie->value.present = X2AP_ProtocolIE_ID_id_E_RABs_ToBeAdded_List; + /* TODO: set value of ie->value.choice.E_RABs_ToBeAdded_List.list */ + ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie); + + /* id-MeNBtoSeNBContainer - mandatory - criticality reject */ + ie = (X2AP_SeNBAdditionRequest_IEs_t *)calloc(1, sizeof(X2AP_SeNBAdditionRequest_IEs_t)); + ie->id = X2AP_ProtocolIE_ID_id_MeNBtoSeNBContainer; + ie->criticality = X2AP_Criticality_reject; + ie->value.present = X2AP_ProtocolIE_ID_id_MeNBtoSeNBContainer; + /* TODO: set value of ie->value.choice.MeNBtoSeNBContainer */ + ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie); + + /* id-CSGMembershipStatus - optional - criticality reject */ + /* TODO */ + + /* id-SeNB-UE-X2AP-ID - optional - criticality reject */ + /* TODO */ + + /* id-SeNB-UE-X2AP-ID-Extension - optional - criticality reject */ + /* TODO */ + + /* id-ExpectedUEBehaviour - optional - criticality ignore */ + /* TODO */ + + /* id-MeNB-UE-X2AP-ID-Extension - optional - criticality reject */ + /* TODO */ + + if (x2ap_eNB_encode_pdu(&pdu, &buffer, &len) < 0) { + X2AP_ERROR("Failed to encode X2AP SeNB Addition Request\n"); + abort(); + return -1; + } + + MSC_LOG_TX_MESSAGE (MSC_X2AP_SRC_ENB, MSC_X2AP_TARGET_ENB, NULL, 0, "0 X2SeNBAdditionRequest/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; +} + +//Panos: +int x2ap_eNB_generate_senb_addition_request_ack (x2ap_eNB_instance_t *instance_p, x2ap_eNB_data_t *x2ap_eNB_data_p, + x2ap_senb_addition_req_ack_t *x2ap_addition_req_ack) +{ + + X2AP_X2AP_PDU_t pdu; + X2AP_SeNBAdditionRequestAcknowledge_t *out; + X2AP_SeNBAdditionRequestAcknowledge_IEs_t *ie; + X2AP_E_RABs_Admitted_ToBeAdded_ItemIEs_t *e_RABS_Admitted_ToBeAdded_ItemIEs; + X2AP_E_RABs_Admitted_ToBeAdded_Item_t *e_RABs_Admitted_ToBeAdded_Item; + int ue_id; + int ue_id_MeNB; + int ue_id_SeNB; + + uint8_t *buffer; + uint32_t len; + int ret = 0; + + DevAssert(instance_p != NULL); + DevAssert(x2ap_eNB_data_p != NULL); + + //Panos: The fact that we have separate IDs here is because the ID for a specific UE might be different + //between the 2 eNBs? + //ue_id = x2ap_addition_req_ack->x2_id_target; //Panos: change name to master_x2... + //id_source = x2ap_id_get_id_source(&instance_p->id_manager, ue_id); + //id_target = ue_id; + + /* Prepare the X2AP addition req. ack. message to encode */ + memset(&pdu, 0, sizeof(pdu)); + pdu.present = X2AP_X2AP_PDU_PR_successfulOutcome; + pdu.choice.successfulOutcome.procedureCode = X2AP_ProcedureCode_id_seNBAdditionPreparation; + //Panos: What does the criticality indicate here? + pdu.choice.successfulOutcome.criticality = X2AP_Criticality_reject; + pdu.choice.successfulOutcome.value.present = X2AP_SuccessfulOutcome__value_PR_SeNBAdditionRequestAcknowledge; + out = &pdu.choice.successfulOutcome.value.choice.SeNBAdditionRequestAcknowledge; + + /* mandatory */ + ie = (X2AP_SeNBAdditionRequestAcknowledge_IEs_t *)calloc(1, sizeof(X2AP_SeNBAdditionRequestAcknowledge_IEs_t)); + ie->id = X2AP_ProtocolIE_ID_id_MeNB_UE_X2AP_ID; + ie->criticality = X2AP_Criticality_reject; + ie->value.present = X2AP_SeNBAdditionRequestAcknowledge_IEs__value_PR_UE_X2AP_ID; + ie->value.choice.UE_X2AP_ID = 0; + ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie); + + /* mandatory */ + ie = (X2AP_SeNBAdditionRequestAcknowledge_IEs_t *)calloc(1, sizeof(X2AP_SeNBAdditionRequestAcknowledge_IEs_t)); + ie->id = X2AP_ProtocolIE_ID_id_SeNB_UE_X2AP_ID; + //Panos: Why for the X2_HANDOVER_REQ_ACK here the criticality is ignore whereas in the specs it is reject? + ie->criticality = X2AP_Criticality_reject; + ie->value.present = X2AP_SeNBAdditionRequestAcknowledge_IEs__value_PR_UE_X2AP_ID_1; + ie->value.choice.UE_X2AP_ID_1 = 0; + ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie); + + /* mandatory */ + ie = (X2AP_SeNBAdditionRequestAcknowledge_IEs_t *)calloc(1, sizeof(X2AP_SeNBAdditionRequestAcknowledge_IEs_t)); + ie->id = X2AP_ProtocolIE_ID_id_E_RABs_Admitted_ToBeAdded_List; + ie->criticality = X2AP_Criticality_ignore; + ie->value.present = X2AP_SeNBAdditionRequestAcknowledge_IEs__value_PR_E_RABs_Admitted_ToBeAdded_List; + + { + // SCG bearers to be added + for (int i=0;i<x2ap_addition_req_ack->nb_sCG_e_rabs_tobeadded;i++) { + e_RABS_Admitted_ToBeAdded_ItemIEs = (X2AP_E_RABs_Admitted_ToBeAdded_ItemIEs_t *)calloc(1,sizeof(X2AP_E_RABs_Admitted_ToBeAdded_ItemIEs_t)); + e_RABS_Admitted_ToBeAdded_ItemIEs->id = X2AP_ProtocolIE_ID_id_E_RABs_Admitted_ToBeAdded_Item; + e_RABS_Admitted_ToBeAdded_ItemIEs->criticality = X2AP_Criticality_ignore; + e_RABS_Admitted_ToBeAdded_ItemIEs->value.present = X2AP_E_RABs_Admitted_ToBeAdded_ItemIEs__value_PR_E_RABs_Admitted_ToBeAdded_Item; + e_RABs_Admitted_ToBeAdded_Item = &e_RABS_Admitted_ToBeAdded_ItemIEs->value.choice.E_RABs_Admitted_ToBeAdded_Item; + { + e_RABs_Admitted_ToBeAdded_Item->choice.sCG_Bearer.e_RAB_ID = x2ap_addition_req_ack->e_sCG_rabs_tobeadded[i].e_rab_id; + INT32_TO_OCTET_STRING(x2ap_addition_req_ack->e_sCG_rabs_tobeadded[i].gtp_teid, &e_RABs_Admitted_ToBeAdded_Item->choice.sCG_Bearer.s1_DL_GTPtunnelEndpoint.gTP_TEID); + + e_RABs_Admitted_ToBeAdded_Item->choice.sCG_Bearer.s1_DL_GTPtunnelEndpoint.transportLayerAddress.size = (uint8_t)(x2ap_addition_req_ack->e_sCG_rabs_tobeadded[i].eNB_addr.length/8); + e_RABs_Admitted_ToBeAdded_Item->choice.sCG_Bearer.s1_DL_GTPtunnelEndpoint.transportLayerAddress.bits_unused = x2ap_addition_req_ack->e_sCG_rabs_tobeadded[i].eNB_addr.length%8; + e_RABs_Admitted_ToBeAdded_Item->choice.sCG_Bearer.s1_DL_GTPtunnelEndpoint.transportLayerAddress.buf = + calloc(1,e_RABs_Admitted_ToBeAdded_Item->choice.sCG_Bearer.s1_DL_GTPtunnelEndpoint.transportLayerAddress.size); + + memcpy (e_RABs_Admitted_ToBeAdded_Item->choice.sCG_Bearer.s1_DL_GTPtunnelEndpoint.transportLayerAddress.buf, + x2ap_addition_req_ack->e_sCG_rabs_tobeadded[i].eNB_addr.buffer, + e_RABs_Admitted_ToBeAdded_Item->choice.sCG_Bearer.s1_DL_GTPtunnelEndpoint.transportLayerAddress.size); + + } + ASN_SEQUENCE_ADD(&ie->value.choice.E_RABs_Admitted_ToBeAdded_List.list, e_RABS_Admitted_ToBeAdded_ItemIEs); + } + + // Split bearers to be added + for (int i=0;i<x2ap_addition_req_ack->nb_split_e_rabs_tobeadded;i++) { + e_RABS_Admitted_ToBeAdded_ItemIEs = (X2AP_E_RABs_Admitted_ToBeAdded_ItemIEs_t *)calloc(1,sizeof(X2AP_E_RABs_Admitted_ToBeAdded_ItemIEs_t)); + e_RABS_Admitted_ToBeAdded_ItemIEs->id = X2AP_ProtocolIE_ID_id_E_RABs_Admitted_ToBeAdded_Item; + e_RABS_Admitted_ToBeAdded_ItemIEs->criticality = X2AP_Criticality_ignore; + e_RABS_Admitted_ToBeAdded_ItemIEs->value.present = X2AP_E_RABs_Admitted_ToBeAdded_ItemIEs__value_PR_E_RABs_Admitted_ToBeAdded_Item; + e_RABs_Admitted_ToBeAdded_Item = &e_RABS_Admitted_ToBeAdded_ItemIEs->value.choice.E_RABs_Admitted_ToBeAdded_Item; + { + e_RABs_Admitted_ToBeAdded_Item->choice.split_Bearer.e_RAB_ID = x2ap_addition_req_ack->e_split_rabs_tobeadded[i].e_rab_id; + INT32_TO_OCTET_STRING(x2ap_addition_req_ack->e_split_rabs_tobeadded[i].gtp_teid, &e_RABs_Admitted_ToBeAdded_Item->choice.split_Bearer.seNB_GTPtunnelEndpoint.gTP_TEID); + + e_RABs_Admitted_ToBeAdded_Item->choice.split_Bearer.seNB_GTPtunnelEndpoint.transportLayerAddress.size = (uint8_t)(x2ap_addition_req_ack->e_split_rabs_tobeadded[i].eNB_addr.length/8); + e_RABs_Admitted_ToBeAdded_Item->choice.split_Bearer.seNB_GTPtunnelEndpoint.transportLayerAddress.bits_unused = x2ap_addition_req_ack->e_split_rabs_tobeadded[i].eNB_addr.length%8; + e_RABs_Admitted_ToBeAdded_Item->choice.split_Bearer.seNB_GTPtunnelEndpoint.transportLayerAddress.buf = + calloc(1,e_RABs_Admitted_ToBeAdded_Item->choice.split_Bearer.seNB_GTPtunnelEndpoint.transportLayerAddress.size); + + memcpy (e_RABs_Admitted_ToBeAdded_Item->choice.split_Bearer.seNB_GTPtunnelEndpoint.transportLayerAddress.buf, + x2ap_addition_req_ack->e_split_rabs_tobeadded[i].eNB_addr.buffer, + e_RABs_Admitted_ToBeAdded_Item->choice.split_Bearer.seNB_GTPtunnelEndpoint.transportLayerAddress.size); + + } + ASN_SEQUENCE_ADD(&ie->value.choice.E_RABs_Admitted_ToBeAdded_List.list, e_RABS_Admitted_ToBeAdded_ItemIEs); + } + + } + + ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie); + + /* mandatory */ + ie = (X2AP_SeNBAdditionRequestAcknowledge_IEs_t *)calloc(1, sizeof(X2AP_SeNBAdditionRequestAcknowledge_IEs_t)); + ie->id = X2AP_ProtocolIE_ID_id_SeNBtoMeNBContainer; + ie->criticality = X2AP_Criticality_reject; + ie->value.present = X2AP_SeNBAdditionRequestAcknowledge_IEs__value_PR_SeNBtoMeNBContainer; + + OCTET_STRING_fromBuf(&ie->value.choice.SeNBtoMeNBContainer, (char*) x2ap_addition_req_ack->rrc_buffer, x2ap_addition_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 SeNB addition response\n"); + abort(); + return -1; + } + + x2ap_eNB_itti_send_sctp_data_req(instance_p->instance, x2ap_eNB_data_p->assoc_id, buffer, len, 1); + + return ret; +} + +/*setup request message from an eNB to a gNB*/ +int x2ap_eNB_generate_ENDC_x2_setup_request( + x2ap_eNB_instance_t *instance_p, x2ap_eNB_data_t *x2ap_eNB_data_p) +{ + printf("In x2ap_eNB_generate_ENDC_x2_setup_request \n"); + X2AP_X2AP_PDU_t pdu; + X2AP_ENDCX2SetupRequest_t *out; + X2AP_ENDCX2SetupRequest_IEs_t *ie; + X2AP_ENB_ENDCX2SetupReqIEs_t *ie_ENB_ENDC; + X2AP_PLMN_Identity_t *plmn; + ServedEUTRAcellsENDCX2ManagementList__Member *servedCellMember; + + 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; + + /* 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_endcX2Setup; + pdu.choice.initiatingMessage.criticality = X2AP_Criticality_reject; + pdu.choice.initiatingMessage.value.present = X2AP_InitiatingMessage__value_PR_ENDCX2SetupRequest; + out = &pdu.choice.initiatingMessage.value.choice.ENDCX2SetupRequest; + + ie = (X2AP_ENDCX2SetupRequest_IEs_t *)calloc(1, sizeof(X2AP_ENDCX2SetupRequest_IEs_t)); + ie->id = X2AP_ProtocolIE_ID_id_InitiatingNodeType_EndcX2Setup; + ie->value.present = X2AP_ENDCX2SetupRequest_IEs__value_PR_InitiatingNodeType_EndcX2Setup; + ie->value.choice.InitiatingNodeType_EndcX2Setup.present = X2AP_InitiatingNodeType_EndcX2Setup_PR_init_eNB; + + ie_ENB_ENDC = (X2AP_ENB_ENDCX2SetupReqIEs_t *)calloc(1, sizeof(X2AP_ENB_ENDCX2SetupReqIEs_t)); + ie_ENB_ENDC->id = X2AP_ProtocolIE_ID_id_GlobalENB_ID; + ie_ENB_ENDC->criticality = X2AP_Criticality_reject; + ie_ENB_ENDC->value.present = X2AP_ENB_ENDCX2SetupReqIEs__value_PR_GlobalENB_ID; + ie_ENB_ENDC->value.choice.GlobalENB_ID.eNB_ID.present = X2AP_ENB_ID_PR_macro_eNB_ID; + MACRO_ENB_ID_TO_BIT_STRING(instance_p->eNB_id, + &ie_ENB_ENDC->value.choice.GlobalENB_ID.eNB_ID.choice.macro_eNB_ID); + MCC_MNC_TO_PLMNID(instance_p->mcc, instance_p->mnc, instance_p->mnc_digit_length, + &ie_ENB_ENDC->value.choice.GlobalENB_ID.pLMN_Identity); + + ASN_SEQUENCE_ADD(&ie->value.choice.InitiatingNodeType_EndcX2Setup.choice.init_eNB.list, ie_ENB_ENDC); + + ie_ENB_ENDC = (X2AP_ENB_ENDCX2SetupReqIEs_t *)calloc(1, sizeof(X2AP_ENB_ENDCX2SetupReqIEs_t)); + ie_ENB_ENDC->id = X2AP_ProtocolIE_ID_id_ServedEUTRAcellsENDCX2ManagementList; + ie_ENB_ENDC->criticality = X2AP_Criticality_reject; + ie_ENB_ENDC->value.present = X2AP_ENB_ENDCX2SetupReqIEs__value_PR_ServedEUTRAcellsENDCX2ManagementList; + + { + for (int i = 0; i<instance_p->num_cc; i++){ + servedCellMember = (ServedEUTRAcellsENDCX2ManagementList__Member *)calloc(1,sizeof(ServedEUTRAcellsENDCX2ManagementList__Member)); + { + servedCellMember->servedEUTRACellInfo.pCI = instance_p->Nid_cell[i]; + + MCC_MNC_TO_PLMNID(instance_p->mcc, instance_p->mnc, instance_p->mnc_digit_length, + &servedCellMember->servedEUTRACellInfo.cellId.pLMN_Identity); + MACRO_ENB_ID_TO_CELL_IDENTITY(instance_p->eNB_id,0, + &servedCellMember->servedEUTRACellInfo.cellId.eUTRANcellIdentifier); + + INT16_TO_OCTET_STRING(instance_p->tac, &servedCellMember->servedEUTRACellInfo.tAC); + plmn = (X2AP_PLMN_Identity_t *)calloc(1,sizeof(X2AP_PLMN_Identity_t)); + { + MCC_MNC_TO_PLMNID(instance_p->mcc, instance_p->mnc, instance_p->mnc_digit_length, plmn); + ASN_SEQUENCE_ADD(&servedCellMember->servedEUTRACellInfo.broadcastPLMNs.list, plmn); + } + + if (instance_p->frame_type[i] == FDD) { + servedCellMember->servedEUTRACellInfo.eUTRA_Mode_Info.present = X2AP_EUTRA_Mode_Info_PR_fDD; + servedCellMember->servedEUTRACellInfo.eUTRA_Mode_Info.choice.fDD.dL_EARFCN = instance_p->fdd_earfcn_DL[i]; + servedCellMember->servedEUTRACellInfo.eUTRA_Mode_Info.choice.fDD.uL_EARFCN = instance_p->fdd_earfcn_UL[i]; + switch (instance_p->N_RB_DL[i]) { + case 6: + servedCellMember->servedEUTRACellInfo.eUTRA_Mode_Info.choice.fDD.uL_Transmission_Bandwidth = X2AP_Transmission_Bandwidth_bw6; + servedCellMember->servedEUTRACellInfo.eUTRA_Mode_Info.choice.fDD.dL_Transmission_Bandwidth = X2AP_Transmission_Bandwidth_bw6; + break; + case 15: + servedCellMember->servedEUTRACellInfo.eUTRA_Mode_Info.choice.fDD.uL_Transmission_Bandwidth = X2AP_Transmission_Bandwidth_bw15; + servedCellMember->servedEUTRACellInfo.eUTRA_Mode_Info.choice.fDD.dL_Transmission_Bandwidth = X2AP_Transmission_Bandwidth_bw15; + break; + case 25: + servedCellMember->servedEUTRACellInfo.eUTRA_Mode_Info.choice.fDD.uL_Transmission_Bandwidth = X2AP_Transmission_Bandwidth_bw25; + servedCellMember->servedEUTRACellInfo.eUTRA_Mode_Info.choice.fDD.dL_Transmission_Bandwidth = X2AP_Transmission_Bandwidth_bw25; + break; + case 50: + servedCellMember->servedEUTRACellInfo.eUTRA_Mode_Info.choice.fDD.uL_Transmission_Bandwidth = X2AP_Transmission_Bandwidth_bw50; + servedCellMember->servedEUTRACellInfo.eUTRA_Mode_Info.choice.fDD.dL_Transmission_Bandwidth = X2AP_Transmission_Bandwidth_bw50; + break; + case 75: + servedCellMember->servedEUTRACellInfo.eUTRA_Mode_Info.choice.fDD.uL_Transmission_Bandwidth = X2AP_Transmission_Bandwidth_bw75; + servedCellMember->servedEUTRACellInfo.eUTRA_Mode_Info.choice.fDD.dL_Transmission_Bandwidth = X2AP_Transmission_Bandwidth_bw75; + break; + case 100: + servedCellMember->servedEUTRACellInfo.eUTRA_Mode_Info.choice.fDD.uL_Transmission_Bandwidth = X2AP_Transmission_Bandwidth_bw100; + servedCellMember->servedEUTRACellInfo.eUTRA_Mode_Info.choice.fDD.dL_Transmission_Bandwidth = X2AP_Transmission_Bandwidth_bw100; + break; + default: + AssertFatal(0,"Failed: Check value for N_RB_DL/N_RB_UL"); + break; + } + } + else { + AssertFatal(0,"X2Setuprequest not supported for TDD!"); + } + } + ASN_SEQUENCE_ADD(&ie_ENB_ENDC->value.choice.ServedEUTRAcellsENDCX2ManagementList.list, servedCellMember); + } + } + ASN_SEQUENCE_ADD(&ie->value.choice.InitiatingNodeType_EndcX2Setup.choice.init_eNB.list, ie_ENB_ENDC); + + + ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie); + + if (x2ap_eNB_encode_pdu(&pdu, &buffer, &len) < 0) { + X2AP_ERROR("Failed to encode X2 setup response\n"); + return -1; + } + + MSC_LOG_TX_MESSAGE (MSC_X2AP_SRC_ENB, MSC_X2AP_TARGET_ENB, NULL, 0, "0 X2Setup/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, 0); + + return ret; +} + + +/*setup request message from an eNB to a gNB*/ +int x2ap_gNB_generate_ENDC_x2_setup_response( + x2ap_eNB_instance_t *instance_p, x2ap_eNB_data_t *x2ap_eNB_data_p) +{ + X2AP_INFO("In x2ap_gNB_generate_ENDC_x2_setup_response ()!\n"); + X2AP_X2AP_PDU_t pdu; + X2AP_ENDCX2SetupResponse_t *out; + X2AP_ENDCX2SetupResponse_IEs_t *ie; + X2AP_En_gNB_ENDCX2SetupReqAckIEs_t *ie_GNB_ENDC; + X2AP_PLMN_Identity_t *plmn; + ServedNRcellsENDCX2ManagementList__Member *servedCellMember; + + 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; + + /* Prepare the X2AP message to encode */ + memset(&pdu, 0, sizeof(pdu)); + pdu.present = X2AP_X2AP_PDU_PR_successfulOutcome; + pdu.choice.successfulOutcome.procedureCode = X2AP_ProcedureCode_id_endcX2Setup; + pdu.choice.successfulOutcome.criticality = X2AP_Criticality_reject; + pdu.choice.successfulOutcome.value.present = X2AP_SuccessfulOutcome__value_PR_ENDCX2SetupResponse; + out = &pdu.choice.successfulOutcome.value.choice.ENDCX2SetupResponse; + + ie = (X2AP_ENDCX2SetupResponse_IEs_t *)calloc(1, sizeof(X2AP_ENDCX2SetupResponse_IEs_t)); + ie->id = X2AP_ProtocolIE_ID_id_RespondingNodeType_EndcX2Setup; + ie->value.present = X2AP_ENDCX2SetupResponse_IEs__value_PR_RespondingNodeType_EndcX2Setup; + ie->value.choice.RespondingNodeType_EndcX2Setup.present = X2AP_RespondingNodeType_EndcX2Setup_PR_respond_en_gNB; + + ie_GNB_ENDC = (X2AP_En_gNB_ENDCX2SetupReqAckIEs_t *)calloc(1, sizeof(X2AP_En_gNB_ENDCX2SetupReqAckIEs_t)); + ie_GNB_ENDC->id = X2AP_ProtocolIE_ID_id_Globalen_gNB_ID; + ie_GNB_ENDC->criticality = X2AP_Criticality_reject; + ie_GNB_ENDC->value.present = X2AP_En_gNB_ENDCX2SetupReqAckIEs__value_PR_GlobalGNB_ID; + ie_GNB_ENDC->value.choice.GlobalGNB_ID.gNB_ID.present = X2AP_GNB_ID_PR_gNB_ID; + + INT32_TO_OCTET_STRING(instance_p->eNB_id, + &ie_GNB_ENDC->value.choice.GlobalGNB_ID.gNB_ID.choice.gNB_ID); + + X2AP_INFO("%d -> %02x%02x%02x\n", instance_p->eNB_id, + ie_GNB_ENDC->value.choice.GlobalGNB_ID.gNB_ID.choice.gNB_ID.buf[0], + ie_GNB_ENDC->value.choice.GlobalGNB_ID.gNB_ID.choice.gNB_ID.buf[1], + ie_GNB_ENDC->value.choice.GlobalGNB_ID.gNB_ID.choice.gNB_ID.buf[2]); + + MCC_MNC_TO_PLMNID(instance_p->mcc, instance_p->mnc, instance_p->mnc_digit_length, + &ie_GNB_ENDC->value.choice.GlobalGNB_ID.pLMN_Identity); + + ASN_SEQUENCE_ADD(&ie->value.choice.RespondingNodeType_EndcX2Setup.choice.respond_en_gNB.list, ie_GNB_ENDC); + + ie_GNB_ENDC = (X2AP_En_gNB_ENDCX2SetupReqAckIEs_t *)calloc(1, sizeof(X2AP_En_gNB_ENDCX2SetupReqAckIEs_t)); + ie_GNB_ENDC->id = X2AP_ProtocolIE_ID_id_ServedNRcellsENDCX2ManagementList; + ie_GNB_ENDC->criticality = X2AP_Criticality_reject; + ie_GNB_ENDC->value.present = X2AP_En_gNB_ENDCX2SetupReqAckIEs__value_PR_ServedNRcellsENDCX2ManagementList; + + { + for (int i = 0; i<instance_p->num_cc; i++){ + servedCellMember = (ServedNRcellsENDCX2ManagementList__Member *)calloc(1,sizeof(ServedNRcellsENDCX2ManagementList__Member)); + { + servedCellMember->servedNRCellInfo.nrpCI = instance_p->Nid_cell[i]; + + MCC_MNC_TO_PLMNID(instance_p->mcc, instance_p->mnc, instance_p->mnc_digit_length, + &servedCellMember->servedNRCellInfo.nrCellID.pLMN_Identity); + NR_CELL_ID_TO_BIT_STRING(instance_p->eNB_id, + &servedCellMember->servedNRCellInfo.nrCellID.nRcellIdentifier); + servedCellMember->servedNRCellInfo.fiveGS_TAC = calloc(1, sizeof(X2AP_FiveGS_TAC_t)); + if (servedCellMember->servedNRCellInfo.fiveGS_TAC == NULL) + exit(1); + NR_FIVEGS_TAC_ID_TO_BIT_STRING(instance_p->tac, servedCellMember->servedNRCellInfo.fiveGS_TAC); + + X2AP_INFO("TAC: %d -> %02x%02x%02x\n", instance_p->tac, + servedCellMember->servedNRCellInfo.fiveGS_TAC->buf[0], + servedCellMember->servedNRCellInfo.fiveGS_TAC->buf[1], + servedCellMember->servedNRCellInfo.fiveGS_TAC->buf[2]); + + plmn = (X2AP_PLMN_Identity_t *)calloc(1,sizeof(X2AP_PLMN_Identity_t)); + { + MCC_MNC_TO_PLMNID(instance_p->mcc, instance_p->mnc, instance_p->mnc_digit_length, plmn); + ASN_SEQUENCE_ADD(&servedCellMember->servedNRCellInfo.broadcastPLMNs.list, plmn); + } + + if (instance_p->frame_type[i] == TDD) { // Panos: Remember to change that to TDD + servedCellMember->servedNRCellInfo.nrModeInfo.present = X2AP_ServedNRCell_Information__nrModeInfo_PR_tdd; + servedCellMember->servedNRCellInfo.nrModeInfo.choice.tdd.nRFreqInfo.nRARFCN = 0; //instance_p->tdd_nRARFCN[i]; + /*Missing addition of Frequency Band List item here, can't find it... */ + switch (instance_p->N_RB_DL[i]) { + case 50: + //This is not correct. Just to be able to test X2 only using an eNB instead of gNB + servedCellMember->servedNRCellInfo.nrModeInfo.choice.tdd.nR_TxBW.nRNRB = X2AP_NRNRB_nrb51; + break; + case 93 : + servedCellMember->servedNRCellInfo.nrModeInfo.choice.tdd.nR_TxBW.nRNRB = X2AP_NRNRB_nrb93; + break; + case 106: + servedCellMember->servedNRCellInfo.nrModeInfo.choice.tdd.nR_TxBW.nRNRB = X2AP_NRNRB_nrb106; + break; + case 121: + servedCellMember->servedNRCellInfo.nrModeInfo.choice.tdd.nR_TxBW.nRNRB = X2AP_NRNRB_nrb121; + break; + + /*More cases to be added */ + + default: + AssertFatal(0,"Failed: Check value for N_RB_DL/N_RB_UL"); + break; + } + + instance_p->nr_SCS[i] = 30; // Hardcoded for now. Normally this should originate from the gNB config file + switch (instance_p->nr_SCS[i]) { + case 15: + servedCellMember->servedNRCellInfo.nrModeInfo.choice.tdd.nR_TxBW.nRSCS = X2AP_NRSCS_scs15; + break; + case 30: + servedCellMember->servedNRCellInfo.nrModeInfo.choice.tdd.nR_TxBW.nRSCS = X2AP_NRSCS_scs30; + break; + case 60: + servedCellMember->servedNRCellInfo.nrModeInfo.choice.tdd.nR_TxBW.nRSCS = X2AP_NRSCS_scs60; + break; + case 120: + servedCellMember->servedNRCellInfo.nrModeInfo.choice.tdd.nR_TxBW.nRSCS = X2AP_NRSCS_scs120; + break; + default: + AssertFatal(0,"Failed: Check value for nr_SCS"); + break; + } + } + else { + AssertFatal(0,"nr_X2Setupresponse not supported for FDD!"); + } + /*Don't know where to extract the value of measurementTimingConfiguration from. Set it to 0 for now */ + INT8_TO_OCTET_STRING(0, &servedCellMember->servedNRCellInfo.measurementTimingConfiguration); + + } + ASN_SEQUENCE_ADD(&ie_GNB_ENDC->value.choice.ServedNRcellsENDCX2ManagementList.list, servedCellMember); + } + } + ASN_SEQUENCE_ADD(&ie->value.choice.RespondingNodeType_EndcX2Setup.choice.respond_en_gNB.list, ie_GNB_ENDC); + + + ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie); + + if (x2ap_eNB_encode_pdu(&pdu, &buffer, &len) < 0) { + X2AP_ERROR("Failed to encode X2 setup request\n"); + return -1; + } + + MSC_LOG_TX_MESSAGE (MSC_X2AP_SRC_ENB, MSC_X2AP_TARGET_ENB, NULL, 0, "0 X2Setup/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, 0); + + return ret; +} + diff --git a/openair2/X2AP/x2ap_eNB_generate_messages.h b/openair2/X2AP/x2ap_eNB_generate_messages.h index 1fcdf31f121e033f08e08b16e13af5bf044170e2..6b0cd9c2da21907efca3c48cac62af5adefc4d91 100644 --- a/openair2/X2AP/x2ap_eNB_generate_messages.h +++ b/openair2/X2AP/x2ap_eNB_generate_messages.h @@ -60,4 +60,14 @@ int x2ap_eNB_generate_x2_handover_cancel (x2ap_eNB_instance_t *instance_p, x2ap_ int x2_ue_id, x2ap_handover_cancel_cause_t cause); +int x2ap_eNB_generate_senb_addition_request (x2ap_eNB_instance_t *instance_p, x2ap_eNB_data_t *x2ap_eNB_data_p + /* TODO: pass needed parameters */); + +int x2ap_eNB_generate_senb_addition_request_ack (x2ap_eNB_instance_t *instance_p, x2ap_eNB_data_t *x2ap_eNB_data_p, + x2ap_senb_addition_req_ack_t *x2ap_addition_req_ack); + +int x2ap_eNB_generate_ENDC_x2_setup_request(x2ap_eNB_instance_t *instance_p, x2ap_eNB_data_t *x2ap_eNB_data_p); + +int x2ap_gNB_generate_ENDC_x2_setup_response( x2ap_eNB_instance_t *instance_p, x2ap_eNB_data_t *x2ap_eNB_data_p); + #endif /* X2AP_ENB_GENERATE_MESSAGES_H_ */ diff --git a/openair2/X2AP/x2ap_eNB_handler.c b/openair2/X2AP/x2ap_eNB_handler.c index 33fd9c5295fb8ad890f297a4de96bb564f1f4b00..8e702a7e2e36b8398308aa98c91276f163f17347 100644 --- a/openair2/X2AP/x2ap_eNB_handler.c +++ b/openair2/X2AP/x2ap_eNB_handler.c @@ -84,6 +84,37 @@ int x2ap_eNB_handle_handover_cancel (instance_t instance, uint32_t stream, X2AP_X2AP_PDU_t *pdu); +static +int x2ap_eNB_handle_senb_addition_request (instance_t instance, + uint32_t assoc_id, + uint32_t stream, + X2AP_X2AP_PDU_t *pdu); + + +static +int x2ap_eNB_handle_senb_addition_request_ack (instance_t instance, + uint32_t assoc_id, + uint32_t stream, + X2AP_X2AP_PDU_t *pdu); + +static +int x2ap_eNB_handle_senb_addition_request_reject (instance_t instance, + uint32_t assoc_id, + uint32_t stream, + X2AP_X2AP_PDU_t *pdu); + +int x2ap_gNB_handle_ENDC_x2_setup_request(instance_t instance, + uint32_t assoc_id, + uint32_t stream, + X2AP_X2AP_PDU_t *pdu); + +int +x2ap_gNB_handle_ENDC_x2_setup_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] = { { x2ap_eNB_handle_handover_preparation, x2ap_eNB_handle_handover_response, 0 }, /* handoverPreparation */ @@ -105,14 +136,27 @@ x2ap_message_decoded_callback x2ap_messages_callback[][3] = { { 0, 0, 0 }, /* x2Release */ { 0, 0, 0 }, /* x2APMessageTransfer */ { 0, 0, 0 }, /* x2Removal */ - { 0, 0, 0 }, /* seNBAdditionPreparation */ + { x2ap_eNB_handle_senb_addition_request, x2ap_eNB_handle_senb_addition_request_ack, x2ap_eNB_handle_senb_addition_request_reject }, /* seNBAdditionPreparation */ { 0, 0, 0 }, /* seNBReconfigurationCompletion */ { 0, 0, 0 }, /* meNBinitiatedSeNBModificationPreparation */ { 0, 0, 0 }, /* seNBinitiatedSeNBModification */ { 0, 0, 0 }, /* meNBinitiatedSeNBRelease */ { 0, 0, 0 }, /* seNBinitiatedSeNBRelease */ { 0, 0, 0 }, /* seNBCounterCheck */ - { 0, 0, 0 } /* retrieveUEContext */ + { 0, 0, 0 }, /* retrieveUEContext */ + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { x2ap_gNB_handle_ENDC_x2_setup_request, x2ap_gNB_handle_ENDC_x2_setup_response, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 } }; char *x2ap_direction2String(int x2ap_dir) { @@ -414,6 +458,7 @@ x2ap_eNB_handle_x2_setup_request(instance_t instance, return x2ap_eNB_generate_x2_setup_response(instance_p, x2ap_eNB_data); } + static int x2ap_eNB_handle_x2_setup_response(instance_t instance, uint32_t assoc_id, @@ -1073,3 +1118,508 @@ int x2ap_eNB_handle_handover_cancel (instance_t instance, return 0; } + + +static +int x2ap_eNB_handle_senb_addition_request (instance_t instance, + uint32_t assoc_id, + uint32_t stream, + X2AP_X2AP_PDU_t *pdu) +{ + + X2AP_SeNBAdditionRequest_t *x2SeNBAdditionRequest; + X2AP_SeNBAdditionRequest_IEs_t *ie; + + X2AP_E_RABs_ToBeAdded_ItemIEs_t *e_RABS_ToBeAdded_ItemIEs; + X2AP_E_RABs_ToBeAdded_Item_t *e_RABs_ToBeAdded_Item; + + x2ap_eNB_instance_t *instance_p; + x2ap_eNB_data_t *x2ap_eNB_data; + MessageDef *msg; + int ue_id; + + DevAssert (pdu != NULL); + x2SeNBAdditionRequest = &pdu->choice.initiatingMessage.value.choice.SeNBAdditionRequest; + + if (stream == 0) { + X2AP_ERROR ("Received new x2 senb addition request on stream == 0\n"); + /* TODO: send a x2 failure response */ + return 0; + } + + X2AP_DEBUG ("Received a new X2 senb addition request\n"); + + //Panos: Do we need this for this message? Where is the x2ap_eNB_data used? + /*x2ap_eNB_data = x2ap_get_eNB(NULL, assoc_id, 0); + DevAssert(x2ap_eNB_data != NULL);*/ + + instance_p = x2ap_eNB_get_instance(instance); + DevAssert(instance_p != NULL); + + msg = itti_alloc_new_message(TASK_X2AP, X2AP_SENB_ADDITION_REQ); + + /*MeNB_UE_X2AP_ID */ + X2AP_FIND_PROTOCOLIE_BY_ID(X2AP_SeNBAdditionRequest_IEs_t, ie, x2SeNBAdditionRequest, + 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; + } + + //Panos: Here not sure which UE ID should be allocated to be forwarded to RRC... + /* allocate a new X2AP UE ID */ + /*ue_id = x2ap_allocate_new_id(&instance_p->id_manager); + if (ue_id == -1) { + X2AP_ERROR("could not allocate a new X2AP UE ID\n"); + exit(1); + } + + x2ap_set_ids(&instance_p->id_manager, ue_id, 0, ie->value.choice.UE_X2AP_ID, ue_id); + x2ap_id_set_state(&instance_p->id_manager, ue_id, X2ID_STATE_TARGET);*/ + + //For now we hardcode both MeNB and SeNB UE IDs values + X2AP_SENB_ADDITION_REQ(msg).x2_MeNB_UE_id = 0; + + /* UESecurityCapabilities is specific to SCGBearerOption.*/ + X2AP_FIND_PROTOCOLIE_BY_ID(X2AP_SeNBAdditionRequest_IEs_t, ie, x2SeNBAdditionRequest, + X2AP_ProtocolIE_ID_id_UE_SecurityCapabilities, true); + + if (ie == NULL ) { + X2AP_ERROR("%s %d: ie is a NULL pointer \n",__FILE__,__LINE__); + return -1; + } + + + X2AP_SENB_ADDITION_REQ(msg).UE_security_capabilities.encryption_algorithms = + BIT_STRING_to_uint16(&ie->value.choice.UESecurityCapabilities.encryptionAlgorithms); + X2AP_SENB_ADDITION_REQ(msg).UE_security_capabilities.integrity_algorithms = + BIT_STRING_to_uint16(&ie->value.choice.UESecurityCapabilities.integrityProtectionAlgorithms); + + + /* SeNBSecurityKey is specific to SCGBearerOption.*/ + X2AP_FIND_PROTOCOLIE_BY_ID(X2AP_SeNBAdditionRequest_IEs_t, ie, x2SeNBAdditionRequest, + X2AP_ProtocolIE_ID_id_SeNBSecurityKey, true); + + if (ie == NULL ) { + X2AP_ERROR("%s %d: ie is a NULL pointer \n",__FILE__,__LINE__); + return -1; + } + + memcpy(X2AP_SENB_ADDITION_REQ(msg).SeNB_security_key, + &ie->value.choice.SeNBSecurityKey.buf, + ie->value.choice.SeNBSecurityKey.size); + + /* SeNB to UE Aggregate Maximum Bit Rate */ + //Panos: SeNBUEAggregateMaximumBitRate: should it be added? It is not active in handover_req + /*X2AP_FIND_PROTOCOLIE_BY_ID(X2AP_SeNBAdditionRequest_IEs_t, ie, x2SeNBAdditionRequest, + X2AP_ProtocolIE_ID_id_SeNBUEAggregateMaximumBitRate, true);*/ + + + /* E-RABs_To Be Added List */ + X2AP_FIND_PROTOCOLIE_BY_ID(X2AP_SeNBAdditionRequest_IEs_t, ie, x2SeNBAdditionRequest, + X2AP_ProtocolIE_ID_id_E_RABs_ToBeAdded_List, true); + + if (ie == NULL ) { + X2AP_ERROR("%s %d: ie is a NULL pointer \n",__FILE__,__LINE__); + return -1; + } + + if (ie->value.choice.E_RABs_ToBeAdded_List.list.count > 0) { + + X2AP_SENB_ADDITION_REQ(msg).total_nb_e_rabs_tobeadded = ie->value.choice.E_RABs_ToBeAdded_List.list.count; + int sCG_Bearers_cnt = 0; + int split_Bearers_cnt = 0; + for (int i=0;i<ie->value.choice.E_RABs_ToBeAdded_List.list.count;i++) { + e_RABS_ToBeAdded_ItemIEs = (X2AP_E_RABs_ToBeAdded_ItemIEs_t *) ie->value.choice.E_RABs_ToBeAdded_List.list. array[i]; + e_RABs_ToBeAdded_Item = &e_RABS_ToBeAdded_ItemIEs->value.choice.E_RABs_ToBeAdded_Item; + + if(e_RABs_ToBeAdded_Item->present == X2AP_E_RABs_ToBeAdded_Item_PR_sCG_Bearer){ + + X2AP_SENB_ADDITION_REQ(msg).e_sCG_rabs_tobeadded[sCG_Bearers_cnt].e_rab_id = e_RABs_ToBeAdded_Item->choice.sCG_Bearer.e_RAB_ID; + + memcpy(X2AP_SENB_ADDITION_REQ(msg).e_sCG_rabs_tobeadded[sCG_Bearers_cnt].eNB_addr.buffer, + e_RABs_ToBeAdded_Item->choice.sCG_Bearer.s1_UL_GTPtunnelEndpoint.transportLayerAddress.buf, + e_RABs_ToBeAdded_Item->choice.sCG_Bearer.s1_UL_GTPtunnelEndpoint.transportLayerAddress.size); + + X2AP_SENB_ADDITION_REQ(msg).e_sCG_rabs_tobeadded[sCG_Bearers_cnt].eNB_addr.length = + e_RABs_ToBeAdded_Item->choice.sCG_Bearer.s1_UL_GTPtunnelEndpoint.transportLayerAddress.size * 8 - e_RABs_ToBeAdded_Item->choice.sCG_Bearer.s1_UL_GTPtunnelEndpoint.transportLayerAddress.bits_unused; + + OCTET_STRING_TO_INT32(&e_RABs_ToBeAdded_Item->choice.sCG_Bearer.s1_UL_GTPtunnelEndpoint.gTP_TEID, + X2AP_SENB_ADDITION_REQ(msg).e_sCG_rabs_tobeadded[sCG_Bearers_cnt].gtp_teid); + + X2AP_SENB_ADDITION_REQ(msg).e_sCG_rab_param[sCG_Bearers_cnt].qos.qci = e_RABs_ToBeAdded_Item->choice.sCG_Bearer.e_RAB_Level_QoS_Parameters.qCI; + X2AP_SENB_ADDITION_REQ(msg).e_sCG_rab_param[sCG_Bearers_cnt].qos.allocation_retention_priority.priority_level = e_RABs_ToBeAdded_Item->choice.sCG_Bearer.e_RAB_Level_QoS_Parameters.allocationAndRetentionPriority.priorityLevel; + X2AP_SENB_ADDITION_REQ(msg).e_sCG_rab_param[sCG_Bearers_cnt].qos.allocation_retention_priority.pre_emp_capability = e_RABs_ToBeAdded_Item->choice.sCG_Bearer.e_RAB_Level_QoS_Parameters.allocationAndRetentionPriority.pre_emptionCapability; + X2AP_SENB_ADDITION_REQ(msg).e_sCG_rab_param[sCG_Bearers_cnt].qos.allocation_retention_priority.pre_emp_vulnerability = e_RABs_ToBeAdded_Item->choice.sCG_Bearer.e_RAB_Level_QoS_Parameters.allocationAndRetentionPriority.pre_emptionVulnerability; + sCG_Bearers_cnt++; + } + else if(e_RABs_ToBeAdded_Item->present == X2AP_E_RABs_ToBeAdded_Item_PR_split_Bearer){ + X2AP_SENB_ADDITION_REQ(msg).e_split_rabs_tobeadded[split_Bearers_cnt].e_rab_id = e_RABs_ToBeAdded_Item->choice.split_Bearer.e_RAB_ID; + + memcpy(X2AP_SENB_ADDITION_REQ(msg).e_split_rabs_tobeadded[split_Bearers_cnt].eNB_addr.buffer, + e_RABs_ToBeAdded_Item->choice.split_Bearer.meNB_GTPtunnelEndpoint.transportLayerAddress.buf, + e_RABs_ToBeAdded_Item->choice.split_Bearer.meNB_GTPtunnelEndpoint.transportLayerAddress.size); + + X2AP_SENB_ADDITION_REQ(msg).e_split_rabs_tobeadded[split_Bearers_cnt].eNB_addr.length = + e_RABs_ToBeAdded_Item->choice.split_Bearer.meNB_GTPtunnelEndpoint.transportLayerAddress.size * 8 - e_RABs_ToBeAdded_Item->choice.split_Bearer.meNB_GTPtunnelEndpoint.transportLayerAddress.bits_unused; + + OCTET_STRING_TO_INT32(&e_RABs_ToBeAdded_Item->choice.split_Bearer.meNB_GTPtunnelEndpoint.gTP_TEID, + X2AP_SENB_ADDITION_REQ(msg).e_split_rabs_tobeadded[split_Bearers_cnt].gtp_teid); + + X2AP_SENB_ADDITION_REQ(msg).e_split_rab_param[split_Bearers_cnt].qos.qci = e_RABs_ToBeAdded_Item->choice.split_Bearer.e_RAB_Level_QoS_Parameters.qCI; + X2AP_SENB_ADDITION_REQ(msg).e_split_rab_param[split_Bearers_cnt].qos.allocation_retention_priority.priority_level = e_RABs_ToBeAdded_Item->choice.split_Bearer.e_RAB_Level_QoS_Parameters.allocationAndRetentionPriority.priorityLevel; + X2AP_SENB_ADDITION_REQ(msg).e_split_rab_param[split_Bearers_cnt].qos.allocation_retention_priority.pre_emp_capability = e_RABs_ToBeAdded_Item->choice.split_Bearer.e_RAB_Level_QoS_Parameters.allocationAndRetentionPriority.pre_emptionCapability; + X2AP_SENB_ADDITION_REQ(msg).e_split_rab_param[split_Bearers_cnt].qos.allocation_retention_priority.pre_emp_vulnerability = e_RABs_ToBeAdded_Item->choice.split_Bearer.e_RAB_Level_QoS_Parameters.allocationAndRetentionPriority.pre_emptionVulnerability; + split_Bearers_cnt++; + } + } + + } + else { + X2AP_ERROR ("Can't decode the e_RABs_ToBeAdded_List \n"); + } + + /*MeNB to SeNB Container */ + X2AP_FIND_PROTOCOLIE_BY_ID(X2AP_SeNBAdditionRequest_IEs_t, ie, x2SeNBAdditionRequest, + X2AP_ProtocolIE_ID_id_MeNBtoSeNBContainer, true); + + if (ie == NULL ) { + X2AP_ERROR("%s %d: ie is a NULL pointer \n",__FILE__,__LINE__); + return -1; + } + + X2AP_MeNBtoSeNBContainer_t *c = &ie->value.choice.MeNBtoSeNBContainer; + + if (c->size > 1024) + { printf("%s:%d: fatal: buffer too big\n", __FILE__, __LINE__); abort(); } + + memcpy(X2AP_SENB_ADDITION_REQ(msg).rrc_buffer, c->buf, c->size); + X2AP_SENB_ADDITION_REQ(msg).rrc_buffer_size = c->size; + + + itti_send_msg_to_task(TASK_RRC_ENB, instance_p->instance, msg); + + return 0; +} + +static +int x2ap_eNB_handle_senb_addition_request_ack (instance_t instance, + uint32_t assoc_id, + uint32_t stream, + X2AP_X2AP_PDU_t *pdu) +{ + printf("%s:%d:%s:TODO\n", __FILE__, __LINE__, __FUNCTION__); + return 0; +} + + +static +int x2ap_eNB_handle_senb_addition_request_reject (instance_t instance, + uint32_t assoc_id, + uint32_t stream, + X2AP_X2AP_PDU_t *pdu) +{ + printf("%s:%d:%s:TODO\n", __FILE__, __LINE__, __FUNCTION__); + return 0; +} + +int +x2ap_gNB_handle_ENDC_x2_setup_request(instance_t instance, + uint32_t assoc_id, + uint32_t stream, + X2AP_X2AP_PDU_t *pdu) +{ + + X2AP_ENDCX2SetupRequest_t *x2_ENDC_SetupRequest; + X2AP_ENDCX2SetupRequest_IEs_t *ie; + X2AP_ENB_ENDCX2SetupReqIEs_t *ie_ENB_ENDC; + ServedEUTRAcellsENDCX2ManagementList__Member *servedCellMember; + + x2ap_eNB_instance_t *instance_p; + x2ap_eNB_data_t *x2ap_eNB_data; + uint32_t eNB_id = 0; + + x2ap_eNB_data = NULL; + DevAssert (pdu != NULL); + x2_ENDC_SetupRequest = &pdu->choice.initiatingMessage.value.choice.ENDCX2SetupRequest; + + /* + * We received a new valid X2 Setup Request on a stream != 0. + * * * * This should not happen -> reject eNB x2 setup request. + */ + + if (stream != 0) { + X2AP_ERROR("Received new x2 setup request on stream != 0\n"); + /* + * Send a x2 setup failure with protocol cause unspecified + */ + // Panos: Here we should be calling an ENDC specific setup_failure function instead + return x2ap_eNB_generate_x2_setup_failure (instance, + assoc_id, + X2AP_Cause_PR_protocol, + X2AP_CauseProtocol_unspecified, + -1); + } + + X2AP_DEBUG("Received a new X2 setup request\n"); + + X2AP_FIND_PROTOCOLIE_BY_ID(X2AP_ENDCX2SetupRequest_IEs_t, ie, x2_ENDC_SetupRequest, + X2AP_ProtocolIE_ID_id_InitiatingNodeType_EndcX2Setup, true); + + + + if (ie == NULL ) { + X2AP_ERROR("%s %d: ie is a NULL pointer \n",__FILE__,__LINE__); + return -1; + } else { + if (ie->value.choice.InitiatingNodeType_EndcX2Setup.choice.init_eNB.list.count > 0) { + //Panos: Here the container parameter in X2AP_FIND_PROTOCOLIE_BY_ID should be the x2_ENDC_SetupRequest + //message or the ie to which there are more nested information elements? + for (int i=0; i<ie->value.choice.InitiatingNodeType_EndcX2Setup.choice.init_eNB.list.count;i++) { + + ie_ENB_ENDC = (X2AP_ENB_ENDCX2SetupReqIEs_t*) ie->value.choice.InitiatingNodeType_EndcX2Setup.choice.init_eNB.list.array[i]; + if (ie_ENB_ENDC == NULL ) { + X2AP_ERROR("%s %d: ie is a NULL pointer \n",__FILE__,__LINE__); + return -1; + } + + else if (ie_ENB_ENDC->id == X2AP_ProtocolIE_ID_id_GlobalENB_ID) { + if (ie_ENB_ENDC->value.choice.GlobalENB_ID.eNB_ID.present == X2AP_ENB_ID_PR_home_eNB_ID) { + // Home eNB ID = 28 bits + uint8_t *eNB_id_buf = ie_ENB_ENDC->value.choice.GlobalENB_ID.eNB_ID.choice.home_eNB_ID.buf; + if (ie_ENB_ENDC->value.choice.GlobalENB_ID.eNB_ID.choice.macro_eNB_ID.size != 28) { + //TODO: handle case were size != 28 -> notify ? reject ? + } + eNB_id = (eNB_id_buf[0] << 20) + (eNB_id_buf[1] << 12) + (eNB_id_buf[2] << 4) + ((eNB_id_buf[3] & 0xf0) >> 4); + X2AP_DEBUG("Home eNB id: %07x\n", eNB_id); + } else { + // Macro eNB = 20 bits + uint8_t *eNB_id_buf = ie_ENB_ENDC->value.choice.GlobalENB_ID.eNB_ID.choice.macro_eNB_ID.buf; + if (ie_ENB_ENDC->value.choice.GlobalENB_ID.eNB_ID.choice.macro_eNB_ID.size != 20) { + //TODO: handle case were size != 20 -> notify ? reject ? + } + eNB_id = (eNB_id_buf[0] << 12) + (eNB_id_buf[1] << 4) + ((eNB_id_buf[2] & 0xf0) >> 4); + X2AP_DEBUG("macro eNB id: %05x\n", eNB_id); + } + X2AP_DEBUG("Adding eNB to the list of associated eNBs\n"); + if ((x2ap_eNB_data = x2ap_is_eNB_id_in_list (eNB_id)) == NULL) { + /* + * eNB has not been found in list of associated eNB, + * * * * Add it to the tail of list and initialize data + */ + if ((x2ap_eNB_data = x2ap_is_eNB_assoc_id_in_list (assoc_id)) == NULL) { + /* + * ?? + */ + return -1; + } else { + x2ap_eNB_data->state = X2AP_ENB_STATE_RESETTING; + x2ap_eNB_data->eNB_id = eNB_id; + } + } else { + x2ap_eNB_data->state = X2AP_ENB_STATE_RESETTING; + + /* + * eNB has been found in list, consider the x2 setup request as a reset connection, + * * * * reseting any previous UE state if sctp association is != than the previous one + */ + if (x2ap_eNB_data->assoc_id != assoc_id) { + /* + * ??: Send an overload cause... + */ + X2AP_ERROR("Rejecting x2 setup request as eNB id %d is already associated to an active sctp association" "Previous known: %d, new one: %d\n", eNB_id, x2ap_eNB_data->assoc_id, assoc_id); + + // Panos: Here we should be calling an ENDC specific setup_failure function instead + x2ap_eNB_generate_x2_setup_failure (instance, + assoc_id, + X2AP_Cause_PR_protocol, + X2AP_CauseProtocol_unspecified, + -1); + return -1; + } + /* + * * TODO: call the reset procedure + */ + } + } + else if (ie_ENB_ENDC->id == X2AP_ProtocolIE_ID_id_ServedEUTRAcellsENDCX2ManagementList){ + if (ie_ENB_ENDC->value.choice.ServedEUTRAcellsENDCX2ManagementList.list.count > 0) { + x2ap_eNB_data->num_cc = ie_ENB_ENDC->value.choice.ServedEUTRAcellsENDCX2ManagementList.list.count; + for (int i=0; i<ie_ENB_ENDC->value.choice.ServedEUTRAcellsENDCX2ManagementList.list.count;i++) { + servedCellMember = (ServedEUTRAcellsENDCX2ManagementList__Member *)ie_ENB_ENDC->value.choice.ServedEUTRAcellsENDCX2ManagementList.list.array[i]; + x2ap_eNB_data->Nid_cell[i] = servedCellMember->servedEUTRACellInfo.pCI; + } + } + } + } + } + else { + X2AP_ERROR("%s %d: init_eNB list is empty \n",__FILE__,__LINE__); + return -1; + } + } + + instance_p = x2ap_eNB_get_instance(instance); + DevAssert(instance_p != NULL); + + // Panos: Here we should be calling an ENDC specific setup response function + return x2ap_gNB_generate_ENDC_x2_setup_response(instance_p, x2ap_eNB_data); + //return x2ap_eNB_generate_x2_setup_response(instance_p, x2ap_eNB_data); +} + +int +x2ap_gNB_handle_ENDC_x2_setup_response(instance_t instance, + uint32_t assoc_id, + uint32_t stream, + X2AP_X2AP_PDU_t *pdu) +{ + + X2AP_ENDCX2SetupResponse_t *x2_ENDC_SetupResponse; + X2AP_ENDCX2SetupResponse_IEs_t *ie; + X2AP_En_gNB_ENDCX2SetupReqAckIEs_t *ie_GNB_ENDC; + ServedNRcellsENDCX2ManagementList__Member *servedCellMember; + + x2ap_eNB_instance_t *instance_p; + x2ap_eNB_data_t *x2ap_eNB_data; + uint32_t gNB_id = 0; + + x2ap_eNB_data = NULL; + DevAssert (pdu != NULL); + x2_ENDC_SetupResponse = &pdu->choice.successfulOutcome.value.choice.ENDCX2SetupResponse; + + /* + * We received a new valid X2 Setup Request on a stream != 0. + * * * * This should not happen -> reject eNB x2 setup request. + */ + + if (stream != 0) { + X2AP_ERROR("Received new x2 setup request on stream != 0\n"); + /* + * Send a x2 setup failure with protocol cause unspecified + */ + // Panos: Here we should be calling an ENDC specific setup_failure function instead + return x2ap_eNB_generate_x2_setup_failure (instance, + assoc_id, + X2AP_Cause_PR_protocol, + X2AP_CauseProtocol_unspecified, + -1); + } + + X2AP_DEBUG("Received a new X2 setup request\n"); + + X2AP_FIND_PROTOCOLIE_BY_ID(X2AP_ENDCX2SetupResponse_IEs_t, ie, x2_ENDC_SetupResponse, + X2AP_ProtocolIE_ID_id_RespondingNodeType_EndcX2Setup, true); + + + + if (ie == NULL ) { + X2AP_ERROR("%s %d: ie is a NULL pointer \n",__FILE__,__LINE__); + return -1; + } else { + if (ie->value.choice.RespondingNodeType_EndcX2Setup.choice.respond_en_gNB.list.count > 0) { + //Panos: Here the container parameter in X2AP_FIND_PROTOCOLIE_BY_ID should be the x2_ENDC_SetupRequest + //message or the ie to which there are more nested information elements? + for (int i=0; i<ie->value.choice.RespondingNodeType_EndcX2Setup.choice.respond_en_gNB.list.count;i++) { + + ie_GNB_ENDC = (X2AP_En_gNB_ENDCX2SetupReqAckIEs_t*) ie->value.choice.RespondingNodeType_EndcX2Setup.choice.respond_en_gNB.list.array[i]; + if (ie_GNB_ENDC == NULL ) { + X2AP_ERROR("%s %d: ie is a NULL pointer \n",__FILE__,__LINE__); + return -1; + } + + else if (ie_GNB_ENDC->id == X2AP_ProtocolIE_ID_id_Globalen_gNB_ID) { + if (ie_GNB_ENDC->value.choice.GlobalGNB_ID.gNB_ID.choice.gNB_ID.size!= 28) { + //TODO: handle case were size != 28 -> notify ? reject ? + } + OCTET_STRING_TO_INT32(&ie_GNB_ENDC->value.choice.GlobalGNB_ID.gNB_ID.choice.gNB_ID,gNB_id); + X2AP_DEBUG("gNB id: %07x\n", gNB_id); + + X2AP_DEBUG("Adding gNB to the list of associated gNBs\n"); + if ((x2ap_eNB_data = x2ap_is_eNB_id_in_list (gNB_id)) == NULL) { + /* + * eNB has not been found in list of associated eNB, + * * * * Add it to the tail of list and initialize data + */ + if ((x2ap_eNB_data = x2ap_is_eNB_assoc_id_in_list (assoc_id)) == NULL) { + /* + * ?? + */ + return -1; + } else { + x2ap_eNB_data->state = X2AP_ENB_STATE_RESETTING; + x2ap_eNB_data->eNB_id = gNB_id; + } + } else { + x2ap_eNB_data->state = X2AP_ENB_STATE_RESETTING; + + /* + * eNB has been found in list, consider the x2 setup request as a reset connection, + * * * * reseting any previous UE state if sctp association is != than the previous one + */ + if (x2ap_eNB_data->assoc_id != assoc_id) { + /* + * ??: Send an overload cause... + */ + X2AP_ERROR("Rejecting x2 setup request as eNB id %d is already associated to an active sctp association" "Previous known: %d, new one: %d\n", gNB_id, x2ap_eNB_data->assoc_id, assoc_id); + + // Panos: Here we should be calling an ENDC specific setup_failure function instead + x2ap_eNB_generate_x2_setup_failure (instance, + assoc_id, + X2AP_Cause_PR_protocol, + X2AP_CauseProtocol_unspecified, + -1); + return -1; + } + /* + * * TODO: call the reset procedure + */ + } + } + else if (ie_GNB_ENDC->id == X2AP_ProtocolIE_ID_id_ServedNRcellsENDCX2ManagementList){ + if (ie_GNB_ENDC->value.choice.ServedNRcellsENDCX2ManagementList.list.count > 0) { + x2ap_eNB_data->num_cc = ie_GNB_ENDC->value.choice.ServedNRcellsENDCX2ManagementList.list.count; + for (int i=0; i<ie_GNB_ENDC->value.choice.ServedNRcellsENDCX2ManagementList.list.count;i++) { + servedCellMember = (ServedNRcellsENDCX2ManagementList__Member *)ie_GNB_ENDC->value.choice.ServedNRcellsENDCX2ManagementList.list.array[i]; + x2ap_eNB_data->Nid_cell[i] = servedCellMember->servedNRCellInfo.nrpCI; + //servedCellMember->servedNRCellInfo.nrCellID.pLMN_Identity.buf[0] + if (servedCellMember->servedNRCellInfo.fiveGS_TAC != NULL) { + X2AP_INFO("TAC: %02x%02x%02x\n", + servedCellMember->servedNRCellInfo.fiveGS_TAC->buf[0], + servedCellMember->servedNRCellInfo.fiveGS_TAC->buf[1], + servedCellMember->servedNRCellInfo.fiveGS_TAC->buf[2]); + } else { + X2AP_INFO("TAC: (NULL)\n"); + } + + X2AP_INFO("PLMN: %02x%02x%02x\n", + servedCellMember->servedNRCellInfo.nrCellID.pLMN_Identity.buf[0], + servedCellMember->servedNRCellInfo.nrCellID.pLMN_Identity.buf[1], + servedCellMember->servedNRCellInfo.nrCellID.pLMN_Identity.buf[2]); + } + } + } + } + } + else { + X2AP_ERROR("%s %d: init_eNB list is empty \n",__FILE__,__LINE__); + return -1; + } + } + + /* Optionaly set the target eNB name */ + + /* The association is now ready as source and target eNBs know parameters of each other. + * Mark the association as connected. + */ + x2ap_eNB_data->state = X2AP_ENB_STATE_READY; + + instance_p = x2ap_eNB_get_instance(instance); + DevAssert(instance_p != NULL); + + instance_p->x2_target_enb_associated_nb ++; + x2ap_handle_x2_setup_message(instance_p, x2ap_eNB_data, 0); + + return 0; +} + + diff --git a/openair3/UTILS/conversions.h b/openair3/UTILS/conversions.h index b4438b1aa5804c76383021c9c1ce0638d3874819..e39a841d96517078ec8f93de2b9a9565e33966a9 100644 --- a/openair3/UTILS/conversions.h +++ b/openair3/UTILS/conversions.h @@ -371,6 +371,26 @@ do { \ (bITsTRING)->bits_unused = 4; \ } while(0) +/* +#define INT16_TO_3_BYTE_BUFFER(x, buf) \ +do { \ + (buf)[0] = 0x00; \ + (buf)[1] = (x) >> 8; \ + (buf)[2] = (x); \ +} while(0) +*/ + +#define NR_FIVEGS_TAC_ID_TO_BIT_STRING(x, aSN) \ +do { \ + (aSN)->buf = calloc(3, sizeof(uint8_t)); \ + (aSN)->size = 3; \ + (aSN)->buf[0] = 0x00; \ + (aSN)->buf[1] = (x) >> 8; \ + (aSN)->buf[2] = (x); \ +} while(0) + + + /* TS 38.473 v15.2.1 section 9.3.1.55: * MaskedIMEISV is BIT_STRING(64) */