diff --git a/openair-cn/S1AP/s1ap_eNB.c b/openair-cn/S1AP/s1ap_eNB.c index e0d0629ff6b9c08fdec3df0f2755834de359dda2..18137475be3d07a38b606ab83be260de97097324 100644 --- a/openair-cn/S1AP/s1ap_eNB.c +++ b/openair-cn/S1AP/s1ap_eNB.c @@ -296,6 +296,10 @@ void *s1ap_eNB_task(void *arg) s1ap_eNB_nas_non_delivery_ind(ITTI_MESSAGE_GET_INSTANCE(received_msg), &S1AP_NAS_NON_DELIVERY_IND(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)); + } break; default: S1AP_ERROR("Received unhandled message: %d:%s\n", ITTI_MSG_ID(received_msg), ITTI_MSG_NAME(received_msg)); diff --git a/openair-cn/S1AP/s1ap_eNB_encoder.c b/openair-cn/S1AP/s1ap_eNB_encoder.c index c8d4cc961893a59d81d6f0a155bc0209831ac6a0..821f791747e8029a065ea6004e308ccc66d2ac49 100644 --- a/openair-cn/S1AP/s1ap_eNB_encoder.c +++ b/openair-cn/S1AP/s1ap_eNB_encoder.c @@ -89,6 +89,13 @@ int s1ap_eNB_encode_nas_non_delivery( uint8_t **buffer, uint32_t *length); +static inline +int s1ap_eNB_encode_ue_context_release_complete( + S1ap_UEContextReleaseCompleteIEs_t *s1ap_UEContextReleaseCompleteIEs, + uint8_t **buffer, + uint32_t *length); + + int s1ap_eNB_encode_pdu(s1ap_message *message, uint8_t **buffer, uint32_t *len) { DevAssert(message != NULL); @@ -198,14 +205,34 @@ int s1ap_eNB_encode_successfull_outcome(s1ap_message *s1ap_message_p, message_string = calloc(10000, sizeof(char)); s1ap_string_total_size = 0; + message_string_size = strlen(message_string); + switch(s1ap_message_p->procedureCode) { - case S1ap_ProcedureCode_id_InitialContextSetup: - ret = s1ap_eNB_encode_initial_context_setup_response( - &s1ap_message_p->msg.s1ap_InitialContextSetupResponseIEs, buffer, len); - s1ap_xer_print_s1ap_initialcontextsetupresponse(s1ap_xer__print2sp, message_string, s1ap_message_p); - message_id = S1AP_INITIAL_CONTEXT_SETUP_LOG; - break; + case S1ap_ProcedureCode_id_InitialContextSetup: + ret = s1ap_eNB_encode_initial_context_setup_response( + &s1ap_message_p->msg.s1ap_InitialContextSetupResponseIEs, buffer, len); + + s1ap_xer_print_s1ap_initialcontextsetupresponse(s1ap_xer__print2sp, message_string, s1ap_message_p); + message_id = S1AP_INITIAL_CONTEXT_SETUP_LOG; + message_p = itti_alloc_new_message_sized(TASK_S1AP, message_id, message_string_size + sizeof (IttiMsgText)); + message_p->ittiMsg.s1ap_initial_context_setup_log.size = message_string_size; + memcpy(&message_p->ittiMsg.s1ap_initial_context_setup_log.text, message_string, message_string_size); + itti_send_msg_to_task(TASK_UNKNOWN, INSTANCE_DEFAULT, message_p); + free(message_string); + break; + + case S1ap_ProcedureCode_id_UEContextRelease: + ret = s1ap_eNB_encode_ue_context_release_complete( + &s1ap_message_p->msg.s1ap_UEContextReleaseCompleteIEs, buffer, len); + s1ap_xer_print_s1ap_uecontextreleasecomplete(s1ap_xer__print2sp, message_string, s1ap_message_p); + message_id = S1AP_UE_CONTEXT_RELEASE_COMPLETE_LOG; + message_p = itti_alloc_new_message_sized(TASK_S1AP, message_id, message_string_size + sizeof (IttiMsgText)); + message_p->ittiMsg.s1ap_ue_context_release_complete_log.size = message_string_size; + memcpy(&message_p->ittiMsg.s1ap_ue_context_release_complete_log.text, message_string, message_string_size); + itti_send_msg_to_task(TASK_UNKNOWN, INSTANCE_DEFAULT, message_p); + free(message_string); + break; default: S1AP_DEBUG("Unknown procedure ID (%d) for successfull outcome message\n", @@ -214,15 +241,6 @@ int s1ap_eNB_encode_successfull_outcome(s1ap_message *s1ap_message_p, break; } - message_string_size = strlen(message_string); - - message_p = itti_alloc_new_message_sized(TASK_S1AP, message_id, message_string_size + sizeof (IttiMsgText)); - message_p->ittiMsg.s1ap_initial_context_setup_log.size = message_string_size; - memcpy(&message_p->ittiMsg.s1ap_initial_context_setup_log.text, message_string, message_string_size); - - itti_send_msg_to_task(TASK_UNKNOWN, INSTANCE_DEFAULT, message_p); - - free(message_string); return ret; } @@ -445,3 +463,31 @@ int s1ap_eNB_encode_initial_context_setup_response( &asn_DEF_S1ap_InitialContextSetupResponse, initial_context_setup_response_p); } + +static inline +int s1ap_eNB_encode_ue_context_release_complete( + S1ap_UEContextReleaseCompleteIEs_t *s1ap_UEContextReleaseCompleteIEs, + uint8_t **buffer, + uint32_t *length) +{ + S1ap_UEContextReleaseComplete_t ue_context_release_complete; + S1ap_UEContextReleaseComplete_t *ue_context_release_complete_p = + &ue_context_release_complete; + + memset((void *)ue_context_release_complete_p, 0, + sizeof(ue_context_release_complete)); + + if (s1ap_encode_s1ap_uecontextreleasecompleteies( + ue_context_release_complete_p, s1ap_UEContextReleaseCompleteIEs) < 0) + { + return -1; + } + + return s1ap_generate_successfull_outcome(buffer, + length, + S1ap_ProcedureCode_id_UEContextRelease, + S1ap_Criticality_reject, + &asn_DEF_S1ap_UEContextReleaseComplete, + ue_context_release_complete_p); +} + diff --git a/openair-cn/S1AP/s1ap_eNB_itti_messaging.c b/openair-cn/S1AP/s1ap_eNB_itti_messaging.c index 8cb4e98f548c1bd3d0272fb5cf45d9dbbe084d67..2eb9011e942cf20fe39a18c552ccaf918e600609 100644 --- a/openair-cn/S1AP/s1ap_eNB_itti_messaging.c +++ b/openair-cn/S1AP/s1ap_eNB_itti_messaging.c @@ -40,3 +40,16 @@ void s1ap_eNB_itti_send_nas_downlink_ind(instance_t instance, itti_send_msg_to_task(TASK_RRC_ENB, instance, message_p); } + +void s1ap_eNB_itti_send_sctp_close_association(instance_t instance, int32_t assoc_id) +{ + MessageDef *message_p = NULL; + sctp_close_association_t *sctp_close_association_p = NULL; + + message_p = itti_alloc_new_message(TASK_S1AP, SCTP_CLOSE_ASSOCIATION); + sctp_close_association_p = &message_p->ittiMsg.sctp_close_association; + sctp_close_association_p->assoc_id = assoc_id; + + itti_send_msg_to_task(TASK_SCTP, instance, message_p); +} + diff --git a/openair-cn/S1AP/s1ap_eNB_itti_messaging.h b/openair-cn/S1AP/s1ap_eNB_itti_messaging.h index 2d9ac3ce0edd50e04b37c1e0e87a6eb89be0198c..8a16d7aad2efad6855e518195e5139e72c86b02c 100644 --- a/openair-cn/S1AP/s1ap_eNB_itti_messaging.h +++ b/openair-cn/S1AP/s1ap_eNB_itti_messaging.h @@ -38,4 +38,8 @@ void s1ap_eNB_itti_send_nas_downlink_ind(instance_t instance, uint8_t *nas_pdu, uint32_t nas_pdu_length); +void s1ap_eNB_itti_send_sctp_close_association(instance_t instance, + int32_t assoc_id); + + #endif /* S1AP_ENB_ITTI_MESSAGING_H_ */ diff --git a/openair-cn/S1AP/s1ap_eNB_nas_procedures.c b/openair-cn/S1AP/s1ap_eNB_nas_procedures.c index 608addc19a12212284e19a5002b9a192e632e7ac..49a9bf0109b346fbe1278cf4d40e031abbdef95f 100644 --- a/openair-cn/S1AP/s1ap_eNB_nas_procedures.c +++ b/openair-cn/S1AP/s1ap_eNB_nas_procedures.c @@ -572,3 +572,75 @@ int s1ap_eNB_ue_capabilities(instance_t instance, return ret; } + +int s1ap_ue_context_release_complete(instance_t instance, + s1ap_ue_release_complete_t *ue_release_complete_p) +{ + s1ap_eNB_instance_t *s1ap_eNB_instance_p = NULL; + struct s1ap_eNB_ue_context_s *ue_context_p = NULL; + + S1ap_UEContextReleaseCompleteIEs_t *ue_ctxt_release_complete_ies_p = NULL; + + s1ap_message message; + + uint8_t *buffer; + uint32_t length; + int ret = -1; + + /* Retrieve the S1AP eNB instance associated with Mod_id */ + s1ap_eNB_instance_p = s1ap_eNB_get_instance(instance); + + DevAssert(ue_release_complete_p != NULL); + DevAssert(s1ap_eNB_instance_p != NULL); + + if ((ue_context_p = s1ap_eNB_get_ue_context(s1ap_eNB_instance_p, + ue_release_complete_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: %u\n", + ue_release_complete_p->eNB_ue_s1ap_id); + 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_UEContextRelease; + //message.criticality = S1ap_Criticality_reject; + message.direction = S1AP_PDU_PR_successfulOutcome; + + ue_ctxt_release_complete_ies_p = &message.msg.s1ap_UEContextReleaseCompleteIEs; + + ue_ctxt_release_complete_ies_p->eNB_UE_S1AP_ID = ue_release_complete_p->eNB_ue_s1ap_id; + ue_ctxt_release_complete_ies_p->mme_ue_s1ap_id = ue_context_p->mme_ue_s1ap_id; + //ue_ctxt_release_complete_ies_p->criticalityDiagnostics + //ue_ctxt_release_complete_ies_p->presenceMask + + if (s1ap_eNB_encode_pdu(&message, &buffer, &length) < 0) { + /* Encode procedure has failed... */ + S1AP_ERROR("Failed to encode UE context release complete\n"); + return -1; + } + + /* 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->stream); + + + s1ap_eNB_itti_send_sctp_close_association(s1ap_eNB_instance_p->instance, + ue_context_p->mme_ref->assoc_id); + + + + // release UE context + struct s1ap_eNB_ue_context_s *ue_context2_p = NULL; + if ((ue_context2_p = RB_REMOVE(s1ap_ue_map, &s1ap_eNB_instance_p->s1ap_ue_head, ue_context_p)) + == NULL) + { + s1ap_eNB_free_ue_context(ue_context2_p); + } + return ret; +} + diff --git a/openair-cn/S1AP/s1ap_eNB_nas_procedures.h b/openair-cn/S1AP/s1ap_eNB_nas_procedures.h index 2e68cf2e12b647d7f2e13808f727dc5d8d8e4440..04d31b0f2a66278cac7e1390a864495ddd9d57c0 100644 --- a/openair-cn/S1AP/s1ap_eNB_nas_procedures.h +++ b/openair-cn/S1AP/s1ap_eNB_nas_procedures.h @@ -49,4 +49,8 @@ int s1ap_eNB_initial_ctxt_resp( int s1ap_eNB_ue_capabilities(instance_t instance, s1ap_ue_cap_info_ind_t *ue_cap_info_ind_p); +int s1ap_ue_context_release_complete(instance_t instance, + s1ap_ue_release_complete_t *ue_release_complete_p); + + #endif /* S1AP_ENB_NAS_PROCEDURES_H_ */ diff --git a/openair-cn/S1AP/s1ap_eNB_ue_context.h b/openair-cn/S1AP/s1ap_eNB_ue_context.h index 51dcb4d897e4d80c521847436bd744112e9bbcbf..8e4906d05e0522b5b3748f8586b26cd880ee1b29 100644 --- a/openair-cn/S1AP/s1ap_eNB_ue_context.h +++ b/openair-cn/S1AP/s1ap_eNB_ue_context.h @@ -91,4 +91,7 @@ struct s1ap_eNB_ue_context_s *s1ap_eNB_get_ue_context( s1ap_eNB_instance_t *instance_p, uint32_t eNB_ue_s1ap_id); +void s1ap_eNB_free_ue_context(struct s1ap_eNB_ue_context_s *ue_context_p); + + #endif /* S1AP_ENB_UE_CONTEXT_H_ */