Commit b767470a authored by Navid Nikaein's avatar Navid Nikaein

x2ap handover updates

parent 982f239b
......@@ -401,6 +401,15 @@ add_library(X2AP_LIB
include_directories ("${X2AP_C_DIR}")
include_directories ("${X2AP_DIR}")
add_library(X2AP_ENB
${X2AP_C_DIR}/x2ap_ies_defs.h
${X2AP_DIR}/x2ap.c
${X2AP_DIR}/x2ap_eNB_decoder.c
${X2AP_DIR}/x2ap_eNB_encoder.c
${X2AP_DIR}/x2ap_eNB_handlers.c
${X2AP_DIR}/x2ap_eNB_itti_messaging.c
${X2AP_DIR}/x2ap_eNB_management_procedures.c
)
# Hardware dependant options
###################################
add_list1_option(NB_ANTENNAS_RX "2" "Number of antennas in reception" "1" "2" "4")
......@@ -460,6 +469,8 @@ include_directories ("${OPENAIR_TARGETS}/ARCH/COMMON")
##############################################################
add_boolean_option(ENABLE_SECURITY True "Enable LTE integrity and ciphering between RRC UE and eNB")
add_boolean_option(ENABLE_USE_MME True "eNB connected to MME (INTERFACE S1-C), not standalone eNB")
add_boolean_option(ENABLE_USE_X2 True "eNB connected to eNB (INTERFACE X2)")
add_boolean_option(NO_RRM True "DO WE HAVE A RADIO RESSOURCE MANAGER: NO")
add_boolean_option(USER_MODE True "????")
......
......@@ -30,7 +30,7 @@
################################################################################
# file build_helper
# brief
# author Laurent Thomas
# author Laurent Thomas and Navid Nikaein
#
#######################################
SUDO='sudo -E'
......@@ -277,6 +277,23 @@ install_asn1c_from_source(){
make > /tmp/log_compile_asn1c 2>&1
$SUDO make install
}
check_install_syscom_software () {
$SUDO apt-get update
$SUDO apt-get install -y pcscd pcsc-tools libccid
$SUDO apt-get install python-setuptools libpcsclite-dev # pyscard dependancies
echo_info "mkdir -p syscom_scripts"
mkdir -p syscom_scripts
cd syscom_scripts
wget http://sourceforge.net/projects/pyscard/files/latest/pyscard-1.7.0.tar.gz
tar -xzvf pyscard-1.7.0.tar.gz
cd pyscard-1.7.0/
echo_info "installing pyscard"
$SUDO python setup.py build_ext install
cd ..
git clone http://cgit.osmocom.org/pysim pysim
git clone -b zecke/tmp http://cgit.osmocom.org/pysim pysim-zecke
}
#################################################
# 2. compile
......
......@@ -33,8 +33,8 @@
#include <stdint.h>
typedef enum {
MIN_MSC_ENV = 0,
MSC_E_UTRAN = MIN_MSC_ENV,
MIN_MSC_ENV = 0,
MSC_E_UTRAN = MIN_MSC_ENV,
MSC_E_UTRAN_LIPA,
MSC_MME_GW,
MSC_MME,
......@@ -70,6 +70,8 @@ typedef enum {
MSC_S11_MME,
MSC_S6A_MME,
MSC_HSS,
MSC_X2AP_SRC_ENB,
MSC_X2AP_TARGET_ENB,
MAX_MSC_PROTOS,
} msc_proto_t;
......
......@@ -27,3 +27,20 @@
*******************************************************************************/
/* eNB application layer -> X2AP messages */
/* ITTI LOG messages */
/* ENCODER */
MESSAGE_DEF(X2AP_RESET_REQUST_LOG , MESSAGE_PRIORITY_MED, IttiMsgText , x2ap_reset_request_log)
MESSAGE_DEF(X2AP_RESOURCE_STATUS_RESPONSE_LOG , MESSAGE_PRIORITY_MED, IttiMsgText , x2ap_resource_status_response_log)
MESSAGE_DEF(X2AP_RESOURCE_STATUS_FAILUIRE_LOG , MESSAGE_PRIORITY_MED, IttiMsgText , x2ap_resource_status_failure_log)
/* DECODER */
MESSAGE_DEF(X2AP_SETUP_REQUEST_LOG , MESSAGE_PRIORITY_MED, IttiMsgText , x2ap_setup_request_log)
/* eNB application layer -> X2AP messages */
MESSAGE_DEF(X2AP_REGISTER_ENB_REQ , MESSAGE_PRIORITY_MED, x2ap_register_enb_req_t , x2ap_register_enb_req)
/* X2AP -> eNB application layer messages */
MESSAGE_DEF(X2AP_REGISTER_ENB_CNF , MESSAGE_PRIORITY_MED, x2ap_register_enb_cnf_t , x2ap_register_enb_cnf)
MESSAGE_DEF(X2AP_DEREGISTERED_ENB_IND , MESSAGE_PRIORITY_MED, x2ap_deregistered_enb_ind_t , x2ap_deregistered_enb_ind)
......@@ -26,3 +26,69 @@
Address : Eurecom, Campus SophiaTech, 450 Route des Chappes, CS 50193 - 06904 Biot Sophia Antipolis cedex, FRANCE
*******************************************************************************/
#ifndef X2AP_MESSAGES_TYPES_H_
#define X2AP_MESSAGES_TYPES_H_
//-------------------------------------------------------------------------------------------//
// Defines to access message fields.
#define X2AP_REGISTER_ENB_REQ(mSGpTR) (mSGpTR)->ittiMsg.x2ap_register_enb_req
#define X2AP_MAX_NB_ENB_IP_ADDRESS 2
// eNB application layer -> X2AP messages
typedef struct x2ap_register_enb_req_s {
/* Unique eNB_id to identify the eNB within EPC.
* For macro eNB ids this field should be 20 bits long.
* For home eNB ids this field should be 28 bits long.
*/
uint32_t eNB_id;
/* The type of the cell */
enum cell_type_e cell_type;
/* Optional name for the cell
* NOTE: the name can be NULL (i.e no name) and will be cropped to 150
* characters.
*/
char *eNB_name;
/* Tracking area code */
uint16_t tac;
/* Mobile Country Code
* Mobile Network Code
*/
uint16_t mcc;
uint16_t mnc;
uint8_t mnc_digit_length;
/*
* EARFCN
*/
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;
/* The local eNB IP address to bind */
net_ip_address_t enb_x2_ip_address;
/* Nb of MME to connect to */
uint8_t nb_x2;
/* List of target eNB to connect to for X2*/
net_ip_address_t target_enb_x2_ip_address[X2AP_MAX_NB_ENB_IP_ADDRESS];
/* Number of SCTP streams used for associations */
uint16_t sctp_in_streams;
uint16_t sctp_out_streams;
} x2ap_register_enb_req_t;
#endif /* X2AP_MESSAGES_TYPES_H_ */
/*******************************************************************************
OpenAirInterface
Copyright(c) 1999 - 2014 Eurecom
Copyright(c) 1999 - 2015 Eurecom
OpenAirInterface is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
......@@ -56,7 +56,11 @@
# include "sctp_eNB_task.h"
# include "gtpv1u_eNB_task.h"
# endif
# if defined(ENABLE_USE_X2)
# include "x2ap.h"
//# include "sctp_eNB_task.h"
//# include "gtpv1u_eNB_task.h"
#endif
extern unsigned char NB_eNB_INST;
#endif
......@@ -194,7 +198,7 @@ static void configure_rrc(uint32_t enb_id, const Enb_properties_array_t *enb_pro
/*------------------------------------------------------------------------------*/
# if defined(ENABLE_USE_MME)
static uint32_t eNB_app_register(uint32_t enb_id_start, uint32_t enb_id_end, const Enb_properties_array_t *enb_properties)
static uint32_t eNB_app_register_s1(uint32_t enb_id_start, uint32_t enb_id_end, const Enb_properties_array_t *enb_properties)
{
uint32_t enb_id;
uint32_t mme_id;
......@@ -264,6 +268,81 @@ static uint32_t eNB_app_register(uint32_t enb_id_start, uint32_t enb_id_end, con
return register_enb_pending;
}
# endif
/*------------------------------------------------------------------------------*/
# if defined(ENABLE_USE_X2)
static uint32_t eNB_app_register_x2(uint32_t enb_id_start, uint32_t enb_id_end, const Enb_properties_array_t *enb_properties)
{
uint32_t enb_id;
uint32_t x2_id;
MessageDef *msg_p;
uint32_t register_enb_x2_pending = 0;
char *str = NULL;
struct in_addr addr;
# if defined(OAI_EMU)
# endif
for (enb_id = enb_id_start; (enb_id < enb_id_end) ; enb_id++) {
# if defined(OAI_EMU)
if (oai_emulation.info.cli_start_enb[enb_id] == 1)
# endif
{
x2ap_register_enb_req_t *x2ap_register_eNB;
msg_p = itti_alloc_new_message (TASK_ENB_APP, X2AP_REGISTER_ENB_REQ);
x2ap_register_eNB = &X2AP_REGISTER_ENB_REQ(msg_p);
/* Some default/random parameters */
x2ap_register_eNB->eNB_id = enb_properties->properties[enb_id]->eNB_id;
x2ap_register_eNB->cell_type = enb_properties->properties[enb_id]->cell_type;
x2ap_register_eNB->eNB_name = enb_properties->properties[enb_id]->eNB_name;
x2ap_register_eNB->tac = enb_properties->properties[enb_id]->tac;
x2ap_register_eNB->mcc = enb_properties->properties[enb_id]->mcc;
x2ap_register_eNB->mnc = enb_properties->properties[enb_id]->mnc;
x2ap_register_eNB->mnc_digit_length = enb_properties->properties[enb_id]->mnc_digit_length;
x2ap_register_eNB->nb_x2 = enb_properties->properties[enb_id]->nb_x2;
AssertFatal (x2ap_register_eNB->nb_x2 <= X2AP_MAX_NB_ENB_IP_ADDRESS, "Too many X2 interfaces for eNB %d (%d/%d)!",
enb_id, x2ap_register_eNB->nb_x2,
X2AP_MAX_NB_ENB_IP_ADDRESS);
for (x2_id = 0; x2_id < x2ap_register_eNB->nb_x2; x2_id++) {
x2ap_register_eNB->target_enb_x2_ip_address[x2_id].ipv4 = enb_properties->properties[enb_id]->target_enb_x2_ip_address[x2_id].ipv4;
x2ap_register_eNB->target_enb_x2_ip_address[x2_id].ipv6 = enb_properties->properties[enb_id]->target_enb_x2_ip_address[x2_id].ipv6;
strncpy (x2ap_register_eNB->target_enb_x2_ip_address[x2_id].ipv4_address,
enb_properties->properties[enb_id]->target_enb_x2_ip_address[x2_id].ipv4_address,
sizeof(x2ap_register_eNB->target_enb_x2_ip_address[0].ipv4_address));
strncpy (x2ap_register_eNB->target_enb_x2_ip_address[x2_id].ipv6_address,
enb_properties->properties[enb_id]->target_enb_x2_ip_address[x2_id].ipv6_address,
sizeof(x2ap_register_eNB->target_enb_x2_ip_address[0].ipv6_address));
}
x2ap_register_eNB->sctp_in_streams = enb_properties->properties[enb_id]->sctp_in_streams;
x2ap_register_eNB->sctp_out_streams = enb_properties->properties[enb_id]->sctp_out_streams;
x2ap_register_eNB->enb_x2_ip_address.ipv6 = 0;
x2ap_register_eNB->enb_x2_ip_address.ipv4 = 1;
addr.s_addr = enb_properties->properties[enb_id]->enb_ipv4_address_for_X2C;
str = inet_ntoa(addr);
strcpy(x2ap_register_eNB->enb_x2_ip_address.ipv4_address, str);
itti_send_msg_to_task (TASK_X2AP, ENB_MODULE_ID_TO_INSTANCE(enb_id), msg_p);
register_enb_x2_pending++;
}
}
return register_enb_x2_pending;
}
# endif
#endif
/*------------------------------------------------------------------------------*/
......@@ -275,9 +354,14 @@ void *eNB_app_task(void *args_p)
uint32_t enb_id_start = 0;
uint32_t enb_id_end = enb_id_start + enb_nb;
# if defined(ENABLE_USE_MME)
uint32_t register_enb_pending;
uint32_t register_enb_pending; // s1ap
uint32_t registered_enb;
long enb_register_retry_timer_id;
# endif
# if defined(ENABLE_USE_X2)
uint32_t x2ap_register_enb_pending;
uint32_t x2ap_registered_enb;
long x2ap_enb_register_retry_timer_id;
# endif
uint32_t enb_id;
MessageDef *msg_p = NULL;
......@@ -311,15 +395,25 @@ void *eNB_app_task(void *args_p)
}
# if defined(ENABLE_USE_MME)
/* Try to register each eNB */
/* Try to register each eNB with MME*/
registered_enb = 0;
register_enb_pending = eNB_app_register (enb_id_start, enb_id_end, enb_properties_p);
register_enb_pending = eNB_app_register_s1 (enb_id_start, enb_id_end, enb_properties_p);
# else
/* Start L2L1 task */
msg_p = itti_alloc_new_message(TASK_ENB_APP, INITIALIZE_MESSAGE);
itti_send_msg_to_task(TASK_L2L1, INSTANCE_DEFAULT, msg_p);
# endif
# if defined(ENABLE_USE_X2)
/* Try to register each eNB with each other */
registered_enb_x2 = 0;
register_enb_x2_pending = eNB_app_register_x2 (enb_id_start, enb_id_end, enb_properties_p);
# else
# endif
do {
// Wait for a message
itti_receive_msg (TASK_ENB_APP, &msg_p);
......@@ -383,7 +477,7 @@ void *eNB_app_task(void *args_p)
sleep(ENB_REGISTER_RETRY_DELAY);
/* Restart the registration process */
registered_enb = 0;
register_enb_pending = eNB_app_register (enb_id_start, enb_id_end, enb_properties_p);
register_enb_pending = eNB_app_register_s1 (enb_id_start, enb_id_end, enb_properties_p);
}
}
}
......@@ -403,12 +497,48 @@ void *eNB_app_task(void *args_p)
if (TIMER_HAS_EXPIRED (msg_p).timer_id == enb_register_retry_timer_id) {
/* Restart the registration process */
registered_enb = 0;
register_enb_pending = eNB_app_register (enb_id_start, enb_id_end, enb_properties_p);
register_enb_pending = eNB_app_register_s1 (enb_id_start, enb_id_end, enb_properties_p);
}
break;
# endif
#ifdef ENABLE_USE_X2
case X2AP_DEREGISTERED_ENB_IND:
LOG_W(ENB_APP, "[eNB %d] Received %s: associated eNB %d\n", instance, msg_name,
X2AP_DEREGISTERED_ENB_IND(msg_p).nb_x2);
/* TODO handle recovering of registration */
break;
case S1AP_REGISTER_ENB_CNF:
LOG_I(ENB_APP, "[eNB %d] Received %s: associated eNB %d\n", instance, msg_name,
X2AP_REGISTER_ENB_CNF(msg_p).nb_x2);
DevAssert(register_enb_x2_pending > 0);
register_enb_x2_pending--;
/* Check if at least eNB is registered with one target eNB */
if (X2AP_REGISTER_ENB_CNF(msg_p).nb_x2 > 0) {
registered_enb_x2++;
}
/* Check if all register eNB requests have been processed */
if (register_enb_x2_pending == 0) {
if (registered_enb_x2 == enb_nb) {
/* If all eNB are registered, start L2L1 task */
}else {
uint32_t not_associated_x2 = enb_nb - registered_enb;
LOG_W(ENB_APP, " %d eNB %s not associated with the target\n",
not_associated, not_associated > 1 ? "are" : "is");
// timer to retry
}
}
break;
# endif
#endif
default:
LOG_E(ENB_APP, "Received unexpected message %s\n", msg_name);
break;
......
......@@ -153,12 +153,19 @@
#define ENB_CONFIG_STRING_SRB1_POLL_PDU "poll_pdu"
#define ENB_CONFIG_STRING_SRB1_POLL_BYTE "poll_byte"
#define ENB_CONFIG_STRING_SRB1_MAX_RETX_THRESHOLD "max_retx_threshold"
#define ENB_CONFIG_STRING_MME_IP_ADDRESS "mme_ip_address"
#define ENB_CONFIG_STRING_MME_IPV4_ADDRESS "ipv4"
#define ENB_CONFIG_STRING_MME_IPV6_ADDRESS "ipv6"
#define ENB_CONFIG_STRING_MME_IP_ADDRESS_ACTIVE "active"
#define ENB_CONFIG_STRING_MME_IP_ADDRESS_PREFERENCE "preference"
#define ENB_CONFIG_STRING_TARGET_ENB_X2_IP_ADDRESS "target_enb_x2_ip_address"
#define ENB_CONFIG_STRING_TARGET_ENB_X2_IPV4_ADDRESS "ipv4"
#define ENB_CONFIG_STRING_TARGET_ENB_X2_IPV6_ADDRESS "ipv6"
#define ENB_CONFIG_STRING_TARGET_ENB_X2_IP_ADDRESS_ACTIVE "active"
#define ENB_CONFIG_STRING_TARGET_ENB_X2_IP_ADDRESS_PREFERENCE "preference"
#define ENB_CONFIG_STRING_SCTP_CONFIG "SCTP"
#define ENB_CONFIG_STRING_SCTP_INSTREAMS "SCTP_INSTREAMS"
#define ENB_CONFIG_STRING_SCTP_OUTSTREAMS "SCTP_OUTSTREAMS"
......@@ -169,7 +176,12 @@
#define ENB_CONFIG_STRING_ENB_INTERFACE_NAME_FOR_S1U "ENB_INTERFACE_NAME_FOR_S1U"
#define ENB_CONFIG_STRING_ENB_IPV4_ADDR_FOR_S1U "ENB_IPV4_ADDRESS_FOR_S1U"
#define ENB_CONFIG_STRING_ENB_PORT_FOR_S1U "ENB_PORT_FOR_S1U"
#define ENB_CONFIG_STRING_ENB_INTERFACE_NAME_FOR_X2C "ENB_INTERFACE_NAME_FOR_X2C"
#define ENB_CONFIG_STRING_ENB_IPV4_ADDR_FOR_X2C "ENB_IPV4_ADDRESS_FOR_X2C"
#define ENB_CONFIG_STRING_ENB_PORT_FOR_X2C "ENB_PORT_FOR_X2C"
#define ENB_CONFIG_STRING_ENB_INTERFACE_NAME_FOR_X2U "ENB_INTERFACE_NAME_FOR_X2U"
#define ENB_CONFIG_STRING_ENB_IPV4_ADDR_FOR_X2U "ENB_IPV4_ADDRESS_FOR_X2U"
#define ENB_CONFIG_STRING_ENB_PORT_FOR_X2U "ENB_PORT_FOR_X2U"
#define ENB_CONFIG_STRING_ASN1_VERBOSITY "Asn1_verbosity"
#define ENB_CONFIG_STRING_ASN1_VERBOSITY_NONE "none"
......@@ -372,6 +384,9 @@ static void enb_config_display(void)
printf( "\tue_TimersAndConstants_n311 for CC %d:\t%ld:\n",j,enb_properties.properties[i]->ue_TimersAndConstants_n311[j]);
}
for (j=0; j < enb_properties.properties[i]->nb_x2; j++) {
printf( "\n\tTarget eNB IPv4 address: \t%s", enb_properties.properties[i]->target_enb_x2_ip_address[j].ipv4_address);
}
for (j=0; j < enb_properties.properties[i]->num_otg_elements; j++) {
printf( "\n\tOTG Destination UE ID: \t%"PRIu16, enb_properties.properties[i]->otg_ue_id[j]);
......@@ -455,6 +470,8 @@ const Enb_properties_array_t *enb_config_init(char* lib_config_file_name_pP)
config_setting_t *setting_srb1 = NULL;
config_setting_t *setting_mme_addresses = NULL;
config_setting_t *setting_mme_address = NULL;
config_setting_t *setting_x2_addresses = NULL;
config_setting_t *setting_x2_address = NULL;
config_setting_t *setting_enb = NULL;
config_setting_t *setting_otg = NULL;
config_setting_t *subsetting_otg = NULL;
......@@ -462,6 +479,7 @@ const Enb_properties_array_t *enb_config_init(char* lib_config_file_name_pP)
int enb_properties_index = 0;
int num_enbs = 0;
int num_mme_address = 0;
int num_x2_address = 0;
int num_otg_elements =0;
int num_component_carriers =0;
int i = 0;
......@@ -565,9 +583,15 @@ const Enb_properties_array_t *enb_config_init(char* lib_config_file_name_pP)
const char* active_enb[MAX_ENB];
char* enb_interface_name_for_S1U = NULL;
char* enb_ipv4_address_for_S1U = NULL;
char* enb_interface_name_for_X2U = NULL;
char* enb_ipv4_address_for_X2U = NULL;
libconfig_int enb_port_for_S1U = 0;
libconfig_int enb_port_for_X2U = 0;
char* enb_interface_name_for_S1_MME = NULL;
char* enb_ipv4_address_for_S1_MME = NULL;
char* enb_interface_name_for_X2C = NULL;
char* enb_ipv4_address_for_X2C = NULL;
libconfig_int enb_port_for_X2C = 0;
char *address = NULL;
char *cidr = NULL;
char *astring = NULL;
......@@ -2137,6 +2161,49 @@ const Enb_properties_array_t *enb_config_init(char* lib_config_file_name_pP)
}
}
// X2_ENB_IP_ADDRESS
setting_x2_addresses = config_setting_get_member (setting_enb, ENB_CONFIG_STRING_TARGET_ENB_X2_IP_ADDRESS);
num_x2_address = config_setting_length(setting_x2_addresses);
enb_properties.properties[enb_properties_index]->nb_x2 = 0;
for (j = 0; j < num_x2_address; j++) {
setting_x2_address = config_setting_get_elem(setting_x2_addresses, j);
if ( !(
config_setting_lookup_string(setting_x2_address, ENB_CONFIG_STRING_TARGET_ENB_X2_IPV4_ADDRESS, (const char **)&ipv4)
&& config_setting_lookup_string(setting_x2_address, ENB_CONFIG_STRING_TARGET_ENB_X2_IPV6_ADDRESS, (const char **)&ipv6)
&& config_setting_lookup_string(setting_x2_address, ENB_CONFIG_STRING_TARGET_ENB_X2_IP_ADDRESS_ACTIVE, (const char **)&active)
&& config_setting_lookup_string(setting_x2_address, ENB_CONFIG_STRING_TARGET_ENB_X2_IP_ADDRESS_PREFERENCE, (const char **)&preference)
)
) {
AssertError (0, parse_errors ++,
"Failed to parse eNB configuration file %s, %u th enb %u the X2 address !\n",
lib_config_file_name_pP, i, j);
continue; // FIXME will prevent segfaults below, not sure what happens at function exit...
}
enb_properties.properties[enb_properties_index]->nb_x2 += 1;
enb_properties.properties[enb_properties_index]->target_enb_x2_ip_address[j].ipv4_address = strdup(ipv4);
enb_properties.properties[enb_properties_index]->target_enb_x2_ip_address[j].ipv6_address = strdup(ipv6);
if (strcmp(active, "yes") == 0) {
enb_properties.properties[enb_properties_index]->target_enb_x2_ip_address[j].active = 1;
} // else { (calloc)
if (strcmp(preference, "ipv4") == 0) {
enb_properties.properties[enb_properties_index]->target_enb_x2_ip_address[j].ipv4 = 1;
} else if (strcmp(preference, "ipv6") == 0) {
enb_properties.properties[enb_properties_index]->target_enb_x2_ip_address[j].ipv6 = 1;
} else if (strcmp(preference, "no") == 0) {
enb_properties.properties[enb_properties_index]->target_enb_x2_ip_address[j].ipv4 = 1;
enb_properties.properties[enb_properties_index]->target_enb_x2_ip_address[j].ipv6 = 1;
}
}
// SCTP SETTING
enb_properties.properties[enb_properties_index]->sctp_out_streams = SCTP_OUT_STREAMS;
enb_properties.properties[enb_properties_index]->sctp_in_streams = SCTP_IN_STREAMS;
......@@ -2169,6 +2236,19 @@ const Enb_properties_array_t *enb_config_init(char* lib_config_file_name_pP)
(const char **)&enb_ipv4_address_for_S1U)
&& config_setting_lookup_int(subsetting, ENB_CONFIG_STRING_ENB_PORT_FOR_S1U,
&enb_port_for_S1U)
&& config_setting_lookup_string( subsetting, ENB_CONFIG_STRING_ENB_INTERFACE_NAME_FOR_X2C,
(const char **)&enb_interface_name_for_X2C)
&& config_setting_lookup_string( subsetting, ENB_CONFIG_STRING_ENB_IPV4_ADDR_FOR_X2C,
(const char **)&enb_ipv4_address_for_X2C)
&& config_setting_lookup_int(subsetting, ENB_CONFIG_STRING_ENB_PORT_FOR_X2C,
&enb_port_for_X2C)
&& config_setting_lookup_string( subsetting, ENB_CONFIG_STRING_ENB_INTERFACE_NAME_FOR_X2U,
(const char **)&enb_interface_name_for_X2U)
&& config_setting_lookup_string( subsetting, ENB_CONFIG_STRING_ENB_IPV4_ADDR_FOR_X2U,
(const char **)&enb_ipv4_address_for_X2U)
&& config_setting_lookup_int(subsetting, ENB_CONFIG_STRING_ENB_PORT_FOR_X2U,
&enb_port_for_X2U)
)
) {
enb_properties.properties[enb_properties_index]->enb_interface_name_for_S1U = strdup(enb_interface_name_for_S1U);
......@@ -2188,6 +2268,26 @@ const Enb_properties_array_t *enb_config_init(char* lib_config_file_name_pP)
if (address) {
IPV4_STR_ADDR_TO_INT_NWBO ( address, enb_properties.properties[enb_properties_index]->enb_ipv4_address_for_S1_MME, "BAD IP ADDRESS FORMAT FOR eNB S1_MME !\n" );
}
enb_properties.properties[enb_properties_index]->enb_interface_name_for_X2U = strdup(enb_interface_name_for_X2U);
cidr = enb_ipv4_address_for_X2U;
address = strtok(cidr, "/");
if (address) {
IPV4_STR_ADDR_TO_INT_NWBO ( address, enb_properties.properties[enb_properties_index]->enb_ipv4_address_for_X2U, "BAD IP ADDRESS FORMAT FOR eNB X2U !\n" );
}
enb_properties.properties[enb_properties_index]->enb_port_for_X2U = enb_port_for_X2U;
enb_properties.properties[enb_properties_index]->enb_interface_name_for_X2C = strdup(enb_interface_name_for_X2C);
cidr = enb_ipv4_address_for_X2C;
address = strtok(cidr, "/");
if (address) {
IPV4_STR_ADDR_TO_INT_NWBO ( address, enb_properties.properties[enb_properties_index]->enb_ipv4_address_for_X2C, "BAD IP ADDRESS FORMAT FOR eNB X2C !\n" );
}
enb_properties.properties[enb_properties_index]->enb_port_for_X2C = enb_port_for_X2C;
}
}
......
......@@ -46,6 +46,7 @@
#include "platform_constants.h"
#include "PHY/impl_defs_lte.h"
#include "s1ap_messages_types.h"
#include "x2ap_messages_types.h"
#ifdef CMAKER
#include "SystemInformationBlockType2.h"
#else
......@@ -78,6 +79,15 @@ typedef struct mme_ip_address_s {
char *ipv6_address;
} mme_ip_address_t;
typedef struct x2_enb_ip_address_s {
unsigned ipv4:1;
unsigned ipv6:1;
unsigned active:1;
char *ipv4_address;
char *ipv6_address;
} x2_enb_ip_address_t;
typedef struct Enb_properties_s {
/* Unique eNB_id to identify the eNB within EPC.
* For macro eNB ids this field should be 20 bits long.
......@@ -193,6 +203,11 @@ typedef struct Enb_properties_s {
/* List of MME to connect to */
mme_ip_address_t mme_ip_address[S1AP_MAX_NB_MME_IP_ADDRESS];
/* Nb of X2 to connect to */
uint8_t nb_x2;
/* List of X2 to connect to */
x2_enb_ip_address_t target_enb_x2_ip_address[X2AP_MAX_NB_ENB_IP_ADDRESS];
int sctp_in_streams;
int sctp_out_streams;
......@@ -203,6 +218,14 @@ typedef struct Enb_properties_s {
char *enb_interface_name_for_S1_MME;
in_addr_t enb_ipv4_address_for_S1_MME;
char *enb_interface_name_for_X2U;
in_addr_t enb_ipv4_address_for_X2U;
tcp_udp_port_t enb_port_for_X2U;
char *enb_interface_name_for_X2C;
in_addr_t enb_ipv4_address_for_X2C;
tcp_udp_port_t enb_port_for_X2C;
// otg config
/* Nb of OTG elements */
uint8_t num_otg_elements;
......
......@@ -3564,7 +3564,7 @@ static void rrc_ue_generate_MeasurementReport( const protocol_ctxt_t* const ctxt
UE_rrc_inst[ctxt_pP->module_id].rsrq_db_filtered[target_eNB_offset]);
// if (measFlag == 1) {
cellId = get_adjacent_cell_id(ctxt_pP->module_id, eNB_index); //PhycellId of serving cell
cellId = eNB_index; //get_adjacent_cell_id(ctxt_pP->module_id, eNB_index); //PhycellId of serving cell
targetCellId = UE_rrc_inst[ctxt_pP->module_id].HandoverInfoUe.targetCellId ;//get_adjacent_cell_id(ue_mod_idP,target_eNB_offset); //PhycellId of target cell
if (pframe!=ctxt_pP->frame) {
......@@ -3628,7 +3628,7 @@ void ue_measurement_report_triggering( const protocol_ctxt_t* const ctxt_pP, con
ttt_ms = timeToTrigger_ms[UE_rrc_inst[ctxt_pP->module_id].ReportConfig[i][reportConfigId
-1]->reportConfig.choice.reportConfigEUTRA.triggerType.choice.event.timeToTrigger];
// Freq specific offset of neighbor cell freq
ofn = 5;//((UE_rrc_inst[ctxt_pP->module_id].MeasObj[i][measObjId-1]->measObject.choice.measObjectEUTRA.offsetFreq != NULL) ?
ofn = 15;//((UE_rrc_inst[ctxt_pP->module_id].MeasObj[i][measObjId-1]->measObject.choice.measObjectEUTRA.offsetFreq != NULL) ?
// *UE_rrc_inst[ctxt_pP->module_id].MeasObj[i][measObjId-1]->measObject.choice.measObjectEUTRA.offsetFreq : 15); // /* 15 is the Default */
// cellIndividualOffset of neighbor cell - not defined yet
ocn = 0;
......
......@@ -1839,7 +1839,7 @@ rrc_eNB_generate_HandoverPreparationInformation(
memcpy((void *)&handoverInfo->as_config.sourceMasterInformationBlock,
(void*)&eNB_rrc_inst[ctxt_pP->module_id].carrier[0] /* CROUX TBC */.mib, sizeof(MasterInformationBlock_t));
memcpy((void *)&handoverInfo->as_config.sourceMeasConfig,
(void*)ue_context_pP->ue_context.measConfig, sizeof(MeasConfig_t));
(void*)&ue_context_pP->ue_context.measConfig, sizeof(MeasConfig_t));
// FIXME handoverInfo not used...
free( handoverInfo );
......@@ -1861,7 +1861,7 @@ rrc_eNB_generate_HandoverPreparationInformation(
ue_context_pP->ue_context.handover_info->as_context.reestablishmentInfo->targetCellShortMAC_I.size = 0;
ue_context_pP->ue_context.handover_info->as_context.reestablishmentInfo->targetCellShortMAC_I.bits_unused = 0;
ue_context_pP->ue_context.handover_info->as_context.reestablishmentInfo->additionalReestabInfoList = NULL;
ue_context_pP->ue_context.handover_info->ho_prepare = 0xFF; //0xF0;
ue_context_pP->ue_context.handover_info->ho_prepare = 0xFF;
ue_context_pP->ue_context.handover_info->ho_complete = 0;
if (mod_id_target != 0xFF) {
......@@ -1950,7 +1950,7 @@ check_handovers(
if (ue_context_p->ue_context.handover_info != NULL) {
if (ue_context_p->ue_context.handover_info->ho_prepare == 0xFF) {
LOG_D(RRC,
"[eNB %d] Frame %d: Incoming handover detected for new UE_idx %d (source eNB %d->target eNB %d) \n",
"[eNB %d] Frame %d: Incoming handover detected for new UE_id %x (source eNB %d->target eNB %d) \n",
ctxt_pP->module_id,
ctxt_pP->frame,
ctxt_pP->rnti,
......@@ -1960,29 +1960,29 @@ check_handovers(
rrc_eNB_process_handoverPreparationInformation(
ctxt_pP,
ue_context_p);
ue_context_p->ue_context.handover_info->ho_prepare = 0xF1;
ue_context_p->ue_context.handover_info->ho_prepare = 0xF0;
}
if (ue_context_p->ue_context.handover_info->ho_complete == 0xF1) {
LOG_D(RRC,
"[eNB %d] Frame %d: handover Command received for new UE_id %x current eNB %d target eNB: %d \n",
ctxt_pP->module_id,
ctxt_pP->frame,
ctxt_pP->rnti,
ctxt_pP->module_id,
ue_context_p->ue_context.handover_info->modid_t);
//if (ue_context_p->ue_context.handover_info->ho_complete == 0xF1) {
//LOG_D(RRC,
// "[eNB %d] Frame %d: handover Command received for new UE_id %x current eNB %d target eNB: %d \n",
//ctxt_pP->module_id,
//ctxt_pP->frame,
//ctxt_pP->rnti,
//ctxt_pP->module_id,
//ue_context_p->ue_context.handover_info->modid_t);
//rrc_eNB_process_handoverPreparationInformation(enb_mod_idP,frameP,i);
result = pdcp_data_req(ctxt_pP,
SRB_FLAG_YES,
DCCH,
rrc_eNB_mui++,
SDU_CONFIRM_NO,
ue_context_p->ue_context.handover_info->size,
ue_context_p->ue_context.handover_info->buf,
PDCP_TRANSMISSION_MODE_CONTROL);
AssertFatal(result == TRUE, "PDCP data request failed!\n");
ue_context_p->ue_context.handover_info->ho_complete = 0xF2;
}
//result = pdcp_data_req(ctxt_pP,
//SRB_FLAG_YES,
//DCCH,
//rrc_eNB_mui++,
//SDU_CONFIRM_NO,
//ue_context_p->ue_context.handover_info->size,
//ue_context_p->ue_context.handover_info->buf,
//PDCP_TRANSMISSION_MODE_CONTROL);
//AssertFatal(result == TRUE, "PDCP data request failed!\n");
//ue_context_p->ue_context.handover_info->ho_complete = 0xF2;
//}
}
}
}
......@@ -2277,6 +2277,7 @@ rrc_eNB_generate_RRCConnectionReconfiguration_handover(
LOG_D(RRC,
"handover_config [FRAME %05d][RRC_eNB][MOD %02d][][--- MAC_CONFIG_REQ (SRB1 UE %x) --->][MAC_eNB][MOD %02d][]\n",
ctxt_pP->frame, ctxt_pP->module_id, ue_context_pP->ue_context.rnti, ctxt_pP->module_id);
rrc_mac_config_req(
ctxt_pP->module_id,
ue_context_pP->ue_context.primaryCC_id,
......@@ -2780,7 +2781,7 @@ rrc_eNB_generate_RRCConnectionReconfiguration_handover(
// rrc_pdcp_config_req (enb_mod_idP, frameP, 1, CONFIG_ACTION_ADD, idx, UNDEF_SECURITY_MODE);
// rrc_rlc_config_req(enb_mod_idP,frameP,1,CONFIG_ACTION_ADD,Idx,SIGNALLING_RADIO_BEARER,Rlc_info_am_config);
rrc_pdcp_config_asn1_req(&ctxt,
rrc_pdcp_config_asn1_req(ctxt_pP,
ue_context_pP->ue_context.SRB_configList,
(DRB_ToAddModList_t *) NULL, (DRB_ToReleaseList_t *) NULL, 0xff, NULL, NULL, NULL
#ifdef Rel10
......@@ -2788,7 +2789,7 @@ rrc_eNB_generate_RRCConnectionReconfiguration_handover(
#endif
);
rrc_rlc_config_asn1_req(&ctxt,
rrc_rlc_config_asn1_req(ctxt_pP,
ue_context_pP->ue_context.SRB_configList,
(DRB_ToAddModList_t *) NULL, (DRB_ToReleaseList_t *) NULL
#ifdef Rel10
......@@ -2849,6 +2850,7 @@ rrc_eNB_generate_RRCConnectionReconfiguration_handover(
ctxt_pP->frame, ctxt_pP->module_id, size, ue_context_pP->ue_context.rnti, rrc_eNB_mui, ctxt_pP->module_id, DCCH);
//rrc_rlc_data_req(ctxt_pP->module_id,frameP, 1,(ue_mod_idP*NB_RB_MAX)+DCCH,rrc_eNB_mui++,0,size,(char*)buffer);
//pdcp_data_req (ctxt_pP->module_id, frameP, 1, (ue_mod_idP * NB_RB_MAX) + DCCH,rrc_eNB_mui++, 0, size, (char *) buffer, 1);
rrc_mac_config_req(
ctxt_pP->module_id,
ue_context_pP->ue_context.primaryCC_id,
......@@ -2906,6 +2908,9 @@ rrc_eNB_generate_RRCConnectionReconfiguration_handover(
ctxt_pP->module_id, ctxt_pP->frame);
#endif
pdcp_rrc_data_req(ctxt_pP,DCCH,rrc_eNB_mui++,SDU_CONFIRM_NO,size,buffer,PDCP_TRANSMISSION_MODE_CONTROL);
}
/*
......
0 0 1800 4800 200
10 0 4700 4840 200
20 0 6500 4880 200
0 0 1800 4700 200
0 0 2680 4800 0
0 1 4648 4800 0
0 2 6648 4800 0
......@@ -27,6 +27,15 @@
*******************************************************************************/
/*! \file x2ap.c
* \brief x2ap protocol
* \author Navid Nikaein
* \date 2014 - 2015
* \version 1.0
* \company Eurecom
* \email: navid.nikaein@eurecom.fr
*/
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
......@@ -37,9 +46,207 @@
#include "x2ap.h"
#include "msc.h"
#include "assertions.h"
#include "conversions.h"
static
void x2ap_eNB_handle_register_eNB(instance_t instance,
x2ap_register_enb_req_t *x2ap_register_eNB);
static
void x2ap_eNB_register_eNB(x2ap_eNB_instance_t *instance_p,
net_ip_address_t *target_eNB_ip_addr,
net_ip_address_t *local_ip_addr,
uint16_t in_streams,
uint16_t out_streams);
static
void x2ap_eNB_handle_sctp_association_resp(instance_t instance,
sctp_new_association_resp_t *sctp_new_association_resp);
static
int x2ap_eNB_generate_x2_setup_request(x2ap_eNB_instance_t *instance_p,
x2ap_enb_data_t *x2ap_enb_data_p);
static
int x2ap_eNB_generate_x2_setup_response(x2ap_eNB_instance_t *instance_p,
x2ap_enb_data_t *x2ap_enb_data_p);
static
int x2ap_eNB_generate_x2_setup_failure(x2ap_eNB_instance_t *instance_p,
x2ap_enb_data_t *x2ap_enb_data_p);
static
void x2ap_eNB_handle_sctp_data_ind(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,
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)
{
x2ap_eNB_instance_t *instance_p;
x2ap_eNB_mme_data_t *x2ap_enb_data_p;
DevAssert(sctp_new_association_resp != NULL);
instance_p = x2ap_eNB_get_instance(instance);
DevAssert(instance_p != NULL);
x2ap_enb_data_p = x2ap_eNB_get_eNB(instance_p, -1,
sctp_new_association_resp->ulp_cnx_id);
DevAssert(x2ap_enb_data_p != NULL);
if (sctp_new_association_resp->sctp_state != SCTP_STATE_ESTABLISHED) {
S1AP_WARN("Received unsuccessful result for SCTP association (%u), instance %d, cnx_id %u\n",
sctp_new_association_resp->sctp_state,
instance,
sctp_new_association_resp->ulp_cnx_id);
//x2ap_handle_x2_setup_message(x2ap_enb_data_p, sctp_new_association_resp->sctp_state == SCTP_STATE_SHUTDOWN);
return;
}
/* Update parameters */
x2ap_enb_data_p->assoc_id = sctp_new_association_resp->assoc_id;
x2ap_enb_data_p->in_streams = sctp_new_association_resp->in_streams;
x2ap_enb_data_p->out_streams = sctp_new_association_resp->out_streams;
/* Prepare new x2 Setup Request */
x2ap_eNB_generate_x2_setup_request(instance_p, x2ap_enb_data_p);
}
static void x2ap_eNB_register_eNB(x2ap_eNB_instance_t *instance_p,
net_ip_address_t *target_eNB_ip_address,
net_ip_address_t *local_ip_addr,
uint16_t in_streams,
uint16_t out_streams)
{
MessageDef *message_p = NULL;
sctp_new_association_req_t *sctp_new_association_req_p = NULL;
x2ap_eNB_data_t *x2ap_enb_data_p = NULL;
DevAssert(instance_p != NULL);
DevAssert(target_eNB_ip_address != NULL);
message_p = itti_alloc_new_message(TASK_X2AP, SCTP_NEW_ASSOCIATION_REQ);
sctp_new_association_req_p = &message_p->ittiMsg.sctp_new_association_req;
sctp_new_association_req_p->port = X2AP_PORT_NUMBER;
sctp_new_association_req_p->ppid = X2AP_SCTP_PPID;
sctp_new_association_req_p->in_streams = in_streams;
sctp_new_association_req_p->out_streams = out_streams;
memcpy(&sctp_new_association_req_p->remote_address,
target_eNB_ip_address,
sizeof(*target_eNB_ip_address));
memcpy(&sctp_new_association_req_p->local_address,
local_ip_addr,
sizeof(*local_ip_addr));
/* Create new MME descriptor */
x2ap_enb_data_p = calloc(1, sizeof(*x2ap_enb_data_p));
DevAssert(x2ap_enb_data_p != NULL);
x2ap_enb_data_p->cnx_id = x2ap_eNB_fetch_add_global_cnx_id();
sctp_new_association_req_p->ulp_cnx_id = x2ap_enb_data_p->cnx_id;
x2ap_enb_data_p->assoc_id = -1;
x2ap_enb_data_p->x2ap_eNB_instance = instance_p;
/* Insert the new descriptor in list of known eNB
* but not yet associated.
*/
RB_INSERT(x2ap_enb_map, &instance_p->x2ap_enb_head, x2ap_enb_data_p);
s1ap_mme_data_p->state = X2AP_ENB_STATE_WAITING;
instance_p->x2ap_enb_nb ++;
instance_p->x2ap_enb_pending_nb ++;
itti_send_msg_to_task(TASK_SCTP, instance_p->instance, message_p);
}
static
void x2ap_eNB_handle_register_eNB(instance_t instance, x2ap_register_enb_req_t *x2ap_register_eNB)
{
x2ap_eNB_instance_t *new_instance;
uint8_t index;
DevAssert(x2ap_register_eNB != NULL);
/* Look if the provided instance already exists */
new_instance = x2ap_eNB_get_instance(instance);
if (new_instance != NULL) {
/* Checks if it is a retry on the same eNB */
DevCheck(new_instance->eNB_id == x2ap_register_eNB->eNB_id, new_instance->eNB_id, x2ap_register_eNB->eNB_id, 0);
DevCheck(new_instance->cell_type == x2ap_register_eNB->cell_type, new_instance->cell_type, x2ap_register_eNB->cell_type, 0);
DevCheck(new_instance->tac == x2ap_register_eNB->tac, new_instance->tac, x2ap_register_eNB->tac, 0);
DevCheck(new_instance->mcc == x2ap_register_eNB->mcc, new_instance->mcc, x2ap_register_eNB->mcc, 0);
DevCheck(new_instance->mnc == x2ap_register_eNB->mnc, new_instance->mnc, x2ap_register_eNB->mnc, 0);
}
else {
new_instance = calloc(1, sizeof(x2ap_eNB_instance_t));
DevAssert(new_instance != NULL);
RB_INIT(&new_instance->x2ap_enb_head);
//RB_INIT(&new_instance->x2ap_ue_head);
/* Copy usefull parameters */
new_instance->instance = instance;
new_instance->eNB_name = x2ap_register_eNB->eNB_name;
new_instance->eNB_id = x2ap_register_eNB->eNB_id;
new_instance->cell_type = x2ap_register_eNB->cell_type;
new_instance->tac = x2ap_register_eNB->tac;
new_instance->mcc = x2ap_register_eNB->mcc;
new_instance->mnc = x2ap_register_eNB->mnc;
new_instance->mnc_digit_length = x2ap_register_eNB->mnc_digit_length;
/* Add the new instance to the list of eNB (meaningfull in virtual mode) */
x2ap_eNB_insert_new_instance(new_instance);
X2AP_INFO("Registered new eNB[%d] and %s eNB id %u\n",
instance,
x2ap_register_eNB->cell_type == CELL_MACRO_ENB ? "macro" : "home",
x2ap_register_eNB->eNB_id);
}
DevCheck(x2ap_register_eNB->nb_mme <= X2AP_MAX_NB_ENB_IP_ADDRESS,
X2AP_MAX_NB_ENB_IP_ADDRESS, x2ap_register_eNB->nb_x2, 0);
/* Trying to connect to the provided list of eNB ip address */
for (index = 0; index < x2ap_register_eNB->nb_x2; index++) {
x2ap_eNB_register_eNB(new_instance,
&x2ap_register_eNB->target_enb_x2_ip_address[index],
&x2ap_register_eNB->enb_x2_ip_address,
x2ap_register_eNB->sctp_in_streams,
x2ap_register_eNB->sctp_out_streams);
}
}
void *x2ap_task(void *arg)
{
......@@ -60,6 +267,23 @@ void *x2ap_task(void *arg)
itti_exit_task();
break;
case X2AP_REGISTER_ENB_REQ:
x2ap_eNB_handle_register_eNB(ITTI_MESSAGE_GET_INSTANCE(received_msg),
&X2AP_REGISTER_ENB_REQ(received_msg));
break;
case SCTP_NEW_ASSOCIATION_RESP:
x2ap_eNB_handle_sctp_association_resp(ITTI_MESSAGE_GET_INSTANCE(received_msg),
&received_msg->ittiMsg.sctp_new_association_resp);
case SCTP_DATA_IND: {
x2ap_eNB_handle_sctp_data_ind(&received_msg->ittiMsg.sctp_data_ind);
}
break;
default:
X2AP_ERROR("Received unhandled message: %d:%s\n",
ITTI_MSG_ID(received_msg), ITTI_MSG_NAME(received_msg));
......
......@@ -38,6 +38,9 @@
#ifndef X2AP_H_
#define X2AP_H_
#define X2AP_PORT_NUMBER (36422) ///< X2AP SCTP IANA ASSIGNED Port Number
#define X2AP_SCTP_PPID (27) ///< X2AP SCTP Payload Protocol Identifier (PPID)
typedef struct x2ap_config_s {
} x2ap_config_t;
......
/*******************************************************************************
OpenAirInterface
Copyright(c) 1999 - 2015 Eurecom
OpenAirInterface is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenAirInterface is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with OpenAirInterface.The full GNU General Public License is
included in this distribution in the file called "COPYING". If not,
see <http://www.gnu.org/licenses/>.
Contact Information
OpenAirInterface Admin: openair_admin@eurecom.fr
OpenAirInterface Tech : openair_tech@eurecom.fr
OpenAirInterface Dev : openair4g-devel@lists.eurecom.fr
Address : Eurecom, Compus SophiaTech 450, route des chappes, 06451 Biot, France.
*******************************************************************************/
/*! \file x2ap_eNB_decoder.c
* \brief x2ap pdu decode procedures for eNB
* \author Navid Nikaein
* \date 2015- 2016
* \version 0.1
*/
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <assert.h>
#include "x2ap_common.h"
#include "x2ap_ies_defs.h"
#include "x2ap_pdu_decoder.h"
static inline int x2ap_decode_initiating(x2ap_message *x2ap_message_p, InitiatingMessage_t *initiating_p);
static inline int x2ap_decode_successful(x2ap_message *x2ap_message_p, SuccessfulOutcome_t *successful_p);
static inline int x2ap_decode_unsuccessful(x2ap_message *x2ap_message_p, UnsuccessfulOutcome_t *unsuccessful_p);
int x2ap_eNB_decode_pdu(x2ap_message *x2ap_message_p, uint8_t *buffer, uint32_t len) {
X2AP_PDU_t pdu;
X2AP_PDU_t *pdu_p = &pdu;
asn_dec_rval_t dec_ret;
DevAssert(buffer != NULL);
memset((void *)pdu_p, 0, sizeof(X2AP_PDU_t));
dec_ret = aper_decode(NULL,
&asn_DEF_X2AP_PDU,
(void**)&pdu_p,
buffer,
len,
0,
0);
if (dec_ret.code != RC_OK){
X2AP_ERROR("Failed to decode X2AP pdu\n");
return -1;
}
x2ap_message_p->direction = pdu_p->present;
asn1_xer_print = 1;
asn_debug = 0;
switch(pdu_p->present) {
case X2AP_PDU_PR_initiatingMessage:
return x2ap_eNB_decode_initiating(x2ap_message_p, &pdu_p->choice.initiatingMessage);
case X2AP_PDU_PR_successfulOutcome:
return x2ap_eNB_decode_successful(x2ap_message_p, &pdu_p->choice.successfulOutcome);
case X2AP_PDU_PR_unsuccessfulOutcome:
return x2ap_eNB_decode_unsuccessful(x2ap_message_p, &pdu_p->choice.unsuccessfulOutcome);
default:
X2AP_DEBUG("Unknown message outcome (%d) or not implemented", (int)pdu_p->present);
break;
}
return -1;
}
static int x2ap_eNB_decode_initiating(x2ap_message *x2ap_message_p, InitiatingMessage_t *initiating_p) {
int ret = -1;
MessageDef *message_p;
char *message_string = NULL;
size_t message_string_size;
MessagesIds message_id;
DevAssert(initiating_p != NULL);
message_string = calloc(10000, sizeof(char));
x2ap_string_total_size = 0;
x2ap_message_p->procedureCode = initiating_p->procedureCode;
x2ap_message_p->criticality = initiating_p->criticality;
switch(x2ap_message_p->procedureCode) {
case ProcedureCode_id_x2Setup:
ret = x2ap_decode_x2setuprequest_ies(&x2ap_message_p->msg.x2SetupRequest_IEs, &initiating_p->value);
x2ap_xer_print_x2setuprequest_(x2ap_xer__print2sp,message_string,message);
message_id = X2AP_SETUP_REQUEST_LOG;
message_string_size = strlen(message_string);
message_p = itti_alloc_new_message_sized(TASK_S1AP,
message_id,
message_string_size + sizeof (IttiMsgText));
message_p->ittiMsg.x2ap_setup_request_log.size = message_string_size;
memcpy(&message_p->ittiMsg.x2ap_setup_request_log.text, message_string, message_string_size);
itti_send_msg_to_task(TASK_UNKNOWN, INSTANCE_DEFAULT, message_p);
free(message_string);
break;
case ProcedureCode_id_reset:
ret = x2ap_decode_resetrequest_ies(&x2ap_message_p->msg.resetRequest_IEs, &initiating_p->value);
break;
case ProcedureCode_id_resourceStatusReportingInitiation:
ret = x2ap_decode_resourcestatusrequest_ies(&x2ap_message_p->msg.resourceStatusRequest_IEs, &initiating_p->value);
break;
case ProcedureCode_id_resourceStatusReporting:
ret = x2ap_decode_resourcestatusupdate_ies(&x2ap_message_p->msg.resourceStatusUpdate_IEs, &initiating_p->value);
break;
case ProcedureCode_id_loadIndication:
ret = x2ap_decode_loadinformation_ies(&x2ap_message_p->msg.loadInformation_IEs, &initiating_p->value);
break;
case ProcedureCode_id_mobilitySettingsChange:
ret = x2ap_decode_mobilitychangerequest_ies(&x2ap_message_p->msg.mobilityChangeRequest_IEs, &initiating_p->value);
break;
case ProcedureCode_id_eNBConfigurationUpdate:
ret = x2ap_decode_enbconfigurationupdate_ies(&x2ap_message_p->msg.enbConfigurationUpdate_IEs, &initiating_p->value);
break;
case ProcedureCode_id_errorIndication:
ret = x2ap_decode_errorindication_ies(&x2ap_message_p->msg.errorIndication_IEs, &initiating_p->value);
break;
case ProcedureCode_id_handoverCancel:
ret = x2ap_decode_handovercancel_ies(&x2ap_message_p->msg.handoverCancel_IEs, &initiating_p->value);
break;
case ProcedureCode_id_handoverPreparation:
ret = x2ap_decode_handoverrequest_ies(&x2ap_message_p->msg.handoverRequest_IEs, &initiating_p->value);
break;
case ProcedureCode_id_uEContextRelease:
ret = x2ap_decode_uecontextrelease_ies(&x2ap_message_p->msg.ueContextRelease_IEs, &initiating_p->value);
break;
case ProcedureCode_id_snStatusTransfer:
ret = x2ap_decode_snstatustransfer_ies(&x2ap_message_p->msg.snStatusTransfer_IEs, &initiating_p->value);
break;
case ProcedureCode_id_rLFIndication:
ret = x2ap_decode_rlfindication_ies(&x2ap_message_p->msg.rlfIndication_IEs, &initiating_p->value);
break;
case ProcedureCode_id_cellActivation:
ret = x2ap_decode_cellactivationrequest_ies(&x2ap_message_p->msg.cellActivationRequest_IEs, &initiating_p->value);
break;
case ProcedureCode_id_handoverReport:
ret = x2ap_decode_handoverreport_ies(&x2ap_message_p->msg.handoverReport_IEs, &initiating_p->value);
break;
default:
X2AP_DEBUG("Unknown procedure (%d) or not implemented", (int)x2ap_message_p->procedureCode);
break;
}
return ret;
}
static int x2ap_eNB_decode_successful(x2ap_message *x2ap_message_p, SuccessfulOutcome_t *successful_p) {
int ret = -1;
MessageDef *message_p;
char *message_string = NULL;
size_t message_string_size;
MessagesIds message_id;
DevAssert(successful_p != NULL);
message_string = calloc(10000, sizeof(char));
x2ap_string_total_size = 0;
x2ap_message_p->procedureCode = successful_p->procedureCode;
x2ap_message_p->criticality = successful_p->criticality;
switch(x2ap_message_p->procedureCode) {
case ProcedureCode_id_x2Setup:
ret = x2ap_decode_x2setupresponse_ies(&x2ap_message_p->msg.x2SetupResponse_IEs, &successful_p->value);
case ProcedureCode_id_reset:
ret = x2ap_decode_resetresponse_ies(&x2ap_message_p->msg.resetResponse_IEs, &successful_p->value);
case ProcedureCode_id_resourceStatusReportingInitiation:
ret = x2ap_decode_resourcestatusresponse_ies(&x2ap_message_p->msg.resourceStatusResponse_IEs, &successful_p->value);
case ProcedureCode_id_mobilitySettingsChange:
ret = x2ap_decode_mobilitychangeacknowledge_ies(&x2ap_message_p->msg.mobilityChangeAcknowledge_IEs, &successful_p->value);
case ProcedureCode_id_eNBConfigurationUpdate:
ret = x2ap_decode_enbconfigurationupdateacknowledge_ies(&x2ap_message_p->msg.enbConfigurationUpdateAcknowledge_IEs, &successful_p->value);
case ProcedureCode_id_handoverPreparation:
ret = x2ap_decode_handoverrequestacknowledge_ies(&x2ap_message_p->msg.handoverRequestAcknowledge_IEs, &successful_p->value);
case ProcedureCode_id_cellActivation:
ret = x2ap_decode_cellactivationresponse_ies(&x2ap_message_p->msg.cellActivationResponse_IEs, &successful_p->value);
default:
X2AP_DEBUG("Unknown procedure (%d) or not implemented", (int)x2ap_message_p->procedureCode);
break;
}
return ret;
}
static int x2ap_decode_unsuccessful(x2ap_message *message_p, UnsuccessfulOutcome_t *unsuccessful_p) {
int ret = -1;
MessageDef *message_p;
char *message_string = NULL;
size_t message_string_size;
MessagesIds message_id;
DevAssert(unsuccessful_p != NULL);
message_string = calloc(10000, sizeof(char));
x2ap_string_total_size = 0;
x2ap_message_p->procedureCode = unsuccessful_p->procedureCode;
x2ap_message_p->criticality = unsuccessful_p->criticality;
switch(x2ap_message_p->procedureCode) {
case ProcedureCode_id_x2Setup:
ret = x2ap_decode_x2setupfailure_ies(&x2ap_message_p->msg.x2SetupFailure_IEs, &unsuccessful_p->value);
case ProcedureCode_id_resourceStatusReportingInitiation:
ret = x2ap_decode_resourcestatusfailure_ies(&x2ap_message_p->msg.resourceStatusFailure_IEs, &unsuccessful_p->value);
case ProcedureCode_id_mobilitySettingsChange:
ret = x2ap_decode_mobilitychangefailure_ies(&x2ap_message_p->msg.mobilityChangeFailure_IEs, &unsuccessful_p->value);
case ProcedureCode_id_eNBConfigurationUpdate:
ret = x2ap_decode_enbconfigurationupdatefailure_ies(&x2ap_message_p->msg.enbConfigurationUpdateFailure_IEs, &unsuccessful_p->value);
case ProcedureCode_id_handoverPreparation:
ret = x2ap_decode_handoverpreparationfailure_ies(&x2ap_message_p->msg.handoverPreparationFailure_IEs, &unsuccessful_p->value);
case ProcedureCode_id_cellActivation:
ret = x2ap_decode_cellactivationfailure_ies(&x2ap_message_p->msg.cellActivationFailure_IEs, &unsuccessful_p->value);
default:
X2AP_DEBUG("Unknown procedure (%d) or not implemented", (int)x2ap_message_p->procedureCode);
break;
}
return ret;
}
/*******************************************************************************
OpenAirInterface
Copyright(c) 1999 - 2015 Eurecom
OpenAirInterface is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenAirInterface is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with OpenAirInterface.The full GNU General Public License is
included in this distribution in the file called "COPYING". If not,
see <http://www.gnu.org/licenses/>.
Contact Information
OpenAirInterface Admin: openair_admin@eurecom.fr
OpenAirInterface Tech : openair_tech@eurecom.fr
OpenAirInterface Dev : openair4g-devel@lists.eurecom.fr
Address : Eurecom, Compus SophiaTech 450, route des chappes, 06451 Biot, France.
*******************************************************************************/
/*! \file x2ap_eNB_decoder.c
* \brief x2ap pdu decode procedures for eNB
* \author Navid Nikaein
* \date 2015- 2016
* \version 0.1
*/
#include "x2ap_common.h"
#include "x2ap_ies_defs.h"
#ifndef X2AP_ENB_PDU_DECODER_H_
#define X2AP_ENB_PDU_DECODER_H_
int x2ap_eNB_decode_pdu(x2ap_message *x2ap_message, uint8_t *buffer, uint32_t len);
#endif /* X2AP_PDU_DECODER_H_ */
/*******************************************************************************
OpenAirInterface
Copyright(c) 1999 - 2014 Eurecom
OpenAirInterface is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenAirInterface is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with OpenAirInterface.The full GNU General Public License is
included in this distribution in the file called "COPYING". If not,
see <http://www.gnu.org/licenses/>.
Contact Information
OpenAirInterface Admin: openair_admin@eurecom.fr
OpenAirInterface Tech : openair_tech@eurecom.fr
OpenAirInterface Dev : openair4g-devel@lists.eurecom.fr
Address : Eurecom, Compus SophiaTech 450, route des chappes, 06451 Biot, France.
*******************************************************************************/
#include <stdint.h>
#include "queue.h"
#include "tree.h"
#include "sctp_eNB_defs.h"
#ifndef X2AP_ENB_DEFS_H_
#define X2AP_ENB_DEFS_H_
#define X2AP_ENB_NAME_LENGTH_MAX (150)
typedef enum {
/* Disconnected state: initial state for any association. */
X2AP_ENB_STATE_DISCONNECTED = 0x0,
/* State waiting for x2 Setup response message if the target eNB accepts or
* X2 Setup failure if rejects the eNB.
*/
X2AP_ENB_STATE_WAITING = 0x1,
/* The eNB is successfully connected to another eNB. */
X2AP_ENB_STATE_CONNECTED = 0x2,
/*
*/
X2AP_ENB_OVERLOAD = 0x3,
/* Max number of states available */
X2AP_ENB_STATE_MAX,
} s1ap_eNB_state_t;
/* Served PLMN identity element */
struct plmn_identity_s {
uint16_t mcc;
uint16_t mnc;
uint8_t mnc_digit_length;
STAILQ_ENTRY(plmn_identity_s) next;
};
/* Served group id element */
struct served_group_id_s {
uint16_t enb_group_id;
STAILQ_ENTRY(served_group_id_s) next;
};
/* Served enn code for a particular eNB */
struct enb_code_s {
uint8_t enb_code;
STAILQ_ENTRY(enb_code_s) next;
};
struct x2ap_eNB_instance_s;
/* This structure describes association of a eNB to another eNB */
typedef struct x2ap_eNB_data_s {
/* eNB descriptors tree, ordered by sctp assoc id */
RB_ENTRY(x2ap_eNB_data_s) entry;
/* This is the optional name provided by the MME */
char *eNB_name;
/* Current eNB load information (if any). */
//x2ap_load_state_t overload_state;
/* Current eNB->eNB X2AP association state */
x2ap_eNB_state_t state;
/* Next usable stream for UE signalling */
int32_t nextstream;
/* Number of input/ouput streams */
uint16_t in_streams;
uint16_t out_streams;
/* Connexion id used between SCTP/S1AP */
uint16_t cnx_id;
/* SCTP association id */
int32_t assoc_id;
/* Only meaningfull in virtual mode */
struct x2ap_eNB_instance_s *x2ap_eNB_instance;
} x2ap_eNB_data_t;
typedef struct x2ap_eNB_instance_s {
/* Next s1ap eNB association.
* Only used for virtual mode.
*/
STAILQ_ENTRY(x2ap_eNB_instance_s) x2ap_eNB_entries;
/* Number of target eNBs requested by eNB (tree size) */
uint32_t x2ap_enb_nb;
/* Number of target eNBs for which association is pending */
uint32_t x2ap_target_enb_pending_nb;
/* Number of target eNB successfully associated to eNB */
uint32_t x2ap_target_enb_associated_nb;
/* Tree of X2AP eNB associations ordered by association ID */
RB_HEAD(x2ap_enb_map, x2ap_eNB_data_s) x2ap_enb_head;
/* Tree of UE ordered by eNB_ue_x2ap_id's */
// RB_HEAD(x2ap_ue_map, x2ap_eNB_ue_context_s) x2ap_ue_head;
/* For virtual mode, mod_id as defined in the rest of the L1/L2 stack */
instance_t instance;
/* Displayable name of eNB */
char *eNB_name;
/* Unique eNB_id to identify the eNB within EPC.
* In our case the eNB is a macro eNB so the id will be 20 bits long.
* For Home eNB id, this field should be 28 bits long.
*/
uint32_t eNB_id;
/* The type of the cell */
enum cell_type_e cell_type;
/* Tracking area code */
uint16_t tac;
/* Mobile Country Code
* Mobile Network Code
*/
uint16_t mcc;
uint16_t mnc;
uint8_t mnc_digit_length;
} x2ap_eNB_instance_t;
typedef struct {
/* List of served eNBs
* Only used for virtual mode
*/
STAILQ_HEAD(x2ap_eNB_instances_head_s, x2ap_eNB_instance_s) x2ap_eNB_instances_head;
/* Nb of registered eNBs */
uint8_t nb_registered_eNBs;
/* Generate a unique connexion id used between S1AP and SCTP */
uint16_t global_cnx_id;
} x2ap_eNB_internal_data_t;
int x2ap_eNB_compare_assoc_id(
struct x2ap_eNB_data_s *p1, struct x2ap_eNB_data_s *p2);
/* Generate the tree management functions */
RB_PROTOTYPE(x2ap_eNB_map, x2ap_eNB_data_s, entry,
x2ap_eNB_compare_assoc_id);
#endif /* S1AP_ENB_DEFS_H_ */
/*******************************************************************************
OpenAirInterface
Copyright(c) 1999 - 2014 Eurecom
OpenAirInterface is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenAirInterface is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with OpenAirInterface.The full GNU General Public License is
included in this distribution in the file called "COPYING". If not,
see <http://www.gnu.org/licenses/>.
Contact Information
OpenAirInterface Admin: openair_admin@eurecom.fr
OpenAirInterface Tech : openair_tech@eurecom.fr
OpenAirInterface Dev : openair4g-devel@lists.eurecom.fr
Address : Eurecom, Compus SophiaTech 450, route des chappes, 06451 Biot, France.
*******************************************************************************/
/*! \file x2ap_eNB_encoder.c
* \brief x2ap pdu encode procedures for eNB
* \author Navid Nikaein
* \date 2015- 2016
* \version 0.1
*/
#include <stdio.h>
#include <string.h>
#include <stdint.h>
#include "conversions.h"
#include "intertask_interface.h"
#include "x2ap_common.h"
#include "x2ap_ies_defs.h"
#include "x2ap_eNB_encoder.h"
static inline int x2ap_encode_initiating(x2ap_message *x2ap_message_p, uint8_t **buf, uint32_t *length);
static inline int x2ap_encode_successful(x2ap_message *x2ap_message_p, uint8_t **buf, uint32_t *length);
static inline int x2ap_encode_unsuccessful(x2ap_message *x2ap_message_p, uint8_t **buf, uint32_t *length);
int
x2ap_eNB_encode_pdu(x2ap_message *x2ap_message_p, uint8_t **buf, uint32_t *length) {
switch(x2ap_message_p->direction) {
case X2AP_PDU_PR_initiatingMessage:
return x2ap_eNB_encode_initiating(x2ap_message_p, buf, length);
case X2AP_PDU_PR_successfulOutcome:
return x2ap_eNB_encode_successful(x2ap_message_p, buf, length);
case X2AP_PDU_PR_unsuccessfulOutcome:
return x2ap_eNB_encode_unsuccessful(x2ap_message_p, buf, length);
default:
X2AP_DEBUG("Unknown message outcome (%d) or not implemented", (int)x2ap_message_p->direction);
break;
}
return -1;
}
static inline int
x2ap_eNB_encode_initiating(x2ap_message *x2ap_message_p, uint8_t **buf, uint32_t *length){
int ret = -1;
MessageDef *message_p;
char *message_string = NULL;
size_t message_string_size;
MessagesIds message_id;
DevAssert(x2ap_message_p != NULL);
message_string = calloc(10000, sizeof(char));
x2ap_string_total_size = 0;
switch(x2ap_message_p->procedureCode) {
case ProcedureCode_id_reset:
ret = x2ap_reset_request_encoder(&x2ap_message_p->msg.resetRequest_IEs, buf, length);
#warning "do the same for the other messages"
x2ap_xer_print_x2ap_resetrequest_(x2ap_xer__print2sp, message_string, x2ap_message_p);
message_id = X2AP_RESET_REQUST_LOG;
message_p = itti_alloc_new_message_sized(TASK_X2AP, message_id, message_string_size + sizeof (IttiMsgText));
message_p->ittiMsg.x2ap_reset_request_log.size = message_string_size;
memcpy(&message_p->ittiMsg.x2ap_reset_request_log.text, message_string, message_string_size);
itti_send_msg_to_task(TASK_UNKNOWN, INSTANCE_DEFAULT, message_p);
free(message_string);
break;
case ProcedureCode_id_loadIndication:
ret = x2ap_load_information_encoder(&x2ap_message_p->msg.loadInformation_IEs, buf, length);
break;
case ProcedureCode_id_resourceStatusReportingInitiation:
ret = x2ap_resource_status_request_encoder(&x2ap_message_p->msg.resourceStatusRequest_IEs, buf, length);
break;
case ProcedureCode_id_resourceStatusReporting:
ret = x2ap_resource_status_update_encoder(&x2ap_message_p->msg.resourceStatusUpdate_IEs, buf, length);
break;
case ProcedureCode_id_mobilitySettingsChange:
ret = x2ap_mobility_change_request_encoder(&x2ap_message_p->msg.mobilityChangeRequest_IEs, buf, length);
break;
case ProcedureCode_id_x2Setup:
ret = x2_setup_request_encoder(&x2ap_message_p->msg.x2SetupRequest_IEs, buf, length);
break;
case ProcedureCode_id_handoverPreparation:
ret = x2ap_handover_request_encoder(&x2ap_message_p->msg.handoverRequest_IEs, buf, length);
break;
case ProcedureCode_id_errorIndication:
ret = x2ap_error_indication_encoder(&x2ap_message_p->msg.errorIndication_IEs, buf, length);
break;
case ProcedureCode_id_handoverCancel:
ret = x2ap_handover_cancel_encoder(&x2ap_message_p->msg.handoverCancel_IEs, buf, length);
break;
case ProcedureCode_id_handoverReport:
ret = x2ap_handover_report_encoder(&x2ap_message_p->msg.handoverReport_IEs, buf, length);
break;
case ProcedureCode_id_eNBConfigurationUpdate:
ret = x2ap_eNB_configuration_update_request_encoder(&x2ap_message_p->msg.enbConfigurationUpdate_IEs,buf, length);
break;
case ProcedureCode_id_uEContextRelease:
ret = x2ap_ue_context_release_encoder(&x2ap_message_p->msg.ueContextRelease_IEs, buf, length );
break;
case ProcedureCode_id_snStatusTransfer:
ret = x2ap_sn_status_transfer_encoder(&x2ap_message_p->msg.snStatusTransfer_IEs, buf, length);
break;
case ProcedureCode_id_rLFIndication:
ret = x2ap_rlf_indication_encoder(&x2ap_message_p->msg.rlfIndication_IEs, buf, length);
break;
case ProcedureCode_id_cellActivation:
ret = x2ap_cell_activation_request_encoder(&x2ap_message_p->msg.cellActivationRequest_IEs, buf, length);
break;
default:
X2AP_DEBUG("Unknown procedure (%d) or not implemented", (int)x2ap_message_p->procedureCode);
break;
}
return ret;
}
static inline int
x2ap_eNB_encode_successful(x2ap_message *x2ap_message_p, uint8_t **buf, uint32_t *length){
int ret = -1;
MessageDef *message_p;
char *message_string = NULL;
size_t message_string_size;
MessagesIds message_id;
DevAssert(x2ap_message_p != NULL);
message_string = calloc(10000, sizeof(char));
x2ap_string_total_size = 0;
switch(x2ap_message_p->procedureCode) {
case ProcedureCode_id_resourceStatusReportingInitiation:
ret = x2ap_resource_status_response_encoder(&x2ap_message_p->msg.resourceStatusResponse_IEs, buf, length);
#warning "do the same for the other messages"
x2ap_xer_print_x2ap_resourcestatusresponse_(x2ap_xer__print2sp, message_string, x2ap_message_p);
message_id = X2AP_RESOURCE_STATUS_RESPONSE_LOG;
message_p = itti_alloc_new_message_sized(TASK_X2AP, message_id, message_string_size + sizeof (IttiMsgText));
message_p->ittiMsg.x2ap_resource_status_response_log.size = message_string_size;
memcpy(&message_p->ittiMsg.x2ap_resource_status_response_log.text, message_string, message_string_size);
itti_send_msg_to_task(TASK_UNKNOWN, INSTANCE_DEFAULT, message_p);
free(message_string);
break;
case ProcedureCode_id_mobilitySettingsChange:
ret = x2ap_mobility_change_acknowledge_encoder(&x2ap_message_p->msg.mobilityChangeAcknowledge_IEs, buf, length);
break;
case ProcedureCode_id_reset:
ret = x2ap_reset_response_encoder(&x2ap_message_p->msg.resetResponse_IEs, buf, length);
break;
case ProcedureCode_id_x2Setup:
ret = x2_setup_response_encoder(&x2ap_message_p->msg.x2SetupResponse_IEs, buf, length);
break;
case ProcedureCode_id_handoverPreparation:
ret = x2ap_handover_request_acknowledge_encoder(&x2ap_message_p->msg.handoverRequestAcknowledge_IEs, buf, length);
break;
case ProcedureCode_id_eNBConfigurationUpdate:
ret = x2ap_eNB_configuration_update_acknowledge_encoder(&x2ap_message_p->msg.enbConfigurationUpdateAcknowledge_IEs, buf, length);
break;
case ProcedureCode_id_cellActivation:
ret = x2ap_cell_activation_response_encoder(&x2ap_message_p->msg.cellActivationResponse_IEs, buf, length);
break;
default:
X2AP_DEBUG("Unknown procedure (%d) or not implemented", (int)x2ap_message_p->procedureCode);
break;
}
return ret;
}
static inline
int x2ap_eNB_encode_unsuccessful(x2ap_message *x2ap_message_p, uint8_t **buf, uint32_t *length){
int ret = -1;
MessageDef *message_p;
char *message_string = NULL;
size_t message_string_size;
MessagesIds message_id;
DevAssert(x2ap_message_p != NULL);
message_string = calloc(10000, sizeof(char));
x2ap_string_total_size = 0;
switch(x2ap_message_p->procedureCode) {
case ProcedureCode_id_resourceStatusReportingInitiation:
ret = x2ap_resource_status_failure_encoder(&x2ap_message_p->msg.resourceStatusFailure_IEs, buf, length);
#warning "do the same for the other messages"
x2ap_xer_print_x2ap_resourcestatusfailure_(x2ap_xer__print2sp, message_string, x2ap_message_p);
message_id = X2AP_RESOURCE_STATUS_FAILURE_LOG;
message_p = itti_alloc_new_message_sized(TASK_X2AP, message_id, message_string_size + sizeof (IttiMsgText));
message_p->ittiMsg.x2ap_resource_status_failure_log.size = message_string_size;
memcpy(&message_p->ittiMsg.x2ap_resource_status_failure_log.text, message_string, message_string_size);
itti_send_msg_to_task(TASK_UNKNOWN, INSTANCE_DEFAULT, message_p);
free(message_string);
break;
case ProcedureCode_id_mobilitySettingsChange:
ret = x2ap_mobility_change_failure_encoder(&x2ap_message_p->msg.mobilityChangeFailure_IEs, buf, length);
break;
case ProcedureCode_id_x2Setup:
ret = x2_setup_failure_encoder(&x2ap_message_p->msg.x2SetupFailure_IEs, buf, length);
break;
case ProcedureCode_id_handoverPreparation:
ret = x2ap_handover_preparation_failure_encoder(&x2ap_message_p->msg.handoverPreparationFailure_IEs, buf, length);
break;
case ProcedureCode_id_eNBConfigurationUpdate:
ret = x2ap_eNB_configuration_update_failure_encoder(&x2ap_message_p->msg.enbConfigurationUpdateFailure_IEs, buf, length);
break;
case ProcedureCode_id_cellActivation:
ret = x2ap_cell_activation_failure_encoder(&x2ap_message_p->msg.cellActivationFailure_IEs, buf, length);
break;
default:
X2AP_DEBUG("Unknown procedure (%d) or not implemented", (int)x2ap_message_p->procedureCode);
break;
}
return ret;
}
static inline
int x2ap_reset_request_encoder(ResetRequest_IEs_t *resetRequest_IEs, uint8_t **buf, uint32_t *length){
int i;
ResetRequest_t resetRequest;
memset (&resetRequest,0, sizeof(ResetRequest_t));
asn1_xer_print = 0;
asn_debug = 0;
// encoding Reset request message
if (x2ap_encode_resetrequest_ies(&resetRequest, resetRequest_IEs) <0) {
printf ("Encode procedure failes\n");
return -1;
}
// encoding ProcedureCode_id_reset
if (x2ap_generate_initiating_message (buf, length, ProcedureCode_id_reset, Criticality_reject, &asn_DEF_ResetRequest, &resetRequest) <0) {
printf ("Encode procedure failes\n");
return -1;
}
for (i=0;i< *length; i++)
{
printf ("0x%02x ", (*buf)[i]);
}
printf ("\n");
}
int x2_setup_response_encoder(X2SetupResponse_IEs_t *x2SetupResponse_IEs, uint8_t **buf, uint32_t *length){
int i;
X2SetupResponse_t x2SetupResponse;
memset (&x2SetupResponse,0, sizeof(X2SetupResponse_t));
asn1_xer_print = 0;
asn_debug = 0;
// encoding X2 Setup response message
if (x2ap_encode_x2setupresponse_ies(&x2SetupResponse, x2SetupResponse_IEs) <0) {
printf ("Encode procedure failes\n");
return -1;
}
// encoding ProcedureCode_id_x2Setup
if (x2ap_generate_successfull_outcome (buf, length, ProcedureCode_id_x2Setup, Criticality_reject, &asn_DEF_X2SetupResponse, &x2SetupResponse) <0) {
printf ("Encode procedure failes\n");
return -1;
}
for (i=0;i< *length; i++)
{
printf ("0x%02x ", (*buf)[i]);
}
printf ("\n");
}
int x2_setup_failure_encoder(X2SetupFailure_IEs_t *x2SetupFailure_IEs, uint8_t **buf, uint32_t *length){
int i;
X2SetupFailure_t x2SetupFailure;
memset (&x2SetupFailure,0, sizeof(X2SetupFailure_t));
asn1_xer_print = 0;
asn_debug = 0;
// encoding X2 Setup failure message
if (x2ap_encode_x2setupfailure_ies(&x2SetupFailure, x2SetupFailure_IEs) <0) {
printf ("Encode procedure failes\n");
return -1;
}
// encoding ProcedureCode_id_x2Setup
if (x2ap_generate_unsuccessfull_outcome (buf, length, ProcedureCode_id_x2Setup, Criticality_reject, &asn_DEF_X2SetupFailure, &x2SetupFailure) <0) {
printf ("Encode procedure failes\n");
return -1;
}
for (i=0;i< *length; i++)
{
printf ("0x%02x ", (*buf)[i]);
}
printf ("\n");
}
int x2_setup_request_encoder(X2SetupRequest_IEs_t *x2SetupRequest_IEs, uint8_t **buf, uint32_t *length){
int i;
X2SetupRequest_t x2SetupRequest;
memset (&x2SetupRequest,0, sizeof(X2SetupRequest_t));
asn1_xer_print = 0;
asn_debug = 0;
// encoding X2 Setup request message
if (x2ap_encode_x2setuprequest_ies(&x2SetupRequest, x2SetupRequest_IEs) <0) {
printf ("Encode procedure failes\n");
return -1;
}
// encoding ProcedureCode_id_x2Setup
if (x2ap_generate_initiating_message (buf, length, ProcedureCode_id_x2Setup, Criticality_reject, &asn_DEF_X2SetupRequest, &x2SetupRequest) <0) {
printf ("Encode procedure failes\n");
return -1;
}
for (i=0;i< *length; i++)
{
printf ("0x%02x ", (*buf)[i]);
}
printf ("\n");
}
static inline
int x2ap_reset_response_encoder(ResetResponse_IEs_t *resetResponse_IEs, uint8_t **buf, uint32_t *length){
int i;
ResetResponse_t resetResponse;
memset (&resetResponse,0, sizeof(ResetResponse_t));
asn1_xer_print = 0;
asn_debug = 0;
// encoding Reset Response message
if (x2ap_encode_resetresponse_ies(&resetResponse, resetResponse_IEs) <0) {
printf ("Encode procedure failes\n");
return -1;
}
// encoding ProcedureCode_id_reset
if (x2ap_generate_successfull_outcome(buf, length, ProcedureCode_id_reset, Criticality_reject, &asn_DEF_ResetResponse, &resetResponse) <0) {
printf ("Encode procedure failes\n");
return -1;
}
for (i=0;i< *length; i++)
{
printf ("0x%02x ", (*buf)[i]);
}
printf ("\n");
}
static inline
int x2ap_mobility_change_failure_encoder(MobilityChangeFailure_IEs_t *mobilityChangeFailure_IEs, uint8_t **buf, uint32_t *length){
int i;
MobilityChangeFailure_t mobilityChangeFailure;
memset (&mobilityChangeFailure,0, sizeof(MobilityChangeFailure_t));
asn1_xer_print = 0;
asn_debug = 0;
// encoding Mobility Change Failure message
if (x2ap_encode_mobilitychangefailure_ies(&mobilityChangeFailure, mobilityChangeFailure_IEs) <0) {
printf ("Encode procedure failes\n");
return -1;
}
// encoding ProcedureCode_id_mobilitySettingsChange
if (x2ap_generate_unsuccessfull_outcome (buf, length, ProcedureCode_id_mobilitySettingsChange, Criticality_reject, &asn_DEF_MobilityChangeFailure, &mobilityChangeFailure) <0) {
printf ("Encode procedure failes\n");
return -1;
}
for (i=0;i< *length; i++)
{
printf ("0x%02x ", (*buf)[i]);
}
printf ("\n");
}
static inline
int x2ap_mobility_change_acknowledge_encoder(MobilityChangeAcknowledge_IEs_t *mobilityChangeAcknowledge_IEs, uint8_t **buf, uint32_t *length){
int i;
MobilityChangeAcknowledge_t mobilityChangeAcknowledge;
memset (&mobilityChangeAcknowledge,0, sizeof(MobilityChangeAcknowledge_t));
asn1_xer_print = 0;
asn_debug = 0;
// encoding Mobility Change Acknowledge message
if (x2ap_encode_mobilitychangeacknowledge_ies(&mobilityChangeAcknowledge, mobilityChangeAcknowledge_IEs) <0) {
printf ("Encode procedure failes\n");
return -1;
}
// encoding ProcedureCode_id_mobilitySettingsChange
if (x2ap_generate_successfull_outcome (buf, length, ProcedureCode_id_mobilitySettingsChange, Criticality_reject, &asn_DEF_MobilityChangeAcknowledge, &mobilityChangeAcknowledge) <0) {
printf ("Encode procedure failes\n");
return -1;
}
for (i=0;i< *length; i++)
{
printf ("0x%02x ", (*buf)[i]);
}
printf ("\n");
}
static inline
int x2ap_mobility_change_request_encoder(MobilityChangeRequest_IEs_t *mobilityChangeRequest_IEs, uint8_t **buf, uint32_t *length){
int i;
MobilityChangeRequest_t mobilityChangeRequest;
memset (&mobilityChangeRequest,0, sizeof(MobilityChangeRequest_t));
asn1_xer_print = 0;
asn_debug = 0;
// encoding Mobility Change Request message
if (x2ap_encode_mobilitychangerequest_ies(&mobilityChangeRequest, mobilityChangeRequest_IEs) <0) {
printf ("Encode procedure failes\n");
return -1;
}
// encoding ProcedureCode_id_mobilitySettingsChange
if (x2ap_generate_initiating_message (buf, length, ProcedureCode_id_mobilitySettingsChange, Criticality_reject, &asn_DEF_MobilityChangeRequest, &mobilityChangeRequest) <0) {
printf ("Encode procedure failes\n");
return -1;
}
for (i=0;i< *length; i++)
{
printf ("0x%02x ", (*buf)[i]);
}
printf ("\n");
}
static inline
int x2ap_resource_status_update_encoder(ResourceStatusUpdate_IEs_t *resourceStatusUpdate_IEs, uint8_t **buf, uint32_t *length){
int i;
ResourceStatusUpdate_t resourceStatusUpdate;
memset (&resourceStatusUpdate,0, sizeof(ResourceStatusUpdate_t));
asn1_xer_print = 0;
asn_debug = 0;
// encoding Resource Status Update message
if (x2ap_encode_resourcestatusupdate_ies(&resourceStatusUpdate, resourceStatusUpdate_IEs) <0) {
printf ("Encode procedure failes\n");
return -1;
}
// encoding ProcedureCode_id_resourceStatusReporting
if (x2ap_generate_initiating_message (buf, length, ProcedureCode_id_resourceStatusReporting, Criticality_ignore, &asn_DEF_ResourceStatusUpdate, &resourceStatusUpdate) <0) {
printf ("Encode procedure failes\n");
return -1;
}
for (i=0;i< *length; i++)
{
printf ("0x%02x ", (*buf)[i]);
}
printf ("\n");
}
static inline
int x2ap_resource_status_failure_encoder(ResourceStatusFailure_IEs_t *resourceStatusFailure_IEs, uint8_t **buf, uint32_t *length){
int i;
ResourceStatusFailure_t resourceStatusFailure;
memset (&resourceStatusFailure,0, sizeof(ResourceStatusFailure_t));
asn1_xer_print = 0;
asn_debug = 0;
// encoding Resource Status Failure message
if (x2ap_encode_resourcestatusfailure_ies(&resourceStatusFailure, resourceStatusFailure_IEs) <0) {
printf ("Encode procedure failes\n");
return -1;
}
// encoding ProcedureCode_id_resourceStatusReportingInitiation
if (x2ap_generate_unsuccessfull_outcome (buf, length, ProcedureCode_id_resourceStatusReportingInitiation, Criticality_reject, &asn_DEF_ResourceStatusFailure, &resourceStatusFailure) <0) {
printf ("Encode procedure failes\n");
return -1;
}
for (i=0;i< *length; i++)
{
printf ("0x%02x ", (*buf)[i]);
}
printf ("\n");
}
static inline
int x2ap_resource_status_response_encoder(ResourceStatusResponse_IEs_t *resourceStatusResponse_IEs, uint8_t **buf, uint32_t *length){
int i;
ResourceStatusResponse_t resourceStatusResponse;
memset (&resourceStatusResponse,0, sizeof(ResourceStatusResponse_t));
asn1_xer_print = 0;
asn_debug = 0;
// encoding Resource Status Response message
if (x2ap_encode_resourcestatusresponse_ies(&resourceStatusResponse, resourceStatusResponse_IEs) <0) {
printf ("Encode procedure failes\n");
return -1;
}
// encoding ProcedureCode_id_resourceStatusReportingInitiation
if (x2ap_generate_successfull_outcome (buf, length, ProcedureCode_id_resourceStatusReportingInitiation, Criticality_reject, &asn_DEF_ResourceStatusResponse, &resourceStatusResponse) <0) {
printf ("Encode procedure failes\n");
return -1;
}
for (i=0;i< *length; i++)
{
printf ("0x%02x ", (*buf)[i]);
}
printf ("\n");
}
static inline
int x2ap_resource_status_request_encoder(ResourceStatusRequest_IEs_t *resourceStatusRequest_IEs, uint8_t **buf, uint32_t *length){
int i;
ResourceStatusRequest_t resourceStatusRequest;
memset (&resourceStatusRequest,0, sizeof(ResourceStatusRequest_t));
asn1_xer_print = 0;
asn_debug = 0;
// encoding Resource Status Resquest message
if (x2ap_encode_resourcestatusrequest_ies(&resourceStatusRequest, resourceStatusRequest_IEs) <0) {
printf ("Encode procedure failes\n");
return -1;
}
// encoding ProcedureCode_id_resourceStatusReportingInitiation
if (x2ap_generate_initiating_message (buf, length, ProcedureCode_id_resourceStatusReportingInitiation, Criticality_reject, &asn_DEF_ResourceStatusRequest, &resourceStatusRequest) <0) {
printf ("Encode procedure failes\n");
return -1;
}
for (i=0;i< *length; i++)
{
printf ("0x%02x ", (*buf)[i]);
}
printf ("\n");
}
static inline
int x2ap_load_information_encoder(LoadInformation_IEs_t *loadInformation_IEs, uint8_t **buf, uint32_t *length){
int i;
LoadInformation_t loadInformation;
memset (&loadInformation,0, sizeof(LoadInformation_t));
asn1_xer_print = 0;
asn_debug = 0;
// encoding Reset request message
if (x2ap_encode_loadinformation_ies(&loadInformation, loadInformation_IEs) <0) {
printf ("Encode procedure failes\n");
return -1;
}
// encoding ProcedureCode_id_loadIndication
if (x2ap_generate_initiating_message (buf, length, ProcedureCode_id_loadIndication, Criticality_ignore, &asn_DEF_LoadInformation, &loadInformation) <0) {
printf ("Encode procedure failes\n");
return -1;
}
for (i=0;i< *length; i++)
{
printf ("0x%02x ", (*buf)[i]);
}
printf ("\n");
}
static inline
int x2ap_handover_request_encoder(HandoverRequest_IEs_t *handoverRequest_IEs, uint8_t **buf, uint32_t *length){
int i;
HandoverRequest_t x2HandoverRequest;
memset (&x2HandoverRequest,0, sizeof(HandoverRequest_t));
asn1_xer_print = 0;
asn_debug = 0;
// encoding Reset request message
if (x2ap_encode_handoverrequest_ies(&x2HandoverRequest, handoverRequest_IEs) <0) {
printf ("Encode procedure failes\n");
return -1;
}
// encoding ProcedureCode_id_loadIndication
if (x2ap_generate_initiating_message (buf, length, ProcedureCode_id_handoverPreparation, Criticality_reject, &asn_DEF_HandoverRequest, &x2HandoverRequest) <0) {
printf ("Encode procedure failes\n");
return -1;
}
for (i=0;i< *length; i++)
{
printf ("0x%02x ", (*buf)[i]);
}
printf ("\n");
}
static inline
int x2ap_handover_request_acknowledge_encoder(HandoverRequestAcknowledge_IEs_t *handoverRequestAcknowledge_IEs, uint8_t **buf, uint32_t *length){
int i;
HandoverRequestAcknowledge_t x2HandoverRequestAcknowledge;
memset (&x2HandoverRequestAcknowledge,0, sizeof(HandoverRequestAcknowledge_t));
asn1_xer_print = 0;
asn_debug = 0;
// encoding Reset request message
if (x2ap_encode_handoverrequestacknowledge_ies(&x2HandoverRequestAcknowledge, handoverRequestAcknowledge_IEs) <0) {
printf ("Encode procedure failes\n");
return -1;
}
if (x2ap_generate_successfull_outcome(buf, length, ProcedureCode_id_handoverPreparation, Criticality_reject, &asn_DEF_HandoverRequestAcknowledge, &x2HandoverRequestAcknowledge) <0) {
printf ("Encode procedure failes\n");
return -1;
}
for (i=0;i< *length; i++)
{
printf ("0x%02x ", (*buf)[i]);
}
printf ("\n");
}
static inline
int x2ap_handover_preparation_failure_encoder(HandoverPreparationFailure_IEs_t *handoverPreparationFailure_IEs, uint8_t **buf, uint32_t *length){
int i;
HandoverPreparationFailure_t x2HandoverPreparationFailure;
memset (&x2HandoverPreparationFailure,0, sizeof(HandoverPreparationFailure_t));
asn1_xer_print = 0;
asn_debug = 0;
// encoding Reset request message
if (x2ap_encode_handoverpreparationfailure_ies(&x2HandoverPreparationFailure, handoverPreparationFailure_IEs) <0) {
printf ("Encode procedure failes\n");
return -1;
}
// encoding ProcedureCode_id_loadIndication
if (x2ap_generate_unsuccessfull_outcome(buf, length, ProcedureCode_id_handoverPreparation, Criticality_reject, &asn_DEF_HandoverPreparationFailure, &x2HandoverPreparationFailure) <0) {
printf ("Encode procedure failes\n");
return -1;
}
for (i=0;i< *length; i++)
{
printf ("0x%02x ", (*buf)[i]);
}
printf ("\n");
}
static inline
int x2ap_error_indication_encoder(ErrorIndication_IEs_t *errorIndication_IEs, uint8_t **buf, uint32_t *length){
int i;
ErrorIndication_t x2Error_indication;
memset (&x2Error_indication,0, sizeof(ErrorIndication_t));
asn1_xer_print = 0;
asn_debug = 0;
// encoding Reset request message
if (x2ap_encode_errorindication_ies(&x2Error_indication, errorIndication_IEs) <0) {
printf ("Encode procedure failes\n");
return -1;
}
// encoding ProcedureCode_id_loadIndication
if (x2ap_generate_initiating_message(buf, length, ProcedureCode_id_errorIndication, Criticality_ignore, &asn_DEF_ErrorIndication, &x2Error_indication) <0) {
printf ("Encode procedure failes\n");
return -1;
}
for (i=0;i< *length; i++)
{
printf ("0x%02x ", (*buf)[i]);
}
printf ("\n");
}
static inline
int x2ap_handover_cancel_encoder(HandoverCancel_IEs_t *handoverCancel_IEs, uint8_t **buf, uint32_t *length){
int i;
HandoverCancel_t x2HandoverCancel;
memset (&x2HandoverCancel,0, sizeof(HandoverCancel_t));
asn1_xer_print = 0;
asn_debug = 0;
// encoding Reset request message
if (x2ap_encode_handovercancel_ies(&x2HandoverCancel, handoverCancel_IEs) <0) {
printf ("Encode procedure failes\n");
return -1;
}
// encoding ProcedureCode_id_loadIndication
if (x2ap_generate_initiating_message(buf, length, ProcedureCode_id_handoverCancel, Criticality_ignore, &asn_DEF_HandoverCancel, &x2HandoverCancel) <0) {
printf ("Encode procedure failes\n");
return -1;
}
for (i=0;i< *length; i++)
{
printf ("0x%02x ", (*buf)[i]);
}
printf ("\n");
}
static inline
int x2ap_handover_report_encoder( HandoverReport_IEs_t *handoverReport_IEs, uint8_t **buf, uint32_t *length){
int i;
HandoverReport_t HandoverReport;
memset (&HandoverReport,0, sizeof(HandoverReport_t));
asn1_xer_print = 0;
asn_debug = 0;
// encoding Reset request message
if (x2ap_encode_handoverreport_ies(&HandoverReport, handoverReport_IEs) <0) {
printf ("Encode procedure failes\n");
return -1;
}
// encoding ProcedureCode_id_loadIndication
if (x2ap_generate_initiating_message(buf, length, ProcedureCode_id_handoverReport, Criticality_ignore, &asn_DEF_HandoverReport, &HandoverReport) <0) {
printf ("Encode procedure failes\n");
return -1;
}
for (i=0;i< *length; i++)
{
printf ("0x%02x ", (*buf)[i]);
}
printf ("\n");
}
static inline
int x2ap_eNB_configuration_update_request_encoder(ENBConfigurationUpdate_IEs_t *enbConfigurationUpdate_IEs, uint8_t **buf, uint32_t *length){
int i;
ENBConfigurationUpdate_t x2ENBConfigurationUpdate;
memset (&x2ENBConfigurationUpdate,0, sizeof(ENBConfigurationUpdate_t));
asn1_xer_print = 0;
asn_debug = 0;
// encoding Reset request message
if (x2ap_encode_enbconfigurationupdate_ies(&x2ENBConfigurationUpdate, enbConfigurationUpdate_IEs) <0) {
printf ("Encode procedure failes\n");
return -1;
}
// encoding ProcedureCode_id_loadIndication
if (x2ap_generate_initiating_message(buf, length, ProcedureCode_id_eNBConfigurationUpdate, Criticality_reject, &asn_DEF_ENBConfigurationUpdate, &x2ENBConfigurationUpdate) <0) {
printf ("Encode procedure failes\n");
return -1;
}
for (i=0;i< *length; i++)
{
printf ("0x%02x ", (*buf)[i]);
}
printf ("\n");
}
static inline
int x2ap_eNB_configuration_update_acknowledge_encoder(ENBConfigurationUpdateAcknowledge_IEs_t *enbConfigurationUpdateAcknowledge_IEs, uint8_t **buf, uint32_t *length){
int i;
ENBConfigurationUpdateAcknowledge_t x2ENBConfigurationUpdateAcknowledge;
memset (&x2ENBConfigurationUpdateAcknowledge,0, sizeof(ENBConfigurationUpdateAcknowledge_t));
asn1_xer_print = 0;
asn_debug = 0;
// encoding Reset request message
if (x2ap_encode_enbconfigurationupdateacknowledge_ies(&x2ENBConfigurationUpdateAcknowledge, enbConfigurationUpdateAcknowledge_IEs) <0) {
printf ("Encode procedure failes\n");
return -1;
}
// encoding ProcedureCode_id_loadIndication
if (x2ap_generate_successfull_outcome(buf, length, ProcedureCode_id_eNBConfigurationUpdate, Criticality_reject, &asn_DEF_ENBConfigurationUpdateAcknowledge, &x2ENBConfigurationUpdateAcknowledge) <0) {
printf ("Encode procedure failes\n");
return -1;
}
for (i=0;i< *length; i++)
{
printf ("0x%02x ", (*buf)[i]);
}
printf ("\n");
}
static inline
int x2ap_eNB_configuration_update_failure_encoder( ENBConfigurationUpdateFailure_IEs_t *enbConfigurationUpdateFailure_IEs, uint8_t **buf, uint32_t *length){
int i;
ENBConfigurationUpdateFailure_t x2ENBConfigurationUpdateFailure;
memset (&x2ENBConfigurationUpdateFailure,0, sizeof(ENBConfigurationUpdateFailure_t));
asn1_xer_print = 0;
asn_debug = 0;
// encoding Reset request message
if (x2ap_encode_enbconfigurationupdatefailure_ies(&x2ENBConfigurationUpdateFailure, enbConfigurationUpdateFailure_IEs) <0) {
printf ("Encode procedure failes\n");
return -1;
}
// encoding ProcedureCode_id_eNBConfigurationUpdate
if (x2ap_generate_unsuccessfull_outcome(buf, length, ProcedureCode_id_eNBConfigurationUpdate, Criticality_reject, &asn_DEF_ENBConfigurationUpdateFailure, &x2ENBConfigurationUpdateFailure) <0) {
printf ("Encode procedure failes\n");
return -1;
}
for (i=0;i< *length; i++)
{
printf ("0x%02x ", (*buf)[i]);
}
printf ("\n");
}
static inline
int x2ap_cell_activation_failure_encoder(CellActivationFailure_IEs_t *cellActivationFailure_IEs, uint8_t **buf, uint32_t *length){
int i;
CellActivationFailure_t cellActivationFailure;
memset (&cellActivationFailure,0, sizeof(CellActivationFailure_t));
asn1_xer_print = 0;
asn_debug = 0;
// encoding cell activationfailure message
if (x2ap_encode_cellactivationfailure_ies(&cellActivationFailure,cellActivationFailure_IEs)<0) {
printf ("Encode procedure failes\n");
return -1;
}
// encoding ProcedureCode_id_cellActivation
if (x2ap_generate_unsuccessfull_outcome (buf, length, ProcedureCode_id_cellActivation , Criticality_reject, &asn_DEF_CellActivationFailure, &cellActivationFailure) <0)
{
printf ("Initiating Message for Encode procedure failes\n");
return -1;
}
//Printing Buff values on terminal
for (i=0;i< *length; i++)
{
printf ("0x%02x ", (*buf)[i]);
}
printf ("\n");
}
static inline
int x2ap_cell_activation_response_encoder(CellActivationResponse_IEs_t *cellActivationResponse_IEs, uint8_t **buf, uint32_t *length) {
int i;
CellActivationResponse_t cellActivationResponse;;
memset (&cellActivationResponse,0, sizeof(CellActivationResponse_t));
asn1_xer_print = 0;
asn_debug = 0;
// encoding Cell Activation Response message
if (x2ap_encode_cellactivationresponse_ies(&cellActivationResponse,cellActivationResponse_IEs)<0) {
printf ("Encode procedure failes\n");
return -1;
}
// encoding ProcedureCode_id_cellActivation
if (x2ap_generate_successfull_outcome (buf, length, ProcedureCode_id_cellActivation , Criticality_reject, &asn_DEF_CellActivationResponse, &cellActivationResponse) <0)
{
printf ("Initiating Message for Encode procedure failes\n");
return -1;
}
//Printing Buff values on terminal
for (i=0;i< *length; i++)
{
printf ("0x%02x ", (*buf)[i]);
}
printf ("\n");
}
static inline
int x2ap_cell_activation_request_encoder(CellActivationRequest_IEs_t *cellActivationRequest_IEs, uint8_t **buf, uint32_t *length) {
int i;
CellActivationRequest_t cellActivationRequest;
memset (&cellActivationRequest,0, sizeof(CellActivationRequest_t));
asn1_xer_print = 0;
asn_debug = 0;
// encoding cell Activation Request message
if (x2ap_encode_cellactivationrequest_ies(&cellActivationRequest,cellActivationRequest_IEs)<0) {
printf ("Encode procedure failes\n");
return -1;
}
// encoding ProcedureCode_id_cellActivation
if (x2ap_generate_initiating_message (buf, length, ProcedureCode_id_cellActivation , Criticality_reject, &asn_DEF_CellActivationRequest, &cellActivationRequest) <0)
{
printf ("Initiating Message for Encode procedure failes\n");
return -1;
}
//Printing Buff values on terminal
for (i=0;i< *length; i++)
{
printf ("0x%02x ", (*buf)[i]);
}
printf ("\n");
}
static inline
int x2ap_rlf_indication_encoder(RLFIndication_IEs_t *rlfIndication_IEs, uint8_t **buf, uint32_t *length) {
int i;
RLFIndication_t rlfIndication;
memset (&rlfIndication,0, sizeof(RLFIndication_t));
asn1_xer_print = 0;
asn_debug = 0;
// encoding RLF Indication message
if (x2ap_encode_rlfindication_ies(&rlfIndication,rlfIndication_IEs)<0) {
printf ("Encode procedure failes\n");
return -1;
}
// encoding ProcedureCode_id_rlfIndication
if (x2ap_generate_initiating_message (buf, length, ProcedureCode_id_rLFIndication , Criticality_reject, &asn_DEF_RLFIndication, &rlfIndication) <0)
{
printf ("Initiating Message for Encode procedure failes\n");
return -1;
}
//Printing Buff values on terminal
for (i=0;i< *length; i++)
{
printf ("0x%02x ", (*buf)[i]);
}
printf ("\n");
}
static inline
int x2ap_sn_status_transfer_encoder(SNStatusTransfer_IEs_t *snStatusTransfer_IEs, uint8_t **buf, uint32_t *length){
int i;
SNStatusTransfer_t snStatusTransfer;
memset (&snStatusTransfer,0, sizeof(SNStatusTransfer_t));
asn1_xer_print = 0;
asn_debug = 0;
// encoding sn status transfer message
if (x2ap_encode_snstatustransfer_ies(&snStatusTransfer,snStatusTransfer_IEs)<0) {
printf ("Encode procedure failes\n");
return -1;
}
if (x2ap_generate_initiating_message (buf, length, ProcedureCode_id_snStatusTransfer , Criticality_reject, &asn_DEF_SNStatusTransfer, &snStatusTransfer) <0)
{
printf ("Initiating Message for Encode procedure failes\n");
return -1;
}
//Printing Buff values on terminal
for (i=0;i< *length; i++)
{
printf ("0x%02x ", (*buf)[i]);
}
printf ("\n");
}
static inline
int x2ap_ue_context_release_encoder(UEContextRelease_IEs_t *uecontext_rel, uint8_t **buf, uint32_t *length){
int i;
UEContextRelease_t ueContextRelease;
memset (&ueContextRelease,0, sizeof(UEContextRelease_t));
asn1_xer_print = 0;
asn_debug = 0;
// encoding ue context release message
if (x2ap_encode_uecontextrelease_ies(&ueContextRelease, uecontext_rel) <0)
{
printf ("Encode procedure failes\n");
return -1;
}
//Procedure code for UE Context Release = "5"
if (x2ap_generate_initiating_message (buf, length, ProcedureCode_id_uEContextRelease , Criticality_reject, &asn_DEF_UEContextRelease, &ueContextRelease) <0)
{
printf ("Initiating Message for Encode procedure failes\n");
return -1;
}
//Printing Buff values on terminal
for (i=0;i< *length; i++)
{
printf ("0x%02x ", (*buf)[i]);
}
printf ("\n");
}
/*******************************************************************************
OpenAirInterface
Copyright(c) 1999 - 2014 Eurecom
OpenAirInterface is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenAirInterface is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with OpenAirInterface.The full GNU General Public License is
included in this distribution in the file called "COPYING". If not,
see <http://www.gnu.org/licenses/>.
Contact Information
OpenAirInterface Admin: openair_admin@eurecom.fr
OpenAirInterface Tech : openair_tech@eurecom.fr
OpenAirInterface Dev : openair4g-devel@lists.eurecom.fr
Address : Eurecom, Compus SophiaTech 450, route des chappes, 06451 Biot, France.
*******************************************************************************/
#ifndef X2AP_ENB_ENCODER_H_
#define X2AP_ENB_ENCODER_H_
int x2ap_eNB_encode_pdu(s1ap_message *message, uint8_t **buffer, uint32_t *len)
__attribute__ ((warn_unused_result));
#endif /* X2AP_ENB_ENCODER_H_ */
/*******************************************************************************
OpenAirInterface
Copyright(c) 1999 - 2014 Eurecom
OpenAirInterface is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenAirInterface is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with OpenAirInterface.The full GNU General Public License is
included in this distribution in the file called "COPYING". If not,
see <http://www.gnu.org/licenses/>.
Contact Information
OpenAirInterface Admin: openair_admin@eurecom.fr
OpenAirInterface Tech : openair_tech@eurecom.fr
OpenAirInterface Dev : openair4g-devel@lists.eurecom.fr
Address : Eurecom, Campus SophiaTech, 450 Route des Chappes, CS 50193 - 06904 Biot Sophia Antipolis cedex, FRANCE
*******************************************************************************/
/*! \file x2ap_eNB_generate_messages.c
* \brief x2ap message generator
* \author Navid Nikaein
* \date 2015 - 2016
* \version 1.0
* \company Eurecom
* \email: navid.nikaein@eurecom.fr
*/
#include "intertask_interface.h"
#include "x2ap.h"
#include "msc.h"
#include "assertions.h"
static
int x2ap_eNB_generate_x2_setup_request(x2ap_eNB_instance_t *instance_p,
x2ap_enb_data_t *x2ap_enb_data_p){
x2ap_message message;
X2SetupRequest_IEs_t *x2SetupRequest_p;
X2ap_PLMN_Identity_t plmnIdentity;
X2ap_PLMN_Identity_t broadcast_plmnIdentity_1;
X2ap_PLMN_Identity_t broadcast_plmnIdentity_2;
X2ap_PLMN_Identity_t broadcast_plmnIdentity_3;
ServedCellItem_t *served_cell= malloc(sizeof(ServedCellItem_t));;
uint8_t *buffer;
uint32_t len;
int ret = 0;
DevAssert(instance_p != NULL);
DevAssert(x2ap_enb_data_p != NULL);
memset(&message, 0, sizeof(x2ap_message));
message.direction = X2AP_PDU_PR_initiatingMessage;
message.procedureCode = X2ap_ProcedureCode_id_X2Setup;
message.criticality = X2ap_Criticality_reject;
x2SetupRequest_p = &message.msg.x2SetupRequest_IEs;
memset((void *)&plmnIdentity, 0, sizeof(X2ap_PLMN_Identity_t));
memset((void *)&broadcast_plmnIdentity_1, 0, sizeof(X2ap_PLMN_Identity_t));
memset((void *)&broadcast_plmnIdentity_2, 0, sizeof(X2ap_PLMN_Identity_t));
memset((void *)&broadcast_plmnIdentity_3, 0, sizeof(X2ap_PLMN_Identity_t));
x2ap_enb_data_p->state = X2AP_ENB_STATE_WAITING;
//----globalENB_ID------
x2SetupRequest_p->global_ENB_ID.eNB_ID.present = X2ap_ENB_ID_PR_macro_eNB_ID;
MACRO_ENB_ID_TO_BIT_STRING(instance_p->eNB_id,
&x2SetupRequest_p->global_ENB_ID.eNB_ID.choice.macroENB_ID);
MCC_MNC_TO_PLMNID(instance_p->mcc, instance_p->mnc, instance_p->mnc_digit_length,
&x2SetupRequest_p->global_ENB_ID.pLMNidentity);
X2AP_INFO("%d -> %02x%02x%02x\n", instance_p->eNB_id,
x2SetupRequest_p->global_ENB_ID.eNB_ID.choice.macroENB_ID.buf[0],
x2SetupRequest_p->global_ENB_ID.eNB_ID.choice.macroENB_ID.buf[1],
x2SetupRequest_p->global_ENB_ID.eNB_ID.choice.macroENB_ID.buf[2]);
//----served cells------
#warning update the value of the message
served_cell->servedCellInfo.pCI = 6;
served_cell->servedCellInfo.eUTRA_Mode_Info.present = EUTRA_Mode_Info_PR_fDD;
served_cell->servedCellInfo.eUTRA_Mode_Info.choice.fDD.uL_EARFCN = 3350;
served_cell->servedCellInfo.eUTRA_Mode_Info.choice.fDD.dL_EARFCN = 3350;
served_cell->servedCellInfo.eUTRA_Mode_Info.choice.fDD.uL_Transmission_Bandwidth = 0;
served_cell->servedCellInfo.eUTRA_Mode_Info.choice.fDD.dL_Transmission_Bandwidth = 0;
MCC_MNC_TO_PLMNID(instance_p->mcc,instance_p->mnc,&served_cell->servedCellInfo.cellId.pLMN_Identity);
MCC_MNC_TO_PLMNID(0,0,&broadcast_plmnid_1);
MCC_MNC_TO_PLMNID(0,0,&broadcast_plmnid_2);
MCC_MNC_TO_PLMNID(0,0,&broadcast_plmnid_3);
ASN_SEQUENCE_ADD(&served_cell->servedCellInfo.broadcastPLMNs.list, &broadcast_plmnid_1);
ASN_SEQUENCE_ADD(&served_cell->servedCellInfo.broadcastPLMNs.list, &broadcast_plmnid_2);
ASN_SEQUENCE_ADD(&served_cell->servedCellInfo.broadcastPLMNs.list, &broadcast_plmnid_3);
ECI_TO_BIT_STRING(instance_p->eNB_id, &served_cell->servedCellInfo.cellId.eUTRANcellIdentifier);
TAC_TO_OCTET_STRING(instance_p->tac, &served_cell->servedCellInfo.tAC);
ASN_SEQUENCE_ADD(&x2SetupRequest_p->servedCells.list, served_cell);
if (x2ap_eNB_encode_pdu(&message, &buffer, &len) < 0) {
X2AP_ERROR("Failed to encode X2 setup request\n");
return -1;
}
/* Non UE-Associated signalling -> stream = 0 */
x2ap_eNB_itti_send_sctp_data_req(instance_p->instance, x2ap_enb_data_p->assoc_id, buffer, len, 0);
return ret;
}
/*******************************************************************************
OpenAirInterface
Copyright(c) 1999 - 2014 Eurecom
OpenAirInterface is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenAirInterface is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with OpenAirInterface.The full GNU General Public License is
included in this distribution in the file called "COPYING". If not,
see <http://www.gnu.org/licenses/>.
Contact Information
OpenAirInterface Admin: openair_admin@eurecom.fr
OpenAirInterface Tech : openair_tech@eurecom.fr
OpenAirInterface Dev : openair4g-devel@lists.eurecom.fr
Address : Eurecom, Compus SophiaTech 450, route des chappes, 06451 Biot, France.
*******************************************************************************/
/*! \file s1ap_eNB_handlers.c
* \brief s1ap messages handlers for eNB part
* \author Sebastien ROUX <sebastien.roux@eurecom.fr>
* \date 2013
* \version 0.1
*/
#include <stdint.h>
#include "intertask_interface.h"
#include "asn1_conversions.h"
#include "x2ap_common.h"
#include "x2ap_ies_defs.h"
// #include "s1ap_eNB.h"
#include "x2ap_eNB_defs.h"
#include "x2ap_eNB_handlers.h"
#include "x2ap_eNB_decoder.h"
#include "x2ap_eNB_management_procedures.h"
//#include "x2ap_eNB_default_values.h"
#include "assertions.h"
#include "conversions.h"
#include "msc.h"
static
int x2ap_eNB_handle_x2_setup_response(uint32_t assoc_id,
uint32_t stream,
struct x2ap_message_s *message_p);
static
int x2ap_eNB_handle_x2_setup_failure(uint32_t assoc_id,
uint32_t stream,
struct x2ap_message_s *message_p);
static
int x2ap_eNB_handle_error_indication(uint32_t assoc_id,
uint32_t stream,
struct x2ap_message_s *message_p);
int x2ap_eNB_handle_initial_context_request(uint32_t assoc_id,
uint32_t stream,
struct x2ap_message_s *message_p);
static
int x2ap_eNB_handle_ue_context_release_command(uint32_t assoc_id,
uint32_t stream,
struct s1ap_message_s *message_p);
/* Handlers matrix. Only eNB related procedure present here */
// x2ap_messages_callback[message.procedureCode][message.direction]
x2ap_message_decoded_callback x2ap_messages_callback[][3] = {
// { x2ap_eNB_handle_handover_preparation, 0, 0 }, /* HandoverPreparation */
{ 0, 0, 0 }, /* HandoverPreparation */
{ 0, 0, 0 }, /* HandoverCancel */
{ 0, 0, 0 }, /* loadIndication */
{ x2ap_eNB_handle_error_indication, 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 */
};
static const char *x2ap_direction2String[] = {
"", /* Nothing */
"Originating message", /* originating message */
"Successfull outcome", /* successfull outcome */
"UnSuccessfull outcome", /* successfull outcome */
};
int x2ap_eNB_handle_message(uint32_t assoc_id, int32_t stream,
const uint8_t * const data, const uint32_t data_length)
{
struct x2ap_message_s message;
DevAssert(data != NULL);
memset(&message, 0, sizeof(struct x2ap_message_s));
if (x2ap_eNB_decode_pdu(&message, data, data_length) < 0) {
X2AP_ERROR("Failed to decode X2AP PDU\n");
return -1;
}
/* Checking procedure Code and direction of message */
if (message.procedureCode > sizeof(messages_callback) / (3 * sizeof(x2ap_message_decoded_callback))
|| (message.direction > X2AP_PDU_PR_unsuccessfulOutcome)) {
X2AP_ERROR("[SCTP %d] Either procedureCode %d or direction %d exceed expected\n",
assoc_id, message.procedureCode, message.direction);
return -1;
}
/* No handler present.
* This can mean not implemented or no procedure for eNB (wrong direction).
*/
if (x2ap_messages_callback[message.procedureCode][message.direction-1] == NULL) {
S1AP_ERROR("[SCTP %d] No handler for procedureCode %d in %s\n",
assoc_id, message.procedureCode,
s1ap_direction2String[message.direction]);
return -1;
}
/* Calling the right handler */
return (*x2ap_messages_callback[message.procedureCode][message.direction-1])
(assoc_id, stream, &message);
}
void x2ap_handle_x2_setup_message(x2ap_enb_data_t *enb_desc_p, int sctp_shutdown)
{
if (sctp_shutdown) {
/* A previously connected eNB has been shutdown */
/* TODO check if it was used by some eNB and send a message to inform these eNB if there is no more associated MME */
if (enb_desc_p->state == X2AP_ENB_STATE_CONNECTED) {
enb_desc_p->state = X2AP_ENB_STATE_DISCONNECTED;
if (enb_desc_p->x2ap_eNB_instance->x2ap_enb_associated_nb > 0) {
/* Decrease associated eNB number */
enb_desc_p->x2ap_eNB_instance->x2ap_enb_associated_nb --;
}
/* If there are no more associated MME, inform eNB app */
if (enb_desc_p->x2ap_eNB_instance->x2ap_enb_associated_nb == 0) {
MessageDef *message_p;
message_p = itti_alloc_new_message(TASK_X2AP, X2AP_DEREGISTERED_ENB_IND);
X2AP_DEREGISTERED_ENB_IND(message_p).nb_x2 = 0;
itti_send_msg_to_task(TASK_ENB_APP, enb_desc_p->x2ap_eNB_instance->instance, message_p);
}
}
} else {
/* Check that at least one setup message is pending */
DevCheck(enb_desc_p->x2ap_eNB_instance->x2ap_enb_pending_nb > 0,
enb_desc_p->x2ap_eNB_instance->instance,
enb_desc_p->x2ap_eNB_instance->x2ap_enb_pending_nb, 0);
if (enb_desc_p->x2ap_eNB_instance->x2ap_enb_pending_nb > 0) {
/* Decrease pending messages number */
enb_desc_p->x2ap_eNB_instance->x2ap_enb_pending_nb --;
}
/* If there are no more pending messages, inform eNB app */
if (enb_desc_p->x2ap_eNB_instance->x2ap_enb_pending_nb == 0) {
MessageDef *message_p;
message_p = itti_alloc_new_message(TASK_X2AP, X2AP_REGISTER_ENB_CNF);
X2AP_REGISTER_ENB_CNF(message_p).nb_x2 = enb_desc_p->x2ap_eNB_instance->x2ap_enb_associated_nb;
itti_send_msg_to_task(TASK_ENB_APP, enb_desc_p->x2ap_eNB_instance->instance, message_p);
}
}
}
int
x2ap_eNB_handle_x2_setup_request (uint32_t assoc_id,
uint32_t stream,
struct s1ap_message_s *message)
{
X2SetupRequestIEs_t *x2SetupRequest_p;
eNB_description_t *eNB_association;
uint32_t eNB_id = 0;
char *eNB_name = NULL;
int ta_ret;
uint16_t max_enb_connected;
DevAssert (message != NULL);
x2SetupRequest_p = &message->msg.X2SetupRequestIEs;
/*
* We received a new valid X2 Setup Request on a stream != 0.
* * * * This should not happen -> reject eNB s1 setup request.
*/
MSC_LOG_RX_MESSAGE (MSC_X2AP_TARGET_ENB, MSC_X2AP_SRC_ENB, NULL, 0, "0 X2Setup/%s assoc_id %u stream %u", x2ap_direction2String[message->direction], assoc_id, stream);
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 (assoc_id,
X2ap_Cause_PR_protocol,
X2ap_CauseProtocol_unspecified,
-1);
}
X2AP_DEBUG ("Received a new X2 setup request\n");
if (x2SetupRequest_p->global_ENB_ID.eNB_ID.present == X2ap_ENB_ID_PR_homeENB_ID) {
// Home eNB ID = 28 bits
uint8_t *eNB_id_buf = x2SetupRequest_p->global_ENB_ID.eNB_ID.choice.homeENB_ID.buf;
if (x2SetupRequest_p->global_ENB_ID.eNB_ID.choice.macroENB_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 ("eNB id: %07x\n", eNB_id);
} else {
// Macro eNB = 20 bits
uint8_t *eNB_id_buf = s1SetupRequest_p->global_ENB_ID.eNB_ID.choice.macroENB_ID.buf;
if (s1SetupRequest_p->global_ENB_ID.eNB_ID.choice.macroENB_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);
S1AP_DEBUG ("macro eNB id: %05x\n", eNB_id);
}
config_read_lock (&mme_config);
max_enb_connected = mme_config.max_eNBs;
config_unlock (&mme_config);
if (nb_eNB_associated == max_enb_connected) {
S1AP_ERROR ("There is too much eNB connected to MME, rejecting the association\n");
S1AP_DEBUG ("Connected = %d, maximum allowed = %d\n", nb_eNB_associated, max_enb_connected);
/*
* Send an overload cause...
*/
return s1ap_mme_generate_s1_setup_failure (assoc_id, S1ap_Cause_PR_misc, S1ap_CauseMisc_control_processing_overload, S1ap_TimeToWait_v20s);
}
/*
* If none of the provided PLMNs/TAC match the one configured in MME,
* * * * the s1 setup should be rejected with a cause set to Unknown PLMN.
*/
ta_ret = s1ap_mme_compare_ta_lists (&s1SetupRequest_p->supportedTAs);
/*
* eNB and MME have no common PLMN
*/
if (ta_ret != TA_LIST_RET_OK) {
S1AP_ERROR ("No Common PLMN with eNB, generate_s1_setup_failure\n");
return s1ap_mme_generate_s1_setup_failure (assoc_id, S1ap_Cause_PR_misc, S1ap_CauseMisc_unknown_PLMN, S1ap_TimeToWait_v20s);
}
S1AP_DEBUG ("Adding eNB to the list of served eNBs\n");
if ((eNB_association = s1ap_is_eNB_id_in_list (eNB_id)) == NULL) {
/*
* eNB has not been fount in list of associated eNB,
* * * * Add it to the tail of list and initialize data
*/
if ((eNB_association = s1ap_is_eNB_assoc_id_in_list (assoc_id)) == NULL) {
/*
* ??
*/
return -1;
} else {
eNB_association->s1_state = S1AP_RESETING;
eNB_association->eNB_id = eNB_id;
eNB_association->default_paging_drx = s1SetupRequest_p->defaultPagingDRX;
if (eNB_name != NULL) {
memcpy (eNB_association->eNB_name, s1SetupRequest_p->eNBname.buf, s1SetupRequest_p->eNBname.size);
eNB_association->eNB_name[s1SetupRequest_p->eNBname.size] = '\0';
}
}
} else {
eNB_association->s1_state = S1AP_RESETING;
/*
* eNB has been fount in list, consider the s1 setup request as a reset connection,
* * * * reseting any previous UE state if sctp association is != than the previous one
*/
if (eNB_association->sctp_assoc_id != assoc_id) {
S1ap_S1SetupFailureIEs_t s1SetupFailure;
memset (&s1SetupFailure, 0, sizeof (s1SetupFailure));
/*
* Send an overload cause...
*/
s1SetupFailure.cause.present = S1ap_Cause_PR_misc; //TODO: send the right cause
s1SetupFailure.cause.choice.misc = S1ap_CauseMisc_control_processing_overload;
S1AP_ERROR ("Rejeting s1 setup request as eNB id %d is already associated to an active sctp association" "Previous known: %d, new one: %d\n", eNB_id, eNB_association->sctp_assoc_id, assoc_id);
// s1ap_mme_encode_s1setupfailure(&s1SetupFailure,
// receivedMessage->msg.s1ap_sctp_new_msg_ind.assocId);
return -1;
}
/*
* TODO: call the reset procedure
*/
}
s1ap_dump_eNB (eNB_association);
return s1ap_generate_s1_setup_response (eNB_association);
} else {
/*
* Can not process the request, MME is not connected to HSS
*/
S1AP_ERROR ("Rejecting s1 setup request Can not process the request, MME is not connected to HSS\n");
return s1ap_mme_generate_s1_setup_failure (assoc_id, S1ap_Cause_PR_misc, S1ap_CauseMisc_unspecified, -1);
}
}
static
int x2ap_eNB_handle_x2_setup_failure(uint32_t assoc_id,
uint32_t stream,
struct x2ap_message_s *message_p)
{
#ifdef 0
X2SetupFailureIEs_t *s1_setup_failure_p;
x2ap_eNB_data_t *enb_desc_p;
DevAssert(message_p != NULL);
s1_setup_failure_p = &message_p->msg.s1ap_S1SetupFailureIEs;
/* S1 Setup Failure == Non UE-related procedure -> stream 0 */
if (stream != 0) {
S1AP_WARN("[SCTP %d] Received s1 setup failure on stream != 0 (%d)\n",
assoc_id, stream);
}
if ((mme_desc_p = s1ap_eNB_get_MME(NULL, assoc_id, 0)) == NULL) {
S1AP_ERROR("[SCTP %d] Received S1 setup response for non existing "
"MME context\n", assoc_id);
return -1;
}
if ((s1_setup_failure_p->cause.present == S1ap_Cause_PR_misc) &&
(s1_setup_failure_p->cause.choice.misc == S1ap_CauseMisc_unspecified)) {
S1AP_WARN("Received s1 setup failure for MME... MME is not ready\n");
} else {
S1AP_ERROR("Received s1 setup failure for MME... please check your parameters\n");
}
mme_desc_p->state = S1AP_ENB_STATE_WAITING;
s1ap_handle_s1_setup_message(mme_desc_p, 0);
#endif
return 0;
}
static
int x2ap_eNB_handle_x2_setup_response(uint32_t assoc_id,
uint32_t stream,
struct x2ap_message_s *message_p)
{
#ifdef 0
S1ap_S1SetupResponseIEs_t *s1SetupResponse_p;
s1ap_eNB_mme_data_t *mme_desc_p;
int i;
DevAssert(message_p != NULL);
s1SetupResponse_p = &message_p->msg.s1ap_S1SetupResponseIEs;
/* S1 Setup Response == Non UE-related procedure -> stream 0 */
if (stream != 0) {
S1AP_ERROR("[SCTP %d] Received s1 setup response on stream != 0 (%d)\n",
assoc_id, stream);
return -1;
}
if ((mme_desc_p = s1ap_eNB_get_MME(NULL, assoc_id, 0)) == NULL) {
S1AP_ERROR("[SCTP %d] Received S1 setup response for non existing "
"MME context\n", assoc_id);
return -1;
}
/* The list of served gummei can contain at most 8 elements.
* LTE related gummei is the first element in the list, i.e with an id of 0.
*/
S1AP_DEBUG("servedGUMMEIs.list.count %d\n",s1SetupResponse_p->servedGUMMEIs.list.count);
DevAssert(s1SetupResponse_p->servedGUMMEIs.list.count > 0);
DevAssert(s1SetupResponse_p->servedGUMMEIs.list.count <= 8);
for (i = 0; i < s1SetupResponse_p->servedGUMMEIs.list.count; i++) {
struct S1ap_ServedGUMMEIsItem *gummei_item_p;
struct served_gummei_s *new_gummei_p;
int j;
gummei_item_p = (struct S1ap_ServedGUMMEIsItem *)
s1SetupResponse_p->servedGUMMEIs.list.array[i];
new_gummei_p = calloc(1, sizeof(struct served_gummei_s));
STAILQ_INIT(&new_gummei_p->served_plmns);
STAILQ_INIT(&new_gummei_p->served_group_ids);
STAILQ_INIT(&new_gummei_p->mme_codes);
S1AP_DEBUG("servedPLMNs.list.count %d\n",gummei_item_p->servedPLMNs.list.count);
for (j = 0; j < gummei_item_p->servedPLMNs.list.count; j++) {
S1ap_PLMNidentity_t *plmn_identity_p;
struct plmn_identity_s *new_plmn_identity_p;
plmn_identity_p = gummei_item_p->servedPLMNs.list.array[j];
new_plmn_identity_p = calloc(1, sizeof(struct plmn_identity_s));
TBCD_TO_MCC_MNC(plmn_identity_p, new_plmn_identity_p->mcc,
new_plmn_identity_p->mnc, new_plmn_identity_p->mnc_digit_length);
STAILQ_INSERT_TAIL(&new_gummei_p->served_plmns, new_plmn_identity_p, next);
new_gummei_p->nb_served_plmns++;
}
for (j = 0; j < gummei_item_p->servedGroupIDs.list.count; j++) {
S1ap_MME_Group_ID_t *mme_group_id_p;
struct served_group_id_s *new_group_id_p;
mme_group_id_p = gummei_item_p->servedGroupIDs.list.array[j];
new_group_id_p = calloc(1, sizeof(struct served_group_id_s));
OCTET_STRING_TO_INT16(mme_group_id_p, new_group_id_p->mme_group_id);
STAILQ_INSERT_TAIL(&new_gummei_p->served_group_ids, new_group_id_p, next);
new_gummei_p->nb_group_id++;
}
for (j = 0; j < gummei_item_p->servedMMECs.list.count; j++) {
S1ap_MME_Code_t *mme_code_p;
struct mme_code_s *new_mme_code_p;
mme_code_p = gummei_item_p->servedMMECs.list.array[j];
new_mme_code_p = calloc(1, sizeof(struct mme_code_s));
OCTET_STRING_TO_INT8(mme_code_p, new_mme_code_p->mme_code);
STAILQ_INSERT_TAIL(&new_gummei_p->mme_codes, new_mme_code_p, next);
new_gummei_p->nb_mme_code++;
}
STAILQ_INSERT_TAIL(&mme_desc_p->served_gummei, new_gummei_p, next);
}
/* Free contents of the list */
ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_S1ap_ServedGUMMEIs,
(void *)&s1SetupResponse_p->servedGUMMEIs);
/* Set the capacity of this MME */
mme_desc_p->relative_mme_capacity = s1SetupResponse_p->relativeMMECapacity;
/* Optionaly set the mme name */
if (s1SetupResponse_p->presenceMask & S1AP_S1SETUPRESPONSEIES_MMENAME_PRESENT) {
mme_desc_p->mme_name = calloc(s1SetupResponse_p->mmEname.size + 1, sizeof(char));
memcpy(mme_desc_p->mme_name, s1SetupResponse_p->mmEname.buf,
s1SetupResponse_p->mmEname.size);
/* Convert the mme name to a printable string */
mme_desc_p->mme_name[s1SetupResponse_p->mmEname.size] = '\0';
}
/* The association is now ready as eNB and MME know parameters of each other.
* Mark the association as UP to enable UE contexts creation.
*/
mme_desc_p->state = S1AP_ENB_STATE_CONNECTED;
mme_desc_p->s1ap_eNB_instance->s1ap_mme_associated_nb ++;
s1ap_handle_s1_setup_message(mme_desc_p, 0);
#endif
return 0;
}
static
int x2ap_eNB_handle_error_indication(uint32_t assoc_id,
uint32_t stream,
struct x2ap_message_s *message_p)
{
#ifdef 0
X2ap_ErrorIndicationIEs_t *x2_error_indication_p;
x2ap_eNB_data_t *enb_desc_p;
DevAssert(message_p != NULL);
s1_error_indication_p = &message_p->msg.s1ap_ErrorIndicationIEs;
/* S1 Setup Failure == Non UE-related procedure -> stream 0 */
if (stream != 0) {
S1AP_WARN("[SCTP %d] Received s1 Error indication on stream != 0 (%d)\n",
assoc_id, stream);
}
if ((mme_desc_p = s1ap_eNB_get_MME(NULL, assoc_id, 0)) == NULL) {
S1AP_ERROR("[SCTP %d] Received S1 Error indication for non existing "
"MME context\n", assoc_id);
return -1;
}
if ( s1_error_indication_p->presenceMask & S1AP_ERRORINDICATIONIES_MME_UE_S1AP_ID_PRESENT) {
S1AP_WARN("Received S1 Error indication MME UE S1AP ID 0x%x\n", s1_error_indication_p->mme_ue_s1ap_id);
}
if ( s1_error_indication_p->presenceMask & S1AP_ERRORINDICATIONIES_ENB_UE_S1AP_ID_PRESENT) {
S1AP_WARN("Received S1 Error indication eNB UE S1AP ID 0x%x\n", s1_error_indication_p->eNB_UE_S1AP_ID);
}
if ( s1_error_indication_p->presenceMask & S1AP_ERRORINDICATIONIES_CAUSE_PRESENT) {
switch(s1_error_indication_p->cause.present) {
case S1ap_Cause_PR_NOTHING:
S1AP_WARN("Received S1 Error indication cause NOTHING\n");
break;
case S1ap_Cause_PR_radioNetwork:
switch (s1_error_indication_p->cause.choice.radioNetwork) {
case S1ap_CauseRadioNetwork_unspecified:
S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_unspecified\n");
break;
case S1ap_CauseRadioNetwork_tx2relocoverall_expiry:
S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_tx2relocoverall_expiry\n");
break;
case S1ap_CauseRadioNetwork_successful_handover:
S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_successful_handover\n");
break;
case S1ap_CauseRadioNetwork_release_due_to_eutran_generated_reason:
S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_release_due_to_eutran_generated_reason\n");
break;
case S1ap_CauseRadioNetwork_handover_cancelled:
S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_handover_cancelled\n");
break;
case S1ap_CauseRadioNetwork_partial_handover:
S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_partial_handover\n");
break;
case S1ap_CauseRadioNetwork_ho_failure_in_target_EPC_eNB_or_target_system:
S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_ho_failure_in_target_EPC_eNB_or_target_system\n");
break;
case S1ap_CauseRadioNetwork_ho_target_not_allowed:
S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_ho_target_not_allowed\n");
break;
case S1ap_CauseRadioNetwork_tS1relocoverall_expiry:
S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_tS1relocoverall_expiry\n");
break;
case S1ap_CauseRadioNetwork_tS1relocprep_expiry:
S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_tS1relocprep_expiry\n");
break;
case S1ap_CauseRadioNetwork_cell_not_available:
S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_cell_not_available\n");
break;
case S1ap_CauseRadioNetwork_unknown_targetID:
S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_unknown_targetID\n");
break;
case S1ap_CauseRadioNetwork_no_radio_resources_available_in_target_cell:
S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_no_radio_resources_available_in_target_cell\n");
break;
case S1ap_CauseRadioNetwork_unknown_mme_ue_s1ap_id:
S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_unknown_mme_ue_s1ap_id\n");
break;
case S1ap_CauseRadioNetwork_unknown_enb_ue_s1ap_id:
S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_unknown_enb_ue_s1ap_id\n");
break;
case S1ap_CauseRadioNetwork_unknown_pair_ue_s1ap_id:
S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_unknown_pair_ue_s1ap_id\n");
break;
case S1ap_CauseRadioNetwork_handover_desirable_for_radio_reason:
S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_handover_desirable_for_radio_reason\n");
break;
case S1ap_CauseRadioNetwork_time_critical_handover:
S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_time_critical_handover\n");
break;
case S1ap_CauseRadioNetwork_resource_optimisation_handover:
S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_resource_optimisation_handover\n");
break;
case S1ap_CauseRadioNetwork_reduce_load_in_serving_cell:
S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_reduce_load_in_serving_cell\n");
break;
case S1ap_CauseRadioNetwork_user_inactivity:
S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_user_inactivity\n");
break;
case S1ap_CauseRadioNetwork_radio_connection_with_ue_lost:
S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_radio_connection_with_ue_lost\n");
break;
case S1ap_CauseRadioNetwork_load_balancing_tau_required:
S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_load_balancing_tau_required\n");
break;
case S1ap_CauseRadioNetwork_cs_fallback_triggered:
S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_cs_fallback_triggered\n");
break;
case S1ap_CauseRadioNetwork_ue_not_available_for_ps_service:
S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_ue_not_available_for_ps_service\n");
break;
case S1ap_CauseRadioNetwork_radio_resources_not_available:
S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_radio_resources_not_available\n");
break;
case S1ap_CauseRadioNetwork_failure_in_radio_interface_procedure:
S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_failure_in_radio_interface_procedure\n");
break;
case S1ap_CauseRadioNetwork_invals1ap_id_qos_combination:
S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_invals1ap_id_qos_combination\n");
break;
case S1ap_CauseRadioNetwork_interrat_redirection:
S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_interrat_redirection\n");
break;
case S1ap_CauseRadioNetwork_interaction_with_other_procedure:
S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_interaction_with_other_procedure\n");
break;
case S1ap_CauseRadioNetwork_unknown_E_RAB_ID:
S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_unknown_E_RAB_ID\n");
break;
case S1ap_CauseRadioNetwork_multiple_E_RAB_ID_instances:
S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_multiple_E_RAB_ID_instances\n");
break;
case S1ap_CauseRadioNetwork_encryption_and_or_integrity_protection_algorithms_not_supported:
S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_encryption_and_or_integrity_protection_algorithms_not_supported\n");
break;
case S1ap_CauseRadioNetwork_s1_intra_system_handover_triggered:
S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_s1_intra_system_handover_triggered\n");
break;
case S1ap_CauseRadioNetwork_s1_inter_system_handover_triggered:
S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_s1_inter_system_handover_triggered\n");
break;
case S1ap_CauseRadioNetwork_x2_handover_triggered:
S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_x2_handover_triggered\n");
break;
case S1ap_CauseRadioNetwork_redirection_towards_1xRTT:
S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_redirection_towards_1xRTT\n");
break;
case S1ap_CauseRadioNetwork_not_supported_QCI_value:
S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_not_supported_QCI_value\n");
break;
case S1ap_CauseRadioNetwork_invals1ap_id_CSG_Id:
S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_invals1ap_id_CSG_Id\n");
break;
default:
S1AP_WARN("Received S1 Error indication cause radio network case not handled\n");
}
break;
case S1ap_Cause_PR_transport:
switch (s1_error_indication_p->cause.choice.transport) {
case S1ap_CauseTransport_transport_resource_unavailable:
S1AP_WARN("Received S1 Error indication S1ap_CauseTransport_transport_resource_unavailable\n");
break;
case S1ap_CauseTransport_unspecified:
S1AP_WARN("Received S1 Error indication S1ap_CauseTransport_unspecified\n");
break;
default:
S1AP_WARN("Received S1 Error indication cause transport case not handled\n");
}
break;
case S1ap_Cause_PR_nas:
switch (s1_error_indication_p->cause.choice.nas) {
case S1ap_CauseNas_normal_release:
S1AP_WARN("Received S1 Error indication S1ap_CauseNas_normal_release\n");
break;
case S1ap_CauseNas_authentication_failure:
S1AP_WARN("Received S1 Error indication S1ap_CauseNas_authentication_failure\n");
break;
case S1ap_CauseNas_detach:
S1AP_WARN("Received S1 Error indication S1ap_CauseNas_detach\n");
break;
case S1ap_CauseNas_unspecified:
S1AP_WARN("Received S1 Error indication S1ap_CauseNas_unspecified\n");
break;
case S1ap_CauseNas_csg_subscription_expiry:
S1AP_WARN("Received S1 Error indication S1ap_CauseNas_csg_subscription_expiry\n");
break;
default:
S1AP_WARN("Received S1 Error indication cause nas case not handled\n");
}
break;
case S1ap_Cause_PR_protocol:
switch (s1_error_indication_p->cause.choice.protocol) {
case S1ap_CauseProtocol_transfer_syntax_error:
S1AP_WARN("Received S1 Error indication S1ap_CauseProtocol_transfer_syntax_error\n");
break;
case S1ap_CauseProtocol_abstract_syntax_error_reject:
S1AP_WARN("Received S1 Error indication S1ap_CauseProtocol_abstract_syntax_error_reject\n");
break;
case S1ap_CauseProtocol_abstract_syntax_error_ignore_and_notify:
S1AP_WARN("Received S1 Error indication S1ap_CauseProtocol_abstract_syntax_error_ignore_and_notify\n");
break;
case S1ap_CauseProtocol_message_not_compatible_with_receiver_state:
S1AP_WARN("Received S1 Error indication S1ap_CauseProtocol_message_not_compatible_with_receiver_state\n");
break;
case S1ap_CauseProtocol_semantic_error:
S1AP_WARN("Received S1 Error indication S1ap_CauseProtocol_semantic_error\n");
break;
case S1ap_CauseProtocol_abstract_syntax_error_falsely_constructed_message:
S1AP_WARN("Received S1 Error indication S1ap_CauseProtocol_abstract_syntax_error_falsely_constructed_message\n");
break;
case S1ap_CauseProtocol_unspecified:
S1AP_WARN("Received S1 Error indication S1ap_CauseProtocol_unspecified\n");
break;
default:
S1AP_WARN("Received S1 Error indication cause protocol case not handled\n");
}
break;
case S1ap_Cause_PR_misc:
switch (s1_error_indication_p->cause.choice.protocol) {
case S1ap_CauseMisc_control_processing_overload:
S1AP_WARN("Received S1 Error indication S1ap_CauseMisc_control_processing_overload\n");
break;
case S1ap_CauseMisc_not_enough_user_plane_processing_resources:
S1AP_WARN("Received S1 Error indication S1ap_CauseMisc_not_enough_user_plane_processing_resources\n");
break;
case S1ap_CauseMisc_hardware_failure:
S1AP_WARN("Received S1 Error indication S1ap_CauseMisc_hardware_failure\n");
break;
case S1ap_CauseMisc_om_intervention:
S1AP_WARN("Received S1 Error indication S1ap_CauseMisc_om_intervention\n");
break;
case S1ap_CauseMisc_unspecified:
S1AP_WARN("Received S1 Error indication S1ap_CauseMisc_unspecified\n");
break;
case S1ap_CauseMisc_unknown_PLMN:
S1AP_WARN("Received S1 Error indication S1ap_CauseMisc_unknown_PLMN\n");
break;
default:
S1AP_WARN("Received S1 Error indication cause misc case not handled\n");
}
break;
}
}
if ( s1_error_indication_p->presenceMask & S1AP_ERRORINDICATIONIES_CRITICALITYDIAGNOSTICS_PRESENT) {
// TODO continue
}
// TODO continue
#endif
return 0;
}
/*******************************************************************************
OpenAirInterface
Copyright(c) 1999 - 2014 Eurecom
OpenAirInterface is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenAirInterface is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with OpenAirInterface.The full GNU General Public License is
included in this distribution in the file called "COPYING". If not,
see <http://www.gnu.org/licenses/>.
Contact Information
OpenAirInterface Admin: openair_admin@eurecom.fr
OpenAirInterface Tech : openair_tech@eurecom.fr
OpenAirInterface Dev : openair4g-devel@lists.eurecom.fr
Address : Eurecom, Compus SophiaTech 450, route des chappes, 06451 Biot, France.
*******************************************************************************/
#ifndef X2AP_ENB_HANDLERS_H_
#define X2AP_ENB_HANDLERS_H_
void x2ap_handle_x2_setup_message(x2ap_eNB_data_t *mme_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);
#endif /* X2AP_ENB_HANDLERS_H_ */
/*******************************************************************************
OpenAirInterface
Copyright(c) 1999 - 2014 Eurecom
OpenAirInterface is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenAirInterface is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with OpenAirInterface.The full GNU General Public License is
included in this distribution in the file called "COPYING". If not,
see <http://www.gnu.org/licenses/>.
Contact Information
OpenAirInterface Admin: openair_admin@eurecom.fr
OpenAirInterface Tech : openair_tech@eurecom.fr
OpenAirInterface Dev : openair4g-devel@lists.eurecom.fr
Address : Eurecom, Compus SophiaTech 450, route des chappes, 06451 Biot, France.
*******************************************************************************/
#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_nas_downlink_ind(instance_t instance,
uint16_t ue_initial_id,
uint32_t eNB_ue_s1ap_id,
uint8_t *nas_pdu,
uint32_t nas_pdu_length)
{
MessageDef *message_p;
x2ap_rrc_t *x2ap_rrc;
message_p = itti_alloc_new_message(TASK_X2AP, X2AP_RRC);
x2ap_rrc = &message_p->ittiMsg.x2ap_rrc;
x2ap_rrc->ue_initial_id = ue_initial_id;
x2ap_rrc->eNB_ue_x2ap_id = eNB_ue_x2ap_id;
x2ap_rrc->rrc_pdu.buffer = rrc_pdu;
x2ap_rrc->rrc_pdu.length = rrc_pdu_length;
itti_send_msg_to_task(TASK_RRC_ENB, 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);
}
/*******************************************************************************
OpenAirInterface
Copyright(c) 1999 - 2014 Eurecom
OpenAirInterface is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenAirInterface is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with OpenAirInterface.The full GNU General Public License is
included in this distribution in the file called "COPYING". If not,
see <http://www.gnu.org/licenses/>.
Contact Information
OpenAirInterface Admin: openair_admin@eurecom.fr
OpenAirInterface Tech : openair_tech@eurecom.fr
OpenAirInterface Dev : openair4g-devel@lists.eurecom.fr
Address : Eurecom, Compus SophiaTech 450, route des chappes, 06451 Biot, France.
*******************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include "intertask_interface.h"
#include "assertions.h"
#include "conversions.h"
#include "x2ap_common.h"
#include "x2ap_eNB_defs.h"
#include "x2ap.h"
x2ap_eNB_internal_data_t x2ap_eNB_internal_data;
RB_GENERATE(x2ap_enb_map, x2ap_eNB_data_s, entry, x2ap_eNB_compare_assoc_id);
int x2ap_eNB_compare_assoc_id(
struct x2ap_eNB_data_s *p1, struct x2ap_eNB_data_s *p2)
{
if (p1->assoc_id == -1) {
if (p1->cnx_id < p2->cnx_id) {
return -1;
}
if (p1->cnx_id > p2->cnx_id) {
return 1;
}
} else {
if (p1->assoc_id < p2->assoc_id) {
return -1;
}
if (p1->assoc_id > p2->assoc_id) {
return 1;
}
}
/* Matching reference */
return 0;
}
uint16_t x2ap_eNB_fetch_add_global_cnx_id(void)
{
return ++x2ap_eNB_internal_data.global_cnx_id;
}
void x2ap_eNB_prepare_internal_data(void)
{
memset(&x2ap_eNB_internal_data, 0, sizeof(x2ap_eNB_internal_data));
STAILQ_INIT(&x2ap_eNB_internal_data.x2ap_eNB_instances_head);
}
void x2ap_eNB_insert_new_instance(x2ap_eNB_instance_t *new_instance_p)
{
DevAssert(new_instance_p != NULL);
STAILQ_INSERT_TAIL(&x2ap_eNB_internal_data.x2ap_eNB_instances_head,
new_instance_p, x2ap_eNB_entries);
}
struct s1ap_eNB_mme_data_s *x2ap_eNB_get_taregt_eNB(
x2ap_eNB_instance_t *instance_p,
int32_t assoc_id, uint16_t cnx_id)
{
struct x2ap_eNB_data_s temp;
struct x2ap_eNB_data_s *found;
memset(&temp, 0, sizeof(struct x2ap_eNB_data_s));
temp.assoc_id = assoc_id;
temp.cnx_id = cnx_id;
if (instance_p == NULL) {
STAILQ_FOREACH(instance_p, &x2ap_eNB_internal_data.x2ap_eNB_instances_head,
x2ap_eNB_entries) {
found = RB_FIND(x2ap_enb_map, &instance_p->x2ap_enb_head, &temp);
if (found != NULL) {
return found;
}
}
} else {
return RB_FIND(x2ap_enb_map, &instance_p->x2ap_enb_head, &temp);
}
return NULL;
}
x2ap_eNB_instance_t *x2ap_eNB_get_instance(instance_t instance)
{
x2ap_eNB_instance_t *temp = NULL;
STAILQ_FOREACH(temp, &x2ap_eNB_internal_data.x2ap_eNB_instances_head,
x2ap_eNB_entries) {
if (temp->instance == instance) {
/* Matching occurence */
return temp;
}
}
return NULL;
}
/*******************************************************************************
OpenAirInterface
Copyright(c) 1999 - 2014 Eurecom
OpenAirInterface is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenAirInterface is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with OpenAirInterface.The full GNU General Public License is
included in this distribution in the file called "COPYING". If not,
see <http://www.gnu.org/licenses/>.
Contact Information
OpenAirInterface Admin: openair_admin@eurecom.fr
OpenAirInterface Tech : openair_tech@eurecom.fr
OpenAirInterface Dev : openair4g-devel@lists.eurecom.fr
Address : Eurecom, Compus SophiaTech 450, route des chappes, 06451 Biot, France.
*******************************************************************************/
#ifndef X2AP_ENB_MANAGEMENT_PROCEDURES_H_
#define X2AP_ENB_MANAGEMENT_PROCEDURES_H_
/*
struct x2ap_eNB_mme_data_s *s1ap_eNB_get_MME(
s1ap_eNB_instance_t *instance_p,
int32_t assoc_id, uint16_t cnx_id);
*/
void x2ap_eNB_insert_new_instance(x2ap_eNB_instance_t *new_instance_p);
x2ap_eNB_instance_t *x2ap_eNB_get_instance(uint8_t mod_id);
uint16_t x2ap_eNB_fetch_add_global_cnx_id(void);
void x2ap_eNB_prepare_internal_data(void);
#endif /* X2AP_ENB_MANAGEMENT_PROCEDURES_H_ */
......@@ -203,7 +203,7 @@ void s1ap_eNB_handle_register_eNB(instance_t instance, s1ap_register_enb_req_t *
/* Trying to connect to provided list of MME ip address */
for (index = 0; index < s1ap_register_eNB->nb_mme; index++) {
s1ap_eNB_register_mme(new_instance,
&s1ap_register_eNB->mme_ip_address[index],
&s1ap_register_eNB->mme_ip_address[index],
&s1ap_register_eNB->enb_ip_address,
s1ap_register_eNB->sctp_in_streams,
s1ap_register_eNB->sctp_out_streams);
......
......@@ -220,7 +220,7 @@ int s1ap_eNB_decode_pdu(s1ap_message *message, const uint8_t * const buffer,
0);
if (dec_ret.code != RC_OK) {
S1AP_ERROR("Failed to decode pdu\n");
S1AP_ERROR("Failed to S1AP decode pdu\n");
return -1;
}
......
......@@ -30,6 +30,7 @@
/*! \file s1ap_eNB_encoder.c
* \brief s1ap pdu encode procedures for eNB
* \author Sebastien ROUX <sebastien.roux@eurecom.fr>
* \maintainer Navid Nikaein
* \date 2013
* \version 0.1
*/
......
......@@ -17,7 +17,7 @@ eNBs =
mobile_country_code = "208";
mobile_network_code = "93";
mobile_network_code = "92";
////////// Physical parameters:
......@@ -133,21 +133,38 @@ eNBs =
////////// MME parameters:
mme_ip_address = ( { ipv4 = "192.168.12.11";
mme_ip_address = ( { ipv4 = "10.0.1.1";
ipv6 = "192:168:30::17";
active = "yes";
preference = "ipv4";
}
);
NETWORK_INTERFACES :
///X2
target_enb_x2_ip_address = ( { ipv4 = "10.0.1.1";
ipv6 = "192:168:30::17";
active = "yes";
preference = "ipv4";
}
);
NETWORK_INTERFACES :
{
ENB_INTERFACE_NAME_FOR_S1_MME = "eth0";
ENB_IPV4_ADDRESS_FOR_S1_MME = "192.168.12.216/24";
ENB_IPV4_ADDRESS_FOR_S1_MME = "10.0.1.100/24";
ENB_INTERFACE_NAME_FOR_S1U = "eth0";
ENB_IPV4_ADDRESS_FOR_S1U = "192.168.12.216/24";
ENB_IPV4_ADDRESS_FOR_S1U = "10.0.1.100/24";
ENB_PORT_FOR_S1U = 2152; # Spec 2152
ENB_INTERFACE_NAME_FOR_X2C = "eth0";
ENB_IPV4_ADDRESS_FOR_X2C = "10.0.1.100/24";
ENB_PORT_FOR_X2C = 1234; # Spec ?
ENB_INTERFACE_NAME_FOR_X2U = "eth0";
ENB_IPV4_ADDRESS_FOR_X2U = "10.0.1.100/24";
ENB_PORT_FOR_X2U = 1234; # Spec ?
};
log_config :
......
......@@ -46,7 +46,7 @@
<eNB_MOBILITY>
<eNB_INITIAL_DISTRIBUTION>random</eNB_INITIAL_DISTRIBUTION> <!-- use random here and trace for the mobility to define your own positions -->
<RANDOM_eNB_DISTRIBUTION>
<NUMBER_OF_CELLS>3</NUMBER_OF_CELLS>
<NUMBER_OF_CELLS>2</NUMBER_OF_CELLS>
</RANDOM_eNB_DISTRIBUTION>
<eNB_MOBILITY_TYPE>TRACE</eNB_MOBILITY_TYPE>
<TRACE_MOBILITY_FILE>hexagonal_eNBs.tr</TRACE_MOBILITY_FILE> <!-- file should be located at $(OPENAIR2)/UTIL/OMG/TRACE/, see README there-->
......
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