Merge remote-tracking branch 'origin/x2' into develop_integration_2018_w39
Signed-off-by: Raphael Defosseux <raphael.defosseux@eurecom.fr>
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
+154
-17
@@ -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);
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
+24
-11
@@ -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:
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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_ */
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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_ */
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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_ */
|
||||
|
||||
@@ -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_ */
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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_ */
|
||||
Reference in New Issue
Block a user