Files
openairinterface5g/openair-cn/S1AP/s1ap_mme_nas_procedures.c
T

766 lines
30 KiB
C

/*******************************************************************************
OpenAirInterface
Copyright(c) 1999 - 2014 Eurecom
OpenAirInterface is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenAirInterface is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with OpenAirInterface.The full GNU General Public License is
included in this distribution in the file called "COPYING". If not,
see <http://www.gnu.org/licenses/>.
Contact Information
OpenAirInterface Admin: openair_admin@eurecom.fr
OpenAirInterface Tech : openair_tech@eurecom.fr
OpenAirInterface Dev : openair4g-devel@eurecom.fr
Address : Eurecom, Compus SophiaTech 450, route des chappes, 06451 Biot, France.
*******************************************************************************/
#include <stdio.h>
#include <stdint.h>
#include "s1ap_common.h"
#include "s1ap_ies_defs.h"
#include "s1ap_mme_encoder.h"
#include "s1ap_mme_handlers.h"
#include "s1ap_mme_nas_procedures.h"
#include "s1ap_mme_retransmission.h"
#include "s1ap_mme_itti_messaging.h"
#include "s1ap_mme.h"
#include "intertask_interface.h"
#include "timer.h"
#include "assertions.h"
#include "conversions.h"
#include "msc.h"
/* Every time a new UE is associated, increment this variable.
* But care if it wraps to increment also the mme_ue_s1ap_id_has_wrapped
* variable. Limit: UINT32_MAX (in stdint.h).
*/
static uint32_t mme_ue_s1ap_id = 0;
static uint8_t mme_ue_s1ap_id_has_wrapped = 0;
extern const char *s1ap_direction2String[];
int s1ap_mme_handle_initial_ue_message(uint32_t assoc_id, uint32_t stream,
struct s1ap_message_s *message)
{
S1ap_InitialUEMessageIEs_t *initialUEMessage_p;
ue_description_t *ue_ref;
eNB_description_t *eNB_ref;
uint32_t eNB_ue_s1ap_id;
initialUEMessage_p = &message->msg.s1ap_InitialUEMessageIEs;
MSC_LOG_RX_MESSAGE(
MSC_S1AP_MME,
MSC_S1AP_ENB,
NULL,0,
"0 initialUEMessage/%s assoc_id %u stream %u "S1AP_UE_ID_FMT" ",
s1ap_direction2String[message->direction],
assoc_id, stream, initialUEMessage_p->eNB_UE_S1AP_ID);
if ((eNB_ref = s1ap_is_eNB_assoc_id_in_list(assoc_id)) == NULL) {
S1AP_DEBUG("Unkwnon eNB on assoc_id %d\n", assoc_id);
return -1;
}
// eNB UE S1AP ID is limited to 24 bits
eNB_ue_s1ap_id = (uint32_t)(initialUEMessage_p->eNB_UE_S1AP_ID & 0x00ffffff);
S1AP_DEBUG("New Initial UE message received with eNB UE S1AP ID: "S1AP_UE_ID_FMT"\n",
eNB_ue_s1ap_id);
ue_ref = s1ap_is_ue_eNB_id_in_list(eNB_ref, eNB_ue_s1ap_id);
if (ue_ref == NULL) {
uint16_t tac = 0;
/* This UE eNB Id has currently no known s1 association.
* Create new UE context by associating new mme_ue_s1ap_id.
* Update eNB UE list.
* Forward message to NAS.
*/
if ((ue_ref = s1ap_new_ue(assoc_id)) == NULL)
// If we failed to allocate a new UE return -1
{
return -1;
}
ue_ref->s1_ue_state = S1AP_UE_WAITING_CSR;
ue_ref->eNB_ue_s1ap_id = eNB_ue_s1ap_id;
ue_ref->mme_ue_s1ap_id = (uint32_t)ue_ref;
// On which stream we received the message
ue_ref->sctp_stream_recv = stream;
ue_ref->sctp_stream_send = ue_ref->eNB->next_sctp_stream;
/* Increment the sctp stream for the eNB association.
* If the next sctp stream is >= outstream negociated between eNB and MME,
* wrap to first stream.
* TODO: search for the first available stream instead.
*/
if (ue_ref->eNB->next_sctp_stream++ >= ue_ref->eNB->outstreams) {
ue_ref->eNB->next_sctp_stream = 1;
}
/* Increment the unique UE mme s1ap id and
* take care about overflow case.
*/
if (mme_ue_s1ap_id_has_wrapped == 0) {
mme_ue_s1ap_id++;
if (mme_ue_s1ap_id == 0) {
mme_ue_s1ap_id_has_wrapped = 1;
}
} else {
/* TODO: should take the first available mme_ue_s1ap_id instead of
* the mme_ue_s1ap_id variable.
*/
DevMessage("mme ue s1ap id has wrapped -> case not handled\n");
}
s1ap_dump_eNB(ue_ref->eNB);
OCTET_STRING_TO_TAC(&initialUEMessage_p->tai.tAC, tac);
/* We received the first NAS transport message: initial UE message.
* Send a NAS ESTABLISH IND to NAS layer
*/
#if defined(ORIGINAL_CODE)
s1ap_mme_itti_nas_establish_ind(
ue_ref->mme_ue_s1ap_id,
initialUEMessage_p->nas_pdu.buf,
initialUEMessage_p->nas_pdu.size,
initialUEMessage_p->rrC_Establishment_Cause,
tac);
#else
s1ap_mme_itti_mme_app_establish_ind(
ue_ref->mme_ue_s1ap_id,
initialUEMessage_p->nas_pdu.buf,
initialUEMessage_p->nas_pdu.size,
initialUEMessage_p->rrC_Establishment_Cause,
tac);
#endif
}
return 0;
}
int s1ap_mme_handle_uplink_nas_transport(uint32_t assoc_id, uint32_t stream,
struct s1ap_message_s *message)
{
S1ap_UplinkNASTransportIEs_t *uplinkNASTransport_p;
ue_description_t *ue_ref;
uplinkNASTransport_p = &message->msg.s1ap_UplinkNASTransportIEs;
MSC_LOG_RX_MESSAGE(
MSC_S1AP_MME,
MSC_S1AP_ENB,
NULL,0,
"0 uplinkNASTransport/%s mme_ue_s1ap_id "S1AP_UE_ID_FMT" eNB_ue_s1ap_id "S1AP_UE_ID_FMT" nas len %u",
s1ap_direction2String[message->direction],
uplinkNASTransport_p->mme_ue_s1ap_id,
uplinkNASTransport_p->eNB_UE_S1AP_ID,
uplinkNASTransport_p->nas_pdu.size);
if ((ue_ref = s1ap_is_ue_mme_id_in_list(uplinkNASTransport_p->mme_ue_s1ap_id))
== NULL) {
S1AP_DEBUG("No UE is attached to this mme UE s1ap id: "S1AP_UE_ID_FMT"\n",
(int)uplinkNASTransport_p->mme_ue_s1ap_id);
return -1;
}
if (ue_ref->s1_ue_state != S1AP_UE_CONNECTED) {
S1AP_DEBUG("Received uplink NAS transport while UE in state != S1AP_UE_CONNECTED\n");
return -1;
}
//TODO: forward NAS PDU to NAS
#if defined(DISABLE_USE_NAS)
DevMessage("Can't go further (TODO)\n");
#else
s1ap_mme_itti_nas_uplink_ind(uplinkNASTransport_p->mme_ue_s1ap_id, uplinkNASTransport_p->nas_pdu.buf,
uplinkNASTransport_p->nas_pdu.size);
#endif
return 0;
}
int s1ap_mme_handle_nas_non_delivery(uint32_t assoc_id, uint32_t stream,
struct s1ap_message_s *message)
{
S1ap_NASNonDeliveryIndication_IEs_t *nasNonDeliveryIndication_p = NULL;
ue_description_t *ue_ref = NULL;
/* UE associated signalling on stream == 0 is not valid. */
if (stream == 0) {
S1AP_DEBUG("Received new nas non delivery on stream == 0\n");
return -1;
}
nasNonDeliveryIndication_p = &message->msg.s1ap_NASNonDeliveryIndication_IEs;
MSC_LOG_RX_MESSAGE(
MSC_S1AP_MME,
MSC_S1AP_ENB,
NULL,0,
"0 NASNonDeliveryIndication/%s mme_ue_s1ap_id "S1AP_UE_ID_FMT" eNB_ue_s1ap_id "S1AP_UE_ID_FMT" cause %u nas len %u",
s1ap_direction2String[message->direction],
nasNonDeliveryIndication_p->mme_ue_s1ap_id,
nasNonDeliveryIndication_p->eNB_UE_S1AP_ID,
nasNonDeliveryIndication_p->cause,
nasNonDeliveryIndication_p->nas_pdu.size);
if ((ue_ref = s1ap_is_ue_mme_id_in_list(nasNonDeliveryIndication_p->mme_ue_s1ap_id))
== NULL) {
S1AP_DEBUG("No UE is attached to this mme UE s1ap id: "S1AP_UE_ID_FMT"\n",
(int)nasNonDeliveryIndication_p->mme_ue_s1ap_id);
return -1;
}
if (ue_ref->s1_ue_state != S1AP_UE_CONNECTED) {
S1AP_DEBUG("Received uplink NASNonDeliveryIndication while UE in state != S1AP_UE_CONNECTED\n");
return -1;
}
//TODO: forward NAS PDU to NAS
s1ap_mme_itti_nas_non_delivery_ind(
nasNonDeliveryIndication_p->mme_ue_s1ap_id,
nasNonDeliveryIndication_p->nas_pdu.buf,
nasNonDeliveryIndication_p->nas_pdu.size);
return 0;
}
int s1ap_generate_downlink_nas_transport(const uint32_t ue_id, void * const data,
const uint32_t size)
{
ue_description_t *ue_ref;
uint8_t *buffer_p;
uint32_t length;
if ((ue_ref = s1ap_is_ue_mme_id_in_list(ue_id)) == NULL) {
/* If the UE-associated logical S1-connection is not established,
* the MME shall allocate a unique MME UE S1AP ID to be used for the UE.
*/
S1AP_DEBUG("Unknown UE MME ID "S1AP_UE_ID_FMT", This case is not handled right now\n", ue_id);
return -1;
} else {
/* We have fount the UE in the list.
* Create new IE list message and encode it.
*/
S1ap_DownlinkNASTransportIEs_t *downlinkNasTransport = NULL;
s1ap_message message;
memset(&message, 0, sizeof(s1ap_message));
message.procedureCode = S1ap_ProcedureCode_id_downlinkNASTransport;
message.direction = S1AP_PDU_PR_initiatingMessage;
ue_ref->s1_ue_state = S1AP_UE_CONNECTED;
downlinkNasTransport = &message.msg.s1ap_DownlinkNASTransportIEs;
/* Setting UE informations with the ones fount in ue_ref */
downlinkNasTransport->mme_ue_s1ap_id = ue_ref->mme_ue_s1ap_id;
downlinkNasTransport->eNB_UE_S1AP_ID = ue_ref->eNB_ue_s1ap_id;
/* Fill in the NAS pdu */
OCTET_STRING_fromBuf(&downlinkNasTransport->nas_pdu, (char*)data, size);
if (s1ap_mme_encode_pdu(&message, &buffer_p, &length) < 0) {
// TODO: handle something
return -1;
}
S1AP_DEBUG("Send S1ap_ProcedureCode_id_downlinkNASTransport ue_id = "S1AP_UE_ID_FMT" mme_ue_s1ap_id = "S1AP_UE_ID_FMT" eNB_UE_S1AP_ID = "S1AP_UE_ID_FMT"\n",
ue_id,
downlinkNasTransport->mme_ue_s1ap_id,
downlinkNasTransport->eNB_UE_S1AP_ID);
MSC_LOG_TX_MESSAGE(
MSC_S1AP_MME,
MSC_S1AP_ENB,
NULL,0,
"0 downlinkNASTransport/initiatingMessage ue_id "S1AP_UE_ID_FMT" mme_ue_s1ap_id "S1AP_UE_ID_FMT" eNB_ue_s1ap_id"S1AP_UE_ID_FMT" nas length %u",
ue_id,
downlinkNasTransport->mme_ue_s1ap_id,
downlinkNasTransport->eNB_UE_S1AP_ID,
size);
s1ap_mme_itti_send_sctp_request(buffer_p, length,
ue_ref->eNB->sctp_assoc_id,
ue_ref->sctp_stream_send);
}
return 0;
}
#if defined(DISABLE_USE_NAS)
int s1ap_handle_attach_accepted(nas_attach_accept_t *attach_accept_p)
{
/* We received create session response from S-GW on S11 interface abstraction.
* At least one bearer has been established. We can now send s1ap initial context setup request
* message to eNB.
*/
uint8_t supportedAlgorithms[] = { 0x00, 0x02 };
uint8_t offset = 0;
uint8_t *buffer_p;
uint32_t length;
ue_description_t *ue_ref = NULL;
s1ap_message message;
s1ap_initial_ctxt_setup_req_t *initial_p;
S1ap_InitialContextSetupRequestIEs_t *initialContextSetupRequest_p;
S1ap_E_RABToBeSetupItemCtxtSUReq_t e_RABToBeSetup;
DevAssert(attach_accept_p != NULL);
initial_p = &attach_accept_p->transparent;
if ((ue_ref = s1ap_is_ue_mme_id_in_list(initial_p->mme_ue_s1ap_id)) == NULL) {
S1AP_DEBUG("This mme ue s1ap id ("S1AP_UE_ID_FMT") is not attached to any UE context\n",
initial_p->mme_ue_s1ap_id);
return -1;
}
/* Start the outcome response timer.
* When time is reached, MME consider that procedure outcome has failed.
*/
// timer_setup(mme_config.s1ap_config.outcome_drop_timer_sec, 0, TASK_S1AP, INSTANCE_DEFAULT,
// TIMER_ONE_SHOT,
// NULL,
// &ue_ref->outcome_response_timer_id);
/* Insert the timer in the MAP of mme_ue_s1ap_id <-> timer_id */
// s1ap_timer_insert(ue_ref->mme_ue_s1ap_id, ue_ref->outcome_response_timer_id);
memset(&message, 0, sizeof(s1ap_message));
memset(&e_RABToBeSetup, 0, sizeof(S1ap_E_RABToBeSetupItemCtxtSUReq_t));
message.procedureCode = S1ap_ProcedureCode_id_InitialContextSetup;
message.direction = S1AP_PDU_PR_initiatingMessage;
initialContextSetupRequest_p = &message.msg.s1ap_InitialContextSetupRequestIEs;
initialContextSetupRequest_p->mme_ue_s1ap_id = (unsigned long)ue_ref->mme_ue_s1ap_id;
initialContextSetupRequest_p->eNB_UE_S1AP_ID = (unsigned long)ue_ref->eNB_ue_s1ap_id;
/* uEaggregateMaximumBitrateDL and uEaggregateMaximumBitrateUL expressed in term of bits/sec */
initialContextSetupRequest_p->uEaggregateMaximumBitrate.uEaggregateMaximumBitRateDL = initial_p->ambr.br_dl;
initialContextSetupRequest_p->uEaggregateMaximumBitrate.uEaggregateMaximumBitRateUL = initial_p->ambr.br_ul;
e_RABToBeSetup.e_RAB_ID = initial_p->ebi;
e_RABToBeSetup.e_RABlevelQoSParameters.qCI = initial_p->qci;
e_RABToBeSetup.e_RABlevelQoSParameters.allocationRetentionPriority.priorityLevel
= initial_p->prio_level; //No priority
e_RABToBeSetup.e_RABlevelQoSParameters.allocationRetentionPriority.pre_emptionCapability
= initial_p->pre_emp_capability;
e_RABToBeSetup.e_RABlevelQoSParameters.allocationRetentionPriority.pre_emptionVulnerability
= initial_p->pre_emp_vulnerability;
/* Set the GTP-TEID. This is the S1-U S-GW TEID */
INT32_TO_OCTET_STRING(initial_p->teid, &e_RABToBeSetup.gTP_TEID);
/* S-GW IP address(es) for user-plane */
if ((initial_p->s_gw_address.pdn_type == IPv4) ||
(initial_p->s_gw_address.pdn_type == IPv4_AND_v6)) {
e_RABToBeSetup.transportLayerAddress.buf = calloc(4, sizeof(uint8_t));
/* Only IPv4 supported */
memcpy(e_RABToBeSetup.transportLayerAddress.buf,
initial_p->s_gw_address.address.ipv4_address,
4);
offset += 4;
e_RABToBeSetup.transportLayerAddress.size = 4;
e_RABToBeSetup.transportLayerAddress.bits_unused = 0;
}
if ((initial_p->s_gw_address.pdn_type == IPv6) ||
(initial_p->s_gw_address.pdn_type == IPv4_AND_v6)) {
if (offset == 0) {
/* Both IPv4 and IPv6 provided */
/* TODO: check memory allocation */
e_RABToBeSetup.transportLayerAddress.buf = calloc(16, sizeof(uint8_t));
} else {
/* Only IPv6 supported */
/* TODO: check memory allocation */
e_RABToBeSetup.transportLayerAddress.buf
= realloc(e_RABToBeSetup.transportLayerAddress.buf, (16 + offset) * sizeof(uint8_t));
}
memcpy(&e_RABToBeSetup.transportLayerAddress.buf[offset],
initial_p->s_gw_address.address.ipv6_address,
16);
e_RABToBeSetup.transportLayerAddress.size = 16 + offset;
e_RABToBeSetup.transportLayerAddress.bits_unused = 0;
}
ASN_SEQUENCE_ADD(&initialContextSetupRequest_p->e_RABToBeSetupListCtxtSUReq,
&e_RABToBeSetup);
initialContextSetupRequest_p->ueSecurityCapabilities.encryptionAlgorithms.buf =
(uint8_t *)supportedAlgorithms;
initialContextSetupRequest_p->ueSecurityCapabilities.encryptionAlgorithms.size = 2;
initialContextSetupRequest_p->ueSecurityCapabilities.encryptionAlgorithms.bits_unused
= 0;
initialContextSetupRequest_p->ueSecurityCapabilities.integrityProtectionAlgorithms.buf
= (uint8_t *)supportedAlgorithms;
initialContextSetupRequest_p->ueSecurityCapabilities.integrityProtectionAlgorithms.size
= 2;
initialContextSetupRequest_p->ueSecurityCapabilities.integrityProtectionAlgorithms.bits_unused
= 0;
initialContextSetupRequest_p->securityKey.buf = initial_p->keNB; /* 256 bits length */
initialContextSetupRequest_p->securityKey.size = 32;
initialContextSetupRequest_p->securityKey.bits_unused = 0;
if (s1ap_mme_encode_pdu(&message, &buffer_p, &length) < 0) {
// TODO: handle something
return -1;
}
return s1ap_mme_itti_send_sctp_request(buffer_p, length, ue_ref->eNB->sctp_assoc_id,
ue_ref->sctp_stream_send);
}
#else
//void s1ap_handle_conn_est_cnf(nas_conn_est_cnf_t *nas_conn_est_cnf_p)
//{
// /* We received create session response from S-GW on S11 interface abstraction.
// * At least one bearer has been established. We can now send s1ap initial context setup request
// * message to eNB.
// */
// uint8_t supportedAlgorithms[] = { 0x00, 0x00 };
// uint8_t offset = 0;
// uint8_t *buffer_p;
// uint32_t length, teid = 12;
//
// ue_description_t *ue_ref = NULL;
// s1ap_message message;
//
// S1ap_InitialContextSetupRequestIEs_t *initialContextSetupRequest_p;
// S1ap_E_RABToBeSetupItemCtxtSUReq_t e_RABToBeSetup;
// S1ap_NAS_PDU_t nas_pdu;
//
// DevAssert(nas_conn_est_cnf_p != NULL);
//
// if ((ue_ref = s1ap_is_ue_mme_id_in_list(nas_conn_est_cnf_p->UEid)) == NULL) {
// S1AP_DEBUG("This mme ue s1ap id (%08x) is not attached to any UE context\n",
// nas_conn_est_cnf_p->UEid);
// DevParam(nas_conn_est_cnf_p->UEid, 0, 0);
// }
//
// /* Start the outcome response timer.
// * When time is reached, MME consider that procedure outcome has failed.
// */
//// timer_setup(mme_config.s1ap_config.outcome_drop_timer_sec, 0, TASK_S1AP, INSTANCE_DEFAULT,
//// TIMER_ONE_SHOT,
//// NULL,
//// &ue_ref->outcome_response_timer_id);
// /* Insert the timer in the MAP of mme_ue_s1ap_id <-> timer_id */
//// s1ap_timer_insert(ue_ref->mme_ue_s1ap_id, ue_ref->outcome_response_timer_id);
//
// memset(&message, 0, sizeof(s1ap_message));
// memset(&e_RABToBeSetup, 0, sizeof(S1ap_E_RABToBeSetupItemCtxtSUReq_t));
//
// message.procedureCode = S1ap_ProcedureCode_id_InitialContextSetup;
// message.direction = S1AP_PDU_PR_initiatingMessage;
//
// initialContextSetupRequest_p = &message.msg.s1ap_InitialContextSetupRequestIEs;
//
// initialContextSetupRequest_p->mme_ue_s1ap_id = (unsigned long)ue_ref->mme_ue_s1ap_id;
// initialContextSetupRequest_p->eNB_UE_S1AP_ID = (unsigned long)ue_ref->eNB_ue_s1ap_id;
//
// /* uEaggregateMaximumBitrateDL and uEaggregateMaximumBitrateUL expressed in term of bits/sec */
//// initialContextSetupRequest_p->uEaggregateMaximumBitrate.uEaggregateMaximumBitRateDL = initial_p->ambr.br_dl;
//// initialContextSetupRequest_p->uEaggregateMaximumBitrate.uEaggregateMaximumBitRateUL = initial_p->ambr.br_ul;
//
// initialContextSetupRequest_p->uEaggregateMaximumBitrate.uEaggregateMaximumBitRateDL = 1024 * 1024;
// initialContextSetupRequest_p->uEaggregateMaximumBitrate.uEaggregateMaximumBitRateDL = 512 * 1024;
//
//// e_RABToBeSetup.e_RAB_ID = initial_p->ebi;
// e_RABToBeSetup.e_RAB_ID = 5;
//// e_RABToBeSetup.e_RABlevelQoSParameters.qCI = initial_p->qci;
// e_RABToBeSetup.e_RABlevelQoSParameters.qCI = 0;
//
// memset(&nas_pdu, 0, sizeof(nas_pdu));
//
// nas_pdu.size = nas_conn_est_cnf_p->nasMsg.length;
// nas_pdu.buf = nas_conn_est_cnf_p->nasMsg.data;
//
// e_RABToBeSetup.nAS_PDU = &nas_pdu;
// e_RABToBeSetup.e_RABlevelQoSParameters.allocationRetentionPriority.priorityLevel =
// S1ap_PriorityLevel_lowest;
// e_RABToBeSetup.e_RABlevelQoSParameters.allocationRetentionPriority.pre_emptionCapability =
// S1ap_Pre_emptionCapability_shall_not_trigger_pre_emption;
// e_RABToBeSetup.e_RABlevelQoSParameters.allocationRetentionPriority.pre_emptionVulnerability =
// S1ap_Pre_emptionVulnerability_not_pre_emptable;
// INT32_TO_OCTET_STRING(teid, &e_RABToBeSetup.gTP_TEID);
//// e_RABToBeSetup.e_RABlevelQoSParameters.allocationRetentionPriority.priorityLevel
//// = initial_p->prio_level; //No priority
//// e_RABToBeSetup.e_RABlevelQoSParameters.allocationRetentionPriority.pre_emptionCapability
//// = initial_p->pre_emp_capability;
//// e_RABToBeSetup.e_RABlevelQoSParameters.allocationRetentionPriority.pre_emptionVulnerability
//// = initial_p->pre_emp_vulnerability;
//
// /* Set the GTP-TEID. This is the S1-U S-GW TEID */
//// INT32_TO_OCTET_STRING(initial_p->teid, &e_RABToBeSetup.gTP_TEID);
//
// /* S-GW IP address(es) for user-plane */
//// if ((initial_p->s_gw_address.pdn_type == IPv4) ||
//// (initial_p->s_gw_address.pdn_type == IPv4_AND_v6))
//// {
//// e_RABToBeSetup.transportLayerAddress.buf = calloc(4, sizeof(uint8_t));
//// /* Only IPv4 supported */
//// memcpy(e_RABToBeSetup.transportLayerAddress.buf,
//// initial_p->s_gw_address.address.ipv4_address,
//// 4);
//// offset += 4;
//// e_RABToBeSetup.transportLayerAddress.size = 4;
//// e_RABToBeSetup.transportLayerAddress.bits_unused = 0;
//// }
//// if ((initial_p->s_gw_address.pdn_type == IPv6) ||
//// (initial_p->s_gw_address.pdn_type == IPv4_AND_v6))
//// {
//// if (offset == 0) {
//// /* Both IPv4 and IPv6 provided */
//// /* TODO: check memory allocation */
//// e_RABToBeSetup.transportLayerAddress.buf = calloc(16, sizeof(uint8_t));
//// } else {
//// /* Only IPv6 supported */
//// /* TODO: check memory allocation */
//// e_RABToBeSetup.transportLayerAddress.buf
//// = realloc(e_RABToBeSetup.transportLayerAddress.buf, (16 + offset) * sizeof(uint8_t));
//// }
//// memcpy(&e_RABToBeSetup.transportLayerAddress.buf[offset],
//// initial_p->s_gw_address.address.ipv6_address,
//// 16);
//// e_RABToBeSetup.transportLayerAddress.size = 16 + offset;
//// e_RABToBeSetup.transportLayerAddress.bits_unused = 0;
//// }
//
// ASN_SEQUENCE_ADD(&initialContextSetupRequest_p->e_RABToBeSetupListCtxtSUReq,
// &e_RABToBeSetup);
//
// initialContextSetupRequest_p->ueSecurityCapabilities.encryptionAlgorithms.buf =
// (uint8_t *)supportedAlgorithms;
// initialContextSetupRequest_p->ueSecurityCapabilities.encryptionAlgorithms.size = 2;
// initialContextSetupRequest_p->ueSecurityCapabilities.encryptionAlgorithms.bits_unused
// = 0;
//
// initialContextSetupRequest_p->ueSecurityCapabilities.integrityProtectionAlgorithms.buf
// = (uint8_t *)supportedAlgorithms;
// initialContextSetupRequest_p->ueSecurityCapabilities.integrityProtectionAlgorithms.size
// = 2;
// initialContextSetupRequest_p->ueSecurityCapabilities.integrityProtectionAlgorithms.bits_unused
// = 0;
//
//// initialContextSetupRequest_p->securityKey.buf = initial_p->keNB; /* 256 bits length */
// uint8_t keNB[32];
// memset(keNB, 0, sizeof(keNB));
//
// initialContextSetupRequest_p->securityKey.buf = keNB;
// initialContextSetupRequest_p->securityKey.size = 32;
// initialContextSetupRequest_p->securityKey.bits_unused = 0;
//
// if (s1ap_mme_encode_pdu(&message, &buffer_p, &length) < 0) {
// // TODO: handle something
// DevMessage("Failed to encode initial context setup request message\n");
// }
//
// free(nas_conn_est_cnf_p->nasMsg.data);
//
// s1ap_mme_itti_send_sctp_request(buffer_p, length, ue_ref->eNB->sctp_assoc_id,
// ue_ref->sctp_stream_send);
//}
void s1ap_handle_conn_est_cnf(const mme_app_connection_establishment_cnf_t * const conn_est_cnf_pP)
{
/* We received create session response from S-GW on S11 interface abstraction.
* At least one bearer has been established. We can now send s1ap initial context setup request
* message to eNB.
*/
uint8_t offset = 0;
uint8_t *buffer_p = NULL;
uint32_t length = 0;
ue_description_t *ue_ref = NULL;
S1ap_InitialContextSetupRequestIEs_t *initialContextSetupRequest_p = NULL;
S1ap_E_RABToBeSetupItemCtxtSUReq_t e_RABToBeSetup;
S1ap_NAS_PDU_t nas_pdu;
s1ap_message message;
DevAssert(conn_est_cnf_pP != NULL);
if ((ue_ref = s1ap_is_ue_mme_id_in_list(conn_est_cnf_pP->nas_conn_est_cnf.UEid)) == NULL) {
S1AP_DEBUG("This mme ue s1ap id ("S1AP_UE_ID_FMT") is not attached to any UE context\n",
conn_est_cnf_pP->nas_conn_est_cnf.UEid);
DevParam(conn_est_cnf_pP->nas_conn_est_cnf.UEid, 0, 0);
}
/* Start the outcome response timer.
* When time is reached, MME consider that procedure outcome has failed.
*/
// timer_setup(mme_config.s1ap_config.outcome_drop_timer_sec, 0, TASK_S1AP, INSTANCE_DEFAULT,
// TIMER_ONE_SHOT,
// NULL,
// &ue_ref->outcome_response_timer_id);
/* Insert the timer in the MAP of mme_ue_s1ap_id <-> timer_id */
// s1ap_timer_insert(ue_ref->mme_ue_s1ap_id, ue_ref->outcome_response_timer_id);
memset(&message, 0, sizeof(s1ap_message));
memset(&e_RABToBeSetup, 0, sizeof(S1ap_E_RABToBeSetupItemCtxtSUReq_t));
message.procedureCode = S1ap_ProcedureCode_id_InitialContextSetup;
message.direction = S1AP_PDU_PR_initiatingMessage;
initialContextSetupRequest_p = &message.msg.s1ap_InitialContextSetupRequestIEs;
initialContextSetupRequest_p->mme_ue_s1ap_id = (unsigned long)ue_ref->mme_ue_s1ap_id;
initialContextSetupRequest_p->eNB_UE_S1AP_ID = (unsigned long)ue_ref->eNB_ue_s1ap_id;
/* uEaggregateMaximumBitrateDL and uEaggregateMaximumBitrateUL expressed in term of bits/sec */
asn_uint642INTEGER(&initialContextSetupRequest_p->uEaggregateMaximumBitrate.uEaggregateMaximumBitRateDL, conn_est_cnf_pP->ambr.br_dl);
asn_uint642INTEGER(&initialContextSetupRequest_p->uEaggregateMaximumBitrate.uEaggregateMaximumBitRateUL, conn_est_cnf_pP->ambr.br_ul);
e_RABToBeSetup.e_RAB_ID = conn_est_cnf_pP->eps_bearer_id; //5;
e_RABToBeSetup.e_RABlevelQoSParameters.qCI = conn_est_cnf_pP->bearer_qos_qci;
memset(&nas_pdu, 0, sizeof(nas_pdu));
nas_pdu.size = conn_est_cnf_pP->nas_conn_est_cnf.nasMsg.length;
nas_pdu.buf = conn_est_cnf_pP->nas_conn_est_cnf.nasMsg.data;
e_RABToBeSetup.nAS_PDU = &nas_pdu;
#if defined(ORIGINAL_S1AP_CODE)
e_RABToBeSetup.e_RABlevelQoSParameters.allocationRetentionPriority.priorityLevel =
S1ap_PriorityLevel_lowest;
e_RABToBeSetup.e_RABlevelQoSParameters.allocationRetentionPriority.pre_emptionCapability =
S1ap_Pre_emptionCapability_shall_not_trigger_pre_emption;
e_RABToBeSetup.e_RABlevelQoSParameters.allocationRetentionPriority.pre_emptionVulnerability =
S1ap_Pre_emptionVulnerability_not_pre_emptable;
#else
e_RABToBeSetup.e_RABlevelQoSParameters.allocationRetentionPriority.priorityLevel =
conn_est_cnf_pP->bearer_qos_prio_level;
e_RABToBeSetup.e_RABlevelQoSParameters.allocationRetentionPriority.pre_emptionCapability =
conn_est_cnf_pP->bearer_qos_pre_emp_capability;
e_RABToBeSetup.e_RABlevelQoSParameters.allocationRetentionPriority.pre_emptionVulnerability =
conn_est_cnf_pP->bearer_qos_pre_emp_vulnerability;
#endif
/* Set the GTP-TEID. This is the S1-U S-GW TEID */
INT32_TO_OCTET_STRING(conn_est_cnf_pP->bearer_s1u_sgw_fteid.teid, &e_RABToBeSetup.gTP_TEID);
/* S-GW IP address(es) for user-plane */
if (conn_est_cnf_pP->bearer_s1u_sgw_fteid.ipv4) {
e_RABToBeSetup.transportLayerAddress.buf = calloc(4, sizeof(uint8_t));
/* Only IPv4 supported */
memcpy(e_RABToBeSetup.transportLayerAddress.buf,
&conn_est_cnf_pP->bearer_s1u_sgw_fteid.ipv4_address,
4);
offset += 4;
e_RABToBeSetup.transportLayerAddress.size = 4;
e_RABToBeSetup.transportLayerAddress.bits_unused = 0;
}
if (conn_est_cnf_pP->bearer_s1u_sgw_fteid.ipv6) {
if (offset == 0) {
/* Both IPv4 and IPv6 provided */
/* TODO: check memory allocation */
e_RABToBeSetup.transportLayerAddress.buf = calloc(16, sizeof(uint8_t));
} else {
/* Only IPv6 supported */
/* TODO: check memory allocation */
e_RABToBeSetup.transportLayerAddress.buf
= realloc(e_RABToBeSetup.transportLayerAddress.buf, (16 + offset) * sizeof(uint8_t));
}
memcpy(&e_RABToBeSetup.transportLayerAddress.buf[offset],
conn_est_cnf_pP->bearer_s1u_sgw_fteid.ipv6_address,
16);
e_RABToBeSetup.transportLayerAddress.size = 16 + offset;
e_RABToBeSetup.transportLayerAddress.bits_unused = 0;
}
ASN_SEQUENCE_ADD(&initialContextSetupRequest_p->e_RABToBeSetupListCtxtSUReq,
&e_RABToBeSetup);
initialContextSetupRequest_p->ueSecurityCapabilities.encryptionAlgorithms.buf =
(uint8_t *)&conn_est_cnf_pP->security_capabilities_encryption_algorithms;
initialContextSetupRequest_p->ueSecurityCapabilities.encryptionAlgorithms.size = 2;
initialContextSetupRequest_p->ueSecurityCapabilities.encryptionAlgorithms.bits_unused
= 0;
initialContextSetupRequest_p->ueSecurityCapabilities.integrityProtectionAlgorithms.buf =
(uint8_t *)&conn_est_cnf_pP->security_capabilities_integrity_algorithms;
initialContextSetupRequest_p->ueSecurityCapabilities.integrityProtectionAlgorithms.size
= 2;
initialContextSetupRequest_p->ueSecurityCapabilities.integrityProtectionAlgorithms.bits_unused
= 0;
S1AP_DEBUG("security_capabilities_encryption_algorithms 0x%04X\n",
conn_est_cnf_pP->security_capabilities_encryption_algorithms);
S1AP_DEBUG("security_capabilities_integrity_algorithms 0x%04X\n",
conn_est_cnf_pP->security_capabilities_integrity_algorithms);
if (conn_est_cnf_pP->keNB) {
initialContextSetupRequest_p->securityKey.buf = malloc(32);
memcpy(initialContextSetupRequest_p->securityKey.buf,
conn_est_cnf_pP->keNB,
32);
initialContextSetupRequest_p->securityKey.size = 32;
} else {
S1AP_DEBUG("No keNB\n");
initialContextSetupRequest_p->securityKey.buf = NULL;
initialContextSetupRequest_p->securityKey.size = 0;
}
initialContextSetupRequest_p->securityKey.bits_unused = 0;
if (s1ap_mme_encode_pdu(&message, &buffer_p, &length) < 0) {
// TODO: handle something
DevMessage("Failed to encode initial context setup request message\n");
}
free(conn_est_cnf_pP->nas_conn_est_cnf.nasMsg.data);
MSC_LOG_TX_MESSAGE(
MSC_S1AP_MME,
MSC_S1AP_ENB,
NULL,0,
"0 InitialContextSetup/initiatingMessage mme_ue_s1ap_id "S1AP_UE_ID_FMT" eNB_ue_s1ap_id "S1AP_UE_ID_FMT" nas length %u",
initialContextSetupRequest_p->mme_ue_s1ap_id,
initialContextSetupRequest_p->eNB_UE_S1AP_ID,
nas_pdu.size);
s1ap_mme_itti_send_sctp_request(
buffer_p,
length,
ue_ref->eNB->sctp_assoc_id,
ue_ref->sctp_stream_send);
}
#endif