x2ap: implement x2setuprequest, x2setupresponse, x2setupfailure

parent 938e0242
......@@ -476,12 +476,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
......
......@@ -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;
......
......@@ -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;
......
......@@ -61,6 +61,9 @@
#include "enb_paramdef.h"
extern uint16_t sf_ahead;
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()
{
......@@ -2337,8 +2340,7 @@ return 0;
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;
......@@ -2350,6 +2352,88 @@ int RCconfig_X2(MessageDef *msg_p, uint32_t i)
/* get global parameters, defined outside any section in the config file */
config_get( ENBSParams,sizeof(ENBSParams)/sizeof(paramdef_t),NULL);
/* 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;
......@@ -2398,7 +2482,9 @@ int RCconfig_X2(MessageDef *msg_p, uint32_t i)
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 */
......@@ -2425,6 +2511,55 @@ int RCconfig_X2(MessageDef *msg_p, uint32_t i)
"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);
......
......@@ -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)
{
......
......@@ -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
......
......@@ -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,
......@@ -429,8 +442,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:
......
/*
* 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;
}
/*
* 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_ */
......@@ -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;
......
/*
* 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;
}
/*
* 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_ */
/*
* 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;
}
/*
* 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_ */
......@@ -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;
}
......@@ -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_ */
/*
* 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);
}
/*
* 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_ */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment