open5gs/src/mme/s1ap_path.c

377 lines
11 KiB
C
Raw Normal View History

2017-02-13 05:17:26 +00:00
#define TRACE_MODULE _s1ap_path
2017-02-13 04:19:53 +00:00
#include "core_debug.h"
#include "core_thread.h"
2017-02-13 07:03:12 +00:00
2017-04-04 01:49:19 +00:00
#include "mme_event.h"
2017-03-26 06:34:34 +00:00
2017-09-07 06:56:31 +00:00
#include "nas_security.h"
#include "nas_path.h"
2017-09-12 14:07:55 +00:00
#include "s1ap_conv.h"
#include "s1ap_build.h"
2017-09-08 07:46:37 +00:00
#include "s1ap_path.h"
2017-02-13 04:19:53 +00:00
2017-04-06 11:10:00 +00:00
status_t s1ap_send_to_enb(mme_enb_t *enb, pkbuf_t *pkbuf)
2017-02-13 04:19:53 +00:00
{
2017-03-07 07:19:18 +00:00
status_t rv = CORE_ERROR;
d_assert(enb,,);
d_assert(pkbuf,,);
d_assert(enb->sock,,);
2017-02-13 04:19:53 +00:00
2017-11-24 10:03:48 +00:00
rv = s1ap_send(enb->sock, pkbuf,
enb->sock_type == SOCK_STREAM ? NULL : enb->addr);
2017-03-26 16:50:01 +00:00
if (rv != CORE_OK)
{
d_error("s1_send error");
pkbuf_free(pkbuf);
}
2017-03-07 05:47:17 +00:00
return rv;
2017-02-13 04:19:53 +00:00
}
2017-09-07 06:56:31 +00:00
status_t s1ap_delayed_send_to_enb(
mme_enb_t *enb, pkbuf_t *pkbuf, c_uint32_t duration)
{
tm_block_id timer = 0;
d_assert(enb, return CORE_ERROR,);
d_assert(pkbuf, return CORE_ERROR,);
if (duration)
{
timer = timer_create(
&mme_self()->tm_service, MME_EVT_S1AP_DELAYED_SEND, duration);
d_assert(timer, return CORE_ERROR,);
timer_set_param1(timer, (c_uintptr_t)enb->index);
timer_set_param2(timer, (c_uintptr_t)pkbuf);
timer_set_param3(timer, timer);
tm_start(timer);
return CORE_OK;
}
else
{
return s1ap_send_to_enb(enb, pkbuf);
}
}
2017-09-07 06:56:31 +00:00
status_t s1ap_send_to_esm(mme_ue_t *mme_ue, pkbuf_t *esmbuf)
{
event_t e;
d_assert(mme_ue, return CORE_ERROR, "Null param");
d_assert(esmbuf, return CORE_ERROR, "Null param");
event_set(&e, MME_EVT_ESM_MESSAGE);
event_set_param1(&e, (c_uintptr_t)mme_ue->index);
2017-09-07 06:56:31 +00:00
event_set_param2(&e, (c_uintptr_t)esmbuf);
mme_event_send(&e);
return CORE_OK;
}
status_t s1ap_send_to_nas(enb_ue_t *enb_ue, S1ap_NAS_PDU_t *nasPdu)
{
nas_security_header_t *sh = NULL;
nas_security_header_type_t security_header_type;
nas_emm_header_t *h = NULL;
pkbuf_t *nasbuf = NULL;
event_t e;
d_assert(enb_ue, return CORE_ERROR, "Null param");
d_assert(nasPdu, return CORE_ERROR, "Null param");
/* The Packet Buffer(pkbuf_t) for NAS message MUST make a HEADROOM.
* When calculating AES_CMAC, we need to use the headroom of the packet. */
nasbuf = pkbuf_alloc(NAS_HEADROOM, nasPdu->size);
d_assert(nasbuf, return CORE_ERROR, "Null param");
memcpy(nasbuf->payload, nasPdu->buf, nasPdu->size);
sh = nasbuf->payload;
d_assert(sh, return CORE_ERROR, "Null param");
memset(&security_header_type, 0, sizeof(nas_security_header_type_t));
switch(sh->security_header_type)
{
case NAS_SECURITY_HEADER_PLAIN_NAS_MESSAGE:
break;
case NAS_SECURITY_HEADER_FOR_SERVICE_REQUEST_MESSAGE:
security_header_type.service_request = 1;
break;
case NAS_SECURITY_HEADER_INTEGRITY_PROTECTED:
security_header_type.integrity_protected = 1;
d_assert(pkbuf_header(nasbuf, -6) == CORE_OK,
return CORE_ERROR, "pkbuf_header error");
break;
case NAS_SECURITY_HEADER_INTEGRITY_PROTECTED_AND_CIPHERED:
security_header_type.integrity_protected = 1;
security_header_type.ciphered = 1;
d_assert(pkbuf_header(nasbuf, -6) == CORE_OK,
return CORE_ERROR, "pkbuf_header error");
break;
case NAS_SECURITY_HEADER_INTEGRITY_PROTECTED_AND_NEW_SECURITY_CONTEXT:
security_header_type.integrity_protected = 1;
security_header_type.new_security_context = 1;
d_assert(pkbuf_header(nasbuf, -6) == CORE_OK,
return CORE_ERROR, "pkbuf_header error");
break;
case NAS_SECURITY_HEADER_INTEGRITY_PROTECTED_AND_CIPHTERD_WITH_NEW_INTEGRITY_CONTEXT:
security_header_type.integrity_protected = 1;
security_header_type.ciphered = 1;
security_header_type.new_security_context = 1;
d_assert(pkbuf_header(nasbuf, -6) == CORE_OK,
return CORE_ERROR, "pkbuf_header error");
break;
default:
d_error("Not implemented(securiry header type:0x%x)",
sh->security_header_type);
return CORE_ERROR;
}
if (enb_ue->mme_ue)
{
d_assert(nas_security_decode(
enb_ue->mme_ue, security_header_type, nasbuf) == CORE_OK,
pkbuf_free(nasbuf);return CORE_ERROR, "nas_security_decode failed");
}
h = nasbuf->payload;
d_assert(h, pkbuf_free(nasbuf); return CORE_ERROR, "Null param");
if (h->protocol_discriminator == NAS_PROTOCOL_DISCRIMINATOR_EMM)
{
event_set(&e, MME_EVT_EMM_MESSAGE);
event_set_param1(&e, (c_uintptr_t)enb_ue->index);
event_set_param2(&e, (c_uintptr_t)security_header_type.type);
event_set_param3(&e, (c_uintptr_t)nasbuf);
mme_event_send(&e);
}
else if (h->protocol_discriminator == NAS_PROTOCOL_DISCRIMINATOR_ESM)
{
mme_ue_t *mme_ue = enb_ue->mme_ue;
d_assert(mme_ue, return CORE_ERROR, "Null param");
s1ap_send_to_esm(mme_ue, nasbuf);
}
else
d_assert(0, pkbuf_free(nasbuf); return CORE_ERROR,
"Unknown protocol:%d", h->protocol_discriminator);
return CORE_OK;
}
status_t s1ap_send_initial_context_setup_request(mme_ue_t *mme_ue)
{
status_t rv;
pkbuf_t *s1apbuf = NULL;
d_assert(mme_ue, return CORE_ERROR, "Null param");
rv = s1ap_build_initial_context_setup_request(&s1apbuf, mme_ue, NULL);
d_assert(rv == CORE_OK && s1apbuf, return CORE_ERROR, "s1ap build error");
rv = nas_send_to_enb(mme_ue, s1apbuf);
d_assert(rv == CORE_OK, return CORE_ERROR, "s1ap send error");
return CORE_OK;
}
2017-09-07 06:56:31 +00:00
2017-09-08 07:46:37 +00:00
status_t s1ap_send_ue_context_release_commmand(
enb_ue_t *enb_ue, S1ap_Cause_t *cause, c_uint32_t delay)
2017-09-08 07:46:37 +00:00
{
status_t rv;
mme_enb_t *enb = NULL;
pkbuf_t *s1apbuf = NULL;
d_assert(enb_ue, return CORE_ERROR, "Null param");
d_assert(cause, return CORE_ERROR, "Null param");
enb = enb_ue->enb;
d_assert(enb, return CORE_ERROR, "Null param");
rv = s1ap_build_ue_context_release_commmand(&s1apbuf, enb_ue, cause);
d_assert(rv == CORE_OK && s1apbuf, return CORE_ERROR, "s1ap build error");
rv = s1ap_delayed_send_to_enb(enb, s1apbuf, delay);
d_assert(rv == CORE_OK,, "s1ap send error");
2017-09-08 07:46:37 +00:00
return CORE_OK;
}
status_t s1ap_send_path_switch_ack(mme_ue_t *mme_ue)
{
status_t rv;
pkbuf_t *s1apbuf = NULL;
d_assert(mme_ue, return CORE_ERROR, "Null param");
rv = s1ap_build_path_switch_ack(&s1apbuf, mme_ue);
d_assert(rv == CORE_OK && s1apbuf, return CORE_ERROR, "s1ap build error");
rv = nas_send_to_enb(mme_ue, s1apbuf);
d_assert(rv == CORE_OK, return CORE_ERROR, "s1ap send error");
return CORE_OK;
}
status_t s1ap_send_path_switch_failure(mme_enb_t *enb,
c_uint32_t enb_ue_s1ap_id, c_uint32_t mme_ue_s1ap_id, S1ap_Cause_t *cause)
{
status_t rv;
pkbuf_t *s1apbuf = NULL;
d_assert(cause, return CORE_ERROR, "Null param");
d_assert(enb, return CORE_ERROR, "Null param");
rv = s1ap_build_path_switch_failure(&s1apbuf,
enb_ue_s1ap_id, mme_ue_s1ap_id, cause);
d_assert(rv == CORE_OK && s1apbuf, return CORE_ERROR, "s1ap build error");
rv = s1ap_send_to_enb(enb, s1apbuf);
d_assert(rv == CORE_OK,, "s1ap send error");
return rv;
}
status_t s1ap_send_handover_command(enb_ue_t *source_ue)
{
status_t rv;
pkbuf_t *s1apbuf = NULL;
mme_enb_t *enb = NULL;
d_assert(source_ue, return CORE_ERROR,);
enb = source_ue->enb;
d_assert(enb, return CORE_ERROR,);
rv = s1ap_build_handover_command(&s1apbuf, source_ue);
d_assert(rv == CORE_OK && s1apbuf, return CORE_ERROR, "s1ap build error");
rv = s1ap_send_to_enb(enb, s1apbuf);
d_assert(rv == CORE_OK,, "s1ap send error");
return rv;
}
status_t s1ap_send_handover_preparation_failure(
enb_ue_t *source_ue, S1ap_Cause_t *cause)
{
status_t rv;
pkbuf_t *s1apbuf = NULL;
mme_enb_t *enb = NULL;
d_assert(source_ue, return CORE_ERROR,);
enb = source_ue->enb;
d_assert(enb, return CORE_ERROR,);
rv = s1ap_build_handover_preparation_failure(&s1apbuf, source_ue, cause);
d_assert(rv == CORE_OK && s1apbuf, return CORE_ERROR, "s1ap build error");
rv = s1ap_send_to_enb(enb, s1apbuf);
d_assert(rv == CORE_OK,, "s1ap send error");
return rv;
}
status_t s1ap_send_handover_cancel_ack(enb_ue_t *source_ue)
{
status_t rv;
pkbuf_t *s1apbuf = NULL;
mme_enb_t *enb = NULL;
d_assert(source_ue, return CORE_ERROR,);
enb = source_ue->enb;
d_assert(enb, return CORE_ERROR,);
rv = s1ap_build_handover_cancel_ack(&s1apbuf, source_ue);
d_assert(rv == CORE_OK && s1apbuf, return CORE_ERROR, "s1ap build error");
rv = s1ap_send_to_enb(enb, s1apbuf);
d_assert(rv == CORE_OK,, "s1ap send error");
return rv;
}
2017-09-12 14:07:55 +00:00
status_t s1ap_send_handover_request(
mme_ue_t *mme_ue, S1ap_HandoverRequiredIEs_t *ies)
{
status_t rv;
pkbuf_t *s1apbuf = NULL;
S1ap_TargetID_t *targetID = NULL;
c_uint32_t enb_id;
mme_enb_t *target_enb = NULL;
enb_ue_t *source_ue = NULL, *target_ue = NULL;
2017-09-12 14:07:55 +00:00
d_assert(mme_ue, return CORE_ERROR,);
source_ue = mme_ue->enb_ue;
d_assert(source_ue, return CORE_ERROR,);
2017-09-12 14:07:55 +00:00
d_assert(ies, return CORE_ERROR,);
targetID = &ies->targetID;
d_assert(targetID, return CORE_ERROR,);
2017-09-12 14:07:55 +00:00
switch(targetID->present)
{
case S1ap_TargetID_PR_targeteNB_ID:
{
s1ap_ENB_ID_to_uint32(
&targetID->choice.targeteNB_ID.global_S1ap_ENB_ID.eNB_ID,
&enb_id);
break;
}
default:
{
d_error("Not implemented(%d)", targetID->present);
return CORE_ERROR;
}
}
target_enb = mme_enb_find_by_enb_id(enb_id);
d_assert(target_enb, return CORE_ERROR,
2017-09-12 14:07:55 +00:00
"Cannot find target eNB = %d", enb_id);
d_assert(source_ue->target_ue == NULL, return CORE_ERROR,
"Handover Required Duplicated");
target_ue = enb_ue_add(target_enb);
d_assert(target_ue, return CORE_ERROR,);
2017-09-12 14:07:55 +00:00
rv = source_ue_associate_target_ue(source_ue, target_ue);
d_assert(rv == CORE_OK, return CORE_ERROR,);
2017-09-12 14:07:55 +00:00
rv = s1ap_build_handover_request(&s1apbuf, mme_ue, target_ue, ies);
2017-09-12 14:07:55 +00:00
d_assert(rv == CORE_OK && s1apbuf,
enb_ue_remove(target_ue); return CORE_ERROR, "s1ap build error");
2017-09-12 14:07:55 +00:00
rv = s1ap_send_to_enb(target_enb, s1apbuf);
d_assert(rv == CORE_OK, enb_ue_remove(target_ue), "s1ap send error");
2017-09-12 14:07:55 +00:00
return rv;
}
2017-09-13 12:51:02 +00:00
status_t s1ap_send_mme_status_transfer(
2017-09-15 03:06:26 +00:00
enb_ue_t *target_ue, S1ap_ENBStatusTransferIEs_t *ies)
{
status_t rv;
pkbuf_t *s1apbuf = NULL;
mme_enb_t *enb = NULL;
2017-09-15 03:06:26 +00:00
d_assert(target_ue, return CORE_ERROR,);
enb = target_ue->enb;
d_assert(enb, return CORE_ERROR,);
2017-09-15 03:06:26 +00:00
rv = s1ap_build_mme_status_transfer(&s1apbuf, target_ue, ies);
d_assert(rv == CORE_OK && s1apbuf, return CORE_ERROR, "s1ap build error");
rv = s1ap_send_to_enb(enb, s1apbuf);
d_assert(rv == CORE_OK,, "s1ap send error");
return rv;
}