Commit cb4e2c55 authored by Raphael Defosseux's avatar Raphael Defosseux

Merge remote-tracking branch 'origin/x2' into develop_integration_2019_w11

parents c6b2ca24 0a459545
......@@ -360,6 +360,11 @@ eNBs =
}
);
///X2
enable_x2 = "no";
t_reloc_prep = 1000; /* unit: millisecond */
tx2_reloc_overall = 2000; /* unit: millisecond */
NETWORK_INTERFACES :
{
ENB_INTERFACE_NAME_FOR_S1_MME = "eth0";
......
......@@ -141,6 +141,11 @@ eNBs =
}
);
///X2
enable_x2 = "no";
t_reloc_prep = 1000; /* unit: millisecond */
tx2_reloc_overall = 2000; /* unit: millisecond */
NETWORK_INTERFACES :
{
ENB_INTERFACE_NAME_FOR_S1_MME = "eth0";
......
......@@ -141,6 +141,11 @@ eNBs =
}
);
///X2
enable_x2 = "no";
t_reloc_prep = 1000; /* unit: millisecond */
tx2_reloc_overall = 2000; /* unit: millisecond */
NETWORK_INTERFACES :
{
ENB_INTERFACE_NAME_FOR_S1_MME = "eth0";
......
......@@ -141,6 +141,11 @@ eNBs =
}
);
///X2
enable_x2 = "no";
t_reloc_prep = 1000; /* unit: millisecond */
tx2_reloc_overall = 2000; /* unit: millisecond */
NETWORK_INTERFACES :
{
ENB_INTERFACE_NAME_FOR_S1_MME = "eth0";
......
......@@ -178,6 +178,11 @@ eNBs =
}
);
///X2
enable_x2 = "no";
t_reloc_prep = 1000; /* unit: millisecond */
tx2_reloc_overall = 2000; /* unit: millisecond */
NETWORK_INTERFACES :
{
ENB_INTERFACE_NAME_FOR_S1_MME = "eth0";
......
......@@ -178,6 +178,11 @@ eNBs =
}
);
///X2
enable_x2 = "no";
t_reloc_prep = 1000; /* unit: millisecond */
tx2_reloc_overall = 2000; /* unit: millisecond */
NETWORK_INTERFACES :
{
ENB_INTERFACE_NAME_FOR_S1_MME = "eth0";
......
......@@ -178,6 +178,11 @@ eNBs =
}
);
///X2
enable_x2 = "no";
t_reloc_prep = 1000; /* unit: millisecond */
tx2_reloc_overall = 2000; /* unit: millisecond */
NETWORK_INTERFACES :
{
ENB_INTERFACE_NAME_FOR_S1_MME = "eth0";
......
......@@ -181,6 +181,11 @@ eNBs =
}
);
///X2
enable_x2 = "no";
t_reloc_prep = 1000; /* unit: millisecond */
tx2_reloc_overall = 2000; /* unit: millisecond */
NETWORK_INTERFACES :
{
ENB_INTERFACE_NAME_FOR_S1_MME = "eth0";
......
......@@ -178,6 +178,11 @@ eNBs =
}
);
///X2
enable_x2 = "no";
t_reloc_prep = 1000; /* unit: millisecond */
tx2_reloc_overall = 2000; /* unit: millisecond */
NETWORK_INTERFACES :
{
......
......@@ -141,6 +141,11 @@ eNBs =
}
);
///X2
enable_x2 = "no";
t_reloc_prep = 1000; /* unit: millisecond */
tx2_reloc_overall = 2000; /* unit: millisecond */
NETWORK_INTERFACES :
{
ENB_INTERFACE_NAME_FOR_S1_MME = "eth0";
......
......@@ -144,6 +144,11 @@ eNBs =
}
);
///X2
enable_x2 = "no";
t_reloc_prep = 1000; /* unit: millisecond */
tx2_reloc_overall = 2000; /* unit: millisecond */
NETWORK_INTERFACES :
{
ENB_INTERFACE_NAME_FOR_S1_MME = "eth0";
......
......@@ -144,6 +144,11 @@ eNBs =
}
);
///X2
enable_x2 = "no";
t_reloc_prep = 1000; /* unit: millisecond */
tx2_reloc_overall = 2000; /* unit: millisecond */
NETWORK_INTERFACES :
{
ENB_INTERFACE_NAME_FOR_S1_MME = "eth0";
......
......@@ -144,6 +144,11 @@ eNBs =
}
);
///X2
enable_x2 = "no";
t_reloc_prep = 1000; /* unit: millisecond */
tx2_reloc_overall = 2000; /* unit: millisecond */
NETWORK_INTERFACES :
{
ENB_INTERFACE_NAME_FOR_S1_MME = "eth0";
......
......@@ -181,6 +181,11 @@ eNBs =
}
);
///X2
enable_x2 = "no";
t_reloc_prep = 1000; /* unit: millisecond */
tx2_reloc_overall = 2000; /* unit: millisecond */
NETWORK_INTERFACES :
{
ENB_INTERFACE_NAME_FOR_S1_MME = "eth0";
......
......@@ -181,6 +181,11 @@ eNBs =
}
);
///X2
enable_x2 = "no";
t_reloc_prep = 1000; /* unit: millisecond */
tx2_reloc_overall = 2000; /* unit: millisecond */
NETWORK_INTERFACES :
{
ENB_INTERFACE_NAME_FOR_S1_MME = "eth0";
......
......@@ -181,6 +181,11 @@ eNBs =
}
);
///X2
enable_x2 = "no";
t_reloc_prep = 1000; /* unit: millisecond */
tx2_reloc_overall = 2000; /* unit: millisecond */
NETWORK_INTERFACES :
{
ENB_INTERFACE_NAME_FOR_S1_MME = "eth0";
......
......@@ -179,6 +179,11 @@ eNBs =
}
);
///X2
enable_x2 = "no";
t_reloc_prep = 1000; /* unit: millisecond */
tx2_reloc_overall = 2000; /* unit: millisecond */
NETWORK_INTERFACES :
{
ENB_INTERFACE_NAME_FOR_S1_MME = "ens3";
......
......@@ -471,6 +471,7 @@ add_library(X2AP_ENB
${X2AP_DIR}/x2ap_eNB_management_procedures.c
${X2AP_DIR}/x2ap_eNB_generate_messages.c
${X2AP_DIR}/x2ap_ids.c
${X2AP_DIR}/x2ap_timers.c
)
add_dependencies(X2AP_ENB rrc_flag x2_flag)
......
......@@ -141,6 +141,11 @@ eNBs =
}
);
///X2
enable_x2 = "no";
t_reloc_prep = 1000; /* unit: millisecond */
tx2_reloc_overall = 2000; /* unit: millisecond */
NETWORK_INTERFACES :
{
ENB_INTERFACE_NAME_FOR_S1_MME = "eth6";
......
......@@ -141,6 +141,11 @@ eNBs =
}
);
///X2
enable_x2 = "no";
t_reloc_prep = 1000; /* unit: millisecond */
tx2_reloc_overall = 2000; /* unit: millisecond */
NETWORK_INTERFACES :
{
ENB_INTERFACE_NAME_FOR_S1_MME = "eth6";
......
......@@ -141,6 +141,11 @@ eNBs =
}
);
///X2
enable_x2 = "no";
t_reloc_prep = 1000; /* unit: millisecond */
tx2_reloc_overall = 2000; /* unit: millisecond */
NETWORK_INTERFACES :
{
ENB_INTERFACE_NAME_FOR_S1_MME = "eth6";
......
......@@ -141,6 +141,11 @@ eNBs =
}
);
///X2
enable_x2 = "no";
t_reloc_prep = 1000; /* unit: millisecond */
tx2_reloc_overall = 2000; /* unit: millisecond */
NETWORK_INTERFACES :
{
ENB_INTERFACE_NAME_FOR_S1_MME = "eth0";
......
......@@ -141,6 +141,11 @@ eNBs =
}
);
///X2
enable_x2 = "no";
t_reloc_prep = 1000; /* unit: millisecond */
tx2_reloc_overall = 2000; /* unit: millisecond */
NETWORK_INTERFACES :
{
ENB_INTERFACE_NAME_FOR_S1_MME = "eth0";
......
......@@ -141,6 +141,11 @@ eNBs =
}
);
///X2
enable_x2 = "no";
t_reloc_prep = 1000; /* unit: millisecond */
tx2_reloc_overall = 2000; /* unit: millisecond */
NETWORK_INTERFACES :
{
ENB_INTERFACE_NAME_FOR_S1_MME = "eth0";
......
......@@ -141,6 +141,11 @@ eNBs =
}
);
///X2
enable_x2 = "no";
t_reloc_prep = 1000; /* unit: millisecond */
tx2_reloc_overall = 2000; /* unit: millisecond */
NETWORK_INTERFACES :
{
ENB_INTERFACE_NAME_FOR_S1_MME = "eth0";
......
......@@ -141,6 +141,11 @@ eNBs =
}
);
///X2
enable_x2 = "no";
t_reloc_prep = 1000; /* unit: millisecond */
tx2_reloc_overall = 2000; /* unit: millisecond */
NETWORK_INTERFACES :
{
ENB_INTERFACE_NAME_FOR_S1_MME = "eth0";
......
......@@ -141,6 +141,11 @@ eNBs =
}
);
///X2
enable_x2 = "no";
t_reloc_prep = 1000; /* unit: millisecond */
tx2_reloc_overall = 2000; /* unit: millisecond */
NETWORK_INTERFACES :
{
ENB_INTERFACE_NAME_FOR_S1_MME = "eth0";
......
......@@ -143,6 +143,11 @@ eNBs =
}
);
///X2
enable_x2 = "no";
t_reloc_prep = 1000; /* unit: millisecond */
tx2_reloc_overall = 2000; /* unit: millisecond */
NETWORK_INTERFACES :
{
ENB_INTERFACE_NAME_FOR_S1_MME = "eth3";
......
......@@ -143,6 +143,11 @@ eNBs =
}
);
///X2
enable_x2 = "no";
t_reloc_prep = 1000; /* unit: millisecond */
tx2_reloc_overall = 2000; /* unit: millisecond */
NETWORK_INTERFACES :
{
ENB_INTERFACE_NAME_FOR_S1_MME = "eth3";
......
......@@ -143,6 +143,11 @@ eNBs =
}
);
///X2
enable_x2 = "no";
t_reloc_prep = 1000; /* unit: millisecond */
tx2_reloc_overall = 2000; /* unit: millisecond */
NETWORK_INTERFACES :
{
ENB_INTERFACE_NAME_FOR_S1_MME = "eth3";
......
......@@ -181,6 +181,11 @@ eNBs =
}
);
///X2
enable_x2 = "no";
t_reloc_prep = 1000; /* unit: millisecond */
tx2_reloc_overall = 2000; /* unit: millisecond */
NETWORK_INTERFACES :
{
ENB_INTERFACE_NAME_FOR_S1_MME = "eth1";
......
......@@ -127,6 +127,9 @@ The X2AP layer is based on **3GPP 36.423** v14.6.0 and implements the following
- X2 Setup Failure
- Handover Request
- Handover Request Acknowledge
- UE Context Release
- X2 timers (t_reloc_prep, tx2_reloc_overall)
- Handover Cancel
## eNB Advanced Features ##
......
......@@ -32,6 +32,7 @@ MESSAGE_DEF(X2AP_SETUP_REQUEST_LOG , MESSAGE_PRIORITY_MED, IttiMsgT
/* eNB application layer -> X2AP messages */
MESSAGE_DEF(X2AP_REGISTER_ENB_REQ , MESSAGE_PRIORITY_MED, x2ap_register_enb_req_t , x2ap_register_enb_req)
MESSAGE_DEF(X2AP_SUBFRAME_PROCESS , MESSAGE_PRIORITY_MED, x2ap_subframe_process_t , x2ap_subframe_process)
/* X2AP -> eNB application layer messages */
MESSAGE_DEF(X2AP_REGISTER_ENB_CNF , MESSAGE_PRIORITY_MED, x2ap_register_enb_cnf_t , x2ap_register_enb_cnf)
......@@ -40,6 +41,7 @@ MESSAGE_DEF(X2AP_DEREGISTERED_ENB_IND , MESSAGE_PRIORITY_MED, x2ap_der
/* handover messages X2AP <-> RRC */
MESSAGE_DEF(X2AP_HANDOVER_REQ , MESSAGE_PRIORITY_MED, x2ap_handover_req_t , x2ap_handover_req)
MESSAGE_DEF(X2AP_HANDOVER_REQ_ACK , MESSAGE_PRIORITY_MED, x2ap_handover_req_ack_t , x2ap_handover_req_ack)
MESSAGE_DEF(X2AP_HANDOVER_CANCEL , MESSAGE_PRIORITY_MED, x2ap_handover_cancel_t , x2ap_handover_cancel)
/* handover messages X2AP <-> S1AP */
MESSAGE_DEF(X2AP_UE_CONTEXT_RELEASE , MESSAGE_PRIORITY_MED, x2ap_ue_context_release_t , x2ap_ue_context_release)
......@@ -34,6 +34,7 @@
#define X2AP_REGISTER_ENB_CNF(mSGpTR) (mSGpTR)->ittiMsg.x2ap_register_enb_cnf
#define X2AP_DEREGISTERED_ENB_IND(mSGpTR) (mSGpTR)->ittiMsg.x2ap_deregistered_enb_ind
#define X2AP_UE_CONTEXT_RELEASE(mSGpTR) (mSGpTR)->ittiMsg.x2ap_ue_context_release
#define X2AP_HANDOVER_CANCEL(mSGpTR) (mSGpTR)->ittiMsg.x2ap_handover_cancel
#define X2AP_MAX_NB_ENB_IP_ADDRESS 2
......@@ -48,6 +49,16 @@ typedef struct x2ap_ue_context_release_s {
int source_assoc_id;
} x2ap_ue_context_release_t;
typedef enum {
X2AP_T_RELOC_PREP_TIMEOUT,
X2AP_TX2_RELOC_OVERALL_TIMEOUT
} x2ap_handover_cancel_cause_t;
typedef struct x2ap_handover_cancel_s {
int rnti;
x2ap_handover_cancel_cause_t cause;
} x2ap_handover_cancel_t;
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.
......@@ -105,8 +116,16 @@ typedef struct x2ap_register_enb_req_s {
/* eNB port for X2C*/
uint32_t enb_port_for_X2C;
/* timers (unit: millisecond) */
int t_reloc_prep;
int tx2_reloc_overall;
} x2ap_register_enb_req_t;
typedef struct x2ap_subframe_process_s {
/* nothing, we simply use the module ID in the header */
} x2ap_subframe_process_t;
//-------------------------------------------------------------------------------------------//
// X2AP -> eNB application layer messages
typedef struct x2ap_register_enb_cnf_s {
......
......@@ -151,8 +151,8 @@ void *eNB_app_task(void *args_p) {
uint32_t register_enb_pending=0;
uint32_t registered_enb;
long enb_register_retry_timer_id;
uint32_t x2_register_enb_pending;
uint32_t x2_registered_enb;
uint32_t x2_register_enb_pending = 0;
uint32_t x2_registered_enb = 0;
long x2_enb_register_retry_timer_id;
uint32_t enb_id;
MessageDef *msg_p = NULL;
......@@ -188,9 +188,11 @@ void *eNB_app_task(void *args_p) {
register_enb_pending = eNB_app_register (enb_id_start, enb_id_end);//, enb_properties_p);
}
if (is_x2ap_enabled()) {
/* Try to register each eNB with each other */
x2_registered_enb = 0;
x2_register_enb_pending = eNB_app_register_x2 (enb_id_start, enb_id_end);
}
do {
// Wait for a message
......
......@@ -2053,6 +2053,28 @@ int RCconfig_X2(MessageDef *msg_p, uint32_t i) {
}
}
// timers
{
int t_reloc_prep = 0;
int tx2_reloc_overall = 0;
paramdef_t p[] = {
{ "t_reloc_prep", "t_reloc_prep", 0, iptr:&t_reloc_prep, defintval:0, TYPE_INT, 0 },
{ "tx2_reloc_overall", "tx2_reloc_overall", 0, iptr:&tx2_reloc_overall, defintval:0, TYPE_INT, 0 }
};
config_get(p, sizeof(p)/sizeof(paramdef_t), aprefix);
if (t_reloc_prep <= 0 || t_reloc_prep > 10000 ||
tx2_reloc_overall <= 0 || tx2_reloc_overall > 20000) {
LOG_E(X2AP, "timers in configuration file have wrong values. We must have [0 < t_reloc_prep <= 10000] and [0 < tx2_reloc_overall <= 20000]\n");
exit(1);
}
X2AP_REGISTER_ENB_REQ (msg_p).t_reloc_prep = t_reloc_prep;
X2AP_REGISTER_ENB_REQ (msg_p).tx2_reloc_overall = tx2_reloc_overall;
}
// SCTP SETTING
X2AP_REGISTER_ENB_REQ (msg_p).sctp_out_streams = SCTP_OUT_STREAMS;
X2AP_REGISTER_ENB_REQ (msg_p).sctp_in_streams = SCTP_IN_STREAMS;
......
......@@ -344,7 +344,8 @@ typedef enum HO_STATE_e {
HO_REQUEST,
HO_ACK,
HO_CONFIGURED,
HO_RELEASE
HO_RELEASE,
HO_CANCEL
} HO_STATE_t;
typedef enum SL_TRIGGER_e {
......
This diff is collapsed.
......@@ -41,6 +41,7 @@
#include "x2ap_eNB_generate_messages.h"
#include "x2ap_common.h"
#include "x2ap_ids.h"
#include "x2ap_timers.h"
#include "queue.h"
#include "assertions.h"
......@@ -301,6 +302,9 @@ void x2ap_eNB_handle_register_eNB(instance_t instance,
new_instance->num_cc = x2ap_register_eNB->num_cc;
x2ap_id_manager_init(&new_instance->id_manager);
x2ap_timers_init(&new_instance->timers,
x2ap_register_eNB->t_reloc_prep,
x2ap_register_eNB->tx2_reloc_overall);
for (int i = 0; i< x2ap_register_eNB->num_cc; i++) {
new_instance->eutra_band[i] = x2ap_register_eNB->eutra_band[i];
......@@ -402,6 +406,10 @@ void x2ap_eNB_handle_handover_req(instance_t instance,
}
/* id_source is ue_id, id_target is unknown yet */
x2ap_set_ids(id_manager, ue_id, x2ap_handover_req->rnti, ue_id, -1);
x2ap_id_set_state(id_manager, ue_id, X2ID_STATE_SOURCE_PREPARE);
x2ap_set_reloc_prep_timer(id_manager, ue_id,
x2ap_timer_get_tti(&instance_p->timers));
x2ap_id_set_target(id_manager, ue_id, target);
x2ap_eNB_generate_x2_handover_request(instance_p, target, x2ap_handover_req, ue_id);
}
......@@ -480,6 +488,10 @@ void *x2ap_task(void *arg) {
itti_exit_task();
break;
case X2AP_SUBFRAME_PROCESS:
x2ap_check_timers(ITTI_MESSAGE_GET_INSTANCE(received_msg));
break;
case X2AP_REGISTER_ENB_REQ:
x2ap_eNB_handle_register_eNB(ITTI_MESSAGE_GET_INSTANCE(received_msg),
&X2AP_REGISTER_ENB_REQ(received_msg));
......@@ -534,4 +546,38 @@ void *x2ap_task(void *arg) {
return NULL;
}
#include "common/config/config_userapi.h"
int is_x2ap_enabled(void)
{
static volatile int config_loaded = 0;
static volatile int enabled = 0;
static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
if (pthread_mutex_lock(&mutex)) goto mutex_error;
if (config_loaded) {
if (pthread_mutex_unlock(&mutex)) goto mutex_error;
return enabled;
}
char *enable_x2 = NULL;
paramdef_t p[] = {
{ "enable_x2", "yes/no", 0, strptr:&enable_x2, defstrval:"", TYPE_STRING, 0 }
};
/* TODO: do it per module - we check only first eNB */
config_get(p, sizeof(p)/sizeof(paramdef_t), "eNBs.[0]");
if (enable_x2 != NULL && strcmp(enable_x2, "yes") == 0)
enabled = 1;
config_loaded = 1;
if (pthread_mutex_unlock(&mutex)) goto mutex_error;
return enabled;
mutex_error:
LOG_E(X2AP, "mutex error\n");
exit(1);
}
......@@ -46,6 +46,8 @@ int x2ap_eNB_init_sctp (x2ap_eNB_instance_t *instance_p,
void *x2ap_task(void *arg);
int is_x2ap_enabled(void);
#endif /* X2AP_H_ */
/**
......
......@@ -48,11 +48,17 @@ static int x2ap_eNB_decode_initiating_message(X2AP_X2AP_PDU_t *pdu)
//asn_encode_to_new_buffer(NULL, ATS_CANONICAL_XER, &asn_DEF_X2AP_X2AP_PDU, pdu);
X2AP_INFO("x2ap_eNB_decode_initiating_message!\n");
break;
case X2AP_ProcedureCode_id_uEContextRelease:
//asn_encode_to_new_buffer(NULL, ATS_CANONICAL_XER, &asn_DEF_X2AP_X2AP_PDU, pdu);
X2AP_INFO("x2ap_eNB_decode_initiating_message!\n");
break;
case X2AP_ProcedureCode_id_handoverCancel:
//asn_encode_to_new_buffer(NULL, ATS_CANONICAL_XER, &asn_DEF_X2AP_X2AP_PDU, pdu);
X2AP_INFO("x2ap_eNB_decode_initiating_message!\n");
break;
default:
X2AP_ERROR("Unknown procedure ID (%d) for initiating message\n",
(int)pdu->choice.initiatingMessage.procedureCode);
......
......@@ -34,6 +34,7 @@
#include "sctp_eNB_defs.h"
#include "x2ap_ids.h"
#include "x2ap_timers.h"
#ifndef X2AP_ENB_DEFS_H_
#define X2AP_ENB_DEFS_H_
......@@ -63,7 +64,6 @@ typedef enum {
X2AP_ENB_STATE_MAX,
} x2ap_eNB_state_t;
/* Served PLMN identity element */
struct plmn_identity_s {
uint16_t mcc;
......@@ -184,6 +184,7 @@ typedef struct x2ap_eNB_instance_s {
int multi_sd;
x2ap_id_manager id_manager;
x2ap_timers_t timers;
} x2ap_eNB_instance_t;
typedef struct {
......
......@@ -718,3 +718,87 @@ int x2ap_eNB_generate_x2_ue_context_release (x2ap_eNB_instance_t *instance_p, x2
return ret;
}
int x2ap_eNB_generate_x2_handover_cancel (x2ap_eNB_instance_t *instance_p, x2ap_eNB_data_t *x2ap_eNB_data_p,
int x2_ue_id,
x2ap_handover_cancel_cause_t cause)
{
X2AP_X2AP_PDU_t pdu;
X2AP_HandoverCancel_t *out;
X2AP_HandoverCancel_IEs_t *ie;
int ue_id;
int id_source;
int id_target;
uint8_t *buffer;
uint32_t len;
int ret = 0;
DevAssert(instance_p != NULL);
DevAssert(x2ap_eNB_data_p != NULL);
ue_id = x2_ue_id;
id_source = ue_id;
id_target = x2ap_id_get_id_target(&instance_p->id_manager, ue_id);
/* Prepare the X2AP handover cancel message to encode */
memset(&pdu, 0, sizeof(pdu));
pdu.present = X2AP_X2AP_PDU_PR_initiatingMessage;
pdu.choice.initiatingMessage.procedureCode = X2AP_ProcedureCode_id_handoverCancel;
pdu.choice.initiatingMessage.criticality = X2AP_Criticality_ignore;
pdu.choice.initiatingMessage.value.present = X2AP_InitiatingMessage__value_PR_HandoverCancel;
out = &pdu.choice.initiatingMessage.value.choice.HandoverCancel;
/* mandatory */
ie = (X2AP_HandoverCancel_IEs_t *)calloc(1, sizeof(X2AP_HandoverCancel_IEs_t));
ie->id = X2AP_ProtocolIE_ID_id_Old_eNB_UE_X2AP_ID;
ie->criticality = X2AP_Criticality_reject;
ie->value.present = X2AP_HandoverCancel_IEs__value_PR_UE_X2AP_ID;
ie->value.choice.UE_X2AP_ID = id_source;
ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
/* optional */
if (id_target != -1) {
ie = (X2AP_HandoverCancel_IEs_t *)calloc(1, sizeof(X2AP_HandoverCancel_IEs_t));
ie->id = X2AP_ProtocolIE_ID_id_New_eNB_UE_X2AP_ID;
ie->criticality = X2AP_Criticality_ignore;
ie->value.present = X2AP_HandoverCancel_IEs__value_PR_UE_X2AP_ID_1;
ie->value.choice.UE_X2AP_ID_1 = id_target;
ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
}
/* mandatory */
ie = (X2AP_HandoverCancel_IEs_t *)calloc(1, sizeof(X2AP_HandoverCancel_IEs_t));
ie->id = X2AP_ProtocolIE_ID_id_Cause;
ie->criticality = X2AP_Criticality_ignore;
ie->value.present = X2AP_HandoverCancel_IEs__value_PR_Cause;
switch (cause) {
case X2AP_T_RELOC_PREP_TIMEOUT:
ie->value.choice.Cause.present = X2AP_Cause_PR_radioNetwork;
ie->value.choice.Cause.choice.radioNetwork =
X2AP_CauseRadioNetwork_trelocprep_expiry;
break;
case X2AP_TX2_RELOC_OVERALL_TIMEOUT:
ie->value.choice.Cause.present = X2AP_Cause_PR_radioNetwork;
ie->value.choice.Cause.choice.radioNetwork =
X2AP_CauseRadioNetwork_tx2relocoverall_expiry;
break;
default:
/* we can't come here */
X2AP_ERROR("unhandled cancel cause\n");
exit(1);
}
ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
if (x2ap_eNB_encode_pdu(&pdu, &buffer, &len) < 0) {
X2AP_ERROR("Failed to encode X2 Handover Cancel\n");
abort();
return -1;
}
MSC_LOG_TX_MESSAGE (MSC_X2AP_SRC_ENB, MSC_X2AP_TARGET_ENB, NULL, 0, "0 X2HandoverCancel/initiatingMessage assoc_id %u", x2ap_eNB_data_p->assoc_id);
x2ap_eNB_itti_send_sctp_data_req(instance_p->instance, x2ap_eNB_data_p->assoc_id, buffer, len, 1);
return ret;
}
......@@ -55,5 +55,10 @@ int x2ap_eNB_generate_x2_handover_request_ack (x2ap_eNB_instance_t *instance_p,
int x2ap_eNB_generate_x2_ue_context_release (x2ap_eNB_instance_t *instance_p, x2ap_eNB_data_t *x2ap_eNB_data_p,
x2ap_ue_context_release_t *x2ap_ue_context_release);
int x2ap_eNB_generate_x2_handover_cancel (x2ap_eNB_instance_t *instance_p, x2ap_eNB_data_t *x2ap_eNB_data_p,
int x2_ue_id,
x2ap_handover_cancel_cause_t cause);
#endif /* X2AP_ENB_GENERATE_MESSAGES_H_ */
......@@ -78,10 +78,16 @@ int x2ap_eNB_handle_ue_context_release (instance_t instance,
uint32_t stream,
X2AP_X2AP_PDU_t *pdu);
static
int x2ap_eNB_handle_handover_cancel (instance_t instance,
uint32_t assoc_id,
uint32_t stream,
X2AP_X2AP_PDU_t *pdu);
/* Handlers matrix. Only eNB related procedure present here */
x2ap_message_decoded_callback x2ap_messages_callback[][3] = {
{ x2ap_eNB_handle_handover_preparation, x2ap_eNB_handle_handover_response, 0 }, /* handoverPreparation */
{ 0, 0, 0 }, /* handoverCancel */
{ x2ap_eNB_handle_handover_cancel, 0, 0 }, /* handoverCancel */
{ 0, 0, 0 }, /* loadIndication */
{ 0, 0, 0 }, /* errorIndication */
{ 0, 0, 0 }, /* snStatusTransfer */
......@@ -631,6 +637,7 @@ int x2ap_eNB_handle_handover_preparation (instance_t instance,
}
/* rnti is unknown yet, must not be set to -1, 0 is fine */
x2ap_set_ids(&instance_p->id_manager, ue_id, 0, ie->value.choice.UE_X2AP_ID, ue_id);
x2ap_id_set_state(&instance_p->id_manager, ue_id, X2ID_STATE_TARGET);
X2AP_HANDOVER_REQ(msg).x2_id = ue_id;
......@@ -775,15 +782,19 @@ int x2ap_eNB_handle_handover_response (instance_t instance,
ue_id = id_source;
if (id_source != x2ap_id_get_id_source(&instance_p->id_manager, ue_id)) {
X2AP_ERROR("incorrect X2AP IDs for UE (old ID %d new ID %d)\n", id_source, id_target);
exit(1);
if (ue_id != x2ap_find_id_from_id_source(&instance_p->id_manager, id_source)) {
X2AP_WARN("incorrect/unknown X2AP IDs for UE (old ID %d new ID %d), ignoring handover response\n",
id_source, id_target);
return 0;
}
rnti = x2ap_id_get_rnti(&instance_p->id_manager, ue_id);
/* id_target is a new information, store it */
x2ap_set_ids(&instance_p->id_manager, ue_id, rnti, id_source, id_target);
x2ap_id_set_state(&instance_p->id_manager, ue_id, X2ID_STATE_SOURCE_OVERALL);
x2ap_set_reloc_overall_timer(&instance_p->id_manager, ue_id,
x2ap_timer_get_tti(&instance_p->timers));
X2AP_HANDOVER_REQ_ACK(msg).rnti = rnti;
......@@ -859,13 +870,19 @@ int x2ap_eNB_handle_ue_context_release (instance_t instance,
id_target = ie->value.choice.UE_X2AP_ID_1;
ue_id = id_source;
if (ue_id != x2ap_find_id_from_id_source(&instance_p->id_manager, id_source)) {
X2AP_WARN("incorrect/unknown X2AP IDs for UE (old ID %d new ID %d), ignoring UE context release\n",
id_source, id_target);
return 0;
}
if (id_target != x2ap_id_get_id_target(&instance_p->id_manager, ue_id)) {
X2AP_ERROR("UE context release: bad id_target for UE %x (id_source %d) expected %d got %d\n",
X2AP_ERROR("UE context release: bad id_target for UE %x (id_source %d) expected %d got %d, ignoring message\n",
x2ap_id_get_rnti(&instance_p->id_manager, ue_id),
id_source,
x2ap_id_get_id_target(&instance_p->id_manager, ue_id),
id_target);
return 0;
}
X2AP_UE_CONTEXT_RELEASE(msg).rnti = x2ap_id_get_rnti(&instance_p->id_manager, ue_id);
......@@ -876,3 +893,111 @@ int x2ap_eNB_handle_ue_context_release (instance_t instance,
return 0;
}
static
int x2ap_eNB_handle_handover_cancel (instance_t instance,
uint32_t assoc_id,
uint32_t stream,
X2AP_X2AP_PDU_t *pdu)
{
X2AP_HandoverCancel_t *x2HandoverCancel;
X2AP_HandoverCancel_IEs_t *ie;
x2ap_eNB_instance_t *instance_p;
x2ap_eNB_data_t *x2ap_eNB_data;
MessageDef *msg;
int ue_id;
int id_source;
int id_target;
x2ap_handover_cancel_cause_t cause;
DevAssert (pdu != NULL);
x2HandoverCancel = &pdu->choice.initiatingMessage.value.choice.HandoverCancel;
if (stream == 0) {
X2AP_ERROR ("Received new x2 handover cancel on stream == 0\n");
return 0;
}
X2AP_DEBUG ("Received a new X2 handover cancel\n");
x2ap_eNB_data = x2ap_get_eNB(NULL, assoc_id, 0);
DevAssert(x2ap_eNB_data != NULL);
instance_p = x2ap_eNB_get_instance(instance);
DevAssert(instance_p != NULL);
X2AP_FIND_PROTOCOLIE_BY_ID(X2AP_HandoverCancel_IEs_t, ie, x2HandoverCancel,
X2AP_ProtocolIE_ID_id_Old_eNB_UE_X2AP_ID, true);
if (ie == NULL ) {
X2AP_ERROR("%s %d: ie is a NULL pointer \n",__FILE__,__LINE__);
return -1;
}
id_source = ie->value.choice.UE_X2AP_ID;
X2AP_FIND_PROTOCOLIE_BY_ID(X2AP_HandoverCancel_IEs_t, ie, x2HandoverCancel,
X2AP_ProtocolIE_ID_id_New_eNB_UE_X2AP_ID, false);
if (ie == NULL ) {
X2AP_INFO("%s %d: ie is a NULL pointer \n",__FILE__,__LINE__);
id_target = -1;
} else
id_target = ie->value.choice.UE_X2AP_ID_1;
X2AP_FIND_PROTOCOLIE_BY_ID(X2AP_HandoverCancel_IEs_t, ie, x2HandoverCancel,
X2AP_ProtocolIE_ID_id_Cause, true);
if (ie == NULL ) {
X2AP_ERROR("%s %d: ie is a NULL pointer \n",__FILE__,__LINE__);
return -1;
}
if (ie->value.present != X2AP_HandoverCancel_IEs__value_PR_Cause ||
ie->value.choice.Cause.present != X2AP_Cause_PR_radioNetwork ||
!(ie->value.choice.Cause.choice.radioNetwork ==
X2AP_CauseRadioNetwork_trelocprep_expiry ||
ie->value.choice.Cause.choice.radioNetwork ==
X2AP_CauseRadioNetwork_tx2relocoverall_expiry)) {
X2AP_ERROR("%s %d: Cause not supported (only T_reloc_prep and TX2_reloc_overall handled)\n",__FILE__,__LINE__);
return -1;
}
switch (ie->value.choice.Cause.choice.radioNetwork) {
case X2AP_CauseRadioNetwork_trelocprep_expiry:
cause = X2AP_T_RELOC_PREP_TIMEOUT;
break;
case X2AP_CauseRadioNetwork_tx2relocoverall_expiry:
cause = X2AP_TX2_RELOC_OVERALL_TIMEOUT;
break;
default: /* can't come here */ exit(1);
}
ue_id = x2ap_find_id_from_id_source(&instance_p->id_manager, id_source);
if (ue_id == -1) {
X2AP_WARN("Handover cancel: UE not found (id_source = %d), ignoring message\n", id_source);
return 0;
}
if (id_target != -1 &&
id_target != x2ap_id_get_id_target(&instance_p->id_manager, ue_id)) {
X2AP_ERROR("Handover cancel: bad id_target for UE %x (id_source %d) expected %d got %d\n",
x2ap_id_get_rnti(&instance_p->id_manager, ue_id),
id_source,
x2ap_id_get_id_target(&instance_p->id_manager, ue_id),
id_target);
exit(1);
}
msg = itti_alloc_new_message(TASK_X2AP, X2AP_HANDOVER_CANCEL);
X2AP_HANDOVER_CANCEL(msg).rnti = x2ap_id_get_rnti(&instance_p->id_manager, ue_id);
X2AP_HANDOVER_CANCEL(msg).cause = cause;
itti_send_msg_to_task(TASK_RRC_ENB, instance_p->instance, msg);
x2ap_release_id(&instance_p->id_manager, ue_id);
return 0;
}
......@@ -60,6 +60,16 @@ int x2ap_find_id(x2ap_id_manager *m, int id_source, int id_target)
return -1;
}
int x2ap_find_id_from_id_source(x2ap_id_manager *m, int id_source)
{
int i;
for (i = 0; i < X2AP_MAX_IDS; i++)
if (m->ids[i].rnti != -1 &&
m->ids[i].id_source == id_source)
return i;
return -1;
}
int x2ap_find_id_from_rnti(x2ap_id_manager *m, int rnti)
{
int i;
......@@ -76,6 +86,27 @@ void x2ap_set_ids(x2ap_id_manager *m, int ue_id, int rnti, int id_source, int id
m->ids[ue_id].id_target = id_target;
}
/* real type of target is x2ap_eNB_data_t * */
void x2ap_id_set_target(x2ap_id_manager *m, int ue_id, void *target)
{
m->ids[ue_id].target = target;
}
void x2ap_id_set_state(x2ap_id_manager *m, int ue_id, x2id_state_t state)
{
m->ids[ue_id].state = state;
}
void x2ap_set_reloc_prep_timer(x2ap_id_manager *m, int ue_id, uint64_t time)
{
m->ids[ue_id].t_reloc_prep_start = time;
}
void x2ap_set_reloc_overall_timer(x2ap_id_manager *m, int ue_id, uint64_t time)
{
m->ids[ue_id].tx2_reloc_overall_start = time;
}
int x2ap_id_get_id_source(x2ap_id_manager *m, int ue_id)
{
return m->ids[ue_id].id_source;
......@@ -90,3 +121,8 @@ int x2ap_id_get_rnti(x2ap_id_manager *m, int ue_id)
{
return m->ids[ue_id].rnti;
}
void *x2ap_id_get_target(x2ap_id_manager *m, int ue_id)
{
return m->ids[ue_id].target;
}
......@@ -22,12 +22,38 @@
#ifndef X2AP_IDS_H_
#define X2AP_IDS_H_
#include <stdint.h>
/* maximum number of simultaneous handovers, do not set too high */
#define X2AP_MAX_IDS 16
/*
* state:
* - when starting handover in source, UE is in state X2ID_STATE_SOURCE_PREPARE
* - after receiving HO_ack in source, UE is in state X2ID_STATE_SOURCE_OVERALL
* - in target, UE is in state X2ID_STATE_TARGET
* The state is used to check timers.
*/
typedef enum {
X2ID_STATE_SOURCE_PREPARE,
X2ID_STATE_SOURCE_OVERALL,
X2ID_STATE_TARGET
} x2id_state_t;
typedef struct {
int rnti; /* -1 when free */
int id_source;
int id_target;
/* the target eNB. Real type is x2ap_eNB_data_t * */
void *target;
/* state: needed to check timers */
x2id_state_t state;
/* timers */
uint64_t t_reloc_prep_start;
uint64_t tx2_reloc_overall_start;
} x2ap_id;
typedef struct {
......@@ -38,10 +64,17 @@ void x2ap_id_manager_init(x2ap_id_manager *m);
int x2ap_allocate_new_id(x2ap_id_manager *m);
void x2ap_release_id(x2ap_id_manager *m, int id);
int x2ap_find_id(x2ap_id_manager *, int id_source, int id_target);
int x2ap_find_id_from_id_source(x2ap_id_manager *, int id_source);
int x2ap_find_id_from_rnti(x2ap_id_manager *, int rnti);
void x2ap_set_ids(x2ap_id_manager *m, int ue_id, int rnti, int id_source, int id_target);
void x2ap_id_set_state(x2ap_id_manager *m, int ue_id, x2id_state_t state);
/* real type of target is x2ap_eNB_data_t * */
void x2ap_id_set_target(x2ap_id_manager *m, int ue_id, void *target);
void x2ap_set_reloc_prep_timer(x2ap_id_manager *m, int ue_id, uint64_t time);
void x2ap_set_reloc_overall_timer(x2ap_id_manager *m, int ue_id, uint64_t time);
int x2ap_id_get_id_source(x2ap_id_manager *m, int ue_id);
int x2ap_id_get_id_target(x2ap_id_manager *m, int ue_id);
int x2ap_id_get_rnti(x2ap_id_manager *m, int ue_id);
void *x2ap_id_get_target(x2ap_id_manager *m, int ue_id);
#endif /* X2AP_IDS_H_ */
/*
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenAirInterface Software Alliance licenses this file to You under
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
* except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.openairinterface.org/?page_id=698
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*-------------------------------------------------------------------------------
* For more information about the OpenAirInterface (OAI) Software Alliance:
* contact@openairinterface.org
*/
#include "x2ap_timers.h"
#include "assertions.h"
#include "PHY/defs_common.h" /* TODO: try to not include this */
#include "x2ap_messages_types.h"
#include "x2ap_eNB_defs.h"
#include "x2ap_ids.h"
#include "x2ap_eNB_management_procedures.h"
#include "x2ap_eNB_generate_messages.h"
void x2ap_timers_init(x2ap_timers_t *t, int t_reloc_prep, int tx2_reloc_overall)
{
t->tti = 0;
t->t_reloc_prep = t_reloc_prep;
t->tx2_reloc_overall = tx2_reloc_overall;
}
void x2ap_check_timers(instance_t instance)
{
x2ap_eNB_instance_t *instance_p;
x2ap_timers_t *t;
x2ap_id_manager *m;
int i;
x2ap_handover_cancel_cause_t cause;
void *target;
MessageDef *msg;
int x2_ongoing;
instance_p = x2ap_eNB_get_instance(instance);
DevAssert(instance_p != NULL);
t = &instance_p->timers;
m = &instance_p->id_manager;
/* increment subframe count */
t->tti++;
x2_ongoing = 0;
for (i = 0; i < X2AP_MAX_IDS; i++) {
if (m->ids[i].rnti == -1) continue;
x2_ongoing++;
if (m->ids[i].state == X2ID_STATE_SOURCE_PREPARE &&
t->tti > m->ids[i].t_reloc_prep_start + t->t_reloc_prep) {
LOG_I(X2AP, "X2 timeout reloc prep\n");
/* t_reloc_prep timed out */
cause = X2AP_T_RELOC_PREP_TIMEOUT;
goto timeout;
}
if (m->ids[i].state == X2ID_STATE_SOURCE_OVERALL &&
t->tti > m->ids[i].tx2_reloc_overall_start + t->tx2_reloc_overall) {
LOG_I(X2AP, "X2 timeout reloc overall\n");
/* tx2_reloc_overall timed out */
cause = X2AP_TX2_RELOC_OVERALL_TIMEOUT;
goto timeout;
}
/* no timeout -> check next UE */
continue;
timeout:
/* inform target about timeout */
target = x2ap_id_get_target(m, i);
x2ap_eNB_generate_x2_handover_cancel(instance_p, target, i, cause);
/* inform RRC of cancellation */
msg = itti_alloc_new_message(TASK_X2AP, X2AP_HANDOVER_CANCEL);
X2AP_HANDOVER_CANCEL(msg).rnti = x2ap_id_get_rnti(m, i);
X2AP_HANDOVER_CANCEL(msg).cause = cause;
itti_send_msg_to_task(TASK_RRC_ENB, instance_p->instance, msg);
/* remove UE from X2AP */
x2ap_release_id(m, i);
}
if (x2_ongoing && t->tti % 1000 == 0)
LOG_I(X2AP, "X2 has %d process ongoing\n", x2_ongoing);
}
uint64_t x2ap_timer_get_tti(x2ap_timers_t *t)
{
return t->tti;
}
/*
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenAirInterface Software Alliance licenses this file to You under
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
* except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.openairinterface.org/?page_id=698
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*-------------------------------------------------------------------------------
* For more information about the OpenAirInterface (OAI) Software Alliance:
* contact@openairinterface.org
*/
#ifndef X2AP_TIMERS_H_
#define X2AP_TIMERS_H_
#include <stdint.h>
#include "platform_types.h"
typedef struct {
/* incremented every TTI (every millisecond when in realtime).
* Used to check timers.
* 64 bits gives us more than 500 million years of (realtime) processing.
* It should be enough.
*/
uint64_t tti;
/* timer values (unit: TTI, ie. millisecond when in realtime) */
int t_reloc_prep;
int tx2_reloc_overall;
} x2ap_timers_t;
void x2ap_timers_init(x2ap_timers_t *t, int t_reloc_prep, int tx2_reloc_overall);
void x2ap_check_timers(instance_t instance);
uint64_t x2ap_timer_get_tti(x2ap_timers_t *t);
#endif /* X2AP_TIMERS_H_ */
......@@ -53,10 +53,13 @@ int create_tasks(uint32_t enb_nb) {
if (EPC_MODE_ENABLED) {
if (enb_nb > 0) {
if (is_x2ap_enabled()) {
if (itti_create_task (TASK_X2AP, x2ap_task, NULL) < 0) {
LOG_E(X2AP, "Create task for X2AP failed\n");
return -1;
}
} else
LOG_I(X2AP, "X2AP is disabled.\n");
if (itti_create_task (TASK_SCTP, sctp_eNB_task, NULL) < 0) {
LOG_E(SCTP, "Create task for SCTP failed\n");
......
......@@ -37,6 +37,11 @@ eNBs =
}
);
///X2
enable_x2 = "no";
t_reloc_prep = 1000; /* unit: millisecond */
tx2_reloc_overall = 2000; /* unit: millisecond */
NETWORK_INTERFACES :
{
ENB_INTERFACE_NAME_FOR_S1_MME = "eth0";
......
......@@ -49,6 +49,11 @@ eNBs =
}
);
///X2
enable_x2 = "no";
t_reloc_prep = 1000; /* unit: millisecond */
tx2_reloc_overall = 2000; /* unit: millisecond */
NETWORK_INTERFACES :
{
ENB_INTERFACE_NAME_FOR_S1_MME = "eth0";
......
......@@ -36,6 +36,11 @@ eNBs =
}
);
///X2
enable_x2 = "no";
t_reloc_prep = 1000; /* unit: millisecond */
tx2_reloc_overall = 2000; /* unit: millisecond */
NETWORK_INTERFACES :
{
ENB_INTERFACE_NAME_FOR_S1_MME = "eth1";
......
......@@ -360,6 +360,11 @@ eNBs =
}
);
///X2
enable_x2 = "no";
t_reloc_prep = 1000; /* unit: millisecond */
tx2_reloc_overall = 2000; /* unit: millisecond */
NETWORK_INTERFACES :
{
......
......@@ -142,6 +142,11 @@ eNBs =
}
);
///X2
enable_x2 = "no";
t_reloc_prep = 1000; /* unit: millisecond */
tx2_reloc_overall = 2000; /* unit: millisecond */
NETWORK_INTERFACES :
{
ENB_INTERFACE_NAME_FOR_S1_MME = "eth0";
......
......@@ -178,6 +178,11 @@ eNBs =
}
);
///X2
enable_x2 = "no";
t_reloc_prep = 1000; /* unit: millisecond */
tx2_reloc_overall = 2000; /* unit: millisecond */
NETWORK_INTERFACES :
{
ENB_INTERFACE_NAME_FOR_S1_MME = "eno1";
......
......@@ -142,6 +142,11 @@ eNBs =
}
);
///X2
enable_x2 = "no";
t_reloc_prep = 1000; /* unit: millisecond */
tx2_reloc_overall = 2000; /* unit: millisecond */
NETWORK_INTERFACES :
{
ENB_INTERFACE_NAME_FOR_S1_MME = "eth0";
......
......@@ -178,6 +178,11 @@ eNBs =
}
);
///X2
enable_x2 = "no";
t_reloc_prep = 1000; /* unit: millisecond */
tx2_reloc_overall = 2000; /* unit: millisecond */
NETWORK_INTERFACES :
{
ENB_INTERFACE_NAME_FOR_S1_MME = "eno1";
......
......@@ -145,6 +145,11 @@ eNBs =
}
);
///X2
enable_x2 = "no";
t_reloc_prep = 1000; /* unit: millisecond */
tx2_reloc_overall = 2000; /* unit: millisecond */
NETWORK_INTERFACES :
{
ENB_INTERFACE_NAME_FOR_S1_MME = "eth6";
......
......@@ -178,6 +178,11 @@ eNBs =
}
);
///X2
enable_x2 = "no";
t_reloc_prep = 1000; /* unit: millisecond */
tx2_reloc_overall = 2000; /* unit: millisecond */
NETWORK_INTERFACES :
{
ENB_INTERFACE_NAME_FOR_S1_MME = "lo";
......
......@@ -179,6 +179,11 @@ eNBs =
}
);
///X2
enable_x2 = "no";
t_reloc_prep = 1000; /* unit: millisecond */
tx2_reloc_overall = 2000; /* unit: millisecond */
NETWORK_INTERFACES :
{
ENB_INTERFACE_NAME_FOR_S1_MME = "lo";
......
......@@ -179,6 +179,11 @@ eNBs =
}
);
///X2
enable_x2 = "no";
t_reloc_prep = 1000; /* unit: millisecond */
tx2_reloc_overall = 2000; /* unit: millisecond */
NETWORK_INTERFACES :
{
ENB_INTERFACE_NAME_FOR_S1_MME = "lo";
......
......@@ -179,6 +179,11 @@ eNBs =
}
);
///X2
enable_x2 = "no";
t_reloc_prep = 1000; /* unit: millisecond */
tx2_reloc_overall = 2000; /* unit: millisecond */
NETWORK_INTERFACES :
{
ENB_INTERFACE_NAME_FOR_S1_MME = "eth0";
......
......@@ -146,6 +146,11 @@ eNBs =
}
);
///X2
enable_x2 = "no";
t_reloc_prep = 1000; /* unit: millisecond */
tx2_reloc_overall = 2000; /* unit: millisecond */
NETWORK_INTERFACES :
{
ENB_INTERFACE_NAME_FOR_S1_MME = "eth0";
......
......@@ -148,6 +148,11 @@ eNBs =
}
);
///X2
enable_x2 = "no";
t_reloc_prep = 1000; /* unit: millisecond */
tx2_reloc_overall = 2000; /* unit: millisecond */
NETWORK_INTERFACES :
{
ENB_INTERFACE_NAME_FOR_S1_MME = "lo";
......
......@@ -148,6 +148,11 @@ eNBs =
}
);
///X2
enable_x2 = "no";
t_reloc_prep = 1000; /* unit: millisecond */
tx2_reloc_overall = 2000; /* unit: millisecond */
NETWORK_INTERFACES :
{
ENB_INTERFACE_NAME_FOR_S1_MME = "vboxnet0";
......
......@@ -179,6 +179,11 @@ eNBs =
}
);
///X2
enable_x2 = "no";
t_reloc_prep = 1000; /* unit: millisecond */
tx2_reloc_overall = 2000; /* unit: millisecond */
NETWORK_INTERFACES :
{
#ENB_INTERFACE_NAME_FOR_S1_MME = "lo";
......
......@@ -148,6 +148,11 @@ eNBs =
}
);
///X2
enable_x2 = "no";
t_reloc_prep = 1000; /* unit: millisecond */
tx2_reloc_overall = 2000; /* unit: millisecond */
NETWORK_INTERFACES :
{
ENB_INTERFACE_NAME_FOR_S1_MME = "eth0";
......
......@@ -147,6 +147,11 @@ eNBs =
}
);
///X2
enable_x2 = "no";
t_reloc_prep = 1000; /* unit: millisecond */
tx2_reloc_overall = 2000; /* unit: millisecond */
NETWORK_INTERFACES :
{
ENB_INTERFACE_NAME_FOR_S1_MME = "lo";
......
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