void s1ap_eNB_handle_sctp_association_resp(instance_t instance, sctp_new_association_resp_t *sctp_new_association_resp) { s1ap_eNB_instance_t *instance_p; s1ap_eNB_mme_data_t *s1ap_mme_data_p; DevAssert(sctp_new_association_resp != NULL); instance_p = s1ap_eNB_get_instance(instance); DevAssert(instance_p != NULL); s1ap_mme_data_p = s1ap_eNB_get_MME(instance_p, -1, sctp_new_association_resp->ulp_cnx_id); DevAssert(s1ap_mme_data_p != NULL); if (sctp_new_association_resp->sctp_state != SCTP_STATE_ESTABLISHED) { S1AP_WARN("Received unsuccessful result for SCTP association (%u), instance %d, cnx_id %u\n", sctp_new_association_resp->sctp_state, instance, sctp_new_association_resp->ulp_cnx_id); s1ap_handle_s1_setup_message(s1ap_mme_data_p, sctp_new_association_resp->sctp_state == SCTP_STATE_SHUTDOWN); return; } /* Update parameters */ s1ap_mme_data_p->assoc_id = sctp_new_association_resp->assoc_id; s1ap_mme_data_p->in_streams = sctp_new_association_resp->in_streams; s1ap_mme_data_p->out_streams = sctp_new_association_resp->out_streams; /* Prepare new S1 Setup Request */ s1ap_eNB_generate_s1_setup_request(instance_p, s1ap_mme_data_p); }
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; }
//------------------------------------------------------------------------------ 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_handle_nas_first_req( instance_t instance, s1ap_nas_first_req_t *s1ap_nas_first_req_p) //------------------------------------------------------------------------------ { s1ap_eNB_instance_t *instance_p = NULL; struct s1ap_eNB_mme_data_s *mme_desc_p = NULL; struct s1ap_eNB_ue_context_s *ue_desc_p = NULL; s1ap_message message; S1ap_InitialUEMessageIEs_t *initial_ue_message_p = NULL; uint8_t *buffer = NULL; uint32_t length = 0; DevAssert(s1ap_nas_first_req_p != NULL); /* Retrieve the S1AP eNB instance associated with Mod_id */ instance_p = s1ap_eNB_get_instance(instance); DevAssert(instance_p != NULL); memset(&message, 0, sizeof(s1ap_message)); message.direction = S1AP_PDU_PR_initiatingMessage; message.procedureCode = S1ap_ProcedureCode_id_initialUEMessage; initial_ue_message_p = &message.msg.s1ap_InitialUEMessageIEs; /* Select the MME corresponding to the provided GUMMEI. */ if (s1ap_nas_first_req_p->ue_identity.presenceMask & UE_IDENTITIES_gummei) { mme_desc_p = s1ap_eNB_nnsf_select_mme_by_gummei( instance_p, s1ap_nas_first_req_p->establishment_cause, s1ap_nas_first_req_p->ue_identity.gummei); } if (mme_desc_p == NULL) { /* Select the MME corresponding to the provided s-TMSI. */ if (s1ap_nas_first_req_p->ue_identity.presenceMask & UE_IDENTITIES_s_tmsi) { mme_desc_p = s1ap_eNB_nnsf_select_mme_by_mme_code( instance_p, s1ap_nas_first_req_p->establishment_cause, s1ap_nas_first_req_p->ue_identity.s_tmsi.mme_code); } } if (mme_desc_p == NULL) { /* * If no MME corresponds to the GUMMEI or the s-TMSI, selects the MME with the * highest capacity. */ mme_desc_p = s1ap_eNB_nnsf_select_mme( instance_p, s1ap_nas_first_req_p->establishment_cause); } if (mme_desc_p == NULL) { /* * In case eNB has no MME associated, the eNB should inform RRC and discard * this request. */ S1AP_WARN("No MME is associated to the eNB\n"); // TODO: Inform RRC return -1; } /* The eNB should allocate a unique eNB UE S1AP ID for this UE. The value * will be used for the duration of the connectivity. */ ue_desc_p = s1ap_eNB_allocate_new_UE_context(); DevAssert(ue_desc_p != NULL); /* Keep a reference to the selected MME */ ue_desc_p->mme_ref = mme_desc_p; ue_desc_p->ue_initial_id = s1ap_nas_first_req_p->ue_initial_id; ue_desc_p->eNB_instance = instance_p; do { struct s1ap_eNB_ue_context_s *collision_p; /* Peek a random value for the eNB_ue_s1ap_id */ ue_desc_p->eNB_ue_s1ap_id = (random() + random()) & 0x00ffffff; if ((collision_p = RB_INSERT(s1ap_ue_map, &instance_p->s1ap_ue_head, ue_desc_p)) == NULL) { S1AP_DEBUG("Found usable eNB_ue_s1ap_id: 0x%06x %d(10)\n", ue_desc_p->eNB_ue_s1ap_id, ue_desc_p->eNB_ue_s1ap_id); /* Break the loop as the id is not already used by another UE */ break; } } while(1); initial_ue_message_p->eNB_UE_S1AP_ID = ue_desc_p->eNB_ue_s1ap_id; /* Prepare the NAS PDU */ initial_ue_message_p->nas_pdu.buf = s1ap_nas_first_req_p->nas_pdu.buffer; initial_ue_message_p->nas_pdu.size = s1ap_nas_first_req_p->nas_pdu.length; /* Set the establishment cause according to those provided by RRC */ DevCheck(s1ap_nas_first_req_p->establishment_cause < RRC_CAUSE_LAST, s1ap_nas_first_req_p->establishment_cause, RRC_CAUSE_LAST, 0); initial_ue_message_p->rrC_Establishment_Cause = s1ap_nas_first_req_p->establishment_cause; if (s1ap_nas_first_req_p->ue_identity.presenceMask & UE_IDENTITIES_s_tmsi) { S1AP_DEBUG("S_TMSI_PRESENT\n"); initial_ue_message_p->presenceMask |= S1AP_INITIALUEMESSAGEIES_S_TMSI_PRESENT; MME_CODE_TO_OCTET_STRING(s1ap_nas_first_req_p->ue_identity.s_tmsi.mme_code, &initial_ue_message_p->s_tmsi.mMEC); M_TMSI_TO_OCTET_STRING(s1ap_nas_first_req_p->ue_identity.s_tmsi.m_tmsi, &initial_ue_message_p->s_tmsi.m_TMSI); } if (s1ap_nas_first_req_p->ue_identity.presenceMask & UE_IDENTITIES_gummei) { S1AP_DEBUG("GUMMEI_ID_PRESENT\n"); initial_ue_message_p->presenceMask |= S1AP_INITIALUEMESSAGEIES_GUMMEI_ID_PRESENT; MCC_MNC_TO_PLMNID( s1ap_nas_first_req_p->ue_identity.gummei.mcc, s1ap_nas_first_req_p->ue_identity.gummei.mnc, s1ap_nas_first_req_p->ue_identity.gummei.mnc_len, &initial_ue_message_p->gummei_id.pLMN_Identity); MME_GID_TO_OCTET_STRING(s1ap_nas_first_req_p->ue_identity.gummei.mme_group_id, &initial_ue_message_p->gummei_id.mME_Group_ID); MME_CODE_TO_OCTET_STRING(s1ap_nas_first_req_p->ue_identity.gummei.mme_code, &initial_ue_message_p->gummei_id.mME_Code); } /* Assuming TAI is the TAI from the cell */ INT16_TO_OCTET_STRING(instance_p->tac, &initial_ue_message_p->tai.tAC); MCC_MNC_TO_PLMNID(instance_p->mcc, instance_p->mnc, instance_p->mnc_digit_length, &initial_ue_message_p->tai.pLMNidentity); /* Set the EUTRAN CGI * The cell identity is defined on 28 bits but as we use macro enb id, * we have to pad. */ #warning "TODO get cell id from RRC" MACRO_ENB_ID_TO_CELL_IDENTITY(instance_p->eNB_id, 0, // Cell ID &initial_ue_message_p->eutran_cgi.cell_ID); MCC_MNC_TO_TBCD(instance_p->mcc, instance_p->mnc, instance_p->mnc_digit_length, &initial_ue_message_p->eutran_cgi.pLMNidentity); if (s1ap_eNB_encode_pdu(&message, &buffer, &length) < 0) { /* Failed to encode message */ DevMessage("Failed to encode initial UE message\n"); } /* Update the current S1AP UE state */ ue_desc_p->ue_state = S1AP_UE_WAITING_CSR; /* Assign a stream for this UE : * From 3GPP 36.412 7)Transport layers: * Within the SCTP association established between one MME and eNB pair: * - a single pair of stream identifiers shall be reserved for the sole use * of S1AP elementary procedures that utilize non UE-associated signalling. * - At least one pair of stream identifiers shall be reserved for the sole use * of S1AP elementary procedures that utilize UE-associated signallings. * However a few pairs (i.e. more than one) should be reserved. * - A single UE-associated signalling shall use one SCTP stream and * the stream should not be changed during the communication of the * UE-associated signalling. */ mme_desc_p->nextstream = (mme_desc_p->nextstream + 1) % mme_desc_p->out_streams; if ((mme_desc_p->nextstream == 0) && (mme_desc_p->out_streams > 1)) { mme_desc_p->nextstream += 1; } ue_desc_p->tx_stream = mme_desc_p->nextstream; MSC_LOG_TX_MESSAGE( MSC_S1AP_ENB, MSC_S1AP_MME, (const char *)NULL, 0, MSC_AS_TIME_FMT" initialUEMessage initiatingMessage eNB_ue_s1ap_id %u", 0,0,//MSC_AS_TIME_ARGS(ctxt_pP), initial_ue_message_p->eNB_UE_S1AP_ID); /* Send encoded message over sctp */ s1ap_eNB_itti_send_sctp_data_req(instance_p->instance, mme_desc_p->assoc_id, buffer, length, ue_desc_p->tx_stream); return 0; }
//------------------------------------------------------------------------------ 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; }
static void s1ap_eNB_register_mme(s1ap_eNB_instance_t *instance_p, net_ip_address_t *mme_ip_address, net_ip_address_t *local_ip_addr, uint16_t in_streams, uint16_t out_streams) { MessageDef *message_p = NULL; sctp_new_association_req_t *sctp_new_association_req_p = NULL; s1ap_eNB_mme_data_t *s1ap_mme_data_p = NULL; struct s1ap_eNB_mme_data_s *mme = NULL; DevAssert(instance_p != NULL); DevAssert(mme_ip_address != NULL); message_p = itti_alloc_new_message(TASK_S1AP, SCTP_NEW_ASSOCIATION_REQ); sctp_new_association_req_p = &message_p->ittiMsg.sctp_new_association_req; sctp_new_association_req_p->port = S1AP_PORT_NUMBER; sctp_new_association_req_p->ppid = S1AP_SCTP_PPID; sctp_new_association_req_p->in_streams = in_streams; sctp_new_association_req_p->out_streams = out_streams; memcpy(&sctp_new_association_req_p->remote_address, mme_ip_address, sizeof(*mme_ip_address)); memcpy(&sctp_new_association_req_p->local_address, local_ip_addr, sizeof(*local_ip_addr)); S1AP_INFO("[eNB %d] check the mme registration state\n",instance_p->instance); mme = s1ap_eNB_get_MME_from_instance(instance_p); if ( mme == NULL ) { /* Create new MME descriptor */ s1ap_mme_data_p = calloc(1, sizeof(*s1ap_mme_data_p)); DevAssert(s1ap_mme_data_p != NULL); s1ap_mme_data_p->cnx_id = s1ap_eNB_fetch_add_global_cnx_id(); sctp_new_association_req_p->ulp_cnx_id = s1ap_mme_data_p->cnx_id; s1ap_mme_data_p->assoc_id = -1; s1ap_mme_data_p->s1ap_eNB_instance = instance_p; STAILQ_INIT(&s1ap_mme_data_p->served_gummei); /* Insert the new descriptor in list of known MME * but not yet associated. */ RB_INSERT(s1ap_mme_map, &instance_p->s1ap_mme_head, s1ap_mme_data_p); s1ap_mme_data_p->state = S1AP_ENB_STATE_WAITING; instance_p->s1ap_mme_nb ++; instance_p->s1ap_mme_pending_nb ++; } else if (mme->state == S1AP_ENB_STATE_WAITING) { instance_p->s1ap_mme_pending_nb ++; sctp_new_association_req_p->ulp_cnx_id = mme->cnx_id; S1AP_INFO("[eNB %d] MME already registered, retrive the data (state %d, cnx %d, mme_nb %d, mme_pending_nb %d)\n", instance_p->instance, mme->state, mme->cnx_id, instance_p->s1ap_mme_nb, instance_p->s1ap_mme_pending_nb); /*s1ap_mme_data_p->cnx_id = mme->cnx_id; sctp_new_association_req_p->ulp_cnx_id = mme->cnx_id; s1ap_mme_data_p->assoc_id = -1; s1ap_mme_data_p->s1ap_eNB_instance = instance_p; */ } else { S1AP_WARN("[eNB %d] MME already registered but not in the waiting state, retrive the data (state %d, cnx %d, mme_nb %d, mme_pending_nb %d)\n", instance_p->instance, mme->state, mme->cnx_id, instance_p->s1ap_mme_nb, instance_p->s1ap_mme_pending_nb); } itti_send_msg_to_task(TASK_SCTP, instance_p->instance, message_p); }
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; }