2017-03-08 06:27:48 +00:00
|
|
|
#define TRACE_MODULE _s1ap_build
|
2017-02-06 10:12:10 +00:00
|
|
|
|
2017-02-06 11:54:31 +00:00
|
|
|
#include "core_debug.h"
|
2017-03-26 06:34:34 +00:00
|
|
|
|
2018-01-04 11:38:22 +00:00
|
|
|
#include "fd/s6a/s6a_message.h"
|
2017-08-25 15:11:46 +00:00
|
|
|
|
2017-04-06 10:20:33 +00:00
|
|
|
#include "mme_context.h"
|
2017-03-26 06:34:34 +00:00
|
|
|
|
2017-04-13 12:05:30 +00:00
|
|
|
#include "mme_kdf.h"
|
2017-02-20 10:46:58 +00:00
|
|
|
#include "s1ap_build.h"
|
2017-02-10 12:51:56 +00:00
|
|
|
#include "s1ap_conv.h"
|
2017-02-06 10:12:10 +00:00
|
|
|
|
|
|
|
status_t s1ap_build_setup_rsp(pkbuf_t **pkbuf)
|
|
|
|
{
|
|
|
|
int erval;
|
|
|
|
int i, j;
|
|
|
|
|
2017-03-06 00:07:59 +00:00
|
|
|
s1ap_message_t message;
|
2017-02-06 10:12:10 +00:00
|
|
|
S1ap_S1SetupResponseIEs_t *ies = NULL;
|
2017-02-07 02:35:22 +00:00
|
|
|
S1ap_ServedGUMMEIsItem_t *servedGUMMEI;
|
|
|
|
S1ap_PLMNidentity_t *plmnIdentity;
|
|
|
|
S1ap_MME_Group_ID_t *mmeGroupId;
|
|
|
|
S1ap_MME_Code_t *mmeCode;
|
2017-02-06 11:54:31 +00:00
|
|
|
|
2017-03-06 00:07:59 +00:00
|
|
|
memset(&message, 0, sizeof(s1ap_message_t));
|
2017-02-06 10:12:10 +00:00
|
|
|
|
2017-03-05 02:46:42 +00:00
|
|
|
ies = &message.s1ap_S1SetupResponseIEs;
|
2017-02-06 10:12:10 +00:00
|
|
|
|
2017-07-14 13:03:10 +00:00
|
|
|
for (i = 0; i < mme_self()->max_num_of_served_gummei; i++)
|
2017-02-06 10:12:10 +00:00
|
|
|
{
|
2017-07-14 13:03:10 +00:00
|
|
|
servedGUMMEI = (S1ap_ServedGUMMEIsItem_t *)
|
|
|
|
core_calloc(1, sizeof(S1ap_ServedGUMMEIsItem_t));
|
|
|
|
served_gummei_t *served_gummei = &mme_self()->served_gummei[i];
|
2017-02-06 10:12:10 +00:00
|
|
|
|
2017-07-14 13:03:10 +00:00
|
|
|
for (j = 0; j < served_gummei->num_of_plmn_id; j++)
|
2017-02-06 10:12:10 +00:00
|
|
|
{
|
2017-02-07 02:35:22 +00:00
|
|
|
plmnIdentity = (S1ap_PLMNidentity_t *)
|
2017-03-24 13:52:55 +00:00
|
|
|
core_calloc(1, sizeof(S1ap_PLMNidentity_t));
|
|
|
|
s1ap_buffer_to_OCTET_STRING(
|
2017-07-14 13:03:10 +00:00
|
|
|
&served_gummei->plmn_id[j], PLMN_ID_LEN, plmnIdentity);
|
2017-02-07 02:35:22 +00:00
|
|
|
ASN_SEQUENCE_ADD(&servedGUMMEI->servedPLMNs, plmnIdentity);
|
2018-01-23 06:38:07 +00:00
|
|
|
d_trace(5, " PLMN_ID[MCC:%d MNC:%d]\n",
|
2018-01-22 14:14:20 +00:00
|
|
|
plmn_id_mcc(&served_gummei->plmn_id[j]),
|
|
|
|
plmn_id_mnc(&served_gummei->plmn_id[j]));
|
2017-02-06 10:12:10 +00:00
|
|
|
}
|
|
|
|
|
2017-07-14 13:03:10 +00:00
|
|
|
for (j = 0; j < served_gummei->num_of_mme_gid; j++)
|
2017-02-06 10:12:10 +00:00
|
|
|
{
|
2017-02-07 02:35:22 +00:00
|
|
|
mmeGroupId = (S1ap_MME_Group_ID_t *)
|
2017-03-24 13:52:55 +00:00
|
|
|
core_calloc(1, sizeof(S1ap_MME_Group_ID_t));
|
2017-03-05 02:29:15 +00:00
|
|
|
s1ap_uint16_to_OCTET_STRING(
|
2017-07-14 13:03:10 +00:00
|
|
|
served_gummei->mme_gid[j], mmeGroupId);
|
2017-02-07 02:35:22 +00:00
|
|
|
ASN_SEQUENCE_ADD(&servedGUMMEI->servedGroupIDs, mmeGroupId);
|
2018-01-23 06:38:07 +00:00
|
|
|
d_trace(5, " MME Group[%d]\n", served_gummei->mme_gid[j]);
|
2017-02-06 10:12:10 +00:00
|
|
|
}
|
|
|
|
|
2017-07-14 13:03:10 +00:00
|
|
|
for (j = 0; j < served_gummei->num_of_mme_code; j++)
|
2017-02-06 10:12:10 +00:00
|
|
|
{
|
2017-02-07 02:35:22 +00:00
|
|
|
mmeCode = (S1ap_MME_Code_t *)
|
2017-03-24 13:52:55 +00:00
|
|
|
core_calloc(1, sizeof(S1ap_MME_Code_t));
|
2017-03-05 02:29:15 +00:00
|
|
|
s1ap_uint8_to_OCTET_STRING(
|
2017-07-14 13:03:10 +00:00
|
|
|
served_gummei->mme_code[j], mmeCode);
|
2017-02-07 02:35:22 +00:00
|
|
|
ASN_SEQUENCE_ADD(&servedGUMMEI->servedMMECs, mmeCode);
|
2018-01-23 06:38:07 +00:00
|
|
|
d_trace(5, " MME Code[%d]\n", served_gummei->mme_code[j]);
|
2017-02-06 10:12:10 +00:00
|
|
|
}
|
2017-07-14 12:46:08 +00:00
|
|
|
ASN_SEQUENCE_ADD(&ies->servedGUMMEIs, servedGUMMEI);
|
2017-02-06 10:12:10 +00:00
|
|
|
}
|
2017-02-14 00:09:01 +00:00
|
|
|
|
|
|
|
ies->relativeMMECapacity = mme_self()->relative_capacity;
|
|
|
|
|
2017-02-06 10:12:10 +00:00
|
|
|
message.procedureCode = S1ap_ProcedureCode_id_S1Setup;
|
|
|
|
message.direction = S1AP_PDU_PR_successfulOutcome;
|
|
|
|
|
|
|
|
erval = s1ap_encode_pdu(pkbuf, &message);
|
2017-02-09 14:15:08 +00:00
|
|
|
s1ap_free_pdu(&message);
|
2017-02-07 02:35:22 +00:00
|
|
|
|
2017-02-06 10:12:10 +00:00
|
|
|
if (erval < 0)
|
2017-02-07 02:35:22 +00:00
|
|
|
{
|
|
|
|
d_error("s1ap_encode_error : (%d)", erval);
|
2017-02-06 10:12:10 +00:00
|
|
|
return CORE_ERROR;
|
2017-02-07 02:35:22 +00:00
|
|
|
}
|
2017-02-06 10:12:10 +00:00
|
|
|
|
|
|
|
return CORE_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-01-21 11:31:28 +00:00
|
|
|
status_t s1ap_build_setup_failure(
|
|
|
|
pkbuf_t **pkbuf, S1ap_Cause_PR group, long cause)
|
2017-02-13 11:10:05 +00:00
|
|
|
{
|
|
|
|
int erval;
|
|
|
|
|
2017-03-06 00:07:59 +00:00
|
|
|
s1ap_message_t message;
|
2017-02-13 11:10:05 +00:00
|
|
|
S1ap_S1SetupFailureIEs_t *ies = NULL;
|
|
|
|
|
2017-03-06 00:07:59 +00:00
|
|
|
memset(&message, 0, sizeof(s1ap_message_t));
|
2017-02-13 11:10:05 +00:00
|
|
|
|
2017-03-05 02:46:42 +00:00
|
|
|
ies = &message.s1ap_S1SetupFailureIEs;
|
2018-01-21 11:31:28 +00:00
|
|
|
ies->cause.present = group;
|
|
|
|
ies->cause.choice.radioNetwork = cause;
|
2017-02-13 11:10:05 +00:00
|
|
|
|
|
|
|
message.procedureCode = S1ap_ProcedureCode_id_S1Setup;
|
|
|
|
message.direction = S1AP_PDU_PR_unsuccessfulOutcome;
|
|
|
|
|
|
|
|
erval = s1ap_encode_pdu(pkbuf, &message);
|
|
|
|
s1ap_free_pdu(&message);
|
|
|
|
|
|
|
|
if (erval < 0)
|
|
|
|
{
|
|
|
|
d_error("s1ap_encode_error : (%d)", erval);
|
|
|
|
return CORE_ERROR;
|
|
|
|
}
|
|
|
|
|
|
|
|
return CORE_OK;
|
|
|
|
}
|
2017-04-13 02:08:42 +00:00
|
|
|
|
2017-04-13 08:46:26 +00:00
|
|
|
status_t s1ap_build_downlink_nas_transport(
|
2017-04-28 07:11:45 +00:00
|
|
|
pkbuf_t **s1apbuf, enb_ue_t *enb_ue, pkbuf_t *emmbuf)
|
2017-04-13 02:08:42 +00:00
|
|
|
{
|
2017-04-13 03:21:47 +00:00
|
|
|
int encoded;
|
|
|
|
s1ap_message_t message;
|
|
|
|
S1ap_DownlinkNASTransport_IEs_t *ies =
|
|
|
|
&message.s1ap_DownlinkNASTransport_IEs;
|
|
|
|
S1ap_NAS_PDU_t *nasPdu = &ies->nas_pdu;
|
2017-04-13 08:46:26 +00:00
|
|
|
|
|
|
|
d_assert(emmbuf, return CORE_ERROR, "Null param");
|
2017-04-28 07:11:45 +00:00
|
|
|
d_assert(enb_ue, return CORE_ERROR, "Null param");
|
2017-04-13 08:46:26 +00:00
|
|
|
|
|
|
|
memset(&message, 0, sizeof(s1ap_message_t));
|
2018-01-22 14:14:20 +00:00
|
|
|
|
|
|
|
d_trace(3, "[MME] Downlink NAS transport\n");
|
2018-01-23 06:38:07 +00:00
|
|
|
d_trace(5, " ENB_UE_S1AP_ID[%d] MME_UE_S1AP_ID[%d]\n",
|
2018-01-22 14:14:20 +00:00
|
|
|
enb_ue->enb_ue_s1ap_id, enb_ue->mme_ue_s1ap_id);
|
2017-04-13 08:46:26 +00:00
|
|
|
|
2017-04-28 07:11:45 +00:00
|
|
|
ies->mme_ue_s1ap_id = enb_ue->mme_ue_s1ap_id;
|
|
|
|
ies->eNB_UE_S1AP_ID = enb_ue->enb_ue_s1ap_id;
|
2017-04-13 08:46:26 +00:00
|
|
|
|
|
|
|
nasPdu->size = emmbuf->len;
|
|
|
|
nasPdu->buf = core_calloc(nasPdu->size, sizeof(c_uint8_t));
|
|
|
|
memcpy(nasPdu->buf, emmbuf->payload, nasPdu->size);
|
|
|
|
|
|
|
|
message.procedureCode = S1ap_ProcedureCode_id_downlinkNASTransport;
|
|
|
|
message.direction = S1AP_PDU_PR_initiatingMessage;
|
|
|
|
|
|
|
|
encoded = s1ap_encode_pdu(s1apbuf, &message);
|
|
|
|
s1ap_free_pdu(&message);
|
|
|
|
|
|
|
|
d_assert(s1apbuf && encoded >= 0,return CORE_ERROR,);
|
|
|
|
pkbuf_free(emmbuf);
|
|
|
|
|
|
|
|
return CORE_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
status_t s1ap_build_initial_context_setup_request(
|
2017-09-11 05:01:11 +00:00
|
|
|
pkbuf_t **s1apbuf, mme_ue_t *mme_ue, pkbuf_t *emmbuf)
|
2017-04-13 08:46:26 +00:00
|
|
|
{
|
2017-12-07 08:40:15 +00:00
|
|
|
status_t rv;
|
2017-04-13 10:58:58 +00:00
|
|
|
|
2017-04-13 08:46:26 +00:00
|
|
|
int encoded;
|
|
|
|
s1ap_message_t message;
|
|
|
|
S1ap_InitialContextSetupRequestIEs_t *ies =
|
|
|
|
&message.s1ap_InitialContextSetupRequestIEs;
|
|
|
|
S1ap_E_RABToBeSetupItemCtxtSUReq_t *e_rab = NULL;
|
2017-09-05 05:52:19 +00:00
|
|
|
struct S1ap_GBR_QosInformation *gbrQosInformation = NULL; /* OPTIONAL */
|
2017-04-13 08:46:26 +00:00
|
|
|
S1ap_NAS_PDU_t *nasPdu = NULL;
|
2017-04-28 07:11:45 +00:00
|
|
|
enb_ue_t *enb_ue = NULL;
|
2017-09-11 05:01:11 +00:00
|
|
|
mme_sess_t *sess = NULL;
|
2017-08-26 09:52:06 +00:00
|
|
|
mme_bearer_t *bearer = NULL;
|
2017-08-25 15:11:46 +00:00
|
|
|
s6a_subscription_data_t *subscription_data = NULL;
|
2017-04-13 03:21:47 +00:00
|
|
|
|
2017-04-28 04:43:42 +00:00
|
|
|
d_assert(mme_ue, return CORE_ERROR, "Null param");
|
2017-04-28 07:11:45 +00:00
|
|
|
enb_ue = mme_ue->enb_ue;
|
|
|
|
d_assert(enb_ue, return CORE_ERROR, "Null param");
|
2017-08-25 15:11:46 +00:00
|
|
|
subscription_data = &mme_ue->subscription_data;
|
|
|
|
d_assert(subscription_data, return CORE_ERROR, "Null param");
|
2017-04-13 03:21:47 +00:00
|
|
|
|
2018-01-22 14:14:20 +00:00
|
|
|
d_trace(3, "[MME] Initial context setup request\n");
|
2018-01-23 06:38:07 +00:00
|
|
|
d_trace(5, " ENB_UE_S1AP_ID[%d] MME_UE_S1AP_ID[%d]\n",
|
2018-01-22 14:14:20 +00:00
|
|
|
enb_ue->enb_ue_s1ap_id, enb_ue->mme_ue_s1ap_id);
|
|
|
|
|
2017-04-13 03:21:47 +00:00
|
|
|
memset(&message, 0, sizeof(s1ap_message_t));
|
|
|
|
|
2017-04-28 07:11:45 +00:00
|
|
|
ies->mme_ue_s1ap_id = enb_ue->mme_ue_s1ap_id;
|
|
|
|
ies->eNB_UE_S1AP_ID = enb_ue->enb_ue_s1ap_id;
|
2017-04-13 03:21:47 +00:00
|
|
|
|
2017-04-13 08:46:26 +00:00
|
|
|
asn_uint642INTEGER(
|
|
|
|
&ies->uEaggregateMaximumBitrate.uEaggregateMaximumBitRateUL,
|
2017-08-25 15:11:46 +00:00
|
|
|
subscription_data->ambr.uplink);
|
2017-04-13 08:46:26 +00:00
|
|
|
asn_uint642INTEGER(
|
|
|
|
&ies->uEaggregateMaximumBitrate.uEaggregateMaximumBitRateDL,
|
2017-08-25 15:11:46 +00:00
|
|
|
subscription_data->ambr.downlink);
|
2017-04-13 08:46:26 +00:00
|
|
|
|
2017-09-11 05:01:11 +00:00
|
|
|
sess = mme_sess_first(mme_ue);
|
|
|
|
while(sess)
|
2017-07-26 02:28:43 +00:00
|
|
|
{
|
2017-09-11 05:01:11 +00:00
|
|
|
bearer = mme_bearer_first(sess);
|
|
|
|
while(bearer)
|
|
|
|
{
|
|
|
|
e_rab = (S1ap_E_RABToBeSetupItemCtxtSUReq_t *)
|
|
|
|
core_calloc(1, sizeof(S1ap_E_RABToBeSetupItemCtxtSUReq_t));
|
|
|
|
e_rab->e_RAB_ID = bearer->ebi;
|
|
|
|
e_rab->e_RABlevelQoSParameters.qCI = bearer->qos.qci;
|
|
|
|
|
2018-02-01 05:07:01 +00:00
|
|
|
d_trace(5, " EBI[%d] QCI[%d] SGW-S1U-TEID[%d]\n",
|
|
|
|
bearer->ebi, bearer->qos.qci, bearer->sgw_s1u_teid);
|
2018-01-22 14:14:20 +00:00
|
|
|
|
2017-09-11 05:01:11 +00:00
|
|
|
e_rab->e_RABlevelQoSParameters.allocationRetentionPriority.
|
|
|
|
priorityLevel = bearer->qos.arp.priority_level;
|
|
|
|
e_rab->e_RABlevelQoSParameters.allocationRetentionPriority.
|
|
|
|
pre_emptionCapability =
|
|
|
|
!(bearer->qos.arp.pre_emption_capability);
|
|
|
|
e_rab->e_RABlevelQoSParameters.allocationRetentionPriority.
|
|
|
|
pre_emptionVulnerability =
|
|
|
|
!(bearer->qos.arp.pre_emption_vulnerability);
|
|
|
|
|
|
|
|
if (bearer->qos.mbr.downlink || bearer->qos.mbr.uplink ||
|
|
|
|
bearer->qos.gbr.downlink || bearer->qos.gbr.uplink)
|
|
|
|
{
|
|
|
|
if (bearer->qos.mbr.downlink == 0)
|
|
|
|
bearer->qos.mbr.downlink = MAX_BIT_RATE;
|
|
|
|
if (bearer->qos.mbr.uplink == 0)
|
|
|
|
bearer->qos.mbr.uplink = MAX_BIT_RATE;
|
|
|
|
if (bearer->qos.gbr.downlink == 0)
|
|
|
|
bearer->qos.gbr.downlink = MAX_BIT_RATE;
|
|
|
|
if (bearer->qos.gbr.uplink == 0)
|
|
|
|
bearer->qos.gbr.uplink = MAX_BIT_RATE;
|
|
|
|
|
|
|
|
gbrQosInformation =
|
|
|
|
core_calloc(1, sizeof(struct S1ap_GBR_QosInformation));
|
|
|
|
asn_uint642INTEGER(&gbrQosInformation->e_RAB_MaximumBitrateDL,
|
|
|
|
bearer->qos.mbr.downlink);
|
|
|
|
asn_uint642INTEGER(&gbrQosInformation->e_RAB_MaximumBitrateUL,
|
|
|
|
bearer->qos.mbr.uplink);
|
|
|
|
asn_uint642INTEGER(&gbrQosInformation->
|
|
|
|
e_RAB_GuaranteedBitrateDL, bearer->qos.gbr.downlink);
|
|
|
|
asn_uint642INTEGER(&gbrQosInformation->
|
|
|
|
e_RAB_GuaranteedBitrateUL, bearer->qos.gbr.uplink);
|
|
|
|
e_rab->e_RABlevelQoSParameters.gbrQosInformation =
|
|
|
|
gbrQosInformation;
|
|
|
|
}
|
|
|
|
|
2017-12-07 08:40:15 +00:00
|
|
|
rv = s1ap_ip_to_BIT_STRING(
|
|
|
|
&bearer->sgw_s1u_ip, &e_rab->transportLayerAddress);
|
|
|
|
d_assert(rv == CORE_OK, return CORE_ERROR,);
|
2017-09-11 05:01:11 +00:00
|
|
|
s1ap_uint32_to_OCTET_STRING(bearer->sgw_s1u_teid, &e_rab->gTP_TEID);
|
|
|
|
|
|
|
|
if (emmbuf && emmbuf->len)
|
|
|
|
{
|
|
|
|
nasPdu = (S1ap_NAS_PDU_t *)core_calloc(
|
|
|
|
1, sizeof(S1ap_NAS_PDU_t));
|
|
|
|
nasPdu->size = emmbuf->len;
|
|
|
|
nasPdu->buf = core_calloc(nasPdu->size, sizeof(c_uint8_t));
|
|
|
|
memcpy(nasPdu->buf, emmbuf->payload, nasPdu->size);
|
|
|
|
e_rab->nAS_PDU = nasPdu;
|
|
|
|
}
|
|
|
|
|
|
|
|
ASN_SEQUENCE_ADD(&ies->e_RABToBeSetupListCtxtSUReq, e_rab);
|
|
|
|
|
|
|
|
bearer = mme_bearer_next(bearer);
|
|
|
|
}
|
|
|
|
sess = mme_sess_next(sess);
|
2017-07-26 02:28:43 +00:00
|
|
|
}
|
2017-04-13 03:21:47 +00:00
|
|
|
|
2017-04-13 12:22:10 +00:00
|
|
|
ies->ueSecurityCapabilities.encryptionAlgorithms.size = 2;
|
|
|
|
ies->ueSecurityCapabilities.encryptionAlgorithms.buf =
|
|
|
|
core_calloc(ies->ueSecurityCapabilities.encryptionAlgorithms.size,
|
|
|
|
sizeof(c_uint8_t));
|
|
|
|
ies->ueSecurityCapabilities.encryptionAlgorithms.bits_unused = 0;
|
|
|
|
ies->ueSecurityCapabilities.encryptionAlgorithms.buf[0] =
|
2017-09-12 14:07:55 +00:00
|
|
|
(mme_ue->ue_network_capability.eea << 1);
|
2017-04-13 12:22:10 +00:00
|
|
|
|
|
|
|
ies->ueSecurityCapabilities.integrityProtectionAlgorithms.size = 2;
|
|
|
|
ies->ueSecurityCapabilities.integrityProtectionAlgorithms.buf =
|
|
|
|
core_calloc(ies->ueSecurityCapabilities.
|
|
|
|
integrityProtectionAlgorithms.size, sizeof(c_uint8_t));
|
|
|
|
ies->ueSecurityCapabilities.integrityProtectionAlgorithms.bits_unused = 0;
|
|
|
|
ies->ueSecurityCapabilities.integrityProtectionAlgorithms.buf[0] =
|
2017-04-28 04:43:42 +00:00
|
|
|
(mme_ue->ue_network_capability.eia << 1);
|
2017-04-13 12:22:10 +00:00
|
|
|
|
2017-04-13 12:05:30 +00:00
|
|
|
ies->securityKey.size = SHA256_DIGEST_SIZE;
|
2017-04-13 08:46:26 +00:00
|
|
|
ies->securityKey.buf =
|
|
|
|
core_calloc(ies->securityKey.size, sizeof(c_uint8_t));
|
2017-04-13 12:22:10 +00:00
|
|
|
ies->securityKey.bits_unused = 0;
|
2017-04-28 04:43:42 +00:00
|
|
|
memcpy(ies->securityKey.buf, mme_ue->kenb, ies->securityKey.size);
|
2017-04-13 08:46:26 +00:00
|
|
|
|
2017-08-08 19:01:08 +00:00
|
|
|
/* Set UeRadioCapability if exists */
|
|
|
|
if (mme_ue->radio_capa)
|
|
|
|
{
|
|
|
|
S1ap_UERadioCapability_t *radio_capa =
|
|
|
|
(S1ap_UERadioCapability_t *)mme_ue->radio_capa;
|
|
|
|
|
|
|
|
ies->presenceMask |=
|
|
|
|
S1AP_INITIALCONTEXTSETUPREQUESTIES_UERADIOCAPABILITY_PRESENT;
|
|
|
|
|
|
|
|
ies->ueRadioCapability.size = radio_capa->size;
|
|
|
|
ies->ueRadioCapability.buf =
|
|
|
|
core_calloc(ies->ueRadioCapability.size, sizeof(c_uint8_t));
|
|
|
|
memcpy(ies->ueRadioCapability.buf, radio_capa->buf, radio_capa->size);
|
|
|
|
}
|
|
|
|
|
2017-04-13 08:46:26 +00:00
|
|
|
message.procedureCode = S1ap_ProcedureCode_id_InitialContextSetup;
|
2017-04-13 03:21:47 +00:00
|
|
|
message.direction = S1AP_PDU_PR_initiatingMessage;
|
|
|
|
|
|
|
|
encoded = s1ap_encode_pdu(s1apbuf, &message);
|
|
|
|
s1ap_free_pdu(&message);
|
|
|
|
|
|
|
|
d_assert(s1apbuf && encoded >= 0,return CORE_ERROR,);
|
|
|
|
|
2017-07-26 02:28:43 +00:00
|
|
|
if (emmbuf && emmbuf->len)
|
|
|
|
{
|
|
|
|
pkbuf_free(emmbuf);
|
|
|
|
}
|
|
|
|
|
2017-04-13 02:08:42 +00:00
|
|
|
return CORE_OK;
|
|
|
|
}
|
2017-04-28 02:20:09 +00:00
|
|
|
|
2017-09-04 15:04:05 +00:00
|
|
|
status_t s1ap_build_e_rab_setup_request(
|
|
|
|
pkbuf_t **s1apbuf, mme_bearer_t *bearer, pkbuf_t *esmbuf)
|
|
|
|
{
|
2017-12-07 08:40:15 +00:00
|
|
|
status_t rv;
|
2017-09-04 15:04:05 +00:00
|
|
|
int encoded;
|
|
|
|
s1ap_message_t message;
|
|
|
|
S1ap_E_RABSetupRequestIEs_t *ies = &message.s1ap_E_RABSetupRequestIEs;
|
|
|
|
S1ap_E_RABToBeSetupItemBearerSUReq_t *e_rab = NULL;
|
|
|
|
struct S1ap_GBR_QosInformation *gbrQosInformation = NULL; /* OPTIONAL */
|
|
|
|
S1ap_NAS_PDU_t *nasPdu = NULL;
|
|
|
|
mme_ue_t *mme_ue = NULL;
|
|
|
|
enb_ue_t *enb_ue = NULL;
|
|
|
|
|
|
|
|
d_assert(esmbuf, return CORE_ERROR, "Null param");
|
|
|
|
d_assert(bearer, return CORE_ERROR, "Null param");
|
|
|
|
|
|
|
|
mme_ue = bearer->mme_ue;
|
|
|
|
d_assert(mme_ue, return CORE_ERROR, "Null param");
|
|
|
|
enb_ue = mme_ue->enb_ue;
|
|
|
|
d_assert(enb_ue, return CORE_ERROR, "Null param");
|
|
|
|
|
2018-01-22 14:14:20 +00:00
|
|
|
d_trace(3, "[MME] E-RAB setup request\n");
|
2018-01-23 06:38:07 +00:00
|
|
|
d_trace(5, " ENB_UE_S1AP_ID[%d] MME_UE_S1AP_ID[%d]\n",
|
2018-01-22 14:14:20 +00:00
|
|
|
enb_ue->enb_ue_s1ap_id, enb_ue->mme_ue_s1ap_id);
|
|
|
|
|
2017-09-04 15:04:05 +00:00
|
|
|
memset(&message, 0, sizeof(s1ap_message_t));
|
|
|
|
|
|
|
|
ies->mme_ue_s1ap_id = enb_ue->mme_ue_s1ap_id;
|
|
|
|
ies->eNB_UE_S1AP_ID = enb_ue->enb_ue_s1ap_id;
|
|
|
|
|
|
|
|
e_rab = (S1ap_E_RABToBeSetupItemBearerSUReq_t *)
|
|
|
|
core_calloc(1, sizeof(S1ap_E_RABToBeSetupItemBearerSUReq_t));
|
|
|
|
e_rab->e_RAB_ID = bearer->ebi;
|
|
|
|
e_rab->e_RABlevelQoSParameters.qCI = bearer->qos.qci;
|
|
|
|
|
2018-01-23 06:38:07 +00:00
|
|
|
d_trace(5, " EBI[%d] QCI[%d]\n", bearer->ebi, bearer->qos.qci);
|
2018-01-22 14:14:20 +00:00
|
|
|
|
2017-09-04 15:04:05 +00:00
|
|
|
e_rab->e_RABlevelQoSParameters.allocationRetentionPriority.
|
|
|
|
priorityLevel = bearer->qos.arp.priority_level;
|
|
|
|
e_rab->e_RABlevelQoSParameters.allocationRetentionPriority.
|
|
|
|
pre_emptionCapability = !(bearer->qos.arp.pre_emption_capability);
|
|
|
|
e_rab->e_RABlevelQoSParameters.allocationRetentionPriority.
|
|
|
|
pre_emptionVulnerability = !(bearer->qos.arp.pre_emption_vulnerability);
|
|
|
|
|
2017-09-05 05:52:19 +00:00
|
|
|
if (bearer->qos.mbr.downlink || bearer->qos.mbr.uplink ||
|
|
|
|
bearer->qos.gbr.downlink || bearer->qos.gbr.uplink)
|
|
|
|
{
|
|
|
|
if (bearer->qos.mbr.downlink == 0)
|
|
|
|
bearer->qos.mbr.downlink = MAX_BIT_RATE;
|
|
|
|
if (bearer->qos.mbr.uplink == 0)
|
|
|
|
bearer->qos.mbr.uplink = MAX_BIT_RATE;
|
|
|
|
if (bearer->qos.gbr.downlink == 0)
|
|
|
|
bearer->qos.gbr.downlink = MAX_BIT_RATE;
|
|
|
|
if (bearer->qos.gbr.uplink == 0)
|
|
|
|
bearer->qos.gbr.uplink = MAX_BIT_RATE;
|
|
|
|
|
|
|
|
gbrQosInformation =
|
|
|
|
core_calloc(1, sizeof(struct S1ap_GBR_QosInformation));
|
|
|
|
asn_uint642INTEGER(&gbrQosInformation->e_RAB_MaximumBitrateDL,
|
|
|
|
bearer->qos.mbr.downlink);
|
|
|
|
asn_uint642INTEGER(&gbrQosInformation->e_RAB_MaximumBitrateUL,
|
|
|
|
bearer->qos.mbr.uplink);
|
|
|
|
asn_uint642INTEGER(&gbrQosInformation->e_RAB_GuaranteedBitrateDL,
|
|
|
|
bearer->qos.gbr.downlink);
|
|
|
|
asn_uint642INTEGER(&gbrQosInformation->e_RAB_GuaranteedBitrateUL,
|
|
|
|
bearer->qos.gbr.uplink);
|
|
|
|
e_rab->e_RABlevelQoSParameters.gbrQosInformation = gbrQosInformation;
|
|
|
|
}
|
2017-09-04 15:04:05 +00:00
|
|
|
|
2017-12-07 08:40:15 +00:00
|
|
|
rv = s1ap_ip_to_BIT_STRING(
|
|
|
|
&bearer->sgw_s1u_ip, &e_rab->transportLayerAddress);
|
|
|
|
d_assert(rv == CORE_OK, return CORE_ERROR,);
|
2017-09-04 15:04:05 +00:00
|
|
|
s1ap_uint32_to_OCTET_STRING(bearer->sgw_s1u_teid, &e_rab->gTP_TEID);
|
2018-02-01 05:07:01 +00:00
|
|
|
d_trace(5, " SGW-S1U-TEID[%d]\n", bearer->sgw_s1u_teid);
|
2017-09-04 15:04:05 +00:00
|
|
|
|
|
|
|
nasPdu = &e_rab->nAS_PDU;
|
|
|
|
nasPdu->size = esmbuf->len;
|
|
|
|
nasPdu->buf = core_calloc(nasPdu->size, sizeof(c_uint8_t));
|
|
|
|
memcpy(nasPdu->buf, esmbuf->payload, nasPdu->size);
|
|
|
|
|
|
|
|
ASN_SEQUENCE_ADD(&ies->e_RABToBeSetupListBearerSUReq, e_rab);
|
|
|
|
|
|
|
|
message.procedureCode = S1ap_ProcedureCode_id_E_RABSetup;
|
|
|
|
message.direction = S1AP_PDU_PR_initiatingMessage;
|
|
|
|
|
|
|
|
encoded = s1ap_encode_pdu(s1apbuf, &message);
|
|
|
|
s1ap_free_pdu(&message);
|
|
|
|
|
|
|
|
d_assert(s1apbuf && encoded >= 0,return CORE_ERROR,);
|
|
|
|
|
|
|
|
pkbuf_free(esmbuf);
|
|
|
|
|
|
|
|
return CORE_OK;
|
|
|
|
}
|
|
|
|
|
2018-01-17 06:41:45 +00:00
|
|
|
status_t s1ap_build_e_rab_modify_request(
|
|
|
|
pkbuf_t **s1apbuf, mme_bearer_t *bearer, pkbuf_t *esmbuf)
|
|
|
|
{
|
|
|
|
int encoded;
|
|
|
|
s1ap_message_t message;
|
|
|
|
S1ap_E_RABModifyRequestIEs_t *ies = &message.s1ap_E_RABModifyRequestIEs;
|
|
|
|
S1ap_E_RABToBeModifiedItemBearerModReq_t *e_rab = NULL;
|
|
|
|
struct S1ap_GBR_QosInformation *gbrQosInformation = NULL; /* OPTIONAL */
|
|
|
|
S1ap_NAS_PDU_t *nasPdu = NULL;
|
|
|
|
mme_ue_t *mme_ue = NULL;
|
|
|
|
enb_ue_t *enb_ue = NULL;
|
|
|
|
|
|
|
|
d_assert(esmbuf, return CORE_ERROR, "Null param");
|
|
|
|
d_assert(bearer, return CORE_ERROR, "Null param");
|
|
|
|
|
|
|
|
mme_ue = bearer->mme_ue;
|
|
|
|
d_assert(mme_ue, return CORE_ERROR, "Null param");
|
|
|
|
enb_ue = mme_ue->enb_ue;
|
|
|
|
d_assert(enb_ue, return CORE_ERROR, "Null param");
|
|
|
|
|
2018-01-22 14:14:20 +00:00
|
|
|
d_trace(3, "[MME] E-RAB modify request\n");
|
2018-01-23 06:38:07 +00:00
|
|
|
d_trace(5, " ENB_UE_S1AP_ID[%d] MME_UE_S1AP_ID[%d]\n",
|
2018-01-22 14:14:20 +00:00
|
|
|
enb_ue->enb_ue_s1ap_id, enb_ue->mme_ue_s1ap_id);
|
|
|
|
|
2018-01-17 06:41:45 +00:00
|
|
|
memset(&message, 0, sizeof(s1ap_message_t));
|
|
|
|
|
|
|
|
ies->mme_ue_s1ap_id = enb_ue->mme_ue_s1ap_id;
|
|
|
|
ies->eNB_UE_S1AP_ID = enb_ue->enb_ue_s1ap_id;
|
|
|
|
|
|
|
|
e_rab = (S1ap_E_RABToBeModifiedItemBearerModReq_t *)
|
|
|
|
core_calloc(1, sizeof(S1ap_E_RABToBeModifiedItemBearerModReq_t));
|
|
|
|
e_rab->e_RAB_ID = bearer->ebi;
|
|
|
|
e_rab->e_RABLevelQoSParameters.qCI = bearer->qos.qci;
|
|
|
|
|
2018-01-23 06:38:07 +00:00
|
|
|
d_trace(5, " EBI[%d] QCI[%d]\n", bearer->ebi, bearer->qos.qci);
|
2018-01-22 14:14:20 +00:00
|
|
|
|
2018-01-17 06:41:45 +00:00
|
|
|
e_rab->e_RABLevelQoSParameters.allocationRetentionPriority.
|
|
|
|
priorityLevel = bearer->qos.arp.priority_level;
|
|
|
|
e_rab->e_RABLevelQoSParameters.allocationRetentionPriority.
|
|
|
|
pre_emptionCapability = !(bearer->qos.arp.pre_emption_capability);
|
|
|
|
e_rab->e_RABLevelQoSParameters.allocationRetentionPriority.
|
|
|
|
pre_emptionVulnerability = !(bearer->qos.arp.pre_emption_vulnerability);
|
|
|
|
|
|
|
|
if (bearer->qos.mbr.downlink || bearer->qos.mbr.uplink ||
|
|
|
|
bearer->qos.gbr.downlink || bearer->qos.gbr.uplink)
|
|
|
|
{
|
|
|
|
if (bearer->qos.mbr.downlink == 0)
|
|
|
|
bearer->qos.mbr.downlink = MAX_BIT_RATE;
|
|
|
|
if (bearer->qos.mbr.uplink == 0)
|
|
|
|
bearer->qos.mbr.uplink = MAX_BIT_RATE;
|
|
|
|
if (bearer->qos.gbr.downlink == 0)
|
|
|
|
bearer->qos.gbr.downlink = MAX_BIT_RATE;
|
|
|
|
if (bearer->qos.gbr.uplink == 0)
|
|
|
|
bearer->qos.gbr.uplink = MAX_BIT_RATE;
|
|
|
|
|
|
|
|
gbrQosInformation =
|
|
|
|
core_calloc(1, sizeof(struct S1ap_GBR_QosInformation));
|
|
|
|
asn_uint642INTEGER(&gbrQosInformation->e_RAB_MaximumBitrateDL,
|
|
|
|
bearer->qos.mbr.downlink);
|
|
|
|
asn_uint642INTEGER(&gbrQosInformation->e_RAB_MaximumBitrateUL,
|
|
|
|
bearer->qos.mbr.uplink);
|
|
|
|
asn_uint642INTEGER(&gbrQosInformation->e_RAB_GuaranteedBitrateDL,
|
|
|
|
bearer->qos.gbr.downlink);
|
|
|
|
asn_uint642INTEGER(&gbrQosInformation->e_RAB_GuaranteedBitrateUL,
|
|
|
|
bearer->qos.gbr.uplink);
|
|
|
|
e_rab->e_RABLevelQoSParameters.gbrQosInformation = gbrQosInformation;
|
|
|
|
}
|
|
|
|
|
|
|
|
nasPdu = &e_rab->nAS_PDU;
|
|
|
|
nasPdu->size = esmbuf->len;
|
|
|
|
nasPdu->buf = core_calloc(nasPdu->size, sizeof(c_uint8_t));
|
|
|
|
memcpy(nasPdu->buf, esmbuf->payload, nasPdu->size);
|
|
|
|
|
|
|
|
ASN_SEQUENCE_ADD(&ies->e_RABToBeModifiedListBearerModReq, e_rab);
|
|
|
|
|
|
|
|
message.procedureCode = S1ap_ProcedureCode_id_E_RABModify;
|
|
|
|
message.direction = S1AP_PDU_PR_initiatingMessage;
|
|
|
|
|
|
|
|
encoded = s1ap_encode_pdu(s1apbuf, &message);
|
|
|
|
s1ap_free_pdu(&message);
|
|
|
|
|
|
|
|
d_assert(s1apbuf && encoded >= 0,return CORE_ERROR,);
|
|
|
|
|
|
|
|
pkbuf_free(esmbuf);
|
|
|
|
|
|
|
|
return CORE_OK;
|
|
|
|
}
|
|
|
|
|
2017-09-07 14:41:05 +00:00
|
|
|
status_t s1ap_build_e_rab_release_command(pkbuf_t **s1apbuf,
|
2018-01-21 11:31:28 +00:00
|
|
|
mme_bearer_t *bearer, pkbuf_t *esmbuf,
|
|
|
|
S1ap_Cause_PR group, long cause)
|
2017-09-07 14:41:05 +00:00
|
|
|
{
|
|
|
|
int encoded;
|
|
|
|
s1ap_message_t message;
|
|
|
|
S1ap_E_RABReleaseCommandIEs_t *ies = &message.s1ap_E_RABReleaseCommandIEs;
|
|
|
|
S1ap_E_RABItem_t *e_rab = NULL;
|
|
|
|
S1ap_NAS_PDU_t *nasPdu = NULL;
|
|
|
|
mme_ue_t *mme_ue = NULL;
|
|
|
|
enb_ue_t *enb_ue = NULL;
|
|
|
|
s6a_subscription_data_t *subscription_data = NULL;
|
|
|
|
|
|
|
|
d_assert(esmbuf, return CORE_ERROR, "Null param");
|
|
|
|
d_assert(bearer, return CORE_ERROR, "Null param");
|
|
|
|
|
|
|
|
mme_ue = bearer->mme_ue;
|
|
|
|
d_assert(mme_ue, return CORE_ERROR, "Null param");
|
|
|
|
enb_ue = mme_ue->enb_ue;
|
|
|
|
d_assert(enb_ue, return CORE_ERROR, "Null param");
|
|
|
|
subscription_data = &mme_ue->subscription_data;
|
|
|
|
d_assert(subscription_data, return CORE_ERROR, "Null param");
|
|
|
|
|
2018-02-09 07:26:55 +00:00
|
|
|
d_trace(3, "[MME] E-RAB release command\n");
|
2018-01-23 06:38:07 +00:00
|
|
|
d_trace(5, " ENB_UE_S1AP_ID[%d] MME_UE_S1AP_ID[%d]\n",
|
2018-01-22 14:14:20 +00:00
|
|
|
enb_ue->enb_ue_s1ap_id, enb_ue->mme_ue_s1ap_id);
|
|
|
|
|
2017-09-07 14:41:05 +00:00
|
|
|
memset(&message, 0, sizeof(s1ap_message_t));
|
|
|
|
|
|
|
|
ies->mme_ue_s1ap_id = enb_ue->mme_ue_s1ap_id;
|
|
|
|
ies->eNB_UE_S1AP_ID = enb_ue->enb_ue_s1ap_id;
|
|
|
|
|
|
|
|
ies->presenceMask |=
|
|
|
|
S1AP_E_RABRELEASECOMMANDIES_UEAGGREGATEMAXIMUMBITRATE_PRESENT;
|
|
|
|
asn_uint642INTEGER(
|
|
|
|
&ies->uEaggregateMaximumBitrate.uEaggregateMaximumBitRateUL,
|
|
|
|
subscription_data->ambr.uplink);
|
|
|
|
asn_uint642INTEGER(
|
|
|
|
&ies->uEaggregateMaximumBitrate.uEaggregateMaximumBitRateDL,
|
|
|
|
subscription_data->ambr.downlink);
|
|
|
|
|
|
|
|
e_rab = (S1ap_E_RABItem_t *)core_calloc(1, sizeof(S1ap_E_RABItem_t));
|
|
|
|
e_rab->e_RAB_ID = bearer->ebi;
|
2018-01-21 11:31:28 +00:00
|
|
|
e_rab->cause.present = group;
|
|
|
|
e_rab->cause.choice.radioNetwork = cause;
|
2017-09-07 14:41:05 +00:00
|
|
|
|
2018-01-23 06:38:07 +00:00
|
|
|
d_trace(5, " EBI[%d] Gruop[%d] Cause[%d]\n", bearer->ebi, group, cause);
|
2018-01-22 14:14:20 +00:00
|
|
|
|
2017-09-07 14:41:05 +00:00
|
|
|
ies->presenceMask |= S1AP_E_RABRELEASECOMMANDIES_NAS_PDU_PRESENT;
|
|
|
|
nasPdu = &ies->nas_pdu;
|
|
|
|
nasPdu->size = esmbuf->len;
|
|
|
|
nasPdu->buf = core_calloc(nasPdu->size, sizeof(c_uint8_t));
|
|
|
|
memcpy(nasPdu->buf, esmbuf->payload, nasPdu->size);
|
|
|
|
|
|
|
|
ASN_SEQUENCE_ADD(&ies->e_RABToBeReleasedList, e_rab);
|
|
|
|
|
|
|
|
message.procedureCode = S1ap_ProcedureCode_id_E_RABRelease;
|
|
|
|
message.direction = S1AP_PDU_PR_initiatingMessage;
|
|
|
|
|
|
|
|
encoded = s1ap_encode_pdu(s1apbuf, &message);
|
|
|
|
s1ap_free_pdu(&message);
|
|
|
|
|
|
|
|
d_assert(s1apbuf && encoded >= 0,return CORE_ERROR,);
|
|
|
|
|
|
|
|
pkbuf_free(esmbuf);
|
|
|
|
|
|
|
|
return CORE_OK;
|
|
|
|
}
|
|
|
|
|
2018-01-21 11:31:28 +00:00
|
|
|
status_t s1ap_build_ue_context_release_command(
|
|
|
|
pkbuf_t **s1apbuf, enb_ue_t *enb_ue, S1ap_Cause_PR group, long cause)
|
2017-04-28 02:20:09 +00:00
|
|
|
{
|
|
|
|
int encoded;
|
|
|
|
s1ap_message_t message;
|
|
|
|
S1ap_UEContextReleaseCommand_IEs_t *ies =
|
|
|
|
&message.s1ap_UEContextReleaseCommand_IEs;
|
|
|
|
|
2017-04-28 07:11:45 +00:00
|
|
|
d_assert(enb_ue, return CORE_ERROR, "Null param");
|
2017-04-28 02:20:09 +00:00
|
|
|
|
|
|
|
memset(&message, 0, sizeof(s1ap_message_t));
|
|
|
|
|
2017-04-28 07:11:45 +00:00
|
|
|
if (enb_ue->mme_ue_s1ap_id == 0)
|
2017-04-28 02:20:09 +00:00
|
|
|
{
|
2017-04-28 07:11:45 +00:00
|
|
|
d_error("invalid mme ue s1ap id (idx: %d)", enb_ue->index);
|
2017-04-28 02:20:09 +00:00
|
|
|
return CORE_ERROR;
|
|
|
|
}
|
|
|
|
|
2018-02-04 07:01:09 +00:00
|
|
|
#if 0 /* ENB_UE_S1AP_ID could be allocated with 0 from eNodeB */
|
2017-04-28 07:11:45 +00:00
|
|
|
if (enb_ue->enb_ue_s1ap_id)
|
2018-02-04 07:01:09 +00:00
|
|
|
#endif
|
2017-04-28 02:20:09 +00:00
|
|
|
{
|
|
|
|
ies->uE_S1AP_IDs.present = S1ap_UE_S1AP_IDs_PR_uE_S1AP_ID_pair;
|
2017-04-28 07:11:45 +00:00
|
|
|
ies->uE_S1AP_IDs.choice.uE_S1AP_ID_pair.mME_UE_S1AP_ID =
|
|
|
|
enb_ue->mme_ue_s1ap_id;
|
|
|
|
ies->uE_S1AP_IDs.choice.uE_S1AP_ID_pair.eNB_UE_S1AP_ID =
|
|
|
|
enb_ue->enb_ue_s1ap_id;
|
2017-04-28 02:20:09 +00:00
|
|
|
ies->uE_S1AP_IDs.choice.uE_S1AP_ID_pair.iE_Extensions = NULL;
|
|
|
|
}
|
2018-02-04 07:01:09 +00:00
|
|
|
#if 0
|
2017-04-28 02:20:09 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
ies->uE_S1AP_IDs.present = S1ap_UE_S1AP_IDs_PR_mME_UE_S1AP_ID;
|
2017-04-28 07:11:45 +00:00
|
|
|
ies->uE_S1AP_IDs.choice.mME_UE_S1AP_ID = enb_ue->mme_ue_s1ap_id;
|
2017-04-28 02:20:09 +00:00
|
|
|
}
|
2018-02-04 07:01:09 +00:00
|
|
|
#endif
|
2017-04-28 02:20:09 +00:00
|
|
|
|
2018-01-21 11:31:28 +00:00
|
|
|
ies->cause.present = group;
|
|
|
|
ies->cause.choice.radioNetwork = cause;
|
2017-04-28 02:20:09 +00:00
|
|
|
|
|
|
|
message.procedureCode = S1ap_ProcedureCode_id_UEContextRelease;
|
|
|
|
message.direction = S1AP_PDU_PR_initiatingMessage;
|
|
|
|
|
|
|
|
encoded = s1ap_encode_pdu(s1apbuf, &message);
|
|
|
|
s1ap_free_pdu(&message);
|
|
|
|
|
2017-07-25 12:15:25 +00:00
|
|
|
d_assert(s1apbuf && encoded >= 0, return CORE_ERROR,);
|
2017-04-28 02:20:09 +00:00
|
|
|
|
|
|
|
return CORE_OK;
|
|
|
|
}
|
2017-08-04 21:34:52 +00:00
|
|
|
|
|
|
|
status_t s1ap_build_paging(pkbuf_t **s1apbuf, mme_ue_t *mme_ue)
|
|
|
|
{
|
|
|
|
int encoded;
|
|
|
|
s1ap_message_t message;
|
|
|
|
S1ap_PagingIEs_t *ies = &message.s1ap_PagingIEs;
|
|
|
|
S1ap_TAIItem_t *tai_item = NULL;
|
|
|
|
c_uint16_t index_value;
|
|
|
|
c_uint64_t ue_imsi_value = 0;
|
|
|
|
int i = 0;
|
|
|
|
|
|
|
|
d_assert(mme_ue, return CORE_ERROR, "Null param");
|
|
|
|
|
|
|
|
memset(&message, 0, sizeof(s1ap_message_t));
|
|
|
|
|
2018-01-22 14:14:20 +00:00
|
|
|
d_trace(3, "[MME] Paging\n");
|
|
|
|
|
2017-08-04 21:34:52 +00:00
|
|
|
/* Set UE Identity Index value : IMSI mod 4096 */
|
|
|
|
ies->ueIdentityIndexValue.size = 2;
|
|
|
|
ies->ueIdentityIndexValue.buf =
|
|
|
|
core_calloc(ies->ueIdentityIndexValue.size, sizeof(c_uint8_t));
|
|
|
|
|
|
|
|
/* Conver string to value */
|
|
|
|
for (i = 0; i < strlen(mme_ue->imsi_bcd); i++)
|
|
|
|
{
|
|
|
|
ue_imsi_value = ue_imsi_value*10 + (mme_ue->imsi_bcd[i] - '0');
|
|
|
|
}
|
|
|
|
|
|
|
|
/* index(10bit) = ue_imsi_value mod 1024 */
|
|
|
|
index_value = ue_imsi_value % 1024;
|
|
|
|
ies->ueIdentityIndexValue.buf[0] = index_value >> 2;
|
|
|
|
ies->ueIdentityIndexValue.buf[1] = (index_value & 0x3f) << 6;
|
|
|
|
ies->ueIdentityIndexValue.bits_unused = 6;
|
|
|
|
|
|
|
|
/* Set Paging Identity */
|
|
|
|
ies->uePagingID.present = S1ap_UEPagingID_PR_s_TMSI;
|
|
|
|
s1ap_uint8_to_OCTET_STRING(mme_ue->guti.mme_code,
|
|
|
|
&ies->uePagingID.choice.s_TMSI.mMEC);
|
|
|
|
|
|
|
|
s1ap_uint32_to_OCTET_STRING(mme_ue->guti.m_tmsi,
|
|
|
|
&ies->uePagingID.choice.s_TMSI.m_TMSI);
|
|
|
|
|
2018-01-23 06:38:07 +00:00
|
|
|
d_trace(5, " MME_CODE[%d] M_TMSI[0x%x]\n",
|
2018-01-22 14:14:20 +00:00
|
|
|
mme_ue->guti.mme_code, mme_ue->guti.m_tmsi);
|
|
|
|
|
2017-08-04 21:34:52 +00:00
|
|
|
/* FIXME : fixed to ps */
|
|
|
|
ies->cnDomain = S1ap_CNDomain_ps;
|
|
|
|
|
|
|
|
|
|
|
|
tai_item = core_calloc(1, sizeof(S1ap_TAIItem_t));
|
|
|
|
s1ap_buffer_to_OCTET_STRING(&mme_ue->tai.plmn_id, sizeof(plmn_id_t),
|
|
|
|
&tai_item->tAI.pLMNidentity);
|
|
|
|
s1ap_uint16_to_OCTET_STRING(mme_ue->tai.tac, &tai_item->tAI.tAC);
|
|
|
|
|
|
|
|
ASN_SEQUENCE_ADD(&ies->taiList, tai_item);
|
|
|
|
|
|
|
|
message.procedureCode = S1ap_ProcedureCode_id_Paging;
|
|
|
|
message.direction = S1AP_PDU_PR_initiatingMessage;
|
|
|
|
|
|
|
|
encoded = s1ap_encode_pdu(s1apbuf, &message);
|
|
|
|
s1ap_free_pdu(&message);
|
|
|
|
|
|
|
|
d_assert(s1apbuf && encoded >= 0, return CORE_ERROR,);
|
|
|
|
|
|
|
|
return CORE_OK;
|
|
|
|
}
|
2017-09-10 14:03:24 +00:00
|
|
|
|
2017-09-11 12:14:55 +00:00
|
|
|
status_t s1ap_build_path_switch_ack(pkbuf_t **s1apbuf, mme_ue_t *mme_ue)
|
|
|
|
{
|
|
|
|
int encoded;
|
|
|
|
s1ap_message_t message;
|
|
|
|
S1ap_PathSwitchRequestAcknowledgeIEs_t *ies =
|
|
|
|
&message.s1ap_PathSwitchRequestAcknowledgeIEs;
|
|
|
|
enb_ue_t *enb_ue = NULL;
|
|
|
|
|
|
|
|
d_assert(mme_ue, return CORE_ERROR, "Null param");
|
|
|
|
enb_ue = mme_ue->enb_ue;
|
|
|
|
d_assert(enb_ue, return CORE_ERROR, "Null param");
|
|
|
|
|
2018-01-22 14:14:20 +00:00
|
|
|
d_trace(3, "[MME] Path switch acknowledge\n");
|
2018-01-23 06:38:07 +00:00
|
|
|
d_trace(5, " ENB_UE_S1AP_ID[%d] MME_UE_S1AP_ID[%d]\n",
|
2018-01-22 14:14:20 +00:00
|
|
|
enb_ue->enb_ue_s1ap_id, enb_ue->mme_ue_s1ap_id);
|
|
|
|
|
2017-09-11 12:14:55 +00:00
|
|
|
memset(&message, 0, sizeof(s1ap_message_t));
|
|
|
|
|
|
|
|
ies->mme_ue_s1ap_id = enb_ue->mme_ue_s1ap_id;
|
|
|
|
ies->eNB_UE_S1AP_ID = enb_ue->enb_ue_s1ap_id;
|
|
|
|
|
2017-09-12 01:41:00 +00:00
|
|
|
ies->securityContext.nextHopChainingCount = mme_ue->nhcc;
|
2017-09-11 12:14:55 +00:00
|
|
|
ies->securityContext.nextHopParameter.size = SHA256_DIGEST_SIZE;
|
|
|
|
ies->securityContext.nextHopParameter.buf =
|
|
|
|
core_calloc(ies->securityContext.nextHopParameter.size,
|
|
|
|
sizeof(c_uint8_t));
|
|
|
|
ies->securityContext.nextHopParameter.bits_unused = 0;
|
|
|
|
memcpy(ies->securityContext.nextHopParameter.buf,
|
2017-09-12 01:41:00 +00:00
|
|
|
mme_ue->nh, ies->securityContext.nextHopParameter.size);
|
2017-09-11 12:14:55 +00:00
|
|
|
|
|
|
|
message.procedureCode = S1ap_ProcedureCode_id_PathSwitchRequest;
|
|
|
|
message.direction = S1AP_PDU_PR_successfulOutcome;
|
|
|
|
|
|
|
|
encoded = s1ap_encode_pdu(s1apbuf, &message);
|
|
|
|
s1ap_free_pdu(&message);
|
|
|
|
|
|
|
|
d_assert(s1apbuf && encoded >= 0,return CORE_ERROR,);
|
|
|
|
|
|
|
|
return CORE_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
status_t s1ap_build_path_switch_failure(pkbuf_t **s1apbuf,
|
2018-01-21 11:31:28 +00:00
|
|
|
c_uint32_t enb_ue_s1ap_id, c_uint32_t mme_ue_s1ap_id,
|
|
|
|
S1ap_Cause_PR group, long cause)
|
2017-09-11 12:14:55 +00:00
|
|
|
{
|
|
|
|
int encoded;
|
|
|
|
s1ap_message_t message;
|
|
|
|
S1ap_PathSwitchRequestFailureIEs_t *ies =
|
|
|
|
&message.s1ap_PathSwitchRequestFailureIEs;
|
|
|
|
|
|
|
|
memset(&message, 0, sizeof(s1ap_message_t));
|
|
|
|
|
2018-01-22 14:14:20 +00:00
|
|
|
d_trace(3, "[MME] Path switch failure\n");
|
2018-01-23 06:38:07 +00:00
|
|
|
d_trace(5, " ENB_UE_S1AP_ID[%d] MME_UE_S1AP_ID[%d]\n",
|
2018-01-22 14:14:20 +00:00
|
|
|
enb_ue_s1ap_id, mme_ue_s1ap_id);
|
2018-01-23 06:38:07 +00:00
|
|
|
d_trace(5, " Group[%d] Cause[%d]\n", group, cause);
|
2018-01-22 14:14:20 +00:00
|
|
|
|
2017-09-11 12:14:55 +00:00
|
|
|
ies->mme_ue_s1ap_id = mme_ue_s1ap_id;
|
|
|
|
ies->eNB_UE_S1AP_ID = enb_ue_s1ap_id;
|
2018-01-21 11:31:28 +00:00
|
|
|
ies->cause.present = group;
|
|
|
|
ies->cause.choice.radioNetwork = cause;
|
2017-09-11 12:14:55 +00:00
|
|
|
|
|
|
|
message.procedureCode = S1ap_ProcedureCode_id_PathSwitchRequest;
|
|
|
|
message.direction = S1AP_PDU_PR_unsuccessfulOutcome;
|
|
|
|
|
|
|
|
encoded = s1ap_encode_pdu(s1apbuf, &message);
|
|
|
|
s1ap_free_pdu(&message);
|
|
|
|
|
|
|
|
d_assert(s1apbuf && encoded >= 0,return CORE_ERROR,);
|
|
|
|
|
|
|
|
return CORE_OK;
|
|
|
|
}
|
|
|
|
|
2017-09-15 04:28:07 +00:00
|
|
|
status_t s1ap_build_handover_command(pkbuf_t **s1apbuf, enb_ue_t *source_ue)
|
|
|
|
{
|
2017-12-07 08:23:45 +00:00
|
|
|
status_t rv;
|
2017-09-15 04:28:07 +00:00
|
|
|
|
|
|
|
int encoded;
|
|
|
|
s1ap_message_t message;
|
|
|
|
S1ap_HandoverCommandIEs_t *ies = &message.s1ap_HandoverCommandIEs;
|
|
|
|
S1ap_E_RABDataForwardingItem_t *e_rab = NULL;
|
|
|
|
|
|
|
|
mme_ue_t *mme_ue = NULL;
|
|
|
|
mme_sess_t *sess = NULL;
|
|
|
|
mme_bearer_t *bearer = NULL;
|
|
|
|
|
|
|
|
d_assert(source_ue, return CORE_ERROR, "Null param");
|
|
|
|
mme_ue = source_ue->mme_ue;
|
|
|
|
|
2018-01-22 14:14:20 +00:00
|
|
|
d_trace(3, "[MME] Handover command\n");
|
|
|
|
|
2017-09-15 04:28:07 +00:00
|
|
|
memset(&message, 0, sizeof(s1ap_message_t));
|
|
|
|
|
|
|
|
ies->mme_ue_s1ap_id = source_ue->mme_ue_s1ap_id;
|
|
|
|
ies->eNB_UE_S1AP_ID = source_ue->enb_ue_s1ap_id;
|
|
|
|
ies->handoverType = source_ue->handover_type;
|
|
|
|
|
2018-01-23 06:38:07 +00:00
|
|
|
d_trace(5, " ENB_UE_S1AP_ID[%d] MME_UE_S1AP_ID[%d]\n",
|
2018-01-22 14:14:20 +00:00
|
|
|
source_ue->enb_ue_s1ap_id, source_ue->mme_ue_s1ap_id);
|
|
|
|
|
2017-09-15 04:28:07 +00:00
|
|
|
sess = mme_sess_first(mme_ue);
|
|
|
|
while(sess)
|
|
|
|
{
|
|
|
|
bearer = mme_bearer_first(sess);
|
|
|
|
while(bearer)
|
|
|
|
{
|
|
|
|
if (MME_HAVE_SGW_DL_INDIRECT_TUNNEL(bearer) ||
|
|
|
|
MME_HAVE_SGW_UL_INDIRECT_TUNNEL(bearer))
|
|
|
|
{
|
|
|
|
e_rab = (S1ap_E_RABDataForwardingItem_t *)
|
|
|
|
core_calloc(1, sizeof(S1ap_E_RABDataForwardingItem_t));
|
|
|
|
e_rab->e_RAB_ID = bearer->ebi;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (MME_HAVE_SGW_DL_INDIRECT_TUNNEL(bearer))
|
|
|
|
{
|
|
|
|
e_rab->dL_transportLayerAddress =
|
|
|
|
(S1ap_TransportLayerAddress_t *)
|
|
|
|
core_calloc(1, sizeof(S1ap_TransportLayerAddress_t));
|
2017-12-07 08:23:45 +00:00
|
|
|
rv = s1ap_ip_to_BIT_STRING(
|
|
|
|
&bearer->sgw_dl_ip, e_rab->dL_transportLayerAddress);
|
|
|
|
d_assert(rv == CORE_OK, return CORE_ERROR,);
|
2017-09-15 04:28:07 +00:00
|
|
|
|
|
|
|
e_rab->dL_gTP_TEID = (S1ap_GTP_TEID_t *)
|
|
|
|
core_calloc(1, sizeof(S1ap_GTP_TEID_t));
|
|
|
|
s1ap_uint32_to_OCTET_STRING(
|
|
|
|
bearer->sgw_dl_teid, e_rab->dL_gTP_TEID);
|
2018-02-01 05:07:01 +00:00
|
|
|
d_trace(5, " SGW-DL-TEID[%d]\n", bearer->sgw_dl_teid);
|
2017-09-15 04:28:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (MME_HAVE_SGW_UL_INDIRECT_TUNNEL(bearer))
|
|
|
|
{
|
|
|
|
e_rab->uL_S1ap_TransportLayerAddress =
|
|
|
|
(S1ap_TransportLayerAddress_t *)
|
|
|
|
core_calloc(1, sizeof(S1ap_TransportLayerAddress_t));
|
2017-12-07 08:23:45 +00:00
|
|
|
rv = s1ap_ip_to_BIT_STRING(
|
|
|
|
&bearer->sgw_ul_ip, e_rab->uL_S1ap_TransportLayerAddress);
|
|
|
|
d_assert(rv == CORE_OK, return CORE_ERROR,);
|
2017-09-15 04:28:07 +00:00
|
|
|
|
|
|
|
e_rab->uL_S1ap_GTP_TEID = (S1ap_GTP_TEID_t *)
|
|
|
|
core_calloc(1, sizeof(S1ap_GTP_TEID_t));
|
|
|
|
s1ap_uint32_to_OCTET_STRING(
|
|
|
|
bearer->sgw_ul_teid, e_rab->uL_S1ap_GTP_TEID);
|
2018-02-01 05:07:01 +00:00
|
|
|
d_trace(5, " SGW-UL-TEID[%d]\n", bearer->sgw_dl_teid);
|
2017-09-15 04:28:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (MME_HAVE_SGW_DL_INDIRECT_TUNNEL(bearer) ||
|
|
|
|
MME_HAVE_SGW_UL_INDIRECT_TUNNEL(bearer))
|
|
|
|
{
|
|
|
|
ASN_SEQUENCE_ADD(&ies->e_RABDataForwardingList, e_rab);
|
|
|
|
}
|
|
|
|
|
|
|
|
bearer = mme_bearer_next(bearer);
|
|
|
|
}
|
|
|
|
sess = mme_sess_next(sess);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ies->e_RABDataForwardingList.s1ap_E_RABDataForwardingItem.count)
|
|
|
|
{
|
|
|
|
ies->presenceMask |=
|
|
|
|
S1AP_HANDOVERCOMMANDIES_E_RABDATAFORWARDINGLIST_PRESENT;
|
|
|
|
}
|
|
|
|
|
|
|
|
s1ap_buffer_to_OCTET_STRING(mme_ue->container.buf, mme_ue->container.size,
|
|
|
|
&ies->target_ToSource_TransparentContainer);
|
|
|
|
|
|
|
|
message.procedureCode = S1ap_ProcedureCode_id_HandoverPreparation;
|
|
|
|
message.direction = S1AP_PDU_PR_successfulOutcome;
|
|
|
|
|
|
|
|
encoded = s1ap_encode_pdu(s1apbuf, &message);
|
|
|
|
s1ap_free_pdu(&message);
|
|
|
|
|
|
|
|
d_assert(s1apbuf && encoded >= 0,return CORE_ERROR,);
|
|
|
|
|
|
|
|
return CORE_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
status_t s1ap_build_handover_preparation_failure(
|
|
|
|
pkbuf_t **s1apbuf, enb_ue_t *source_ue, S1ap_Cause_t *cause)
|
|
|
|
{
|
|
|
|
int encoded;
|
|
|
|
s1ap_message_t message;
|
|
|
|
S1ap_HandoverPreparationFailureIEs_t *ies =
|
|
|
|
&message.s1ap_HandoverPreparationFailureIEs;
|
|
|
|
|
2018-01-21 11:31:28 +00:00
|
|
|
d_assert(s1apbuf, return CORE_ERROR,);
|
|
|
|
d_assert(source_ue, return CORE_ERROR,);
|
|
|
|
d_assert(cause, return CORE_ERROR,);
|
|
|
|
|
2017-09-15 04:28:07 +00:00
|
|
|
memset(&message, 0, sizeof(s1ap_message_t));
|
|
|
|
|
2018-01-22 14:14:20 +00:00
|
|
|
d_trace(3, "[MME] Handover preparation failure\n");
|
|
|
|
|
2017-09-15 04:28:07 +00:00
|
|
|
ies->mme_ue_s1ap_id = source_ue->mme_ue_s1ap_id;
|
|
|
|
ies->eNB_UE_S1AP_ID = source_ue->enb_ue_s1ap_id;
|
2018-01-21 11:31:28 +00:00
|
|
|
ies->cause.present = cause->present;
|
|
|
|
ies->cause.choice.radioNetwork = cause->choice.radioNetwork;
|
2017-09-15 04:28:07 +00:00
|
|
|
|
2018-01-23 06:38:07 +00:00
|
|
|
d_trace(5, " ENB_UE_S1AP_ID[%d] MME_UE_S1AP_ID[%d]\n",
|
2018-01-22 14:14:20 +00:00
|
|
|
source_ue->enb_ue_s1ap_id, source_ue->mme_ue_s1ap_id);
|
2018-01-23 06:38:07 +00:00
|
|
|
d_trace(5, " Group[%d] Cause[%d]\n",
|
2018-01-22 14:14:20 +00:00
|
|
|
cause->present, cause->choice.radioNetwork);
|
|
|
|
|
2017-09-15 04:28:07 +00:00
|
|
|
message.procedureCode = S1ap_ProcedureCode_id_HandoverPreparation;
|
|
|
|
message.direction = S1AP_PDU_PR_unsuccessfulOutcome;
|
|
|
|
|
|
|
|
encoded = s1ap_encode_pdu(s1apbuf, &message);
|
|
|
|
s1ap_free_pdu(&message);
|
|
|
|
|
|
|
|
d_assert(s1apbuf && encoded >= 0,return CORE_ERROR,);
|
|
|
|
|
|
|
|
return CORE_OK;
|
|
|
|
}
|
|
|
|
|
2017-09-12 14:07:55 +00:00
|
|
|
status_t s1ap_build_handover_request(
|
2017-09-15 03:06:26 +00:00
|
|
|
pkbuf_t **s1apbuf, mme_ue_t *mme_ue, enb_ue_t *target_ue,
|
2017-09-12 14:07:55 +00:00
|
|
|
S1ap_HandoverRequiredIEs_t *required)
|
|
|
|
{
|
2017-12-07 08:40:15 +00:00
|
|
|
status_t rv;
|
2017-09-12 14:07:55 +00:00
|
|
|
|
|
|
|
int encoded;
|
|
|
|
s1ap_message_t message;
|
|
|
|
S1ap_HandoverRequestIEs_t *ies = &message.s1ap_HandoverRequestIEs;
|
|
|
|
S1ap_E_RABToBeSetupItemHOReq_t *e_rab = NULL;
|
|
|
|
struct S1ap_GBR_QosInformation *gbrQosInformation = NULL; /* OPTIONAL */
|
|
|
|
|
|
|
|
mme_sess_t *sess = NULL;
|
|
|
|
mme_bearer_t *bearer = NULL;
|
|
|
|
s6a_subscription_data_t *subscription_data = NULL;
|
|
|
|
|
2017-09-15 03:06:26 +00:00
|
|
|
d_assert(target_ue, return CORE_ERROR, "Null param");
|
2017-09-12 14:07:55 +00:00
|
|
|
d_assert(mme_ue, return CORE_ERROR, "Null param");
|
|
|
|
d_assert(required, return CORE_ERROR, "Null param");
|
|
|
|
subscription_data = &mme_ue->subscription_data;
|
|
|
|
d_assert(subscription_data, return CORE_ERROR, "Null param");
|
|
|
|
|
|
|
|
memset(&message, 0, sizeof(s1ap_message_t));
|
|
|
|
|
2017-09-15 03:06:26 +00:00
|
|
|
ies->mme_ue_s1ap_id = target_ue->mme_ue_s1ap_id;
|
2017-09-12 14:07:55 +00:00
|
|
|
ies->handoverType = required->handoverType;
|
2018-01-21 11:31:28 +00:00
|
|
|
ies->cause.present = required->cause.present;
|
|
|
|
ies->cause.choice.radioNetwork = required->cause.choice.radioNetwork;
|
2017-09-12 14:07:55 +00:00
|
|
|
|
|
|
|
asn_uint642INTEGER(
|
|
|
|
&ies->uEaggregateMaximumBitrate.uEaggregateMaximumBitRateUL,
|
|
|
|
subscription_data->ambr.uplink);
|
|
|
|
asn_uint642INTEGER(
|
|
|
|
&ies->uEaggregateMaximumBitrate.uEaggregateMaximumBitRateDL,
|
|
|
|
subscription_data->ambr.downlink);
|
|
|
|
|
|
|
|
sess = mme_sess_first(mme_ue);
|
|
|
|
while(sess)
|
|
|
|
{
|
|
|
|
bearer = mme_bearer_first(sess);
|
|
|
|
while(bearer)
|
|
|
|
{
|
|
|
|
e_rab = (S1ap_E_RABToBeSetupItemHOReq_t *)
|
|
|
|
core_calloc(1, sizeof(S1ap_E_RABToBeSetupItemHOReq_t));
|
|
|
|
e_rab->e_RAB_ID = bearer->ebi;
|
|
|
|
e_rab->e_RABlevelQosParameters.qCI = bearer->qos.qci;
|
|
|
|
|
|
|
|
e_rab->e_RABlevelQosParameters.allocationRetentionPriority.
|
|
|
|
priorityLevel = bearer->qos.arp.priority_level;
|
|
|
|
e_rab->e_RABlevelQosParameters.allocationRetentionPriority.
|
|
|
|
pre_emptionCapability =
|
|
|
|
!(bearer->qos.arp.pre_emption_capability);
|
|
|
|
e_rab->e_RABlevelQosParameters.allocationRetentionPriority.
|
|
|
|
pre_emptionVulnerability =
|
|
|
|
!(bearer->qos.arp.pre_emption_vulnerability);
|
|
|
|
|
|
|
|
if (bearer->qos.mbr.downlink || bearer->qos.mbr.uplink ||
|
|
|
|
bearer->qos.gbr.downlink || bearer->qos.gbr.uplink)
|
|
|
|
{
|
|
|
|
if (bearer->qos.mbr.downlink == 0)
|
|
|
|
bearer->qos.mbr.downlink = MAX_BIT_RATE;
|
|
|
|
if (bearer->qos.mbr.uplink == 0)
|
|
|
|
bearer->qos.mbr.uplink = MAX_BIT_RATE;
|
|
|
|
if (bearer->qos.gbr.downlink == 0)
|
|
|
|
bearer->qos.gbr.downlink = MAX_BIT_RATE;
|
|
|
|
if (bearer->qos.gbr.uplink == 0)
|
|
|
|
bearer->qos.gbr.uplink = MAX_BIT_RATE;
|
|
|
|
|
|
|
|
gbrQosInformation =
|
|
|
|
core_calloc(1, sizeof(struct S1ap_GBR_QosInformation));
|
|
|
|
asn_uint642INTEGER(&gbrQosInformation->e_RAB_MaximumBitrateDL,
|
|
|
|
bearer->qos.mbr.downlink);
|
|
|
|
asn_uint642INTEGER(&gbrQosInformation->e_RAB_MaximumBitrateUL,
|
|
|
|
bearer->qos.mbr.uplink);
|
|
|
|
asn_uint642INTEGER(&gbrQosInformation->
|
|
|
|
e_RAB_GuaranteedBitrateDL, bearer->qos.gbr.downlink);
|
|
|
|
asn_uint642INTEGER(&gbrQosInformation->
|
|
|
|
e_RAB_GuaranteedBitrateUL, bearer->qos.gbr.uplink);
|
|
|
|
e_rab->e_RABlevelQosParameters.gbrQosInformation =
|
|
|
|
gbrQosInformation;
|
|
|
|
}
|
|
|
|
|
2017-12-07 08:40:15 +00:00
|
|
|
rv = s1ap_ip_to_BIT_STRING(
|
|
|
|
&bearer->sgw_s1u_ip, &e_rab->transportLayerAddress);
|
|
|
|
d_assert(rv == CORE_OK, return CORE_ERROR,);
|
2017-09-12 14:07:55 +00:00
|
|
|
s1ap_uint32_to_OCTET_STRING(bearer->sgw_s1u_teid, &e_rab->gTP_TEID);
|
2018-02-01 05:07:01 +00:00
|
|
|
d_trace(5, " SGW-S1U-TEID[%d]\n", bearer->sgw_s1u_teid);
|
2017-09-12 14:07:55 +00:00
|
|
|
|
|
|
|
ASN_SEQUENCE_ADD(&ies->e_RABToBeSetupListHOReq, e_rab);
|
|
|
|
|
|
|
|
bearer = mme_bearer_next(bearer);
|
|
|
|
}
|
|
|
|
sess = mme_sess_next(sess);
|
|
|
|
}
|
|
|
|
|
|
|
|
s1ap_buffer_to_OCTET_STRING(
|
|
|
|
required->source_ToTarget_TransparentContainer.buf,
|
|
|
|
required->source_ToTarget_TransparentContainer.size,
|
|
|
|
&ies->source_ToTarget_TransparentContainer);
|
|
|
|
|
|
|
|
ies->ueSecurityCapabilities.encryptionAlgorithms.size = 2;
|
|
|
|
ies->ueSecurityCapabilities.encryptionAlgorithms.buf =
|
|
|
|
core_calloc(ies->ueSecurityCapabilities.encryptionAlgorithms.size,
|
|
|
|
sizeof(c_uint8_t));
|
|
|
|
ies->ueSecurityCapabilities.encryptionAlgorithms.bits_unused = 0;
|
|
|
|
ies->ueSecurityCapabilities.encryptionAlgorithms.buf[0] =
|
|
|
|
(mme_ue->ue_network_capability.eea << 1);
|
|
|
|
|
|
|
|
ies->ueSecurityCapabilities.integrityProtectionAlgorithms.size = 2;
|
|
|
|
ies->ueSecurityCapabilities.integrityProtectionAlgorithms.buf =
|
|
|
|
core_calloc(ies->ueSecurityCapabilities.
|
|
|
|
integrityProtectionAlgorithms.size, sizeof(c_uint8_t));
|
|
|
|
ies->ueSecurityCapabilities.integrityProtectionAlgorithms.bits_unused = 0;
|
|
|
|
ies->ueSecurityCapabilities.integrityProtectionAlgorithms.buf[0] =
|
|
|
|
(mme_ue->ue_network_capability.eia << 1);
|
|
|
|
|
|
|
|
ies->securityContext.nextHopChainingCount = mme_ue->nhcc;
|
|
|
|
ies->securityContext.nextHopParameter.size = SHA256_DIGEST_SIZE;
|
|
|
|
ies->securityContext.nextHopParameter.buf =
|
|
|
|
core_calloc(ies->securityContext.nextHopParameter.size,
|
|
|
|
sizeof(c_uint8_t));
|
|
|
|
ies->securityContext.nextHopParameter.bits_unused = 0;
|
|
|
|
memcpy(ies->securityContext.nextHopParameter.buf,
|
|
|
|
mme_ue->nh, ies->securityContext.nextHopParameter.size);
|
|
|
|
|
|
|
|
message.procedureCode = S1ap_ProcedureCode_id_HandoverResourceAllocation;
|
|
|
|
message.direction = S1AP_PDU_PR_initiatingMessage;
|
|
|
|
|
|
|
|
encoded = s1ap_encode_pdu(s1apbuf, &message);
|
|
|
|
s1ap_free_pdu(&message);
|
|
|
|
|
|
|
|
d_assert(s1apbuf && encoded >= 0,return CORE_ERROR,);
|
|
|
|
|
|
|
|
return CORE_OK;
|
|
|
|
}
|
|
|
|
|
2017-09-15 03:06:26 +00:00
|
|
|
status_t s1ap_build_handover_cancel_ack(pkbuf_t **s1apbuf, enb_ue_t *source_ue)
|
|
|
|
{
|
|
|
|
int encoded;
|
|
|
|
s1ap_message_t message;
|
|
|
|
S1ap_HandoverCancelAcknowledgeIEs_t *ies =
|
|
|
|
&message.s1ap_HandoverCancelAcknowledgeIEs;
|
|
|
|
|
|
|
|
d_assert(source_ue, return CORE_ERROR, "Null param");
|
|
|
|
|
2018-01-22 14:14:20 +00:00
|
|
|
d_trace(3, "[MME] Handover cancel acknowledge\n");
|
|
|
|
|
2017-09-15 03:06:26 +00:00
|
|
|
memset(&message, 0, sizeof(s1ap_message_t));
|
|
|
|
|
|
|
|
ies->mme_ue_s1ap_id = source_ue->mme_ue_s1ap_id;
|
|
|
|
ies->eNB_UE_S1AP_ID = source_ue->enb_ue_s1ap_id;
|
|
|
|
|
2018-01-23 06:38:07 +00:00
|
|
|
d_trace(5, " Source : ENB_UE_S1AP_ID[%d] MME_UE_S1AP_ID[%d]\n",
|
2018-01-22 14:14:20 +00:00
|
|
|
source_ue->enb_ue_s1ap_id, source_ue->mme_ue_s1ap_id);
|
|
|
|
|
2017-09-15 03:06:26 +00:00
|
|
|
message.procedureCode = S1ap_ProcedureCode_id_HandoverCancel;
|
|
|
|
message.direction = S1AP_PDU_PR_successfulOutcome;
|
|
|
|
|
|
|
|
encoded = s1ap_encode_pdu(s1apbuf, &message);
|
|
|
|
s1ap_free_pdu(&message);
|
|
|
|
|
|
|
|
d_assert(s1apbuf && encoded >= 0,return CORE_ERROR,);
|
|
|
|
|
2017-09-14 02:12:02 +00:00
|
|
|
return CORE_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
status_t s1ap_build_mme_status_transfer(pkbuf_t **s1apbuf,
|
2017-09-15 03:06:26 +00:00
|
|
|
enb_ue_t *target_ue, S1ap_ENBStatusTransferIEs_t *enb_ies)
|
2017-09-14 02:12:02 +00:00
|
|
|
{
|
2017-09-15 01:40:25 +00:00
|
|
|
int i;
|
2017-09-14 02:12:02 +00:00
|
|
|
|
|
|
|
int encoded;
|
|
|
|
s1ap_message_t message;
|
|
|
|
S1ap_MMEStatusTransferIEs_t *mme_ies = &message.s1ap_MMEStatusTransferIEs;
|
|
|
|
|
2017-09-15 03:06:26 +00:00
|
|
|
d_assert(target_ue, return CORE_ERROR, "Null param");
|
2017-09-14 02:12:02 +00:00
|
|
|
d_assert(enb_ies, return CORE_ERROR, "Null param");
|
2018-01-22 14:14:20 +00:00
|
|
|
|
|
|
|
d_trace(3, "[MME] MME status transfer\n");
|
2017-09-14 02:12:02 +00:00
|
|
|
|
|
|
|
memset(&message, 0, sizeof(s1ap_message_t));
|
|
|
|
|
2017-09-15 03:06:26 +00:00
|
|
|
mme_ies->mme_ue_s1ap_id = target_ue->mme_ue_s1ap_id;
|
|
|
|
mme_ies->eNB_UE_S1AP_ID = target_ue->enb_ue_s1ap_id;
|
2017-09-15 01:40:25 +00:00
|
|
|
|
2018-01-23 06:38:07 +00:00
|
|
|
d_trace(5, " Target : ENB_UE_S1AP_ID[%d] MME_UE_S1AP_ID[%d]\n",
|
2018-01-22 14:14:20 +00:00
|
|
|
target_ue->enb_ue_s1ap_id, target_ue->mme_ue_s1ap_id);
|
|
|
|
|
2017-09-15 01:40:25 +00:00
|
|
|
for (i = 0; i < enb_ies->eNB_StatusTransfer_TransparentContainer.
|
|
|
|
bearers_SubjectToStatusTransferList.list.count; i++)
|
|
|
|
{
|
|
|
|
S1ap_IE_t *enb_ie = NULL, *mme_ie = NULL;
|
|
|
|
|
|
|
|
enb_ie = (S1ap_IE_t *)enb_ies->
|
|
|
|
eNB_StatusTransfer_TransparentContainer.
|
|
|
|
bearers_SubjectToStatusTransferList.list.array[i];
|
|
|
|
d_assert(enb_ie, return CORE_ERROR, "Null param");
|
|
|
|
|
|
|
|
mme_ie = s1ap_copy_ie(enb_ie);
|
|
|
|
d_assert(mme_ie, return CORE_ERROR, "Null param");
|
|
|
|
|
|
|
|
ASN_SEQUENCE_ADD(&mme_ies->
|
|
|
|
eNB_StatusTransfer_TransparentContainer.
|
|
|
|
bearers_SubjectToStatusTransferList, mme_ie);
|
|
|
|
}
|
2017-09-14 02:12:02 +00:00
|
|
|
|
|
|
|
message.procedureCode = S1ap_ProcedureCode_id_MMEStatusTransfer;
|
|
|
|
message.direction = S1AP_PDU_PR_initiatingMessage;
|
|
|
|
|
|
|
|
encoded = s1ap_encode_pdu(s1apbuf, &message);
|
|
|
|
s1ap_free_pdu(&message);
|
|
|
|
|
|
|
|
d_assert(s1apbuf && encoded >= 0,return CORE_ERROR,);
|
|
|
|
|
2017-09-13 12:51:02 +00:00
|
|
|
return CORE_OK;
|
|
|
|
}
|
2018-02-03 02:48:15 +00:00
|
|
|
|
|
|
|
status_t s1ap_build_error_indication(
|
|
|
|
pkbuf_t **s1apbuf, c_uint16_t presenceMask,
|
|
|
|
c_uint32_t enb_ue_s1ap_id, c_uint32_t mme_ue_s1ap_id,
|
|
|
|
S1ap_Cause_PR group, long cause)
|
|
|
|
{
|
|
|
|
int encoded;
|
|
|
|
s1ap_message_t message;
|
|
|
|
S1ap_ErrorIndicationIEs_t *ies = &message.s1ap_ErrorIndicationIEs;
|
|
|
|
|
|
|
|
d_assert(presenceMask, return CORE_ERROR,
|
|
|
|
"Invalid PresenceMask[0x%x]", presenceMask);
|
|
|
|
|
|
|
|
d_trace(3, "[MME] Error Indication\n");
|
|
|
|
|
|
|
|
memset(&message, 0, sizeof(s1ap_message_t));
|
|
|
|
|
|
|
|
ies->presenceMask = presenceMask;
|
|
|
|
ies->mme_ue_s1ap_id = mme_ue_s1ap_id;
|
|
|
|
ies->eNB_UE_S1AP_ID = enb_ue_s1ap_id;
|
|
|
|
ies->cause.present = group;
|
|
|
|
ies->cause.choice.radioNetwork = cause;
|
|
|
|
|
|
|
|
d_trace(5, " PresenceMask[0x%x]\n", presenceMask);
|
|
|
|
d_trace(5, " ENB_UE_S1AP_ID[%d] MME_UE_S1AP_ID[%d]\n",
|
|
|
|
enb_ue_s1ap_id, mme_ue_s1ap_id);
|
|
|
|
d_trace(5, " Group[%d] Cause[%d]\n", group, cause);
|
|
|
|
|
|
|
|
message.procedureCode = S1ap_ProcedureCode_id_ErrorIndication;
|
|
|
|
message.direction = S1AP_PDU_PR_initiatingMessage;
|
|
|
|
|
|
|
|
encoded = s1ap_encode_pdu(s1apbuf, &message);
|
|
|
|
s1ap_free_pdu(&message);
|
|
|
|
|
|
|
|
d_assert(s1apbuf && encoded >= 0,return CORE_ERROR,);
|
|
|
|
|
|
|
|
return CORE_OK;
|
|
|
|
}
|