int s1ap_eNB_new_data_request(uint8_t eNB_id, uint8_t ue_id, uint8_t *buffer, uint32_t length) { s1ap_message message; struct s1ap_eNB_UE_description_s *ue_ref; struct s1ap_eNB_description_s *eNB_ref; /* If we don't found the eNB as S1 associated, this may indicate that no S1 Setup Request has been sent, * or S1 Setup has failed. */ if ((eNB_ref = s1ap_get_eNB_eNB_id(eNB_id)) == NULL) { S1AP_ERROR("This eNB (%d) has no known S1 association with any MME\n", eNB_id); return -1; } ///TODO: Check if eNB is associated to a MME /* Searching for UE in eNB. * If we failed founding it, request a new initial UE message to MME. */ if ((ue_ref = s1ap_get_ue_id_pair(eNB_id, ue_id)) == NULL) { if ((ue_ref = s1ap_UE_add_new(eNB_ref)) == NULL) { /* We failed to allocate a new UE in list */ S1AP_ERROR("Failed to allocate new UE description for UE %d attached to eNB %d\n", ue_id, eNB_id); return -1; } ue_ref->eNB_UE_s1ap_id = ue_id; /* MME UE S1AP ID is allocated by MME, waiting for Initial Context Setup Request Message * before setting it. */ ue_ref->mme_UE_s1ap_id = 0; ue_ref->eNB->nextstream++; /* Do we reached max number of output streams ?. * If so wrap to 1. */ if (ue_ref->eNB->nextstream == ue_ref->eNB->outstreams) ue_ref->eNB->nextstream = 1; /* Set the output stream that will be used for this UE */ ue_ref->stream_send = ue_ref->eNB->nextstream; S1AP_ERROR("Sending Initial UE message for UE %d on eNB %d\n", ue_id, eNB_id); return s1ap_eNB_generate_initial_ue_message(ue_ref, buffer, length); } else { /* UE is already associated to a valid Context. * Consider request as Uplink NAS transport. */ S1AP_ERROR("Sending Uplink NAS transport message for UE %d on eNB %d\n", ue_id, eNB_id); return s1ap_eNB_generate_uplink_nas_transport(ue_ref, buffer, length); } }
void s1ap_eNB_free_ue_context(struct s1ap_eNB_ue_context_s *ue_context_p) { if (ue_context_p == NULL) { S1AP_ERROR("Trying to free a NULL context\n"); return; } /* TODO: check that context is currently not in the tree of known * contexts. */ free(ue_context_p); }
int s1ap_eNB_init(const char *mme_ip_address, const uint8_t eNB_id) { uint8_t args = eNB_id; if (sctp_connect_to_remote_host( mme_ip_address, 36412, &args, s1ap_sctp_connected_callback, s1ap_sctp_recv_callback) < 0) { S1AP_ERROR("[eNB %02d] Failed to setup SCTP\n", eNB_id); return -1; } S1AP_DEBUG("[eNB %02d] successfully connected to MME\n", eNB_id); return 0; }
int s1ap_eNB_handle_message(uint32_t assoc_id, int32_t stream, const uint8_t * const data, const uint32_t data_length) { struct s1ap_message_s message; DevAssert(data != NULL); memset(&message, 0, sizeof(struct s1ap_message_s)); if (s1ap_eNB_decode_pdu(&message, data, data_length) < 0) { S1AP_ERROR("Failed to decode PDU\n"); return -1; } /* Checking procedure Code and direction of message */ if (message.procedureCode > sizeof(messages_callback) / (3 * sizeof( s1ap_message_decoded_callback)) || (message.direction > S1AP_PDU_PR_unsuccessfulOutcome)) { S1AP_ERROR("[SCTP %d] Either procedureCode %d or direction %d exceed expected\n", assoc_id, message.procedureCode, message.direction); return -1; } /* No handler present. * This can mean not implemented or no procedure for eNB (wrong direction). */ if (messages_callback[message.procedureCode][message.direction-1] == NULL) { S1AP_ERROR("[SCTP %d] No handler for procedureCode %d in %s\n", assoc_id, message.procedureCode, s1ap_direction2String[message.direction]); return -1; } /* Calling the right handler */ return (*messages_callback[message.procedureCode][message.direction-1]) (assoc_id, stream, &message); }
static int s1ap_eNB_handle_s1_setup_failure(uint32_t assoc_id, uint32_t stream, struct s1ap_message_s *message_p) { S1ap_S1SetupFailureIEs_t *s1_setup_failure_p; s1ap_eNB_mme_data_t *mme_desc_p; DevAssert(message_p != NULL); s1_setup_failure_p = &message_p->msg.s1ap_S1SetupFailureIEs; /* S1 Setup Failure == Non UE-related procedure -> stream 0 */ if (stream != 0) { S1AP_WARN("[SCTP %d] Received s1 setup 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 setup response for non existing " "MME context\n", assoc_id); return -1; } if ((s1_setup_failure_p->cause.present == S1ap_Cause_PR_misc) && (s1_setup_failure_p->cause.choice.misc == S1ap_CauseMisc_unspecified)) { S1AP_WARN("Received s1 setup failure for MME... MME is not ready\n"); } else { S1AP_ERROR("Received s1 setup failure for MME... please check your parameters\n"); } mme_desc_p->state = S1AP_ENB_STATE_WAITING; s1ap_handle_s1_setup_message(mme_desc_p, 0); return 0; }
struct s1ap_eNB_ue_context_s *s1ap_eNB_allocate_new_UE_context(void) { struct s1ap_eNB_ue_context_s *new_p; new_p = malloc(sizeof(struct s1ap_eNB_ue_context_s)); if (new_p == NULL) { S1AP_ERROR("Cannot allocate new ue context\n"); return NULL; } memset(new_p, 0, sizeof(struct s1ap_eNB_ue_context_s)); return new_p; }
static int s1ap_eNB_decode_successful_outcome(s1ap_message *message, S1ap_SuccessfulOutcome_t *successfullOutcome_p) { int ret = -1; MessageDef *message_p; char *message_string = NULL; size_t message_string_size; MessagesIds message_id; DevAssert(successfullOutcome_p != NULL); message_string = malloc(sizeof(char) * 10000); s1ap_string_total_size = 0; message->procedureCode = successfullOutcome_p->procedureCode; message->criticality = successfullOutcome_p->criticality; switch(successfullOutcome_p->procedureCode) { case S1ap_ProcedureCode_id_S1Setup: ret = s1ap_decode_s1ap_s1setupresponseies( &message->msg.s1ap_S1SetupResponseIEs, &successfullOutcome_p->value); s1ap_xer_print_s1ap_s1setupresponse(s1ap_xer__print2sp, message_string, message); message_id = S1AP_S1_SETUP_LOG; break; default: S1AP_ERROR("Unknown procedure ID (%d) for successfull outcome message\n", (int)successfullOutcome_p->procedureCode); return -1; } 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_s1_setup_log.size = message_string_size; memcpy(&message_p->ittiMsg.s1ap_s1_setup_log.text, message_string, message_string_size); itti_send_msg_to_task(TASK_UNKNOWN, INSTANCE_DEFAULT, message_p); free(message_string); return ret; }
int s1ap_eNB_decode_pdu(s1ap_message *message, const uint8_t * const buffer, const uint32_t length) { S1AP_PDU_t pdu; S1AP_PDU_t *pdu_p = &pdu; asn_dec_rval_t dec_ret; DevAssert(buffer != NULL); memset((void *)pdu_p, 0, sizeof(S1AP_PDU_t)); dec_ret = aper_decode(NULL, &asn_DEF_S1AP_PDU, (void **)&pdu_p, buffer, length, 0, 0); if (dec_ret.code != RC_OK) { S1AP_ERROR("Failed to decode pdu\n"); return -1; } message->direction = pdu_p->present; switch(pdu_p->present) { case S1AP_PDU_PR_initiatingMessage: return s1ap_eNB_decode_initiating_message(message, &pdu_p->choice.initiatingMessage); case S1AP_PDU_PR_successfulOutcome: return s1ap_eNB_decode_successful_outcome(message, &pdu_p->choice.successfulOutcome); case S1AP_PDU_PR_unsuccessfulOutcome: return s1ap_eNB_decode_unsuccessful_outcome(message, &pdu_p->choice.unsuccessfulOutcome); default: S1AP_DEBUG("Unknown presence (%d) or not implemented\n", (int)pdu_p->present); break; } return -1; }
static int s1ap_eNB_decode_unsuccessful_outcome(s1ap_message *message, S1ap_UnsuccessfulOutcome_t *unSuccessfullOutcome_p) { int ret = -1; DevAssert(unSuccessfullOutcome_p != NULL); message->procedureCode = unSuccessfullOutcome_p->procedureCode; message->criticality = unSuccessfullOutcome_p->criticality; switch(unSuccessfullOutcome_p->procedureCode) { case S1ap_ProcedureCode_id_S1Setup: return s1ap_decode_s1ap_s1setupfailureies( &message->msg.s1ap_S1SetupFailureIEs, &unSuccessfullOutcome_p->value); default: S1AP_ERROR("Unknown procedure ID (%d) for unsuccessfull outcome message\n", (int)unSuccessfullOutcome_p->procedureCode); break; } return ret; }
int s1ap_sctp_connected_callback(void *args, uint32_t assocId, uint32_t instreams, uint32_t outstreams) { struct s1ap_eNB_description_s* eNB_ref; if ((eNB_ref = s1ap_eNB_add_new()) == NULL) return; eNB_ref->eNB_id = *((uint8_t*)args); eNB_ref->assocId = assocId; eNB_ref->instreams = instreams; eNB_ref->outstreams = outstreams; eNB_ref->state = S1AP_ENB_STATE_DECONNECTED; /* First usable stream for UE associated signalling */ eNB_ref->nextstream = 1; if (s1ap_eNB_generate_s1_setup_request(eNB_ref) < 0) { S1AP_ERROR("[eNB %02d] Failed to encode S1 Setup Request\n", eNB_ref->eNB_id); return -1; } /* Waiting for the response from MME */ while ((volatile)(eNB_ref->state) & S1AP_ENB_STATE_WAITING) { } return 0; }
//------------------------------------------------------------------------------ int s1ap_eNB_ue_capabilities(instance_t instance, s1ap_ue_cap_info_ind_t *ue_cap_info_ind_p) //------------------------------------------------------------------------------ { s1ap_eNB_instance_t *s1ap_eNB_instance_p; struct s1ap_eNB_ue_context_s *ue_context_p; S1ap_UECapabilityInfoIndicationIEs_t *ue_cap_info_ind_ies_p; 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_cap_info_ind_p != NULL); DevAssert(s1ap_eNB_instance_p != NULL); if ((ue_context_p = s1ap_eNB_get_ue_context(s1ap_eNB_instance_p, ue_cap_info_ind_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_cap_info_ind_p->eNB_ue_s1ap_id); return -1; } /* UE capabilities message 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: %u, current state: %d\n", ue_cap_info_ind_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_initiatingMessage; message.procedureCode = S1ap_ProcedureCode_id_UECapabilityInfoIndication; ue_cap_info_ind_ies_p = &message.msg.s1ap_UECapabilityInfoIndicationIEs; ue_cap_info_ind_ies_p->ueRadioCapability.buf = ue_cap_info_ind_p->ue_radio_cap.buffer; ue_cap_info_ind_ies_p->ueRadioCapability.size = ue_cap_info_ind_p->ue_radio_cap.length; ue_cap_info_ind_ies_p->eNB_UE_S1AP_ID = ue_cap_info_ind_p->eNB_ue_s1ap_id; ue_cap_info_ind_ies_p->mme_ue_s1ap_id = ue_context_p->mme_ue_s1ap_id; if (s1ap_eNB_encode_pdu(&message, &buffer, &length) < 0) { /* Encode procedure has failed... */ S1AP_ERROR("Failed to encode UE capabilities indication\n"); return -1; } MSC_LOG_TX_MESSAGE( MSC_S1AP_ENB, MSC_S1AP_MME, (const char *)buffer, length, MSC_AS_TIME_FMT" UECapabilityInfoIndication initiatingMessage eNB_ue_s1ap_id %u mme_ue_s1ap_id %u", 0,0,//MSC_AS_TIME_ARGS(ctxt_pP), ue_cap_info_ind_ies_p->eNB_UE_S1AP_ID, ue_cap_info_ind_ies_p->mme_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; }
//------------------------------------------------------------------------------ int s1ap_eNB_initial_ctxt_resp( instance_t instance, s1ap_initial_context_setup_resp_t *initial_ctxt_resp_p) //------------------------------------------------------------------------------ { s1ap_eNB_instance_t *s1ap_eNB_instance_p = NULL; struct s1ap_eNB_ue_context_s *ue_context_p = NULL; S1ap_InitialContextSetupResponseIEs_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(initial_ctxt_resp_p != NULL); DevAssert(s1ap_eNB_instance_p != NULL); if ((ue_context_p = s1ap_eNB_get_ue_context(s1ap_eNB_instance_p, initial_ctxt_resp_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", initial_ctxt_resp_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", initial_ctxt_resp_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_InitialContextSetup; initial_ies_p = &message.msg.s1ap_InitialContextSetupResponseIEs; initial_ies_p->eNB_UE_S1AP_ID = initial_ctxt_resp_p->eNB_ue_s1ap_id; initial_ies_p->mme_ue_s1ap_id = ue_context_p->mme_ue_s1ap_id; for (i = 0; i < initial_ctxt_resp_p->nb_of_e_rabs; i++) { S1ap_E_RABSetupItemCtxtSURes_t *new_item; new_item = calloc(1, sizeof(S1ap_E_RABSetupItemCtxtSURes_t)); new_item->e_RAB_ID = initial_ctxt_resp_p->e_rabs[i].e_rab_id; GTP_TEID_TO_ASN1(initial_ctxt_resp_p->e_rabs[i].gtp_teid, &new_item->gTP_TEID); new_item->transportLayerAddress.buf = initial_ctxt_resp_p->e_rabs[i].eNB_addr.buffer; new_item->transportLayerAddress.size = initial_ctxt_resp_p->e_rabs[i].eNB_addr.length; new_item->transportLayerAddress.bits_unused = 0; ASN_SEQUENCE_ADD(&initial_ies_p->e_RABSetupListCtxtSURes.s1ap_E_RABSetupItemCtxtSURes, new_item); } if (s1ap_eNB_encode_pdu(&message, &buffer, &length) < 0) { S1AP_ERROR("Failed to encode uplink NAS transport\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" InitialContextSetup 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->mme_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; }
//------------------------------------------------------------------------------ void s1ap_eNB_nas_non_delivery_ind(instance_t instance, s1ap_nas_non_delivery_ind_t *s1ap_nas_non_delivery_ind) //------------------------------------------------------------------------------ { struct s1ap_eNB_ue_context_s *ue_context_p; s1ap_eNB_instance_t *s1ap_eNB_instance_p; S1ap_NASNonDeliveryIndication_IEs_t *nas_non_delivery_p; s1ap_message message; uint8_t *buffer; uint32_t length; DevAssert(s1ap_nas_non_delivery_ind != NULL); /* Retrieve the S1AP eNB instance associated with Mod_id */ s1ap_eNB_instance_p = s1ap_eNB_get_instance(instance); DevAssert(s1ap_eNB_instance_p != NULL); if ((ue_context_p = s1ap_eNB_get_ue_context(s1ap_eNB_instance_p, s1ap_nas_non_delivery_ind->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: %06x\n", s1ap_nas_non_delivery_ind->eNB_ue_s1ap_id); MSC_LOG_EVENT( MSC_S1AP_ENB, MSC_AS_TIME_FMT" Sent of NAS_NON_DELIVERY_IND to MME failed, no context for eNB_ue_s1ap_id %06x", s1ap_nas_non_delivery_ind->eNB_ue_s1ap_id); return; } /* Prepare the S1AP message to encode */ memset(&message, 0, sizeof(s1ap_message)); message.direction = S1AP_PDU_PR_initiatingMessage; message.procedureCode = S1ap_ProcedureCode_id_NASNonDeliveryIndication; nas_non_delivery_p = &message.msg.s1ap_NASNonDeliveryIndication_IEs; nas_non_delivery_p->eNB_UE_S1AP_ID = ue_context_p->eNB_ue_s1ap_id; nas_non_delivery_p->mme_ue_s1ap_id = ue_context_p->mme_ue_s1ap_id; nas_non_delivery_p->nas_pdu.buf = s1ap_nas_non_delivery_ind->nas_pdu.buffer; nas_non_delivery_p->nas_pdu.size = s1ap_nas_non_delivery_ind->nas_pdu.length; /* Send a dummy cause */ nas_non_delivery_p->cause.present = S1ap_Cause_PR_radioNetwork; nas_non_delivery_p->cause.choice.radioNetwork = S1ap_CauseRadioNetwork_radio_connection_with_ue_lost; if (s1ap_eNB_encode_pdu(&message, &buffer, &length) < 0) { S1AP_ERROR("Failed to encode NAS NON delivery indication\n"); /* Encode procedure has failed... */ MSC_LOG_EVENT( MSC_S1AP_ENB, MSC_AS_TIME_FMT" Sent of NAS_NON_DELIVERY_IND to MME failed (encoding)"); return; } MSC_LOG_TX_MESSAGE( MSC_S1AP_ENB, MSC_S1AP_MME, (const char *)s1ap_nas_non_delivery_ind, sizeof(s1ap_nas_non_delivery_ind_t), MSC_AS_TIME_FMT" NASNonDeliveryIndication initiatingMessage eNB_ue_s1ap_id %u mme_ue_s1ap_id %u", 0,0,//MSC_AS_TIME_ARGS(ctxt_pP), nas_non_delivery_p->eNB_UE_S1AP_ID, nas_non_delivery_p->mme_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); }
//------------------------------------------------------------------------------ int s1ap_eNB_nas_uplink(instance_t instance, s1ap_uplink_nas_t *s1ap_uplink_nas_p) //------------------------------------------------------------------------------ { struct s1ap_eNB_ue_context_s *ue_context_p; s1ap_eNB_instance_t *s1ap_eNB_instance_p; S1ap_UplinkNASTransportIEs_t *uplink_NAS_transport_p; s1ap_message message; uint8_t *buffer; uint32_t length; DevAssert(s1ap_uplink_nas_p != NULL); /* Retrieve the S1AP eNB instance associated with Mod_id */ s1ap_eNB_instance_p = s1ap_eNB_get_instance(instance); DevAssert(s1ap_eNB_instance_p != NULL); if ((ue_context_p = s1ap_eNB_get_ue_context(s1ap_eNB_instance_p, s1ap_uplink_nas_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: %06x\n", s1ap_uplink_nas_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: %u, current state: %d\n", s1ap_uplink_nas_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_initiatingMessage; message.procedureCode = S1ap_ProcedureCode_id_uplinkNASTransport; uplink_NAS_transport_p = &message.msg.s1ap_UplinkNASTransportIEs; uplink_NAS_transport_p->mme_ue_s1ap_id = ue_context_p->mme_ue_s1ap_id; uplink_NAS_transport_p->eNB_UE_S1AP_ID = ue_context_p->eNB_ue_s1ap_id; uplink_NAS_transport_p->nas_pdu.buf = s1ap_uplink_nas_p->nas_pdu.buffer; uplink_NAS_transport_p->nas_pdu.size = s1ap_uplink_nas_p->nas_pdu.length; MCC_MNC_TO_PLMNID( s1ap_eNB_instance_p->mcc, s1ap_eNB_instance_p->mnc, s1ap_eNB_instance_p->mnc_digit_length, &uplink_NAS_transport_p->eutran_cgi.pLMNidentity); #warning "TODO get cell id from RRC" MACRO_ENB_ID_TO_CELL_IDENTITY(s1ap_eNB_instance_p->eNB_id, 0, &uplink_NAS_transport_p->eutran_cgi.cell_ID); /* 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, &uplink_NAS_transport_p->tai.pLMNidentity); TAC_TO_ASN1(s1ap_eNB_instance_p->tac, &uplink_NAS_transport_p->tai.tAC); if (s1ap_eNB_encode_pdu(&message, &buffer, &length) < 0) { S1AP_ERROR("Failed to encode uplink NAS transport\n"); /* Encode procedure has failed... */ return -1; } MSC_LOG_TX_MESSAGE( MSC_S1AP_ENB, MSC_S1AP_MME, (const char *)NULL, 0, MSC_AS_TIME_FMT" uplinkNASTransport initiatingMessage eNB_ue_s1ap_id %u mme_ue_s1ap_id %u", 0,0,//MSC_AS_TIME_ARGS(ctxt_pP), uplink_NAS_transport_p->eNB_UE_S1AP_ID, uplink_NAS_transport_p->mme_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 0; }
//------------------------------------------------------------------------------ int s1ap_eNB_handle_nas_downlink(const uint32_t assoc_id, const uint32_t stream, struct s1ap_message_s* message_p) //------------------------------------------------------------------------------ { const S1ap_DownlinkNASTransportIEs_t *downlink_NAS_transport_p = NULL; s1ap_eNB_mme_data_t *mme_desc_p = NULL; s1ap_eNB_ue_context_t *ue_desc_p = NULL; s1ap_eNB_instance_t *s1ap_eNB_instance = NULL; DevAssert(message_p != NULL); downlink_NAS_transport_p = &message_p->msg.s1ap_DownlinkNASTransportIEs; /* UE-related procedure -> stream != 0 */ if (stream == 0) { S1AP_ERROR("[SCTP %d] Received UE-related procedure on stream == 0\n", assoc_id); return -1; } if ((mme_desc_p = s1ap_eNB_get_MME(NULL, assoc_id, 0)) == NULL) { S1AP_ERROR( "[SCTP %d] Received NAS downlink message for non existing MME context\n", assoc_id); return -1; } s1ap_eNB_instance = mme_desc_p->s1ap_eNB_instance; if ((ue_desc_p = s1ap_eNB_get_ue_context(s1ap_eNB_instance, downlink_NAS_transport_p->eNB_UE_S1AP_ID)) == NULL) { MSC_LOG_RX_DISCARDED_MESSAGE( MSC_S1AP_ENB, MSC_S1AP_MME, (const char *)downlink_NAS_transport_p, sizeof(S1ap_DownlinkNASTransportIEs_t), MSC_AS_TIME_FMT" downlinkNASTransport eNB_ue_s1ap_id %u mme_ue_s1ap_id %u", 0,0,//MSC_AS_TIME_ARGS(ctxt_pP), downlink_NAS_transport_p->eNB_UE_S1AP_ID, downlink_NAS_transport_p->mme_ue_s1ap_id); S1AP_ERROR("[SCTP %d] Received NAS downlink message for non existing UE context eNB_UE_S1AP_ID: 0x%"PRIx32" %u\n", assoc_id, downlink_NAS_transport_p->eNB_UE_S1AP_ID, downlink_NAS_transport_p->eNB_UE_S1AP_ID); return -1; } if (0 == ue_desc_p->rx_stream) { ue_desc_p->rx_stream = stream; } else if (stream != ue_desc_p->rx_stream) { S1AP_ERROR("[SCTP %d] Received UE-related procedure on stream %u, expecting %u\n", assoc_id, stream, ue_desc_p->rx_stream); return -1; } /* Is it the first outcome of the MME for this UE ? If so store the mme * UE s1ap id. */ if (ue_desc_p->mme_ue_s1ap_id == 0) { ue_desc_p->mme_ue_s1ap_id = downlink_NAS_transport_p->mme_ue_s1ap_id; } else { /* We already have a mme ue s1ap id check the received is the same */ if (ue_desc_p->mme_ue_s1ap_id != downlink_NAS_transport_p->mme_ue_s1ap_id) { S1AP_ERROR("[SCTP %d] Mismatch in MME UE S1AP ID (0x%"PRIx32" != 0x%"PRIx32")\n", assoc_id, downlink_NAS_transport_p->mme_ue_s1ap_id, ue_desc_p->mme_ue_s1ap_id ); return -1; } } MSC_LOG_RX_MESSAGE( MSC_S1AP_ENB, MSC_S1AP_MME, (const char *)downlink_NAS_transport_p, sizeof(S1ap_DownlinkNASTransportIEs_t), MSC_AS_TIME_FMT" downlinkNASTransport eNB_ue_s1ap_id %u mme_ue_s1ap_id %u", 0,0,//MSC_AS_TIME_ARGS(ctxt_pP), downlink_NAS_transport_p->eNB_UE_S1AP_ID, downlink_NAS_transport_p->mme_ue_s1ap_id); /* Forward the NAS PDU to RRC */ s1ap_eNB_itti_send_nas_downlink_ind(s1ap_eNB_instance->instance, ue_desc_p->ue_initial_id, ue_desc_p->eNB_ue_s1ap_id, downlink_NAS_transport_p->nas_pdu.buf, downlink_NAS_transport_p->nas_pdu.size); // LG: Why set to 0 ?? //ue_desc_p->ue_initial_id = 0; return 0; }
static int s1ap_eNB_generate_s1_setup_request( s1ap_eNB_instance_t *instance_p, s1ap_eNB_mme_data_t *s1ap_mme_data_p) { s1ap_message message; S1ap_S1SetupRequestIEs_t *s1SetupRequest_p; S1ap_PLMNidentity_t plmnIdentity; S1ap_SupportedTAs_Item_t ta; uint8_t *buffer; uint32_t len; int ret = 0; DevAssert(instance_p != NULL); DevAssert(s1ap_mme_data_p != NULL); memset(&message, 0, sizeof(s1ap_message)); message.direction = S1AP_PDU_PR_initiatingMessage; message.procedureCode = S1ap_ProcedureCode_id_S1Setup; message.criticality = S1ap_Criticality_reject; s1SetupRequest_p = &message.msg.s1ap_S1SetupRequestIEs; memset((void *)&plmnIdentity, 0, sizeof(S1ap_PLMNidentity_t)); memset((void *)&ta, 0, sizeof(S1ap_SupportedTAs_Item_t)); s1ap_mme_data_p->state = S1AP_ENB_STATE_WAITING; s1SetupRequest_p->global_ENB_ID.eNB_ID.present = S1ap_ENB_ID_PR_macroENB_ID; MACRO_ENB_ID_TO_BIT_STRING(instance_p->eNB_id, &s1SetupRequest_p->global_ENB_ID.eNB_ID.choice.macroENB_ID); MCC_MNC_TO_PLMNID(instance_p->mcc, instance_p->mnc, instance_p->mnc_digit_length, &s1SetupRequest_p->global_ENB_ID.pLMNidentity); S1AP_INFO("%d -> %02x%02x%02x\n", instance_p->eNB_id, s1SetupRequest_p->global_ENB_ID.eNB_ID.choice.macroENB_ID.buf[0], s1SetupRequest_p->global_ENB_ID.eNB_ID.choice.macroENB_ID.buf[1], s1SetupRequest_p->global_ENB_ID.eNB_ID.choice.macroENB_ID.buf[2]); INT16_TO_OCTET_STRING(instance_p->tac, &ta.tAC); MCC_MNC_TO_TBCD(instance_p->mcc, instance_p->mnc, instance_p->mnc_digit_length, &plmnIdentity); ASN_SEQUENCE_ADD(&ta.broadcastPLMNs.list, &plmnIdentity); ASN_SEQUENCE_ADD(&s1SetupRequest_p->supportedTAs.list, &ta); s1SetupRequest_p->defaultPagingDRX = instance_p->default_drx; if (instance_p->eNB_name != NULL) { s1SetupRequest_p->presenceMask |= S1AP_S1SETUPREQUESTIES_ENBNAME_PRESENT; OCTET_STRING_fromBuf(&s1SetupRequest_p->eNBname, instance_p->eNB_name, strlen(instance_p->eNB_name)); } if (s1ap_eNB_encode_pdu(&message, &buffer, &len) < 0) { S1AP_ERROR("Failed to encode S1 setup request\n"); return -1; } /* Non UE-Associated signalling -> stream = 0 */ s1ap_eNB_itti_send_sctp_data_req(instance_p->instance, s1ap_mme_data_p->assoc_id, buffer, len, 0); return ret; }
static int s1ap_eNB_handle_s1_setup_response(uint32_t assoc_id, uint32_t stream, struct s1ap_message_s *message_p) { S1ap_S1SetupResponseIEs_t *s1SetupResponse_p; s1ap_eNB_mme_data_t *mme_desc_p; int i; DevAssert(message_p != NULL); s1SetupResponse_p = &message_p->msg.s1ap_S1SetupResponseIEs; /* S1 Setup Response == Non UE-related procedure -> stream 0 */ if (stream != 0) { S1AP_ERROR("[SCTP %d] Received s1 setup response 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 setup response for non existing " "MME context\n", assoc_id); return -1; } /* The list of served gummei can contain at most 8 elements. * LTE related gummei is the first element in the list, i.e with an id of 0. */ DevAssert(s1SetupResponse_p->servedGUMMEIs.list.count == 1); for (i = 0; i < s1SetupResponse_p->servedGUMMEIs.list.count; i++) { struct S1ap_ServedGUMMEIsItem *gummei_item_p; struct served_gummei_s *new_gummei_p; int j; gummei_item_p = (struct S1ap_ServedGUMMEIsItem *) s1SetupResponse_p->servedGUMMEIs.list.array[i]; new_gummei_p = calloc(1, sizeof(struct served_gummei_s)); STAILQ_INIT(&new_gummei_p->served_plmns); STAILQ_INIT(&new_gummei_p->served_group_ids); STAILQ_INIT(&new_gummei_p->mme_codes); for (j = 0; j < gummei_item_p->servedPLMNs.list.count; j++) { S1ap_PLMNidentity_t *plmn_identity_p; struct plmn_identity_s *new_plmn_identity_p; plmn_identity_p = gummei_item_p->servedPLMNs.list.array[i]; new_plmn_identity_p = calloc(1, sizeof(struct plmn_identity_s)); TBCD_TO_MCC_MNC(plmn_identity_p, new_plmn_identity_p->mcc, new_plmn_identity_p->mnc, new_plmn_identity_p->mnc_digit_length); STAILQ_INSERT_TAIL(&new_gummei_p->served_plmns, new_plmn_identity_p, next); new_gummei_p->nb_served_plmns++; } for (j = 0; j < gummei_item_p->servedGroupIDs.list.count; j++) { S1ap_MME_Group_ID_t *mme_group_id_p; struct served_group_id_s *new_group_id_p; mme_group_id_p = gummei_item_p->servedGroupIDs.list.array[i]; new_group_id_p = calloc(1, sizeof(struct served_group_id_s)); OCTET_STRING_TO_INT16(mme_group_id_p, new_group_id_p->mme_group_id); STAILQ_INSERT_TAIL(&new_gummei_p->served_group_ids, new_group_id_p, next); new_gummei_p->nb_group_id++; } for (j = 0; j < gummei_item_p->servedMMECs.list.count; j++) { S1ap_MME_Code_t *mme_code_p; struct mme_code_s *new_mme_code_p; mme_code_p = gummei_item_p->servedMMECs.list.array[i]; new_mme_code_p = calloc(1, sizeof(struct mme_code_s)); OCTET_STRING_TO_INT8(mme_code_p, new_mme_code_p->mme_code); STAILQ_INSERT_TAIL(&new_gummei_p->mme_codes, new_mme_code_p, next); new_gummei_p->nb_mme_code++; } STAILQ_INSERT_TAIL(&mme_desc_p->served_gummei, new_gummei_p, next); } /* Free contents of the list */ ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_S1ap_ServedGUMMEIs, (void *)&s1SetupResponse_p->servedGUMMEIs); /* Set the capacity of this MME */ mme_desc_p->relative_mme_capacity = s1SetupResponse_p->relativeMMECapacity; /* Optionaly set the mme name */ if (s1SetupResponse_p->presenceMask & S1AP_S1SETUPRESPONSEIES_MMENAME_PRESENT) { mme_desc_p->mme_name = calloc(s1SetupResponse_p->mmEname.size + 1, sizeof(char)); memcpy(mme_desc_p->mme_name, s1SetupResponse_p->mmEname.buf, s1SetupResponse_p->mmEname.size); /* Convert the mme name to a printable string */ mme_desc_p->mme_name[s1SetupResponse_p->mmEname.size] = '\0'; } /* The association is now ready as eNB and MME know parameters of each other. * Mark the association as UP to enable UE contexts creation. */ mme_desc_p->state = S1AP_ENB_STATE_CONNECTED; mme_desc_p->s1ap_eNB_instance->s1ap_mme_associated_nb ++; s1ap_handle_s1_setup_message(mme_desc_p, 0); #if 0 /* We call back our self * -> generate a dummy initial UE message */ { s1ap_nas_first_req_t s1ap_nas_first_req; memset(&s1ap_nas_first_req, 0, sizeof(s1ap_nas_first_req_t)); s1ap_nas_first_req.rnti = 0xC03A; s1ap_nas_first_req.establishment_cause = RRC_CAUSE_MO_DATA; s1ap_nas_first_req.ue_identity.presenceMask = UE_IDENTITIES_gummei; s1ap_nas_first_req.ue_identity.gummei.mcc = 208; s1ap_nas_first_req.ue_identity.gummei.mnc = 34; s1ap_nas_first_req.ue_identity.gummei.mme_code = 0; s1ap_nas_first_req.ue_identity.gummei.mme_group_id = 0; /* NAS Attach request with IMSI */ static uint8_t nas_attach_req_imsi[] = { 0x07, 0x41, /* EPS Mobile identity = IMSI */ 0x71, 0x08, 0x29, 0x80, 0x43, 0x21, 0x43, 0x65, 0x87, 0xF9, /* End of EPS Mobile Identity */ 0x02, 0xE0, 0xE0, 0x00, 0x20, 0x02, 0x03, 0xD0, 0x11, 0x27, 0x1A, 0x80, 0x80, 0x21, 0x10, 0x01, 0x00, 0x00, 0x10, 0x81, 0x06, 0x00, 0x00, 0x00, 0x00, 0x83, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x0A, 0x00, 0x52, 0x12, 0xF2, 0x01, 0x27, 0x11, }; /* NAS Attach request with GUTI */ static uint8_t nas_attach_req_guti[] = { 0x07, 0x41, /* EPS Mobile identity = IMSI */ 0x71, 0x0B, 0xF6, 0x12, 0xF2, 0x01, 0x80, 0x00, 0x01, 0xE0, 0x00, 0xDA, 0x1F, /* End of EPS Mobile Identity */ 0x02, 0xE0, 0xE0, 0x00, 0x20, 0x02, 0x03, 0xD0, 0x11, 0x27, 0x1A, 0x80, 0x80, 0x21, 0x10, 0x01, 0x00, 0x00, 0x10, 0x81, 0x06, 0x00, 0x00, 0x00, 0x00, 0x83, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x0A, 0x00, 0x52, 0x12, 0xF2, 0x01, 0x27, 0x11, }; s1ap_nas_first_req.nas_pdu.buffer = nas_attach_req_guti; s1ap_nas_first_req.nas_pdu.length = sizeof(nas_attach_req_guti); s1ap_eNB_handle_nas_first_req(mme_desc_p->s1ap_eNB_instance->instance, &s1ap_nas_first_req); } #endif return 0; }
static int s1ap_eNB_handle_error_indication(uint32_t assoc_id, uint32_t stream, struct s1ap_message_s *message_p) { S1ap_ErrorIndicationIEs_t *s1_error_indication_p; s1ap_eNB_mme_data_t *mme_desc_p; DevAssert(message_p != NULL); s1_error_indication_p = &message_p->msg.s1ap_ErrorIndicationIEs; /* S1 Setup Failure == Non UE-related procedure -> stream 0 */ if (stream != 0) { S1AP_WARN("[SCTP %d] Received s1 Error indication 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 Error indication for non existing " "MME context\n", assoc_id); return -1; } if ( s1_error_indication_p->presenceMask & S1AP_ERRORINDICATIONIES_MME_UE_S1AP_ID_PRESENT) { S1AP_WARN("Received S1 Error indication MME UE S1AP ID 0x%x\n", s1_error_indication_p->mme_ue_s1ap_id); } if ( s1_error_indication_p->presenceMask & S1AP_ERRORINDICATIONIES_ENB_UE_S1AP_ID_PRESENT) { S1AP_WARN("Received S1 Error indication eNB UE S1AP ID 0x%x\n", s1_error_indication_p->eNB_UE_S1AP_ID); } if ( s1_error_indication_p->presenceMask & S1AP_ERRORINDICATIONIES_CAUSE_PRESENT) { switch(s1_error_indication_p->cause.present) { case S1ap_Cause_PR_NOTHING: S1AP_WARN("Received S1 Error indication cause NOTHING\n"); break; case S1ap_Cause_PR_radioNetwork: switch (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; case S1ap_Cause_PR_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; case S1ap_Cause_PR_nas: switch (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; case S1ap_Cause_PR_protocol: switch (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; case S1ap_Cause_PR_misc: switch (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; } } if ( s1_error_indication_p->presenceMask & S1AP_ERRORINDICATIONIES_CRITICALITYDIAGNOSTICS_PRESENT) { // TODO continue } // TODO continue return 0; }
static int s1ap_eNB_handle_ue_context_release_command(uint32_t assoc_id, uint32_t stream, struct s1ap_message_s *s1ap_message_p) { s1ap_eNB_mme_data_t *mme_desc_p = NULL; s1ap_eNB_ue_context_t *ue_desc_p = NULL; MessageDef *message_p = NULL; S1ap_UEContextReleaseCommandIEs_t *ueContextReleaseCommand_p; DevAssert(s1ap_message_p != NULL); ueContextReleaseCommand_p = &s1ap_message_p->msg.s1ap_UEContextReleaseCommandIEs; if ((mme_desc_p = s1ap_eNB_get_MME(NULL, assoc_id, 0)) == NULL) { S1AP_ERROR("[SCTP %d] Received UE context release command for non " "existing MME context\n", assoc_id); return -1; } S1ap_MME_UE_S1AP_ID_t mme_ue_s1ap_id; S1ap_ENB_UE_S1AP_ID_t enb_ue_s1ap_id; switch (ueContextReleaseCommand_p->uE_S1AP_IDs.present) { case S1ap_UE_S1AP_IDs_PR_uE_S1AP_ID_pair: enb_ue_s1ap_id = ueContextReleaseCommand_p->uE_S1AP_IDs.choice.uE_S1AP_ID_pair.eNB_UE_S1AP_ID; mme_ue_s1ap_id = ueContextReleaseCommand_p->uE_S1AP_IDs.choice.uE_S1AP_ID_pair.mME_UE_S1AP_ID; MSC_LOG_RX_MESSAGE( MSC_S1AP_ENB, MSC_S1AP_MME, NULL,0, "0 UEContextRelease/%s eNB_ue_s1ap_id "S1AP_UE_ID_FMT" mme_ue_s1ap_id "S1AP_UE_ID_FMT" len %u", s1ap_direction2String[s1ap_message_p->direction], enb_ue_s1ap_id, mme_ue_s1ap_id); if ((ue_desc_p = s1ap_eNB_get_ue_context(mme_desc_p->s1ap_eNB_instance, enb_ue_s1ap_id)) == NULL) { S1AP_ERROR("[SCTP %d] Received UE context release command for non " "existing UE context 0x%06x\n", assoc_id, enb_ue_s1ap_id); /*MessageDef *msg_complete_p; msg_complete_p = itti_alloc_new_message(TASK_RRC_ENB, S1AP_UE_CONTEXT_RELEASE_COMPLETE); S1AP_UE_CONTEXT_RELEASE_COMPLETE(msg_complete_p).eNB_ue_s1ap_id = enb_ue_s1ap_id; itti_send_msg_to_task(TASK_S1AP, ue_desc_p->eNB_instance->instance <=> 0, msg_complete_p); */ return -1; } else { MSC_LOG_TX_MESSAGE( MSC_S1AP_ENB, MSC_RRC_ENB, NULL,0, "0 S1AP_UE_CONTEXT_RELEASE_COMMAND/%d eNB_ue_s1ap_id "S1AP_UE_ID_FMT" ", enb_ue_s1ap_id); message_p = itti_alloc_new_message(TASK_S1AP, S1AP_UE_CONTEXT_RELEASE_COMMAND); S1AP_UE_CONTEXT_RELEASE_COMMAND(message_p).eNB_ue_s1ap_id = enb_ue_s1ap_id; itti_send_msg_to_task(TASK_RRC_ENB, ue_desc_p->eNB_instance->instance, message_p); return 0; } break; #warning "TODO mapping mme_ue_s1ap_id enb_ue_s1ap_id?" case S1ap_UE_S1AP_IDs_PR_mME_UE_S1AP_ID: mme_ue_s1ap_id = ueContextReleaseCommand_p->uE_S1AP_IDs.choice.mME_UE_S1AP_ID; S1AP_ERROR("TO DO mapping mme_ue_s1ap_id enb_ue_s1ap_id"); case S1ap_UE_S1AP_IDs_PR_NOTHING: default: S1AP_ERROR("S1AP_UE_CONTEXT_RELEASE_COMMAND not processed, missing info elements"); return -1; } }
static int s1ap_eNB_handle_initial_context_request(uint32_t assoc_id, uint32_t stream, struct s1ap_message_s *s1ap_message_p) { int i; s1ap_eNB_mme_data_t *mme_desc_p = NULL; s1ap_eNB_ue_context_t *ue_desc_p = NULL; MessageDef *message_p = NULL; S1ap_InitialContextSetupRequestIEs_t *initialContextSetupRequest_p; DevAssert(s1ap_message_p != NULL); initialContextSetupRequest_p = &s1ap_message_p->msg.s1ap_InitialContextSetupRequestIEs; if ((mme_desc_p = s1ap_eNB_get_MME(NULL, assoc_id, 0)) == NULL) { S1AP_ERROR("[SCTP %d] Received initial context setup request 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, initialContextSetupRequest_p->eNB_UE_S1AP_ID)) == NULL) { S1AP_ERROR("[SCTP %d] Received initial context setup request for non " "existing UE context 0x%06x\n", assoc_id, initialContextSetupRequest_p->eNB_UE_S1AP_ID); return -1; } /* Initial context request = UE-related procedure -> stream != 0 */ if (stream == 0) { S1AP_ERROR("[SCTP %d] Received UE-related procedure on stream (%d)\n", assoc_id, stream); return -1; } ue_desc_p->rx_stream = stream; ue_desc_p->mme_ue_s1ap_id = initialContextSetupRequest_p->mme_ue_s1ap_id; message_p = itti_alloc_new_message(TASK_S1AP, S1AP_INITIAL_CONTEXT_SETUP_REQ); S1AP_INITIAL_CONTEXT_SETUP_REQ(message_p).ue_initial_id = ue_desc_p->ue_initial_id; ue_desc_p->ue_initial_id = 0; S1AP_INITIAL_CONTEXT_SETUP_REQ(message_p).eNB_ue_s1ap_id = ue_desc_p->eNB_ue_s1ap_id; S1AP_INITIAL_CONTEXT_SETUP_REQ(message_p).nb_of_e_rabs = initialContextSetupRequest_p->e_RABToBeSetupListCtxtSUReq.s1ap_E_RABToBeSetupItemCtxtSUReq.count; S1AP_INITIAL_CONTEXT_SETUP_REQ(message_p).ue_ambr.br_ul = 64;// TO DO(bitrate_t)(initialContextSetupRequest_p->uEaggregateMaximumBitrate.uEaggregateMaximumBitRateUL); S1AP_INITIAL_CONTEXT_SETUP_REQ(message_p).ue_ambr.br_dl = 1024;//(bitrate_t)(initialContextSetupRequest_p->uEaggregateMaximumBitrate.uEaggregateMaximumBitRateDL); S1AP_INITIAL_CONTEXT_SETUP_REQ(message_p).security_capabilities.encryption_algorithms = BIT_STRING_to_uint16(&initialContextSetupRequest_p->ueSecurityCapabilities.encryptionAlgorithms); S1AP_INITIAL_CONTEXT_SETUP_REQ(message_p).security_capabilities.integrity_algorithms = BIT_STRING_to_uint16(&initialContextSetupRequest_p->ueSecurityCapabilities.integrityProtectionAlgorithms); /* Copy the security key */ memcpy(&S1AP_INITIAL_CONTEXT_SETUP_REQ(message_p).security_key, initialContextSetupRequest_p->securityKey.buf, initialContextSetupRequest_p->securityKey.size); for (i = 0; i < initialContextSetupRequest_p->e_RABToBeSetupListCtxtSUReq.s1ap_E_RABToBeSetupItemCtxtSUReq.count; i++) { S1ap_E_RABToBeSetupItemCtxtSUReq_t *item_p; item_p = (S1ap_E_RABToBeSetupItemCtxtSUReq_t *)initialContextSetupRequest_p->e_RABToBeSetupListCtxtSUReq.s1ap_E_RABToBeSetupItemCtxtSUReq.array[i]; S1AP_INITIAL_CONTEXT_SETUP_REQ(message_p).e_rab_param[i].e_rab_id = item_p->e_RAB_ID; if (item_p->nAS_PDU != NULL) { /* Only copy NAS pdu if present */ S1AP_INITIAL_CONTEXT_SETUP_REQ(message_p).e_rab_param[i].nas_pdu.length = item_p->nAS_PDU->size; S1AP_INITIAL_CONTEXT_SETUP_REQ(message_p).e_rab_param[i].nas_pdu.buffer = malloc(sizeof(uint8_t) * item_p->nAS_PDU->size); memcpy(S1AP_INITIAL_CONTEXT_SETUP_REQ(message_p).e_rab_param[i].nas_pdu.buffer, item_p->nAS_PDU->buf, item_p->nAS_PDU->size); } else { S1AP_INITIAL_CONTEXT_SETUP_REQ(message_p).e_rab_param[i].nas_pdu.length = 0; S1AP_INITIAL_CONTEXT_SETUP_REQ(message_p).e_rab_param[i].nas_pdu.buffer = NULL; } /* Set the transport layer address */ memcpy(S1AP_INITIAL_CONTEXT_SETUP_REQ(message_p).e_rab_param[i].sgw_addr.buffer, item_p->transportLayerAddress.buf, item_p->transportLayerAddress.size); S1AP_INITIAL_CONTEXT_SETUP_REQ(message_p).e_rab_param[i].sgw_addr.length = item_p->transportLayerAddress.size * 8 - item_p->transportLayerAddress.bits_unused; /* 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); /* 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.allocation_retention_priority.priority_level = item_p->e_RABlevelQoSParameters.allocationRetentionPriority.priorityLevel; S1AP_INITIAL_CONTEXT_SETUP_REQ(message_p).e_rab_param[i].qos.allocation_retention_priority.pre_emp_capability = item_p->e_RABlevelQoSParameters.allocationRetentionPriority.pre_emptionCapability; S1AP_INITIAL_CONTEXT_SETUP_REQ(message_p).e_rab_param[i].qos.allocation_retention_priority.pre_emp_vulnerability = item_p->e_RABlevelQoSParameters.allocationRetentionPriority.pre_emptionVulnerability; } itti_send_msg_to_task(TASK_RRC_ENB, ue_desc_p->eNB_instance->instance, message_p); return 0; }
static int s1ap_eNB_decode_initiating_message(s1ap_message *message, S1ap_InitiatingMessage_t *initiating_p) { int ret = -1; MessageDef *message_p; char *message_string = NULL; size_t message_string_size; MessagesIds message_id; DevAssert(initiating_p != NULL); message_string = calloc(10000, sizeof(char)); s1ap_string_total_size = 0; message->procedureCode = initiating_p->procedureCode; message->criticality = initiating_p->criticality; switch(initiating_p->procedureCode) { case S1ap_ProcedureCode_id_downlinkNASTransport: ret = s1ap_decode_s1ap_downlinknastransporties( &message->msg.s1ap_DownlinkNASTransportIEs, &initiating_p->value); s1ap_xer_print_s1ap_downlinknastransport(s1ap_xer__print2sp, message_string, message); message_id = S1AP_DOWNLINK_NAS_LOG; 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_downlink_nas_log.size = message_string_size; memcpy(&message_p->ittiMsg.s1ap_downlink_nas_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_InitialContextSetup: ret = s1ap_decode_s1ap_initialcontextsetuprequesties( &message->msg.s1ap_InitialContextSetupRequestIEs, &initiating_p->value); s1ap_xer_print_s1ap_initialcontextsetuprequest(s1ap_xer__print2sp, message_string, message); message_id = S1AP_INITIAL_CONTEXT_SETUP_LOG; 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); break; case S1ap_ProcedureCode_id_UEContextRelease: ret = s1ap_decode_s1ap_uecontextreleasecommandies( &message->msg.s1ap_UEContextReleaseCommandIEs, &initiating_p->value); s1ap_xer_print_s1ap_uecontextreleasecommand(s1ap_xer__print2sp, message_string, message); message_id = S1AP_UE_CONTEXT_RELEASE_COMMAND_LOG; 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_ue_context_release_command_log.size = message_string_size; memcpy(&message_p->ittiMsg.s1ap_ue_context_release_command_log.text, message_string, message_string_size); itti_send_msg_to_task(TASK_UNKNOWN, INSTANCE_DEFAULT, message_p); free(message_string); break; default: S1AP_ERROR("Unknown procedure ID (%d) for initiating message\n", (int)initiating_p->procedureCode); AssertFatal( 0 , "Unknown procedure ID (%d) for initiating message\n", (int)initiating_p->procedureCode); return -1; } return ret; }
void *s1ap_eNB_task(void *arg) { MessageDef *received_msg = NULL; int result; S1AP_DEBUG("Starting S1AP layer\n"); s1ap_eNB_prepare_internal_data(); itti_mark_task_ready(TASK_S1AP); MSC_START_USE(); while (1) { itti_receive_msg(TASK_S1AP, &received_msg); switch (ITTI_MSG_ID(received_msg)) { case TERMINATE_MESSAGE: itti_exit_task(); break; case S1AP_REGISTER_ENB_REQ: { /* Register a new eNB. * in Virtual mode eNBs will be distinguished using the mod_id/ * Each eNB has to send an S1AP_REGISTER_ENB message with its * own parameters. */ s1ap_eNB_handle_register_eNB(ITTI_MESSAGE_GET_INSTANCE(received_msg), &S1AP_REGISTER_ENB_REQ(received_msg)); } break; case SCTP_NEW_ASSOCIATION_RESP: { s1ap_eNB_handle_sctp_association_resp(ITTI_MESSAGE_GET_INSTANCE(received_msg), &received_msg->ittiMsg.sctp_new_association_resp); } break; case SCTP_DATA_IND: { s1ap_eNB_handle_sctp_data_ind(&received_msg->ittiMsg.sctp_data_ind); } break; case S1AP_NAS_FIRST_REQ: { s1ap_eNB_handle_nas_first_req(ITTI_MESSAGE_GET_INSTANCE(received_msg), &S1AP_NAS_FIRST_REQ(received_msg)); } break; case S1AP_UPLINK_NAS: { s1ap_eNB_nas_uplink(ITTI_MESSAGE_GET_INSTANCE(received_msg), &S1AP_UPLINK_NAS(received_msg)); } break; case S1AP_UE_CAPABILITIES_IND: { s1ap_eNB_ue_capabilities(ITTI_MESSAGE_GET_INSTANCE(received_msg), &S1AP_UE_CAPABILITIES_IND(received_msg)); } break; case S1AP_INITIAL_CONTEXT_SETUP_RESP: { s1ap_eNB_initial_ctxt_resp(ITTI_MESSAGE_GET_INSTANCE(received_msg), &S1AP_INITIAL_CONTEXT_SETUP_RESP(received_msg)); } break; case S1AP_E_RAB_SETUP_RESP: { s1ap_eNB_e_rab_setup_resp(ITTI_MESSAGE_GET_INSTANCE(received_msg), &S1AP_E_RAB_SETUP_RESP(received_msg)); } break; case S1AP_NAS_NON_DELIVERY_IND: { 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; case S1AP_UE_CONTEXT_RELEASE_REQ: { s1ap_eNB_instance_t *s1ap_eNB_instance_p = NULL; // test struct s1ap_eNB_ue_context_s *ue_context_p = NULL; // test s1ap_ue_context_release_req(ITTI_MESSAGE_GET_INSTANCE(received_msg), &S1AP_UE_CONTEXT_RELEASE_REQ(received_msg)); s1ap_eNB_instance_p = s1ap_eNB_get_instance(ITTI_MESSAGE_GET_INSTANCE(received_msg)); // test DevAssert(s1ap_eNB_instance_p != NULL); // test if ((ue_context_p = s1ap_eNB_get_ue_context(s1ap_eNB_instance_p, S1AP_UE_CONTEXT_RELEASE_REQ(received_msg).eNB_ue_s1ap_id)) == NULL) { // test /* The context for this eNB ue s1ap id doesn't exist in the map of eNB UEs */ S1AP_ERROR("Failed to find ue context associated with eNB ue s1ap id: %u\n", S1AP_UE_CONTEXT_RELEASE_REQ(received_msg).eNB_ue_s1ap_id); // test } // test } break; default: S1AP_ERROR("Received unhandled message: %d:%s\n", ITTI_MSG_ID(received_msg), ITTI_MSG_NAME(received_msg)); break; } result = itti_free (ITTI_MSG_ORIGIN_ID(received_msg), received_msg); AssertFatal (result == EXIT_SUCCESS, "Failed to free memory (%d)!\n", result); received_msg = NULL; } return NULL; }