diff --git a/cmake_targets/CMakeLists.txt b/cmake_targets/CMakeLists.txt index 8683dfd2e169618dfb245add84ee52cf856f14a3..5bf07dae01f1a792cd3465453139495f9815578a 100644 --- a/cmake_targets/CMakeLists.txt +++ b/cmake_targets/CMakeLists.txt @@ -474,12 +474,12 @@ include_directories ("${X2AP_DIR}") add_library(X2AP_ENB ${X2AP_DIR}/x2ap_eNB.c - # ${X2AP_DIR}/x2ap_eNB_decoder.c - # ${X2AP_DIR}/x2ap_eNB_encoder.c + ${X2AP_DIR}/x2ap_eNB_decoder.c + ${X2AP_DIR}/x2ap_eNB_encoder.c ${X2AP_DIR}/x2ap_eNB_handler.c - # ${X2AP_DIR}/x2ap_eNB_itti_messaging.c + ${X2AP_DIR}/x2ap_eNB_itti_messaging.c ${X2AP_DIR}/x2ap_eNB_management_procedures.c - # ${X2AP_DIR}/x2ap_eNB_generate_messages.c + ${X2AP_DIR}/x2ap_eNB_generate_messages.c ) # Hardware dependant options diff --git a/common/utils/msc/msc.h b/common/utils/msc/msc.h index 78eb6cdb080665290f80474328110f79a1d61f28..e8a8a4a0e82d7f65f9b9fcd80b54ddc79cff2759 100644 --- a/common/utils/msc/msc.h +++ b/common/utils/msc/msc.h @@ -63,6 +63,8 @@ typedef enum { MSC_S6A_MME, MSC_HSS, MAX_MSC_PROTOS, + MSC_X2AP_SRC_ENB, + MSC_X2AP_TARGET_ENB, } msc_proto_t; diff --git a/openair2/COMMON/x2ap_messages_types.h b/openair2/COMMON/x2ap_messages_types.h index 6c4031b981df42869d76abbe210bb88289a27115..c74a826ff84685c88ea9a36b6226ccbf58eee166 100644 --- a/openair2/COMMON/x2ap_messages_types.h +++ b/openair2/COMMON/x2ap_messages_types.h @@ -63,17 +63,21 @@ typedef struct x2ap_register_enb_req_s { uint8_t mnc_digit_length; /* - * EARFCN + * CC Params */ - uint16_t fdd_uL_EARFCN; - uint16_t fdd_dL_EARFCN; - uint16_t tdd_EARFCN; - - - uint16_t fdd_uL_Transmission_Bandwidth; - uint16_t fdd_dL_Transmission_Bandwidth; - uint16_t tdd_Transmission_Bandwidth; - + int16_t eutra_band[MAX_NUM_CCs]; + uint32_t downlink_frequency[MAX_NUM_CCs]; + int32_t uplink_frequency_offset[MAX_NUM_CCs]; + uint32_t Nid_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]; + uint32_t fdd_earfcn_UL[MAX_NUM_CCs]; + int num_cc; + + /* To be considered for TDD */ + //uint16_t tdd_EARFCN; + //uint16_t tdd_Transmission_Bandwidth; /* The local eNB IP address to bind */ net_ip_address_t enb_x2_ip_address; diff --git a/openair2/ENB_APP/enb_config.c b/openair2/ENB_APP/enb_config.c index dd995a53a043c2fb4afda8844a84e12054cd5961..2506a0a9dca71261a67156ec4bcec93ec5b648e6 100644 --- a/openair2/ENB_APP/enb_config.c +++ b/openair2/ENB_APP/enb_config.c @@ -65,6 +65,8 @@ extern void set_parallel_conf(char* parallel_conf); extern void set_worker_conf(char* worker_conf); extern PARALLEL_CONF_t get_thread_parallel_conf(void); extern WORKER_CONF_t get_thread_worker_conf(void); +extern uint32_t to_earfcn_DL(int eutra_bandP, uint32_t dl_CarrierFreq, uint32_t bw); +extern uint32_t to_earfcn_UL(int eutra_bandP, uint32_t ul_CarrierFreq, uint32_t bw); void RCconfig_flexran() { uint16_t i; @@ -2172,7 +2174,7 @@ int RCconfig_S1(MessageDef *msg_p, uint32_t i) { } int RCconfig_X2(MessageDef *msg_p, uint32_t i) { - int j, k, l; + int I, J, j, k, l; int enb_id; char *address = NULL; char *cidr = NULL; @@ -2181,21 +2183,104 @@ int RCconfig_X2(MessageDef *msg_p, uint32_t i) { paramlist_def_t ENBParamList = {ENB_CONFIG_STRING_ENB_LIST,NULL,0}; /* get global parameters, defined outside any section in the config file */ config_get( ENBSParams,sizeof(ENBSParams)/sizeof(paramdef_t),NULL); - /*#if defined(ENABLE_ITTI) && defined(ENABLE_USE_MME) - if (strcasecmp( *(ENBSParams[ENB_ASN1_VERBOSITY_IDX].strptr), ENB_CONFIG_STRING_ASN1_VERBOSITY_NONE) == 0) { - asn_debug = 0; - asn1_xer_print = 0; - } else if (strcasecmp( *(ENBSParams[ENB_ASN1_VERBOSITY_IDX].strptr), ENB_CONFIG_STRING_ASN1_VERBOSITY_INFO) == 0) { - asn_debug = 1; - asn1_xer_print = 1; - } else if (strcasecmp(*(ENBSParams[ENB_ASN1_VERBOSITY_IDX].strptr) , ENB_CONFIG_STRING_ASN1_VERBOSITY_ANNOYING) == 0) { - asn_debug = 1; - asn1_xer_print = 2; - } else { - asn_debug = 0; - asn1_xer_print = 0; - } - #endif */ + + /* define CC params */ + + int32_t Nid_cell = 0; + + char *frame_type, *prefix_type, *pbch_repetition, *prach_high_speed, + *pusch_hoppingMode, *pusch_enable64QAM, *pusch_groupHoppingEnabled, + *pusch_sequenceHoppingEnabled, *phich_duration, *phich_resource, + *srs_enable, *srs_ackNackST, *srs_MaxUpPts, *pusch_alpha, + *pucch_deltaF_Format1, *pucch_deltaF_Format1b, *pucch_deltaF_Format2, + *pucch_deltaF_Format2a, *pucch_deltaF_Format2b, + *rach_preamblesGroupAConfig, *rach_messagePowerOffsetGroupB, *pcch_nB; + long long int downlink_frequency; + int32_t tdd_config, tdd_config_s, eutra_band, uplink_frequency_offset, + Nid_cell_mbsfn, N_RB_DL, nb_antenna_ports, prach_root, prach_config_index, + prach_zero_correlation, prach_freq_offset, pucch_delta_shift, + pucch_nRB_CQI, pucch_nCS_AN, pucch_n1_AN, pdsch_referenceSignalPower, + pdsch_p_b, pusch_n_SB, pusch_hoppingOffset, pusch_groupAssignment, + pusch_nDMRS1, srs_BandwidthConfig, srs_SubframeConfig, pusch_p0_Nominal, + pucch_p0_Nominal, msg3_delta_Preamble, rach_numberOfRA_Preambles, + rach_sizeOfRA_PreamblesGroupA, rach_messageSizeGroupA, + rach_powerRampingStep, rach_preambleInitialReceivedTargetPower, + rach_preambleTransMax, rach_raResponseWindowSize, + rach_macContentionResolutionTimer, rach_maxHARQ_Msg3Tx, + pcch_defaultPagingCycle, bcch_modificationPeriodCoeff, + ue_TimersAndConstants_t300, ue_TimersAndConstants_t301, + ue_TimersAndConstants_t310, ue_TimersAndConstants_t311, + ue_TimersAndConstants_n310, ue_TimersAndConstants_n311, + ue_TransmissionMode, ue_multiple_max; + + const char* rxPool_sc_CP_Len; + const char* rxPool_sc_Period; + const char* rxPool_data_CP_Len; + libconfig_int rxPool_ResourceConfig_prb_Num; + libconfig_int rxPool_ResourceConfig_prb_Start; + libconfig_int rxPool_ResourceConfig_prb_End; + const char* rxPool_ResourceConfig_offsetIndicator_present; + libconfig_int rxPool_ResourceConfig_offsetIndicator_choice; + const char* rxPool_ResourceConfig_subframeBitmap_present; + char* rxPool_ResourceConfig_subframeBitmap_choice_bs_buf; + libconfig_int rxPool_ResourceConfig_subframeBitmap_choice_bs_size; + libconfig_int rxPool_ResourceConfig_subframeBitmap_choice_bs_bits_unused; + + //SIB19 + //for discRxPool + const char* discRxPool_cp_Len; + const char* discRxPool_discPeriod; + libconfig_int discRxPool_numRetx; + libconfig_int discRxPool_numRepetition; + libconfig_int discRxPool_ResourceConfig_prb_Num; + libconfig_int discRxPool_ResourceConfig_prb_Start; + libconfig_int discRxPool_ResourceConfig_prb_End; + const char* discRxPool_ResourceConfig_offsetIndicator_present; + libconfig_int discRxPool_ResourceConfig_offsetIndicator_choice; + const char* discRxPool_ResourceConfig_subframeBitmap_present; + char* discRxPool_ResourceConfig_subframeBitmap_choice_bs_buf; + libconfig_int discRxPool_ResourceConfig_subframeBitmap_choice_bs_size; + libconfig_int discRxPool_ResourceConfig_subframeBitmap_choice_bs_bits_unused; + + //for discRxPoolPS + const char* discRxPoolPS_cp_Len; + const char* discRxPoolPS_discPeriod; + libconfig_int discRxPoolPS_numRetx; + libconfig_int discRxPoolPS_numRepetition; + libconfig_int discRxPoolPS_ResourceConfig_prb_Num; + libconfig_int discRxPoolPS_ResourceConfig_prb_Start; + libconfig_int discRxPoolPS_ResourceConfig_prb_End; + const char* discRxPoolPS_ResourceConfig_offsetIndicator_present; + libconfig_int discRxPoolPS_ResourceConfig_offsetIndicator_choice; + const char* discRxPoolPS_ResourceConfig_subframeBitmap_present; + char* discRxPoolPS_ResourceConfig_subframeBitmap_choice_bs_buf; + libconfig_int discRxPoolPS_ResourceConfig_subframeBitmap_choice_bs_size; + libconfig_int discRxPoolPS_ResourceConfig_subframeBitmap_choice_bs_bits_unused; + + checkedparam_t config_check_CCparams[] = CCPARAMS_CHECK; + paramdef_t CCsParams[] = CCPARAMS_DESC; + paramlist_def_t CCsParamList = {ENB_CONFIG_STRING_COMPONENT_CARRIERS, NULL, 0}; + + /* map parameter checking array instances to parameter definition array instances */ + for (I = 0; I < (sizeof(CCsParams) / sizeof(paramdef_t)); I++) { + CCsParams[I].chkPptr = &(config_check_CCparams[I]); + } +/*#if defined(ENABLE_ITTI) && defined(ENABLE_USE_MME) + if (strcasecmp( *(ENBSParams[ENB_ASN1_VERBOSITY_IDX].strptr), ENB_CONFIG_STRING_ASN1_VERBOSITY_NONE) == 0) { + asn_debug = 0; + asn1_xer_print = 0; + } else if (strcasecmp( *(ENBSParams[ENB_ASN1_VERBOSITY_IDX].strptr), ENB_CONFIG_STRING_ASN1_VERBOSITY_INFO) == 0) { + asn_debug = 1; + asn1_xer_print = 1; + } else if (strcasecmp(*(ENBSParams[ENB_ASN1_VERBOSITY_IDX].strptr) , ENB_CONFIG_STRING_ASN1_VERBOSITY_ANNOYING) == 0) { + asn_debug = 1; + asn1_xer_print = 2; + } else { + asn_debug = 0; + asn1_xer_print = 0; + } +#endif */ + AssertFatal(i < ENBSParams[ENB_ACTIVE_ENBS_IDX].numelt, "Failed to parse config file %s, %uth attribute %s \n", RC.config_file_name, i, ENB_CONFIG_STRING_ACTIVE_ENBS); @@ -2226,7 +2311,9 @@ int RCconfig_X2(MessageDef *msg_p, uint32_t i) { paramlist_def_t X2ParamList = {ENB_CONFIG_STRING_TARGET_ENB_X2_IP_ADDRESS,NULL,0}; paramdef_t SCTPParams[] = SCTPPARAMS_DESC; paramdef_t NETParams[] = NETPARAMS_DESC; - char aprefix[MAX_OPTNAME_SIZE*2 + 8]; + /* TODO: fix the size - if set lower we have a crash (MAX_OPTNAME_SIZE was 64 when this code was written) */ + /* this is most probably a problem with the config module */ + char aprefix[MAX_OPTNAME_SIZE*80 + 8]; /* Some default/random parameters */ X2AP_REGISTER_ENB_REQ (msg_p).eNB_id = enb_id; @@ -2249,6 +2336,56 @@ int RCconfig_X2(MessageDef *msg_p, uint32_t i) { (X2AP_REGISTER_ENB_REQ (msg_p).mnc_digit_length == 3), "BAD MNC DIGIT LENGTH %d", X2AP_REGISTER_ENB_REQ (msg_p).mnc_digit_length); + + /* CC params */ + sprintf(aprefix, "%s.[%i]", ENB_CONFIG_STRING_ENB_LIST, k); + config_getlist(&CCsParamList, NULL, 0, aprefix); + + X2AP_REGISTER_ENB_REQ (msg_p).num_cc = CCsParamList.numelt; + + if (CCsParamList.numelt > 0) { + + //char ccspath[MAX_OPTNAME_SIZE*2 + 16]; + + for (J = 0; J < CCsParamList.numelt ; J++) { + + sprintf(aprefix, "%s.[%i].%s.[%i]", ENB_CONFIG_STRING_ENB_LIST, k, ENB_CONFIG_STRING_COMPONENT_CARRIERS, J); + config_get(CCsParams, sizeof(CCsParams)/sizeof(paramdef_t), aprefix); + + X2AP_REGISTER_ENB_REQ (msg_p).eutra_band[J] = eutra_band; + X2AP_REGISTER_ENB_REQ (msg_p).downlink_frequency[J] = (uint32_t) downlink_frequency; + X2AP_REGISTER_ENB_REQ (msg_p).uplink_frequency_offset[J] = (unsigned int) uplink_frequency_offset; + X2AP_REGISTER_ENB_REQ (msg_p).Nid_cell[J]= Nid_cell; + + if (Nid_cell>503) { + AssertFatal (0, + "Failed to parse eNB configuration file %s, enb %d unknown value \"%d\" for Nid_cell choice: 0...503 !\n", + RC.config_file_name, k, Nid_cell); + } + + X2AP_REGISTER_ENB_REQ (msg_p).N_RB_DL[J]= N_RB_DL; + + if ((N_RB_DL!=6) && (N_RB_DL!=15) && (N_RB_DL!=25) && (N_RB_DL!=50) && (N_RB_DL!=75) && (N_RB_DL!=100)) { + AssertFatal (0, + "Failed to parse eNB configuration file %s, enb %d unknown value \"%d\" for N_RB_DL choice: 6,15,25,50,75,100 !\n", + RC.config_file_name, k, N_RB_DL); + } + + if (strcmp(frame_type, "FDD") == 0) { + X2AP_REGISTER_ENB_REQ (msg_p).frame_type[J] = FDD; + } else if (strcmp(frame_type, "TDD") == 0) { + X2AP_REGISTER_ENB_REQ (msg_p).frame_type[J] = TDD; + } else { + AssertFatal (0, + "Failed to parse eNB configuration file %s, enb %d unknown value \"%s\" for frame_type choice: FDD or TDD !\n", + RC.config_file_name, k, frame_type); + } + + X2AP_REGISTER_ENB_REQ (msg_p).fdd_earfcn_DL[J] = to_earfcn_DL(eutra_band, downlink_frequency, N_RB_DL); + X2AP_REGISTER_ENB_REQ (msg_p).fdd_earfcn_UL[J] = to_earfcn_UL(eutra_band, downlink_frequency + uplink_frequency_offset, N_RB_DL); + } + } + sprintf(aprefix,"%s.[%i]",ENB_CONFIG_STRING_ENB_LIST,k); config_getlist( &X2ParamList,X2Params,sizeof(X2Params)/sizeof(paramdef_t),aprefix); diff --git a/openair2/LAYER2/MAC/config.c b/openair2/LAYER2/MAC/config.c index 5331f07a6883a7ebbbb0b0bf4f432711a3660e38..0b4f05a56e1883374afc17d50a35d9ee7a69bd4e 100644 --- a/openair2/LAYER2/MAC/config.c +++ b/openair2/LAYER2/MAC/config.c @@ -160,6 +160,58 @@ uint32_t to_earfcn(int eutra_bandP, uint32_t dl_CarrierFreq, uint32_t bw) (eutra_bandtable[i].N_OFFs_DL / 10)); } +uint32_t to_earfcn_DL(int eutra_bandP, long long int dl_CarrierFreq, uint32_t bw) +{ + + uint32_t dl_CarrierFreq_by_100k = dl_CarrierFreq / 100000; + int bw_by_100 = bw / 100; + + int i; + + AssertFatal(eutra_bandP < 69, "eutra_band %d > 68\n", eutra_bandP); + for (i = 0; i < 69 && eutra_bandtable[i].band != eutra_bandP; i++); + + AssertFatal(dl_CarrierFreq_by_100k >= eutra_bandtable[i].dl_min, + "Band %d, bw %u : DL carrier frequency %lld Hz < %u\n", + eutra_bandP, bw, dl_CarrierFreq, + eutra_bandtable[i].dl_min); + AssertFatal(dl_CarrierFreq_by_100k <= + (eutra_bandtable[i].dl_max - bw_by_100), + "Band %d, bw %u : DL carrier frequency %lld Hz > %d\n", + eutra_bandP, bw, dl_CarrierFreq, + eutra_bandtable[i].dl_max - bw_by_100); + + + return (dl_CarrierFreq_by_100k - eutra_bandtable[i].dl_min + + (eutra_bandtable[i].N_OFFs_DL / 10)); +} + +uint32_t to_earfcn_UL(int eutra_bandP, long long int ul_CarrierFreq, uint32_t bw) +{ + + uint32_t ul_CarrierFreq_by_100k = ul_CarrierFreq / 100000; + int bw_by_100 = bw / 100; + + int i; + + AssertFatal(eutra_bandP < 69, "eutra_band %d > 68\n", eutra_bandP); + for (i = 0; i < 69 && eutra_bandtable[i].band != eutra_bandP; i++); + + AssertFatal(ul_CarrierFreq_by_100k >= eutra_bandtable[i].ul_min, + "Band %d, bw %u : UL carrier frequency %lld Hz < %u\n", + eutra_bandP, bw, ul_CarrierFreq, + eutra_bandtable[i].ul_min); + AssertFatal(ul_CarrierFreq_by_100k <= + (eutra_bandtable[i].ul_max - bw_by_100), + "Band %d, bw %u : UL carrier frequency %lld Hz > %d\n", + eutra_bandP, bw, ul_CarrierFreq, + eutra_bandtable[i].ul_max - bw_by_100); + + + return (ul_CarrierFreq_by_100k - eutra_bandtable[i].ul_min + + ((eutra_bandtable[i].N_OFFs_DL + 180000) / 10)); +} + uint32_t from_earfcn(int eutra_bandP, uint32_t dl_earfcn) { diff --git a/openair2/X2AP/x2ap_common.h b/openair2/X2AP/x2ap_common.h index ceda1c8eb96e04a3a7e4509d460a4396be2be85b..a2f903a73725f812b44314e02408ad40ceed145f 100644 --- a/openair2/X2AP/x2ap_common.h +++ b/openair2/X2AP/x2ap_common.h @@ -28,12 +28,12 @@ #include "X2AP_InitiatingMessage.h" #include "X2AP_SuccessfulOutcome.h" #include "X2AP_UnsuccessfulOutcome.h" -#include "X2AP_ProtocolIE-Field.h" #include "X2AP_ProtocolIE-FieldPair.h" #include "X2AP_ProtocolIE-ContainerPair.h" #include "X2AP_ProtocolExtensionField.h" #include "X2AP_ProtocolExtensionContainer.h" #include "X2AP_asn_constant.h" +#include "intertask_interface.h" #ifndef X2AP_COMMON_H_ #define X2AP_COMMON_H_ @@ -87,15 +87,13 @@ extern int asn1_xer_print; if (mandatory) DevAssert(ie != NULL); \ } while(0) -//Forward declaration -struct x2ap_message_s; - /** \brief Function callback prototype. **/ typedef int (*x2ap_message_decoded_callback)( + instance_t instance, uint32_t assocId, uint32_t stream, - struct x2ap_message_s *message); + X2AP_X2AP_PDU_t *pdu); /** \brief Encode a successfull outcome message \param buffer pointer to buffer in which data will be encoded diff --git a/openair2/X2AP/x2ap_eNB.c b/openair2/X2AP/x2ap_eNB.c index a1469509a90563acf4e6dd3546a74056a600cb3a..d12dfa881979b9a3841471ed236b64ff4475c621 100644 --- a/openair2/X2AP/x2ap_eNB.c +++ b/openair2/X2AP/x2ap_eNB.c @@ -31,6 +31,7 @@ #include "x2ap_eNB_defs.h" #include "x2ap_eNB_management_procedures.h" #include "x2ap_eNB_handler.h" +#include "x2ap_eNB_generate_messages.h" #include "x2ap_common.h" #include "queue.h" @@ -42,9 +43,9 @@ struct x2ap_eNB_data_s; RB_PROTOTYPE(x2ap_enb_map, x2ap_eNB_data_s, entry, x2ap_eNB_compare_assoc_id); -//static -//void x2ap_eNB_handle_sctp_data_ind(instance_t instance, - // sctp_data_ind_t *sctp_data_ind); +static +void x2ap_eNB_handle_sctp_data_ind(instance_t instance, sctp_data_ind_t *sctp_data_ind); + static void x2ap_eNB_handle_sctp_association_resp(instance_t instance, sctp_new_association_resp_t *sctp_new_association_resp); @@ -63,22 +64,21 @@ 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_sctp_data_ind(instance_t instance, - sctp_data_ind_t *sctp_data_ind) { +void x2ap_eNB_handle_sctp_data_ind(instance_t instance, sctp_data_ind_t *sctp_data_ind) { int result; DevAssert(sctp_data_ind != NULL); - x2ap_eNB_handle_message(sctp_data_ind->assoc_id, sctp_data_ind->stream, + x2ap_eNB_handle_message(instance, sctp_data_ind->assoc_id, sctp_data_ind->stream, sctp_data_ind->buffer, sctp_data_ind->buffer_length); result = itti_free(TASK_UNKNOWN, sctp_data_ind->buffer); AssertFatal (result == EXIT_SUCCESS, "Failed to free memory (%d)!\n", result); -}*/ +} static void x2ap_eNB_handle_sctp_association_resp(instance_t instance, sctp_new_association_resp_t *sctp_new_association_resp) @@ -143,7 +143,7 @@ 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_x2_setup_request(instance_p, x2ap_enb_data_p); } static @@ -325,6 +325,19 @@ void x2ap_eNB_handle_register_eNB(instance_t instance, new_instance->mnc = x2ap_register_eNB->mnc; new_instance->mnc_digit_length = x2ap_register_eNB->mnc_digit_length; + new_instance->num_cc = x2ap_register_eNB->num_cc; + + for (int i = 0; i< x2ap_register_eNB->num_cc; i++){ + new_instance->eutra_band[i] = x2ap_register_eNB->eutra_band[i]; + new_instance->downlink_frequency[i] = x2ap_register_eNB->downlink_frequency[i]; + new_instance->uplink_frequency_offset[i] = x2ap_register_eNB->uplink_frequency_offset[i]; + new_instance->Nid_cell[i] = x2ap_register_eNB->Nid_cell[i]; + new_instance->N_RB_DL[i] = x2ap_register_eNB->N_RB_DL[i]; + new_instance->frame_type[i] = x2ap_register_eNB->frame_type[i]; + new_instance->fdd_earfcn_DL[i] = x2ap_register_eNB->fdd_earfcn_DL[i]; + new_instance->fdd_earfcn_UL[i] = x2ap_register_eNB->fdd_earfcn_UL[i]; + } + DevCheck(x2ap_register_eNB->nb_x2 <= X2AP_MAX_NB_ENB_IP_ADDRESS, X2AP_MAX_NB_ENB_IP_ADDRESS, x2ap_register_eNB->nb_x2, 0); memcpy(new_instance->target_enb_x2_ip_address, @@ -432,8 +445,8 @@ void *x2ap_task(void *arg) break; case SCTP_DATA_IND: - //x2ap_eNB_handle_sctp_data_ind(ITTI_MESSAGE_GET_INSTANCE(received_msg), - // &received_msg->ittiMsg.sctp_data_ind); + x2ap_eNB_handle_sctp_data_ind(ITTI_MESSAGE_GET_INSTANCE(received_msg), + &received_msg->ittiMsg.sctp_data_ind); break; default: diff --git a/openair2/X2AP/x2ap_eNB_decoder.c b/openair2/X2AP/x2ap_eNB_decoder.c new file mode 100644 index 0000000000000000000000000000000000000000..f156d96d175beab05523d01625cd34324bc1e1a5 --- /dev/null +++ b/openair2/X2AP/x2ap_eNB_decoder.c @@ -0,0 +1,127 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +#include <stdio.h> + +#include "assertions.h" +#include "intertask_interface.h" +#include "x2ap_common.h" +#include "x2ap_eNB_decoder.h" + +static int x2ap_eNB_decode_initiating_message(X2AP_X2AP_PDU_t *pdu) +{ + DevAssert(pdu != NULL); + + 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); + X2AP_INFO("x2ap_eNB_decode_initiating_message!\n"); + break; + + default: + X2AP_ERROR("Unknown procedure ID (%d) for initiating message\n", + (int)pdu->choice.initiatingMessage.procedureCode); + AssertFatal( 0, "Unknown procedure ID (%d) for initiating message\n", + (int)pdu->choice.initiatingMessage.procedureCode); + return -1; + } + + return 0; +} + +static int x2ap_eNB_decode_successful_outcome(X2AP_X2AP_PDU_t *pdu) +{ + DevAssert(pdu != NULL); + + 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); + 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); + return -1; + } + + return 0; +} + +static int x2ap_eNB_decode_unsuccessful_outcome(X2AP_X2AP_PDU_t *pdu) +{ + DevAssert(pdu != NULL); + + 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); + X2AP_INFO("x2ap_eNB_decode_unsuccessfuloutcome_message!\n"); + break; + + default: + X2AP_ERROR("Unknown procedure ID (%d) for unsuccessfull outcome message\n", + (int)pdu->choice.unsuccessfulOutcome.procedureCode); + return -1; + } + + return 0; +} + +int x2ap_eNB_decode_pdu(X2AP_X2AP_PDU_t *pdu, const uint8_t *const buffer, uint32_t length) +{ + asn_dec_rval_t dec_ret; + + DevAssert(buffer != NULL); + + dec_ret = aper_decode(NULL, + &asn_DEF_X2AP_X2AP_PDU, + (void **)&pdu, + buffer, + length, + 0, + 0); + + xer_fprint(stdout, &asn_DEF_X2AP_X2AP_PDU, pdu); + + if (dec_ret.code != RC_OK) { + X2AP_ERROR("Failed to decode pdu\n"); + return -1; + } + + switch(pdu->present) { + case X2AP_X2AP_PDU_PR_initiatingMessage: + return x2ap_eNB_decode_initiating_message(pdu); + + case X2AP_X2AP_PDU_PR_successfulOutcome: + return x2ap_eNB_decode_successful_outcome(pdu); + + case X2AP_X2AP_PDU_PR_unsuccessfulOutcome: + return x2ap_eNB_decode_unsuccessful_outcome(pdu); + + default: + X2AP_DEBUG("Unknown presence (%d) or not implemented\n", (int)pdu->present); + break; + } + + + return -1; +} diff --git a/openair2/X2AP/x2ap_eNB_decoder.h b/openair2/X2AP/x2ap_eNB_decoder.h new file mode 100644 index 0000000000000000000000000000000000000000..9ce9ea3d40ef039a9c36c45163bdeb2969b0b9fb --- /dev/null +++ b/openair2/X2AP/x2ap_eNB_decoder.h @@ -0,0 +1,29 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +#ifndef X2AP_ENB_DECODER_H_ +#define X2AP_ENB_DECODER_H_ + +int x2ap_eNB_decode_pdu(X2AP_X2AP_PDU_t *pdu, const uint8_t *const buffer, uint32_t length) +__attribute__ ((warn_unused_result)); + +#endif /* X2AP_ENB_DECODER_H_ */ + diff --git a/openair2/X2AP/x2ap_eNB_defs.h b/openair2/X2AP/x2ap_eNB_defs.h index 11b4434dc0ae5c1146aff0faa151d18664c8f779..3014290206913e516b046bfc5dbab94fa64397b1 100644 --- a/openair2/X2AP/x2ap_eNB_defs.h +++ b/openair2/X2AP/x2ap_eNB_defs.h @@ -151,6 +151,17 @@ typedef struct x2ap_eNB_instance_s { uint16_t mnc; uint8_t mnc_digit_length; + /* CC params */ + int16_t eutra_band[MAX_NUM_CCs]; + uint32_t downlink_frequency[MAX_NUM_CCs]; + int32_t uplink_frequency_offset[MAX_NUM_CCs]; + uint32_t Nid_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]; + uint32_t fdd_earfcn_UL[MAX_NUM_CCs]; + int num_cc; + net_ip_address_t target_enb_x2_ip_address[X2AP_MAX_NB_ENB_IP_ADDRESS]; uint8_t nb_x2; net_ip_address_t enb_x2_ip_address; diff --git a/openair2/X2AP/x2ap_eNB_encoder.c b/openair2/X2AP/x2ap_eNB_encoder.c new file mode 100644 index 0000000000000000000000000000000000000000..1eb617a7f1ddec817a88648fe25ddbef2ac9ad7c --- /dev/null +++ b/openair2/X2AP/x2ap_eNB_encoder.c @@ -0,0 +1,54 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +#include <stdio.h> +#include <string.h> +#include <stdint.h> + +#include "assertions.h" +#include "conversions.h" +#include "intertask_interface.h" +#include "x2ap_common.h" +#include "x2ap_eNB_encoder.h" + +int x2ap_eNB_encode_pdu(X2AP_X2AP_PDU_t *pdu, uint8_t **buffer, uint32_t *len) +{ + ssize_t encoded; + + DevAssert(pdu != NULL); + DevAssert(buffer != NULL); + DevAssert(len != NULL); + + 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); + + if (encoded < 0) { + return -1; + } + + *len = encoded; + + ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_X2AP_X2AP_PDU, pdu); + return encoded; +} diff --git a/openair2/X2AP/x2ap_eNB_encoder.h b/openair2/X2AP/x2ap_eNB_encoder.h new file mode 100644 index 0000000000000000000000000000000000000000..04c77583b4f27c05fcc723100784bf418bf26c3a --- /dev/null +++ b/openair2/X2AP/x2ap_eNB_encoder.h @@ -0,0 +1,28 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +#ifndef X2AP_ENB_ENCODER_H_ +#define X2AP_ENB_ENCODER_H_ + +int x2ap_eNB_encode_pdu(X2AP_X2AP_PDU_t *pdu, uint8_t **buffer, uint32_t *len) +__attribute__ ((warn_unused_result)); + +#endif /* X2AP_ENB_ENCODER_H_ */ diff --git a/openair2/X2AP/x2ap_eNB_generate_messages.c b/openair2/X2AP/x2ap_eNB_generate_messages.c new file mode 100644 index 0000000000000000000000000000000000000000..9c5a281506730409d8cf9b7048e4d68b90e826a7 --- /dev/null +++ b/openair2/X2AP/x2ap_eNB_generate_messages.c @@ -0,0 +1,405 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +#include "intertask_interface.h" + +#include "x2ap_common.h" +#include "x2ap_eNB.h" +#include "x2ap_eNB_generate_messages.h" +#include "x2ap_eNB_encoder.h" + +#include "x2ap_eNB_itti_messaging.h" + +#include "msc.h" +#include "assertions.h" +#include "conversions.h" + +int x2ap_eNB_generate_x2_setup_request( + x2ap_eNB_instance_t *instance_p, x2ap_eNB_data_t *x2ap_eNB_data_p) +{ + X2AP_X2AP_PDU_t pdu; + X2AP_X2SetupRequest_t *out; + X2AP_X2SetupRequest_IEs_t *ie; + X2AP_PLMN_Identity_t *plmn; + ServedCells__Member *servedCellMember; + X2AP_GU_Group_ID_t *gu; + + 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_x2Setup; + pdu.choice.initiatingMessage.criticality = X2AP_Criticality_reject; + pdu.choice.initiatingMessage.value.present = X2AP_InitiatingMessage__value_PR_X2SetupRequest; + out = &pdu.choice.initiatingMessage.value.choice.X2SetupRequest; + + /* mandatory */ + ie = (X2AP_X2SetupRequest_IEs_t *)calloc(1, sizeof(X2AP_X2SetupRequest_IEs_t)); + ie->id = X2AP_ProtocolIE_ID_id_GlobalENB_ID; + ie->criticality = X2AP_Criticality_reject; + ie->value.present = X2AP_X2SetupRequest_IEs__value_PR_GlobalENB_ID; + MCC_MNC_TO_PLMNID(instance_p->mcc, instance_p->mnc, instance_p->mnc_digit_length, + &ie->value.choice.GlobalENB_ID.pLMN_Identity); + ie->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->value.choice.GlobalENB_ID.eNB_ID.choice.macro_eNB_ID); + X2AP_INFO("%d -> %02x%02x%02x\n", instance_p->eNB_id, + ie->value.choice.GlobalENB_ID.eNB_ID.choice.macro_eNB_ID.buf[0], + ie->value.choice.GlobalENB_ID.eNB_ID.choice.macro_eNB_ID.buf[1], + ie->value.choice.GlobalENB_ID.eNB_ID.choice.macro_eNB_ID.buf[2]); + ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie); + + /* mandatory */ + ie = (X2AP_X2SetupRequest_IEs_t *)calloc(1, sizeof(X2AP_X2SetupRequest_IEs_t)); + ie->id = X2AP_ProtocolIE_ID_id_ServedCells; + ie->criticality = X2AP_Criticality_reject; + ie->value.present = X2AP_X2SetupRequest_IEs__value_PR_ServedCells; + { + for (int i = 0; i<instance_p->num_cc; i++){ + servedCellMember = (ServedCells__Member *)calloc(1,sizeof(ServedCells__Member)); + { + servedCellMember->servedCellInfo.pCI = instance_p->Nid_cell[i]; + + MCC_MNC_TO_PLMNID(instance_p->mcc, instance_p->mnc, instance_p->mnc_digit_length, + &servedCellMember->servedCellInfo.cellId.pLMN_Identity); + MACRO_ENB_ID_TO_CELL_IDENTITY(instance_p->eNB_id,0, + &servedCellMember->servedCellInfo.cellId.eUTRANcellIdentifier); + + INT16_TO_OCTET_STRING(instance_p->tac, &servedCellMember->servedCellInfo.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->servedCellInfo.broadcastPLMNs.list, plmn); + } + + if (instance_p->frame_type[i] == FDD) { + servedCellMember->servedCellInfo.eUTRA_Mode_Info.present = X2AP_EUTRA_Mode_Info_PR_fDD; + servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.dL_EARFCN = instance_p->fdd_earfcn_DL[i]; + servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.uL_EARFCN = instance_p->fdd_earfcn_UL[i]; + switch (instance_p->N_RB_DL[i]) { + case 6: + servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.uL_Transmission_Bandwidth = X2AP_Transmission_Bandwidth_bw6; + servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.dL_Transmission_Bandwidth = X2AP_Transmission_Bandwidth_bw6; + break; + case 15: + servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.uL_Transmission_Bandwidth = X2AP_Transmission_Bandwidth_bw15; + servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.dL_Transmission_Bandwidth = X2AP_Transmission_Bandwidth_bw15; + break; + case 25: + servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.uL_Transmission_Bandwidth = X2AP_Transmission_Bandwidth_bw25; + servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.dL_Transmission_Bandwidth = X2AP_Transmission_Bandwidth_bw25; + break; + case 50: + servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.uL_Transmission_Bandwidth = X2AP_Transmission_Bandwidth_bw50; + servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.dL_Transmission_Bandwidth = X2AP_Transmission_Bandwidth_bw50; + break; + case 75: + servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.uL_Transmission_Bandwidth = X2AP_Transmission_Bandwidth_bw75; + servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.dL_Transmission_Bandwidth = X2AP_Transmission_Bandwidth_bw75; + break; + case 100: + servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.uL_Transmission_Bandwidth = X2AP_Transmission_Bandwidth_bw100; + servedCellMember->servedCellInfo.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->value.choice.ServedCells.list, servedCellMember); + } + } + ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie); + + /* mandatory */ + ie = (X2AP_X2SetupRequest_IEs_t *)calloc(1, sizeof(X2AP_X2SetupRequest_IEs_t)); + ie->id = X2AP_ProtocolIE_ID_id_GUGroupIDList; + ie->criticality = X2AP_Criticality_reject; + ie->value.present = X2AP_X2SetupRequest_IEs__value_PR_GUGroupIDList; + { + gu = (X2AP_GU_Group_ID_t *)calloc(1, sizeof(X2AP_GU_Group_ID_t)); + { + MCC_MNC_TO_PLMNID(instance_p->mcc, instance_p->mnc, instance_p->mnc_digit_length, + &gu->pLMN_Identity); + //@TODO: consider to update this value + INT16_TO_OCTET_STRING(0, &gu->mME_Group_ID); + } + ASN_SEQUENCE_ADD(&ie->value.choice.GUGroupIDList.list, gu); + } + 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; +} + +int x2ap_eNB_generate_x2_setup_response(x2ap_eNB_data_t *x2ap_eNB_data_p) +{ + X2AP_X2AP_PDU_t pdu; + X2AP_X2SetupResponse_t *out; + X2AP_X2SetupResponse_IEs_t *ie; + X2AP_PLMN_Identity_t *plmn; + ServedCells__Member *servedCellMember; + X2AP_GU_Group_ID_t *gu; + + 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 message to encode */ + memset(&pdu, 0, sizeof(pdu)); + pdu.present = X2AP_X2AP_PDU_PR_successfulOutcome; + pdu.choice.successfulOutcome.procedureCode = X2AP_ProcedureCode_id_x2Setup; + pdu.choice.successfulOutcome.criticality = X2AP_Criticality_reject; + pdu.choice.successfulOutcome.value.present = X2AP_SuccessfulOutcome__value_PR_X2SetupResponse; + out = &pdu.choice.successfulOutcome.value.choice.X2SetupResponse; + + /* mandatory */ + ie = (X2AP_X2SetupResponse_IEs_t *)calloc(1, sizeof(X2AP_X2SetupResponse_IEs_t)); + ie->id = X2AP_ProtocolIE_ID_id_GlobalENB_ID; + ie->criticality = X2AP_Criticality_reject; + ie->value.present = X2AP_X2SetupResponse_IEs__value_PR_GlobalENB_ID; + MCC_MNC_TO_PLMNID(instance_p->mcc, instance_p->mnc, instance_p->mnc_digit_length, + &ie->value.choice.GlobalENB_ID.pLMN_Identity); + ie->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->value.choice.GlobalENB_ID.eNB_ID.choice.macro_eNB_ID); + X2AP_INFO("%d -> %02x%02x%02x\n", instance_p->eNB_id, + ie->value.choice.GlobalENB_ID.eNB_ID.choice.macro_eNB_ID.buf[0], + ie->value.choice.GlobalENB_ID.eNB_ID.choice.macro_eNB_ID.buf[1], + ie->value.choice.GlobalENB_ID.eNB_ID.choice.macro_eNB_ID.buf[2]); + ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie); + + /* mandatory */ + ie = (X2AP_X2SetupResponse_IEs_t *)calloc(1, sizeof(X2AP_X2SetupResponse_IEs_t)); + ie->id = X2AP_ProtocolIE_ID_id_ServedCells; + ie->criticality = X2AP_Criticality_reject; + ie->value.present = X2AP_X2SetupResponse_IEs__value_PR_ServedCells; + { + for (int i = 0; i<instance_p->num_cc; i++){ + servedCellMember = (ServedCells__Member *)calloc(1,sizeof(ServedCells__Member)); + { + servedCellMember->servedCellInfo.pCI = instance_p->Nid_cell[i]; + + MCC_MNC_TO_PLMNID(instance_p->mcc, instance_p->mnc, instance_p->mnc_digit_length, + &servedCellMember->servedCellInfo.cellId.pLMN_Identity); + MACRO_ENB_ID_TO_CELL_IDENTITY(instance_p->eNB_id,0, + &servedCellMember->servedCellInfo.cellId.eUTRANcellIdentifier); + + INT16_TO_OCTET_STRING(instance_p->tac, &servedCellMember->servedCellInfo.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->servedCellInfo.broadcastPLMNs.list, plmn); + } + + if (instance_p->frame_type[i] == FDD) { + servedCellMember->servedCellInfo.eUTRA_Mode_Info.present = X2AP_EUTRA_Mode_Info_PR_fDD; + servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.dL_EARFCN = instance_p->fdd_earfcn_DL[i]; + servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.uL_EARFCN = instance_p->fdd_earfcn_UL[i]; + switch (instance_p->N_RB_DL[i]) { + case 6: + servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.uL_Transmission_Bandwidth = X2AP_Transmission_Bandwidth_bw6; + servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.dL_Transmission_Bandwidth = X2AP_Transmission_Bandwidth_bw6; + break; + case 15: + servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.uL_Transmission_Bandwidth = X2AP_Transmission_Bandwidth_bw15; + servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.dL_Transmission_Bandwidth = X2AP_Transmission_Bandwidth_bw15; + break; + case 25: + servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.uL_Transmission_Bandwidth = X2AP_Transmission_Bandwidth_bw25; + servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.dL_Transmission_Bandwidth = X2AP_Transmission_Bandwidth_bw25; + break; + case 50: + servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.uL_Transmission_Bandwidth = X2AP_Transmission_Bandwidth_bw50; + servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.dL_Transmission_Bandwidth = X2AP_Transmission_Bandwidth_bw50; + break; + case 75: + servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.uL_Transmission_Bandwidth = X2AP_Transmission_Bandwidth_bw75; + servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.dL_Transmission_Bandwidth = X2AP_Transmission_Bandwidth_bw75; + break; + case 100: + servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.uL_Transmission_Bandwidth = X2AP_Transmission_Bandwidth_bw100; + servedCellMember->servedCellInfo.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,"X2Setupresponse not supported for TDD!"); + } + } + ASN_SEQUENCE_ADD(&ie->value.choice.ServedCells.list, servedCellMember); + } + } + ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie); + + /* mandatory */ + ie = (X2AP_X2SetupResponse_IEs_t *)calloc(1, sizeof(X2AP_X2SetupResponse_IEs_t)); + ie->id = X2AP_ProtocolIE_ID_id_GUGroupIDList; + ie->criticality = X2AP_Criticality_reject; + ie->value.present = X2AP_X2SetupResponse_IEs__value_PR_GUGroupIDList; + { + gu = (X2AP_GU_Group_ID_t *)calloc(1, sizeof(X2AP_GU_Group_ID_t)); + { + MCC_MNC_TO_PLMNID(instance_p->mcc, instance_p->mnc, instance_p->mnc_digit_length, + &gu->pLMN_Identity); + //@TODO: consider to update this value + INT16_TO_OCTET_STRING(0, &gu->mME_Group_ID); + } + ASN_SEQUENCE_ADD(&ie->value.choice.GUGroupIDList.list, gu); + } + 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; + } + + x2ap_eNB_data_p->state = X2AP_ENB_STATE_READY; + + MSC_LOG_TX_MESSAGE (MSC_X2AP_SRC_ENB, MSC_X2AP_TARGET_ENB, NULL, 0, "0 X2Setup/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, 0); + + return ret; +} + +int x2ap_eNB_generate_x2_setup_failure(instance_t instance, + uint32_t assoc_id, + X2AP_Cause_PR cause_type, + long cause_value, + long time_to_wait) +{ + X2AP_X2AP_PDU_t pdu; + X2AP_X2SetupFailure_t *out; + X2AP_X2SetupFailure_IEs_t *ie; + + uint8_t *buffer; + uint32_t len; + int ret = 0; + + /* Prepare the X2AP message to encode */ + memset(&pdu, 0, sizeof(pdu)); + pdu.present = X2AP_X2AP_PDU_PR_unsuccessfulOutcome; + pdu.choice.unsuccessfulOutcome.procedureCode = X2AP_ProcedureCode_id_x2Setup; + pdu.choice.unsuccessfulOutcome.criticality = X2AP_Criticality_reject; + pdu.choice.unsuccessfulOutcome.value.present = X2AP_UnsuccessfulOutcome__value_PR_X2SetupFailure; + out = &pdu.choice.unsuccessfulOutcome.value.choice.X2SetupFailure; + + /* mandatory */ + ie = (X2AP_X2SetupFailure_IEs_t *)calloc(1, sizeof(X2AP_X2SetupFailure_IEs_t)); + ie->id = X2AP_ProtocolIE_ID_id_Cause; + ie->criticality = X2AP_Criticality_ignore; + ie->value.present = X2AP_X2SetupFailure_IEs__value_PR_Cause; + + x2ap_eNB_set_cause (&ie->value.choice.Cause, cause_type, cause_value); + + ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie); + + /* optional: consider to handle this later */ + ie = (X2AP_X2SetupFailure_IEs_t *)calloc(1, sizeof(X2AP_X2SetupFailure_IEs_t)); + ie->id = X2AP_ProtocolIE_ID_id_TimeToWait; + ie->criticality = X2AP_Criticality_ignore; + ie->value.present = X2AP_X2SetupFailure_IEs__value_PR_TimeToWait; + + if (time_to_wait > -1) { + ie->value.choice.TimeToWait = time_to_wait; + } + + ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie); + + if (x2ap_eNB_encode_pdu(&pdu, &buffer, &len) < 0) { + X2AP_ERROR("Failed to encode X2 setup failure\n"); + return -1; + } + + MSC_LOG_TX_MESSAGE (MSC_X2AP_SRC_ENB, + MSC_X2AP_TARGET_ENB, NULL, 0, + "0 X2Setup/unsuccessfulOutcome assoc_id %u cause %u value %u", + assoc_id, cause_type, cause_value); + + x2ap_eNB_itti_send_sctp_data_req(instance, assoc_id, buffer, len, 0); + + return ret; +} + +int x2ap_eNB_set_cause (X2AP_Cause_t * cause_p, + X2AP_Cause_PR cause_type, + long cause_value) +{ + + DevAssert (cause_p != NULL); + cause_p->present = cause_type; + + switch (cause_type) { + case X2AP_Cause_PR_radioNetwork: + cause_p->choice.misc = cause_value; + break; + + case X2AP_Cause_PR_transport: + cause_p->choice.misc = cause_value; + break; + + case X2AP_Cause_PR_protocol: + cause_p->choice.misc = cause_value; + break; + + case X2AP_Cause_PR_misc: + cause_p->choice.misc = cause_value; + break; + + default: + return -1; + } + + return 0; +} diff --git a/openair2/X2AP/x2ap_eNB_generate_messages.h b/openair2/X2AP/x2ap_eNB_generate_messages.h new file mode 100644 index 0000000000000000000000000000000000000000..a72b37e743da4ff24bdd8cd827ec0ffaeec47713 --- /dev/null +++ b/openair2/X2AP/x2ap_eNB_generate_messages.h @@ -0,0 +1,44 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +#ifndef X2AP_ENB_GENERATE_MESSAGES_H_ +#define X2AP_ENB_GENERATE_MESSAGES_H_ + +#include "x2ap_eNB_defs.h" +#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); + +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, + X2AP_Cause_PR cause_type, + long cause_value, + long time_to_wait); + +int x2ap_eNB_set_cause (X2AP_Cause_t * cause_p, + X2AP_Cause_PR cause_type, + long cause_value); + +#endif /* X2AP_ENB_GENERATE_MESSAGES_H_ */ + diff --git a/openair2/X2AP/x2ap_eNB_handler.c b/openair2/X2AP/x2ap_eNB_handler.c index 180535baa69d932ab85e59ffe40940a4cc362ba6..a16a3da5a8ac9d3b5fd998875fed3e61cd8cc5fc 100644 --- a/openair2/X2AP/x2ap_eNB_handler.c +++ b/openair2/X2AP/x2ap_eNB_handler.c @@ -27,12 +27,72 @@ #include "x2ap_common.h" #include "x2ap_eNB_defs.h" #include "x2ap_eNB_handler.h" +#include "x2ap_eNB_decoder.h" #include "x2ap_eNB_management_procedures.h" +#include "x2ap_eNB_generate_messages.h" +#include "msc.h" #include "assertions.h" #include "conversions.h" +static +int x2ap_eNB_handle_x2_setup_request (instance_t instance, + uint32_t assoc_id, + uint32_t stream, + X2AP_X2AP_PDU_t *pdu); +static +int x2ap_eNB_handle_x2_setup_response (instance_t instance, + uint32_t assoc_id, + uint32_t stream, + X2AP_X2AP_PDU_t *pdu); +static +int x2ap_eNB_handle_x2_setup_failure (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 */ + { 0, 0, 0 }, /* handoverCancel */ + { 0, 0, 0 }, /* loadIndication */ + { 0, 0, 0 }, /* errorIndication */ + { 0, 0, 0 }, /* snStatusTransfer */ + { 0, 0, 0 }, /* uEContextRelease */ + { x2ap_eNB_handle_x2_setup_request, x2ap_eNB_handle_x2_setup_response, x2ap_eNB_handle_x2_setup_failure }, /* x2Setup */ + { 0, 0, 0 }, /* reset */ + { 0, 0, 0 }, /* eNBConfigurationUpdate */ + { 0, 0, 0 }, /* resourceStatusReportingInitiation */ + { 0, 0, 0 }, /* resourceStatusReporting */ + { 0, 0, 0 }, /* privateMessage */ + { 0, 0, 0 }, /* mobilitySettingsChange */ + { 0, 0, 0 }, /* rLFIndication */ + { 0, 0, 0 }, /* handoverReport */ + { 0, 0, 0 }, /* cellActivation */ + { 0, 0, 0 }, /* x2Release */ + { 0, 0, 0 }, /* x2APMessageTransfer */ + { 0, 0, 0 }, /* x2Removal */ + { 0, 0, 0 }, /* 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 */ +}; + +char *x2ap_direction2String(int x2ap_dir) { +static char *x2ap_direction_String[] = { + "", /* Nothing */ + "Originating message", /* originating message */ + "Successfull outcome", /* successfull outcome */ + "UnSuccessfull outcome", /* successfull outcome */ +}; +return(x2ap_direction_String[x2ap_dir]); +} + void x2ap_handle_x2_setup_message(x2ap_eNB_data_t *enb_desc_p, int sctp_shutdown) { if (sctp_shutdown) { @@ -77,3 +137,296 @@ void x2ap_handle_x2_setup_message(x2ap_eNB_data_t *enb_desc_p, int sctp_shutdown } } } + + +int x2ap_eNB_handle_message(instance_t instance, uint32_t assoc_id, int32_t stream, + const uint8_t *const data, const uint32_t data_length) +{ + X2AP_X2AP_PDU_t pdu; + int ret; + + DevAssert(data != NULL); + + memset(&pdu, 0, sizeof(pdu)); + + 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; + } + + /* 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); + ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_X2AP_X2AP_PDU, &pdu); + return ret; +} + +int +x2ap_eNB_handle_x2_setup_request(instance_t instance, + uint32_t assoc_id, + uint32_t stream, + X2AP_X2AP_PDU_t *pdu) +{ + + X2AP_X2SetupRequest_t *x2SetupRequest; + X2AP_X2SetupRequest_IEs_t *ie; + + x2ap_eNB_data_t *x2ap_eNB_data; + uint32_t eNB_id = 0; + + DevAssert (pdu != NULL); + x2SetupRequest = &pdu->choice.initiatingMessage.value.choice.X2SetupRequest; + + /* + * 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 + */ + 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_X2SetupRequest_IEs_t, ie, x2SetupRequest, + X2AP_ProtocolIE_ID_id_GlobalENB_ID, true); + + if (ie->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->value.choice.GlobalENB_ID.eNB_ID.choice.home_eNB_ID.buf; + + if (ie->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->value.choice.GlobalENB_ID.eNB_ID.choice.macro_eNB_ID.buf; + + if (ie->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); + + DevAssert(x2ap_eNB_data->x2ap_eNB_instance != NULL); + x2ap_eNB_generate_x2_setup_failure (x2ap_eNB_data->x2ap_eNB_instance->instance, + assoc_id, + X2AP_Cause_PR_protocol, + X2AP_CauseProtocol_unspecified, + -1); + return -1; + } + /* + * TODO: call the reset procedure + */ + } + + return x2ap_eNB_generate_x2_setup_response(x2ap_eNB_data); +} + +static +int x2ap_eNB_handle_x2_setup_response(instance_t instance, + uint32_t assoc_id, + uint32_t stream, + X2AP_X2AP_PDU_t *pdu) +{ + + X2AP_X2SetupResponse_t *x2SetupResponse; + X2AP_X2SetupResponse_IEs_t *ie; + + x2ap_eNB_data_t *x2ap_eNB_data; + uint32_t eNB_id = 0; + + DevAssert (pdu != NULL); + x2SetupResponse = &pdu->choice.successfulOutcome.value.choice.X2SetupResponse; + + /* + * We received a new valid X2 Setup Response on a stream != 0. + * * * * This should not happen -> reject eNB x2 setup response. + */ + + if (stream != 0) { + X2AP_ERROR("Received new x2 setup response on stream != 0\n"); + } + + if ((x2ap_eNB_data = x2ap_get_eNB(NULL, assoc_id, 0)) == NULL) { + X2AP_ERROR("[SCTP %d] Received X2 setup response for non existing " + "eNB context\n", assoc_id); + return -1; + } + + X2AP_DEBUG("Received a new X2 setup response\n"); + + X2AP_FIND_PROTOCOLIE_BY_ID(X2AP_X2SetupResponse_IEs_t, ie, x2SetupResponse, + X2AP_ProtocolIE_ID_id_GlobalENB_ID, true); + + if (ie->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->value.choice.GlobalENB_ID.eNB_ID.choice.home_eNB_ID.buf; + + if (ie->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->value.choice.GlobalENB_ID.eNB_ID.choice.macro_eNB_ID.buf; + + if (ie->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) { + /* + * ??: Send an overload cause... + */ + 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; + /* + * TODO: call the reset procedure + */ + } + + /* 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; + x2ap_eNB_data->x2ap_eNB_instance->x2_target_enb_associated_nb ++; + x2ap_handle_x2_setup_message(x2ap_eNB_data, 0); + + return 0; +} + +static +int x2ap_eNB_handle_x2_setup_failure(instance_t instance, + uint32_t assoc_id, + uint32_t stream, + X2AP_X2AP_PDU_t *pdu) +{ + + X2AP_X2SetupFailure_t *x2SetupFailure; + X2AP_X2SetupFailure_IEs_t *ie; + + x2ap_eNB_data_t *x2ap_eNB_data; + + DevAssert(pdu != NULL); + + x2SetupFailure = &pdu->choice.unsuccessfulOutcome.value.choice.X2SetupFailure; + + /* + * We received a new valid X2 Setup Failure on a stream != 0. + * * * * This should not happen -> reject eNB x2 setup failure. + */ + + if (stream != 0) { + X2AP_WARN("[SCTP %d] Received x2 setup failure on stream != 0 (%d)\n", + assoc_id, stream); + } + + if ((x2ap_eNB_data = x2ap_get_eNB (NULL, assoc_id, 0)) == NULL) { + X2AP_ERROR("[SCTP %d] Received X2 setup failure for non existing " + "eNB context\n", assoc_id); + return -1; + } + + X2AP_DEBUG("Received a new X2 setup failure\n"); + + X2AP_FIND_PROTOCOLIE_BY_ID(X2AP_X2SetupFailure_IEs_t, ie, x2SetupFailure, + X2AP_ProtocolIE_ID_id_Cause, true); + + + // need a FSM to handle all cases + if ((ie->value.choice.Cause.present == X2AP_Cause_PR_misc) && + (ie->value.choice.Cause.choice.misc == X2AP_CauseMisc_unspecified)) { + X2AP_WARN("Received X2 setup failure for eNB ... eNB is not ready\n"); + } else { + X2AP_ERROR("Received x2 setup failure for eNB... please check your parameters\n"); + } + + x2ap_eNB_data->state = X2AP_ENB_STATE_WAITING; + x2ap_handle_x2_setup_message(x2ap_eNB_data, 0); + + return 0; +} diff --git a/openair2/X2AP/x2ap_eNB_handler.h b/openair2/X2AP/x2ap_eNB_handler.h index 6d65c25a0a01e73bf7b543831b918508237dfc5e..0f93859a84213e273c3a19eac0dd158d1616212e 100644 --- a/openair2/X2AP/x2ap_eNB_handler.h +++ b/openair2/X2AP/x2ap_eNB_handler.h @@ -24,10 +24,10 @@ #include "x2ap_eNB_defs.h" -void x2ap_handle_x2_setup_message(x2ap_eNB_data_t *mme_desc_p, int sctp_shutdown); +void x2ap_handle_x2_setup_message(x2ap_eNB_data_t *eNB_desc_p, int sctp_shutdown); -//int x2ap_eNB_handle_message(uint32_t assoc_id, int32_t stream, - // const uint8_t * const data, const uint32_t data_length); +int x2ap_eNB_handle_message(instance_t instance, uint32_t assoc_id, int32_t stream, + const uint8_t * const data, const uint32_t data_length); #endif /* X2AP_ENB_HANDLERS_H_ */ diff --git a/openair2/X2AP/x2ap_eNB_itti_messaging.c b/openair2/X2AP/x2ap_eNB_itti_messaging.c new file mode 100644 index 0000000000000000000000000000000000000000..d8e1e19afeeae608e1d44b18784ca1ec0aa293a6 --- /dev/null +++ b/openair2/X2AP/x2ap_eNB_itti_messaging.c @@ -0,0 +1,56 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +#include "intertask_interface.h" + +#include "x2ap_eNB_itti_messaging.h" + +void x2ap_eNB_itti_send_sctp_data_req(instance_t instance, int32_t assoc_id, uint8_t *buffer, + uint32_t buffer_length, uint16_t stream) +{ + MessageDef *message_p; + sctp_data_req_t *sctp_data_req; + + message_p = itti_alloc_new_message(TASK_X2AP, SCTP_DATA_REQ); + + sctp_data_req = &message_p->ittiMsg.sctp_data_req; + + sctp_data_req->assoc_id = assoc_id; + sctp_data_req->buffer = buffer; + sctp_data_req->buffer_length = buffer_length; + sctp_data_req->stream = stream; + + itti_send_msg_to_task(TASK_SCTP, instance, message_p); +} + + +void x2ap_eNB_itti_send_sctp_close_association(instance_t instance, int32_t assoc_id) +{ + MessageDef *message_p = NULL; + sctp_close_association_t *sctp_close_association_p = NULL; + + message_p = itti_alloc_new_message(TASK_X2AP, SCTP_CLOSE_ASSOCIATION); + sctp_close_association_p = &message_p->ittiMsg.sctp_close_association; + sctp_close_association_p->assoc_id = assoc_id; + + itti_send_msg_to_task(TASK_SCTP, instance, message_p); +} + diff --git a/openair2/X2AP/x2ap_eNB_itti_messaging.h b/openair2/X2AP/x2ap_eNB_itti_messaging.h new file mode 100644 index 0000000000000000000000000000000000000000..55bf58b6605260c85c70b4d5887f768c42f3e49f --- /dev/null +++ b/openair2/X2AP/x2ap_eNB_itti_messaging.h @@ -0,0 +1,32 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +#ifndef X2AP_ENB_ITTI_MESSAGING_H_ +#define X2AP_ENB_ITTI_MESSAGING_H_ + +void x2ap_eNB_itti_send_sctp_data_req(instance_t instance, int32_t assoc_id, uint8_t *buffer, + uint32_t buffer_length, uint16_t stream); + + +void x2ap_eNB_itti_send_sctp_close_association(instance_t instance, int32_t assoc_id); + + +#endif /* X2AP_ENB_ITTI_MESSAGING_H_ */