Merge remote-tracking branch 'origin/x2' into develop_integration_2019_w11
This commit is contained in:
@@ -360,6 +360,11 @@ eNBs =
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
///X2
|
||||||
|
enable_x2 = "no";
|
||||||
|
t_reloc_prep = 1000; /* unit: millisecond */
|
||||||
|
tx2_reloc_overall = 2000; /* unit: millisecond */
|
||||||
|
|
||||||
NETWORK_INTERFACES :
|
NETWORK_INTERFACES :
|
||||||
{
|
{
|
||||||
ENB_INTERFACE_NAME_FOR_S1_MME = "eth0";
|
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 :
|
NETWORK_INTERFACES :
|
||||||
{
|
{
|
||||||
ENB_INTERFACE_NAME_FOR_S1_MME = "eth0";
|
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 :
|
NETWORK_INTERFACES :
|
||||||
{
|
{
|
||||||
ENB_INTERFACE_NAME_FOR_S1_MME = "eth0";
|
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 :
|
NETWORK_INTERFACES :
|
||||||
{
|
{
|
||||||
ENB_INTERFACE_NAME_FOR_S1_MME = "eth0";
|
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 :
|
NETWORK_INTERFACES :
|
||||||
{
|
{
|
||||||
ENB_INTERFACE_NAME_FOR_S1_MME = "eth0";
|
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 :
|
NETWORK_INTERFACES :
|
||||||
{
|
{
|
||||||
ENB_INTERFACE_NAME_FOR_S1_MME = "eth0";
|
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 :
|
NETWORK_INTERFACES :
|
||||||
{
|
{
|
||||||
ENB_INTERFACE_NAME_FOR_S1_MME = "eth0";
|
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 :
|
NETWORK_INTERFACES :
|
||||||
{
|
{
|
||||||
ENB_INTERFACE_NAME_FOR_S1_MME = "eth0";
|
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 :
|
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 :
|
NETWORK_INTERFACES :
|
||||||
{
|
{
|
||||||
ENB_INTERFACE_NAME_FOR_S1_MME = "eth0";
|
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 :
|
NETWORK_INTERFACES :
|
||||||
{
|
{
|
||||||
ENB_INTERFACE_NAME_FOR_S1_MME = "eth0";
|
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 :
|
NETWORK_INTERFACES :
|
||||||
{
|
{
|
||||||
ENB_INTERFACE_NAME_FOR_S1_MME = "eth0";
|
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 :
|
NETWORK_INTERFACES :
|
||||||
{
|
{
|
||||||
ENB_INTERFACE_NAME_FOR_S1_MME = "eth0";
|
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 :
|
NETWORK_INTERFACES :
|
||||||
{
|
{
|
||||||
ENB_INTERFACE_NAME_FOR_S1_MME = "eth0";
|
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 :
|
NETWORK_INTERFACES :
|
||||||
{
|
{
|
||||||
ENB_INTERFACE_NAME_FOR_S1_MME = "eth0";
|
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 :
|
NETWORK_INTERFACES :
|
||||||
{
|
{
|
||||||
ENB_INTERFACE_NAME_FOR_S1_MME = "eth0";
|
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 :
|
NETWORK_INTERFACES :
|
||||||
{
|
{
|
||||||
ENB_INTERFACE_NAME_FOR_S1_MME = "ens3";
|
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_management_procedures.c
|
||||||
${X2AP_DIR}/x2ap_eNB_generate_messages.c
|
${X2AP_DIR}/x2ap_eNB_generate_messages.c
|
||||||
${X2AP_DIR}/x2ap_ids.c
|
${X2AP_DIR}/x2ap_ids.c
|
||||||
|
${X2AP_DIR}/x2ap_timers.c
|
||||||
)
|
)
|
||||||
add_dependencies(X2AP_ENB rrc_flag x2_flag)
|
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 :
|
NETWORK_INTERFACES :
|
||||||
{
|
{
|
||||||
ENB_INTERFACE_NAME_FOR_S1_MME = "eth6";
|
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 :
|
NETWORK_INTERFACES :
|
||||||
{
|
{
|
||||||
ENB_INTERFACE_NAME_FOR_S1_MME = "eth6";
|
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 :
|
NETWORK_INTERFACES :
|
||||||
{
|
{
|
||||||
ENB_INTERFACE_NAME_FOR_S1_MME = "eth6";
|
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 :
|
NETWORK_INTERFACES :
|
||||||
{
|
{
|
||||||
ENB_INTERFACE_NAME_FOR_S1_MME = "eth0";
|
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 :
|
NETWORK_INTERFACES :
|
||||||
{
|
{
|
||||||
ENB_INTERFACE_NAME_FOR_S1_MME = "eth0";
|
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 :
|
NETWORK_INTERFACES :
|
||||||
{
|
{
|
||||||
ENB_INTERFACE_NAME_FOR_S1_MME = "eth0";
|
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 :
|
NETWORK_INTERFACES :
|
||||||
{
|
{
|
||||||
ENB_INTERFACE_NAME_FOR_S1_MME = "eth0";
|
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 :
|
NETWORK_INTERFACES :
|
||||||
{
|
{
|
||||||
ENB_INTERFACE_NAME_FOR_S1_MME = "eth0";
|
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 :
|
NETWORK_INTERFACES :
|
||||||
{
|
{
|
||||||
ENB_INTERFACE_NAME_FOR_S1_MME = "eth0";
|
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 :
|
NETWORK_INTERFACES :
|
||||||
{
|
{
|
||||||
ENB_INTERFACE_NAME_FOR_S1_MME = "eth3";
|
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 :
|
NETWORK_INTERFACES :
|
||||||
{
|
{
|
||||||
ENB_INTERFACE_NAME_FOR_S1_MME = "eth3";
|
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 :
|
NETWORK_INTERFACES :
|
||||||
{
|
{
|
||||||
ENB_INTERFACE_NAME_FOR_S1_MME = "eth3";
|
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 :
|
NETWORK_INTERFACES :
|
||||||
{
|
{
|
||||||
ENB_INTERFACE_NAME_FOR_S1_MME = "eth1";
|
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
|
- X2 Setup Failure
|
||||||
- Handover Request
|
- Handover Request
|
||||||
- Handover Request Acknowledge
|
- Handover Request Acknowledge
|
||||||
|
- UE Context Release
|
||||||
|
- X2 timers (t_reloc_prep, tx2_reloc_overall)
|
||||||
|
- Handover Cancel
|
||||||
|
|
||||||
## eNB Advanced Features ##
|
## eNB Advanced Features ##
|
||||||
|
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ MESSAGE_DEF(X2AP_SETUP_REQUEST_LOG , MESSAGE_PRIORITY_MED, IttiMsgT
|
|||||||
|
|
||||||
/* eNB application layer -> X2AP messages */
|
/* 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_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 */
|
/* 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_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 */
|
/* handover messages X2AP <-> RRC */
|
||||||
MESSAGE_DEF(X2AP_HANDOVER_REQ , MESSAGE_PRIORITY_MED, x2ap_handover_req_t , x2ap_handover_req)
|
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_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 */
|
/* handover messages X2AP <-> S1AP */
|
||||||
MESSAGE_DEF(X2AP_UE_CONTEXT_RELEASE , MESSAGE_PRIORITY_MED, x2ap_ue_context_release_t , x2ap_ue_context_release)
|
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_REGISTER_ENB_CNF(mSGpTR) (mSGpTR)->ittiMsg.x2ap_register_enb_cnf
|
||||||
#define X2AP_DEREGISTERED_ENB_IND(mSGpTR) (mSGpTR)->ittiMsg.x2ap_deregistered_enb_ind
|
#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_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
|
#define X2AP_MAX_NB_ENB_IP_ADDRESS 2
|
||||||
@@ -48,6 +49,16 @@ typedef struct x2ap_ue_context_release_s {
|
|||||||
int source_assoc_id;
|
int source_assoc_id;
|
||||||
} x2ap_ue_context_release_t;
|
} 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 {
|
typedef struct x2ap_register_enb_req_s {
|
||||||
/* Unique eNB_id to identify the eNB within EPC.
|
/* Unique eNB_id to identify the eNB within EPC.
|
||||||
* For macro eNB ids this field should be 20 bits long.
|
* 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*/
|
/* eNB port for X2C*/
|
||||||
uint32_t 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;
|
} 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
|
// X2AP -> eNB application layer messages
|
||||||
typedef struct x2ap_register_enb_cnf_s {
|
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 register_enb_pending=0;
|
||||||
uint32_t registered_enb;
|
uint32_t registered_enb;
|
||||||
long enb_register_retry_timer_id;
|
long enb_register_retry_timer_id;
|
||||||
uint32_t x2_register_enb_pending;
|
uint32_t x2_register_enb_pending = 0;
|
||||||
uint32_t x2_registered_enb;
|
uint32_t x2_registered_enb = 0;
|
||||||
long x2_enb_register_retry_timer_id;
|
long x2_enb_register_retry_timer_id;
|
||||||
uint32_t enb_id;
|
uint32_t enb_id;
|
||||||
MessageDef *msg_p = NULL;
|
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);
|
register_enb_pending = eNB_app_register (enb_id_start, enb_id_end);//, enb_properties_p);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Try to register each eNB with each other */
|
if (is_x2ap_enabled()) {
|
||||||
x2_registered_enb = 0;
|
/* Try to register each eNB with each other */
|
||||||
x2_register_enb_pending = eNB_app_register_x2 (enb_id_start, enb_id_end);
|
x2_registered_enb = 0;
|
||||||
|
x2_register_enb_pending = eNB_app_register_x2 (enb_id_start, enb_id_end);
|
||||||
|
}
|
||||||
|
|
||||||
do {
|
do {
|
||||||
// Wait for a message
|
// 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
|
// SCTP SETTING
|
||||||
X2AP_REGISTER_ENB_REQ (msg_p).sctp_out_streams = SCTP_OUT_STREAMS;
|
X2AP_REGISTER_ENB_REQ (msg_p).sctp_out_streams = SCTP_OUT_STREAMS;
|
||||||
X2AP_REGISTER_ENB_REQ (msg_p).sctp_in_streams = SCTP_IN_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_REQUEST,
|
||||||
HO_ACK,
|
HO_ACK,
|
||||||
HO_CONFIGURED,
|
HO_CONFIGURED,
|
||||||
HO_RELEASE
|
HO_RELEASE,
|
||||||
|
HO_CANCEL
|
||||||
} HO_STATE_t;
|
} HO_STATE_t;
|
||||||
|
|
||||||
typedef enum SL_TRIGGER_e {
|
typedef enum SL_TRIGGER_e {
|
||||||
|
|||||||
+134
-838
File diff suppressed because it is too large
Load Diff
@@ -41,6 +41,7 @@
|
|||||||
#include "x2ap_eNB_generate_messages.h"
|
#include "x2ap_eNB_generate_messages.h"
|
||||||
#include "x2ap_common.h"
|
#include "x2ap_common.h"
|
||||||
#include "x2ap_ids.h"
|
#include "x2ap_ids.h"
|
||||||
|
#include "x2ap_timers.h"
|
||||||
|
|
||||||
#include "queue.h"
|
#include "queue.h"
|
||||||
#include "assertions.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;
|
new_instance->num_cc = x2ap_register_eNB->num_cc;
|
||||||
|
|
||||||
x2ap_id_manager_init(&new_instance->id_manager);
|
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++) {
|
for (int i = 0; i< x2ap_register_eNB->num_cc; i++) {
|
||||||
new_instance->eutra_band[i] = x2ap_register_eNB->eutra_band[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 */
|
/* 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_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);
|
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();
|
itti_exit_task();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case X2AP_SUBFRAME_PROCESS:
|
||||||
|
x2ap_check_timers(ITTI_MESSAGE_GET_INSTANCE(received_msg));
|
||||||
|
break;
|
||||||
|
|
||||||
case X2AP_REGISTER_ENB_REQ:
|
case X2AP_REGISTER_ENB_REQ:
|
||||||
x2ap_eNB_handle_register_eNB(ITTI_MESSAGE_GET_INSTANCE(received_msg),
|
x2ap_eNB_handle_register_eNB(ITTI_MESSAGE_GET_INSTANCE(received_msg),
|
||||||
&X2AP_REGISTER_ENB_REQ(received_msg));
|
&X2AP_REGISTER_ENB_REQ(received_msg));
|
||||||
@@ -534,4 +546,38 @@ void *x2ap_task(void *arg) {
|
|||||||
return NULL;
|
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);
|
void *x2ap_task(void *arg);
|
||||||
|
|
||||||
|
int is_x2ap_enabled(void);
|
||||||
|
|
||||||
#endif /* X2AP_H_ */
|
#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);
|
//asn_encode_to_new_buffer(NULL, ATS_CANONICAL_XER, &asn_DEF_X2AP_X2AP_PDU, pdu);
|
||||||
X2AP_INFO("x2ap_eNB_decode_initiating_message!\n");
|
X2AP_INFO("x2ap_eNB_decode_initiating_message!\n");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case X2AP_ProcedureCode_id_uEContextRelease:
|
case X2AP_ProcedureCode_id_uEContextRelease:
|
||||||
//asn_encode_to_new_buffer(NULL, ATS_CANONICAL_XER, &asn_DEF_X2AP_X2AP_PDU, pdu);
|
//asn_encode_to_new_buffer(NULL, ATS_CANONICAL_XER, &asn_DEF_X2AP_X2AP_PDU, pdu);
|
||||||
X2AP_INFO("x2ap_eNB_decode_initiating_message!\n");
|
X2AP_INFO("x2ap_eNB_decode_initiating_message!\n");
|
||||||
break;
|
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:
|
default:
|
||||||
X2AP_ERROR("Unknown procedure ID (%d) for initiating message\n",
|
X2AP_ERROR("Unknown procedure ID (%d) for initiating message\n",
|
||||||
(int)pdu->choice.initiatingMessage.procedureCode);
|
(int)pdu->choice.initiatingMessage.procedureCode);
|
||||||
|
|||||||
@@ -34,6 +34,7 @@
|
|||||||
#include "sctp_eNB_defs.h"
|
#include "sctp_eNB_defs.h"
|
||||||
|
|
||||||
#include "x2ap_ids.h"
|
#include "x2ap_ids.h"
|
||||||
|
#include "x2ap_timers.h"
|
||||||
|
|
||||||
#ifndef X2AP_ENB_DEFS_H_
|
#ifndef X2AP_ENB_DEFS_H_
|
||||||
#define X2AP_ENB_DEFS_H_
|
#define X2AP_ENB_DEFS_H_
|
||||||
@@ -63,7 +64,6 @@ typedef enum {
|
|||||||
X2AP_ENB_STATE_MAX,
|
X2AP_ENB_STATE_MAX,
|
||||||
} x2ap_eNB_state_t;
|
} x2ap_eNB_state_t;
|
||||||
|
|
||||||
|
|
||||||
/* Served PLMN identity element */
|
/* Served PLMN identity element */
|
||||||
struct plmn_identity_s {
|
struct plmn_identity_s {
|
||||||
uint16_t mcc;
|
uint16_t mcc;
|
||||||
@@ -184,6 +184,7 @@ typedef struct x2ap_eNB_instance_s {
|
|||||||
int multi_sd;
|
int multi_sd;
|
||||||
|
|
||||||
x2ap_id_manager id_manager;
|
x2ap_id_manager id_manager;
|
||||||
|
x2ap_timers_t timers;
|
||||||
} x2ap_eNB_instance_t;
|
} x2ap_eNB_instance_t;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
|||||||
@@ -718,3 +718,87 @@ int x2ap_eNB_generate_x2_ue_context_release (x2ap_eNB_instance_t *instance_p, x2
|
|||||||
|
|
||||||
return ret;
|
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,
|
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);
|
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_ */
|
#endif /* X2AP_ENB_GENERATE_MESSAGES_H_ */
|
||||||
|
|
||||||
|
|||||||
@@ -78,10 +78,16 @@ int x2ap_eNB_handle_ue_context_release (instance_t instance,
|
|||||||
uint32_t stream,
|
uint32_t stream,
|
||||||
X2AP_X2AP_PDU_t *pdu);
|
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 */
|
/* Handlers matrix. Only eNB related procedure present here */
|
||||||
x2ap_message_decoded_callback x2ap_messages_callback[][3] = {
|
x2ap_message_decoded_callback x2ap_messages_callback[][3] = {
|
||||||
{ x2ap_eNB_handle_handover_preparation, x2ap_eNB_handle_handover_response, 0 }, /* handoverPreparation */
|
{ 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 }, /* loadIndication */
|
||||||
{ 0, 0, 0 }, /* errorIndication */
|
{ 0, 0, 0 }, /* errorIndication */
|
||||||
{ 0, 0, 0 }, /* snStatusTransfer */
|
{ 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 */
|
/* 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_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;
|
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;
|
ue_id = id_source;
|
||||||
|
|
||||||
if (id_source != x2ap_id_get_id_source(&instance_p->id_manager, ue_id)) {
|
if (ue_id != x2ap_find_id_from_id_source(&instance_p->id_manager, id_source)) {
|
||||||
X2AP_ERROR("incorrect X2AP IDs for UE (old ID %d new ID %d)\n", id_source, id_target);
|
X2AP_WARN("incorrect/unknown X2AP IDs for UE (old ID %d new ID %d), ignoring handover response\n",
|
||||||
exit(1);
|
id_source, id_target);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
rnti = x2ap_id_get_rnti(&instance_p->id_manager, ue_id);
|
rnti = x2ap_id_get_rnti(&instance_p->id_manager, ue_id);
|
||||||
|
|
||||||
/* id_target is a new information, store it */
|
/* id_target is a new information, store it */
|
||||||
x2ap_set_ids(&instance_p->id_manager, ue_id, rnti, id_source, id_target);
|
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;
|
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;
|
id_target = ie->value.choice.UE_X2AP_ID_1;
|
||||||
|
|
||||||
ue_id = id_source;
|
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)) {
|
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),
|
x2ap_id_get_rnti(&instance_p->id_manager, ue_id),
|
||||||
id_source,
|
id_source,
|
||||||
x2ap_id_get_id_target(&instance_p->id_manager, ue_id),
|
x2ap_id_get_id_target(&instance_p->id_manager, ue_id),
|
||||||
id_target);
|
id_target);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
X2AP_UE_CONTEXT_RELEASE(msg).rnti = x2ap_id_get_rnti(&instance_p->id_manager, ue_id);
|
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;
|
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;
|
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 x2ap_find_id_from_rnti(x2ap_id_manager *m, int rnti)
|
||||||
{
|
{
|
||||||
int i;
|
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;
|
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)
|
int x2ap_id_get_id_source(x2ap_id_manager *m, int ue_id)
|
||||||
{
|
{
|
||||||
return m->ids[ue_id].id_source;
|
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;
|
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_
|
#ifndef X2AP_IDS_H_
|
||||||
#define 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
|
#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 {
|
typedef struct {
|
||||||
int rnti; /* -1 when free */
|
int rnti; /* -1 when free */
|
||||||
int id_source;
|
int id_source;
|
||||||
int id_target;
|
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;
|
} x2ap_id;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
@@ -38,10 +64,17 @@ void x2ap_id_manager_init(x2ap_id_manager *m);
|
|||||||
int x2ap_allocate_new_id(x2ap_id_manager *m);
|
int x2ap_allocate_new_id(x2ap_id_manager *m);
|
||||||
void x2ap_release_id(x2ap_id_manager *m, int id);
|
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(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);
|
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_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_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_id_target(x2ap_id_manager *m, int ue_id);
|
||||||
int x2ap_id_get_rnti(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_ */
|
#endif /* X2AP_IDS_H_ */
|
||||||
|
|||||||
@@ -0,0 +1,105 @@
|
|||||||
|
/*
|
||||||
|
* 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;
|
||||||
|
}
|
||||||
@@ -0,0 +1,45 @@
|
|||||||
|
/*
|
||||||
|
* 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 (EPC_MODE_ENABLED) {
|
||||||
if (enb_nb > 0) {
|
if (enb_nb > 0) {
|
||||||
if (itti_create_task (TASK_X2AP, x2ap_task, NULL) < 0) {
|
if (is_x2ap_enabled()) {
|
||||||
LOG_E(X2AP, "Create task for X2AP failed\n");
|
if (itti_create_task (TASK_X2AP, x2ap_task, NULL) < 0) {
|
||||||
return -1;
|
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) {
|
if (itti_create_task (TASK_SCTP, sctp_eNB_task, NULL) < 0) {
|
||||||
LOG_E(SCTP, "Create task for SCTP failed\n");
|
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 :
|
NETWORK_INTERFACES :
|
||||||
{
|
{
|
||||||
ENB_INTERFACE_NAME_FOR_S1_MME = "eth0";
|
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 :
|
NETWORK_INTERFACES :
|
||||||
{
|
{
|
||||||
ENB_INTERFACE_NAME_FOR_S1_MME = "eth0";
|
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 :
|
NETWORK_INTERFACES :
|
||||||
{
|
{
|
||||||
ENB_INTERFACE_NAME_FOR_S1_MME = "eth1";
|
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 :
|
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 :
|
NETWORK_INTERFACES :
|
||||||
{
|
{
|
||||||
ENB_INTERFACE_NAME_FOR_S1_MME = "eth0";
|
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 :
|
NETWORK_INTERFACES :
|
||||||
{
|
{
|
||||||
ENB_INTERFACE_NAME_FOR_S1_MME = "eno1";
|
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 :
|
NETWORK_INTERFACES :
|
||||||
{
|
{
|
||||||
ENB_INTERFACE_NAME_FOR_S1_MME = "eth0";
|
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 :
|
NETWORK_INTERFACES :
|
||||||
{
|
{
|
||||||
ENB_INTERFACE_NAME_FOR_S1_MME = "eno1";
|
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 :
|
NETWORK_INTERFACES :
|
||||||
{
|
{
|
||||||
ENB_INTERFACE_NAME_FOR_S1_MME = "eth6";
|
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 :
|
NETWORK_INTERFACES :
|
||||||
{
|
{
|
||||||
ENB_INTERFACE_NAME_FOR_S1_MME = "lo";
|
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 :
|
NETWORK_INTERFACES :
|
||||||
{
|
{
|
||||||
ENB_INTERFACE_NAME_FOR_S1_MME = "lo";
|
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 :
|
NETWORK_INTERFACES :
|
||||||
{
|
{
|
||||||
ENB_INTERFACE_NAME_FOR_S1_MME = "lo";
|
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 :
|
NETWORK_INTERFACES :
|
||||||
{
|
{
|
||||||
ENB_INTERFACE_NAME_FOR_S1_MME = "eth0";
|
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 :
|
NETWORK_INTERFACES :
|
||||||
{
|
{
|
||||||
ENB_INTERFACE_NAME_FOR_S1_MME = "eth0";
|
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 :
|
NETWORK_INTERFACES :
|
||||||
{
|
{
|
||||||
ENB_INTERFACE_NAME_FOR_S1_MME = "lo";
|
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 :
|
NETWORK_INTERFACES :
|
||||||
{
|
{
|
||||||
ENB_INTERFACE_NAME_FOR_S1_MME = "vboxnet0";
|
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 :
|
NETWORK_INTERFACES :
|
||||||
{
|
{
|
||||||
#ENB_INTERFACE_NAME_FOR_S1_MME = "lo";
|
#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 :
|
NETWORK_INTERFACES :
|
||||||
{
|
{
|
||||||
ENB_INTERFACE_NAME_FOR_S1_MME = "eth0";
|
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 :
|
NETWORK_INTERFACES :
|
||||||
{
|
{
|
||||||
ENB_INTERFACE_NAME_FOR_S1_MME = "lo";
|
ENB_INTERFACE_NAME_FOR_S1_MME = "lo";
|
||||||
|
|||||||
Reference in New Issue
Block a user