//------------------------------------------------------------------------------ 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 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; }