2020-05-25 16:15:22 +00:00
|
|
|
/*
|
|
|
|
* Copyright (C) 2019,2020 by Sukchan Lee <acetcom@gmail.com>
|
|
|
|
*
|
|
|
|
* This file is part of Open5GS.
|
|
|
|
*
|
|
|
|
* This program is free software: you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU Affero General Public License as published by
|
|
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
|
|
* (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This program 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 this program. If not, see <https://www.gnu.org/licenses/>.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "ogs-sctp.h"
|
|
|
|
|
|
|
|
#include "context.h"
|
|
|
|
|
|
|
|
#include "ngap-build.h"
|
|
|
|
#include "ngap-path.h"
|
2020-06-04 18:12:05 +00:00
|
|
|
#include "nas-security.h"
|
2020-06-17 05:22:28 +00:00
|
|
|
#include "nas-path.h"
|
2020-06-25 04:37:29 +00:00
|
|
|
#include "sbi-path.h"
|
2020-05-25 16:15:22 +00:00
|
|
|
|
|
|
|
int ngap_open(void)
|
|
|
|
{
|
|
|
|
ogs_socknode_t *node = NULL;
|
|
|
|
|
|
|
|
ogs_list_for_each(&amf_self()->ngap_list, node)
|
|
|
|
ngap_server(node);
|
|
|
|
|
|
|
|
ogs_list_for_each(&amf_self()->ngap_list6, node)
|
|
|
|
ngap_server(node);
|
|
|
|
|
|
|
|
return OGS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
void ngap_close()
|
|
|
|
{
|
|
|
|
ogs_socknode_remove_all(&amf_self()->ngap_list);
|
|
|
|
ogs_socknode_remove_all(&amf_self()->ngap_list6);
|
|
|
|
}
|
|
|
|
|
|
|
|
int ngap_send_to_gnb(amf_gnb_t *gnb, ogs_pkbuf_t *pkbuf, uint16_t stream_no)
|
|
|
|
{
|
|
|
|
char buf[OGS_ADDRSTRLEN];
|
|
|
|
|
|
|
|
ogs_assert(gnb);
|
|
|
|
ogs_assert(pkbuf);
|
2020-11-11 18:21:32 +00:00
|
|
|
ogs_assert(gnb->sctp.sock);
|
2021-02-04 04:49:16 +00:00
|
|
|
if (gnb->sctp.sock->fd == INVALID_SOCKET) {
|
|
|
|
ogs_fatal("gNB SCTP socket has already been destroyed");
|
|
|
|
ogs_log_hexdump(OGS_LOG_FATAL, pkbuf->data, pkbuf->len);
|
|
|
|
ogs_assert_if_reached();
|
|
|
|
return OGS_ERROR;
|
|
|
|
}
|
2020-05-25 16:15:22 +00:00
|
|
|
|
2020-11-11 18:21:32 +00:00
|
|
|
ogs_debug(" IP[%s] RAN_ID[%d]",
|
|
|
|
OGS_ADDR(gnb->sctp.addr, buf), gnb->gnb_id);
|
2020-05-25 16:15:22 +00:00
|
|
|
|
2021-01-02 15:03:35 +00:00
|
|
|
ogs_sctp_ppid_in_pkbuf(pkbuf) = OGS_SCTP_NGAP_PPID;
|
|
|
|
ogs_sctp_stream_no_in_pkbuf(pkbuf) = stream_no;
|
|
|
|
|
2020-11-11 18:21:32 +00:00
|
|
|
if (gnb->sctp.type == SOCK_STREAM) {
|
|
|
|
ogs_sctp_write_to_buffer(&gnb->sctp, pkbuf);
|
|
|
|
return OGS_OK;
|
|
|
|
} else {
|
|
|
|
return ogs_sctp_senddata(gnb->sctp.sock, pkbuf, gnb->sctp.addr);
|
|
|
|
}
|
2020-05-25 16:15:22 +00:00
|
|
|
}
|
|
|
|
|
2020-06-04 18:12:05 +00:00
|
|
|
int ngap_send_to_ran_ue(ran_ue_t *ran_ue, ogs_pkbuf_t *pkbuf)
|
2020-05-25 16:15:22 +00:00
|
|
|
{
|
|
|
|
amf_gnb_t *gnb = NULL;
|
|
|
|
|
2020-06-04 18:12:05 +00:00
|
|
|
ogs_assert(ran_ue);
|
|
|
|
gnb = ran_ue->gnb;
|
2020-05-25 16:15:22 +00:00
|
|
|
ogs_assert(gnb);
|
|
|
|
|
2020-06-04 18:12:05 +00:00
|
|
|
return ngap_send_to_gnb(gnb, pkbuf, ran_ue->gnb_ostream_id);
|
2020-05-25 16:15:22 +00:00
|
|
|
}
|
|
|
|
|
2020-06-04 18:12:05 +00:00
|
|
|
int ngap_delayed_send_to_ran_ue(
|
|
|
|
ran_ue_t *ran_ue, ogs_pkbuf_t *pkbuf, ogs_time_t duration)
|
2020-05-25 16:15:22 +00:00
|
|
|
{
|
2020-06-04 18:12:05 +00:00
|
|
|
ogs_assert(ran_ue);
|
2020-05-25 16:15:22 +00:00
|
|
|
ogs_assert(pkbuf);
|
|
|
|
|
|
|
|
if (duration) {
|
|
|
|
amf_event_t *e = NULL;
|
|
|
|
|
|
|
|
e = amf_event_new(AMF_EVT_NGAP_TIMER);
|
|
|
|
ogs_assert(e);
|
|
|
|
e->timer = ogs_timer_add(
|
2020-08-26 03:05:01 +00:00
|
|
|
ogs_app()->timer_mgr, amf_timer_ng_delayed_send, e);
|
2020-05-25 16:15:22 +00:00
|
|
|
ogs_assert(e->timer);
|
|
|
|
e->pkbuf = pkbuf;
|
2020-06-04 18:12:05 +00:00
|
|
|
e->ran_ue = ran_ue;
|
|
|
|
e->gnb = ran_ue->gnb;
|
2020-05-25 16:15:22 +00:00
|
|
|
|
|
|
|
ogs_timer_start(e->timer, duration);
|
|
|
|
|
|
|
|
return OGS_OK;
|
|
|
|
} else {
|
|
|
|
amf_gnb_t *gnb = NULL;
|
2020-06-04 18:12:05 +00:00
|
|
|
gnb = ran_ue->gnb;
|
2020-05-25 16:15:22 +00:00
|
|
|
ogs_assert(gnb);
|
2020-06-04 18:12:05 +00:00
|
|
|
return ngap_send_to_ran_ue(ran_ue, pkbuf);
|
2020-05-25 16:15:22 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-06-04 18:12:05 +00:00
|
|
|
int ngap_send_to_5gsm(amf_ue_t *amf_ue, ogs_pkbuf_t *esmbuf)
|
2020-05-25 16:15:22 +00:00
|
|
|
{
|
|
|
|
int rv;
|
|
|
|
amf_event_t *e = NULL;
|
|
|
|
|
|
|
|
ogs_assert(amf_ue);
|
|
|
|
ogs_assert(esmbuf);
|
|
|
|
|
2020-06-04 18:12:05 +00:00
|
|
|
e = amf_event_new(AMF_EVT_5GSM_MESSAGE);
|
2020-05-25 16:15:22 +00:00
|
|
|
ogs_assert(e);
|
|
|
|
e->amf_ue = amf_ue;
|
|
|
|
e->pkbuf = esmbuf;
|
2020-08-26 03:05:01 +00:00
|
|
|
rv = ogs_queue_push(ogs_app()->queue, e);
|
2020-05-25 16:15:22 +00:00
|
|
|
if (rv != OGS_OK) {
|
|
|
|
ogs_warn("ogs_queue_push() failed:%d", (int)rv);
|
|
|
|
ogs_pkbuf_free(e->pkbuf);
|
|
|
|
amf_event_free(e);
|
|
|
|
}
|
|
|
|
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
2020-06-04 18:12:05 +00:00
|
|
|
int ngap_send_to_nas(ran_ue_t *ran_ue,
|
2020-05-25 16:15:22 +00:00
|
|
|
NGAP_ProcedureCode_t procedureCode, NGAP_NAS_PDU_t *nasPdu)
|
|
|
|
{
|
2020-06-04 18:12:05 +00:00
|
|
|
ogs_nas_5gs_security_header_t *sh = NULL;
|
2020-05-25 16:15:22 +00:00
|
|
|
ogs_nas_security_header_type_t security_header_type;
|
|
|
|
|
2020-06-04 18:12:05 +00:00
|
|
|
ogs_nas_5gmm_header_t *h = NULL;
|
2020-05-25 16:15:22 +00:00
|
|
|
ogs_pkbuf_t *nasbuf = NULL;
|
|
|
|
amf_event_t *e = NULL;
|
|
|
|
|
2020-06-04 18:12:05 +00:00
|
|
|
ogs_assert(ran_ue);
|
2020-05-25 16:15:22 +00:00
|
|
|
ogs_assert(nasPdu);
|
|
|
|
|
|
|
|
/* 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 = ogs_pkbuf_alloc(NULL, OGS_NAS_HEADROOM+nasPdu->size);
|
2020-09-07 03:53:38 +00:00
|
|
|
ogs_assert(nasbuf);
|
2020-05-25 16:15:22 +00:00
|
|
|
ogs_pkbuf_reserve(nasbuf, OGS_NAS_HEADROOM);
|
|
|
|
ogs_pkbuf_put_data(nasbuf, nasPdu->buf, nasPdu->size);
|
|
|
|
|
2020-06-04 18:12:05 +00:00
|
|
|
sh = (ogs_nas_5gs_security_header_t *)nasbuf->data;
|
2020-05-25 16:15:22 +00:00
|
|
|
ogs_assert(sh);
|
|
|
|
|
|
|
|
memset(&security_header_type, 0, sizeof(ogs_nas_security_header_type_t));
|
|
|
|
switch(sh->security_header_type) {
|
|
|
|
case OGS_NAS_SECURITY_HEADER_PLAIN_NAS_MESSAGE:
|
|
|
|
break;
|
|
|
|
case OGS_NAS_SECURITY_HEADER_INTEGRITY_PROTECTED:
|
|
|
|
security_header_type.integrity_protected = 1;
|
2020-06-04 18:12:05 +00:00
|
|
|
ogs_pkbuf_pull(nasbuf, 7);
|
2020-05-25 16:15:22 +00:00
|
|
|
break;
|
|
|
|
case OGS_NAS_SECURITY_HEADER_INTEGRITY_PROTECTED_AND_CIPHERED:
|
|
|
|
security_header_type.integrity_protected = 1;
|
|
|
|
security_header_type.ciphered = 1;
|
2020-06-04 18:12:05 +00:00
|
|
|
ogs_pkbuf_pull(nasbuf, 7);
|
2020-05-25 16:15:22 +00:00
|
|
|
break;
|
|
|
|
case OGS_NAS_SECURITY_HEADER_INTEGRITY_PROTECTED_AND_NEW_SECURITY_CONTEXT:
|
|
|
|
security_header_type.integrity_protected = 1;
|
|
|
|
security_header_type.new_security_context = 1;
|
2020-06-04 18:12:05 +00:00
|
|
|
ogs_pkbuf_pull(nasbuf, 7);
|
2020-05-25 16:15:22 +00:00
|
|
|
break;
|
|
|
|
case OGS_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;
|
2020-06-04 18:12:05 +00:00
|
|
|
ogs_pkbuf_pull(nasbuf, 7);
|
2020-05-25 16:15:22 +00:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
ogs_error("Not implemented(security header type:0x%x)",
|
|
|
|
sh->security_header_type);
|
|
|
|
return OGS_ERROR;
|
|
|
|
}
|
|
|
|
|
2020-06-04 18:12:05 +00:00
|
|
|
if (ran_ue->amf_ue) {
|
|
|
|
if (nas_5gs_security_decode(ran_ue->amf_ue,
|
2020-05-25 16:15:22 +00:00
|
|
|
security_header_type, nasbuf) != OGS_OK) {
|
|
|
|
ogs_error("nas_eps_security_decode failed()");
|
|
|
|
return OGS_ERROR;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-06-04 18:12:05 +00:00
|
|
|
h = (ogs_nas_5gmm_header_t *)nasbuf->data;
|
2020-05-25 16:15:22 +00:00
|
|
|
ogs_assert(h);
|
2020-06-04 18:12:05 +00:00
|
|
|
if (h->extended_protocol_discriminator ==
|
|
|
|
OGS_NAS_EXTENDED_PROTOCOL_DISCRIMINATOR_5GMM) {
|
2020-05-25 16:15:22 +00:00
|
|
|
int rv;
|
2020-06-04 18:12:05 +00:00
|
|
|
e = amf_event_new(AMF_EVT_5GMM_MESSAGE);
|
2021-02-15 17:17:33 +00:00
|
|
|
if (!e) {
|
|
|
|
ogs_error("ngap_send_to_nas() failed");
|
|
|
|
ogs_pkbuf_free(nasbuf);
|
|
|
|
return OGS_ERROR;
|
|
|
|
}
|
2020-06-04 18:12:05 +00:00
|
|
|
e->ran_ue = ran_ue;
|
|
|
|
e->ngap.code = procedureCode;
|
|
|
|
e->nas.type = security_header_type.type;
|
2020-05-25 16:15:22 +00:00
|
|
|
e->pkbuf = nasbuf;
|
2020-08-26 03:05:01 +00:00
|
|
|
rv = ogs_queue_push(ogs_app()->queue, e);
|
2020-05-25 16:15:22 +00:00
|
|
|
if (rv != OGS_OK) {
|
2021-02-15 17:17:33 +00:00
|
|
|
ogs_warn("ngap_send_to_nas() failed:%d", (int)rv);
|
2020-05-25 16:15:22 +00:00
|
|
|
ogs_pkbuf_free(e->pkbuf);
|
|
|
|
amf_event_free(e);
|
|
|
|
}
|
|
|
|
return rv;
|
2020-06-04 18:12:05 +00:00
|
|
|
} else if (h->extended_protocol_discriminator ==
|
|
|
|
OGS_NAS_EXTENDED_PROTOCOL_DISCRIMINATOR_5GSM) {
|
|
|
|
amf_ue_t *amf_ue = ran_ue->amf_ue;
|
2020-09-22 00:06:41 +00:00
|
|
|
if (!amf_ue) {
|
|
|
|
ogs_error("No UE Context");
|
2021-02-15 17:17:33 +00:00
|
|
|
ogs_pkbuf_free(nasbuf);
|
2020-09-22 00:06:41 +00:00
|
|
|
return OGS_ERROR;
|
|
|
|
}
|
2020-06-04 18:12:05 +00:00
|
|
|
return ngap_send_to_5gsm(amf_ue, nasbuf);
|
2020-05-25 16:15:22 +00:00
|
|
|
} else {
|
2020-06-04 18:12:05 +00:00
|
|
|
ogs_error("Unknown NAS Protocol discriminator 0x%02x",
|
|
|
|
h->extended_protocol_discriminator);
|
2021-02-15 17:17:33 +00:00
|
|
|
ogs_pkbuf_free(nasbuf);
|
2020-05-25 16:15:22 +00:00
|
|
|
return OGS_ERROR;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void ngap_send_ng_setup_response(amf_gnb_t *gnb)
|
|
|
|
{
|
|
|
|
ogs_pkbuf_t *ngap_buffer;
|
|
|
|
|
2020-06-04 18:12:05 +00:00
|
|
|
ogs_debug("NG-Setup response");
|
|
|
|
ngap_buffer = ngap_build_ng_setup_response();
|
2020-05-25 16:15:22 +00:00
|
|
|
ogs_expect_or_return(ngap_buffer);
|
|
|
|
|
|
|
|
ogs_expect(OGS_OK ==
|
|
|
|
ngap_send_to_gnb(gnb, ngap_buffer, NGAP_NON_UE_SIGNALLING));
|
|
|
|
}
|
|
|
|
|
|
|
|
void ngap_send_ng_setup_failure(
|
|
|
|
amf_gnb_t *gnb, NGAP_Cause_PR group, long cause)
|
|
|
|
{
|
|
|
|
ogs_pkbuf_t *ngap_buffer;
|
|
|
|
|
2020-06-04 18:12:05 +00:00
|
|
|
ogs_debug("NG-Setup failure");
|
|
|
|
ngap_buffer = ngap_build_ng_setup_failure(
|
|
|
|
group, cause, NGAP_TimeToWait_v10s);
|
2020-05-25 16:15:22 +00:00
|
|
|
ogs_expect_or_return(ngap_buffer);
|
|
|
|
|
|
|
|
ogs_expect(OGS_OK ==
|
|
|
|
ngap_send_to_gnb(gnb, ngap_buffer, NGAP_NON_UE_SIGNALLING));
|
|
|
|
}
|
|
|
|
|
2020-06-17 05:22:28 +00:00
|
|
|
#if 0
|
2020-05-25 16:15:22 +00:00
|
|
|
void ngap_send_ue_context_modification_request(amf_ue_t *amf_ue)
|
|
|
|
{
|
|
|
|
int rv;
|
|
|
|
ogs_pkbuf_t *ngapbuf = NULL;
|
|
|
|
|
|
|
|
ogs_assert(amf_ue);
|
|
|
|
|
|
|
|
ngapbuf = ngap_build_ue_context_modification_request(amf_ue);
|
|
|
|
ogs_expect_or_return(ngapbuf);
|
|
|
|
|
2020-06-17 05:22:28 +00:00
|
|
|
rv = nas_5gs_send_to_gnb(amf_ue, ngapbuf);
|
2020-05-25 16:15:22 +00:00
|
|
|
ogs_expect(rv == OGS_OK);
|
|
|
|
}
|
2020-06-22 03:07:14 +00:00
|
|
|
#endif
|
2020-05-25 16:15:22 +00:00
|
|
|
|
2020-06-25 04:37:29 +00:00
|
|
|
void ngap_send_ran_ue_context_release_command(
|
2020-06-04 18:12:05 +00:00
|
|
|
ran_ue_t *ran_ue, NGAP_Cause_PR group, long cause,
|
2021-01-28 19:23:54 +00:00
|
|
|
uint8_t action, ogs_time_t duration)
|
2020-05-25 16:15:22 +00:00
|
|
|
{
|
|
|
|
int rv;
|
|
|
|
ogs_pkbuf_t *ngapbuf = NULL;
|
|
|
|
|
2020-06-04 18:12:05 +00:00
|
|
|
ogs_assert(ran_ue);
|
2020-05-25 16:15:22 +00:00
|
|
|
|
2020-06-22 03:07:14 +00:00
|
|
|
ogs_debug("UE Context release command");
|
|
|
|
ogs_debug(" RAN_UE_NGAP_ID[%d] AMF_UE_NGAP_ID[%lld]",
|
|
|
|
ran_ue->ran_ue_ngap_id, (long long)ran_ue->amf_ue_ngap_id);
|
2020-05-25 16:15:22 +00:00
|
|
|
|
2020-09-03 23:59:00 +00:00
|
|
|
ogs_assert(action != NGAP_UE_CTX_REL_INVALID_ACTION);
|
|
|
|
ran_ue->ue_ctx_rel_action = action;
|
2020-05-25 16:15:22 +00:00
|
|
|
|
2021-01-28 19:23:54 +00:00
|
|
|
ogs_debug(" Group[%d] Cause[%d] Action[%d] Duration[%d]",
|
|
|
|
group, (int)cause, action, (int)duration);
|
2020-05-25 16:15:22 +00:00
|
|
|
|
2020-09-03 23:59:00 +00:00
|
|
|
ngapbuf = ngap_build_ue_context_release_command(ran_ue, group, cause);
|
|
|
|
ogs_expect_or_return(ngapbuf);
|
2020-05-25 16:15:22 +00:00
|
|
|
|
2021-01-28 19:23:54 +00:00
|
|
|
rv = ngap_delayed_send_to_ran_ue(ran_ue, ngapbuf, duration);
|
2020-09-03 23:59:00 +00:00
|
|
|
ogs_expect(rv == OGS_OK);
|
2020-09-21 15:08:41 +00:00
|
|
|
|
|
|
|
ogs_timer_start(ran_ue->t_ng_holding,
|
|
|
|
amf_timer_cfg(AMF_TIMER_NG_HOLDING)->duration);
|
2020-05-25 16:15:22 +00:00
|
|
|
}
|
|
|
|
|
2020-06-25 04:37:29 +00:00
|
|
|
void ngap_send_amf_ue_context_release_command(
|
|
|
|
amf_ue_t *amf_ue, NGAP_Cause_PR group, long cause,
|
2021-01-28 19:23:54 +00:00
|
|
|
uint8_t action, ogs_time_t duration)
|
2020-06-25 04:37:29 +00:00
|
|
|
{
|
|
|
|
ogs_assert(amf_ue);
|
|
|
|
|
2020-10-29 02:59:27 +00:00
|
|
|
ran_ue_t *ran_ue = ran_ue_cycle(amf_ue->ran_ue);
|
2020-06-25 04:37:29 +00:00
|
|
|
if (ran_ue) {
|
|
|
|
ngap_send_ran_ue_context_release_command(ran_ue,
|
2021-01-28 19:23:54 +00:00
|
|
|
group, cause, action, duration);
|
2020-06-25 04:37:29 +00:00
|
|
|
ogs_debug(" SUPI[%s]", amf_ue->supi);
|
|
|
|
} else {
|
|
|
|
ogs_error("[%s] No NG Context - "
|
2021-01-28 19:23:54 +00:00
|
|
|
"Group[%d] Cause[%d] Action[%d] Duration[%d]",
|
|
|
|
amf_ue->supi, group, (int)cause, action, (int)duration);
|
2020-06-25 04:37:29 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-01-18 16:48:35 +00:00
|
|
|
void ngap_send_paging(amf_ue_t *amf_ue)
|
2020-05-25 16:15:22 +00:00
|
|
|
{
|
|
|
|
ogs_pkbuf_t *ngapbuf = NULL;
|
|
|
|
amf_gnb_t *gnb = NULL;
|
2021-01-18 16:48:35 +00:00
|
|
|
int i, j;
|
2020-05-25 16:15:22 +00:00
|
|
|
int rv;
|
|
|
|
|
|
|
|
ogs_list_for_each(&amf_self()->gnb_list, gnb) {
|
|
|
|
for (i = 0; i < gnb->num_of_supported_ta_list; i++) {
|
2021-01-18 16:48:35 +00:00
|
|
|
for (j = 0; j < gnb->supported_ta_list[i].num_of_bplmn_list; j++) {
|
|
|
|
if (memcmp(&gnb->supported_ta_list[i].bplmn_list[j].plmn_id,
|
2021-03-08 12:25:09 +00:00
|
|
|
&amf_ue->nr_tai.plmn_id, OGS_PLMN_ID_LEN) == 0 &&
|
|
|
|
gnb->supported_ta_list[i].tac.v == amf_ue->nr_tai.tac.v) {
|
2021-01-18 16:48:35 +00:00
|
|
|
|
|
|
|
if (amf_ue->t3513.pkbuf) {
|
|
|
|
ngapbuf = amf_ue->t3513.pkbuf;
|
|
|
|
} else {
|
|
|
|
ngapbuf = ngap_build_paging(amf_ue);
|
|
|
|
ogs_expect_or_return(ngapbuf);
|
|
|
|
}
|
|
|
|
|
|
|
|
amf_ue->t3513.pkbuf = ogs_pkbuf_copy(ngapbuf);
|
|
|
|
ogs_assert(amf_ue->t3513.pkbuf);
|
|
|
|
|
|
|
|
rv = ngap_send_to_gnb(gnb, ngapbuf, amf_ue->gnb_ostream_id);
|
|
|
|
ogs_expect(rv == OGS_OK);
|
2020-05-25 16:15:22 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-01-18 16:48:35 +00:00
|
|
|
/* Start T3513 */
|
|
|
|
ogs_timer_start(amf_ue->t3513.timer,
|
|
|
|
amf_timer_cfg(AMF_TIMER_T3513)->duration);
|
|
|
|
}
|
|
|
|
|
|
|
|
void ngap_send_pdu_resource_setup_request(
|
|
|
|
amf_sess_t *sess, ogs_pkbuf_t *n2smbuf)
|
|
|
|
{
|
|
|
|
int rv;
|
|
|
|
ran_ue_t *ran_ue = NULL;
|
|
|
|
amf_ue_t *amf_ue = NULL;
|
|
|
|
|
|
|
|
ogs_pkbuf_t *ngapbuf = NULL;
|
|
|
|
|
|
|
|
ogs_assert(sess);
|
|
|
|
amf_ue = sess->amf_ue;
|
|
|
|
ogs_assert(amf_ue);
|
|
|
|
ran_ue = ran_ue_cycle(amf_ue->ran_ue);
|
|
|
|
ogs_assert(ran_ue);
|
|
|
|
|
|
|
|
if (ran_ue->ue_context_requested == true &&
|
|
|
|
ran_ue->initial_context_setup_request_sent == false) {
|
|
|
|
ngapbuf = ngap_sess_build_initial_context_setup_request(
|
|
|
|
sess, NULL, n2smbuf);
|
|
|
|
ogs_expect_or_return(ngapbuf);
|
|
|
|
|
|
|
|
rv = nas_5gs_send_to_gnb(amf_ue, ngapbuf);
|
|
|
|
ogs_expect_or_return(rv == OGS_OK);
|
|
|
|
|
|
|
|
ran_ue->initial_context_setup_request_sent = true;
|
|
|
|
} else {
|
|
|
|
ngapbuf = ngap_sess_build_pdu_session_resource_setup_request(
|
|
|
|
sess, NULL, n2smbuf);
|
|
|
|
ogs_expect_or_return(ngapbuf);
|
|
|
|
|
|
|
|
rv = nas_5gs_send_to_gnb(amf_ue, ngapbuf);
|
|
|
|
ogs_expect_or_return(rv == OGS_OK);
|
|
|
|
}
|
2020-05-25 16:15:22 +00:00
|
|
|
}
|
|
|
|
|
2021-01-28 19:23:54 +00:00
|
|
|
void ngap_send_downlink_ran_configuration_transfer(
|
|
|
|
amf_gnb_t *target_gnb, NGAP_SONConfigurationTransfer_t *transfer)
|
2020-05-25 16:15:22 +00:00
|
|
|
{
|
|
|
|
int rv;
|
|
|
|
ogs_pkbuf_t *ngapbuf = NULL;
|
|
|
|
|
|
|
|
ogs_assert(target_gnb);
|
2021-01-28 19:23:54 +00:00
|
|
|
ogs_assert(transfer);
|
2020-05-25 16:15:22 +00:00
|
|
|
|
2021-01-28 19:23:54 +00:00
|
|
|
ngapbuf = ngap_build_downlink_ran_configuration_transfer(transfer);
|
2020-05-25 16:15:22 +00:00
|
|
|
ogs_expect_or_return(ngapbuf);
|
|
|
|
|
|
|
|
rv = ngap_send_to_gnb(target_gnb, ngapbuf, NGAP_NON_UE_SIGNALLING);
|
|
|
|
ogs_expect(rv == OGS_OK);
|
|
|
|
}
|
|
|
|
|
2021-01-04 04:29:01 +00:00
|
|
|
void ngap_send_path_switch_ack(amf_sess_t *sess)
|
2020-05-25 16:15:22 +00:00
|
|
|
{
|
|
|
|
int rv;
|
2021-01-03 05:50:59 +00:00
|
|
|
|
|
|
|
amf_ue_t *amf_ue = NULL;
|
2020-05-25 16:15:22 +00:00
|
|
|
ogs_pkbuf_t *ngapbuf = NULL;
|
|
|
|
|
2021-01-03 05:50:59 +00:00
|
|
|
ogs_assert(sess);
|
|
|
|
amf_ue = sess->amf_ue;
|
2020-05-25 16:15:22 +00:00
|
|
|
ogs_assert(amf_ue);
|
|
|
|
|
2021-01-04 04:29:01 +00:00
|
|
|
ngapbuf = ngap_build_path_switch_ack(amf_ue);
|
2020-05-25 16:15:22 +00:00
|
|
|
ogs_expect_or_return(ngapbuf);
|
|
|
|
|
2020-06-17 05:22:28 +00:00
|
|
|
rv = nas_5gs_send_to_gnb(amf_ue, ngapbuf);
|
2020-05-25 16:15:22 +00:00
|
|
|
ogs_expect(rv == OGS_OK);
|
|
|
|
}
|
|
|
|
|
2021-01-28 19:23:54 +00:00
|
|
|
void ngap_send_handover_request(amf_ue_t *amf_ue)
|
2020-05-25 16:15:22 +00:00
|
|
|
{
|
|
|
|
int rv;
|
2021-01-28 19:23:54 +00:00
|
|
|
|
|
|
|
ran_ue_t *source_ue = NULL, *target_ue = NULL;
|
2020-05-25 16:15:22 +00:00
|
|
|
ogs_pkbuf_t *ngapbuf = NULL;
|
|
|
|
|
2021-01-28 19:23:54 +00:00
|
|
|
ogs_assert(amf_ue);
|
|
|
|
source_ue = amf_ue->ran_ue;
|
2020-05-25 16:15:22 +00:00
|
|
|
ogs_assert(source_ue);
|
2021-01-28 19:23:54 +00:00
|
|
|
target_ue = source_ue->target_ue;
|
|
|
|
ogs_assert(target_ue);
|
2020-05-25 16:15:22 +00:00
|
|
|
|
2021-01-28 19:23:54 +00:00
|
|
|
ngapbuf = ngap_build_handover_request(target_ue);
|
2020-05-25 16:15:22 +00:00
|
|
|
ogs_expect_or_return(ngapbuf);
|
|
|
|
|
2021-01-28 19:23:54 +00:00
|
|
|
rv = ngap_send_to_ran_ue(target_ue, ngapbuf);
|
2020-05-25 16:15:22 +00:00
|
|
|
ogs_expect(rv == OGS_OK);
|
|
|
|
}
|
|
|
|
|
|
|
|
void ngap_send_handover_preparation_failure(
|
2020-06-04 18:12:05 +00:00
|
|
|
ran_ue_t *source_ue, NGAP_Cause_t *cause)
|
2020-05-25 16:15:22 +00:00
|
|
|
{
|
|
|
|
int rv;
|
|
|
|
ogs_pkbuf_t *ngapbuf = NULL;
|
|
|
|
|
|
|
|
ogs_assert(source_ue);
|
|
|
|
ogs_assert(cause);
|
|
|
|
|
|
|
|
ngapbuf = ngap_build_handover_preparation_failure(source_ue, cause);
|
|
|
|
ogs_expect_or_return(ngapbuf);
|
|
|
|
|
2020-06-04 18:12:05 +00:00
|
|
|
rv = ngap_send_to_ran_ue(source_ue, ngapbuf);
|
2020-05-25 16:15:22 +00:00
|
|
|
ogs_expect(rv == OGS_OK);
|
|
|
|
}
|
|
|
|
|
2021-01-28 19:23:54 +00:00
|
|
|
void ngap_send_handover_command(amf_ue_t *amf_ue)
|
2020-05-25 16:15:22 +00:00
|
|
|
{
|
|
|
|
int rv;
|
2021-01-28 19:23:54 +00:00
|
|
|
|
|
|
|
ran_ue_t *source_ue = NULL;
|
2020-05-25 16:15:22 +00:00
|
|
|
ogs_pkbuf_t *ngapbuf = NULL;
|
|
|
|
|
2021-01-28 19:23:54 +00:00
|
|
|
ogs_assert(amf_ue);
|
|
|
|
source_ue = amf_ue->ran_ue;
|
2020-05-25 16:15:22 +00:00
|
|
|
ogs_assert(source_ue);
|
|
|
|
|
2021-01-28 19:23:54 +00:00
|
|
|
ngapbuf = ngap_build_handover_command(source_ue);
|
2020-05-25 16:15:22 +00:00
|
|
|
ogs_expect_or_return(ngapbuf);
|
|
|
|
|
2020-06-04 18:12:05 +00:00
|
|
|
rv = ngap_send_to_ran_ue(source_ue, ngapbuf);
|
2020-05-25 16:15:22 +00:00
|
|
|
ogs_expect(rv == OGS_OK);
|
|
|
|
}
|
|
|
|
|
2021-01-28 19:23:54 +00:00
|
|
|
void ngap_send_handover_cancel_ack(ran_ue_t *source_ue)
|
2020-05-25 16:15:22 +00:00
|
|
|
{
|
|
|
|
int rv;
|
|
|
|
ogs_pkbuf_t *ngapbuf = NULL;
|
|
|
|
|
|
|
|
ogs_assert(source_ue);
|
|
|
|
|
2021-01-28 19:23:54 +00:00
|
|
|
ngapbuf = ngap_build_handover_cancel_ack(source_ue);
|
2020-05-25 16:15:22 +00:00
|
|
|
ogs_expect_or_return(ngapbuf);
|
|
|
|
|
2021-01-28 19:23:54 +00:00
|
|
|
rv = ngap_send_to_ran_ue(source_ue, ngapbuf);
|
2020-05-25 16:15:22 +00:00
|
|
|
ogs_expect(rv == OGS_OK);
|
|
|
|
}
|
|
|
|
|
2021-01-28 19:23:54 +00:00
|
|
|
void ngap_send_downlink_ran_status_transfer(
|
2020-06-04 18:12:05 +00:00
|
|
|
ran_ue_t *target_ue,
|
2021-01-28 19:23:54 +00:00
|
|
|
NGAP_RANStatusTransfer_TransparentContainer_t *transfer)
|
2020-05-25 16:15:22 +00:00
|
|
|
{
|
|
|
|
int rv;
|
|
|
|
ogs_pkbuf_t *ngapbuf = NULL;
|
|
|
|
|
|
|
|
ogs_assert(target_ue);
|
2021-01-28 19:23:54 +00:00
|
|
|
ogs_assert(transfer);
|
2020-05-25 16:15:22 +00:00
|
|
|
|
2021-01-28 19:23:54 +00:00
|
|
|
ngapbuf = ngap_build_uplink_ran_status_transfer(target_ue, transfer);
|
2020-05-25 16:15:22 +00:00
|
|
|
ogs_expect_or_return(ngapbuf);
|
|
|
|
|
2020-06-04 18:12:05 +00:00
|
|
|
rv = ngap_send_to_ran_ue(target_ue, ngapbuf);
|
2020-05-25 16:15:22 +00:00
|
|
|
ogs_expect(rv == OGS_OK);
|
|
|
|
}
|
|
|
|
|
|
|
|
void ngap_send_error_indication(
|
|
|
|
amf_gnb_t *gnb,
|
2020-06-22 03:07:14 +00:00
|
|
|
uint32_t *ran_ue_ngap_id,
|
2020-06-04 18:12:05 +00:00
|
|
|
uint64_t *amf_ue_ngap_id,
|
2020-05-25 16:15:22 +00:00
|
|
|
NGAP_Cause_PR group, long cause)
|
|
|
|
{
|
|
|
|
int rv;
|
|
|
|
ogs_pkbuf_t *ngapbuf = NULL;
|
|
|
|
|
|
|
|
ogs_assert(gnb);
|
|
|
|
|
2021-01-25 04:43:42 +00:00
|
|
|
ngapbuf = ogs_ngap_build_error_indication(
|
2020-06-22 03:07:14 +00:00
|
|
|
ran_ue_ngap_id, amf_ue_ngap_id, group, cause);
|
2020-05-25 16:15:22 +00:00
|
|
|
ogs_expect_or_return(ngapbuf);
|
|
|
|
|
|
|
|
rv = ngap_send_to_gnb(gnb, ngapbuf, NGAP_NON_UE_SIGNALLING);
|
|
|
|
ogs_expect(rv == OGS_OK);
|
|
|
|
}
|
|
|
|
|
2020-06-17 05:22:28 +00:00
|
|
|
void ngap_send_error_indication2(
|
|
|
|
amf_ue_t *amf_ue, NGAP_Cause_PR group, long cause)
|
|
|
|
{
|
|
|
|
amf_gnb_t *gnb;
|
|
|
|
ran_ue_t *ran_ue;
|
|
|
|
|
|
|
|
ogs_assert(amf_ue);
|
2020-10-29 02:59:27 +00:00
|
|
|
ran_ue = ran_ue_cycle(amf_ue->ran_ue);
|
2020-06-17 05:22:28 +00:00
|
|
|
ogs_expect_or_return(ran_ue);
|
|
|
|
gnb = ran_ue->gnb;
|
|
|
|
ogs_expect_or_return(gnb);
|
|
|
|
|
2020-06-22 03:07:14 +00:00
|
|
|
ngap_send_error_indication(
|
|
|
|
gnb, &ran_ue->ran_ue_ngap_id, &ran_ue->amf_ue_ngap_id, group, cause);
|
2020-06-17 05:22:28 +00:00
|
|
|
}
|
|
|
|
|
2020-05-25 16:15:22 +00:00
|
|
|
void ngap_send_ng_reset_ack(
|
|
|
|
amf_gnb_t *gnb,
|
2021-01-25 04:43:42 +00:00
|
|
|
NGAP_UE_associatedLogicalNG_connectionList_t *partOfNG_Interface)
|
2020-05-25 16:15:22 +00:00
|
|
|
{
|
|
|
|
int rv;
|
|
|
|
ogs_pkbuf_t *ngapbuf = NULL;
|
|
|
|
|
|
|
|
ogs_assert(gnb);
|
|
|
|
|
2021-01-25 04:43:42 +00:00
|
|
|
ngapbuf = ogs_ngap_build_ng_reset_ack(partOfNG_Interface);
|
2020-05-25 16:15:22 +00:00
|
|
|
ogs_expect_or_return(ngapbuf);
|
|
|
|
|
|
|
|
rv = ngap_send_to_gnb(gnb, ngapbuf, NGAP_NON_UE_SIGNALLING);
|
|
|
|
ogs_expect(rv == OGS_OK);
|
|
|
|
}
|