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
########################################
# 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})
......
......@@ -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_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_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 */
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_
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_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 */
MESSAGE_DEF(S1AP_DOWNLINK_NAS , MESSAGE_PRIORITY_MED, s1ap_downlink_nas_t , s1ap_downlink_nas )
......
......@@ -41,6 +41,8 @@
#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_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_INITIAL_CONTEXT_SETUP_REQ(mSGpTR) (mSGpTR)->ittiMsg.s1ap_initial_context_setup_req
......@@ -261,6 +263,17 @@ typedef struct e_rab_setup_s {
uint32_t gtp_teid;
} 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 {
/* Unique e_rab_id for the UE. */
uint8_t e_rab_id;
......@@ -511,6 +524,54 @@ typedef struct s1ap_e_rab_setup_resp_s {
e_rab_failed_t e_rabs_failed[S1AP_MAX_E_RAB];
} 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
typedef struct s1ap_ue_release_command_s {
......
......@@ -48,4 +48,4 @@ MESSAGE_DEF(X2AP_DEREGISTERED_ENB_IND , MESSAGE_PRIORITY_MED, x2ap_deregist
/* handover messages X2AP <-> RRC */
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 @@
#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_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_DEREGISTERED_ENB_IND(mSGpTR) (mSGpTR)->ittiMsg.x2ap_deregistered_enb_ind
......@@ -120,11 +120,11 @@ typedef struct x2ap_handover_req_s {
int target_mod_id;
} 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_x2id; /* TODO: to be fixed/remove */
/* TODO: this parameter has to be removed */
int target_mod_id;
} x2ap_handover_resp_t;
} x2ap_handover_req_ack_t;
#endif /* X2AP_MESSAGES_TYPES_H_ */
......@@ -279,7 +279,9 @@ typedef enum e_rab_satus_e {
E_RAB_STATUS_NEW,
E_RAB_STATUS_DONE, // from the eNB perspective
E_RAB_STATUS_ESTABLISHED, // get the reconfigurationcomplete form UE
E_RAB_STATUS_REESTABLISHED, // after HO
E_RAB_STATUS_FAILED,
E_RAB_STATUS_RELEASED
} e_rab_status_t;
typedef struct e_rab_param_s {
......@@ -409,14 +411,23 @@ typedef struct eNB_RRC_UE_s {
uint32_t eNB_ue_s1ap_id :24;
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 */
uint8_t setup_e_rabs;
/* Number of e_rab to be setup in the list */
uint8_t nb_of_e_rabs;
/* list of e_rab to be setup by RRC layers */
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
uint32_t enb_gtp_teid[S1AP_MAX_E_RAB];
transport_layer_addr_t enb_gtp_addrs[S1AP_MAX_E_RAB];
......
......@@ -2273,7 +2273,9 @@ rrc_eNB_process_MeasurementReport(
LOG_I(RRC, "RSRP of Source %d\n", measResults2->measResultServCell.rsrpResult);
LOG_I(RRC, "RSRQ of Source %d\n", measResults2->measResultServCell.rsrqResult);
#endif
/* algorithm to decide whether to trigger HO or not */
/* if the UE is not in handover mode, start handover procedure */
if (ue_context_pP->ue_context.Status != RRC_HO_EXECUTION) {
MessageDef *msg;
......@@ -2361,7 +2363,7 @@ rrc_eNB_generate_HandoverPreparationInformation(
{
struct rrc_eNB_ue_context_s* ue_context_target_p = NULL;
//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));
/*
uint8_t buffer[100];
......@@ -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_complete = 0;
/* simulation related logic */
if (mod_id_target != 0xFF) {
//UE_id_target = rrc_find_free_ue_index(modid_target);
ue_context_target_p =
......@@ -2646,10 +2649,10 @@ check_handovers(
memcpy(UE_rrc_inst[0].sib1[0]->cellAccessRelatedInfo.cellIdentity.buf,
eNB_rrc_inst[ctxt_pP->module_id].carrier[0].sib1->cellAccessRelatedInfo.cellIdentity.buf,
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 */
X2AP_HANDOVER_RESP(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).target_mod_id = 1 - ctxt_pP->module_id;
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);
}
......@@ -5428,15 +5431,19 @@ rrc_enb_task(
break;
# 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:
LOG_I(RRC, "[eNB %d] X2-Received %s\n", instance, msg_name_p);
rrc_eNB_process_handoverPreparationInformation(instance, &X2AP_HANDOVER_REQ(msg_p));
break;
case X2AP_HANDOVER_RESP: {
case X2AP_HANDOVER_REQ_ACK: {
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);
DevAssert(ue_context_p != NULL);
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,
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_USE_MME) */
......@@ -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_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 /* defined(ENABLE_USE_MME) */
#endif /* RRC_ENB_S1AP_H_ */
......@@ -74,8 +74,8 @@ void x2ap_eNB_handle_handover_req(instance_t instance,
x2ap_handover_req_t *x2ap_handover_req);
static
void x2ap_eNB_handle_handover_resp(instance_t instance,
x2ap_handover_resp_t *x2ap_handover_resp);
void x2ap_eNB_handle_handover_req_ack(instance_t instance,
x2ap_handover_req_ack_t *x2ap_handover_req_ack);
static
void x2ap_eNB_register_eNB(x2ap_eNB_instance_t *instance_p,
......@@ -421,8 +421,8 @@ void x2ap_eNB_handle_handover_req(instance_t instance,
}
static
void x2ap_eNB_handle_handover_resp(instance_t instance,
x2ap_handover_resp_t *x2ap_handover_resp)
void x2ap_eNB_handle_handover_req_ack(instance_t instance,
x2ap_handover_req_ack_t *x2ap_handover_req_ack)
{
/* TODO: remove this hack (the goal is to find the correct
* 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,
x2ap_eNB_instance_t *instance_p;
x2ap_eNB_data_t *target;
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);
DevAssert(instance_p != NULL);
......@@ -442,7 +442,7 @@ void x2ap_eNB_handle_handover_resp(instance_t instance,
target = x2ap_is_eNB_id_in_list(target_enb_id);
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)
......@@ -474,9 +474,9 @@ void *x2ap_task(void *arg)
&X2AP_HANDOVER_REQ(received_msg));
break;
case X2AP_HANDOVER_RESP:
x2ap_eNB_handle_handover_resp(ITTI_MESSAGE_GET_INSTANCE(received_msg),
&X2AP_HANDOVER_RESP(received_msg));
case X2AP_HANDOVER_REQ_ACK:
x2ap_eNB_handle_handover_req_ack(ITTI_MESSAGE_GET_INSTANCE(received_msg),
&X2AP_HANDOVER_REQ_ACK(received_msg));
break;
case SCTP_NEW_ASSOCIATION_RESP:
......
......@@ -395,9 +395,9 @@ abort();
return ret;
}
int x2ap_eNB_generate_x2_handover_response(x2ap_eNB_instance_t *instance,
x2ap_eNB_data_t *x2ap_enb_data_p,
int source_x2id)
int x2ap_eNB_generate_x2_handover_req_ack(x2ap_eNB_instance_t *instance,
x2ap_eNB_data_t *x2ap_enb_data_p,
int source_x2id)
{
x2ap_message message;
......
......@@ -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,
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,
int source_x2id);
......
......@@ -353,11 +353,11 @@ x2ap_eNB_handle_handover_response(uint32_t assoc_id,
x2ap_eNB_data = x2ap_get_eNB(NULL, assoc_id, 0);
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 */
extern int x2id_to_source_rnti[1];
X2AP_HANDOVER_RESP(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_x2id = 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);
return 0;
}
......
......@@ -141,7 +141,7 @@ gtpv1u_create_s1u_tunnel(
const gtpv1u_enb_create_tunnel_req_t * const create_tunnel_req_pP,
gtpv1u_enb_create_tunnel_resp_t * const create_tunnel_resp_pP);
static int
int
gtpv1u_delete_s1u_tunnel(
const instance_t instanceP,
const gtpv1u_enb_delete_tunnel_req_t * const req_pP);
......@@ -809,7 +809,8 @@ gtpv1u_create_s1u_tunnel(
//-----------------------------------------------------------------------------
static int gtpv1u_delete_s1u_tunnel(
int
gtpv1u_delete_s1u_tunnel(
const instance_t instanceP,
const gtpv1u_enb_delete_tunnel_req_t * const req_pP)
{
......
......@@ -371,6 +371,12 @@ void *s1ap_eNB_task(void *arg)
}
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: {
s1ap_ue_context_release_complete(ITTI_MESSAGE_GET_INSTANCE(received_msg),
&S1AP_UE_CONTEXT_RELEASE_COMPLETE(received_msg));
......
This diff is collapsed.
......@@ -837,3 +837,152 @@ int s1ap_eNB_e_rab_setup_resp(instance_t instance,
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,
int s1ap_eNB_e_rab_setup_resp(instance_t instance,
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_ */
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