2019-06-01 09:52:38 +00:00
|
|
|
/*
|
|
|
|
* Copyright (C) 2019 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/>.
|
|
|
|
*/
|
|
|
|
|
2019-06-01 09:19:00 +00:00
|
|
|
#include "ogs-sctp.h"
|
|
|
|
|
2019-06-11 13:10:47 +00:00
|
|
|
#include "mme-event.h"
|
2019-07-20 06:16:46 +00:00
|
|
|
#include "mme-timer.h"
|
2017-03-26 06:34:34 +00:00
|
|
|
|
2019-06-11 13:10:47 +00:00
|
|
|
#include "nas-security.h"
|
|
|
|
#include "nas-path.h"
|
2017-09-10 14:03:24 +00:00
|
|
|
|
2019-06-11 13:10:47 +00:00
|
|
|
#include "s1ap-build.h"
|
2019-06-01 09:52:38 +00:00
|
|
|
#include "s1ap-path.h"
|
2017-02-13 04:19:53 +00:00
|
|
|
|
2019-04-27 14:54:30 +00:00
|
|
|
int s1ap_open(void)
|
2017-11-24 16:08:26 +00:00
|
|
|
{
|
2019-06-01 09:43:33 +00:00
|
|
|
ogs_socknode_t *node = NULL;
|
|
|
|
|
2019-06-15 07:54:49 +00:00
|
|
|
ogs_list_for_each(&mme_self()->s1ap_list, node)
|
2019-06-01 09:43:33 +00:00
|
|
|
s1ap_server(node);
|
2017-12-08 05:29:35 +00:00
|
|
|
|
2019-06-15 07:54:49 +00:00
|
|
|
ogs_list_for_each(&mme_self()->s1ap_list6, node)
|
2019-06-01 09:43:33 +00:00
|
|
|
s1ap_server(node);
|
2017-12-08 05:29:35 +00:00
|
|
|
|
2019-04-27 14:54:30 +00:00
|
|
|
return OGS_OK;
|
2017-12-08 05:29:35 +00:00
|
|
|
}
|
|
|
|
|
2019-05-31 12:05:35 +00:00
|
|
|
void s1ap_close()
|
2017-12-08 05:29:35 +00:00
|
|
|
{
|
2019-05-31 12:05:35 +00:00
|
|
|
ogs_socknode_remove_all(&mme_self()->s1ap_list);
|
|
|
|
ogs_socknode_remove_all(&mme_self()->s1ap_list6);
|
2017-12-08 05:29:35 +00:00
|
|
|
}
|
|
|
|
|
2019-04-27 14:54:30 +00:00
|
|
|
int s1ap_send_to_enb(mme_enb_t *enb, ogs_pkbuf_t *pkbuf, uint16_t stream_no)
|
2017-02-13 04:19:53 +00:00
|
|
|
{
|
2019-04-27 14:54:30 +00:00
|
|
|
char buf[OGS_ADDRSTRLEN];
|
2018-01-22 14:14:20 +00:00
|
|
|
|
2019-04-27 14:54:30 +00:00
|
|
|
ogs_assert(enb);
|
|
|
|
ogs_assert(pkbuf);
|
2020-11-11 18:21:32 +00:00
|
|
|
ogs_assert(enb->sctp.sock);
|
2021-02-04 04:49:16 +00:00
|
|
|
if (enb->sctp.sock->fd == INVALID_SOCKET) {
|
|
|
|
ogs_fatal("eNB SCTP socket has already been destroyed");
|
|
|
|
ogs_log_hexdump(OGS_LOG_FATAL, pkbuf->data, pkbuf->len);
|
|
|
|
ogs_assert_if_reached();
|
|
|
|
return OGS_ERROR;
|
|
|
|
}
|
2018-01-22 14:14:20 +00:00
|
|
|
|
2020-11-11 18:21:32 +00:00
|
|
|
ogs_debug(" IP[%s] ENB_ID[%d]",
|
|
|
|
OGS_ADDR(enb->sctp.addr, buf), enb->enb_id);
|
2017-02-13 04:19:53 +00:00
|
|
|
|
2020-11-11 18:21:32 +00:00
|
|
|
ogs_sctp_ppid_in_pkbuf(pkbuf) = OGS_SCTP_S1AP_PPID;
|
|
|
|
ogs_sctp_stream_no_in_pkbuf(pkbuf) = stream_no;
|
|
|
|
|
|
|
|
if (enb->sctp.type == SOCK_STREAM) {
|
|
|
|
ogs_sctp_write_to_buffer(&enb->sctp, pkbuf);
|
|
|
|
return OGS_OK;
|
|
|
|
} else {
|
|
|
|
return ogs_sctp_senddata(enb->sctp.sock, pkbuf, enb->sctp.addr);
|
|
|
|
}
|
2017-02-13 04:19:53 +00:00
|
|
|
}
|
2017-09-07 06:56:31 +00:00
|
|
|
|
2019-04-27 14:54:30 +00:00
|
|
|
int s1ap_send_to_enb_ue(enb_ue_t *enb_ue, ogs_pkbuf_t *pkbuf)
|
2017-09-18 10:30:03 +00:00
|
|
|
{
|
2018-05-13 09:02:24 +00:00
|
|
|
mme_enb_t *enb = NULL;
|
2017-09-18 10:30:03 +00:00
|
|
|
|
2019-04-27 14:54:30 +00:00
|
|
|
ogs_assert(enb_ue);
|
2018-05-13 09:02:24 +00:00
|
|
|
enb = enb_ue->enb;
|
2019-04-27 14:54:30 +00:00
|
|
|
ogs_assert(enb);
|
2018-05-13 09:02:24 +00:00
|
|
|
|
2019-06-28 09:11:16 +00:00
|
|
|
return s1ap_send_to_enb(enb, pkbuf, enb_ue->enb_ostream_id);
|
2018-05-13 09:02:24 +00:00
|
|
|
}
|
|
|
|
|
2019-04-27 14:54:30 +00:00
|
|
|
int s1ap_delayed_send_to_enb_ue(
|
|
|
|
enb_ue_t *enb_ue, ogs_pkbuf_t *pkbuf, ogs_time_t duration)
|
2018-05-13 09:02:24 +00:00
|
|
|
{
|
2019-04-27 14:54:30 +00:00
|
|
|
ogs_assert(enb_ue);
|
|
|
|
ogs_assert(pkbuf);
|
2017-09-18 10:30:03 +00:00
|
|
|
|
2019-06-01 09:52:38 +00:00
|
|
|
if (duration) {
|
2019-04-27 14:54:30 +00:00
|
|
|
mme_event_t *e = NULL;
|
2017-09-18 10:30:03 +00:00
|
|
|
|
2019-07-20 06:16:46 +00:00
|
|
|
e = mme_event_new(MME_EVT_S1AP_TIMER);
|
2019-04-27 14:54:30 +00:00
|
|
|
ogs_assert(e);
|
2019-07-20 06:16:46 +00:00
|
|
|
e->timer = ogs_timer_add(
|
2020-08-26 03:05:01 +00:00
|
|
|
ogs_app()->timer_mgr, mme_timer_s1_delayed_send, e);
|
2019-04-27 14:54:30 +00:00
|
|
|
ogs_assert(e->timer);
|
|
|
|
e->pkbuf = pkbuf;
|
|
|
|
e->enb_ue = enb_ue;
|
2019-07-20 06:16:46 +00:00
|
|
|
e->enb = enb_ue->enb;
|
2017-09-18 10:30:03 +00:00
|
|
|
|
2019-04-27 14:54:30 +00:00
|
|
|
ogs_timer_start(e->timer, duration);
|
2017-09-18 10:30:03 +00:00
|
|
|
|
2019-04-27 14:54:30 +00:00
|
|
|
return OGS_OK;
|
2019-06-01 09:52:38 +00:00
|
|
|
} else {
|
2018-05-13 09:02:24 +00:00
|
|
|
mme_enb_t *enb = NULL;
|
|
|
|
enb = enb_ue->enb;
|
2019-04-27 14:54:30 +00:00
|
|
|
ogs_assert(enb);
|
2018-05-13 09:02:24 +00:00
|
|
|
return s1ap_send_to_enb_ue(enb_ue, pkbuf);
|
2017-09-18 10:30:03 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-11-08 02:25:53 +00:00
|
|
|
int s1ap_send_to_esm(mme_ue_t *mme_ue, ogs_pkbuf_t *esmbuf, uint8_t nas_type)
|
2017-09-07 06:56:31 +00:00
|
|
|
{
|
2019-05-06 14:13:26 +00:00
|
|
|
int rv;
|
2019-04-27 14:54:30 +00:00
|
|
|
mme_event_t *e = NULL;
|
2017-09-07 06:56:31 +00:00
|
|
|
|
2019-04-27 14:54:30 +00:00
|
|
|
ogs_assert(mme_ue);
|
|
|
|
ogs_assert(esmbuf);
|
2017-09-07 06:56:31 +00:00
|
|
|
|
2019-04-27 14:54:30 +00:00
|
|
|
e = mme_event_new(MME_EVT_ESM_MESSAGE);
|
|
|
|
ogs_assert(e);
|
|
|
|
e->mme_ue = mme_ue;
|
|
|
|
e->pkbuf = esmbuf;
|
2020-11-08 02:25:53 +00:00
|
|
|
e->nas_type = nas_type;
|
2020-08-26 03:05:01 +00:00
|
|
|
rv = ogs_queue_push(ogs_app()->queue, e);
|
2019-05-06 14:13:26 +00:00
|
|
|
if (rv != OGS_OK) {
|
|
|
|
ogs_warn("ogs_queue_push() failed:%d", (int)rv);
|
|
|
|
ogs_pkbuf_free(e->pkbuf);
|
|
|
|
mme_event_free(e);
|
|
|
|
}
|
2017-09-07 06:56:31 +00:00
|
|
|
|
2019-11-30 07:45:09 +00:00
|
|
|
return rv;
|
2017-09-07 06:56:31 +00:00
|
|
|
}
|
2018-05-13 09:02:24 +00:00
|
|
|
|
2019-04-27 14:54:30 +00:00
|
|
|
int s1ap_send_to_nas(enb_ue_t *enb_ue,
|
2018-03-05 14:01:07 +00:00
|
|
|
S1AP_ProcedureCode_t procedureCode, S1AP_NAS_PDU_t *nasPdu)
|
2017-09-07 06:56:31 +00:00
|
|
|
{
|
2020-05-23 02:24:48 +00:00
|
|
|
ogs_nas_eps_security_header_t *sh = NULL;
|
|
|
|
ogs_nas_security_header_type_t security_header_type;
|
2017-09-07 06:56:31 +00:00
|
|
|
|
2019-09-13 12:07:47 +00:00
|
|
|
ogs_nas_emm_header_t *h = NULL;
|
2019-04-27 14:54:30 +00:00
|
|
|
ogs_pkbuf_t *nasbuf = NULL;
|
|
|
|
mme_event_t *e = NULL;
|
2017-09-07 06:56:31 +00:00
|
|
|
|
2019-04-27 14:54:30 +00:00
|
|
|
ogs_assert(enb_ue);
|
|
|
|
ogs_assert(nasPdu);
|
2017-09-07 06:56:31 +00:00
|
|
|
|
|
|
|
/* 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. */
|
2019-09-13 12:07:47 +00:00
|
|
|
nasbuf = ogs_pkbuf_alloc(NULL, OGS_NAS_HEADROOM+nasPdu->size);
|
2020-09-07 03:53:38 +00:00
|
|
|
ogs_assert(nasbuf);
|
2019-09-13 12:07:47 +00:00
|
|
|
ogs_pkbuf_reserve(nasbuf, OGS_NAS_HEADROOM);
|
2019-04-27 14:54:30 +00:00
|
|
|
ogs_pkbuf_put_data(nasbuf, nasPdu->buf, nasPdu->size);
|
2017-09-07 06:56:31 +00:00
|
|
|
|
2020-05-23 02:24:48 +00:00
|
|
|
sh = (ogs_nas_eps_security_header_t *)nasbuf->data;
|
2019-04-27 14:54:30 +00:00
|
|
|
ogs_assert(sh);
|
2017-09-07 06:56:31 +00:00
|
|
|
|
2020-05-23 02:24:48 +00:00
|
|
|
memset(&security_header_type, 0, sizeof(ogs_nas_security_header_type_t));
|
2019-06-01 09:52:38 +00:00
|
|
|
switch(sh->security_header_type) {
|
2019-09-13 12:07:47 +00:00
|
|
|
case OGS_NAS_SECURITY_HEADER_PLAIN_NAS_MESSAGE:
|
2019-06-01 09:52:38 +00:00
|
|
|
break;
|
2019-09-13 12:07:47 +00:00
|
|
|
case OGS_NAS_SECURITY_HEADER_FOR_SERVICE_REQUEST_MESSAGE:
|
2019-06-01 09:52:38 +00:00
|
|
|
security_header_type.service_request = 1;
|
|
|
|
break;
|
2019-09-13 12:07:47 +00:00
|
|
|
case OGS_NAS_SECURITY_HEADER_INTEGRITY_PROTECTED:
|
2019-06-01 09:52:38 +00:00
|
|
|
security_header_type.integrity_protected = 1;
|
2019-11-30 07:45:09 +00:00
|
|
|
ogs_pkbuf_pull(nasbuf, 6);
|
2019-06-01 09:52:38 +00:00
|
|
|
break;
|
2019-09-13 12:07:47 +00:00
|
|
|
case OGS_NAS_SECURITY_HEADER_INTEGRITY_PROTECTED_AND_CIPHERED:
|
2019-06-01 09:52:38 +00:00
|
|
|
security_header_type.integrity_protected = 1;
|
|
|
|
security_header_type.ciphered = 1;
|
2019-11-30 07:45:09 +00:00
|
|
|
ogs_pkbuf_pull(nasbuf, 6);
|
2019-06-01 09:52:38 +00:00
|
|
|
break;
|
2019-09-13 12:07:47 +00:00
|
|
|
case OGS_NAS_SECURITY_HEADER_INTEGRITY_PROTECTED_AND_NEW_SECURITY_CONTEXT:
|
2019-06-01 09:52:38 +00:00
|
|
|
security_header_type.integrity_protected = 1;
|
|
|
|
security_header_type.new_security_context = 1;
|
2019-11-30 07:45:09 +00:00
|
|
|
ogs_pkbuf_pull(nasbuf, 6);
|
2019-06-01 09:52:38 +00:00
|
|
|
break;
|
2019-09-13 12:07:47 +00:00
|
|
|
case OGS_NAS_SECURITY_HEADER_INTEGRITY_PROTECTED_AND_CIPHTERD_WITH_NEW_INTEGRITY_CONTEXT:
|
2019-06-01 09:52:38 +00:00
|
|
|
security_header_type.integrity_protected = 1;
|
|
|
|
security_header_type.ciphered = 1;
|
|
|
|
security_header_type.new_security_context = 1;
|
2019-11-30 07:45:09 +00:00
|
|
|
ogs_pkbuf_pull(nasbuf, 6);
|
2019-06-01 09:52:38 +00:00
|
|
|
break;
|
|
|
|
default:
|
2020-04-26 19:36:05 +00:00
|
|
|
ogs_error("Not implemented(security header type:0x%x)",
|
2019-06-01 09:52:38 +00:00
|
|
|
sh->security_header_type);
|
|
|
|
return OGS_ERROR;
|
2017-09-07 06:56:31 +00:00
|
|
|
}
|
|
|
|
|
2019-06-01 09:52:38 +00:00
|
|
|
if (enb_ue->mme_ue) {
|
2020-05-23 02:24:48 +00:00
|
|
|
if (nas_eps_security_decode(enb_ue->mme_ue,
|
2019-11-30 07:45:09 +00:00
|
|
|
security_header_type, nasbuf) != OGS_OK) {
|
2020-05-23 02:24:48 +00:00
|
|
|
ogs_error("nas_eps_security_decode failed()");
|
2019-11-29 06:31:22 +00:00
|
|
|
return OGS_ERROR;
|
|
|
|
}
|
2017-09-07 06:56:31 +00:00
|
|
|
}
|
|
|
|
|
2019-10-27 08:41:14 +00:00
|
|
|
h = (ogs_nas_emm_header_t *)nasbuf->data;
|
2019-04-27 14:54:30 +00:00
|
|
|
ogs_assert(h);
|
2019-09-13 12:07:47 +00:00
|
|
|
if (h->protocol_discriminator == OGS_NAS_PROTOCOL_DISCRIMINATOR_EMM) {
|
2019-05-06 14:13:26 +00:00
|
|
|
int rv;
|
2019-04-27 14:54:30 +00:00
|
|
|
e = mme_event_new(MME_EVT_EMM_MESSAGE);
|
2021-02-15 17:17:33 +00:00
|
|
|
if (!e) {
|
|
|
|
ogs_error("s1ap_send_to_nas() failed");
|
|
|
|
ogs_pkbuf_free(nasbuf);
|
|
|
|
return OGS_ERROR;
|
|
|
|
}
|
2019-04-27 14:54:30 +00:00
|
|
|
e->enb_ue = enb_ue;
|
|
|
|
e->s1ap_code = procedureCode;
|
|
|
|
e->nas_type = security_header_type.type;
|
|
|
|
e->pkbuf = nasbuf;
|
2020-08-26 03:05:01 +00:00
|
|
|
rv = ogs_queue_push(ogs_app()->queue, e);
|
2019-05-06 14:13:26 +00:00
|
|
|
if (rv != OGS_OK) {
|
2021-02-15 17:17:33 +00:00
|
|
|
ogs_warn("s1ap_send_to_nas() failed:%d", (int)rv);
|
2019-05-06 14:13:26 +00:00
|
|
|
ogs_pkbuf_free(e->pkbuf);
|
|
|
|
mme_event_free(e);
|
|
|
|
}
|
2019-11-30 07:45:09 +00:00
|
|
|
return rv;
|
2020-09-22 00:06:41 +00:00
|
|
|
} else if (h->protocol_discriminator ==
|
|
|
|
OGS_NAS_PROTOCOL_DISCRIMINATOR_ESM) {
|
2017-09-07 06:56:31 +00:00
|
|
|
mme_ue_t *mme_ue = enb_ue->mme_ue;
|
2020-09-22 00:06:41 +00:00
|
|
|
if (!mme_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-11-08 02:25:53 +00:00
|
|
|
return s1ap_send_to_esm(mme_ue, nasbuf, security_header_type.type);
|
2019-11-29 06:31:22 +00:00
|
|
|
} else {
|
|
|
|
ogs_error("Unknown/Unimplemented NAS Protocol discriminator 0x%02x",
|
|
|
|
h->protocol_discriminator);
|
2021-02-15 17:17:33 +00:00
|
|
|
ogs_pkbuf_free(nasbuf);
|
2019-11-29 06:31:22 +00:00
|
|
|
return OGS_ERROR;
|
|
|
|
}
|
2017-09-07 06:56:31 +00:00
|
|
|
}
|
|
|
|
|
2020-04-27 02:18:47 +00:00
|
|
|
void s1ap_send_s1_setup_response(mme_enb_t *enb)
|
|
|
|
{
|
|
|
|
ogs_pkbuf_t *s1ap_buffer;
|
|
|
|
|
|
|
|
ogs_debug("[MME] S1-Setup response");
|
|
|
|
s1ap_buffer = s1ap_build_setup_rsp();
|
|
|
|
ogs_expect_or_return(s1ap_buffer);
|
|
|
|
|
|
|
|
ogs_expect(OGS_OK ==
|
|
|
|
s1ap_send_to_enb(enb, s1ap_buffer, S1AP_NON_UE_SIGNALLING));
|
|
|
|
}
|
|
|
|
|
|
|
|
void s1ap_send_s1_setup_failure(
|
|
|
|
mme_enb_t *enb, S1AP_Cause_PR group, long cause)
|
|
|
|
{
|
|
|
|
ogs_pkbuf_t *s1ap_buffer;
|
|
|
|
|
|
|
|
ogs_debug("[MME] S1-Setup failure");
|
|
|
|
s1ap_buffer = s1ap_build_setup_failure(group, cause, S1AP_TimeToWait_v10s);
|
|
|
|
ogs_expect_or_return(s1ap_buffer);
|
|
|
|
|
|
|
|
ogs_expect(OGS_OK ==
|
|
|
|
s1ap_send_to_enb(enb, s1ap_buffer, S1AP_NON_UE_SIGNALLING));
|
|
|
|
}
|
|
|
|
|
2019-11-30 07:45:09 +00:00
|
|
|
void s1ap_send_initial_context_setup_request(mme_ue_t *mme_ue)
|
2017-09-10 14:03:24 +00:00
|
|
|
{
|
2019-04-27 14:54:30 +00:00
|
|
|
int rv;
|
|
|
|
ogs_pkbuf_t *s1apbuf = NULL;
|
2017-09-10 14:03:24 +00:00
|
|
|
|
2019-04-27 14:54:30 +00:00
|
|
|
ogs_assert(mme_ue);
|
2017-09-10 14:03:24 +00:00
|
|
|
|
2019-11-30 07:45:09 +00:00
|
|
|
s1apbuf = s1ap_build_initial_context_setup_request(mme_ue, NULL);
|
|
|
|
ogs_expect_or_return(s1apbuf);
|
2017-09-10 14:03:24 +00:00
|
|
|
|
2020-05-23 02:24:48 +00:00
|
|
|
rv = nas_eps_send_to_enb(mme_ue, s1apbuf);
|
2019-11-29 06:31:22 +00:00
|
|
|
ogs_expect(rv == OGS_OK);
|
2017-09-10 14:03:24 +00:00
|
|
|
}
|
2017-09-07 06:56:31 +00:00
|
|
|
|
2019-11-30 07:45:09 +00:00
|
|
|
void s1ap_send_ue_context_modification_request(mme_ue_t *mme_ue)
|
2019-07-10 13:04:52 +00:00
|
|
|
{
|
|
|
|
int rv;
|
|
|
|
ogs_pkbuf_t *s1apbuf = NULL;
|
|
|
|
|
|
|
|
ogs_assert(mme_ue);
|
|
|
|
|
2019-11-30 07:45:09 +00:00
|
|
|
s1apbuf = s1ap_build_ue_context_modification_request(mme_ue);
|
|
|
|
ogs_expect_or_return(s1apbuf);
|
2019-07-10 13:04:52 +00:00
|
|
|
|
2020-05-23 02:24:48 +00:00
|
|
|
rv = nas_eps_send_to_enb(mme_ue, s1apbuf);
|
2019-11-29 06:31:22 +00:00
|
|
|
ogs_expect(rv == OGS_OK);
|
2019-07-10 13:04:52 +00:00
|
|
|
}
|
|
|
|
|
2019-11-15 14:56:55 +00:00
|
|
|
void s1ap_send_ue_context_release_command(
|
2018-03-05 14:01:07 +00:00
|
|
|
enb_ue_t *enb_ue, S1AP_Cause_PR group, long cause,
|
2021-01-28 19:23:54 +00:00
|
|
|
uint8_t action, ogs_time_t duration)
|
2017-09-08 07:46:37 +00:00
|
|
|
{
|
2019-04-27 14:54:30 +00:00
|
|
|
int rv;
|
|
|
|
ogs_pkbuf_t *s1apbuf = NULL;
|
2017-09-08 07:46:37 +00:00
|
|
|
|
2019-04-27 14:54:30 +00:00
|
|
|
ogs_assert(enb_ue);
|
2017-09-08 07:46:37 +00:00
|
|
|
|
2019-04-27 14:54:30 +00:00
|
|
|
ogs_debug("[MME] UE Context release command");
|
|
|
|
ogs_debug(" ENB_UE_S1AP_ID[%d] MME_UE_S1AP_ID[%d]",
|
2018-01-22 14:14:20 +00:00
|
|
|
enb_ue->enb_ue_s1ap_id, enb_ue->mme_ue_s1ap_id);
|
|
|
|
|
2020-09-03 23:59:00 +00:00
|
|
|
ogs_assert(action != S1AP_UE_CTX_REL_INVALID_ACTION);
|
|
|
|
enb_ue->ue_ctx_rel_action = action;
|
2017-09-08 07:46:37 +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);
|
2019-07-20 16:03:19 +00:00
|
|
|
|
2020-09-03 23:59:00 +00:00
|
|
|
s1apbuf = s1ap_build_ue_context_release_command(enb_ue, group, cause);
|
|
|
|
ogs_expect_or_return(s1apbuf);
|
2019-11-18 00:04:10 +00:00
|
|
|
|
2021-01-28 19:23:54 +00:00
|
|
|
rv = s1ap_delayed_send_to_enb_ue(enb_ue, s1apbuf, duration);
|
2020-09-03 23:59:00 +00:00
|
|
|
ogs_expect(rv == OGS_OK);
|
2019-07-20 16:03:19 +00:00
|
|
|
|
2020-09-03 23:59:00 +00:00
|
|
|
ogs_timer_start(enb_ue->t_s1_holding,
|
|
|
|
mme_timer_cfg(MME_TIMER_S1_HOLDING)->duration);
|
2017-09-08 07:46:37 +00:00
|
|
|
}
|
2017-09-11 12:14:55 +00:00
|
|
|
|
2019-07-08 09:15:19 +00:00
|
|
|
void s1ap_send_paging(mme_ue_t *mme_ue, S1AP_CNDomain_t cn_domain)
|
|
|
|
{
|
|
|
|
ogs_pkbuf_t *s1apbuf = NULL;
|
|
|
|
mme_enb_t *enb = NULL;
|
|
|
|
int i;
|
|
|
|
int rv;
|
|
|
|
|
|
|
|
/* Find enB with matched TAI */
|
2019-07-08 12:03:39 +00:00
|
|
|
ogs_list_for_each(&mme_self()->enb_list, enb) {
|
2019-07-08 09:15:19 +00:00
|
|
|
for (i = 0; i < enb->num_of_supported_ta_list; i++) {
|
|
|
|
|
|
|
|
if (memcmp(&enb->supported_ta_list[i], &mme_ue->tai,
|
2020-05-25 16:15:22 +00:00
|
|
|
sizeof(ogs_eps_tai_t)) == 0) {
|
2019-07-08 09:15:19 +00:00
|
|
|
|
2019-07-20 11:38:03 +00:00
|
|
|
if (mme_ue->t3413.pkbuf) {
|
|
|
|
s1apbuf = mme_ue->t3413.pkbuf;
|
2019-07-08 12:44:03 +00:00
|
|
|
} else {
|
2019-11-30 07:45:09 +00:00
|
|
|
s1apbuf = s1ap_build_paging(mme_ue, cn_domain);
|
|
|
|
ogs_expect_or_return(s1apbuf);
|
2019-07-08 12:44:03 +00:00
|
|
|
}
|
2019-07-08 09:15:19 +00:00
|
|
|
|
2019-07-20 11:38:03 +00:00
|
|
|
mme_ue->t3413.pkbuf = ogs_pkbuf_copy(s1apbuf);
|
2020-09-18 18:53:23 +00:00
|
|
|
ogs_assert(mme_ue->t3413.pkbuf);
|
2019-07-08 09:15:19 +00:00
|
|
|
|
2021-01-18 16:48:35 +00:00
|
|
|
rv = s1ap_send_to_enb(enb, s1apbuf, mme_ue->enb_ostream_id);
|
2019-11-29 06:31:22 +00:00
|
|
|
ogs_expect(rv == OGS_OK);
|
2019-07-08 09:15:19 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Start T3413 */
|
2019-07-20 11:38:03 +00:00
|
|
|
ogs_timer_start(mme_ue->t3413.timer,
|
2019-07-20 07:25:09 +00:00
|
|
|
mme_timer_cfg(MME_TIMER_T3413)->duration);
|
2019-07-08 09:15:19 +00:00
|
|
|
}
|
|
|
|
|
2019-11-30 07:45:09 +00:00
|
|
|
void s1ap_send_mme_configuration_transfer(
|
2018-03-24 01:08:55 +00:00
|
|
|
mme_enb_t *target_enb,
|
|
|
|
S1AP_SONConfigurationTransfer_t *SONConfigurationTransfer)
|
|
|
|
{
|
2019-04-27 14:54:30 +00:00
|
|
|
int rv;
|
|
|
|
ogs_pkbuf_t *s1apbuf = NULL;
|
2018-03-24 01:08:55 +00:00
|
|
|
|
2019-04-27 14:54:30 +00:00
|
|
|
ogs_assert(target_enb);
|
|
|
|
ogs_assert(SONConfigurationTransfer);
|
2018-03-24 01:08:55 +00:00
|
|
|
|
2019-11-30 07:45:09 +00:00
|
|
|
s1apbuf = s1ap_build_mme_configuration_transfer(SONConfigurationTransfer);
|
|
|
|
ogs_expect_or_return(s1apbuf);
|
2018-03-24 01:08:55 +00:00
|
|
|
|
2018-05-13 09:02:24 +00:00
|
|
|
rv = s1ap_send_to_enb(target_enb, s1apbuf, S1AP_NON_UE_SIGNALLING);
|
2019-11-29 06:31:22 +00:00
|
|
|
ogs_expect(rv == OGS_OK);
|
2018-03-24 01:08:55 +00:00
|
|
|
}
|
|
|
|
|
2019-11-30 07:45:09 +00:00
|
|
|
void s1ap_send_path_switch_ack(mme_ue_t *mme_ue)
|
2017-09-11 12:14:55 +00:00
|
|
|
{
|
2019-04-27 14:54:30 +00:00
|
|
|
int rv;
|
|
|
|
ogs_pkbuf_t *s1apbuf = NULL;
|
2017-09-11 12:14:55 +00:00
|
|
|
|
2019-04-27 14:54:30 +00:00
|
|
|
ogs_assert(mme_ue);
|
2017-09-11 12:14:55 +00:00
|
|
|
|
2019-11-30 07:45:09 +00:00
|
|
|
s1apbuf = s1ap_build_path_switch_ack(mme_ue);
|
|
|
|
ogs_expect_or_return(s1apbuf);
|
2017-09-11 12:14:55 +00:00
|
|
|
|
2020-05-23 02:24:48 +00:00
|
|
|
rv = nas_eps_send_to_enb(mme_ue, s1apbuf);
|
2019-11-29 06:31:22 +00:00
|
|
|
ogs_expect(rv == OGS_OK);
|
2017-09-11 12:14:55 +00:00
|
|
|
}
|
|
|
|
|
2019-11-30 07:45:09 +00:00
|
|
|
void s1ap_send_handover_command(enb_ue_t *source_ue)
|
2017-09-15 04:28:07 +00:00
|
|
|
{
|
2019-04-27 14:54:30 +00:00
|
|
|
int rv;
|
|
|
|
ogs_pkbuf_t *s1apbuf = NULL;
|
2017-09-15 04:28:07 +00:00
|
|
|
|
2019-04-27 14:54:30 +00:00
|
|
|
ogs_assert(source_ue);
|
2017-09-15 04:28:07 +00:00
|
|
|
|
2019-11-30 07:45:09 +00:00
|
|
|
s1apbuf = s1ap_build_handover_command(source_ue);
|
|
|
|
ogs_expect_or_return(s1apbuf);
|
2017-09-15 04:28:07 +00:00
|
|
|
|
2018-05-13 09:02:24 +00:00
|
|
|
rv = s1ap_send_to_enb_ue(source_ue, s1apbuf);
|
2019-11-29 06:31:22 +00:00
|
|
|
ogs_expect(rv == OGS_OK);
|
2017-09-15 04:28:07 +00:00
|
|
|
}
|
|
|
|
|
2019-11-30 07:45:09 +00:00
|
|
|
void s1ap_send_handover_preparation_failure(
|
2018-03-05 14:01:07 +00:00
|
|
|
enb_ue_t *source_ue, S1AP_Cause_t *cause)
|
2017-09-15 04:28:07 +00:00
|
|
|
{
|
2019-04-27 14:54:30 +00:00
|
|
|
int rv;
|
|
|
|
ogs_pkbuf_t *s1apbuf = NULL;
|
2017-09-15 04:28:07 +00:00
|
|
|
|
2019-04-27 14:54:30 +00:00
|
|
|
ogs_assert(source_ue);
|
|
|
|
ogs_assert(cause);
|
2017-09-15 04:28:07 +00:00
|
|
|
|
2019-11-30 07:45:09 +00:00
|
|
|
s1apbuf = s1ap_build_handover_preparation_failure(source_ue, cause);
|
|
|
|
ogs_expect_or_return(s1apbuf);
|
2017-09-15 04:28:07 +00:00
|
|
|
|
2018-05-13 09:02:24 +00:00
|
|
|
rv = s1ap_send_to_enb_ue(source_ue, s1apbuf);
|
2019-11-29 06:31:22 +00:00
|
|
|
ogs_expect(rv == OGS_OK);
|
2017-09-15 04:28:07 +00:00
|
|
|
}
|
|
|
|
|
2019-11-30 07:45:09 +00:00
|
|
|
void s1ap_send_handover_cancel_ack(enb_ue_t *source_ue)
|
2017-09-15 04:28:07 +00:00
|
|
|
{
|
2019-04-27 14:54:30 +00:00
|
|
|
int rv;
|
|
|
|
ogs_pkbuf_t *s1apbuf = NULL;
|
2017-09-15 04:28:07 +00:00
|
|
|
|
2019-04-27 14:54:30 +00:00
|
|
|
ogs_assert(source_ue);
|
2017-09-15 04:28:07 +00:00
|
|
|
|
2019-11-30 07:45:09 +00:00
|
|
|
s1apbuf = s1ap_build_handover_cancel_ack(source_ue);
|
|
|
|
ogs_expect_or_return(s1apbuf);
|
2017-09-15 04:28:07 +00:00
|
|
|
|
2018-05-13 09:02:24 +00:00
|
|
|
rv = s1ap_send_to_enb_ue(source_ue, s1apbuf);
|
2019-11-29 06:31:22 +00:00
|
|
|
ogs_expect(rv == OGS_OK);
|
2017-09-15 04:28:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2019-11-30 07:45:09 +00:00
|
|
|
void s1ap_send_handover_request(
|
2021-01-28 19:23:54 +00:00
|
|
|
enb_ue_t *source_ue, mme_enb_t *target_enb,
|
|
|
|
S1AP_HandoverType_t *handovertype, S1AP_Cause_t *cause,
|
2018-03-13 14:16:01 +00:00
|
|
|
S1AP_Source_ToTarget_TransparentContainer_t
|
|
|
|
*source_totarget_transparentContainer)
|
2017-09-12 14:07:55 +00:00
|
|
|
{
|
2019-04-27 14:54:30 +00:00
|
|
|
int rv;
|
|
|
|
ogs_pkbuf_t *s1apbuf = NULL;
|
2017-09-12 14:07:55 +00:00
|
|
|
|
2021-01-28 19:23:54 +00:00
|
|
|
enb_ue_t *target_ue = NULL;
|
2017-09-12 14:07:55 +00:00
|
|
|
|
2021-01-05 04:24:22 +00:00
|
|
|
ogs_info("Handover request");
|
2018-03-23 04:14:56 +00:00
|
|
|
|
2019-04-27 14:54:30 +00:00
|
|
|
ogs_assert(source_ue);
|
|
|
|
ogs_assert(source_ue->target_ue == NULL);
|
2021-01-28 19:23:54 +00:00
|
|
|
ogs_assert(target_enb);
|
2017-09-14 10:33:58 +00:00
|
|
|
|
2019-12-13 04:46:22 +00:00
|
|
|
target_ue = enb_ue_add(target_enb, INVALID_UE_S1AP_ID);
|
2019-04-27 14:54:30 +00:00
|
|
|
ogs_assert(target_ue);
|
2017-09-12 14:07:55 +00:00
|
|
|
|
2021-01-05 04:24:22 +00:00
|
|
|
ogs_info(" Source : ENB_UE_S1AP_ID[%d] MME_UE_S1AP_ID[%d]",
|
2018-01-22 14:14:20 +00:00
|
|
|
source_ue->enb_ue_s1ap_id, source_ue->mme_ue_s1ap_id);
|
2021-01-05 04:24:22 +00:00
|
|
|
ogs_info(" Target : ENB_UE_S1AP_ID[Unknown] MME_UE_S1AP_ID[%d]",
|
2018-01-28 06:08:52 +00:00
|
|
|
target_ue->mme_ue_s1ap_id);
|
2018-01-22 14:14:20 +00:00
|
|
|
|
2019-06-30 11:46:15 +00:00
|
|
|
source_ue_associate_target_ue(source_ue, target_ue);
|
2017-09-12 14:07:55 +00:00
|
|
|
|
2021-01-28 19:23:54 +00:00
|
|
|
s1apbuf = s1ap_build_handover_request(
|
|
|
|
target_ue, handovertype, cause,
|
2018-03-13 14:16:01 +00:00
|
|
|
source_totarget_transparentContainer);
|
2019-11-30 07:45:09 +00:00
|
|
|
ogs_expect_or_return(s1apbuf);
|
2017-09-12 14:07:55 +00:00
|
|
|
|
2018-05-13 09:02:24 +00:00
|
|
|
rv = s1ap_send_to_enb_ue(target_ue, s1apbuf);
|
2019-11-29 06:31:22 +00:00
|
|
|
ogs_expect(rv == OGS_OK);
|
2017-09-12 14:07:55 +00:00
|
|
|
}
|
2017-09-13 12:51:02 +00:00
|
|
|
|
2019-11-30 07:45:09 +00:00
|
|
|
void s1ap_send_mme_status_transfer(
|
2018-03-13 14:16:01 +00:00
|
|
|
enb_ue_t *target_ue,
|
|
|
|
S1AP_ENB_StatusTransfer_TransparentContainer_t
|
|
|
|
*enb_statustransfer_transparentContainer)
|
2017-09-14 02:12:02 +00:00
|
|
|
{
|
2019-04-27 14:54:30 +00:00
|
|
|
int rv;
|
|
|
|
ogs_pkbuf_t *s1apbuf = NULL;
|
2017-09-14 02:12:02 +00:00
|
|
|
|
2019-04-27 14:54:30 +00:00
|
|
|
ogs_assert(target_ue);
|
2017-09-14 02:12:02 +00:00
|
|
|
|
2019-11-30 07:45:09 +00:00
|
|
|
s1apbuf = s1ap_build_mme_status_transfer(target_ue,
|
2018-03-13 14:16:01 +00:00
|
|
|
enb_statustransfer_transparentContainer);
|
2019-11-30 07:45:09 +00:00
|
|
|
ogs_expect_or_return(s1apbuf);
|
2017-09-14 02:12:02 +00:00
|
|
|
|
2018-05-13 09:02:24 +00:00
|
|
|
rv = s1ap_send_to_enb_ue(target_ue, s1apbuf);
|
2019-11-29 06:31:22 +00:00
|
|
|
ogs_expect(rv == OGS_OK);
|
2017-09-14 02:12:02 +00:00
|
|
|
}
|
2018-02-03 02:48:15 +00:00
|
|
|
|
2019-11-30 07:45:09 +00:00
|
|
|
void s1ap_send_error_indication(
|
2018-03-12 14:06:14 +00:00
|
|
|
mme_enb_t *enb,
|
|
|
|
S1AP_MME_UE_S1AP_ID_t *mme_ue_s1ap_id,
|
|
|
|
S1AP_ENB_UE_S1AP_ID_t *enb_ue_s1ap_id,
|
2018-03-14 08:59:56 +00:00
|
|
|
S1AP_Cause_PR group, long cause)
|
2018-02-03 02:48:15 +00:00
|
|
|
{
|
2019-04-27 14:54:30 +00:00
|
|
|
int rv;
|
|
|
|
ogs_pkbuf_t *s1apbuf = NULL;
|
2018-02-03 02:48:15 +00:00
|
|
|
|
2019-04-27 14:54:30 +00:00
|
|
|
ogs_assert(enb);
|
2018-02-03 02:48:15 +00:00
|
|
|
|
2020-08-22 03:33:45 +00:00
|
|
|
s1apbuf = ogs_s1ap_build_error_indication(
|
2018-03-14 08:59:56 +00:00
|
|
|
mme_ue_s1ap_id, enb_ue_s1ap_id, group, cause);
|
2019-11-30 07:45:09 +00:00
|
|
|
ogs_expect_or_return(s1apbuf);
|
2018-02-03 02:48:15 +00:00
|
|
|
|
2018-05-13 09:02:24 +00:00
|
|
|
rv = s1ap_send_to_enb(enb, s1apbuf, S1AP_NON_UE_SIGNALLING);
|
2019-11-29 06:31:22 +00:00
|
|
|
ogs_expect(rv == OGS_OK);
|
2018-02-03 02:48:15 +00:00
|
|
|
}
|
2018-03-21 07:10:20 +00:00
|
|
|
|
2020-09-08 02:02:45 +00:00
|
|
|
void s1ap_send_error_indication2(
|
|
|
|
mme_ue_t *mme_ue, S1AP_Cause_PR group, long cause)
|
|
|
|
{
|
|
|
|
mme_enb_t *enb;
|
|
|
|
enb_ue_t *enb_ue;
|
|
|
|
|
|
|
|
S1AP_MME_UE_S1AP_ID_t mme_ue_s1ap_id;
|
|
|
|
S1AP_ENB_UE_S1AP_ID_t enb_ue_s1ap_id;
|
|
|
|
|
|
|
|
ogs_assert(mme_ue);
|
2020-10-29 02:59:27 +00:00
|
|
|
enb_ue = enb_ue_cycle(mme_ue->enb_ue);
|
2020-09-08 02:02:45 +00:00
|
|
|
ogs_expect_or_return(enb_ue);
|
|
|
|
enb = enb_ue->enb;
|
|
|
|
ogs_expect_or_return(enb);
|
|
|
|
|
|
|
|
mme_ue_s1ap_id = enb_ue->mme_ue_s1ap_id,
|
|
|
|
enb_ue_s1ap_id = enb_ue->enb_ue_s1ap_id,
|
|
|
|
|
|
|
|
s1ap_send_error_indication(
|
|
|
|
enb, &mme_ue_s1ap_id, &enb_ue_s1ap_id, group, cause);
|
|
|
|
}
|
|
|
|
|
2019-11-30 07:45:09 +00:00
|
|
|
void s1ap_send_s1_reset_ack(
|
2018-03-21 07:10:20 +00:00
|
|
|
mme_enb_t *enb,
|
|
|
|
S1AP_UE_associatedLogicalS1_ConnectionListRes_t *partOfS1_Interface)
|
|
|
|
{
|
2019-04-27 14:54:30 +00:00
|
|
|
int rv;
|
|
|
|
ogs_pkbuf_t *s1apbuf = NULL;
|
2018-03-21 07:10:20 +00:00
|
|
|
|
2019-04-27 14:54:30 +00:00
|
|
|
ogs_assert(enb);
|
2018-03-21 07:10:20 +00:00
|
|
|
|
2020-08-22 03:33:45 +00:00
|
|
|
s1apbuf = ogs_s1ap_build_s1_reset_ack(partOfS1_Interface);
|
2019-11-30 07:45:09 +00:00
|
|
|
ogs_expect_or_return(s1apbuf);
|
2018-03-21 07:10:20 +00:00
|
|
|
|
2018-05-13 09:02:24 +00:00
|
|
|
rv = s1ap_send_to_enb(enb, s1apbuf, S1AP_NON_UE_SIGNALLING);
|
2019-11-29 06:31:22 +00:00
|
|
|
ogs_expect(rv == OGS_OK);
|
2018-03-21 07:10:20 +00:00
|
|
|
}
|