Commit 1280c9cc authored by Navid Nikaein's avatar Navid Nikaein

Add path switch messahe generation and processing for eNB

parent a8e6930e
...@@ -415,7 +415,7 @@ add_library(S1AP_ENB ...@@ -415,7 +415,7 @@ add_library(S1AP_ENB
######################################## ########################################
# X2AP LAYER OPTIONS # X2AP LAYER OPTIONS
########################## ##########################
add_boolean_option(ENABLE_USE_X2 True "Enable X2 interface for X2 hanodover") add_boolean_option(ENABLE_USE_X2 True "Enable X2 interface for X2 handover")
if (${ENABLE_USE_X2}) if (${ENABLE_USE_X2})
......
...@@ -33,6 +33,8 @@ MESSAGE_DEF(S1AP_UE_CONTEXT_RELEASE_COMPLETE_LOG, MESSAGE_PRIORITY_MED, IttiMsgT ...@@ -33,6 +33,8 @@ MESSAGE_DEF(S1AP_UE_CONTEXT_RELEASE_COMPLETE_LOG, MESSAGE_PRIORITY_MED, IttiMsgT
MESSAGE_DEF(S1AP_UE_CONTEXT_RELEASE_LOG , MESSAGE_PRIORITY_MED, IttiMsgText , s1ap_ue_context_release_log) MESSAGE_DEF(S1AP_UE_CONTEXT_RELEASE_LOG , MESSAGE_PRIORITY_MED, IttiMsgText , s1ap_ue_context_release_log)
MESSAGE_DEF(S1AP_E_RAB_SETUP_REQUEST_LOG , MESSAGE_PRIORITY_MED, IttiMsgText , s1ap_e_rab_setup_request_log) MESSAGE_DEF(S1AP_E_RAB_SETUP_REQUEST_LOG , MESSAGE_PRIORITY_MED, IttiMsgText , s1ap_e_rab_setup_request_log)
MESSAGE_DEF(S1AP_E_RAB_SETUP_RESPONSE_LOG , MESSAGE_PRIORITY_MED, IttiMsgText , s1ap_e_rab_setup_response_log) MESSAGE_DEF(S1AP_E_RAB_SETUP_RESPONSE_LOG , MESSAGE_PRIORITY_MED, IttiMsgText , s1ap_e_rab_setup_response_log)
MESSAGE_DEF(S1AP_PATH_SWITCH_REQ_LOG , MESSAGE_PRIORITY_MED, IttiMsgText , s1ap_path_switch_req_log)
MESSAGE_DEF(S1AP_PATH_SWITCH_REQ_ACK_LOG , MESSAGE_PRIORITY_MED, IttiMsgText , s1ap_path_switch_req_ack_log)
/* eNB application layer -> S1AP messages */ /* eNB application layer -> S1AP messages */
MESSAGE_DEF(S1AP_REGISTER_ENB_REQ , MESSAGE_PRIORITY_MED, s1ap_register_enb_req_t , s1ap_register_enb_req) MESSAGE_DEF(S1AP_REGISTER_ENB_REQ , MESSAGE_PRIORITY_MED, s1ap_register_enb_req_t , s1ap_register_enb_req)
...@@ -54,6 +56,8 @@ MESSAGE_DEF(S1AP_UE_CTXT_MODIFICATION_RESP , MESSAGE_PRIORITY_MED, s1ap_ue_ctxt_ ...@@ -54,6 +56,8 @@ MESSAGE_DEF(S1AP_UE_CTXT_MODIFICATION_RESP , MESSAGE_PRIORITY_MED, s1ap_ue_ctxt_
MESSAGE_DEF(S1AP_UE_CTXT_MODIFICATION_FAIL , MESSAGE_PRIORITY_MED, s1ap_ue_ctxt_modification_fail_t , s1ap_ue_ctxt_modification_fail) MESSAGE_DEF(S1AP_UE_CTXT_MODIFICATION_FAIL , MESSAGE_PRIORITY_MED, s1ap_ue_ctxt_modification_fail_t , s1ap_ue_ctxt_modification_fail)
MESSAGE_DEF(S1AP_E_RAB_SETUP_RESP , MESSAGE_PRIORITY_MED, s1ap_e_rab_setup_resp_t , s1ap_e_rab_setup_resp) MESSAGE_DEF(S1AP_E_RAB_SETUP_RESP , MESSAGE_PRIORITY_MED, s1ap_e_rab_setup_resp_t , s1ap_e_rab_setup_resp)
MESSAGE_DEF(S1AP_E_RAB_SETUP_REQUEST_FAIL , MESSAGE_PRIORITY_MED, s1ap_e_rab_setup_req_fail_t , s1ap_e_rab_setup_request_fail) MESSAGE_DEF(S1AP_E_RAB_SETUP_REQUEST_FAIL , MESSAGE_PRIORITY_MED, s1ap_e_rab_setup_req_fail_t , s1ap_e_rab_setup_request_fail)
MESSAGE_DEF(S1AP_PATH_SWITCH_REQ , MESSAGE_PRIORITY_MED, s1ap_path_switch_req_t , s1ap_path_switch_req)
MESSAGE_DEF(S1AP_PATH_SWITCH_REQ_ACK , MESSAGE_PRIORITY_MED, s1ap_path_switch_req_ack_t , s1ap_path_switch_req_ack)
/* S1AP -> RRC messages */ /* S1AP -> RRC messages */
MESSAGE_DEF(S1AP_DOWNLINK_NAS , MESSAGE_PRIORITY_MED, s1ap_downlink_nas_t , s1ap_downlink_nas ) MESSAGE_DEF(S1AP_DOWNLINK_NAS , MESSAGE_PRIORITY_MED, s1ap_downlink_nas_t , s1ap_downlink_nas )
......
...@@ -41,6 +41,8 @@ ...@@ -41,6 +41,8 @@
#define S1AP_UE_CTXT_MODIFICATION_FAIL(mSGpTR) (mSGpTR)->ittiMsg.s1ap_ue_ctxt_modification_fail #define S1AP_UE_CTXT_MODIFICATION_FAIL(mSGpTR) (mSGpTR)->ittiMsg.s1ap_ue_ctxt_modification_fail
#define S1AP_E_RAB_SETUP_RESP(mSGpTR) (mSGpTR)->ittiMsg.s1ap_e_rab_setup_resp #define S1AP_E_RAB_SETUP_RESP(mSGpTR) (mSGpTR)->ittiMsg.s1ap_e_rab_setup_resp
#define S1AP_E_RAB_SETUP_FAIL(mSGpTR) (mSGpTR)->ittiMsg.s1ap_e_rab_setup_req_fail #define S1AP_E_RAB_SETUP_FAIL(mSGpTR) (mSGpTR)->ittiMsg.s1ap_e_rab_setup_req_fail
#define S1AP_PATH_SWITCH_REQ(mSGpTR) (mSGpTR)->ittiMsg.s1ap_path_switch_req
#define S1AP_PATH_SWITCH_REQ_ACK(mSGpTR) (mSGpTR)->ittiMsg.s1ap_path_switch_req_ack
#define S1AP_DOWNLINK_NAS(mSGpTR) (mSGpTR)->ittiMsg.s1ap_downlink_nas #define S1AP_DOWNLINK_NAS(mSGpTR) (mSGpTR)->ittiMsg.s1ap_downlink_nas
#define S1AP_INITIAL_CONTEXT_SETUP_REQ(mSGpTR) (mSGpTR)->ittiMsg.s1ap_initial_context_setup_req #define S1AP_INITIAL_CONTEXT_SETUP_REQ(mSGpTR) (mSGpTR)->ittiMsg.s1ap_initial_context_setup_req
...@@ -261,6 +263,17 @@ typedef struct e_rab_setup_s { ...@@ -261,6 +263,17 @@ typedef struct e_rab_setup_s {
uint32_t gtp_teid; uint32_t gtp_teid;
} e_rab_setup_t; } e_rab_setup_t;
typedef struct e_rab_tobeswitched_s {
/* Unique e_rab_id for the UE. */
uint8_t e_rab_id;
/* The transport layer address for the IP packets */
transport_layer_addr_t sgw_addr;
/* S-GW Tunnel endpoint identifier */
uint32_t gtp_teid;
} e_rab_tobeswitched_t;
typedef struct e_rab_failed_s { typedef struct e_rab_failed_s {
/* Unique e_rab_id for the UE. */ /* Unique e_rab_id for the UE. */
uint8_t e_rab_id; uint8_t e_rab_id;
...@@ -511,6 +524,54 @@ typedef struct s1ap_e_rab_setup_resp_s { ...@@ -511,6 +524,54 @@ typedef struct s1ap_e_rab_setup_resp_s {
e_rab_failed_t e_rabs_failed[S1AP_MAX_E_RAB]; e_rab_failed_t e_rabs_failed[S1AP_MAX_E_RAB];
} s1ap_e_rab_setup_resp_t; } s1ap_e_rab_setup_resp_t;
typedef struct s1ap_path_switch_req_s {
unsigned eNB_ue_s1ap_id:24;
/* Number of e_rab setup-ed in the list */
uint8_t nb_of_e_rabs;
/* list of e_rab setup-ed by RRC layers */
e_rab_setup_t e_rabs_tobeswitched[S1AP_MAX_E_RAB];
/* MME UE id */
uint16_t mme_ue_s1ap_id;
/* Security algorithms */
security_capabilities_t security_capabilities;
} s1ap_path_switch_req_t;
typedef struct s1ap_path_switch_req_ack_s {
/* UE id for initial connection to S1AP */
uint16_t ue_initial_id;
unsigned eNB_ue_s1ap_id:24;
/* MME UE id */
uint16_t mme_ue_s1ap_id;
/* UE aggregate maximum bitrate */
ambr_t ue_ambr;
/* Number of e_rab setup-ed in the list */
uint8_t nb_e_rabs_tobeswitched;
/* list of e_rab to be switched by RRC layers */
e_rab_tobeswitched_t e_rabs_tobeswitched[S1AP_MAX_E_RAB];
/* Number of e_rabs to be released by RRC */
uint8_t nb_e_rabs_tobereleased;
/* list of e_rabs to be released */
e_rab_failed_t e_rabs_tobereleased[S1AP_MAX_E_RAB];
/* Security key */
int next_hop_chain_count;
uint8_t next_security_key[SECURITY_KEY_LENGTH];
} s1ap_path_switch_req_ack_t;
// S1AP --> RRC messages // S1AP --> RRC messages
typedef struct s1ap_ue_release_command_s { typedef struct s1ap_ue_release_command_s {
......
...@@ -48,4 +48,4 @@ MESSAGE_DEF(X2AP_DEREGISTERED_ENB_IND , MESSAGE_PRIORITY_MED, x2ap_deregist ...@@ -48,4 +48,4 @@ MESSAGE_DEF(X2AP_DEREGISTERED_ENB_IND , MESSAGE_PRIORITY_MED, x2ap_deregist
/* 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_RESP , MESSAGE_PRIORITY_MED, x2ap_handover_resp_t , x2ap_handover_resp) MESSAGE_DEF(X2AP_HANDOVER_REQ_ACK , MESSAGE_PRIORITY_MED, x2ap_handover_req_ack_t , x2ap_handover_req_ack)
...@@ -37,7 +37,7 @@ ...@@ -37,7 +37,7 @@
#define X2AP_REGISTER_ENB_REQ(mSGpTR) (mSGpTR)->ittiMsg.x2ap_register_enb_req #define X2AP_REGISTER_ENB_REQ(mSGpTR) (mSGpTR)->ittiMsg.x2ap_register_enb_req
#define X2AP_HANDOVER_REQ(mSGpTR) (mSGpTR)->ittiMsg.x2ap_handover_req #define X2AP_HANDOVER_REQ(mSGpTR) (mSGpTR)->ittiMsg.x2ap_handover_req
#define X2AP_HANDOVER_RESP(mSGpTR) (mSGpTR)->ittiMsg.x2ap_handover_resp #define X2AP_HANDOVER_REQ_ACK(mSGpTR) (mSGpTR)->ittiMsg.x2ap_handover_req_ack
#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
...@@ -120,11 +120,11 @@ typedef struct x2ap_handover_req_s { ...@@ -120,11 +120,11 @@ typedef struct x2ap_handover_req_s {
int target_mod_id; int target_mod_id;
} x2ap_handover_req_t; } x2ap_handover_req_t;
typedef struct x2ap_handover_resp_s { typedef struct x2ap_handover_req_ack_s {
int source_rnti; /* TODO: to be fixed/remove */ int source_rnti; /* TODO: to be fixed/remove */
int source_x2id; /* TODO: to be fixed/remove */ int source_x2id; /* TODO: to be fixed/remove */
/* TODO: this parameter has to be removed */ /* TODO: this parameter has to be removed */
int target_mod_id; int target_mod_id;
} x2ap_handover_resp_t; } x2ap_handover_req_ack_t;
#endif /* X2AP_MESSAGES_TYPES_H_ */ #endif /* X2AP_MESSAGES_TYPES_H_ */
...@@ -279,7 +279,9 @@ typedef enum e_rab_satus_e { ...@@ -279,7 +279,9 @@ typedef enum e_rab_satus_e {
E_RAB_STATUS_NEW, E_RAB_STATUS_NEW,
E_RAB_STATUS_DONE, // from the eNB perspective E_RAB_STATUS_DONE, // from the eNB perspective
E_RAB_STATUS_ESTABLISHED, // get the reconfigurationcomplete form UE E_RAB_STATUS_ESTABLISHED, // get the reconfigurationcomplete form UE
E_RAB_STATUS_REESTABLISHED, // after HO
E_RAB_STATUS_FAILED, E_RAB_STATUS_FAILED,
E_RAB_STATUS_RELEASED
} e_rab_status_t; } e_rab_status_t;
typedef struct e_rab_param_s { typedef struct e_rab_param_s {
...@@ -409,14 +411,23 @@ typedef struct eNB_RRC_UE_s { ...@@ -409,14 +411,23 @@ typedef struct eNB_RRC_UE_s {
uint32_t eNB_ue_s1ap_id :24; uint32_t eNB_ue_s1ap_id :24;
security_capabilities_t security_capabilities; security_capabilities_t security_capabilities;
int next_hop_chain_count;
uint8_t next_security_key[SECURITY_KEY_LENGTH];
/* Total number of e_rab already setup in the list */ /* Total number of e_rab already setup in the list */
uint8_t setup_e_rabs; uint8_t setup_e_rabs;
/* Number of e_rab to be setup in the list */ /* Number of e_rab to be setup in the list */
uint8_t nb_of_e_rabs; uint8_t nb_of_e_rabs;
/* list of e_rab to be setup by RRC layers */ /* list of e_rab to be setup by RRC layers */
e_rab_param_t e_rab[NB_RB_MAX];//[S1AP_MAX_E_RAB]; e_rab_param_t e_rab[NB_RB_MAX];//[S1AP_MAX_E_RAB];
/* UE aggregate maximum bitrate */
ambr_t ue_ambr;
/* Number of e_rab to be released in the list */
uint8_t nb_e_rabs_tobereleased;
/* list of e_rab to be released by RRC layers */
uint8_t e_rabs_tobereleased[NB_RB_MAX];
// LG: For GTPV1 TUNNELS // LG: For GTPV1 TUNNELS
uint32_t enb_gtp_teid[S1AP_MAX_E_RAB]; uint32_t enb_gtp_teid[S1AP_MAX_E_RAB];
transport_layer_addr_t enb_gtp_addrs[S1AP_MAX_E_RAB]; transport_layer_addr_t enb_gtp_addrs[S1AP_MAX_E_RAB];
......
...@@ -2273,7 +2273,9 @@ rrc_eNB_process_MeasurementReport( ...@@ -2273,7 +2273,9 @@ rrc_eNB_process_MeasurementReport(
LOG_I(RRC, "RSRP of Source %d\n", measResults2->measResultServCell.rsrpResult); LOG_I(RRC, "RSRP of Source %d\n", measResults2->measResultServCell.rsrpResult);
LOG_I(RRC, "RSRQ of Source %d\n", measResults2->measResultServCell.rsrqResult); LOG_I(RRC, "RSRQ of Source %d\n", measResults2->measResultServCell.rsrqResult);
#endif #endif
/* algorithm to decide whether to trigger HO or not */
/* if the UE is not in handover mode, start handover procedure */ /* if the UE is not in handover mode, start handover procedure */
if (ue_context_pP->ue_context.Status != RRC_HO_EXECUTION) { if (ue_context_pP->ue_context.Status != RRC_HO_EXECUTION) {
MessageDef *msg; MessageDef *msg;
...@@ -2361,7 +2363,7 @@ rrc_eNB_generate_HandoverPreparationInformation( ...@@ -2361,7 +2363,7 @@ rrc_eNB_generate_HandoverPreparationInformation(
{ {
struct rrc_eNB_ue_context_s* ue_context_target_p = NULL; struct rrc_eNB_ue_context_s* ue_context_target_p = NULL;
//uint8_t UE_id_target = -1; //uint8_t UE_id_target = -1;
uint8_t mod_id_target = get_adjacent_cell_mod_id(targetPhyId); uint8_t mod_id_target = get_adjacent_cell_mod_id(targetPhyId); /*simulation related var*/
HANDOVER_INFO *handoverInfo = CALLOC(1, sizeof(*handoverInfo)); HANDOVER_INFO *handoverInfo = CALLOC(1, sizeof(*handoverInfo));
/* /*
uint8_t buffer[100]; uint8_t buffer[100];
...@@ -2404,6 +2406,7 @@ rrc_eNB_generate_HandoverPreparationInformation( ...@@ -2404,6 +2406,7 @@ rrc_eNB_generate_HandoverPreparationInformation(
ue_context_pP->ue_context.handover_info->ho_prepare = 0xFF; //0xF0; ue_context_pP->ue_context.handover_info->ho_prepare = 0xFF; //0xF0;
ue_context_pP->ue_context.handover_info->ho_complete = 0; ue_context_pP->ue_context.handover_info->ho_complete = 0;
/* simulation related logic */
if (mod_id_target != 0xFF) { if (mod_id_target != 0xFF) {
//UE_id_target = rrc_find_free_ue_index(modid_target); //UE_id_target = rrc_find_free_ue_index(modid_target);
ue_context_target_p = ue_context_target_p =
...@@ -2646,10 +2649,10 @@ check_handovers( ...@@ -2646,10 +2649,10 @@ check_handovers(
memcpy(UE_rrc_inst[0].sib1[0]->cellAccessRelatedInfo.cellIdentity.buf, memcpy(UE_rrc_inst[0].sib1[0]->cellAccessRelatedInfo.cellIdentity.buf,
eNB_rrc_inst[ctxt_pP->module_id].carrier[0].sib1->cellAccessRelatedInfo.cellIdentity.buf, eNB_rrc_inst[ctxt_pP->module_id].carrier[0].sib1->cellAccessRelatedInfo.cellIdentity.buf,
4); 4);
msg = itti_alloc_new_message(TASK_RRC_ENB, X2AP_HANDOVER_RESP); msg = itti_alloc_new_message(TASK_RRC_ENB, X2AP_HANDOVER_REQ_ACK);
/* TODO: remove this hack */ /* TODO: remove this hack */
X2AP_HANDOVER_RESP(msg).target_mod_id = 1 - ctxt_pP->module_id; X2AP_HANDOVER_REQ_ACK(msg).target_mod_id = 1 - ctxt_pP->module_id;
X2AP_HANDOVER_RESP(msg).source_x2id = ue_context_p->ue_context.handover_info->source_x2id; X2AP_HANDOVER_REQ_ACK(msg).source_x2id = ue_context_p->ue_context.handover_info->source_x2id;
itti_send_msg_to_task(TASK_X2AP, ENB_MODULE_ID_TO_INSTANCE(ctxt_pP->module_id), msg); itti_send_msg_to_task(TASK_X2AP, ENB_MODULE_ID_TO_INSTANCE(ctxt_pP->module_id), msg);
} }
...@@ -5428,15 +5431,19 @@ rrc_enb_task( ...@@ -5428,15 +5431,19 @@ rrc_enb_task(
break; break;
# endif # endif
case S1AP_PATH_SWITCH_REQ_ACK:
LOG_I(RRC, "[eNB %d] received path switch ack %s\n", instance, msg_name_p);
rrc_eNB_process_S1AP_PATH_SWITCH_REQ_ACK(msg_p, msg_name_p, instance);
break;
case X2AP_HANDOVER_REQ: case X2AP_HANDOVER_REQ:
LOG_I(RRC, "[eNB %d] X2-Received %s\n", instance, msg_name_p); LOG_I(RRC, "[eNB %d] X2-Received %s\n", instance, msg_name_p);
rrc_eNB_process_handoverPreparationInformation(instance, &X2AP_HANDOVER_REQ(msg_p)); rrc_eNB_process_handoverPreparationInformation(instance, &X2AP_HANDOVER_REQ(msg_p));
break; break;
case X2AP_HANDOVER_RESP: { case X2AP_HANDOVER_REQ_ACK: {
struct rrc_eNB_ue_context_s *ue_context_p = NULL; struct rrc_eNB_ue_context_s *ue_context_p = NULL;
ue_context_p = rrc_eNB_get_ue_context(&eNB_rrc_inst[instance], X2AP_HANDOVER_RESP(msg_p).source_rnti); ue_context_p = rrc_eNB_get_ue_context(&eNB_rrc_inst[instance], X2AP_HANDOVER_REQ_ACK(msg_p).source_rnti);
LOG_I(RRC, "[eNB %d] X2-Received %s\n", instance, msg_name_p); LOG_I(RRC, "[eNB %d] X2-Received %s\n", instance, msg_name_p);
DevAssert(ue_context_p != NULL); DevAssert(ue_context_p != NULL);
if (ue_context_p->ue_context.handover_info->state != HO_REQUEST) abort(); if (ue_context_p->ue_context.handover_info->state != HO_REQUEST) abort();
......
...@@ -1428,5 +1428,168 @@ int rrc_eNB_send_S1AP_E_RAB_SETUP_RESP(const protocol_ctxt_t* const ctxt_pP, ...@@ -1428,5 +1428,168 @@ int rrc_eNB_send_S1AP_E_RAB_SETUP_RESP(const protocol_ctxt_t* const ctxt_pP,
return 0; return 0;
} }
/*NN: careful about the typcast of xid (long -> uint8_t*/
int rrc_eNB_send_PATH_SWITCH_REQ(const protocol_ctxt_t* const ctxt_pP,
rrc_eNB_ue_context_t* const ue_context_pP){
MessageDef *msg_p = NULL;
int e_rab;
int e_rabs_done = 0;
msg_p = itti_alloc_new_message (TASK_RRC_ENB, S1AP_PATH_SWITCH_REQ);
S1AP_PATH_SWITCH_REQ (msg_p).eNB_ue_s1ap_id = ue_context_pP->ue_context.eNB_ue_s1ap_id;
S1AP_PATH_SWITCH_REQ (msg_p).security_capabilities.encryption_algorithms=ue_context_pP->ue_context.security_capabilities.encryption_algorithms;
S1AP_PATH_SWITCH_REQ (msg_p).security_capabilities.integrity_algorithms=ue_context_pP->ue_context.security_capabilities.integrity_algorithms;
// the context for UE to be handedover is obtained through ho_req message
for (e_rab = 0; e_rab < ue_context_pP->ue_context.setup_e_rabs ; e_rab++) {
if (ue_context_pP->ue_context.e_rab[e_rab].status == E_RAB_STATUS_ESTABLISHED) {
S1AP_PATH_SWITCH_REQ (msg_p).e_rabs_tobeswitched[e_rabs_done].e_rab_id = ue_context_pP->ue_context.e_rab[e_rab].param.e_rab_id;
S1AP_PATH_SWITCH_REQ (msg_p).e_rabs_tobeswitched[e_rabs_done].gtp_teid = ue_context_pP->ue_context.enb_gtp_teid[e_rab];
S1AP_PATH_SWITCH_REQ (msg_p).e_rabs_tobeswitched[e_rabs_done].eNB_addr = ue_context_pP->ue_context.enb_gtp_addrs[e_rab];
LOG_I (RRC,"enb_gtp_addr (msg index %d, e_rab index %d, status %d): nb_of_e_rabs %d, e_rab_id %d, teid: %u, addr: %d.%d.%d.%d \n ",
e_rabs_done, e_rab, ue_context_pP->ue_context.e_rab[e_rab].status,
ue_context_pP->ue_context.nb_of_e_rabs,
S1AP_PATH_SWITCH_REQ (msg_p).e_rabs_tobeswitched[e_rabs_done].e_rab_id,
S1AP_PATH_SWITCH_REQ (msg_p).e_rabs_tobeswitched[e_rabs_done].gtp_teid,
S1AP_PATH_SWITCH_REQ (msg_p).e_rabs_tobeswitched[e_rabs_done].eNB_addr.buffer[0],
S1AP_PATH_SWITCH_REQ (msg_p).e_rabs_tobeswitched[e_rabs_done].eNB_addr.buffer[1],
S1AP_PATH_SWITCH_REQ (msg_p).e_rabs_tobeswitched[e_rabs_done].eNB_addr.buffer[2],
S1AP_PATH_SWITCH_REQ (msg_p).e_rabs_tobeswitched[e_rabs_done].eNB_addr.buffer[3]);
e_rabs_done++;
}
S1AP_PATH_SWITCH_REQ (msg_p).nb_of_e_rabs = e_rabs_done;
// NN: add conditions for e_rabs_failed
if ((e_rabs_done > 0) ){
LOG_I(RRC,"S1AP_PATH_SWITCH_REQ: sending the message: nb_of_erabstobeswitched %d, total e_rabs %d, index %d\n",
ue_context_pP->ue_context.nb_of_e_rabs, ue_context_pP->ue_context.setup_e_rabs, e_rab);
MSC_LOG_TX_MESSAGE(
MSC_RRC_ENB,
MSC_S1AP_ENB,
(const char *)&S1AP_PATH_SWITCH_REQ (msg_p),
sizeof(s1ap_path_switch_req_t),
MSC_AS_TIME_FMT" PATH_SWITCH_REQ UE %X eNB_ue_s1ap_id %u e_rabs:%u succ",
MSC_AS_TIME_ARGS(ctxt_pP),
ue_context_pP->ue_id_rnti,
S1AP_PATH_SWITCH_REQ (msg_p).eNB_ue_s1ap_id,
e_rabs_done);
itti_send_msg_to_task (TASK_S1AP, ctxt_pP->instance, msg_p);
}
}
return 0;
}
int rrc_eNB_process_S1AP_PATH_SWITCH_REQ_ACK (MessageDef *msg_p, const char *msg_name, instance_t instance)
{
uint16_t ue_initial_id;
uint32_t eNB_ue_s1ap_id;
gtpv1u_enb_create_tunnel_req_t create_tunnel_req;
gtpv1u_enb_create_tunnel_resp_t create_tunnel_resp;
gtpv1u_enb_delete_tunnel_req_t delete_tunnel_req;
struct rrc_eNB_ue_context_s* ue_context_p = NULL;
protocol_ctxt_t ctxt;
int i;
ue_initial_id = S1AP_E_RAB_SETUP_REQ (msg_p).ue_initial_id;
//mme_ue_s1ap_id = S1AP_PATH_SWITCH_REQ_ACK (msg_p).mme_ue_s1ap_id;
eNB_ue_s1ap_id = S1AP_PATH_SWITCH_REQ_ACK (msg_p).eNB_ue_s1ap_id;
ue_context_p = rrc_eNB_get_ue_context_from_s1ap_ids(instance, ue_initial_id, eNB_ue_s1ap_id);
LOG_I(RRC, "[eNB %d] Received %s: ue_initial_id %d, eNB_ue_s1ap_id %d, nb_of_e_rabs %d\n",
instance, msg_name, ue_initial_id, eNB_ue_s1ap_id, S1AP_E_RAB_SETUP_REQ (msg_p).nb_e_rabs_tosetup);
if (ue_context_p == NULL) {
/* Can not associate this message to an UE index, send a failure to S1AP and discard it! */
MessageDef *msg_fail_p = NULL;
LOG_W(RRC, "[eNB %d] In S1AP_PATH_SWITCH_REQ_ACK: unknown UE from S1AP ids (%d, %d)\n", instance, ue_initial_id, eNB_ue_s1ap_id);
//msg_fail_p = itti_alloc_new_message (TASK_RRC_ENB, S1AP_PATH_SWITCH_REQ_ACK_FAIL);
//S1AP_PATH_SWITCH_REQ_ACK (msg_fail_p).eNB_ue_s1ap_id = eNB_ue_s1ap_id;
// TODO add failure cause when defined!
//itti_send_msg_to_task (TASK_S1AP, instance, msg_fail_p);
return (-1);
} else {
PROTOCOL_CTXT_SET_BY_INSTANCE(&ctxt, instance, ENB_FLAG_YES, ue_context_p->ue_context.rnti, 0, 0);
ue_context_p->ue_context.eNB_ue_s1ap_id = S1AP_PATH_SWITCH_REQ_ACK (msg_p).eNB_ue_s1ap_id;
/* Save e RAB information for later */
{
for (i = 0;
i < ue_context_p->ue_context.setup_e_rabs; // go over total number of e_rabs received through x2_ho_req msg
i++) {
// assume that we are releasing all the DRBs
ue_context_p->ue_context.e_rab[i].status = E_RAB_STATUS_RELEASED;
}
memset(&create_tunnel_req, 0 , sizeof(create_tunnel_req));
uint8_t nb_e_rabs_tobeswitched = S1AP_PATH_SWITCH_REQ_ACK (msg_p).nb_e_rabs_tobeswitched;
// keep the previous bearer
// the index for the rec
for (i = 0;
i < nb_e_rabs_tobeswitched; // go over total number of e_rabs received through x2_ho_req msg
i++) {
/* Harmonize with enb_gtp_teid, enb_gtp_addrs, and enb_gtp_rbi vars in the top level structure */
ue_context_p->ue_context.e_rab[i].status = E_RAB_STATUS_REESTABLISHED;
ue_context_p->ue_context.e_rab[i].param.e_rab_id = S1AP_PATH_SWITCH_REQ_ACK (msg_p).e_rabs_tobeswitched[i].e_rab_id;
ue_context_p->ue_context.e_rab[i].param.sgw_addr= S1AP_PATH_SWITCH_REQ_ACK (msg_p).e_rabs_tobeswitched[i].sgw_addr;
ue_context_p->ue_context.e_rab[i].param.gtp_teid = S1AP_PATH_SWITCH_REQ_ACK (msg_p).e_rabs_tobeswitched[i].gtp_teid;
/* Tunnel must have been already created in X2_HO_REQ procedure */
}
ue_context_p->ue_context.setup_e_rabs=i;
ue_context_p->ue_context.nb_of_e_rabs=i;
}
ue_context_p->ue_context.ue_ambr=S1AP_PATH_SWITCH_REQ_ACK (msg_p).ue_ambr;
ue_context_p->ue_context.nb_e_rabs_tobereleased = S1AP_PATH_SWITCH_REQ_ACK (msg_p).nb_e_rabs_tobereleased;
memset(&delete_tunnel_req, 0 , sizeof(delete_tunnel_req));
for (i = 0;
i < ue_context_p->ue_context.nb_e_rabs_tobereleased;
i++) {
ue_context_p->ue_context.e_rabs_tobereleased[i]=S1AP_PATH_SWITCH_REQ_ACK (msg_p).e_rabs_tobereleased[i].e_rab_id;
delete_tunnel_req.eps_bearer_id[i] = S1AP_PATH_SWITCH_REQ_ACK (msg_p).e_rabs_tobereleased[i].e_rab_id;
}
if (ue_context_p->ue_context.nb_e_rabs_tobereleased>0){
delete_tunnel_req.rnti= ue_context_p->ue_context.rnti;
delete_tunnel_req.num_erab= ue_context_p->ue_context.nb_e_rabs_tobereleased;
/* this could also be done through ITTI message */
gtpv1u_delete_s1u_tunnel(instance,
&delete_tunnel_req);
/* TBD: release the DRB not admitted */
//rrc_eNB_generate_dedicatedRRCConnectionReconfiguration(&ctxt, ue_context_p, 0);
}
/* Security key */
ue_context_p->ue_context.next_hop_chain_count=S1AP_PATH_SWITCH_REQ_ACK (msg_p).next_hop_chain_count;
memcpy ( ue_context_p->ue_context.next_security_key,
S1AP_PATH_SWITCH_REQ_ACK (msg_p).next_security_key,
SECURITY_KEY_LENGTH);
return (0);
}
}
# endif /* defined(ENABLE_ITTI) */ # endif /* defined(ENABLE_ITTI) */
#endif /* defined(ENABLE_USE_MME) */ #endif /* defined(ENABLE_USE_MME) */
...@@ -213,6 +213,10 @@ int rrc_eNB_process_S1AP_UE_CONTEXT_RELEASE_REQ (MessageDef *msg_p, const char * ...@@ -213,6 +213,10 @@ int rrc_eNB_process_S1AP_UE_CONTEXT_RELEASE_REQ (MessageDef *msg_p, const char *
*/ */
int rrc_eNB_process_S1AP_UE_CONTEXT_RELEASE_COMMAND (MessageDef *msg_p, const char *msg_name, instance_t instance); int rrc_eNB_process_S1AP_UE_CONTEXT_RELEASE_COMMAND (MessageDef *msg_p, const char *msg_name, instance_t instance);
int rrc_eNB_send_PATH_SWITCH_REQ(const protocol_ctxt_t* const ctxt_pP,
rrc_eNB_ue_context_t* const ue_context_pP);
int rrc_eNB_process_S1AP_PATH_SWITCH_REQ_ACK (MessageDef *msg_p, const char *msg_name, instance_t instance);
# endif # endif
# endif /* defined(ENABLE_USE_MME) */ # endif /* defined(ENABLE_USE_MME) */
#endif /* RRC_ENB_S1AP_H_ */ #endif /* RRC_ENB_S1AP_H_ */
...@@ -74,8 +74,8 @@ void x2ap_eNB_handle_handover_req(instance_t instance, ...@@ -74,8 +74,8 @@ void x2ap_eNB_handle_handover_req(instance_t instance,
x2ap_handover_req_t *x2ap_handover_req); x2ap_handover_req_t *x2ap_handover_req);
static static
void x2ap_eNB_handle_handover_resp(instance_t instance, void x2ap_eNB_handle_handover_req_ack(instance_t instance,
x2ap_handover_resp_t *x2ap_handover_resp); x2ap_handover_req_ack_t *x2ap_handover_req_ack);
static static
void x2ap_eNB_register_eNB(x2ap_eNB_instance_t *instance_p, void x2ap_eNB_register_eNB(x2ap_eNB_instance_t *instance_p,
...@@ -421,8 +421,8 @@ void x2ap_eNB_handle_handover_req(instance_t instance, ...@@ -421,8 +421,8 @@ void x2ap_eNB_handle_handover_req(instance_t instance,
} }
static static
void x2ap_eNB_handle_handover_resp(instance_t instance, void x2ap_eNB_handle_handover_req_ack(instance_t instance,
x2ap_handover_resp_t *x2ap_handover_resp) x2ap_handover_req_ack_t *x2ap_handover_req_ack)
{ {
/* TODO: remove this hack (the goal is to find the correct /* TODO: remove this hack (the goal is to find the correct
* eNodeB structure for the other end) - we need a proper way for RRC * eNodeB structure for the other end) - we need a proper way for RRC
...@@ -434,7 +434,7 @@ void x2ap_eNB_handle_handover_resp(instance_t instance, ...@@ -434,7 +434,7 @@ void x2ap_eNB_handle_handover_resp(instance_t instance,
x2ap_eNB_instance_t *instance_p; x2ap_eNB_instance_t *instance_p;
x2ap_eNB_data_t *target; x2ap_eNB_data_t *target;
const Enb_properties_array_t *enb_properties = enb_config_get(); const Enb_properties_array_t *enb_properties = enb_config_get();
int target_enb_id = enb_properties->properties[x2ap_handover_resp->target_mod_id]->eNB_id; int target_enb_id = enb_properties->properties[x2ap_handover_req_ack->target_mod_id]->eNB_id;
instance_p = x2ap_eNB_get_instance(instance); instance_p = x2ap_eNB_get_instance(instance);
DevAssert(instance_p != NULL); DevAssert(instance_p != NULL);
...@@ -442,7 +442,7 @@ void x2ap_eNB_handle_handover_resp(instance_t instance, ...@@ -442,7 +442,7 @@ void x2ap_eNB_handle_handover_resp(instance_t instance,
target = x2ap_is_eNB_id_in_list(target_enb_id); target = x2ap_is_eNB_id_in_list(target_enb_id);
DevAssert(target != NULL); DevAssert(target != NULL);
x2ap_eNB_generate_x2_handover_response(instance_p, target, x2ap_handover_resp->source_x2id); x2ap_eNB_generate_x2_handover_req_ack(instance_p, target, x2ap_handover_req_ack->source_x2id);
} }
void *x2ap_task(void *arg) void *x2ap_task(void *arg)
...@@ -474,9 +474,9 @@ void *x2ap_task(void *arg) ...@@ -474,9 +474,9 @@ void *x2ap_task(void *arg)
&X2AP_HANDOVER_REQ(received_msg)); &X2AP_HANDOVER_REQ(received_msg));
break; break;
case X2AP_HANDOVER_RESP: case X2AP_HANDOVER_REQ_ACK:
x2ap_eNB_handle_handover_resp(ITTI_MESSAGE_GET_INSTANCE(received_msg), x2ap_eNB_handle_handover_req_ack(ITTI_MESSAGE_GET_INSTANCE(received_msg),
&X2AP_HANDOVER_RESP(received_msg)); &X2AP_HANDOVER_REQ_ACK(received_msg));
break; break;
case SCTP_NEW_ASSOCIATION_RESP: case SCTP_NEW_ASSOCIATION_RESP:
......
...@@ -395,9 +395,9 @@ abort(); ...@@ -395,9 +395,9 @@ abort();
return ret; return ret;
} }
int x2ap_eNB_generate_x2_handover_response(x2ap_eNB_instance_t *instance, int x2ap_eNB_generate_x2_handover_req_ack(x2ap_eNB_instance_t *instance,
x2ap_eNB_data_t *x2ap_enb_data_p, x2ap_eNB_data_t *x2ap_enb_data_p,
int source_x2id) int source_x2id)
{ {
x2ap_message message; x2ap_message message;
......
...@@ -47,7 +47,7 @@ int x2ap_eNB_generate_x2_handover_request(x2ap_eNB_instance_t *instance_p, ...@@ -47,7 +47,7 @@ int x2ap_eNB_generate_x2_handover_request(x2ap_eNB_instance_t *instance_p,
x2ap_eNB_data_t *x2ap_enb_data_p, x2ap_eNB_data_t *x2ap_enb_data_p,
int source_x2id); int source_x2id);
int x2ap_eNB_generate_x2_handover_response(x2ap_eNB_instance_t *instance_p, int x2ap_eNB_generate_x2_handover_request_ack(x2ap_eNB_instance_t *instance_p,
x2ap_eNB_data_t *x2ap_enb_data_p, x2ap_eNB_data_t *x2ap_enb_data_p,
int source_x2id); int source_x2id);
......
...@@ -353,11 +353,11 @@ x2ap_eNB_handle_handover_response(uint32_t assoc_id, ...@@ -353,11 +353,11 @@ x2ap_eNB_handle_handover_response(uint32_t assoc_id,
x2ap_eNB_data = x2ap_get_eNB(NULL, assoc_id, 0); x2ap_eNB_data = x2ap_get_eNB(NULL, assoc_id, 0);
DevAssert(x2ap_eNB_data != NULL); DevAssert(x2ap_eNB_data != NULL);
m = itti_alloc_new_message(TASK_X2AP, X2AP_HANDOVER_RESP); m = itti_alloc_new_message(TASK_X2AP, X2AP_HANDOVER_REQ_ACK);
/* TODO: fill the message */ /* TODO: fill the message */
extern int x2id_to_source_rnti[1]; extern int x2id_to_source_rnti[1];
X2AP_HANDOVER_RESP(m).source_x2id = x2HandoverRequestAck->old_eNB_UE_X2AP_ID; X2AP_HANDOVER_REQ_ACK(m).source_x2id = x2HandoverRequestAck->old_eNB_UE_X2AP_ID;
X2AP_HANDOVER_RESP(m).source_rnti = x2id_to_source_rnti[x2HandoverRequestAck->old_eNB_UE_X2AP_ID]; X2AP_HANDOVER_REQ_ACK(m).source_rnti = x2id_to_source_rnti[x2HandoverRequestAck->old_eNB_UE_X2AP_ID];
itti_send_msg_to_task(TASK_RRC_ENB, x2ap_eNB_data->x2ap_eNB_instance->instance, m); itti_send_msg_to_task(TASK_RRC_ENB, x2ap_eNB_data->x2ap_eNB_instance->instance, m);
return 0; return 0;
} }
......
...@@ -141,7 +141,7 @@ gtpv1u_create_s1u_tunnel( ...@@ -141,7 +141,7 @@ gtpv1u_create_s1u_tunnel(
const gtpv1u_enb_create_tunnel_req_t * const create_tunnel_req_pP, const gtpv1u_enb_create_tunnel_req_t * const create_tunnel_req_pP,
gtpv1u_enb_create_tunnel_resp_t * const create_tunnel_resp_pP); gtpv1u_enb_create_tunnel_resp_t * const create_tunnel_resp_pP);
static int int
gtpv1u_delete_s1u_tunnel( gtpv1u_delete_s1u_tunnel(
const instance_t instanceP, const instance_t instanceP,
const gtpv1u_enb_delete_tunnel_req_t * const req_pP); const gtpv1u_enb_delete_tunnel_req_t * const req_pP);
...@@ -809,7 +809,8 @@ gtpv1u_create_s1u_tunnel( ...@@ -809,7 +809,8 @@ gtpv1u_create_s1u_tunnel(
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
static int gtpv1u_delete_s1u_tunnel( int
gtpv1u_delete_s1u_tunnel(
const instance_t instanceP, const instance_t instanceP,
const gtpv1u_enb_delete_tunnel_req_t * const req_pP) const gtpv1u_enb_delete_tunnel_req_t * const req_pP)
{ {
......
...@@ -371,6 +371,12 @@ void *s1ap_eNB_task(void *arg) ...@@ -371,6 +371,12 @@ void *s1ap_eNB_task(void *arg)
} }
break; break;
case S1AP_PATH_SWITCH_REQ: {
s1ap_eNB_path_switch_req(ITTI_MESSAGE_GET_INSTANCE(received_msg),
&S1AP_PATH_SWITCH_REQ(received_msg));
}
break;
case S1AP_UE_CONTEXT_RELEASE_COMPLETE: { case S1AP_UE_CONTEXT_RELEASE_COMPLETE: {
s1ap_ue_context_release_complete(ITTI_MESSAGE_GET_INSTANCE(received_msg), s1ap_ue_context_release_complete(ITTI_MESSAGE_GET_INSTANCE(received_msg),
&S1AP_UE_CONTEXT_RELEASE_COMPLETE(received_msg)); &S1AP_UE_CONTEXT_RELEASE_COMPLETE(received_msg));
......
...@@ -81,13 +81,36 @@ int s1ap_eNB_handle_e_rab_setup_request(uint32_t assoc_id, ...@@ -81,13 +81,36 @@ int s1ap_eNB_handle_e_rab_setup_request(uint32_t assoc_id,
uint32_t stream, uint32_t stream,
struct s1ap_message_s *s1ap_message_p); struct s1ap_message_s *s1ap_message_p);
static
int s1ap_eNB_handle_s1_path_switch_request_ack(uint32_t assoc_id,
uint32_t stream,
struct s1ap_message_s *message_p);
static
int s1ap_eNB_handle_s1_path_switch_request_failure(uint32_t assoc_id,
uint32_t stream,
struct s1ap_message_s *message_p);
static
void process_radio_network_failure(S1ap_CauseRadioNetwork_t cause);
static
void process_transport_failure(S1ap_CauseTransport_t cause);
static
void process_nas_failure(S1ap_CauseNas_t cause);
static
void process_protocol_failure(S1ap_CauseProtocol_t cause);
static
void process_misc_failure(S1ap_CauseMisc_t cause);
/* Handlers matrix. Only eNB related procedure present here */ /* Handlers matrix. Only eNB related procedure present here */
s1ap_message_decoded_callback messages_callback[][3] = { s1ap_message_decoded_callback messages_callback[][3] = {
{ 0, 0, 0 }, /* HandoverPreparation */ { 0, 0, 0 }, /* HandoverPreparation */
{ 0, 0, 0 }, /* HandoverResourceAllocation */ { 0, 0, 0 }, /* HandoverResourceAllocation */
{ 0, 0, 0 }, /* HandoverNotification */ { 0, 0, 0 }, /* HandoverNotification */
{ 0, 0, 0 }, /* PathSwitchRequest */ { 0, s1ap_eNB_handle_s1_path_switch_request_ack, s1ap_eNB_handle_s1_path_switch_request_failure}, /* PathSwitchRequest */
{ 0, 0, 0 }, /* HandoverCancel */ { 0, 0, 0 }, /* HandoverCancel */
{ s1ap_eNB_handle_e_rab_setup_request, 0, 0 }, /* E_RABSetup */ { s1ap_eNB_handle_e_rab_setup_request, 0, 0 }, /* E_RABSetup */
{ 0, 0, 0 }, /* E_RABModify */ { 0, 0, 0 }, /* E_RABModify */
...@@ -460,224 +483,34 @@ int s1ap_eNB_handle_error_indication(uint32_t assoc_id, ...@@ -460,224 +483,34 @@ int s1ap_eNB_handle_error_indication(uint32_t assoc_id,
if ( s1_error_indication_p->presenceMask & S1AP_ERRORINDICATIONIES_CAUSE_PRESENT) { if ( s1_error_indication_p->presenceMask & S1AP_ERRORINDICATIONIES_CAUSE_PRESENT) {
switch(s1_error_indication_p->cause.present) { switch(s1_error_indication_p->cause.present) {
case S1ap_Cause_PR_NOTHING: case S1ap_Cause_PR_NOTHING:
S1AP_WARN("Received S1 Error indication cause NOTHING\n"); S1AP_WARN("Received S1 Error indication cause NOTHING\n");
break; break;
case S1ap_Cause_PR_radioNetwork: case S1ap_Cause_PR_radioNetwork:
switch (s1_error_indication_p->cause.choice.radioNetwork) { process_radio_network_failure(s1_error_indication_p->cause.choice.radioNetwork);
case S1ap_CauseRadioNetwork_unspecified:
S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_unspecified\n");
break;
case S1ap_CauseRadioNetwork_tx2relocoverall_expiry:
S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_tx2relocoverall_expiry\n");
break;
case S1ap_CauseRadioNetwork_successful_handover:
S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_successful_handover\n");
break;
case S1ap_CauseRadioNetwork_release_due_to_eutran_generated_reason:
S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_release_due_to_eutran_generated_reason\n");
break;
case S1ap_CauseRadioNetwork_handover_cancelled:
S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_handover_cancelled\n");
break;
case S1ap_CauseRadioNetwork_partial_handover:
S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_partial_handover\n");
break;
case S1ap_CauseRadioNetwork_ho_failure_in_target_EPC_eNB_or_target_system:
S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_ho_failure_in_target_EPC_eNB_or_target_system\n");
break;
case S1ap_CauseRadioNetwork_ho_target_not_allowed:
S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_ho_target_not_allowed\n");
break;
case S1ap_CauseRadioNetwork_tS1relocoverall_expiry:
S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_tS1relocoverall_expiry\n");
break;
case S1ap_CauseRadioNetwork_tS1relocprep_expiry:
S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_tS1relocprep_expiry\n");
break;
case S1ap_CauseRadioNetwork_cell_not_available:
S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_cell_not_available\n");
break;
case S1ap_CauseRadioNetwork_unknown_targetID:
S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_unknown_targetID\n");
break;
case S1ap_CauseRadioNetwork_no_radio_resources_available_in_target_cell:
S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_no_radio_resources_available_in_target_cell\n");
break;
case S1ap_CauseRadioNetwork_unknown_mme_ue_s1ap_id:
S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_unknown_mme_ue_s1ap_id\n");
break;
case S1ap_CauseRadioNetwork_unknown_enb_ue_s1ap_id:
S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_unknown_enb_ue_s1ap_id\n");
break;
case S1ap_CauseRadioNetwork_unknown_pair_ue_s1ap_id:
S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_unknown_pair_ue_s1ap_id\n");
break;
case S1ap_CauseRadioNetwork_handover_desirable_for_radio_reason:
S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_handover_desirable_for_radio_reason\n");
break;
case S1ap_CauseRadioNetwork_time_critical_handover:
S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_time_critical_handover\n");
break;
case S1ap_CauseRadioNetwork_resource_optimisation_handover:
S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_resource_optimisation_handover\n");
break;
case S1ap_CauseRadioNetwork_reduce_load_in_serving_cell:
S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_reduce_load_in_serving_cell\n");
break;
case S1ap_CauseRadioNetwork_user_inactivity:
S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_user_inactivity\n");
break;
case S1ap_CauseRadioNetwork_radio_connection_with_ue_lost:
S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_radio_connection_with_ue_lost\n");
break;
case S1ap_CauseRadioNetwork_load_balancing_tau_required:
S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_load_balancing_tau_required\n");
break;
case S1ap_CauseRadioNetwork_cs_fallback_triggered:
S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_cs_fallback_triggered\n");
break;
case S1ap_CauseRadioNetwork_ue_not_available_for_ps_service:
S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_ue_not_available_for_ps_service\n");
break;
case S1ap_CauseRadioNetwork_radio_resources_not_available:
S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_radio_resources_not_available\n");
break;
case S1ap_CauseRadioNetwork_failure_in_radio_interface_procedure:
S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_failure_in_radio_interface_procedure\n");
break;
case S1ap_CauseRadioNetwork_invals1ap_id_qos_combination:
S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_invals1ap_id_qos_combination\n");
break;
case S1ap_CauseRadioNetwork_interrat_redirection:
S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_interrat_redirection\n");
break;
case S1ap_CauseRadioNetwork_interaction_with_other_procedure:
S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_interaction_with_other_procedure\n");
break;
case S1ap_CauseRadioNetwork_unknown_E_RAB_ID:
S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_unknown_E_RAB_ID\n");
break;
case S1ap_CauseRadioNetwork_multiple_E_RAB_ID_instances:
S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_multiple_E_RAB_ID_instances\n");
break;
case S1ap_CauseRadioNetwork_encryption_and_or_integrity_protection_algorithms_not_supported:
S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_encryption_and_or_integrity_protection_algorithms_not_supported\n");
break;
case S1ap_CauseRadioNetwork_s1_intra_system_handover_triggered:
S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_s1_intra_system_handover_triggered\n");
break;
case S1ap_CauseRadioNetwork_s1_inter_system_handover_triggered:
S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_s1_inter_system_handover_triggered\n");
break;
case S1ap_CauseRadioNetwork_x2_handover_triggered:
S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_x2_handover_triggered\n");
break;
case S1ap_CauseRadioNetwork_redirection_towards_1xRTT:
S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_redirection_towards_1xRTT\n");
break;
case S1ap_CauseRadioNetwork_not_supported_QCI_value:
S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_not_supported_QCI_value\n");
break;
case S1ap_CauseRadioNetwork_invals1ap_id_CSG_Id:
S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_invals1ap_id_CSG_Id\n");
break;
default:
S1AP_WARN("Received S1 Error indication cause radio network case not handled\n");
}
break; break;
case S1ap_Cause_PR_transport:
case S1ap_Cause_PR_transport: process_transport_failure(s1_error_indication_p->cause.choice.transport);
switch (s1_error_indication_p->cause.choice.transport) {
case S1ap_CauseTransport_transport_resource_unavailable:
S1AP_WARN("Received S1 Error indication S1ap_CauseTransport_transport_resource_unavailable\n");
break;
case S1ap_CauseTransport_unspecified:
S1AP_WARN("Received S1 Error indication S1ap_CauseTransport_unspecified\n");
break;
default:
S1AP_WARN("Received S1 Error indication cause transport case not handled\n");
}
break; break;
case S1ap_Cause_PR_nas: case S1ap_Cause_PR_nas:
switch (s1_error_indication_p->cause.choice.nas) { process_nas_failure(s1_error_indication_p->cause.choice.nas);
case S1ap_CauseNas_normal_release:
S1AP_WARN("Received S1 Error indication S1ap_CauseNas_normal_release\n");
break;
case S1ap_CauseNas_authentication_failure:
S1AP_WARN("Received S1 Error indication S1ap_CauseNas_authentication_failure\n");
break;
case S1ap_CauseNas_detach:
S1AP_WARN("Received S1 Error indication S1ap_CauseNas_detach\n");
break;
case S1ap_CauseNas_unspecified:
S1AP_WARN("Received S1 Error indication S1ap_CauseNas_unspecified\n");
break;
case S1ap_CauseNas_csg_subscription_expiry:
S1AP_WARN("Received S1 Error indication S1ap_CauseNas_csg_subscription_expiry\n");
break;
default:
S1AP_WARN("Received S1 Error indication cause nas case not handled\n");
}
break; break;
case S1ap_Cause_PR_protocol: case S1ap_Cause_PR_protocol:
switch (s1_error_indication_p->cause.choice.protocol) { process_protocol_failure(s1_error_indication_p->cause.choice.protocol);
case S1ap_CauseProtocol_transfer_syntax_error:
S1AP_WARN("Received S1 Error indication S1ap_CauseProtocol_transfer_syntax_error\n");
break;
case S1ap_CauseProtocol_abstract_syntax_error_reject:
S1AP_WARN("Received S1 Error indication S1ap_CauseProtocol_abstract_syntax_error_reject\n");
break;
case S1ap_CauseProtocol_abstract_syntax_error_ignore_and_notify:
S1AP_WARN("Received S1 Error indication S1ap_CauseProtocol_abstract_syntax_error_ignore_and_notify\n");
break;
case S1ap_CauseProtocol_message_not_compatible_with_receiver_state:
S1AP_WARN("Received S1 Error indication S1ap_CauseProtocol_message_not_compatible_with_receiver_state\n");
break;
case S1ap_CauseProtocol_semantic_error:
S1AP_WARN("Received S1 Error indication S1ap_CauseProtocol_semantic_error\n");
break;
case S1ap_CauseProtocol_abstract_syntax_error_falsely_constructed_message:
S1AP_WARN("Received S1 Error indication S1ap_CauseProtocol_abstract_syntax_error_falsely_constructed_message\n");
break;
case S1ap_CauseProtocol_unspecified:
S1AP_WARN("Received S1 Error indication S1ap_CauseProtocol_unspecified\n");
break;
default:
S1AP_WARN("Received S1 Error indication cause protocol case not handled\n");
}
break; break;
case S1ap_Cause_PR_misc: case S1ap_Cause_PR_misc:
switch (s1_error_indication_p->cause.choice.protocol) { process_misc_failure(s1_error_indication_p->cause.choice.protocol);
case S1ap_CauseMisc_control_processing_overload:
S1AP_WARN("Received S1 Error indication S1ap_CauseMisc_control_processing_overload\n");
break;
case S1ap_CauseMisc_not_enough_user_plane_processing_resources:
S1AP_WARN("Received S1 Error indication S1ap_CauseMisc_not_enough_user_plane_processing_resources\n");
break;
case S1ap_CauseMisc_hardware_failure:
S1AP_WARN("Received S1 Error indication S1ap_CauseMisc_hardware_failure\n");
break;
case S1ap_CauseMisc_om_intervention:
S1AP_WARN("Received S1 Error indication S1ap_CauseMisc_om_intervention\n");
break;
case S1ap_CauseMisc_unspecified:
S1AP_WARN("Received S1 Error indication S1ap_CauseMisc_unspecified\n");
break;
case S1ap_CauseMisc_unknown_PLMN:
S1AP_WARN("Received S1 Error indication S1ap_CauseMisc_unknown_PLMN\n");
break;
default:
S1AP_WARN("Received S1 Error indication cause misc case not handled\n");
}
break; break;
default:
S1AP_WARN("Received an unknown S1 Error indication cause\n");
} }
} }
if ( s1_error_indication_p->presenceMask & S1AP_ERRORINDICATIONIES_CRITICALITYDIAGNOSTICS_PRESENT) { if ( s1_error_indication_p->presenceMask & S1AP_ERRORINDICATIONIES_CRITICALITYDIAGNOSTICS_PRESENT) {
// TODO continue S1AP_WARN("Critical Diagnostic not supported\n");
} }
// TODO continue // TODO continue
...@@ -776,7 +609,7 @@ int s1ap_eNB_handle_initial_context_request(uint32_t assoc_id, ...@@ -776,7 +609,7 @@ int s1ap_eNB_handle_initial_context_request(uint32_t assoc_id,
item_p->transportLayerAddress.size * 8 - item_p->transportLayerAddress.bits_unused; item_p->transportLayerAddress.size * 8 - item_p->transportLayerAddress.bits_unused;
/* GTP tunnel endpoint ID */ /* GTP tunnel endpoint ID */
OCTET_STRING_TO_INT32(&item_p->gTP_TEID, S1AP_INITIAL_CONTEXT_SETUP_REQ(message_p).e_rab_param[i].gtp_teid); OCTET_STRING_TO_INT32 (&item_p->gTP_TEID, S1AP_INITIAL_CONTEXT_SETUP_REQ(message_p).e_rab_param[i].gtp_teid);
/* Set the QOS informations */ /* Set the QOS informations */
S1AP_INITIAL_CONTEXT_SETUP_REQ(message_p).e_rab_param[i].qos.qci = item_p->e_RABlevelQoSParameters.qCI; S1AP_INITIAL_CONTEXT_SETUP_REQ(message_p).e_rab_param[i].qos.qci = item_p->e_RABlevelQoSParameters.qCI;
...@@ -935,23 +768,7 @@ int s1ap_eNB_handle_e_rab_setup_request(uint32_t assoc_id, ...@@ -935,23 +768,7 @@ int s1ap_eNB_handle_e_rab_setup_request(uint32_t assoc_id,
item_p = (S1ap_E_RABToBeSetupItemBearerSUReq_t *)s1ap_E_RABSetupRequest->e_RABToBeSetupListBearerSUReq.s1ap_E_RABToBeSetupItemBearerSUReq.array[i]; item_p = (S1ap_E_RABToBeSetupItemBearerSUReq_t *)s1ap_E_RABSetupRequest->e_RABToBeSetupListBearerSUReq.s1ap_E_RABToBeSetupItemBearerSUReq.array[i];
S1AP_E_RAB_SETUP_REQ(message_p).e_rab_setup_params[i].e_rab_id = item_p->e_RAB_ID; S1AP_E_RAB_SETUP_REQ(message_p).e_rab_setup_params[i].e_rab_id = item_p->e_RAB_ID;
// check for the NAS PDU
if (item_p->nAS_PDU.size > 0 ) {
S1AP_E_RAB_SETUP_REQ(message_p).e_rab_setup_params[i].nas_pdu.length = item_p->nAS_PDU.size;
S1AP_E_RAB_SETUP_REQ(message_p).e_rab_setup_params[i].nas_pdu.buffer = malloc(sizeof(uint8_t) * item_p->nAS_PDU.size);
memcpy(S1AP_E_RAB_SETUP_REQ(message_p).e_rab_setup_params[i].nas_pdu.buffer,
item_p->nAS_PDU.buf, item_p->nAS_PDU.size);
// S1AP_INFO("received a NAS PDU with size %d (%02x.%02x)\n",S1AP_E_RAB_SETUP_REQ(message_p).e_rab_setup_params[i].nas_pdu.length, item_p->nAS_PDU.buf[0], item_p->nAS_PDU.buf[1]);
} else {
S1AP_E_RAB_SETUP_REQ(message_p).e_rab_setup_params[i].nas_pdu.length = 0;
S1AP_E_RAB_SETUP_REQ(message_p).e_rab_setup_params[i].nas_pdu.buffer = NULL;
S1AP_WARN("NAS PDU is not provided, generate a E_RAB_SETUP Failure (TBD) back to MME \n");
return -1;
}
/* Set the transport layer address */ /* Set the transport layer address */
memcpy(S1AP_E_RAB_SETUP_REQ(message_p).e_rab_setup_params[i].sgw_addr.buffer, memcpy(S1AP_E_RAB_SETUP_REQ(message_p).e_rab_setup_params[i].sgw_addr.buffer,
...@@ -984,3 +801,404 @@ int s1ap_eNB_handle_e_rab_setup_request(uint32_t assoc_id, ...@@ -984,3 +801,404 @@ int s1ap_eNB_handle_e_rab_setup_request(uint32_t assoc_id,
} }
static
int s1ap_eNB_handle_s1_path_switch_request_ack(uint32_t assoc_id,
uint32_t stream,
struct s1ap_message_s *s1ap_message_p)
{
S1ap_PathSwitchRequestAcknowledgeIEs_t *s1PathSwitchRequestAcknowledge_p;
s1ap_eNB_mme_data_t *mme_desc_p;
s1ap_eNB_ue_context_t *ue_desc_p = NULL;
MessageDef *message_p = NULL;
int i;
DevAssert(s1ap_message_p != NULL);
s1PathSwitchRequestAcknowledge_p = &s1ap_message_p->msg.s1ap_PathSwitchRequestAcknowledgeIEs;
/* S1 Setup Response == Non UE-related procedure -> stream 0 */
if (stream != 0) {
S1AP_ERROR("[SCTP %d] Received s1 path switch request ack on stream != 0 (%d)\n",
assoc_id, stream);
return -1;
}
if ((mme_desc_p = s1ap_eNB_get_MME(NULL, assoc_id, 0)) == NULL) {
S1AP_ERROR("[SCTP %d] Received S1 path switch request ack for non existing "
"MME context\n", assoc_id);
return -1;
}
if ((ue_desc_p = s1ap_eNB_get_ue_context(mme_desc_p->s1ap_eNB_instance,
s1PathSwitchRequestAcknowledge_p->eNB_UE_S1AP_ID)) == NULL) {
S1AP_ERROR("[SCTP %d] Received path switch request ack for non "
"existing UE context 0x%06lx\n", assoc_id,
s1PathSwitchRequestAcknowledge_p->eNB_UE_S1AP_ID);
return -1;
}
if ( ue_desc_p->mme_ue_s1ap_id != s1PathSwitchRequestAcknowledge_p->mme_ue_s1ap_id){
S1AP_WARN("UE context mme_ue_s1ap_id is different form that of the message (%d != %ld)",
ue_desc_p->mme_ue_s1ap_id, s1PathSwitchRequestAcknowledge_p->mme_ue_s1ap_id);
}
// send a message to RRC
message_p = itti_alloc_new_message(TASK_S1AP, S1AP_PATH_SWITCH_REQ_ACK);
S1AP_PATH_SWITCH_REQ_ACK(message_p).ue_initial_id = ue_desc_p->ue_initial_id;
S1AP_PATH_SWITCH_REQ_ACK(message_p).eNB_ue_s1ap_id = s1PathSwitchRequestAcknowledge_p->eNB_UE_S1AP_ID;
S1AP_PATH_SWITCH_REQ_ACK(message_p).mme_ue_s1ap_id = s1PathSwitchRequestAcknowledge_p->mme_ue_s1ap_id;
S1AP_PATH_SWITCH_REQ_ACK(message_p).next_hop_chain_count =
s1PathSwitchRequestAcknowledge_p->securityContext.nextHopChainingCount;
memcpy(&S1AP_PATH_SWITCH_REQ_ACK(message_p).next_security_key,
s1PathSwitchRequestAcknowledge_p->securityContext.nextHopParameter.buf,
s1PathSwitchRequestAcknowledge_p->securityContext.nextHopParameter.size);
// optional
if (s1PathSwitchRequestAcknowledge_p->presenceMask &
S1AP_PATHSWITCHREQUESTACKNOWLEDGEIES_UEAGGREGATEMAXIMUMBITRATE_PRESENT) {
// todo
OCTET_STRING_TO_INT32 (
&s1PathSwitchRequestAcknowledge_p->uEaggregateMaximumBitrate.uEaggregateMaximumBitRateUL,
S1AP_PATH_SWITCH_REQ_ACK(message_p).ue_ambr.br_ul
);
OCTET_STRING_TO_INT32 (
&s1PathSwitchRequestAcknowledge_p->uEaggregateMaximumBitrate.uEaggregateMaximumBitRateDL,
S1AP_PATH_SWITCH_REQ_ACK(message_p).ue_ambr.br_dl
);
//S1AP_PATH_SWITCH_REQ_ACK(message_p).ue_ambr.br_ul = 10000;
//S1AP_PATH_SWITCH_REQ_ACK(message_p).ue_ambr.br_dl = 10000;
} else {
S1AP_PATH_SWITCH_REQ_ACK(message_p).ue_ambr.br_ul = 0;
S1AP_PATH_SWITCH_REQ_ACK(message_p).ue_ambr.br_dl = 0;
}
if (s1PathSwitchRequestAcknowledge_p->presenceMask &
S1AP_PATHSWITCHREQUESTACKNOWLEDGEIES_E_RABTOBESWITCHEDULLIST_PRESENT) {
S1AP_PATH_SWITCH_REQ_ACK(message_p).nb_e_rabs_tobeswitched =
s1PathSwitchRequestAcknowledge_p->e_RABToBeSwitchedULList.s1ap_E_RABToBeSwitchedULItem.count;
for (i = 0; i < s1PathSwitchRequestAcknowledge_p->e_RABToBeSwitchedULList.s1ap_E_RABToBeSwitchedULItem.count; i++) {
S1ap_E_RABToBeSwitchedULItem_t *item_p;
item_p = (S1ap_E_RABToBeSwitchedULItem_t *)s1PathSwitchRequestAcknowledge_p->e_RABToBeSwitchedULList.s1ap_E_RABToBeSwitchedULItem.array[i];
S1AP_PATH_SWITCH_REQ_ACK (message_p).e_rabs_tobeswitched[i].e_rab_id = item_p->e_RAB_ID;
memcpy(S1AP_PATH_SWITCH_REQ_ACK (message_p).e_rabs_tobeswitched[i].sgw_addr.buffer,
item_p->transportLayerAddress.buf, item_p->transportLayerAddress.size);
S1AP_PATH_SWITCH_REQ_ACK (message_p).e_rabs_tobeswitched[i].sgw_addr.length =
item_p->transportLayerAddress.size * 8 - item_p->transportLayerAddress.bits_unused;
OCTET_STRING_TO_INT32(&item_p->gTP_TEID,
S1AP_PATH_SWITCH_REQ_ACK (message_p).e_rabs_tobeswitched[i].gtp_teid);
}
}
if (s1PathSwitchRequestAcknowledge_p->presenceMask &
S1AP_PATHSWITCHREQUESTACKNOWLEDGEIES_E_RABTOBERELEASEDLIST_PRESENT) {
S1AP_PATH_SWITCH_REQ_ACK(message_p).nb_e_rabs_tobereleased =
s1PathSwitchRequestAcknowledge_p->e_RABToBeReleasedList.s1ap_E_RABItem.count;
for (i = 0; i < s1PathSwitchRequestAcknowledge_p->e_RABToBeReleasedList.s1ap_E_RABItem.count; i++) {
S1ap_E_RABItem_t *item_p;
item_p = (S1ap_E_RABItem_t *) s1PathSwitchRequestAcknowledge_p->e_RABToBeReleasedList.s1ap_E_RABItem.array[i];
S1AP_PATH_SWITCH_REQ_ACK (message_p).e_rabs_tobereleased[i].e_rab_id = item_p->e_RAB_ID;
}
}
if (s1PathSwitchRequestAcknowledge_p->presenceMask &
S1AP_PATHSWITCHREQUESTACKNOWLEDGEIES_CRITICALITYDIAGNOSTICS_PRESENT) {
S1AP_WARN("S1AP_PATHSWITCHREQUESTACKNOWLEDGEIES_CRITICALITYDIAGNOSTICS flag not supported\n");
}
if (s1PathSwitchRequestAcknowledge_p->presenceMask &
S1AP_PATHSWITCHREQUESTACKNOWLEDGEIES_MME_UE_S1AP_ID_2_PRESENT) {
S1AP_WARN("S1AP_PATHSWITCHREQUESTACKNOWLEDGEIES_MME_UE_S1AP_ID_2 flag not supported\n");
}
itti_send_msg_to_task(TASK_RRC_ENB, ue_desc_p->eNB_instance->instance, message_p);
return 0;
}
static
int s1ap_eNB_handle_s1_path_switch_request_failure(uint32_t assoc_id,
uint32_t stream,
struct s1ap_message_s *s1ap_message_p)
{
S1ap_PathSwitchRequestFailureIEs_t *s1_PathSwitchRequestFailure_p;
s1ap_eNB_mme_data_t *mme_desc_p;
DevAssert(s1ap_message_p != NULL);
s1_PathSwitchRequestFailure_p = &s1ap_message_p->msg.s1ap_PathSwitchRequestFailureIEs;
/* S1 Setup Failure == Non UE-related procedure -> stream 0 */
if (stream != 0) {
S1AP_WARN("[SCTP %d] Received s1 path switch request failure on stream != 0 (%d)\n",
assoc_id, stream);
}
if ((mme_desc_p = s1ap_eNB_get_MME(NULL, assoc_id, 0)) == NULL) {
S1AP_ERROR("[SCTP %d] Received S1 path switch request for non existing "
"MME context\n", assoc_id);
return -1;
}
switch(s1_PathSwitchRequestFailure_p->cause.present) {
case S1ap_Cause_PR_NOTHING:
S1AP_WARN("Received S1 Error indication cause NOTHING\n");
break;
case S1ap_Cause_PR_radioNetwork:
process_radio_network_failure(s1_PathSwitchRequestFailure_p->cause.choice.radioNetwork);
break;
case S1ap_Cause_PR_transport:
process_transport_failure(s1_PathSwitchRequestFailure_p->cause.choice.transport);
break;
case S1ap_Cause_PR_nas:
process_nas_failure(s1_PathSwitchRequestFailure_p->cause.choice.nas);
break;
case S1ap_Cause_PR_misc:
process_misc_failure(s1_PathSwitchRequestFailure_p->cause.choice.protocol);
break;
default:
S1AP_WARN("Received an unknown S1 Error indication cause \n");
}
if (s1_PathSwitchRequestFailure_p->presenceMask & S1AP_PATHSWITCHREQUESTFAILUREIES_CRITICALITYDIAGNOSTICS_PRESENT) {
S1AP_WARN("Critical Diagnostic not supported\n");
}
// TODO continue
return 0;
}
// for the moment, only print the cause ;)
static
void process_radio_network_failure(S1ap_CauseRadioNetwork_t cause){
switch (cause) {
case S1ap_CauseRadioNetwork_unspecified:
S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_unspecified\n");
break;
case S1ap_CauseRadioNetwork_tx2relocoverall_expiry:
S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_tx2relocoverall_expiry\n");
break;
case S1ap_CauseRadioNetwork_successful_handover:
S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_successful_handover\n");
break;
case S1ap_CauseRadioNetwork_release_due_to_eutran_generated_reason:
S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_release_due_to_eutran_generated_reason\n");
break;
case S1ap_CauseRadioNetwork_handover_cancelled:
S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_handover_cancelled\n");
break;
case S1ap_CauseRadioNetwork_partial_handover:
S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_partial_handover\n");
break;
case S1ap_CauseRadioNetwork_ho_failure_in_target_EPC_eNB_or_target_system:
S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_ho_failure_in_target_EPC_eNB_or_target_system\n");
break;
case S1ap_CauseRadioNetwork_ho_target_not_allowed:
S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_ho_target_not_allowed\n");
break;
case S1ap_CauseRadioNetwork_tS1relocoverall_expiry:
S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_tS1relocoverall_expiry\n");
break;
case S1ap_CauseRadioNetwork_tS1relocprep_expiry:
S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_tS1relocprep_expiry\n");
break;
case S1ap_CauseRadioNetwork_cell_not_available:
S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_cell_not_available\n");
break;
case S1ap_CauseRadioNetwork_unknown_targetID:
S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_unknown_targetID\n");
break;
case S1ap_CauseRadioNetwork_no_radio_resources_available_in_target_cell:
S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_no_radio_resources_available_in_target_cell\n");
break;
case S1ap_CauseRadioNetwork_unknown_mme_ue_s1ap_id:
S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_unknown_mme_ue_s1ap_id\n");
break;
case S1ap_CauseRadioNetwork_unknown_enb_ue_s1ap_id:
S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_unknown_enb_ue_s1ap_id\n");
break;
case S1ap_CauseRadioNetwork_unknown_pair_ue_s1ap_id:
S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_unknown_pair_ue_s1ap_id\n");
break;
case S1ap_CauseRadioNetwork_handover_desirable_for_radio_reason:
S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_handover_desirable_for_radio_reason\n");
break;
case S1ap_CauseRadioNetwork_time_critical_handover:
S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_time_critical_handover\n");
break;
case S1ap_CauseRadioNetwork_resource_optimisation_handover:
S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_resource_optimisation_handover\n");
break;
case S1ap_CauseRadioNetwork_reduce_load_in_serving_cell:
S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_reduce_load_in_serving_cell\n");
break;
case S1ap_CauseRadioNetwork_user_inactivity:
S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_user_inactivity\n");
break;
case S1ap_CauseRadioNetwork_radio_connection_with_ue_lost:
S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_radio_connection_with_ue_lost\n");
break;
case S1ap_CauseRadioNetwork_load_balancing_tau_required:
S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_load_balancing_tau_required\n");
break;
case S1ap_CauseRadioNetwork_cs_fallback_triggered:
S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_cs_fallback_triggered\n");
break;
case S1ap_CauseRadioNetwork_ue_not_available_for_ps_service:
S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_ue_not_available_for_ps_service\n");
break;
case S1ap_CauseRadioNetwork_radio_resources_not_available:
S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_radio_resources_not_available\n");
break;
case S1ap_CauseRadioNetwork_failure_in_radio_interface_procedure:
S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_failure_in_radio_interface_procedure\n");
break;
case S1ap_CauseRadioNetwork_invals1ap_id_qos_combination:
S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_invals1ap_id_qos_combination\n");
break;
case S1ap_CauseRadioNetwork_interrat_redirection:
S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_interrat_redirection\n");
break;
case S1ap_CauseRadioNetwork_interaction_with_other_procedure:
S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_interaction_with_other_procedure\n");
break;
case S1ap_CauseRadioNetwork_unknown_E_RAB_ID:
S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_unknown_E_RAB_ID\n");
break;
case S1ap_CauseRadioNetwork_multiple_E_RAB_ID_instances:
S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_multiple_E_RAB_ID_instances\n");
break;
case S1ap_CauseRadioNetwork_encryption_and_or_integrity_protection_algorithms_not_supported:
S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_encryption_and_or_integrity_protection_algorithms_not_supported\n");
break;
case S1ap_CauseRadioNetwork_s1_intra_system_handover_triggered:
S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_s1_intra_system_handover_triggered\n");
break;
case S1ap_CauseRadioNetwork_s1_inter_system_handover_triggered:
S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_s1_inter_system_handover_triggered\n");
break;
case S1ap_CauseRadioNetwork_x2_handover_triggered:
S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_x2_handover_triggered\n");
break;
case S1ap_CauseRadioNetwork_redirection_towards_1xRTT:
S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_redirection_towards_1xRTT\n");
break;
case S1ap_CauseRadioNetwork_not_supported_QCI_value:
S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_not_supported_QCI_value\n");
break;
case S1ap_CauseRadioNetwork_invals1ap_id_CSG_Id:
S1AP_WARN("Received S1 Error indication S1ap_CauseRadioNetwork_invals1ap_id_CSG_Id\n");
break;
default:
S1AP_WARN("Received S1 Error indication cause radio network case not handled\n");
}
}
static
void process_transport_failure(S1ap_CauseTransport_t cause) {
switch (cause) {
case S1ap_CauseTransport_transport_resource_unavailable:
S1AP_WARN("Received S1 Error indication S1ap_CauseTransport_transport_resource_unavailable\n");
break;
case S1ap_CauseTransport_unspecified:
S1AP_WARN("Received S1 Error indication S1ap_CauseTransport_unspecified\n");
break;
default:
S1AP_WARN("Received S1 Error indication cause transport case not handled\n");
}
}
static
void process_nas_failure(S1ap_CauseNas_t cause) {
switch (cause) {
case S1ap_CauseNas_normal_release:
S1AP_WARN("Received S1 Error indication S1ap_CauseNas_normal_release\n");
break;
case S1ap_CauseNas_authentication_failure:
S1AP_WARN("Received S1 Error indication S1ap_CauseNas_authentication_failure\n");
break;
case S1ap_CauseNas_detach:
S1AP_WARN("Received S1 Error indication S1ap_CauseNas_detach\n");
break;
case S1ap_CauseNas_unspecified:
S1AP_WARN("Received S1 Error indication S1ap_CauseNas_unspecified\n");
break;
case S1ap_CauseNas_csg_subscription_expiry:
S1AP_WARN("Received S1 Error indication S1ap_CauseNas_csg_subscription_expiry\n");
break;
default:
S1AP_WARN("Received S1 Error indication cause nas case not handled\n");
}
}
static
void process_protocol_failure(S1ap_CauseProtocol_t cause){
switch (cause) {
case S1ap_CauseProtocol_transfer_syntax_error:
S1AP_WARN("Received S1 Error indication S1ap_CauseProtocol_transfer_syntax_error\n");
break;
case S1ap_CauseProtocol_abstract_syntax_error_reject:
S1AP_WARN("Received S1 Error indication S1ap_CauseProtocol_abstract_syntax_error_reject\n");
break;
case S1ap_CauseProtocol_abstract_syntax_error_ignore_and_notify:
S1AP_WARN("Received S1 Error indication S1ap_CauseProtocol_abstract_syntax_error_ignore_and_notify\n");
break;
case S1ap_CauseProtocol_message_not_compatible_with_receiver_state:
S1AP_WARN("Received S1 Error indication S1ap_CauseProtocol_message_not_compatible_with_receiver_state\n");
break;
case S1ap_CauseProtocol_semantic_error:
S1AP_WARN("Received S1 Error indication S1ap_CauseProtocol_semantic_error\n");
break;
case S1ap_CauseProtocol_abstract_syntax_error_falsely_constructed_message:
S1AP_WARN("Received S1 Error indication S1ap_CauseProtocol_abstract_syntax_error_falsely_constructed_message\n");
break;
case S1ap_CauseProtocol_unspecified:
S1AP_WARN("Received S1 Error indication S1ap_CauseProtocol_unspecified\n");
break;
default:
S1AP_WARN("Received S1 Error indication cause protocol case not handled\n");
}
}
static
void process_misc_failure(S1ap_CauseMisc_t cause){
switch (cause) {
case S1ap_CauseMisc_control_processing_overload:
S1AP_WARN("Received S1 Error indication S1ap_CauseMisc_control_processing_overload\n");
break;
case S1ap_CauseMisc_not_enough_user_plane_processing_resources:
S1AP_WARN("Received S1 Error indication S1ap_CauseMisc_not_enough_user_plane_processing_resources\n");
break;
case S1ap_CauseMisc_hardware_failure:
S1AP_WARN("Received S1 Error indication S1ap_CauseMisc_hardware_failure\n");
break;
case S1ap_CauseMisc_om_intervention:
S1AP_WARN("Received S1 Error indication S1ap_CauseMisc_om_intervention\n");
break;
case S1ap_CauseMisc_unspecified:
S1AP_WARN("Received S1 Error indication S1ap_CauseMisc_unspecified\n");
break;
case S1ap_CauseMisc_unknown_PLMN:
S1AP_WARN("Received S1 Error indication S1ap_CauseMisc_unknown_PLMN\n");
break;
default:
S1AP_WARN("Received S1 Error indication cause misc case not handled\n");
}
}
...@@ -837,3 +837,152 @@ int s1ap_eNB_e_rab_setup_resp(instance_t instance, ...@@ -837,3 +837,152 @@ int s1ap_eNB_e_rab_setup_resp(instance_t instance,
return ret; return ret;
} }
//------------------------------------------------------------------------------
int s1ap_eNB_path_switch_req(instance_t instance,
s1ap_path_switch_req_t *path_switch_req_p)
//------------------------------------------------------------------------------
{
s1ap_eNB_instance_t *s1ap_eNB_instance_p = NULL;
struct s1ap_eNB_ue_context_s *ue_context_p = NULL;
S1ap_PathSwitchRequestIEs_t *initial_ies_p = NULL;
s1ap_message message;
uint8_t *buffer = NULL;
uint32_t length;
int ret = -1;
int i;
/* Retrieve the S1AP eNB instance associated with Mod_id */
s1ap_eNB_instance_p = s1ap_eNB_get_instance(instance);
DevAssert(path_switch_req_p != NULL);
DevAssert(s1ap_eNB_instance_p != NULL);
if ((ue_context_p = s1ap_eNB_get_ue_context(s1ap_eNB_instance_p,
path_switch_req_p->eNB_ue_s1ap_id)) == NULL) {
/* The context for this eNB ue s1ap id doesn't exist in the map of eNB UEs */
S1AP_WARN("Failed to find ue context associated with eNB ue s1ap id: 0x%06x\n",
path_switch_req_p->eNB_ue_s1ap_id);
return -1;
}
/* Uplink NAS transport can occur either during an s1ap connected state
* or during initial attach (for example: NAS authentication).
*/
if (!(ue_context_p->ue_state == S1AP_UE_CONNECTED ||
ue_context_p->ue_state == S1AP_UE_WAITING_CSR)) {
S1AP_WARN("You are attempting to send NAS data over non-connected "
"eNB ue s1ap id: %06x, current state: %d\n",
path_switch_req_p->eNB_ue_s1ap_id, ue_context_p->ue_state);
return -1;
}
/* Prepare the S1AP message to encode */
memset(&message, 0, sizeof(s1ap_message));
message.direction = S1AP_PDU_PR_successfulOutcome;
message.procedureCode = S1ap_ProcedureCode_id_PathSwitchRequest;
message.criticality = S1ap_Criticality_reject;
initial_ies_p = &message.msg.s1ap_PathSwitchRequestIEs;
initial_ies_p->eNB_UE_S1AP_ID = path_switch_req_p->eNB_ue_s1ap_id;
initial_ies_p->sourceMME_UE_S1AP_ID = ue_context_p->mme_ue_s1ap_id;
// S1AP_PATHSWITCHREQUESTIES_CSG_ID_PRESENT
// S1AP_PATHSWITCHREQUESTIES_CELLACCESSMODE_PRESENT
// S1AP_PATHSWITCHREQUESTIES_SOURCEMME_GUMMEI_PRESENT
initial_ies_p->presenceMask |= 0;
for (i = 0; i < path_switch_req_p->nb_of_e_rabs; i++) {
S1ap_E_RABToBeSwitchedDLItem_t *new_item;
new_item = calloc(1, sizeof(S1ap_E_RABToBeSwitchedDLListIEs_t));
new_item->e_RAB_ID = path_switch_req_p->e_rabs_tobeswitched[i].e_rab_id;
GTP_TEID_TO_ASN1(path_switch_req_p->e_rabs_tobeswitched[i].gtp_teid, &new_item->gTP_TEID);
new_item->transportLayerAddress.buf = path_switch_req_p->e_rabs_tobeswitched[i].eNB_addr.buffer;
new_item->transportLayerAddress.size = path_switch_req_p->e_rabs_tobeswitched[i].eNB_addr.length;
new_item->transportLayerAddress.bits_unused = 0;
S1AP_DEBUG("path_switch_req: e_rab ID %ld, teid %u, enb_addr %d.%d.%d.%d, SIZE %d\n",
new_item->e_RAB_ID,
path_switch_req_p->e_rabs_tobeswitched[i].gtp_teid,
new_item->transportLayerAddress.buf[0],
new_item->transportLayerAddress.buf[1],
new_item->transportLayerAddress.buf[2],
new_item->transportLayerAddress.buf[3],
new_item->transportLayerAddress.size);
S1ap_IE_t *ie = s1ap_new_ie(S1ap_ProtocolIE_ID_id_E_RABToBeSwitchedDLItem,
S1ap_Criticality_ignore,
&asn_DEF_S1ap_E_RABToBeSwitchedDLItem,
new_item);
ASN_SEQUENCE_ADD(&initial_ies_p->e_RABToBeSwitchedDLList.s1ap_E_RABToBeSwitchedDLItem,
ie);
}
// S1ap_EUTRAN_CGI_t
MCC_MNC_TO_PLMNID(
s1ap_eNB_instance_p->mcc,
s1ap_eNB_instance_p->mnc,
s1ap_eNB_instance_p->mnc_digit_length,
&initial_ies_p->eutran_cgi.pLMNidentity);
MACRO_ENB_ID_TO_CELL_IDENTITY(s1ap_eNB_instance_p->eNB_id,
0,
&initial_ies_p->eutran_cgi.cell_ID);
// S1ap_TAI_t
/* MCC/MNC should be repeated in TAI and EUTRAN CGI */
MCC_MNC_TO_PLMNID(
s1ap_eNB_instance_p->mcc,
s1ap_eNB_instance_p->mnc,
s1ap_eNB_instance_p->mnc_digit_length,
&initial_ies_p->tai.pLMNidentity);
TAC_TO_ASN1(s1ap_eNB_instance_p->tac,&initial_ies_p->tai.tAC);
//S1ap_UESecurityCapabilities_t
INT16_TO_OCTET_STRING(
path_switch_req_p->security_capabilities.encryption_algorithms,
&initial_ies_p->ueSecurityCapabilities.encryptionAlgorithms
);
INT16_TO_OCTET_STRING(
path_switch_req_p->security_capabilities.integrity_algorithms,
&initial_ies_p->ueSecurityCapabilities.encryptionAlgorithms
);
fprintf(stderr, "start encode\n");
if (s1ap_eNB_encode_pdu(&message, &buffer, &length) < 0) {
S1AP_ERROR("Failed to encode Path Switch Req \n");
/* Encode procedure has failed... */
return -1;
}
MSC_LOG_TX_MESSAGE(
MSC_S1AP_ENB,
MSC_S1AP_MME,
(const char *)buffer,
length,
MSC_AS_TIME_FMT" E_RAN Setup successfulOutcome eNB_ue_s1ap_id %u mme_ue_s1ap_id %u",
0,0,//MSC_AS_TIME_ARGS(ctxt_pP),
initial_ies_p->eNB_UE_S1AP_ID,
initial_ies_p->sourceMME_UE_S1AP_ID);
/* UE associated signalling -> use the allocated stream */
s1ap_eNB_itti_send_sctp_data_req(s1ap_eNB_instance_p->instance,
ue_context_p->mme_ref->assoc_id, buffer,
length, ue_context_p->tx_stream);
return ret;
}
...@@ -44,4 +44,7 @@ int s1ap_eNB_ue_capabilities(instance_t instance, ...@@ -44,4 +44,7 @@ int s1ap_eNB_ue_capabilities(instance_t instance,
int s1ap_eNB_e_rab_setup_resp(instance_t instance, int s1ap_eNB_e_rab_setup_resp(instance_t instance,
s1ap_e_rab_setup_resp_t *e_rab_setup_resp_p); s1ap_e_rab_setup_resp_t *e_rab_setup_resp_p);
int s1ap_eNB_path_switch_req(instance_t instance,
s1ap_path_switch_req_t *path_switch_req_p);
#endif /* S1AP_ENB_NAS_PROCEDURES_H_ */ #endif /* S1AP_ENB_NAS_PROCEDURES_H_ */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment