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 "ngap-handler.h"
|
2020-06-25 04:37:29 +00:00
|
|
|
#include "ngap-path.h"
|
|
|
|
#include "sbi-path.h"
|
2021-04-13 08:34:25 +00:00
|
|
|
#include "nas-path.h"
|
2020-05-25 16:15:22 +00:00
|
|
|
|
|
|
|
static bool served_tai_is_found(amf_gnb_t *gnb)
|
|
|
|
{
|
2020-06-23 04:35:41 +00:00
|
|
|
int i, j;
|
2020-05-25 16:15:22 +00:00
|
|
|
int served_tai_index;
|
|
|
|
|
|
|
|
for (i = 0; i < gnb->num_of_supported_ta_list; i++) {
|
2020-06-23 04:35:41 +00:00
|
|
|
for (j = 0; j < gnb->supported_ta_list[i].num_of_bplmn_list; j++) {
|
|
|
|
ogs_5gs_tai_t tai;
|
|
|
|
memcpy(&tai.plmn_id,
|
|
|
|
&gnb->supported_ta_list[i].bplmn_list[j].plmn_id,
|
|
|
|
OGS_PLMN_ID_LEN);
|
|
|
|
tai.tac.v = gnb->supported_ta_list[i].tac.v;
|
|
|
|
served_tai_index = amf_find_served_tai(&tai);
|
|
|
|
if (served_tai_index >= 0 &&
|
|
|
|
served_tai_index < OGS_MAX_NUM_OF_SERVED_TAI) {
|
|
|
|
ogs_debug(" TAC[%d]", gnb->supported_ta_list[i].tac.v);
|
|
|
|
ogs_debug(" PLMN_ID[MCC:%d MNC:%d]",
|
|
|
|
ogs_plmn_id_mcc(&gnb->supported_ta_list[i].
|
|
|
|
bplmn_list[j].plmn_id),
|
|
|
|
ogs_plmn_id_mnc(&gnb->supported_ta_list[i].
|
|
|
|
bplmn_list[j].plmn_id));
|
|
|
|
ogs_debug(" SERVED_TAI_INDEX[%d]", served_tai_index);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool s_nssai_is_found(amf_gnb_t *gnb)
|
|
|
|
{
|
|
|
|
int i, j, k;
|
|
|
|
ogs_s_nssai_t *s_nssai = NULL;
|
|
|
|
|
|
|
|
for (i = 0; i < gnb->num_of_supported_ta_list; i++) {
|
|
|
|
for (j = 0; j < gnb->supported_ta_list[i].num_of_bplmn_list; j++) {
|
|
|
|
for (k = 0; k < gnb->supported_ta_list[i].
|
|
|
|
bplmn_list[j].num_of_s_nssai; k++) {
|
|
|
|
s_nssai = amf_find_s_nssai(
|
|
|
|
&gnb->supported_ta_list[i].bplmn_list[j].plmn_id,
|
|
|
|
&gnb->supported_ta_list[i].bplmn_list[j].s_nssai[k]);
|
|
|
|
if (s_nssai) {
|
|
|
|
ogs_debug(" PLMN_ID[MCC:%d MNC:%d]",
|
|
|
|
ogs_plmn_id_mcc(&gnb->supported_ta_list[i].
|
|
|
|
bplmn_list[j].plmn_id),
|
|
|
|
ogs_plmn_id_mnc(&gnb->supported_ta_list[i].
|
|
|
|
bplmn_list[j].plmn_id));
|
|
|
|
ogs_debug(" S_NSSAI[SST:%d SD:0x%x]",
|
|
|
|
gnb->supported_ta_list[i].bplmn_list[j].s_nssai[k].sst,
|
|
|
|
gnb->supported_ta_list[i].bplmn_list[j].
|
|
|
|
s_nssai[k].sd.v);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
2020-05-25 16:15:22 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool maximum_number_of_gnbs_is_reached(void)
|
|
|
|
{
|
|
|
|
amf_gnb_t *gnb = NULL, *next_gnb = NULL;
|
|
|
|
int number_of_gnbs_online = 0;
|
|
|
|
|
|
|
|
ogs_list_for_each_safe(&amf_self()->gnb_list, next_gnb, gnb) {
|
|
|
|
if (gnb->state.ng_setup_success) {
|
|
|
|
number_of_gnbs_online++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-08-05 07:56:36 +00:00
|
|
|
return number_of_gnbs_online >= ogs_app()->max.peer;
|
2020-05-25 16:15:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void ngap_handle_ng_setup_request(amf_gnb_t *gnb, ogs_ngap_message_t *message)
|
|
|
|
{
|
|
|
|
char buf[OGS_ADDRSTRLEN];
|
2023-01-23 01:37:22 +00:00
|
|
|
int i, j, k, r;
|
2020-05-25 16:15:22 +00:00
|
|
|
|
|
|
|
NGAP_InitiatingMessage_t *initiatingMessage = NULL;
|
|
|
|
NGAP_NGSetupRequest_t *NGSetupRequest = NULL;
|
|
|
|
|
|
|
|
NGAP_NGSetupRequestIEs_t *ie = NULL;
|
|
|
|
NGAP_GlobalRANNodeID_t *GlobalRANNodeID = NULL;
|
|
|
|
NGAP_GlobalGNB_ID_t *globalGNB_ID = NULL;
|
|
|
|
NGAP_SupportedTAList_t *SupportedTAList = NULL;
|
|
|
|
NGAP_PagingDRX_t *PagingDRX = NULL;
|
|
|
|
|
|
|
|
NGAP_Cause_PR group = NGAP_Cause_PR_NOTHING;
|
|
|
|
long cause = 0;
|
|
|
|
|
2020-06-04 18:12:05 +00:00
|
|
|
uint32_t gnb_id;
|
|
|
|
|
2020-05-25 16:15:22 +00:00
|
|
|
ogs_assert(gnb);
|
2020-11-11 18:21:32 +00:00
|
|
|
ogs_assert(gnb->sctp.sock);
|
2020-05-25 16:15:22 +00:00
|
|
|
|
|
|
|
ogs_assert(message);
|
|
|
|
initiatingMessage = message->choice.initiatingMessage;
|
|
|
|
ogs_assert(initiatingMessage);
|
|
|
|
NGSetupRequest = &initiatingMessage->value.choice.NGSetupRequest;
|
|
|
|
ogs_assert(NGSetupRequest);
|
|
|
|
|
2021-02-01 13:52:22 +00:00
|
|
|
ogs_debug("NGSetupRequest");
|
2020-05-25 16:15:22 +00:00
|
|
|
|
|
|
|
for (i = 0; i < NGSetupRequest->protocolIEs.list.count; i++) {
|
|
|
|
ie = NGSetupRequest->protocolIEs.list.array[i];
|
|
|
|
switch (ie->id) {
|
|
|
|
case NGAP_ProtocolIE_ID_id_GlobalRANNodeID:
|
|
|
|
GlobalRANNodeID = &ie->value.choice.GlobalRANNodeID;
|
|
|
|
break;
|
|
|
|
case NGAP_ProtocolIE_ID_id_SupportedTAList:
|
|
|
|
SupportedTAList = &ie->value.choice.SupportedTAList;
|
|
|
|
break;
|
|
|
|
case NGAP_ProtocolIE_ID_id_DefaultPagingDRX:
|
|
|
|
PagingDRX = &ie->value.choice.PagingDRX;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!GlobalRANNodeID) {
|
2020-06-17 05:22:28 +00:00
|
|
|
ogs_error("No GlobalRANNodeID");
|
2020-05-25 16:15:22 +00:00
|
|
|
group = NGAP_Cause_PR_protocol;
|
|
|
|
cause = NGAP_CauseProtocol_semantic_error;
|
2023-01-23 01:37:22 +00:00
|
|
|
r = ngap_send_ng_setup_failure(gnb, group, cause);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2020-05-25 16:15:22 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
globalGNB_ID = GlobalRANNodeID->choice.globalGNB_ID;
|
|
|
|
if (!globalGNB_ID) {
|
2020-06-17 05:22:28 +00:00
|
|
|
ogs_error("No globalGNB_ID");
|
2020-05-25 16:15:22 +00:00
|
|
|
group = NGAP_Cause_PR_protocol;
|
|
|
|
cause = NGAP_CauseProtocol_semantic_error;
|
2023-01-23 01:37:22 +00:00
|
|
|
r = ngap_send_ng_setup_failure(gnb, group, cause);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2020-05-25 16:15:22 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!SupportedTAList) {
|
2020-06-17 05:22:28 +00:00
|
|
|
ogs_error("No SupportedTAList");
|
2020-05-25 16:15:22 +00:00
|
|
|
group = NGAP_Cause_PR_protocol;
|
|
|
|
cause = NGAP_CauseProtocol_semantic_error;
|
2023-01-23 01:37:22 +00:00
|
|
|
r = ngap_send_ng_setup_failure(gnb, group, cause);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2020-05-25 16:15:22 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
ogs_ngap_GNB_ID_to_uint32(&globalGNB_ID->gNB_ID, &gnb_id);
|
2020-11-11 18:21:32 +00:00
|
|
|
ogs_debug(" IP[%s] GNB_ID[0x%x]", OGS_ADDR(gnb->sctp.addr, buf), gnb_id);
|
2020-05-25 16:15:22 +00:00
|
|
|
|
|
|
|
if (PagingDRX)
|
|
|
|
ogs_debug(" PagingDRX[%ld]", *PagingDRX);
|
|
|
|
|
|
|
|
/* Parse Supported TA */
|
2020-06-23 04:35:41 +00:00
|
|
|
for (i = 0, gnb->num_of_supported_ta_list = 0;
|
|
|
|
i < SupportedTAList->list.count &&
|
|
|
|
gnb->num_of_supported_ta_list < OGS_MAX_NUM_OF_TAI;
|
|
|
|
i++) {
|
2020-05-25 16:15:22 +00:00
|
|
|
NGAP_SupportedTAItem_t *SupportedTAItem = NULL;
|
|
|
|
|
|
|
|
SupportedTAItem = (NGAP_SupportedTAItem_t *)
|
|
|
|
SupportedTAList->list.array[i];
|
2020-06-23 04:35:41 +00:00
|
|
|
if (!SupportedTAItem) {
|
|
|
|
ogs_error("No SupportedTAItem");
|
|
|
|
group = NGAP_Cause_PR_protocol;
|
|
|
|
cause = NGAP_CauseProtocol_semantic_error;
|
2023-01-23 01:37:22 +00:00
|
|
|
r = ngap_send_ng_setup_failure(gnb, group, cause);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2020-06-23 04:35:41 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
ogs_asn_OCTET_STRING_to_uint24(&SupportedTAItem->tAC,
|
|
|
|
&gnb->supported_ta_list[i].tac);
|
|
|
|
|
|
|
|
ogs_debug(" TAC[%d]", gnb->supported_ta_list[i].tac.v);
|
|
|
|
|
|
|
|
for (j = 0, gnb->supported_ta_list[i].num_of_bplmn_list = 0;
|
|
|
|
j < SupportedTAItem->broadcastPLMNList.list.count &&
|
|
|
|
gnb->supported_ta_list[i].num_of_bplmn_list <
|
|
|
|
OGS_MAX_NUM_OF_BPLMN;
|
|
|
|
j++) {
|
2020-05-25 16:15:22 +00:00
|
|
|
|
|
|
|
NGAP_BroadcastPLMNItem_t *BroadcastPLMNItem = NULL;
|
|
|
|
NGAP_PLMNIdentity_t *pLMNIdentity = NULL;
|
|
|
|
|
|
|
|
BroadcastPLMNItem = (NGAP_BroadcastPLMNItem_t *)
|
2020-06-23 04:35:41 +00:00
|
|
|
SupportedTAItem->broadcastPLMNList.list.array[j];
|
|
|
|
if (!BroadcastPLMNItem) {
|
|
|
|
ogs_error("No BroadcastPLMNItem");
|
|
|
|
group = NGAP_Cause_PR_protocol;
|
|
|
|
cause = NGAP_CauseProtocol_semantic_error;
|
2023-01-23 01:37:22 +00:00
|
|
|
r = ngap_send_ng_setup_failure(gnb, group, cause);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2020-06-23 04:35:41 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2020-05-25 16:15:22 +00:00
|
|
|
pLMNIdentity = (NGAP_PLMNIdentity_t *)
|
|
|
|
&BroadcastPLMNItem->pLMNIdentity;
|
|
|
|
ogs_assert(pLMNIdentity);
|
|
|
|
|
2020-06-23 04:35:41 +00:00
|
|
|
memcpy(&gnb->supported_ta_list[i].bplmn_list[j].plmn_id,
|
2020-05-25 16:15:22 +00:00
|
|
|
pLMNIdentity->buf, sizeof(ogs_plmn_id_t));
|
2020-06-23 04:35:41 +00:00
|
|
|
ogs_debug(" PLMN_ID[MCC:%d MNC:%d]",
|
|
|
|
ogs_plmn_id_mcc(&gnb->supported_ta_list[i].
|
|
|
|
bplmn_list[j].plmn_id),
|
|
|
|
ogs_plmn_id_mnc(&gnb->supported_ta_list[i].
|
|
|
|
bplmn_list[j].plmn_id));
|
|
|
|
|
|
|
|
for (k = 0, gnb->supported_ta_list[i].
|
|
|
|
bplmn_list[j].num_of_s_nssai = 0;
|
|
|
|
k < BroadcastPLMNItem->tAISliceSupportList.list.count &&
|
|
|
|
gnb->supported_ta_list[i].bplmn_list[j].num_of_s_nssai <
|
2021-03-08 12:25:09 +00:00
|
|
|
OGS_MAX_NUM_OF_SLICE;
|
2020-06-23 04:35:41 +00:00
|
|
|
k++) {
|
|
|
|
NGAP_SliceSupportItem_t *SliceSupportItem = NULL;
|
|
|
|
NGAP_S_NSSAI_t *s_NSSAI = NULL;
|
|
|
|
|
|
|
|
SliceSupportItem = (NGAP_SliceSupportItem_t *)
|
|
|
|
BroadcastPLMNItem->tAISliceSupportList.list.array[k];
|
|
|
|
if (!SliceSupportItem) {
|
|
|
|
ogs_error("No SliceSupportItem");
|
|
|
|
group = NGAP_Cause_PR_protocol;
|
|
|
|
cause = NGAP_CauseProtocol_semantic_error;
|
2023-01-23 01:37:22 +00:00
|
|
|
r = ngap_send_ng_setup_failure(gnb, group, cause);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2020-06-23 04:35:41 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
s_NSSAI = &SliceSupportItem->s_NSSAI;
|
|
|
|
ogs_assert(s_NSSAI);
|
|
|
|
|
|
|
|
ogs_asn_OCTET_STRING_to_uint8(&s_NSSAI->sST,
|
|
|
|
&gnb->supported_ta_list[i].bplmn_list[j].s_nssai[k].sst);
|
|
|
|
if (!s_NSSAI->sD) {
|
|
|
|
gnb->supported_ta_list[i].bplmn_list[j].s_nssai[k].sd.v =
|
|
|
|
OGS_S_NSSAI_NO_SD_VALUE;
|
|
|
|
} else {
|
|
|
|
ogs_asn_OCTET_STRING_to_uint24(s_NSSAI->sD,
|
|
|
|
&gnb->supported_ta_list[i].bplmn_list[j].s_nssai[k].sd);
|
|
|
|
}
|
|
|
|
|
|
|
|
ogs_debug(" S_NSSAI[SST:%d SD:0x%x]",
|
|
|
|
gnb->supported_ta_list[i].bplmn_list[j].s_nssai[k].sst,
|
|
|
|
gnb->supported_ta_list[i].bplmn_list[j].s_nssai[k].sd.v);
|
|
|
|
|
|
|
|
gnb->supported_ta_list[i].bplmn_list[j].num_of_s_nssai++;
|
|
|
|
}
|
|
|
|
|
|
|
|
gnb->supported_ta_list[i].num_of_bplmn_list++;
|
2020-05-25 16:15:22 +00:00
|
|
|
}
|
2020-06-23 04:35:41 +00:00
|
|
|
|
|
|
|
gnb->num_of_supported_ta_list++;
|
2020-05-25 16:15:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (maximum_number_of_gnbs_is_reached()) {
|
|
|
|
ogs_warn("NG-Setup failure:");
|
|
|
|
ogs_warn(" Maximum number of gNBs reached");
|
|
|
|
group = NGAP_Cause_PR_misc;
|
|
|
|
cause = NGAP_CauseMisc_control_processing_overload;
|
|
|
|
|
2023-01-23 01:37:22 +00:00
|
|
|
r = ngap_send_ng_setup_failure(gnb, group, cause);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2020-05-25 16:15:22 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (gnb->num_of_supported_ta_list == 0) {
|
|
|
|
ogs_warn("NG-Setup failure:");
|
|
|
|
ogs_warn(" No supported TA exist in NG-Setup request");
|
|
|
|
group = NGAP_Cause_PR_protocol;
|
|
|
|
cause = NGAP_CauseProtocol_message_not_compatible_with_receiver_state;
|
|
|
|
|
2023-01-23 01:37:22 +00:00
|
|
|
r = ngap_send_ng_setup_failure(gnb, group, cause);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2020-05-25 16:15:22 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!served_tai_is_found(gnb)) {
|
|
|
|
ogs_warn("NG-Setup failure:");
|
|
|
|
ogs_warn(" Cannot find Served TAI. Check 'amf.tai' configuration");
|
|
|
|
group = NGAP_Cause_PR_misc;
|
2021-12-28 08:38:11 +00:00
|
|
|
cause = NGAP_CauseMisc_unknown_PLMN_or_SNPN;
|
2020-05-25 16:15:22 +00:00
|
|
|
|
2023-01-23 01:37:22 +00:00
|
|
|
r = ngap_send_ng_setup_failure(gnb, group, cause);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2020-05-25 16:15:22 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2020-06-23 04:35:41 +00:00
|
|
|
if (!s_nssai_is_found(gnb)) {
|
|
|
|
ogs_warn("NG-Setup failure:");
|
|
|
|
ogs_warn(" Cannot find S_NSSAI. "
|
2021-03-20 00:17:14 +00:00
|
|
|
"Check 'amf.plmn_support.s_nssai' configuration");
|
2021-06-22 08:56:45 +00:00
|
|
|
group = NGAP_Cause_PR_radioNetwork;
|
|
|
|
cause = NGAP_CauseRadioNetwork_slice_not_supported;
|
2020-06-23 04:35:41 +00:00
|
|
|
|
2023-01-23 01:37:22 +00:00
|
|
|
r = ngap_send_ng_setup_failure(gnb, group, cause);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2020-06-23 04:35:41 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
amf_gnb_set_gnb_id(gnb, gnb_id);
|
|
|
|
|
2020-05-25 16:15:22 +00:00
|
|
|
gnb->state.ng_setup_success = true;
|
2023-01-23 01:37:22 +00:00
|
|
|
r = ngap_send_ng_setup_response(gnb);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2020-05-25 16:15:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void ngap_handle_initial_ue_message(amf_gnb_t *gnb, ogs_ngap_message_t *message)
|
|
|
|
{
|
2023-01-23 01:37:22 +00:00
|
|
|
int i, r;
|
2020-05-25 16:15:22 +00:00
|
|
|
char buf[OGS_ADDRSTRLEN];
|
|
|
|
|
2020-06-22 03:07:14 +00:00
|
|
|
ran_ue_t *ran_ue = NULL;
|
|
|
|
|
2020-05-25 16:15:22 +00:00
|
|
|
NGAP_InitiatingMessage_t *initiatingMessage = NULL;
|
|
|
|
NGAP_InitialUEMessage_t *InitialUEMessage = NULL;
|
|
|
|
|
|
|
|
NGAP_InitialUEMessage_IEs_t *ie = NULL;
|
2020-06-04 18:12:05 +00:00
|
|
|
NGAP_RAN_UE_NGAP_ID_t *RAN_UE_NGAP_ID = NULL;
|
2020-05-25 16:15:22 +00:00
|
|
|
NGAP_NAS_PDU_t *NAS_PDU = NULL;
|
2020-06-04 18:12:05 +00:00
|
|
|
NGAP_UserLocationInformation_t *UserLocationInformation = NULL;
|
2021-01-08 03:26:06 +00:00
|
|
|
NGAP_UserLocationInformationNR_t *UserLocationInformationNR = NULL;
|
2020-06-04 18:12:05 +00:00
|
|
|
NGAP_FiveG_S_TMSI_t *FiveG_S_TMSI = NULL;
|
2021-01-08 03:26:06 +00:00
|
|
|
NGAP_UEContextRequest_t *UEContextRequest = NULL;
|
2020-05-25 16:15:22 +00:00
|
|
|
|
|
|
|
ogs_assert(gnb);
|
2020-11-11 18:21:32 +00:00
|
|
|
ogs_assert(gnb->sctp.sock);
|
2020-05-25 16:15:22 +00:00
|
|
|
|
|
|
|
ogs_assert(message);
|
|
|
|
initiatingMessage = message->choice.initiatingMessage;
|
|
|
|
ogs_assert(initiatingMessage);
|
|
|
|
InitialUEMessage = &initiatingMessage->value.choice.InitialUEMessage;
|
|
|
|
ogs_assert(InitialUEMessage);
|
|
|
|
|
2021-02-01 13:52:22 +00:00
|
|
|
ogs_info("InitialUEMessage");
|
2020-05-25 16:15:22 +00:00
|
|
|
|
|
|
|
for (i = 0; i < InitialUEMessage->protocolIEs.list.count; i++) {
|
|
|
|
ie = InitialUEMessage->protocolIEs.list.array[i];
|
|
|
|
switch (ie->id) {
|
2020-06-04 18:12:05 +00:00
|
|
|
case NGAP_ProtocolIE_ID_id_RAN_UE_NGAP_ID:
|
|
|
|
RAN_UE_NGAP_ID = &ie->value.choice.RAN_UE_NGAP_ID;
|
2020-05-25 16:15:22 +00:00
|
|
|
break;
|
|
|
|
case NGAP_ProtocolIE_ID_id_NAS_PDU:
|
|
|
|
NAS_PDU = &ie->value.choice.NAS_PDU;
|
|
|
|
break;
|
2020-06-04 18:12:05 +00:00
|
|
|
case NGAP_ProtocolIE_ID_id_UserLocationInformation:
|
2020-07-31 02:10:20 +00:00
|
|
|
UserLocationInformation =
|
|
|
|
&ie->value.choice.UserLocationInformation;
|
2020-05-25 16:15:22 +00:00
|
|
|
break;
|
2020-06-04 18:12:05 +00:00
|
|
|
case NGAP_ProtocolIE_ID_id_FiveG_S_TMSI:
|
|
|
|
FiveG_S_TMSI = &ie->value.choice.FiveG_S_TMSI;
|
2020-05-25 16:15:22 +00:00
|
|
|
break;
|
2021-01-08 03:26:06 +00:00
|
|
|
case NGAP_ProtocolIE_ID_id_UEContextRequest:
|
|
|
|
UEContextRequest = &ie->value.choice.UEContextRequest;
|
|
|
|
break;
|
2020-05-25 16:15:22 +00:00
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
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
|
|
|
|
2020-06-04 18:12:05 +00:00
|
|
|
if (!RAN_UE_NGAP_ID) {
|
2020-06-17 05:22:28 +00:00
|
|
|
ogs_error("No RAN_UE_NGAP_ID");
|
2023-01-23 01:37:22 +00:00
|
|
|
r = ngap_send_error_indication(gnb, NULL, NULL,
|
|
|
|
NGAP_Cause_PR_protocol, NGAP_CauseProtocol_semantic_error);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2020-06-04 18:12:05 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
ran_ue = ran_ue_find_by_ran_ue_ngap_id(gnb, *RAN_UE_NGAP_ID);
|
|
|
|
if (!ran_ue) {
|
|
|
|
ran_ue = ran_ue_add(gnb, *RAN_UE_NGAP_ID);
|
2022-10-07 05:31:34 +00:00
|
|
|
if (ran_ue == NULL) {
|
2023-01-23 01:37:22 +00:00
|
|
|
r = ngap_send_error_indication(gnb, NULL, NULL,
|
2022-10-07 05:31:34 +00:00
|
|
|
NGAP_Cause_PR_misc,
|
2023-01-23 01:37:22 +00:00
|
|
|
NGAP_CauseMisc_control_processing_overload);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2022-10-07 05:31:34 +00:00
|
|
|
return;
|
|
|
|
}
|
2020-05-25 16:15:22 +00:00
|
|
|
|
2020-06-22 03:07:14 +00:00
|
|
|
/* Find AMF_UE if 5G-S_TMSI included */
|
2020-06-04 18:12:05 +00:00
|
|
|
if (FiveG_S_TMSI) {
|
2020-05-25 16:15:22 +00:00
|
|
|
ogs_nas_5gs_guti_t nas_guti;
|
|
|
|
amf_ue_t *amf_ue = NULL;
|
2020-06-04 18:12:05 +00:00
|
|
|
uint8_t region;
|
|
|
|
uint16_t set;
|
|
|
|
uint8_t pointer;
|
|
|
|
uint32_t m_tmsi;
|
2020-05-25 16:15:22 +00:00
|
|
|
|
|
|
|
memset(&nas_guti, 0, sizeof(ogs_nas_5gs_guti_t));
|
|
|
|
|
2020-06-22 03:07:14 +00:00
|
|
|
/* Use the first configured plmn_id and mme group id */
|
2020-06-04 18:12:05 +00:00
|
|
|
ogs_nas_from_plmn_id(&nas_guti.nas_plmn_id,
|
2020-06-22 03:07:14 +00:00
|
|
|
&amf_self()->served_guami[0].plmn_id);
|
|
|
|
region = amf_self()->served_guami[0].amf_id.region;
|
2020-06-04 18:12:05 +00:00
|
|
|
|
|
|
|
/* Getting from 5G-S_TMSI */
|
|
|
|
ogs_ngap_AMFSetID_to_uint16(&FiveG_S_TMSI->aMFSetID, &set);
|
2020-07-21 19:14:07 +00:00
|
|
|
ogs_ngap_AMFPointer_to_uint8(&FiveG_S_TMSI->aMFPointer, &pointer);
|
2020-06-04 18:12:05 +00:00
|
|
|
|
|
|
|
ogs_amf_id_build(&nas_guti.amf_id, region, set, pointer);
|
2020-05-25 16:15:22 +00:00
|
|
|
|
|
|
|
/* size must be 4 */
|
2020-06-04 18:12:05 +00:00
|
|
|
ogs_asn_OCTET_STRING_to_uint32(&FiveG_S_TMSI->fiveG_TMSI, &m_tmsi);
|
|
|
|
nas_guti.m_tmsi = m_tmsi;
|
2020-05-25 16:15:22 +00:00
|
|
|
|
|
|
|
amf_ue = amf_ue_find_by_guti(&nas_guti);
|
|
|
|
if (!amf_ue) {
|
2021-01-05 04:24:22 +00:00
|
|
|
ogs_info("Unknown UE by 5G-S_TMSI[AMF_ID:0x%x,M_TMSI:0x%x]",
|
2020-06-04 18:12:05 +00:00
|
|
|
ogs_amf_id_hexdump(&nas_guti.amf_id), nas_guti.m_tmsi);
|
2020-05-25 16:15:22 +00:00
|
|
|
} else {
|
2021-01-05 04:24:22 +00:00
|
|
|
ogs_info("[%s] 5G-S_TMSI[AMF_ID:0x%x,M_TMSI:0x%x]",
|
2020-06-04 18:12:05 +00:00
|
|
|
AMF_UE_HAVE_SUCI(amf_ue) ? amf_ue->suci : "Unknown ID",
|
2021-04-13 08:34:25 +00:00
|
|
|
ogs_amf_id_hexdump(&amf_ue->current.guti.amf_id),
|
|
|
|
amf_ue->current.guti.m_tmsi);
|
2020-05-25 16:15:22 +00:00
|
|
|
/* If NAS(amf_ue_t) has already been associated with
|
2020-06-04 18:12:05 +00:00
|
|
|
* older NG(ran_ue_t) context */
|
2020-06-22 03:07:14 +00:00
|
|
|
if (CM_CONNECTED(amf_ue)) {
|
2020-09-04 02:00:26 +00:00
|
|
|
/* Previous NG(ran_ue_t) context the holding timer(30secs)
|
|
|
|
* is started.
|
|
|
|
* Newly associated NG(ran_ue_t) context holding timer
|
|
|
|
* is stopped. */
|
|
|
|
ogs_debug("[%s] Start NG Holding Timer", amf_ue->suci);
|
|
|
|
ogs_debug("[%s] RAN_UE_NGAP_ID[%d] AMF_UE_NGAP_ID[%lld]",
|
|
|
|
amf_ue->suci, amf_ue->ran_ue->ran_ue_ngap_id,
|
|
|
|
(long long)amf_ue->ran_ue->amf_ue_ngap_id);
|
|
|
|
|
|
|
|
/* De-associate NG with NAS/EMM */
|
|
|
|
ran_ue_deassociate(amf_ue->ran_ue);
|
|
|
|
|
2023-01-23 01:37:22 +00:00
|
|
|
r = ngap_send_ran_ue_context_release_command(
|
|
|
|
amf_ue->ran_ue,
|
2020-09-04 02:00:26 +00:00
|
|
|
NGAP_Cause_PR_nas, NGAP_CauseNas_normal_release,
|
2023-01-23 01:37:22 +00:00
|
|
|
NGAP_UE_CTX_REL_NG_CONTEXT_REMOVE, 0);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2020-05-25 16:15:22 +00:00
|
|
|
}
|
2020-06-04 18:12:05 +00:00
|
|
|
amf_ue_associate_ran_ue(amf_ue, ran_ue);
|
2023-01-08 11:02:18 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* TS 24.501
|
|
|
|
* 5.3.7 Handling of the periodic registration update timer
|
|
|
|
*
|
|
|
|
* The mobile reachable timer shall be stopped
|
|
|
|
* when a NAS signalling connection is established for the UE.
|
|
|
|
* The implicit de-registration timer shall be stopped
|
|
|
|
* when a NAS signalling connection is established for the UE.
|
|
|
|
*/
|
|
|
|
CLEAR_AMF_UE_TIMER(amf_ue->mobile_reachable);
|
|
|
|
CLEAR_AMF_UE_TIMER(amf_ue->implicit_deregistration);
|
2020-05-25 16:15:22 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-06-17 05:22:28 +00:00
|
|
|
if (!UserLocationInformation) {
|
|
|
|
ogs_error("No UserLocationInformation");
|
2023-01-23 01:37:22 +00:00
|
|
|
r = ngap_send_error_indication(gnb, &ran_ue->ran_ue_ngap_id, NULL,
|
|
|
|
NGAP_Cause_PR_protocol, NGAP_CauseProtocol_semantic_error);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2020-06-17 05:22:28 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2021-01-08 03:26:06 +00:00
|
|
|
if (UserLocationInformation->present !=
|
2020-06-04 18:12:05 +00:00
|
|
|
NGAP_UserLocationInformation_PR_userLocationInformationNR) {
|
|
|
|
ogs_error("Not implemented UserLocationInformation[%d]",
|
|
|
|
UserLocationInformation->present);
|
2023-01-23 01:37:22 +00:00
|
|
|
r = ngap_send_error_indication(gnb, &ran_ue->ran_ue_ngap_id, NULL,
|
|
|
|
NGAP_Cause_PR_protocol, NGAP_CauseProtocol_unspecified);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2021-01-03 05:50:59 +00:00
|
|
|
return;
|
|
|
|
}
|
2020-05-25 16:15:22 +00:00
|
|
|
|
2021-01-08 03:26:06 +00:00
|
|
|
if (!NAS_PDU) {
|
|
|
|
ogs_error("No NAS_PDU");
|
2023-01-23 01:37:22 +00:00
|
|
|
r = ngap_send_error_indication(gnb, &ran_ue->ran_ue_ngap_id, NULL,
|
|
|
|
NGAP_Cause_PR_protocol, NGAP_CauseProtocol_semantic_error);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2021-01-08 03:26:06 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
UserLocationInformationNR =
|
|
|
|
UserLocationInformation->choice.userLocationInformationNR;
|
|
|
|
ogs_assert(UserLocationInformationNR);
|
|
|
|
ogs_ngap_ASN_to_nr_cgi(
|
|
|
|
&UserLocationInformationNR->nR_CGI, &ran_ue->saved.nr_cgi);
|
|
|
|
ogs_ngap_ASN_to_5gs_tai(
|
2021-03-08 12:25:09 +00:00
|
|
|
&UserLocationInformationNR->tAI, &ran_ue->saved.nr_tai);
|
2021-01-08 03:26:06 +00:00
|
|
|
|
2021-01-05 04:24:22 +00:00
|
|
|
ogs_info(" RAN_UE_NGAP_ID[%d] AMF_UE_NGAP_ID[%lld] "
|
2020-06-04 18:12:05 +00:00
|
|
|
"TAC[%d] CellID[0x%llx]",
|
|
|
|
ran_ue->ran_ue_ngap_id, (long long)ran_ue->amf_ue_ngap_id,
|
2021-03-08 12:25:09 +00:00
|
|
|
ran_ue->saved.nr_tai.tac.v, (long long)ran_ue->saved.nr_cgi.cell_id);
|
2020-06-04 18:12:05 +00:00
|
|
|
|
2021-01-08 03:26:06 +00:00
|
|
|
if (UEContextRequest) {
|
|
|
|
if (*UEContextRequest == NGAP_UEContextRequest_requested) {
|
|
|
|
ran_ue->ue_context_requested = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-01-23 01:37:22 +00:00
|
|
|
ogs_expect(OGS_OK == ngap_send_to_nas(
|
|
|
|
ran_ue, NGAP_ProcedureCode_id_InitialUEMessage, NAS_PDU));
|
2020-05-25 16:15:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void ngap_handle_uplink_nas_transport(
|
|
|
|
amf_gnb_t *gnb, ogs_ngap_message_t *message)
|
|
|
|
{
|
|
|
|
char buf[OGS_ADDRSTRLEN];
|
2023-01-23 01:37:22 +00:00
|
|
|
int i, r;
|
2020-05-25 16:15:22 +00:00
|
|
|
|
2021-01-28 19:23:54 +00:00
|
|
|
amf_ue_t *amf_ue = NULL;
|
2020-06-22 03:07:14 +00:00
|
|
|
ran_ue_t *ran_ue = NULL;
|
|
|
|
uint64_t amf_ue_ngap_id;
|
|
|
|
|
2020-05-25 16:15:22 +00:00
|
|
|
NGAP_InitiatingMessage_t *initiatingMessage = NULL;
|
|
|
|
NGAP_UplinkNASTransport_t *UplinkNASTransport = NULL;
|
|
|
|
|
|
|
|
NGAP_UplinkNASTransport_IEs_t *ie = NULL;
|
2020-07-31 02:10:20 +00:00
|
|
|
NGAP_RAN_UE_NGAP_ID_t *RAN_UE_NGAP_ID = NULL;
|
2020-06-22 03:07:14 +00:00
|
|
|
NGAP_AMF_UE_NGAP_ID_t *AMF_UE_NGAP_ID = NULL;
|
2020-05-25 16:15:22 +00:00
|
|
|
NGAP_NAS_PDU_t *NAS_PDU = NULL;
|
2021-01-20 14:27:57 +00:00
|
|
|
NGAP_UserLocationInformation_t *UserLocationInformation = NULL;
|
|
|
|
NGAP_UserLocationInformationNR_t *UserLocationInformationNR = NULL;
|
2020-05-25 16:15:22 +00:00
|
|
|
|
|
|
|
ogs_assert(gnb);
|
2020-11-11 18:21:32 +00:00
|
|
|
ogs_assert(gnb->sctp.sock);
|
2020-05-25 16:15:22 +00:00
|
|
|
|
|
|
|
ogs_assert(message);
|
|
|
|
initiatingMessage = message->choice.initiatingMessage;
|
|
|
|
ogs_assert(initiatingMessage);
|
|
|
|
UplinkNASTransport = &initiatingMessage->value.choice.UplinkNASTransport;
|
|
|
|
ogs_assert(UplinkNASTransport);
|
|
|
|
|
2021-02-01 13:52:22 +00:00
|
|
|
ogs_debug("UplinkNASTransport");
|
2020-05-25 16:15:22 +00:00
|
|
|
|
|
|
|
for (i = 0; i < UplinkNASTransport->protocolIEs.list.count; i++) {
|
|
|
|
ie = UplinkNASTransport->protocolIEs.list.array[i];
|
|
|
|
switch (ie->id) {
|
2020-07-31 02:10:20 +00:00
|
|
|
case NGAP_ProtocolIE_ID_id_RAN_UE_NGAP_ID:
|
|
|
|
RAN_UE_NGAP_ID = &ie->value.choice.RAN_UE_NGAP_ID;
|
|
|
|
break;
|
2020-06-22 03:07:14 +00:00
|
|
|
case NGAP_ProtocolIE_ID_id_AMF_UE_NGAP_ID:
|
|
|
|
AMF_UE_NGAP_ID = &ie->value.choice.AMF_UE_NGAP_ID;
|
2020-05-25 16:15:22 +00:00
|
|
|
break;
|
|
|
|
case NGAP_ProtocolIE_ID_id_NAS_PDU:
|
|
|
|
NAS_PDU = &ie->value.choice.NAS_PDU;
|
|
|
|
break;
|
2021-01-20 15:03:32 +00:00
|
|
|
case NGAP_ProtocolIE_ID_id_UserLocationInformation:
|
|
|
|
UserLocationInformation = &ie->value.choice.UserLocationInformation;
|
2021-01-20 14:27:57 +00:00
|
|
|
break;
|
2020-05-25 16:15:22 +00:00
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
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-06-17 05:22:28 +00:00
|
|
|
|
2020-06-22 03:07:14 +00:00
|
|
|
if (!AMF_UE_NGAP_ID) {
|
|
|
|
ogs_error("No AMF_UE_NGAP_ID");
|
2023-01-23 01:37:22 +00:00
|
|
|
r = ngap_send_error_indication(gnb, (uint32_t *)RAN_UE_NGAP_ID, NULL,
|
|
|
|
NGAP_Cause_PR_protocol, NGAP_CauseProtocol_semantic_error);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2020-06-17 05:22:28 +00:00
|
|
|
return;
|
|
|
|
}
|
2020-05-25 16:15:22 +00:00
|
|
|
|
2020-06-22 03:07:14 +00:00
|
|
|
if (asn_INTEGER2ulong(AMF_UE_NGAP_ID,
|
|
|
|
(unsigned long *)&amf_ue_ngap_id) != 0) {
|
|
|
|
ogs_error("Invalid AMF_UE_NGAP_ID");
|
2023-01-23 01:37:22 +00:00
|
|
|
r = ngap_send_error_indication(gnb, (uint32_t *)RAN_UE_NGAP_ID, NULL,
|
|
|
|
NGAP_Cause_PR_protocol, NGAP_CauseProtocol_semantic_error);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2020-06-17 05:22:28 +00:00
|
|
|
return;
|
|
|
|
}
|
2020-05-25 16:15:22 +00:00
|
|
|
|
2020-06-22 03:07:14 +00:00
|
|
|
ran_ue = ran_ue_find_by_amf_ue_ngap_id(amf_ue_ngap_id);
|
|
|
|
if (!ran_ue) {
|
|
|
|
ogs_error("No RAN UE Context : AMF_UE_NGAP_ID[%lld]",
|
|
|
|
(long long)amf_ue_ngap_id);
|
2023-01-23 01:37:22 +00:00
|
|
|
r = ngap_send_error_indication(
|
2020-07-31 02:10:20 +00:00
|
|
|
gnb, (uint32_t *)RAN_UE_NGAP_ID, &amf_ue_ngap_id,
|
2020-06-22 03:07:14 +00:00
|
|
|
NGAP_Cause_PR_radioNetwork,
|
2023-01-23 01:37:22 +00:00
|
|
|
NGAP_CauseRadioNetwork_unknown_local_UE_NGAP_ID);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2020-06-22 03:07:14 +00:00
|
|
|
return;
|
|
|
|
}
|
2020-05-25 16:15:22 +00:00
|
|
|
|
2021-01-28 19:23:54 +00:00
|
|
|
amf_ue = ran_ue->amf_ue;
|
|
|
|
if (!amf_ue) {
|
|
|
|
ogs_error("Cannot find AMF-UE Context [%lld]",
|
|
|
|
(long long)amf_ue_ngap_id);
|
2023-01-23 01:37:22 +00:00
|
|
|
r = ngap_send_error_indication(
|
2021-01-28 19:23:54 +00:00
|
|
|
gnb, &ran_ue->ran_ue_ngap_id, &ran_ue->amf_ue_ngap_id,
|
|
|
|
NGAP_Cause_PR_radioNetwork,
|
2023-01-23 01:37:22 +00:00
|
|
|
NGAP_CauseRadioNetwork_unknown_local_UE_NGAP_ID);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2021-01-28 19:23:54 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2021-01-20 14:27:57 +00:00
|
|
|
if (!UserLocationInformation) {
|
|
|
|
ogs_error("No UserLocationInformation");
|
2023-01-23 01:37:22 +00:00
|
|
|
r = ngap_send_error_indication(gnb, &ran_ue->ran_ue_ngap_id, NULL,
|
|
|
|
NGAP_Cause_PR_protocol, NGAP_CauseProtocol_semantic_error);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2021-01-20 14:27:57 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (UserLocationInformation->present !=
|
|
|
|
NGAP_UserLocationInformation_PR_userLocationInformationNR) {
|
|
|
|
ogs_error("Not implemented UserLocationInformation[%d]",
|
|
|
|
UserLocationInformation->present);
|
2023-01-23 01:37:22 +00:00
|
|
|
r = ngap_send_error_indication(gnb, &ran_ue->ran_ue_ngap_id, NULL,
|
|
|
|
NGAP_Cause_PR_protocol, NGAP_CauseProtocol_unspecified);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2021-01-20 14:27:57 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2020-06-17 05:22:28 +00:00
|
|
|
if (!NAS_PDU) {
|
|
|
|
ogs_error("No NAS_PDU");
|
2023-01-23 01:37:22 +00:00
|
|
|
r = ngap_send_error_indication(
|
2021-05-16 03:22:10 +00:00
|
|
|
gnb, &ran_ue->ran_ue_ngap_id, &ran_ue->amf_ue_ngap_id,
|
2023-01-23 01:37:22 +00:00
|
|
|
NGAP_Cause_PR_protocol, NGAP_CauseProtocol_semantic_error);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2020-06-17 05:22:28 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2021-01-20 14:27:57 +00:00
|
|
|
UserLocationInformationNR =
|
|
|
|
UserLocationInformation->choice.userLocationInformationNR;
|
|
|
|
ogs_assert(UserLocationInformationNR);
|
|
|
|
ogs_ngap_ASN_to_nr_cgi(
|
|
|
|
&UserLocationInformationNR->nR_CGI, &ran_ue->saved.nr_cgi);
|
|
|
|
ogs_ngap_ASN_to_5gs_tai(
|
2021-03-08 12:25:09 +00:00
|
|
|
&UserLocationInformationNR->tAI, &ran_ue->saved.nr_tai);
|
2021-01-20 14:27:57 +00:00
|
|
|
|
2021-01-20 15:03:32 +00:00
|
|
|
ogs_debug(" RAN_UE_NGAP_ID[%d] AMF_UE_NGAP_ID[%lld] "
|
2021-01-20 14:27:57 +00:00
|
|
|
"TAC[%d] CellID[0x%llx]",
|
|
|
|
ran_ue->ran_ue_ngap_id, (long long)ran_ue->amf_ue_ngap_id,
|
2021-03-08 12:25:09 +00:00
|
|
|
ran_ue->saved.nr_tai.tac.v, (long long)ran_ue->saved.nr_cgi.cell_id);
|
2021-01-20 14:27:57 +00:00
|
|
|
|
2021-01-28 19:23:54 +00:00
|
|
|
/* Copy NR-TAI/NR-CGI from ran_ue */
|
2021-03-08 12:25:09 +00:00
|
|
|
memcpy(&amf_ue->nr_tai, &ran_ue->saved.nr_tai, sizeof(ogs_5gs_tai_t));
|
2021-01-28 19:23:54 +00:00
|
|
|
memcpy(&amf_ue->nr_cgi, &ran_ue->saved.nr_cgi, sizeof(ogs_nr_cgi_t));
|
2021-01-20 15:03:32 +00:00
|
|
|
|
2023-01-23 01:37:22 +00:00
|
|
|
ogs_expect(OGS_OK == ngap_send_to_nas(
|
|
|
|
ran_ue, NGAP_ProcedureCode_id_UplinkNASTransport, NAS_PDU));
|
2020-05-25 16:15:22 +00:00
|
|
|
}
|
|
|
|
|
2020-06-17 05:22:28 +00:00
|
|
|
void ngap_handle_ue_radio_capability_info_indication(
|
2020-05-25 16:15:22 +00:00
|
|
|
amf_gnb_t *gnb, ogs_ngap_message_t *message)
|
|
|
|
{
|
|
|
|
char buf[OGS_ADDRSTRLEN];
|
2023-01-23 01:37:22 +00:00
|
|
|
int i, r;
|
2020-05-25 16:15:22 +00:00
|
|
|
|
2020-06-22 03:07:14 +00:00
|
|
|
ran_ue_t *ran_ue = NULL;
|
|
|
|
uint64_t amf_ue_ngap_id;
|
|
|
|
|
2020-05-25 16:15:22 +00:00
|
|
|
NGAP_InitiatingMessage_t *initiatingMessage = NULL;
|
2020-06-17 05:22:28 +00:00
|
|
|
NGAP_UERadioCapabilityInfoIndication_t
|
|
|
|
*UERadioCapabilityInfoIndication = NULL;
|
2020-05-25 16:15:22 +00:00
|
|
|
|
2020-06-17 05:22:28 +00:00
|
|
|
NGAP_UERadioCapabilityInfoIndicationIEs_t *ie = NULL;
|
2020-07-31 02:10:20 +00:00
|
|
|
NGAP_RAN_UE_NGAP_ID_t *RAN_UE_NGAP_ID = NULL;
|
2020-06-22 03:07:14 +00:00
|
|
|
NGAP_AMF_UE_NGAP_ID_t *AMF_UE_NGAP_ID = NULL;
|
2020-05-25 16:15:22 +00:00
|
|
|
NGAP_UERadioCapability_t *UERadioCapability = NULL;
|
|
|
|
|
|
|
|
ogs_assert(gnb);
|
2020-11-11 18:21:32 +00:00
|
|
|
ogs_assert(gnb->sctp.sock);
|
2020-05-25 16:15:22 +00:00
|
|
|
|
|
|
|
ogs_assert(message);
|
|
|
|
initiatingMessage = message->choice.initiatingMessage;
|
|
|
|
ogs_assert(initiatingMessage);
|
2020-06-17 05:22:28 +00:00
|
|
|
UERadioCapabilityInfoIndication =
|
|
|
|
&initiatingMessage->value.choice.UERadioCapabilityInfoIndication;
|
|
|
|
ogs_assert(UERadioCapabilityInfoIndication);
|
2020-05-25 16:15:22 +00:00
|
|
|
|
2021-02-01 13:52:22 +00:00
|
|
|
ogs_debug("UERadioCapabilityInfoIndication");
|
2020-05-25 16:15:22 +00:00
|
|
|
|
2020-06-17 05:22:28 +00:00
|
|
|
for (i = 0;
|
|
|
|
i < UERadioCapabilityInfoIndication->protocolIEs.list.count; i++) {
|
|
|
|
ie = UERadioCapabilityInfoIndication->protocolIEs.list.array[i];
|
2020-05-25 16:15:22 +00:00
|
|
|
switch (ie->id) {
|
2020-07-31 02:10:20 +00:00
|
|
|
case NGAP_ProtocolIE_ID_id_RAN_UE_NGAP_ID:
|
|
|
|
RAN_UE_NGAP_ID = &ie->value.choice.RAN_UE_NGAP_ID;
|
|
|
|
break;
|
2020-06-22 03:07:14 +00:00
|
|
|
case NGAP_ProtocolIE_ID_id_AMF_UE_NGAP_ID:
|
|
|
|
AMF_UE_NGAP_ID = &ie->value.choice.AMF_UE_NGAP_ID;
|
2020-05-25 16:15:22 +00:00
|
|
|
break;
|
|
|
|
case NGAP_ProtocolIE_ID_id_UERadioCapability:
|
|
|
|
UERadioCapability = &ie->value.choice.UERadioCapability;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
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-06-17 05:22:28 +00:00
|
|
|
|
2020-06-22 03:07:14 +00:00
|
|
|
if (!AMF_UE_NGAP_ID) {
|
|
|
|
ogs_error("No AMF_UE_NGAP_ID");
|
2023-01-23 01:37:22 +00:00
|
|
|
r = ngap_send_error_indication(gnb, (uint32_t *)RAN_UE_NGAP_ID, NULL,
|
|
|
|
NGAP_Cause_PR_protocol, NGAP_CauseProtocol_semantic_error);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2020-06-17 05:22:28 +00:00
|
|
|
return;
|
|
|
|
}
|
2020-05-25 16:15:22 +00:00
|
|
|
|
2020-06-22 03:07:14 +00:00
|
|
|
if (asn_INTEGER2ulong(AMF_UE_NGAP_ID,
|
|
|
|
(unsigned long *)&amf_ue_ngap_id) != 0) {
|
|
|
|
ogs_error("Invalid AMF_UE_NGAP_ID");
|
2023-01-23 01:37:22 +00:00
|
|
|
r = ngap_send_error_indication(gnb, (uint32_t *)RAN_UE_NGAP_ID, NULL,
|
|
|
|
NGAP_Cause_PR_protocol, NGAP_CauseProtocol_semantic_error);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2020-06-22 03:07:14 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
ran_ue = ran_ue_find_by_amf_ue_ngap_id(amf_ue_ngap_id);
|
|
|
|
if (!ran_ue) {
|
|
|
|
ogs_error("No RAN UE Context : AMF_UE_NGAP_ID[%lld]",
|
|
|
|
(long long)amf_ue_ngap_id);
|
2023-01-23 01:37:22 +00:00
|
|
|
r = ngap_send_error_indication(
|
2020-07-31 02:10:20 +00:00
|
|
|
gnb, (uint32_t *)RAN_UE_NGAP_ID, &amf_ue_ngap_id,
|
2020-06-17 05:22:28 +00:00
|
|
|
NGAP_Cause_PR_radioNetwork,
|
2023-01-23 01:37:22 +00:00
|
|
|
NGAP_CauseRadioNetwork_unknown_local_UE_NGAP_ID);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2020-06-17 05:22:28 +00:00
|
|
|
return;
|
|
|
|
}
|
2020-05-25 16:15:22 +00:00
|
|
|
|
2020-06-17 05:22:28 +00:00
|
|
|
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-06-17 05:22:28 +00:00
|
|
|
if (!UERadioCapability) {
|
|
|
|
ogs_error("No UERadioCapability");
|
2023-01-23 01:37:22 +00:00
|
|
|
r = ngap_send_error_indication(
|
2020-06-22 03:07:14 +00:00
|
|
|
gnb, &ran_ue->ran_ue_ngap_id, &ran_ue->amf_ue_ngap_id,
|
2023-01-23 01:37:22 +00:00
|
|
|
NGAP_Cause_PR_protocol, NGAP_CauseProtocol_semantic_error);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2020-06-17 05:22:28 +00:00
|
|
|
return;
|
2020-05-25 16:15:22 +00:00
|
|
|
}
|
2020-06-17 05:22:28 +00:00
|
|
|
|
|
|
|
if (ran_ue->amf_ue)
|
|
|
|
OGS_ASN_STORE_DATA(&ran_ue->amf_ue->ueRadioCapability,
|
|
|
|
UERadioCapability);
|
2020-05-25 16:15:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void ngap_handle_initial_context_setup_response(
|
|
|
|
amf_gnb_t *gnb, ogs_ngap_message_t *message)
|
|
|
|
{
|
|
|
|
char buf[OGS_ADDRSTRLEN];
|
2023-01-23 01:37:22 +00:00
|
|
|
int i, r;
|
2020-05-25 16:15:22 +00:00
|
|
|
|
2020-06-22 03:07:14 +00:00
|
|
|
amf_ue_t *amf_ue = NULL;
|
|
|
|
ran_ue_t *ran_ue = NULL;
|
2021-04-13 08:34:25 +00:00
|
|
|
amf_sess_t *sess = NULL;
|
2020-06-22 03:07:14 +00:00
|
|
|
uint64_t amf_ue_ngap_id;
|
2021-05-29 06:56:12 +00:00
|
|
|
amf_nsmf_pdusession_sm_context_param_t param;
|
2020-06-22 03:07:14 +00:00
|
|
|
|
2020-05-25 16:15:22 +00:00
|
|
|
NGAP_SuccessfulOutcome_t *successfulOutcome = NULL;
|
|
|
|
NGAP_InitialContextSetupResponse_t *InitialContextSetupResponse = NULL;
|
|
|
|
|
|
|
|
NGAP_InitialContextSetupResponseIEs_t *ie = NULL;
|
2020-07-31 02:10:20 +00:00
|
|
|
NGAP_RAN_UE_NGAP_ID_t *RAN_UE_NGAP_ID = NULL;
|
2020-06-22 03:07:14 +00:00
|
|
|
NGAP_AMF_UE_NGAP_ID_t *AMF_UE_NGAP_ID = NULL;
|
|
|
|
NGAP_PDUSessionResourceSetupListCxtRes_t *PDUSessionList = NULL;
|
|
|
|
NGAP_PDUSessionResourceSetupItemCxtRes_t *PDUSessionItem = NULL;
|
|
|
|
OCTET_STRING_t *transfer = NULL;
|
2020-05-25 16:15:22 +00:00
|
|
|
|
|
|
|
ogs_assert(gnb);
|
2020-11-11 18:21:32 +00:00
|
|
|
ogs_assert(gnb->sctp.sock);
|
2020-05-25 16:15:22 +00:00
|
|
|
|
|
|
|
ogs_assert(message);
|
|
|
|
successfulOutcome = message->choice.successfulOutcome;
|
|
|
|
ogs_assert(successfulOutcome);
|
|
|
|
InitialContextSetupResponse =
|
|
|
|
&successfulOutcome->value.choice.InitialContextSetupResponse;
|
|
|
|
ogs_assert(InitialContextSetupResponse);
|
|
|
|
|
2021-02-01 13:52:22 +00:00
|
|
|
ogs_debug("InitialContextSetupResponse");
|
2020-05-25 16:15:22 +00:00
|
|
|
|
|
|
|
for (i = 0; i < InitialContextSetupResponse->protocolIEs.list.count; i++) {
|
|
|
|
ie = InitialContextSetupResponse->protocolIEs.list.array[i];
|
|
|
|
switch (ie->id) {
|
2020-07-31 02:10:20 +00:00
|
|
|
case NGAP_ProtocolIE_ID_id_RAN_UE_NGAP_ID:
|
|
|
|
RAN_UE_NGAP_ID = &ie->value.choice.RAN_UE_NGAP_ID;
|
|
|
|
break;
|
2020-06-22 03:07:14 +00:00
|
|
|
case NGAP_ProtocolIE_ID_id_AMF_UE_NGAP_ID:
|
|
|
|
AMF_UE_NGAP_ID = &ie->value.choice.AMF_UE_NGAP_ID;
|
|
|
|
break;
|
|
|
|
case NGAP_ProtocolIE_ID_id_PDUSessionResourceSetupListCxtRes:
|
|
|
|
PDUSessionList =
|
|
|
|
&ie->value.choice.PDUSessionResourceSetupListCxtRes;
|
2020-05-25 16:15:22 +00:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
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
|
|
|
|
2020-06-22 03:07:14 +00:00
|
|
|
if (!AMF_UE_NGAP_ID) {
|
|
|
|
ogs_error("No AMF_UE_NGAP_ID");
|
2023-01-23 01:37:22 +00:00
|
|
|
r = ngap_send_error_indication(gnb, (uint32_t *)RAN_UE_NGAP_ID, NULL,
|
|
|
|
NGAP_Cause_PR_protocol, NGAP_CauseProtocol_semantic_error);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2020-06-17 05:22:28 +00:00
|
|
|
return;
|
2020-05-25 16:15:22 +00:00
|
|
|
}
|
|
|
|
|
2020-06-22 03:07:14 +00:00
|
|
|
if (asn_INTEGER2ulong(AMF_UE_NGAP_ID,
|
|
|
|
(unsigned long *)&amf_ue_ngap_id) != 0) {
|
|
|
|
ogs_error("Invalid AMF_UE_NGAP_ID");
|
2023-01-23 01:37:22 +00:00
|
|
|
r = ngap_send_error_indication(gnb, (uint32_t *)RAN_UE_NGAP_ID, NULL,
|
|
|
|
NGAP_Cause_PR_protocol, NGAP_CauseProtocol_semantic_error);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2020-06-22 03:07:14 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
ran_ue = ran_ue_find_by_amf_ue_ngap_id(amf_ue_ngap_id);
|
|
|
|
if (!ran_ue) {
|
|
|
|
ogs_error("No RAN UE Context : AMF_UE_NGAP_ID[%lld]",
|
|
|
|
(long long)amf_ue_ngap_id);
|
2023-01-23 01:37:22 +00:00
|
|
|
r = ngap_send_error_indication(
|
2020-07-31 02:10:20 +00:00
|
|
|
gnb, (uint32_t *)RAN_UE_NGAP_ID, &amf_ue_ngap_id,
|
2020-06-17 05:22:28 +00:00
|
|
|
NGAP_Cause_PR_radioNetwork,
|
2023-01-23 01:37:22 +00:00
|
|
|
NGAP_CauseRadioNetwork_unknown_local_UE_NGAP_ID);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2020-06-17 05:22:28 +00:00
|
|
|
return;
|
2020-05-25 16:15:22 +00:00
|
|
|
}
|
|
|
|
|
2020-06-17 05:22:28 +00:00
|
|
|
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);
|
|
|
|
|
|
|
|
amf_ue = ran_ue->amf_ue;
|
2021-01-28 19:23:54 +00:00
|
|
|
if (!amf_ue) {
|
|
|
|
ogs_error("Cannot find AMF-UE Context [%lld]",
|
|
|
|
(long long)amf_ue_ngap_id);
|
2023-01-23 01:37:22 +00:00
|
|
|
r = ngap_send_error_indication(
|
2021-01-28 19:23:54 +00:00
|
|
|
gnb, &ran_ue->ran_ue_ngap_id, &ran_ue->amf_ue_ngap_id,
|
|
|
|
NGAP_Cause_PR_radioNetwork,
|
2023-01-23 01:37:22 +00:00
|
|
|
NGAP_CauseRadioNetwork_unknown_local_UE_NGAP_ID);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2021-01-28 19:23:54 +00:00
|
|
|
return;
|
|
|
|
}
|
2020-06-22 03:07:14 +00:00
|
|
|
|
2021-04-13 08:34:25 +00:00
|
|
|
for (i = 0; PDUSessionList && i < PDUSessionList->list.count; i++) {
|
2020-06-22 03:07:14 +00:00
|
|
|
PDUSessionItem = (NGAP_PDUSessionResourceSetupItemCxtRes_t *)
|
|
|
|
PDUSessionList->list.array[i];
|
|
|
|
|
|
|
|
if (!PDUSessionItem) {
|
|
|
|
ogs_error("No PDUSessionResourceSetupItemCxtRes");
|
2023-01-23 01:37:22 +00:00
|
|
|
r = ngap_send_error_indication2(amf_ue,
|
|
|
|
NGAP_Cause_PR_protocol, NGAP_CauseProtocol_semantic_error);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2020-06-22 03:07:14 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
transfer = &PDUSessionItem->pDUSessionResourceSetupResponseTransfer;
|
|
|
|
if (!transfer) {
|
|
|
|
ogs_error("No PDUSessionResourceSetupResponseTransfer");
|
2023-01-23 01:37:22 +00:00
|
|
|
r = ngap_send_error_indication2(amf_ue,
|
|
|
|
NGAP_Cause_PR_protocol, NGAP_CauseProtocol_semantic_error);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2020-06-22 03:07:14 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (PDUSessionItem->pDUSessionID ==
|
|
|
|
OGS_NAS_PDU_SESSION_IDENTITY_UNASSIGNED) {
|
|
|
|
ogs_error("PDU Session Identity is unassigned");
|
2023-01-23 01:37:22 +00:00
|
|
|
r = ngap_send_error_indication2(amf_ue,
|
|
|
|
NGAP_Cause_PR_protocol, NGAP_CauseProtocol_semantic_error);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2020-06-22 03:07:14 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
sess = amf_sess_find_by_psi(amf_ue, PDUSessionItem->pDUSessionID);
|
|
|
|
if (!sess) {
|
|
|
|
ogs_error("Cannot find PDU Session ID [%d]",
|
|
|
|
(int)PDUSessionItem->pDUSessionID);
|
2023-01-23 01:37:22 +00:00
|
|
|
r = ngap_send_error_indication2(amf_ue,
|
2020-06-22 03:07:14 +00:00
|
|
|
NGAP_Cause_PR_radioNetwork,
|
2023-01-23 01:37:22 +00:00
|
|
|
NGAP_CauseRadioNetwork_unknown_PDU_session_ID);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2020-06-22 03:07:14 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2020-06-27 19:21:29 +00:00
|
|
|
if (!SESSION_CONTEXT_IN_SMF(sess)) {
|
|
|
|
ogs_error("Session Context is not in SMF [%d]",
|
|
|
|
(int)PDUSessionItem->pDUSessionID);
|
2023-01-23 01:37:22 +00:00
|
|
|
r = ngap_send_error_indication2(amf_ue,
|
2020-06-27 19:21:29 +00:00
|
|
|
NGAP_Cause_PR_radioNetwork,
|
2023-01-23 01:37:22 +00:00
|
|
|
NGAP_CauseRadioNetwork_unknown_PDU_session_ID);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2020-06-27 19:21:29 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2022-12-04 05:32:19 +00:00
|
|
|
ogs_debug(" SUPI[%s] PSI[%d] OLD ACTIVATED[0x%x]",
|
|
|
|
amf_ue->supi, sess->psi, ran_ue->psimask.activated);
|
|
|
|
ran_ue->psimask.activated |= ((1 << sess->psi));
|
|
|
|
ogs_debug(" NEW ACTIVATED[0x%x]", ran_ue->psimask.activated);
|
|
|
|
|
2020-06-22 03:07:14 +00:00
|
|
|
memset(¶m, 0, sizeof(param));
|
|
|
|
param.n2smbuf = ogs_pkbuf_alloc(NULL, OGS_MAX_SDU_LEN);
|
2020-09-07 03:53:38 +00:00
|
|
|
ogs_assert(param.n2smbuf);
|
2020-07-02 05:50:23 +00:00
|
|
|
param.n2SmInfoType = OpenAPI_n2_sm_info_type_PDU_RES_SETUP_RSP;
|
2020-06-22 03:07:14 +00:00
|
|
|
ogs_pkbuf_put_data(param.n2smbuf, transfer->buf, transfer->size);
|
|
|
|
|
2023-01-31 10:38:17 +00:00
|
|
|
r = amf_sess_sbi_discover_and_send(
|
2022-08-26 15:12:22 +00:00
|
|
|
OGS_SBI_SERVICE_TYPE_NSMF_PDUSESSION, NULL,
|
2022-07-24 06:10:09 +00:00
|
|
|
amf_nsmf_pdusession_build_update_sm_context,
|
2023-01-31 10:38:17 +00:00
|
|
|
sess, AMF_UPDATE_SM_CONTEXT_ACTIVATED, ¶m);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2020-06-22 03:07:14 +00:00
|
|
|
|
|
|
|
ogs_pkbuf_free(param.n2smbuf);
|
|
|
|
}
|
2021-04-13 08:34:25 +00:00
|
|
|
|
2021-11-14 12:07:56 +00:00
|
|
|
/*
|
|
|
|
* TS24.501
|
|
|
|
* 5.4.4 Generic UE configuration update procedure
|
|
|
|
* 5.4.4.1 General
|
|
|
|
*
|
|
|
|
* This procedure shall be initiated by the network to assign
|
|
|
|
* a new 5G-GUTI to the UE after a successful service request
|
|
|
|
* procedure invoked as a response to a paging request
|
|
|
|
* from the network and before the release of the N1 NAS signalling
|
|
|
|
* connection.
|
|
|
|
*/
|
|
|
|
if (DOWNLINK_SIGNALLING_PENDING(amf_ue) == true) {
|
|
|
|
/*
|
|
|
|
* TS24.501
|
|
|
|
* 5.4.4 Generic UE configuration update procedure
|
|
|
|
* 5.4.4.1 General
|
|
|
|
*
|
|
|
|
* If the service request procedure was triggered
|
|
|
|
* due to 5GSM downlink signalling pending, the procedure
|
|
|
|
* for assigning a new 5G-GUTI can be initiated by the network
|
|
|
|
* after the transport of the 5GSM downlink signalling.
|
|
|
|
*/
|
|
|
|
ogs_list_for_each(&amf_ue->sess_list, sess) {
|
|
|
|
/* There is no Downlink Signalling Pending in this sesssion */
|
|
|
|
if (sess->gsm_message.type == 0) continue;
|
|
|
|
|
|
|
|
switch (sess->gsm_message.type) {
|
|
|
|
case OGS_NAS_5GS_PDU_SESSION_MODIFICATION_COMMAND:
|
2023-01-23 01:37:22 +00:00
|
|
|
r = nas_send_pdu_session_modification_command(sess,
|
|
|
|
sess->gsm_message.n1buf, sess->gsm_message.n2buf);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2021-04-13 08:34:25 +00:00
|
|
|
|
2022-03-22 13:47:45 +00:00
|
|
|
/* n1buf is de-allocated
|
|
|
|
* in gmm_build_dl_nas_transport() */
|
|
|
|
sess->gsm_message.n1buf = NULL;
|
|
|
|
/* n2buf is de-allocated
|
|
|
|
* in ngap_build_pdu_session_resource_modify_request() */
|
|
|
|
sess->gsm_message.n2buf = NULL;
|
|
|
|
|
2021-11-14 12:07:56 +00:00
|
|
|
AMF_SESS_CLEAR_5GSM_MESSAGE(sess);
|
|
|
|
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
ogs_fatal("Unknown GSM Message Type[%d]",
|
|
|
|
sess->gsm_message.type);
|
|
|
|
ogs_assert_if_reached();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else if (PAGING_ONGOING(amf_ue) == true) {
|
2021-04-13 08:34:25 +00:00
|
|
|
gmm_configuration_update_command_param_t param;
|
|
|
|
|
2021-07-01 07:23:27 +00:00
|
|
|
/*
|
|
|
|
* TS24.501
|
|
|
|
* 5.3.3 Temporary identities
|
|
|
|
*
|
|
|
|
* The AMF shall assign a new 5G-GUTI for a particular UE:
|
|
|
|
*
|
|
|
|
* a) during a successful initial registration procedure;
|
|
|
|
* b) during a successful registration procedure
|
|
|
|
* for mobility registration update; and
|
|
|
|
* c) after a successful service request procedure invoked
|
|
|
|
* as a response to a paging request from the network and
|
|
|
|
* before the release of the N1 NAS signalling connection
|
|
|
|
* as specified in subclause 5.4.4.1.
|
|
|
|
*
|
|
|
|
* The AMF should assign a new 5G-GUTI for a particular UE
|
|
|
|
* during a successful registration procedure
|
|
|
|
* for periodic registration update.
|
|
|
|
*
|
|
|
|
* The AMF may assign a new 5G-GUTI at any time for a particular UE
|
|
|
|
* by performing the generic UE configuration update procedure.
|
|
|
|
*/
|
2021-04-13 08:34:25 +00:00
|
|
|
amf_ue_new_guti(amf_ue);
|
|
|
|
|
|
|
|
memset(¶m, 0, sizeof(param));
|
|
|
|
param.acknowledgement_requested = 1;
|
|
|
|
param.guti = 1;
|
2023-01-23 01:37:22 +00:00
|
|
|
r = nas_5gs_send_configuration_update_command(amf_ue, ¶m);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2021-04-13 08:34:25 +00:00
|
|
|
|
2021-11-14 12:07:56 +00:00
|
|
|
AMF_UE_CLEAR_PAGING_INFO(amf_ue);
|
|
|
|
}
|
2020-05-25 16:15:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void ngap_handle_initial_context_setup_failure(
|
|
|
|
amf_gnb_t *gnb, ogs_ngap_message_t *message)
|
|
|
|
{
|
|
|
|
char buf[OGS_ADDRSTRLEN];
|
2023-01-23 01:37:22 +00:00
|
|
|
int i, r, old_xact_count = 0, new_xact_count = 0;
|
2020-05-25 16:15:22 +00:00
|
|
|
|
2020-06-22 03:07:14 +00:00
|
|
|
ran_ue_t *ran_ue = NULL;
|
2020-08-07 15:57:17 +00:00
|
|
|
amf_ue_t *amf_ue = NULL;
|
2020-06-22 03:07:14 +00:00
|
|
|
uint64_t amf_ue_ngap_id;
|
|
|
|
|
2020-05-25 16:15:22 +00:00
|
|
|
NGAP_UnsuccessfulOutcome_t *unsuccessfulOutcome = NULL;
|
|
|
|
NGAP_InitialContextSetupFailure_t *InitialContextSetupFailure = NULL;
|
|
|
|
|
|
|
|
NGAP_InitialContextSetupFailureIEs_t *ie = NULL;
|
2020-07-31 02:10:20 +00:00
|
|
|
NGAP_RAN_UE_NGAP_ID_t *RAN_UE_NGAP_ID = NULL;
|
2020-06-22 03:07:14 +00:00
|
|
|
NGAP_AMF_UE_NGAP_ID_t *AMF_UE_NGAP_ID = NULL;
|
2020-05-25 16:15:22 +00:00
|
|
|
NGAP_Cause_t *Cause = NULL;
|
|
|
|
|
|
|
|
ogs_assert(gnb);
|
2020-11-11 18:21:32 +00:00
|
|
|
ogs_assert(gnb->sctp.sock);
|
2020-05-25 16:15:22 +00:00
|
|
|
|
|
|
|
ogs_assert(message);
|
|
|
|
unsuccessfulOutcome = message->choice.unsuccessfulOutcome;
|
|
|
|
ogs_assert(unsuccessfulOutcome);
|
|
|
|
InitialContextSetupFailure =
|
|
|
|
&unsuccessfulOutcome->value.choice.InitialContextSetupFailure;
|
|
|
|
ogs_assert(InitialContextSetupFailure);
|
|
|
|
|
2021-02-01 13:52:22 +00:00
|
|
|
ogs_debug("InitialContextSetupFailure");
|
2020-05-25 16:15:22 +00:00
|
|
|
|
|
|
|
for (i = 0; i < InitialContextSetupFailure->protocolIEs.list.count; i++) {
|
|
|
|
ie = InitialContextSetupFailure->protocolIEs.list.array[i];
|
|
|
|
switch (ie->id) {
|
2020-07-31 02:10:20 +00:00
|
|
|
case NGAP_ProtocolIE_ID_id_RAN_UE_NGAP_ID:
|
|
|
|
RAN_UE_NGAP_ID = &ie->value.choice.RAN_UE_NGAP_ID;
|
|
|
|
break;
|
2020-06-22 03:07:14 +00:00
|
|
|
case NGAP_ProtocolIE_ID_id_AMF_UE_NGAP_ID:
|
|
|
|
AMF_UE_NGAP_ID = &ie->value.choice.AMF_UE_NGAP_ID;
|
2020-05-25 16:15:22 +00:00
|
|
|
break;
|
|
|
|
case NGAP_ProtocolIE_ID_id_Cause:
|
|
|
|
Cause = &ie->value.choice.Cause;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
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
|
|
|
|
2020-06-22 03:07:14 +00:00
|
|
|
if (!AMF_UE_NGAP_ID) {
|
|
|
|
ogs_error("No AMF_UE_NGAP_ID");
|
2023-01-23 01:37:22 +00:00
|
|
|
r = ngap_send_error_indication(gnb, (uint32_t *)RAN_UE_NGAP_ID, NULL,
|
|
|
|
NGAP_Cause_PR_protocol, NGAP_CauseProtocol_semantic_error);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2020-06-17 05:22:28 +00:00
|
|
|
return;
|
|
|
|
}
|
2020-05-25 16:15:22 +00:00
|
|
|
|
2020-06-22 03:07:14 +00:00
|
|
|
if (asn_INTEGER2ulong(AMF_UE_NGAP_ID,
|
|
|
|
(unsigned long *)&amf_ue_ngap_id) != 0) {
|
|
|
|
ogs_error("Invalid AMF_UE_NGAP_ID");
|
2023-01-23 01:37:22 +00:00
|
|
|
r = ngap_send_error_indication(gnb, (uint32_t *)RAN_UE_NGAP_ID, NULL,
|
|
|
|
NGAP_Cause_PR_protocol, NGAP_CauseProtocol_semantic_error);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2020-06-22 03:07:14 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
ran_ue = ran_ue_find_by_amf_ue_ngap_id(amf_ue_ngap_id);
|
|
|
|
if (!ran_ue) {
|
|
|
|
ogs_error("No RAN UE Context : AMF_UE_NGAP_ID[%lld]",
|
|
|
|
(long long)amf_ue_ngap_id);
|
2023-01-23 01:37:22 +00:00
|
|
|
r = ngap_send_error_indication(
|
2020-07-31 02:10:20 +00:00
|
|
|
gnb, (uint32_t *)RAN_UE_NGAP_ID, &amf_ue_ngap_id,
|
2020-06-17 05:22:28 +00:00
|
|
|
NGAP_Cause_PR_radioNetwork,
|
2023-01-23 01:37:22 +00:00
|
|
|
NGAP_CauseRadioNetwork_unknown_local_UE_NGAP_ID);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2020-05-25 16:15:22 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2020-06-17 05:22:28 +00:00
|
|
|
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);
|
|
|
|
|
|
|
|
if (!Cause) {
|
|
|
|
ogs_error("No Cause");
|
2023-01-23 01:37:22 +00:00
|
|
|
r = ngap_send_error_indication(
|
2020-06-22 03:07:14 +00:00
|
|
|
gnb, &ran_ue->ran_ue_ngap_id, &ran_ue->amf_ue_ngap_id,
|
2023-01-23 01:37:22 +00:00
|
|
|
NGAP_Cause_PR_protocol, NGAP_CauseProtocol_semantic_error);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2020-06-17 05:22:28 +00:00
|
|
|
return;
|
|
|
|
}
|
2020-05-25 16:15:22 +00:00
|
|
|
ogs_debug(" Cause[Group:%d Cause:%d]",
|
|
|
|
Cause->present, (int)Cause->choice.radioNetwork);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* 19.2.2.3 in Spec 36.300
|
|
|
|
*
|
2020-06-04 18:12:05 +00:00
|
|
|
* In case of failure, RAN and AMF behaviours are not mandated.
|
2020-05-25 16:15:22 +00:00
|
|
|
*
|
|
|
|
* Both implicit release (local release at each node) and
|
|
|
|
* explicit release (AMF-initiated UE Context Release procedure)
|
2020-06-04 18:12:05 +00:00
|
|
|
* may in principle be adopted. The RAN should ensure
|
|
|
|
* that no hanging resources remain at the RAN.
|
2020-05-25 16:15:22 +00:00
|
|
|
*/
|
2020-08-07 15:57:17 +00:00
|
|
|
amf_ue = ran_ue->amf_ue;
|
|
|
|
if (amf_ue) {
|
2021-11-16 03:59:04 +00:00
|
|
|
/*
|
|
|
|
* if T3550 is running, Registration complete will be sent.
|
|
|
|
* So, we need to clear all the timer at this point.
|
|
|
|
*/
|
|
|
|
CLEAR_AMF_UE_ALL_TIMERS(amf_ue);
|
|
|
|
|
2020-08-07 15:57:17 +00:00
|
|
|
old_xact_count = amf_sess_xact_count(amf_ue);
|
|
|
|
|
2021-02-17 17:19:20 +00:00
|
|
|
amf_ue->deactivation.group = NGAP_Cause_PR_nas;
|
|
|
|
amf_ue->deactivation.cause = NGAP_CauseNas_normal_release;
|
|
|
|
|
2020-10-09 02:54:13 +00:00
|
|
|
amf_sbi_send_deactivate_all_sessions(
|
2020-11-07 22:27:12 +00:00
|
|
|
amf_ue, AMF_UPDATE_SM_CONTEXT_DEACTIVATED,
|
|
|
|
Cause->present, (int)Cause->choice.radioNetwork);
|
2020-08-07 15:57:17 +00:00
|
|
|
|
|
|
|
new_xact_count = amf_sess_xact_count(amf_ue);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (old_xact_count == new_xact_count) {
|
2023-01-23 01:37:22 +00:00
|
|
|
r = ngap_send_ran_ue_context_release_command(ran_ue,
|
2021-05-16 03:22:10 +00:00
|
|
|
NGAP_Cause_PR_nas, NGAP_CauseNas_normal_release,
|
2023-01-23 01:37:22 +00:00
|
|
|
NGAP_UE_CTX_REL_NG_CONTEXT_REMOVE, 0);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2020-08-07 15:57:17 +00:00
|
|
|
}
|
2020-06-17 05:22:28 +00:00
|
|
|
}
|
|
|
|
|
2022-11-23 11:49:37 +00:00
|
|
|
void ngap_handle_ue_context_modification_response(
|
|
|
|
amf_gnb_t *gnb, ogs_ngap_message_t *message)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
char buf[OGS_ADDRSTRLEN];
|
|
|
|
uint64_t amf_ue_ngap_id;
|
|
|
|
|
|
|
|
ran_ue_t *ran_ue = NULL;
|
|
|
|
|
|
|
|
NGAP_SuccessfulOutcome_t *SuccessfulOutcome = NULL;
|
|
|
|
NGAP_UEContextModificationResponse_t *UEContextModificationResponse = NULL;
|
|
|
|
|
|
|
|
NGAP_UEContextModificationResponseIEs_t *ie = NULL;
|
|
|
|
NGAP_RAN_UE_NGAP_ID_t *RAN_UE_NGAP_ID = NULL;
|
|
|
|
NGAP_AMF_UE_NGAP_ID_t *AMF_UE_NGAP_ID = NULL;
|
|
|
|
/* NGAP_RRCState_t *RRCState = NULL; */
|
|
|
|
/* NGAP_UserLocationInformation_t *UserLocationInformation = NULL; */
|
|
|
|
/* NGAP_CriticalityDiagnostics_t *CriticalityDiagnostics = NULL; */
|
|
|
|
|
|
|
|
ogs_assert(gnb);
|
|
|
|
ogs_assert(gnb->sctp.sock);
|
|
|
|
|
|
|
|
ogs_assert(message);
|
|
|
|
SuccessfulOutcome = message->choice.successfulOutcome;
|
|
|
|
ogs_assert(SuccessfulOutcome);
|
|
|
|
UEContextModificationResponse = &SuccessfulOutcome->value.choice.UEContextModificationResponse;
|
|
|
|
ogs_assert(UEContextModificationResponse);
|
|
|
|
|
|
|
|
ogs_warn("UEContextModificationResponse");
|
|
|
|
|
|
|
|
for (i = 0; i < UEContextModificationResponse->protocolIEs.list.count; i++) {
|
|
|
|
ie = UEContextModificationResponse->protocolIEs.list.array[i];
|
|
|
|
switch (ie->id) {
|
|
|
|
case NGAP_ProtocolIE_ID_id_RAN_UE_NGAP_ID:
|
|
|
|
RAN_UE_NGAP_ID = &ie->value.choice.RAN_UE_NGAP_ID;
|
|
|
|
break;
|
|
|
|
case NGAP_ProtocolIE_ID_id_AMF_UE_NGAP_ID:
|
|
|
|
AMF_UE_NGAP_ID = &ie->value.choice.AMF_UE_NGAP_ID;
|
|
|
|
break;
|
|
|
|
/* case NGAP_ProtocolIE_ID_id_RRCState: */
|
|
|
|
/* RRCState = &ie->value.choice.RRCState; */
|
|
|
|
/* break; */
|
|
|
|
/* case NGAP_ProtocolIE_ID_id_UserLocationInformation: */
|
|
|
|
/* UserLocationInformation = &ie->value.choice.UserLocationInformation; */
|
|
|
|
/* case NGAP_ProtocolIE_ID_id_CriticalityDiagnostics: */
|
|
|
|
/* CriticalityDiagnostics = &ie->value.choice.CriticalityDiagnostics; */
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
ogs_debug(" IP[%s] RAN_ID[%d]",
|
|
|
|
OGS_ADDR(gnb->sctp.addr, buf), gnb->gnb_id);
|
|
|
|
|
|
|
|
if (AMF_UE_NGAP_ID) {
|
|
|
|
|
|
|
|
if (asn_INTEGER2ulong(AMF_UE_NGAP_ID,
|
|
|
|
(unsigned long *)&amf_ue_ngap_id) != 0) {
|
|
|
|
ogs_warn("Invalid AMF_UE_NGAP_ID");
|
|
|
|
}
|
|
|
|
|
|
|
|
ran_ue = ran_ue_find_by_amf_ue_ngap_id(amf_ue_ngap_id);
|
|
|
|
if (!ran_ue)
|
|
|
|
ogs_warn("No RAN UE Context : AMF_UE_NGAP_ID[%lld]",
|
|
|
|
(long long)amf_ue_ngap_id);
|
|
|
|
|
|
|
|
} else if (RAN_UE_NGAP_ID) {
|
|
|
|
ran_ue = ran_ue_find_by_ran_ue_ngap_id(gnb, *RAN_UE_NGAP_ID);
|
|
|
|
if (!ran_ue)
|
|
|
|
ogs_warn("No RAN UE Context : RAN_UE_NGAP_ID[%d]",
|
|
|
|
(int)*RAN_UE_NGAP_ID);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void ngap_handle_ue_context_modification_failure(
|
|
|
|
amf_gnb_t *gnb, ogs_ngap_message_t *message)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
char buf[OGS_ADDRSTRLEN];
|
|
|
|
uint64_t amf_ue_ngap_id;
|
|
|
|
|
|
|
|
ran_ue_t *ran_ue = NULL;
|
|
|
|
|
|
|
|
NGAP_UnsuccessfulOutcome_t *UnsuccessfulOutcome = NULL;
|
|
|
|
NGAP_UEContextModificationFailure_t *UEContextModificationFailiure = NULL;
|
|
|
|
|
|
|
|
NGAP_UEContextModificationFailureIEs_t *ie = NULL;
|
|
|
|
NGAP_RAN_UE_NGAP_ID_t *RAN_UE_NGAP_ID = NULL;
|
|
|
|
NGAP_AMF_UE_NGAP_ID_t *AMF_UE_NGAP_ID = NULL;
|
|
|
|
NGAP_Cause_t *Cause = NULL;
|
|
|
|
|
|
|
|
ogs_assert(gnb);
|
|
|
|
ogs_assert(gnb->sctp.sock);
|
|
|
|
|
|
|
|
ogs_assert(message);
|
|
|
|
UnsuccessfulOutcome = message->choice.unsuccessfulOutcome;
|
|
|
|
ogs_assert(UnsuccessfulOutcome);
|
|
|
|
UEContextModificationFailiure = &UnsuccessfulOutcome->value.choice.UEContextModificationFailure;
|
|
|
|
ogs_assert(UEContextModificationFailiure);
|
|
|
|
|
|
|
|
ogs_warn("UEContextModificationFailiure");
|
|
|
|
|
|
|
|
for (i = 0; i < UEContextModificationFailiure->protocolIEs.list.count; i++) {
|
|
|
|
ie = UEContextModificationFailiure->protocolIEs.list.array[i];
|
|
|
|
switch (ie->id) {
|
|
|
|
case NGAP_ProtocolIE_ID_id_RAN_UE_NGAP_ID:
|
|
|
|
RAN_UE_NGAP_ID = &ie->value.choice.RAN_UE_NGAP_ID;
|
|
|
|
break;
|
|
|
|
case NGAP_ProtocolIE_ID_id_AMF_UE_NGAP_ID:
|
|
|
|
AMF_UE_NGAP_ID = &ie->value.choice.AMF_UE_NGAP_ID;
|
|
|
|
break;
|
|
|
|
case NGAP_ProtocolIE_ID_id_Cause:
|
|
|
|
Cause = &ie->value.choice.Cause;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
ogs_warn(" IP[%s] RAN_ID[%d]",
|
|
|
|
OGS_ADDR(gnb->sctp.addr, buf), gnb->gnb_id);
|
|
|
|
|
|
|
|
if (AMF_UE_NGAP_ID) {
|
|
|
|
|
|
|
|
if (asn_INTEGER2ulong(AMF_UE_NGAP_ID,
|
|
|
|
(unsigned long *)&amf_ue_ngap_id) != 0) {
|
|
|
|
ogs_warn("Invalid AMF_UE_NGAP_ID");
|
|
|
|
}
|
|
|
|
|
|
|
|
ran_ue = ran_ue_find_by_amf_ue_ngap_id(amf_ue_ngap_id);
|
|
|
|
if (!ran_ue)
|
|
|
|
ogs_warn("No RAN UE Context : AMF_UE_NGAP_ID[%lld]",
|
|
|
|
(long long)amf_ue_ngap_id);
|
|
|
|
else
|
|
|
|
ogs_warn(" RAN_UE_NGAP_ID[%d] AMF_UE_NGAP_ID[%lld]",
|
|
|
|
ran_ue->ran_ue_ngap_id, (long long)ran_ue->amf_ue_ngap_id);
|
|
|
|
|
|
|
|
} else if (RAN_UE_NGAP_ID) {
|
|
|
|
ran_ue = ran_ue_find_by_ran_ue_ngap_id(gnb, *RAN_UE_NGAP_ID);
|
|
|
|
if (!ran_ue)
|
|
|
|
ogs_warn("No RAN UE Context : RAN_UE_NGAP_ID[%d]",
|
|
|
|
(int)*RAN_UE_NGAP_ID);
|
|
|
|
else
|
|
|
|
ogs_warn(" RAN_UE_NGAP_ID[%d] AMF_UE_NGAP_ID[%lld]",
|
|
|
|
ran_ue->ran_ue_ngap_id, (long long)ran_ue->amf_ue_ngap_id);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (Cause) {
|
|
|
|
ogs_warn(" Cause[Group:%d Cause:%d]",
|
|
|
|
Cause->present, (int)Cause->choice.radioNetwork);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2020-05-25 16:15:22 +00:00
|
|
|
void ngap_handle_ue_context_release_request(
|
|
|
|
amf_gnb_t *gnb, ogs_ngap_message_t *message)
|
|
|
|
{
|
2023-01-23 01:37:22 +00:00
|
|
|
int i, r;
|
2020-06-22 03:07:14 +00:00
|
|
|
char buf[OGS_ADDRSTRLEN];
|
|
|
|
uint64_t amf_ue_ngap_id;
|
|
|
|
|
|
|
|
ran_ue_t *ran_ue = NULL;
|
|
|
|
amf_ue_t *amf_ue = NULL;
|
2020-06-24 04:33:10 +00:00
|
|
|
amf_sess_t *sess = NULL;
|
|
|
|
|
2020-05-25 16:15:22 +00:00
|
|
|
NGAP_InitiatingMessage_t *initiatingMessage = NULL;
|
|
|
|
NGAP_UEContextReleaseRequest_t *UEContextReleaseRequest = NULL;
|
|
|
|
|
|
|
|
NGAP_UEContextReleaseRequest_IEs_t *ie = NULL;
|
2020-07-31 02:10:20 +00:00
|
|
|
NGAP_RAN_UE_NGAP_ID_t *RAN_UE_NGAP_ID = NULL;
|
2020-05-25 16:15:22 +00:00
|
|
|
NGAP_AMF_UE_NGAP_ID_t *AMF_UE_NGAP_ID = NULL;
|
2020-06-22 03:07:14 +00:00
|
|
|
NGAP_PDUSessionResourceListCxtRelReq_t *PDUSessionList = NULL;
|
|
|
|
NGAP_PDUSessionResourceItemCxtRelReq_t *PDUSessionItem = NULL;
|
2020-05-25 16:15:22 +00:00
|
|
|
NGAP_Cause_t *Cause = NULL;
|
|
|
|
|
|
|
|
ogs_assert(gnb);
|
2020-11-11 18:21:32 +00:00
|
|
|
ogs_assert(gnb->sctp.sock);
|
2020-05-25 16:15:22 +00:00
|
|
|
|
|
|
|
ogs_assert(message);
|
|
|
|
initiatingMessage = message->choice.initiatingMessage;
|
|
|
|
ogs_assert(initiatingMessage);
|
|
|
|
UEContextReleaseRequest =
|
|
|
|
&initiatingMessage->value.choice.UEContextReleaseRequest;
|
|
|
|
ogs_assert(UEContextReleaseRequest);
|
|
|
|
|
2021-02-01 13:52:22 +00:00
|
|
|
ogs_debug("UEContextReleaseRequest");
|
2020-05-25 16:15:22 +00:00
|
|
|
|
|
|
|
for (i = 0; i < UEContextReleaseRequest->protocolIEs.list.count; i++) {
|
|
|
|
ie = UEContextReleaseRequest->protocolIEs.list.array[i];
|
|
|
|
switch (ie->id) {
|
2020-07-31 02:10:20 +00:00
|
|
|
case NGAP_ProtocolIE_ID_id_RAN_UE_NGAP_ID:
|
|
|
|
RAN_UE_NGAP_ID = &ie->value.choice.RAN_UE_NGAP_ID;
|
|
|
|
break;
|
2020-05-25 16:15:22 +00:00
|
|
|
case NGAP_ProtocolIE_ID_id_AMF_UE_NGAP_ID:
|
|
|
|
AMF_UE_NGAP_ID = &ie->value.choice.AMF_UE_NGAP_ID;
|
|
|
|
break;
|
2020-06-22 03:07:14 +00:00
|
|
|
case NGAP_ProtocolIE_ID_id_PDUSessionResourceListCxtRelReq:
|
|
|
|
PDUSessionList = &ie->value.choice.PDUSessionResourceListCxtRelReq;
|
2020-05-25 16:15:22 +00:00
|
|
|
break;
|
|
|
|
case NGAP_ProtocolIE_ID_id_Cause:
|
|
|
|
Cause = &ie->value.choice.Cause;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
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
|
|
|
|
2020-06-22 03:07:14 +00:00
|
|
|
if (!AMF_UE_NGAP_ID) {
|
|
|
|
ogs_error("No AMF_UE_NGAP_ID");
|
2023-01-23 01:37:22 +00:00
|
|
|
r = ngap_send_error_indication(gnb, (uint32_t *)RAN_UE_NGAP_ID, NULL,
|
|
|
|
NGAP_Cause_PR_protocol, NGAP_CauseProtocol_semantic_error);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2020-06-22 03:07:14 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (asn_INTEGER2ulong(AMF_UE_NGAP_ID,
|
|
|
|
(unsigned long *)&amf_ue_ngap_id) != 0) {
|
|
|
|
ogs_error("Invalid AMF_UE_NGAP_ID");
|
2023-01-23 01:37:22 +00:00
|
|
|
r = ngap_send_error_indication(gnb, (uint32_t *)RAN_UE_NGAP_ID, NULL,
|
|
|
|
NGAP_Cause_PR_protocol, NGAP_CauseProtocol_semantic_error);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2020-06-22 03:07:14 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
ran_ue = ran_ue_find_by_amf_ue_ngap_id(amf_ue_ngap_id);
|
2020-06-04 18:12:05 +00:00
|
|
|
if (!ran_ue) {
|
2020-06-26 02:44:28 +00:00
|
|
|
ogs_warn("No RAN UE Context : AMF_UE_NGAP_ID[%lld]",
|
2020-06-22 03:07:14 +00:00
|
|
|
(long long)amf_ue_ngap_id);
|
2023-01-23 01:37:22 +00:00
|
|
|
r = ngap_send_error_indication(
|
2020-07-31 02:10:20 +00:00
|
|
|
gnb, (uint32_t *)RAN_UE_NGAP_ID, &amf_ue_ngap_id,
|
2020-05-25 16:15:22 +00:00
|
|
|
NGAP_Cause_PR_radioNetwork,
|
2023-01-23 01:37:22 +00:00
|
|
|
NGAP_CauseRadioNetwork_unknown_local_UE_NGAP_ID);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2020-05-25 16:15:22 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2020-06-22 03:07:14 +00:00
|
|
|
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);
|
|
|
|
|
|
|
|
if (!Cause) {
|
|
|
|
ogs_error("No Cause");
|
2023-01-23 01:37:22 +00:00
|
|
|
r = ngap_send_error_indication(
|
2020-06-22 03:07:14 +00:00
|
|
|
gnb, &ran_ue->ran_ue_ngap_id, &ran_ue->amf_ue_ngap_id,
|
2023-01-23 01:37:22 +00:00
|
|
|
NGAP_Cause_PR_protocol, NGAP_CauseProtocol_semantic_error);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2020-06-22 03:07:14 +00:00
|
|
|
return;
|
|
|
|
}
|
2020-05-25 16:15:22 +00:00
|
|
|
|
|
|
|
ogs_debug(" Cause[Group:%d Cause:%d]",
|
|
|
|
Cause->present, (int)Cause->choice.radioNetwork);
|
|
|
|
|
|
|
|
switch (Cause->present) {
|
|
|
|
case NGAP_Cause_PR_radioNetwork:
|
|
|
|
case NGAP_Cause_PR_transport:
|
|
|
|
case NGAP_Cause_PR_protocol:
|
|
|
|
case NGAP_Cause_PR_misc:
|
|
|
|
break;
|
|
|
|
case NGAP_Cause_PR_nas:
|
|
|
|
ogs_warn("NAS-Cause[%d]", (int)Cause->choice.nas);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
ogs_warn("Invalid cause group[%d]", Cause->present);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2020-06-22 03:07:14 +00:00
|
|
|
amf_ue = ran_ue->amf_ue;
|
|
|
|
if (!amf_ue) {
|
2021-01-28 19:23:54 +00:00
|
|
|
ogs_error("Cannot find AMF-UE Context [%lld]",
|
|
|
|
(long long)amf_ue_ngap_id);
|
2023-01-23 01:37:22 +00:00
|
|
|
r = ngap_send_ran_ue_context_release_command(ran_ue,
|
2021-02-17 17:19:20 +00:00
|
|
|
Cause->present, (int)Cause->choice.radioNetwork,
|
2023-01-23 01:37:22 +00:00
|
|
|
NGAP_UE_CTX_REL_NG_CONTEXT_REMOVE, 0);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2020-06-25 04:37:29 +00:00
|
|
|
} else {
|
2020-08-03 03:22:41 +00:00
|
|
|
int xact_count = amf_sess_xact_count(amf_ue);
|
|
|
|
|
2021-02-17 17:19:20 +00:00
|
|
|
amf_ue->deactivation.group = Cause->present;
|
|
|
|
amf_ue->deactivation.cause = (int)Cause->choice.radioNetwork;
|
|
|
|
|
2020-06-25 04:37:29 +00:00
|
|
|
if (!PDUSessionList) {
|
|
|
|
amf_sbi_send_deactivate_all_sessions(
|
2020-11-07 22:27:12 +00:00
|
|
|
amf_ue, AMF_UPDATE_SM_CONTEXT_DEACTIVATED,
|
|
|
|
Cause->present, (int)Cause->choice.radioNetwork);
|
2020-06-25 04:37:29 +00:00
|
|
|
} else {
|
|
|
|
for (i = 0; i < PDUSessionList->list.count; i++) {
|
|
|
|
PDUSessionItem = (NGAP_PDUSessionResourceItemCxtRelReq_t *)
|
|
|
|
PDUSessionList->list.array[i];
|
|
|
|
|
|
|
|
if (!PDUSessionItem) {
|
|
|
|
ogs_error("No PDUSessionResourceSetupItemSURes");
|
2023-01-23 01:37:22 +00:00
|
|
|
r = ngap_send_error_indication2(
|
2020-06-25 04:37:29 +00:00
|
|
|
amf_ue, NGAP_Cause_PR_protocol,
|
2023-01-23 01:37:22 +00:00
|
|
|
NGAP_CauseProtocol_semantic_error);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2020-06-25 04:37:29 +00:00
|
|
|
return;
|
|
|
|
}
|
2020-06-24 04:33:10 +00:00
|
|
|
|
2020-06-25 04:37:29 +00:00
|
|
|
if (PDUSessionItem->pDUSessionID ==
|
|
|
|
OGS_NAS_PDU_SESSION_IDENTITY_UNASSIGNED) {
|
|
|
|
ogs_error("PDU Session Identity is unassigned");
|
2023-01-23 01:37:22 +00:00
|
|
|
r = ngap_send_error_indication2(
|
2020-06-25 04:37:29 +00:00
|
|
|
amf_ue, NGAP_Cause_PR_protocol,
|
2023-01-23 01:37:22 +00:00
|
|
|
NGAP_CauseProtocol_semantic_error);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2020-06-25 04:37:29 +00:00
|
|
|
return;
|
|
|
|
}
|
2020-06-24 04:33:10 +00:00
|
|
|
|
2020-06-25 04:37:29 +00:00
|
|
|
sess = amf_sess_find_by_psi(amf_ue,
|
|
|
|
PDUSessionItem->pDUSessionID);
|
2020-06-27 19:21:29 +00:00
|
|
|
if (SESSION_CONTEXT_IN_SMF(sess)) {
|
2020-06-25 04:37:29 +00:00
|
|
|
amf_sbi_send_deactivate_session(
|
2020-11-07 22:27:12 +00:00
|
|
|
sess, AMF_UPDATE_SM_CONTEXT_DEACTIVATED,
|
|
|
|
Cause->present, (int)Cause->choice.radioNetwork);
|
2020-06-27 19:21:29 +00:00
|
|
|
}
|
2020-06-24 04:33:10 +00:00
|
|
|
}
|
|
|
|
}
|
2023-01-23 01:37:22 +00:00
|
|
|
|
|
|
|
if (amf_sess_xact_count(amf_ue) == xact_count) {
|
|
|
|
r = ngap_send_amf_ue_context_release_command(amf_ue,
|
2021-02-17 17:19:20 +00:00
|
|
|
Cause->present, (int)Cause->choice.radioNetwork,
|
2023-01-23 01:37:22 +00:00
|
|
|
NGAP_UE_CTX_REL_NG_REMOVE_AND_UNLINK, 0);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
|
|
|
}
|
2020-06-22 03:07:14 +00:00
|
|
|
}
|
2020-05-25 16:15:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void ngap_handle_ue_context_release_complete(
|
|
|
|
amf_gnb_t *gnb, ogs_ngap_message_t *message)
|
|
|
|
{
|
2023-01-23 01:37:22 +00:00
|
|
|
int i, r;
|
2020-06-22 03:07:14 +00:00
|
|
|
char buf[OGS_ADDRSTRLEN];
|
|
|
|
uint64_t amf_ue_ngap_id;
|
|
|
|
|
|
|
|
ran_ue_t *ran_ue = NULL;
|
2020-05-25 16:15:22 +00:00
|
|
|
|
|
|
|
NGAP_SuccessfulOutcome_t *successfulOutcome = NULL;
|
|
|
|
NGAP_UEContextReleaseComplete_t *UEContextReleaseComplete = NULL;
|
|
|
|
|
|
|
|
NGAP_UEContextReleaseComplete_IEs_t *ie = NULL;
|
2020-07-31 02:10:20 +00:00
|
|
|
NGAP_RAN_UE_NGAP_ID_t *RAN_UE_NGAP_ID = NULL;
|
2020-05-25 16:15:22 +00:00
|
|
|
NGAP_AMF_UE_NGAP_ID_t *AMF_UE_NGAP_ID = NULL;
|
|
|
|
|
|
|
|
ogs_assert(gnb);
|
2020-11-11 18:21:32 +00:00
|
|
|
ogs_assert(gnb->sctp.sock);
|
2020-05-25 16:15:22 +00:00
|
|
|
|
|
|
|
ogs_assert(message);
|
|
|
|
successfulOutcome = message->choice.successfulOutcome;
|
|
|
|
ogs_assert(successfulOutcome);
|
|
|
|
UEContextReleaseComplete =
|
|
|
|
&successfulOutcome->value.choice.UEContextReleaseComplete;
|
|
|
|
ogs_assert(UEContextReleaseComplete);
|
|
|
|
|
2021-02-01 13:52:22 +00:00
|
|
|
ogs_debug("UEContextReleaseComplete");
|
2020-05-25 16:15:22 +00:00
|
|
|
|
|
|
|
for (i = 0; i < UEContextReleaseComplete->protocolIEs.list.count; i++) {
|
|
|
|
ie = UEContextReleaseComplete->protocolIEs.list.array[i];
|
|
|
|
switch (ie->id) {
|
2020-07-31 02:10:20 +00:00
|
|
|
case NGAP_ProtocolIE_ID_id_RAN_UE_NGAP_ID:
|
|
|
|
RAN_UE_NGAP_ID = &ie->value.choice.RAN_UE_NGAP_ID;
|
|
|
|
break;
|
2020-05-25 16:15:22 +00:00
|
|
|
case NGAP_ProtocolIE_ID_id_AMF_UE_NGAP_ID:
|
|
|
|
AMF_UE_NGAP_ID = &ie->value.choice.AMF_UE_NGAP_ID;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
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-06-22 03:07:14 +00:00
|
|
|
|
|
|
|
if (!AMF_UE_NGAP_ID) {
|
|
|
|
ogs_error("No AMF_UE_NGAP_ID");
|
2023-01-23 01:37:22 +00:00
|
|
|
r = ngap_send_error_indication(gnb, (uint32_t *)RAN_UE_NGAP_ID, NULL,
|
|
|
|
NGAP_Cause_PR_protocol, NGAP_CauseProtocol_semantic_error);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2020-06-22 03:07:14 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (asn_INTEGER2ulong(AMF_UE_NGAP_ID,
|
|
|
|
(unsigned long *)&amf_ue_ngap_id) != 0) {
|
|
|
|
ogs_error("Invalid AMF_UE_NGAP_ID");
|
2023-01-23 01:37:22 +00:00
|
|
|
r = ngap_send_error_indication(gnb, (uint32_t *)RAN_UE_NGAP_ID, NULL,
|
|
|
|
NGAP_Cause_PR_protocol, NGAP_CauseProtocol_semantic_error);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2020-06-22 03:07:14 +00:00
|
|
|
return;
|
|
|
|
}
|
2020-05-25 16:15:22 +00:00
|
|
|
|
2020-06-22 03:07:14 +00:00
|
|
|
ran_ue = ran_ue_find_by_amf_ue_ngap_id(amf_ue_ngap_id);
|
2020-06-04 18:12:05 +00:00
|
|
|
if (!ran_ue) {
|
2020-06-22 03:07:14 +00:00
|
|
|
ogs_error("No RAN UE Context : AMF_UE_NGAP_ID[%lld]",
|
|
|
|
(long long)amf_ue_ngap_id);
|
2023-01-23 01:37:22 +00:00
|
|
|
r = ngap_send_error_indication(
|
2020-07-31 02:10:20 +00:00
|
|
|
gnb, (uint32_t *)RAN_UE_NGAP_ID, &amf_ue_ngap_id,
|
2020-05-25 16:15:22 +00:00
|
|
|
NGAP_Cause_PR_radioNetwork,
|
2023-01-23 01:37:22 +00:00
|
|
|
NGAP_CauseRadioNetwork_unknown_local_UE_NGAP_ID);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2020-05-25 16:15:22 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2020-09-04 02:00:26 +00:00
|
|
|
ngap_handle_ue_context_release_action(ran_ue);
|
|
|
|
}
|
|
|
|
|
|
|
|
void ngap_handle_ue_context_release_action(ran_ue_t *ran_ue)
|
|
|
|
{
|
2023-01-23 01:37:22 +00:00
|
|
|
int r;
|
2020-09-04 02:00:26 +00:00
|
|
|
amf_ue_t *amf_ue = NULL;
|
|
|
|
|
|
|
|
ogs_assert(ran_ue);
|
2020-05-25 16:15:22 +00:00
|
|
|
|
2021-01-05 04:24:22 +00:00
|
|
|
if (ran_ue_cycle(ran_ue) == NULL) {
|
|
|
|
ogs_error("NG context has already been removed");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2020-06-22 03:07:14 +00:00
|
|
|
amf_ue = ran_ue->amf_ue;
|
2020-05-25 16:15:22 +00:00
|
|
|
|
2020-10-09 02:54:13 +00:00
|
|
|
ogs_info("UE Context Release [Action:%d]", ran_ue->ue_ctx_rel_action);
|
|
|
|
ogs_info(" RAN_UE_NGAP_ID[%d] AMF_UE_NGAP_ID[%lld]",
|
2020-09-04 02:00:26 +00:00
|
|
|
ran_ue->ran_ue_ngap_id, (long long)ran_ue->amf_ue_ngap_id);
|
2021-06-22 07:13:06 +00:00
|
|
|
if (amf_ue) {
|
2020-10-09 02:54:13 +00:00
|
|
|
ogs_info(" SUCI[%s]", amf_ue->suci ? amf_ue->suci : "Unknown");
|
2021-12-04 01:53:49 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* An assert occurs when a NAS message retransmission occurs.
|
|
|
|
*
|
|
|
|
* Because there is no `ran_ue` context.
|
2022-04-29 12:28:16 +00:00
|
|
|
*
|
2021-12-04 01:53:49 +00:00
|
|
|
* Therefore, before removing `ran_ue`, all Timers must be stopped
|
|
|
|
* to prevent retransmission of NAS messages.
|
|
|
|
*/
|
2021-06-22 07:13:06 +00:00
|
|
|
CLEAR_AMF_UE_ALL_TIMERS(amf_ue);
|
2023-01-08 04:53:48 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* TS 24.501
|
|
|
|
* 5.3.7 Handling of the periodic registration update timer and
|
|
|
|
*
|
|
|
|
* Start AMF_TIMER_MOBILE_REACHABLE
|
|
|
|
* mobile reachable timer
|
|
|
|
* The network supervises the periodic registration update procedure
|
|
|
|
* of the UE by means of the mobile reachable timer.
|
|
|
|
* If the UE is not registered for emergency services,
|
|
|
|
* the mobile reachable timer shall be longer than the value of timer
|
|
|
|
* T3512. In this case, by default, the mobile reachable timer is
|
|
|
|
* 4 minutes greater than the value of timer T3512.
|
|
|
|
* The mobile reachable timer shall be reset and started with the
|
|
|
|
* value as indicated above, when the AMF releases the NAS signalling
|
|
|
|
* connection for the UE.
|
|
|
|
*
|
|
|
|
* TODO: If the UE is registered for emergency services, the AMF shall
|
|
|
|
* set the mobile reachable timer with a value equal to timer T3512.
|
|
|
|
*/
|
|
|
|
if (OGS_FSM_CHECK(&amf_ue->sm, gmm_state_registered) &&
|
|
|
|
ran_ue->ue_ctx_rel_action == NGAP_UE_CTX_REL_NG_REMOVE_AND_UNLINK) {
|
|
|
|
|
|
|
|
ogs_timer_start(amf_ue->mobile_reachable.timer,
|
|
|
|
ogs_time_from_sec(amf_self()->time.t3512.value + 240));
|
|
|
|
}
|
2021-06-22 07:13:06 +00:00
|
|
|
}
|
2020-09-04 02:00:26 +00:00
|
|
|
|
2020-06-04 18:12:05 +00:00
|
|
|
switch (ran_ue->ue_ctx_rel_action) {
|
2020-06-22 03:07:14 +00:00
|
|
|
case NGAP_UE_CTX_REL_NG_CONTEXT_REMOVE:
|
2020-09-03 23:59:00 +00:00
|
|
|
ogs_debug(" Action: NG context remove");
|
2020-06-04 18:12:05 +00:00
|
|
|
ran_ue_remove(ran_ue);
|
2020-05-25 16:15:22 +00:00
|
|
|
break;
|
2020-06-22 03:07:14 +00:00
|
|
|
case NGAP_UE_CTX_REL_NG_REMOVE_AND_UNLINK:
|
|
|
|
ogs_debug(" Action: NG normal release");
|
2020-06-04 18:12:05 +00:00
|
|
|
ran_ue_remove(ran_ue);
|
2023-01-23 01:37:22 +00:00
|
|
|
if (!amf_ue) {
|
|
|
|
ogs_error("No UE(amf-ue) Context");
|
|
|
|
return;
|
|
|
|
}
|
2020-05-25 16:15:22 +00:00
|
|
|
amf_ue_deassociate(amf_ue);
|
|
|
|
break;
|
|
|
|
case NGAP_UE_CTX_REL_UE_CONTEXT_REMOVE:
|
2020-09-03 23:59:00 +00:00
|
|
|
ogs_debug(" Action: UE context remove");
|
2020-06-04 18:12:05 +00:00
|
|
|
ran_ue_remove(ran_ue);
|
2023-01-23 01:37:22 +00:00
|
|
|
if (!amf_ue) {
|
|
|
|
ogs_error("No UE(amf-ue) context");
|
|
|
|
return;
|
|
|
|
}
|
2020-05-25 16:15:22 +00:00
|
|
|
amf_ue_remove(amf_ue);
|
|
|
|
break;
|
2021-01-28 19:23:54 +00:00
|
|
|
case NGAP_UE_CTX_REL_NG_HANDOVER_COMPLETE:
|
|
|
|
ogs_debug(" Action: NG handover complete");
|
2020-05-25 16:15:22 +00:00
|
|
|
|
2020-06-04 18:12:05 +00:00
|
|
|
source_ue_deassociate_target_ue(ran_ue);
|
|
|
|
ran_ue_remove(ran_ue);
|
2020-05-25 16:15:22 +00:00
|
|
|
|
2023-01-23 01:37:22 +00:00
|
|
|
if (!amf_ue) {
|
|
|
|
ogs_error("No UE(amf-ue) context");
|
|
|
|
return;
|
|
|
|
}
|
2021-02-01 04:01:15 +00:00
|
|
|
break;
|
|
|
|
case NGAP_UE_CTX_REL_NG_HANDOVER_CANCEL:
|
|
|
|
ogs_warn(" Action: NG handover cancel");
|
|
|
|
|
|
|
|
source_ue_deassociate_target_ue(ran_ue);
|
|
|
|
ran_ue_remove(ran_ue);
|
|
|
|
|
2023-01-23 01:37:22 +00:00
|
|
|
if (!amf_ue) {
|
|
|
|
ogs_error("No UE(amf-ue) context");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (!amf_ue->ran_ue) {
|
|
|
|
ogs_error("No NG context");
|
|
|
|
return;
|
|
|
|
}
|
2021-02-01 04:01:15 +00:00
|
|
|
|
2023-01-23 01:37:22 +00:00
|
|
|
r = ngap_send_handover_cancel_ack(amf_ue->ran_ue);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2021-02-01 04:01:15 +00:00
|
|
|
break;
|
|
|
|
case NGAP_UE_CTX_REL_NG_HANDOVER_FAILURE:
|
|
|
|
ogs_warn(" Action: NG handover failure");
|
|
|
|
|
|
|
|
source_ue_deassociate_target_ue(ran_ue);
|
|
|
|
ran_ue_remove(ran_ue);
|
|
|
|
|
2023-01-23 01:37:22 +00:00
|
|
|
if (!amf_ue) {
|
|
|
|
ogs_error("No UE(amf-ue) context");
|
|
|
|
return;
|
|
|
|
}
|
2020-05-25 16:15:22 +00:00
|
|
|
break;
|
|
|
|
default:
|
2020-06-04 20:16:16 +00:00
|
|
|
ogs_error("Invalid Action[%d]", ran_ue->ue_ctx_rel_action);
|
2020-05-25 16:15:22 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-06-22 03:07:14 +00:00
|
|
|
void ngap_handle_pdu_session_resource_setup_response(
|
|
|
|
amf_gnb_t *gnb, ogs_ngap_message_t *message)
|
|
|
|
{
|
|
|
|
char buf[OGS_ADDRSTRLEN];
|
2023-01-23 01:37:22 +00:00
|
|
|
int i, r;
|
2020-06-22 03:07:14 +00:00
|
|
|
|
|
|
|
amf_ue_t *amf_ue = NULL;
|
|
|
|
ran_ue_t *ran_ue = NULL;
|
|
|
|
uint64_t amf_ue_ngap_id;
|
2021-05-29 06:56:12 +00:00
|
|
|
amf_nsmf_pdusession_sm_context_param_t param;
|
2020-06-22 03:07:14 +00:00
|
|
|
|
|
|
|
NGAP_SuccessfulOutcome_t *successfulOutcome = NULL;
|
|
|
|
NGAP_PDUSessionResourceSetupResponse_t *PDUSessionResourceSetupResponse;
|
|
|
|
|
|
|
|
NGAP_PDUSessionResourceSetupResponseIEs_t *ie = NULL;
|
2020-07-31 02:10:20 +00:00
|
|
|
NGAP_RAN_UE_NGAP_ID_t *RAN_UE_NGAP_ID = NULL;
|
2020-06-22 03:07:14 +00:00
|
|
|
NGAP_AMF_UE_NGAP_ID_t *AMF_UE_NGAP_ID = NULL;
|
|
|
|
NGAP_PDUSessionResourceSetupListSURes_t *PDUSessionList = NULL;
|
|
|
|
NGAP_PDUSessionResourceSetupItemSURes_t *PDUSessionItem = NULL;
|
2021-11-28 11:54:51 +00:00
|
|
|
NGAP_PDUSessionResourceFailedToSetupListSURes_t
|
|
|
|
*PDUSessionFailedList = NULL;
|
|
|
|
NGAP_PDUSessionResourceFailedToSetupItemSURes_t
|
|
|
|
*PDUSessionFailedItem = NULL;
|
2020-06-22 03:07:14 +00:00
|
|
|
OCTET_STRING_t *transfer = NULL;
|
|
|
|
|
|
|
|
ogs_assert(gnb);
|
2020-11-11 18:21:32 +00:00
|
|
|
ogs_assert(gnb->sctp.sock);
|
2020-06-22 03:07:14 +00:00
|
|
|
|
|
|
|
ogs_assert(message);
|
|
|
|
successfulOutcome = message->choice.successfulOutcome;
|
|
|
|
ogs_assert(successfulOutcome);
|
|
|
|
PDUSessionResourceSetupResponse =
|
|
|
|
&successfulOutcome->value.choice.PDUSessionResourceSetupResponse;
|
|
|
|
ogs_assert(PDUSessionResourceSetupResponse);
|
|
|
|
|
2021-02-01 13:52:22 +00:00
|
|
|
ogs_debug("PDUSessionResourceSetupResponse");
|
2020-06-22 03:07:14 +00:00
|
|
|
|
|
|
|
for (i = 0; i < PDUSessionResourceSetupResponse->protocolIEs.list.count;
|
|
|
|
i++) {
|
|
|
|
ie = PDUSessionResourceSetupResponse->protocolIEs.list.array[i];
|
|
|
|
switch (ie->id) {
|
2020-07-31 02:10:20 +00:00
|
|
|
case NGAP_ProtocolIE_ID_id_RAN_UE_NGAP_ID:
|
|
|
|
RAN_UE_NGAP_ID = &ie->value.choice.RAN_UE_NGAP_ID;
|
|
|
|
break;
|
2020-06-22 03:07:14 +00:00
|
|
|
case NGAP_ProtocolIE_ID_id_AMF_UE_NGAP_ID:
|
|
|
|
AMF_UE_NGAP_ID = &ie->value.choice.AMF_UE_NGAP_ID;
|
|
|
|
break;
|
|
|
|
case NGAP_ProtocolIE_ID_id_PDUSessionResourceSetupListSURes:
|
2020-07-31 02:10:20 +00:00
|
|
|
PDUSessionList =
|
|
|
|
&ie->value.choice.PDUSessionResourceSetupListSURes;
|
2020-06-22 03:07:14 +00:00
|
|
|
break;
|
2021-11-28 11:54:51 +00:00
|
|
|
case NGAP_ProtocolIE_ID_id_PDUSessionResourceFailedToSetupListSURes:
|
|
|
|
PDUSessionFailedList =
|
|
|
|
&ie->value.choice.PDUSessionResourceFailedToSetupListSURes;
|
|
|
|
break;
|
2020-06-22 03:07:14 +00:00
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
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-06-22 03:07:14 +00:00
|
|
|
|
|
|
|
if (!AMF_UE_NGAP_ID) {
|
|
|
|
ogs_error("No AMF_UE_NGAP_ID");
|
2023-01-23 01:37:22 +00:00
|
|
|
r = ngap_send_error_indication(gnb, (uint32_t *)RAN_UE_NGAP_ID, NULL,
|
|
|
|
NGAP_Cause_PR_protocol, NGAP_CauseProtocol_semantic_error);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2020-06-22 03:07:14 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (asn_INTEGER2ulong(AMF_UE_NGAP_ID,
|
|
|
|
(unsigned long *)&amf_ue_ngap_id) != 0) {
|
|
|
|
ogs_error("Invalid AMF_UE_NGAP_ID");
|
2023-01-23 01:37:22 +00:00
|
|
|
r = ngap_send_error_indication(gnb, (uint32_t *)RAN_UE_NGAP_ID, NULL,
|
|
|
|
NGAP_Cause_PR_protocol, NGAP_CauseProtocol_semantic_error);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2020-06-22 03:07:14 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
ran_ue = ran_ue_find_by_amf_ue_ngap_id(amf_ue_ngap_id);
|
|
|
|
if (!ran_ue) {
|
|
|
|
ogs_error("No RAN UE Context : AMF_UE_NGAP_ID[%lld]",
|
|
|
|
(long long)amf_ue_ngap_id);
|
2023-01-23 01:37:22 +00:00
|
|
|
r = ngap_send_error_indication(
|
2020-07-31 02:10:20 +00:00
|
|
|
gnb, (uint32_t *)RAN_UE_NGAP_ID, &amf_ue_ngap_id,
|
2020-06-22 03:07:14 +00:00
|
|
|
NGAP_Cause_PR_radioNetwork,
|
2023-01-23 01:37:22 +00:00
|
|
|
NGAP_CauseRadioNetwork_unknown_local_UE_NGAP_ID);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2020-06-22 03:07:14 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
|
|
|
amf_ue = ran_ue->amf_ue;
|
|
|
|
if (!amf_ue) {
|
|
|
|
ogs_error("Cannot find AMF-UE Context [%lld]",
|
|
|
|
(long long)amf_ue_ngap_id);
|
2023-01-23 01:37:22 +00:00
|
|
|
r = ngap_send_error_indication(
|
2020-06-22 03:07:14 +00:00
|
|
|
gnb, &ran_ue->ran_ue_ngap_id, &ran_ue->amf_ue_ngap_id,
|
|
|
|
NGAP_Cause_PR_radioNetwork,
|
2023-01-23 01:37:22 +00:00
|
|
|
NGAP_CauseRadioNetwork_unknown_local_UE_NGAP_ID);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2020-06-22 03:07:14 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2021-11-28 11:54:51 +00:00
|
|
|
if (PDUSessionList) {
|
|
|
|
for (i = 0; i < PDUSessionList->list.count; i++) {
|
|
|
|
amf_sess_t *sess = NULL;
|
|
|
|
PDUSessionItem = (NGAP_PDUSessionResourceSetupItemSURes_t *)
|
|
|
|
PDUSessionList->list.array[i];
|
2020-06-22 03:07:14 +00:00
|
|
|
|
2021-11-28 11:54:51 +00:00
|
|
|
if (!PDUSessionItem) {
|
|
|
|
ogs_error("No PDUSessionResourceSetupItemSURes");
|
2023-01-23 01:37:22 +00:00
|
|
|
r = ngap_send_error_indication2(
|
2021-11-28 11:54:51 +00:00
|
|
|
amf_ue,
|
|
|
|
NGAP_Cause_PR_protocol,
|
2023-01-23 01:37:22 +00:00
|
|
|
NGAP_CauseProtocol_semantic_error);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2021-11-28 11:54:51 +00:00
|
|
|
return;
|
|
|
|
}
|
2020-06-22 03:07:14 +00:00
|
|
|
|
2021-11-28 11:54:51 +00:00
|
|
|
transfer = &PDUSessionItem->pDUSessionResourceSetupResponseTransfer;
|
|
|
|
if (!transfer) {
|
|
|
|
ogs_error("No PDUSessionResourceSetupResponseTransfer");
|
2023-01-23 01:37:22 +00:00
|
|
|
r = ngap_send_error_indication2(
|
2021-11-28 11:54:51 +00:00
|
|
|
amf_ue,
|
|
|
|
NGAP_Cause_PR_protocol,
|
2023-01-23 01:37:22 +00:00
|
|
|
NGAP_CauseProtocol_semantic_error);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2021-11-28 11:54:51 +00:00
|
|
|
return;
|
|
|
|
}
|
2020-06-22 03:07:14 +00:00
|
|
|
|
2021-11-28 11:54:51 +00:00
|
|
|
if (PDUSessionItem->pDUSessionID ==
|
|
|
|
OGS_NAS_PDU_SESSION_IDENTITY_UNASSIGNED) {
|
|
|
|
ogs_error("PDU Session Identity is unassigned");
|
2023-01-23 01:37:22 +00:00
|
|
|
r = ngap_send_error_indication2(
|
2021-11-28 11:54:51 +00:00
|
|
|
amf_ue,
|
|
|
|
NGAP_Cause_PR_protocol,
|
2023-01-23 01:37:22 +00:00
|
|
|
NGAP_CauseProtocol_semantic_error);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2021-11-28 11:54:51 +00:00
|
|
|
return;
|
|
|
|
}
|
2020-06-22 03:07:14 +00:00
|
|
|
|
2021-11-28 11:54:51 +00:00
|
|
|
sess = amf_sess_find_by_psi(amf_ue, PDUSessionItem->pDUSessionID);
|
|
|
|
if (!sess) {
|
|
|
|
ogs_error("Cannot find PDU Session ID [%d]",
|
|
|
|
(int)PDUSessionItem->pDUSessionID);
|
2023-01-23 01:37:22 +00:00
|
|
|
r = ngap_send_error_indication2(amf_ue,
|
2021-11-28 11:54:51 +00:00
|
|
|
NGAP_Cause_PR_radioNetwork,
|
2023-01-23 01:37:22 +00:00
|
|
|
NGAP_CauseRadioNetwork_unknown_PDU_session_ID);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2021-11-28 11:54:51 +00:00
|
|
|
return;
|
|
|
|
}
|
2020-06-22 03:07:14 +00:00
|
|
|
|
2021-11-28 11:54:51 +00:00
|
|
|
if (!SESSION_CONTEXT_IN_SMF(sess)) {
|
|
|
|
ogs_error("Session Context is not in SMF [%d]",
|
|
|
|
(int)PDUSessionItem->pDUSessionID);
|
2023-01-23 01:37:22 +00:00
|
|
|
r = ngap_send_error_indication2(amf_ue,
|
2021-11-28 11:54:51 +00:00
|
|
|
NGAP_Cause_PR_radioNetwork,
|
2023-01-23 01:37:22 +00:00
|
|
|
NGAP_CauseRadioNetwork_unknown_PDU_session_ID);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2021-11-28 11:54:51 +00:00
|
|
|
return;
|
|
|
|
}
|
2020-06-27 19:21:29 +00:00
|
|
|
|
2022-12-04 05:32:19 +00:00
|
|
|
ogs_debug(" SUPI[%s] PSI[%d] OLD ACTIVATED[0x%x]",
|
|
|
|
amf_ue->supi, sess->psi, ran_ue->psimask.activated);
|
|
|
|
ran_ue->psimask.activated |= ((1 << sess->psi));
|
|
|
|
ogs_debug(" NEW ACTIVATED[0x%x]", ran_ue->psimask.activated);
|
|
|
|
|
2021-11-28 11:54:51 +00:00
|
|
|
memset(¶m, 0, sizeof(param));
|
|
|
|
param.n2smbuf = ogs_pkbuf_alloc(NULL, OGS_MAX_SDU_LEN);
|
|
|
|
ogs_assert(param.n2smbuf);
|
|
|
|
param.n2SmInfoType = OpenAPI_n2_sm_info_type_PDU_RES_SETUP_RSP;
|
|
|
|
ogs_pkbuf_put_data(param.n2smbuf, transfer->buf, transfer->size);
|
|
|
|
|
2023-01-31 10:38:17 +00:00
|
|
|
r = amf_sess_sbi_discover_and_send(
|
2022-08-26 15:12:22 +00:00
|
|
|
OGS_SBI_SERVICE_TYPE_NSMF_PDUSESSION, NULL,
|
2022-07-24 06:10:09 +00:00
|
|
|
amf_nsmf_pdusession_build_update_sm_context,
|
2023-01-31 10:38:17 +00:00
|
|
|
sess, AMF_UPDATE_SM_CONTEXT_ACTIVATED, ¶m);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2021-11-28 11:54:51 +00:00
|
|
|
|
|
|
|
ogs_pkbuf_free(param.n2smbuf);
|
2020-06-22 03:07:14 +00:00
|
|
|
}
|
2021-11-28 11:54:51 +00:00
|
|
|
} else if (PDUSessionFailedList) {
|
|
|
|
for (i = 0; i < PDUSessionFailedList->list.count; i++) {
|
|
|
|
amf_sess_t *sess = NULL;
|
|
|
|
PDUSessionFailedItem =
|
|
|
|
(NGAP_PDUSessionResourceFailedToSetupItemSURes_t *)
|
|
|
|
PDUSessionFailedList->list.array[i];
|
|
|
|
|
|
|
|
if (!PDUSessionFailedItem) {
|
|
|
|
ogs_error("No PDUSessionResourceFailedToSetupItemSURes");
|
2023-01-23 01:37:22 +00:00
|
|
|
r = ngap_send_error_indication2(
|
2021-11-28 11:54:51 +00:00
|
|
|
amf_ue,
|
|
|
|
NGAP_Cause_PR_protocol,
|
2023-01-23 01:37:22 +00:00
|
|
|
NGAP_CauseProtocol_semantic_error);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2021-11-28 11:54:51 +00:00
|
|
|
return;
|
|
|
|
}
|
2020-06-22 03:07:14 +00:00
|
|
|
|
2021-11-28 11:54:51 +00:00
|
|
|
transfer =
|
|
|
|
&PDUSessionFailedItem->
|
|
|
|
pDUSessionResourceSetupUnsuccessfulTransfer;
|
|
|
|
if (!transfer) {
|
|
|
|
ogs_error("No PDUSessionResourceSetupUnsuccessfulTransfer");
|
2023-01-23 01:37:22 +00:00
|
|
|
r = ngap_send_error_indication2(
|
2021-11-28 11:54:51 +00:00
|
|
|
amf_ue,
|
|
|
|
NGAP_Cause_PR_protocol,
|
2023-01-23 01:37:22 +00:00
|
|
|
NGAP_CauseProtocol_semantic_error);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2021-11-28 11:54:51 +00:00
|
|
|
return;
|
|
|
|
}
|
2020-07-02 05:50:23 +00:00
|
|
|
|
2021-11-28 11:54:51 +00:00
|
|
|
if (PDUSessionFailedItem->pDUSessionID ==
|
|
|
|
OGS_NAS_PDU_SESSION_IDENTITY_UNASSIGNED) {
|
|
|
|
ogs_error("PDU Session Identity is unassigned");
|
2023-01-23 01:37:22 +00:00
|
|
|
r = ngap_send_error_indication2(
|
2021-11-28 11:54:51 +00:00
|
|
|
amf_ue,
|
|
|
|
NGAP_Cause_PR_protocol,
|
2023-01-23 01:37:22 +00:00
|
|
|
NGAP_CauseProtocol_semantic_error);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2021-11-28 11:54:51 +00:00
|
|
|
return;
|
|
|
|
}
|
2020-07-02 05:50:23 +00:00
|
|
|
|
2021-11-28 11:54:51 +00:00
|
|
|
sess = amf_sess_find_by_psi(
|
|
|
|
amf_ue, PDUSessionFailedItem->pDUSessionID);
|
|
|
|
if (!sess) {
|
|
|
|
ogs_error("Cannot find PDU Session ID [%d]",
|
|
|
|
(int)PDUSessionFailedItem->pDUSessionID);
|
2023-01-23 01:37:22 +00:00
|
|
|
r = ngap_send_error_indication2(
|
2021-11-28 11:54:51 +00:00
|
|
|
amf_ue,
|
|
|
|
NGAP_Cause_PR_radioNetwork,
|
2023-01-23 01:37:22 +00:00
|
|
|
NGAP_CauseRadioNetwork_unknown_PDU_session_ID);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2021-11-28 11:54:51 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!SESSION_CONTEXT_IN_SMF(sess)) {
|
|
|
|
ogs_error("Session Context is not in SMF [%d]",
|
|
|
|
(int)PDUSessionFailedItem->pDUSessionID);
|
2023-01-23 01:37:22 +00:00
|
|
|
r = ngap_send_error_indication2(amf_ue,
|
2021-11-28 11:54:51 +00:00
|
|
|
NGAP_Cause_PR_radioNetwork,
|
2023-01-23 01:37:22 +00:00
|
|
|
NGAP_CauseRadioNetwork_unknown_PDU_session_ID);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2021-11-28 11:54:51 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* TS23.502
|
|
|
|
* 4.2.3 Service Request procedures
|
|
|
|
* 4.2.3.2 UE Triggered Service Request
|
|
|
|
*
|
|
|
|
* 15. ...
|
|
|
|
* If a PDU Session is rejected by the serving NG-RAN
|
|
|
|
* with an indication that the PDU Session was rejected
|
|
|
|
* because User Plane Security Enforcement is not supported
|
|
|
|
* in the serving NG-RAN and the User Plane Enforcement Policy
|
|
|
|
* indicates "Required" as described in clause 5.10.3
|
|
|
|
* of TS 23.501 [2], the SMF shall trigger the release
|
|
|
|
* of this PDU Session.
|
|
|
|
*
|
|
|
|
* In all other cases of PDU Session rejection,
|
|
|
|
* the SMF can decide whether to release the PDU Session
|
|
|
|
* or to deactivate the UP connection of this PDU Session.
|
|
|
|
*
|
|
|
|
*
|
|
|
|
* TS29.502
|
|
|
|
*
|
|
|
|
* 5.2.2.3.2
|
|
|
|
* Activation and Deactivation of the User Plane connection
|
|
|
|
* of a PDU session
|
|
|
|
* 5.2.2.3.2.2
|
|
|
|
* Activation of User Plane connectivity of a PDU session
|
|
|
|
*
|
|
|
|
* 3. ...
|
|
|
|
* N2 SM information received from the 5G-AN
|
|
|
|
* (see PDU Session Resource Setup Unsuccessful Transfer IE
|
|
|
|
* in clause 9.3.4.16 of 3GPP TS 38.413 [9]),
|
|
|
|
* including the Cause of the failure, if resources failed
|
|
|
|
* to be established for the PDU session.
|
|
|
|
*
|
|
|
|
* Upon receipt of this request, the SMF shall:
|
|
|
|
* - consider that the activation of the User Plane connection
|
|
|
|
* has failed and set the upCnxState attribute to DEACTIVATED"
|
|
|
|
* otherwise.
|
|
|
|
*/
|
|
|
|
memset(¶m, 0, sizeof(param));
|
|
|
|
param.n2smbuf = ogs_pkbuf_alloc(NULL, OGS_MAX_SDU_LEN);
|
|
|
|
ogs_assert(param.n2smbuf);
|
|
|
|
param.n2SmInfoType = OpenAPI_n2_sm_info_type_PDU_RES_SETUP_FAIL;
|
|
|
|
ogs_pkbuf_put_data(param.n2smbuf, transfer->buf, transfer->size);
|
|
|
|
|
|
|
|
amf_ue->deactivation.group = NGAP_Cause_PR_nas;
|
|
|
|
amf_ue->deactivation.cause = NGAP_CauseNas_normal_release;
|
|
|
|
|
2023-01-31 10:38:17 +00:00
|
|
|
r = amf_sess_sbi_discover_and_send(
|
2022-08-26 15:12:22 +00:00
|
|
|
OGS_SBI_SERVICE_TYPE_NSMF_PDUSESSION, NULL,
|
2022-07-24 06:10:09 +00:00
|
|
|
amf_nsmf_pdusession_build_update_sm_context,
|
2023-01-31 10:38:17 +00:00
|
|
|
sess, AMF_UPDATE_SM_CONTEXT_SETUP_FAIL, ¶m);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2021-11-28 11:54:51 +00:00
|
|
|
|
|
|
|
ogs_pkbuf_free(param.n2smbuf);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
ogs_error("No PDUSessionResourceList");
|
2023-01-23 01:37:22 +00:00
|
|
|
r = ngap_send_error_indication2(amf_ue,
|
|
|
|
NGAP_Cause_PR_protocol, NGAP_CauseProtocol_semantic_error);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2020-07-02 05:50:23 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-01-01 02:07:08 +00:00
|
|
|
void ngap_handle_pdu_session_resource_modify_response(
|
|
|
|
amf_gnb_t *gnb, ogs_ngap_message_t *message)
|
|
|
|
{
|
|
|
|
char buf[OGS_ADDRSTRLEN];
|
2023-01-23 01:37:22 +00:00
|
|
|
int i, r;
|
2021-01-01 02:07:08 +00:00
|
|
|
|
|
|
|
amf_ue_t *amf_ue = NULL;
|
|
|
|
ran_ue_t *ran_ue = NULL;
|
|
|
|
uint64_t amf_ue_ngap_id;
|
2021-05-29 06:56:12 +00:00
|
|
|
amf_nsmf_pdusession_sm_context_param_t param;
|
2021-01-01 02:07:08 +00:00
|
|
|
|
|
|
|
NGAP_SuccessfulOutcome_t *successfulOutcome = NULL;
|
|
|
|
NGAP_PDUSessionResourceModifyResponse_t *PDUSessionResourceModifyResponse;
|
|
|
|
|
|
|
|
NGAP_PDUSessionResourceModifyResponseIEs_t *ie = NULL;
|
|
|
|
NGAP_RAN_UE_NGAP_ID_t *RAN_UE_NGAP_ID = NULL;
|
|
|
|
NGAP_AMF_UE_NGAP_ID_t *AMF_UE_NGAP_ID = NULL;
|
|
|
|
NGAP_PDUSessionResourceModifyListModRes_t *PDUSessionList = NULL;
|
|
|
|
NGAP_PDUSessionResourceModifyItemModRes_t *PDUSessionItem = NULL;
|
|
|
|
OCTET_STRING_t *transfer = NULL;
|
|
|
|
|
|
|
|
ogs_assert(gnb);
|
|
|
|
ogs_assert(gnb->sctp.sock);
|
|
|
|
|
|
|
|
ogs_assert(message);
|
|
|
|
successfulOutcome = message->choice.successfulOutcome;
|
|
|
|
ogs_assert(successfulOutcome);
|
|
|
|
PDUSessionResourceModifyResponse =
|
|
|
|
&successfulOutcome->value.choice.PDUSessionResourceModifyResponse;
|
|
|
|
ogs_assert(PDUSessionResourceModifyResponse);
|
|
|
|
|
2021-02-01 13:52:22 +00:00
|
|
|
ogs_debug("PDUSessionResourceModifyResponse");
|
2021-01-01 02:07:08 +00:00
|
|
|
|
|
|
|
for (i = 0; i < PDUSessionResourceModifyResponse->protocolIEs.list.count;
|
|
|
|
i++) {
|
|
|
|
ie = PDUSessionResourceModifyResponse->protocolIEs.list.array[i];
|
|
|
|
switch (ie->id) {
|
|
|
|
case NGAP_ProtocolIE_ID_id_RAN_UE_NGAP_ID:
|
|
|
|
RAN_UE_NGAP_ID = &ie->value.choice.RAN_UE_NGAP_ID;
|
|
|
|
break;
|
|
|
|
case NGAP_ProtocolIE_ID_id_AMF_UE_NGAP_ID:
|
|
|
|
AMF_UE_NGAP_ID = &ie->value.choice.AMF_UE_NGAP_ID;
|
|
|
|
break;
|
|
|
|
case NGAP_ProtocolIE_ID_id_PDUSessionResourceModifyListModRes:
|
|
|
|
PDUSessionList =
|
|
|
|
&ie->value.choice.PDUSessionResourceModifyListModRes;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
ogs_debug(" IP[%s] RAN_ID[%d]",
|
|
|
|
OGS_ADDR(gnb->sctp.addr, buf), gnb->gnb_id);
|
|
|
|
|
|
|
|
if (!AMF_UE_NGAP_ID) {
|
|
|
|
ogs_error("No AMF_UE_NGAP_ID");
|
2023-01-23 01:37:22 +00:00
|
|
|
r = ngap_send_error_indication(gnb, (uint32_t *)RAN_UE_NGAP_ID, NULL,
|
|
|
|
NGAP_Cause_PR_protocol, NGAP_CauseProtocol_semantic_error);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2021-01-01 02:07:08 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (asn_INTEGER2ulong(AMF_UE_NGAP_ID,
|
|
|
|
(unsigned long *)&amf_ue_ngap_id) != 0) {
|
|
|
|
ogs_error("Invalid AMF_UE_NGAP_ID");
|
2023-01-23 01:37:22 +00:00
|
|
|
r = ngap_send_error_indication(gnb, (uint32_t *)RAN_UE_NGAP_ID, NULL,
|
|
|
|
NGAP_Cause_PR_protocol, NGAP_CauseProtocol_semantic_error);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2021-01-01 02:07:08 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
ran_ue = ran_ue_find_by_amf_ue_ngap_id(amf_ue_ngap_id);
|
|
|
|
if (!ran_ue) {
|
|
|
|
ogs_error("No RAN UE Context : AMF_UE_NGAP_ID[%lld]",
|
|
|
|
(long long)amf_ue_ngap_id);
|
2023-01-23 01:37:22 +00:00
|
|
|
r = ngap_send_error_indication(
|
2021-01-01 02:07:08 +00:00
|
|
|
gnb, (uint32_t *)RAN_UE_NGAP_ID, &amf_ue_ngap_id,
|
|
|
|
NGAP_Cause_PR_radioNetwork,
|
2023-01-23 01:37:22 +00:00
|
|
|
NGAP_CauseRadioNetwork_unknown_local_UE_NGAP_ID);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2021-01-01 02:07:08 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
|
|
|
amf_ue = ran_ue->amf_ue;
|
|
|
|
if (!amf_ue) {
|
|
|
|
ogs_error("Cannot find AMF-UE Context [%lld]",
|
|
|
|
(long long)amf_ue_ngap_id);
|
2023-01-23 01:37:22 +00:00
|
|
|
r = ngap_send_error_indication(
|
2021-01-01 02:07:08 +00:00
|
|
|
gnb, &ran_ue->ran_ue_ngap_id, &ran_ue->amf_ue_ngap_id,
|
|
|
|
NGAP_Cause_PR_radioNetwork,
|
2023-01-23 01:37:22 +00:00
|
|
|
NGAP_CauseRadioNetwork_unknown_local_UE_NGAP_ID);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2021-01-01 02:07:08 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!PDUSessionList) {
|
|
|
|
ogs_error("No PDUSessionResourceModifyListModRes");
|
2023-01-23 01:37:22 +00:00
|
|
|
r = ngap_send_error_indication2(amf_ue,
|
|
|
|
NGAP_Cause_PR_protocol, NGAP_CauseProtocol_semantic_error);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2021-01-01 02:07:08 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0; i < PDUSessionList->list.count; i++) {
|
|
|
|
amf_sess_t *sess = NULL;
|
|
|
|
PDUSessionItem = (NGAP_PDUSessionResourceModifyItemModRes_t *)
|
|
|
|
PDUSessionList->list.array[i];
|
|
|
|
|
|
|
|
if (!PDUSessionItem) {
|
|
|
|
ogs_error("No PDUSessionResourceModifyItemModRes");
|
2023-01-23 01:37:22 +00:00
|
|
|
r = ngap_send_error_indication2(amf_ue,
|
|
|
|
NGAP_Cause_PR_protocol, NGAP_CauseProtocol_semantic_error);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2021-01-01 02:07:08 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
transfer = &PDUSessionItem->pDUSessionResourceModifyResponseTransfer;
|
|
|
|
if (!transfer) {
|
|
|
|
ogs_error("No PDUSessionResourceModifyResponseTransfer");
|
2023-01-23 01:37:22 +00:00
|
|
|
r = ngap_send_error_indication2(amf_ue,
|
|
|
|
NGAP_Cause_PR_protocol, NGAP_CauseProtocol_semantic_error);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2021-01-01 02:07:08 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (PDUSessionItem->pDUSessionID ==
|
|
|
|
OGS_NAS_PDU_SESSION_IDENTITY_UNASSIGNED) {
|
|
|
|
ogs_error("PDU Session Identity is unassigned");
|
2023-01-23 01:37:22 +00:00
|
|
|
r = ngap_send_error_indication2(amf_ue,
|
|
|
|
NGAP_Cause_PR_protocol, NGAP_CauseProtocol_semantic_error);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2021-01-01 02:07:08 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
sess = amf_sess_find_by_psi(amf_ue, PDUSessionItem->pDUSessionID);
|
|
|
|
if (!sess) {
|
|
|
|
ogs_error("Cannot find PDU Session ID [%d]",
|
|
|
|
(int)PDUSessionItem->pDUSessionID);
|
2023-01-23 01:37:22 +00:00
|
|
|
r = ngap_send_error_indication2(amf_ue,
|
2021-01-01 02:07:08 +00:00
|
|
|
NGAP_Cause_PR_radioNetwork,
|
2023-01-23 01:37:22 +00:00
|
|
|
NGAP_CauseRadioNetwork_unknown_PDU_session_ID);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2021-01-01 02:07:08 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!SESSION_CONTEXT_IN_SMF(sess)) {
|
|
|
|
ogs_error("Session Context is not in SMF [%d]",
|
|
|
|
(int)PDUSessionItem->pDUSessionID);
|
2023-01-23 01:37:22 +00:00
|
|
|
r = ngap_send_error_indication2(amf_ue,
|
2021-01-01 02:07:08 +00:00
|
|
|
NGAP_Cause_PR_radioNetwork,
|
2023-01-23 01:37:22 +00:00
|
|
|
NGAP_CauseRadioNetwork_unknown_PDU_session_ID);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2021-01-01 02:07:08 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
memset(¶m, 0, sizeof(param));
|
|
|
|
param.n2smbuf = ogs_pkbuf_alloc(NULL, OGS_MAX_SDU_LEN);
|
|
|
|
ogs_assert(param.n2smbuf);
|
|
|
|
param.n2SmInfoType = OpenAPI_n2_sm_info_type_PDU_RES_MOD_RSP;
|
|
|
|
ogs_pkbuf_put_data(param.n2smbuf, transfer->buf, transfer->size);
|
|
|
|
|
2023-01-31 10:38:17 +00:00
|
|
|
r = amf_sess_sbi_discover_and_send(
|
2022-08-26 15:12:22 +00:00
|
|
|
OGS_SBI_SERVICE_TYPE_NSMF_PDUSESSION, NULL,
|
2022-07-24 06:10:09 +00:00
|
|
|
amf_nsmf_pdusession_build_update_sm_context,
|
2023-01-31 10:38:17 +00:00
|
|
|
sess, AMF_UPDATE_SM_CONTEXT_MODIFIED, ¶m);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2021-01-01 02:07:08 +00:00
|
|
|
|
|
|
|
ogs_pkbuf_free(param.n2smbuf);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-07-02 05:50:23 +00:00
|
|
|
void ngap_handle_pdu_session_resource_release_response(
|
|
|
|
amf_gnb_t *gnb, ogs_ngap_message_t *message)
|
|
|
|
{
|
|
|
|
char buf[OGS_ADDRSTRLEN];
|
2023-01-23 01:37:22 +00:00
|
|
|
int i, r;
|
2020-07-02 05:50:23 +00:00
|
|
|
|
|
|
|
amf_ue_t *amf_ue = NULL;
|
|
|
|
ran_ue_t *ran_ue = NULL;
|
|
|
|
uint64_t amf_ue_ngap_id;
|
2021-05-29 06:56:12 +00:00
|
|
|
amf_nsmf_pdusession_sm_context_param_t param;
|
2020-07-02 05:50:23 +00:00
|
|
|
|
|
|
|
NGAP_SuccessfulOutcome_t *successfulOutcome = NULL;
|
2020-07-31 02:10:20 +00:00
|
|
|
NGAP_PDUSessionResourceReleaseResponse_t
|
|
|
|
*PDUSessionResourceReleaseResponse;
|
2020-07-02 05:50:23 +00:00
|
|
|
|
|
|
|
NGAP_PDUSessionResourceReleaseResponseIEs_t *ie = NULL;
|
2020-07-31 02:10:20 +00:00
|
|
|
NGAP_RAN_UE_NGAP_ID_t *RAN_UE_NGAP_ID = NULL;
|
2020-07-02 05:50:23 +00:00
|
|
|
NGAP_AMF_UE_NGAP_ID_t *AMF_UE_NGAP_ID = NULL;
|
|
|
|
NGAP_PDUSessionResourceReleasedListRelRes_t *PDUSessionList = NULL;
|
|
|
|
NGAP_PDUSessionResourceReleasedItemRelRes_t *PDUSessionItem = NULL;
|
|
|
|
OCTET_STRING_t *transfer = NULL;
|
|
|
|
|
|
|
|
ogs_assert(gnb);
|
2020-11-11 18:21:32 +00:00
|
|
|
ogs_assert(gnb->sctp.sock);
|
2020-07-02 05:50:23 +00:00
|
|
|
|
|
|
|
ogs_assert(message);
|
|
|
|
successfulOutcome = message->choice.successfulOutcome;
|
|
|
|
ogs_assert(successfulOutcome);
|
|
|
|
PDUSessionResourceReleaseResponse =
|
|
|
|
&successfulOutcome->value.choice.PDUSessionResourceReleaseResponse;
|
|
|
|
ogs_assert(PDUSessionResourceReleaseResponse);
|
|
|
|
|
2021-02-01 13:52:22 +00:00
|
|
|
ogs_debug("PDUSessionResourceReleaseResponse");
|
2020-07-02 05:50:23 +00:00
|
|
|
|
|
|
|
for (i = 0; i < PDUSessionResourceReleaseResponse->protocolIEs.list.count;
|
|
|
|
i++) {
|
|
|
|
ie = PDUSessionResourceReleaseResponse->protocolIEs.list.array[i];
|
|
|
|
switch (ie->id) {
|
2020-07-31 02:10:20 +00:00
|
|
|
case NGAP_ProtocolIE_ID_id_RAN_UE_NGAP_ID:
|
|
|
|
RAN_UE_NGAP_ID = &ie->value.choice.RAN_UE_NGAP_ID;
|
|
|
|
break;
|
2020-07-02 05:50:23 +00:00
|
|
|
case NGAP_ProtocolIE_ID_id_AMF_UE_NGAP_ID:
|
|
|
|
AMF_UE_NGAP_ID = &ie->value.choice.AMF_UE_NGAP_ID;
|
|
|
|
break;
|
|
|
|
case NGAP_ProtocolIE_ID_id_PDUSessionResourceReleasedListRelRes:
|
|
|
|
PDUSessionList =
|
|
|
|
&ie->value.choice.PDUSessionResourceReleasedListRelRes;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
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-07-02 05:50:23 +00:00
|
|
|
|
|
|
|
if (!AMF_UE_NGAP_ID) {
|
|
|
|
ogs_error("No AMF_UE_NGAP_ID");
|
2023-01-23 01:37:22 +00:00
|
|
|
r = ngap_send_error_indication(gnb, (uint32_t *)RAN_UE_NGAP_ID, NULL,
|
|
|
|
NGAP_Cause_PR_protocol, NGAP_CauseProtocol_semantic_error);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2020-07-02 05:50:23 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (asn_INTEGER2ulong(AMF_UE_NGAP_ID,
|
|
|
|
(unsigned long *)&amf_ue_ngap_id) != 0) {
|
|
|
|
ogs_error("Invalid AMF_UE_NGAP_ID");
|
2023-01-23 01:37:22 +00:00
|
|
|
r = ngap_send_error_indication(gnb, (uint32_t *)RAN_UE_NGAP_ID, NULL,
|
|
|
|
NGAP_Cause_PR_protocol, NGAP_CauseProtocol_semantic_error);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2020-07-02 05:50:23 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
ran_ue = ran_ue_find_by_amf_ue_ngap_id(amf_ue_ngap_id);
|
|
|
|
if (!ran_ue) {
|
|
|
|
ogs_error("No RAN UE Context : AMF_UE_NGAP_ID[%lld]",
|
|
|
|
(long long)amf_ue_ngap_id);
|
2023-01-23 01:37:22 +00:00
|
|
|
r = ngap_send_error_indication(
|
2020-07-31 02:10:20 +00:00
|
|
|
gnb, (uint32_t *)RAN_UE_NGAP_ID, &amf_ue_ngap_id,
|
2020-07-02 05:50:23 +00:00
|
|
|
NGAP_Cause_PR_radioNetwork,
|
2023-01-23 01:37:22 +00:00
|
|
|
NGAP_CauseRadioNetwork_unknown_local_UE_NGAP_ID);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2020-07-02 05:50:23 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
|
|
|
amf_ue = ran_ue->amf_ue;
|
|
|
|
if (!amf_ue) {
|
|
|
|
ogs_error("Cannot find AMF-UE Context [%lld]",
|
|
|
|
(long long)amf_ue_ngap_id);
|
2023-01-23 01:37:22 +00:00
|
|
|
r = ngap_send_error_indication(
|
2020-07-02 05:50:23 +00:00
|
|
|
gnb, &ran_ue->ran_ue_ngap_id, &ran_ue->amf_ue_ngap_id,
|
|
|
|
NGAP_Cause_PR_radioNetwork,
|
2023-01-23 01:37:22 +00:00
|
|
|
NGAP_CauseRadioNetwork_unknown_local_UE_NGAP_ID);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2020-07-02 05:50:23 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!PDUSessionList) {
|
|
|
|
ogs_error("No PDUSessionResourceReleasedListRelRes");
|
2023-01-23 01:37:22 +00:00
|
|
|
r = ngap_send_error_indication2(amf_ue,
|
|
|
|
NGAP_Cause_PR_protocol, NGAP_CauseProtocol_semantic_error);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2020-07-02 05:50:23 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0; i < PDUSessionList->list.count; i++) {
|
|
|
|
amf_sess_t *sess = NULL;
|
|
|
|
PDUSessionItem = (NGAP_PDUSessionResourceReleasedItemRelRes_t *)
|
|
|
|
PDUSessionList->list.array[i];
|
|
|
|
|
|
|
|
if (!PDUSessionItem) {
|
|
|
|
ogs_error("No PDUSessionResourceReleasedItemRelRes");
|
2023-01-23 01:37:22 +00:00
|
|
|
r = ngap_send_error_indication2(amf_ue,
|
|
|
|
NGAP_Cause_PR_protocol, NGAP_CauseProtocol_semantic_error);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2020-07-02 05:50:23 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
transfer = &PDUSessionItem->pDUSessionResourceReleaseResponseTransfer;
|
|
|
|
if (!transfer) {
|
|
|
|
ogs_error("No PDUSessionResourceReleaseResponseTransfer");
|
2023-01-23 01:37:22 +00:00
|
|
|
r = ngap_send_error_indication2(amf_ue,
|
|
|
|
NGAP_Cause_PR_protocol, NGAP_CauseProtocol_semantic_error);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2020-07-02 05:50:23 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (PDUSessionItem->pDUSessionID ==
|
|
|
|
OGS_NAS_PDU_SESSION_IDENTITY_UNASSIGNED) {
|
|
|
|
ogs_error("PDU Session Identity is unassigned");
|
2023-01-23 01:37:22 +00:00
|
|
|
r = ngap_send_error_indication2(amf_ue,
|
|
|
|
NGAP_Cause_PR_protocol, NGAP_CauseProtocol_semantic_error);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2020-07-02 05:50:23 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
sess = amf_sess_find_by_psi(amf_ue, PDUSessionItem->pDUSessionID);
|
|
|
|
if (!sess) {
|
|
|
|
ogs_error("Cannot find PDU Session ID [%d]",
|
|
|
|
(int)PDUSessionItem->pDUSessionID);
|
2023-01-23 01:37:22 +00:00
|
|
|
r = ngap_send_error_indication2(amf_ue,
|
2020-07-02 05:50:23 +00:00
|
|
|
NGAP_Cause_PR_radioNetwork,
|
2023-01-23 01:37:22 +00:00
|
|
|
NGAP_CauseRadioNetwork_unknown_PDU_session_ID);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2020-07-02 05:50:23 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!SESSION_CONTEXT_IN_SMF(sess)) {
|
|
|
|
ogs_error("Session Context is not in SMF [%d]",
|
|
|
|
(int)PDUSessionItem->pDUSessionID);
|
2023-01-23 01:37:22 +00:00
|
|
|
r = ngap_send_error_indication2(amf_ue,
|
2020-07-02 05:50:23 +00:00
|
|
|
NGAP_Cause_PR_radioNetwork,
|
2023-01-23 01:37:22 +00:00
|
|
|
NGAP_CauseRadioNetwork_unknown_PDU_session_ID);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2020-07-02 05:50:23 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
memset(¶m, 0, sizeof(param));
|
|
|
|
param.n2smbuf = ogs_pkbuf_alloc(NULL, OGS_MAX_SDU_LEN);
|
2020-09-07 03:53:38 +00:00
|
|
|
ogs_assert(param.n2smbuf);
|
2020-07-02 05:50:23 +00:00
|
|
|
param.n2SmInfoType = OpenAPI_n2_sm_info_type_PDU_RES_REL_RSP;
|
2020-06-22 03:07:14 +00:00
|
|
|
ogs_pkbuf_put_data(param.n2smbuf, transfer->buf, transfer->size);
|
|
|
|
|
2023-01-31 10:38:17 +00:00
|
|
|
r = amf_sess_sbi_discover_and_send(
|
2022-08-26 15:12:22 +00:00
|
|
|
OGS_SBI_SERVICE_TYPE_NSMF_PDUSESSION, NULL,
|
2022-07-24 06:10:09 +00:00
|
|
|
amf_nsmf_pdusession_build_update_sm_context,
|
2023-01-31 10:38:17 +00:00
|
|
|
sess, AMF_UPDATE_SM_CONTEXT_N2_RELEASED, ¶m);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2020-06-22 03:07:14 +00:00
|
|
|
|
|
|
|
ogs_pkbuf_free(param.n2smbuf);
|
|
|
|
}
|
|
|
|
}
|
2020-10-15 02:56:18 +00:00
|
|
|
|
2021-01-28 19:23:54 +00:00
|
|
|
void ngap_handle_uplink_ran_configuration_transfer(
|
|
|
|
amf_gnb_t *gnb, ogs_ngap_message_t *message, ogs_pkbuf_t *pkbuf)
|
|
|
|
{
|
|
|
|
char buf[OGS_ADDRSTRLEN];
|
2023-01-23 01:37:22 +00:00
|
|
|
int i, r;
|
2021-01-28 19:23:54 +00:00
|
|
|
|
|
|
|
NGAP_InitiatingMessage_t *initiatingMessage = NULL;
|
|
|
|
NGAP_UplinkRANConfigurationTransfer_t
|
|
|
|
*UplinkRANConfigurationTransfer = NULL;
|
|
|
|
|
|
|
|
NGAP_UplinkRANConfigurationTransferIEs_t *ie = NULL;
|
|
|
|
NGAP_SONConfigurationTransfer_t *SONConfigurationTransfer = NULL;
|
|
|
|
|
|
|
|
ogs_assert(gnb);
|
|
|
|
ogs_assert(gnb->sctp.sock);
|
|
|
|
|
|
|
|
ogs_assert(message);
|
|
|
|
initiatingMessage = message->choice.initiatingMessage;
|
|
|
|
ogs_assert(initiatingMessage);
|
|
|
|
UplinkRANConfigurationTransfer =
|
|
|
|
&initiatingMessage->value.choice.UplinkRANConfigurationTransfer;
|
|
|
|
ogs_assert(UplinkRANConfigurationTransfer);
|
|
|
|
|
2021-02-01 13:52:22 +00:00
|
|
|
ogs_debug("UplinkRANConfigurationTransfer");
|
2021-01-28 19:23:54 +00:00
|
|
|
for (i = 0;
|
|
|
|
i < UplinkRANConfigurationTransfer->protocolIEs.list.count; i++) {
|
|
|
|
ie = UplinkRANConfigurationTransfer->protocolIEs.list.array[i];
|
|
|
|
switch (ie->id) {
|
|
|
|
case NGAP_ProtocolIE_ID_id_SONConfigurationTransferUL:
|
|
|
|
SONConfigurationTransfer =
|
|
|
|
&ie->value.choice.SONConfigurationTransfer;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
ogs_debug(" IP[%s] ENB_ID[%d]",
|
|
|
|
OGS_ADDR(gnb->sctp.addr, buf), gnb->gnb_id);
|
|
|
|
|
|
|
|
if (SONConfigurationTransfer) {
|
|
|
|
NGAP_TargetRANNodeID_t *targetRANNodeID = NULL;
|
|
|
|
NGAP_GlobalRANNodeID_t *targetGlobalRANNodeID;
|
|
|
|
NGAP_GlobalGNB_ID_t *targetGlobalGNB_ID;
|
|
|
|
NGAP_SourceRANNodeID_t *sourceRANNodeID = NULL;
|
|
|
|
NGAP_GlobalRANNodeID_t *sourceGlobalRANNodeID;
|
|
|
|
NGAP_GlobalGNB_ID_t *sourceGlobalGNB_ID;
|
|
|
|
|
|
|
|
amf_gnb_t *target_gnb = NULL;
|
|
|
|
uint32_t target_gnb_id, source_gnb_id;
|
|
|
|
ogs_5gs_tai_t target_tai, source_tai;
|
|
|
|
|
|
|
|
targetRANNodeID = &SONConfigurationTransfer->targetRANNodeID;
|
|
|
|
targetGlobalRANNodeID = &targetRANNodeID->globalRANNodeID;
|
|
|
|
|
|
|
|
if (targetGlobalRANNodeID->present !=
|
|
|
|
NGAP_GlobalRANNodeID_PR_globalGNB_ID) {
|
|
|
|
ogs_error("Not implemented targetGlobalRANNodeID->present[%d]",
|
|
|
|
targetGlobalRANNodeID->present);
|
2023-01-23 01:37:22 +00:00
|
|
|
r = ngap_send_error_indication(gnb, NULL, NULL,
|
|
|
|
NGAP_Cause_PR_protocol, NGAP_CauseProtocol_semantic_error);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2021-01-28 19:23:54 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
targetGlobalGNB_ID = targetGlobalRANNodeID->choice.globalGNB_ID;
|
|
|
|
if (!targetGlobalGNB_ID) {
|
|
|
|
ogs_error("No targetGlobalGNB_ID");
|
2023-01-23 01:37:22 +00:00
|
|
|
r = ngap_send_error_indication(gnb, NULL, NULL,
|
|
|
|
NGAP_Cause_PR_protocol, NGAP_CauseProtocol_semantic_error);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2021-01-28 19:23:54 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
ogs_ngap_GNB_ID_to_uint32(&targetGlobalGNB_ID->gNB_ID, &target_gnb_id);
|
|
|
|
ogs_ngap_ASN_to_5gs_tai(&targetRANNodeID->selectedTAI, &target_tai);
|
|
|
|
|
|
|
|
sourceRANNodeID = &SONConfigurationTransfer->sourceRANNodeID;
|
|
|
|
sourceGlobalRANNodeID = &sourceRANNodeID->globalRANNodeID;
|
|
|
|
|
|
|
|
if (sourceGlobalRANNodeID->present !=
|
|
|
|
NGAP_GlobalRANNodeID_PR_globalGNB_ID) {
|
|
|
|
ogs_error("Not implemented sourceGlobalRANNodeID->present[%d]",
|
|
|
|
sourceGlobalRANNodeID->present);
|
2023-01-23 01:37:22 +00:00
|
|
|
r = ngap_send_error_indication(gnb, NULL, NULL,
|
|
|
|
NGAP_Cause_PR_protocol, NGAP_CauseProtocol_semantic_error);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2021-01-28 19:23:54 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
sourceGlobalGNB_ID = sourceGlobalRANNodeID->choice.globalGNB_ID;
|
|
|
|
if (!sourceGlobalGNB_ID) {
|
|
|
|
ogs_error("No sourceGlobalGNB_ID");
|
2023-01-23 01:37:22 +00:00
|
|
|
r = ngap_send_error_indication(gnb, NULL, NULL,
|
|
|
|
NGAP_Cause_PR_protocol, NGAP_CauseProtocol_semantic_error);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2021-01-28 19:23:54 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
ogs_ngap_GNB_ID_to_uint32(&sourceGlobalGNB_ID->gNB_ID, &source_gnb_id);
|
|
|
|
ogs_ngap_ASN_to_5gs_tai(&sourceRANNodeID->selectedTAI, &source_tai);
|
|
|
|
|
|
|
|
ogs_debug(" Target : GNB_ID[0x%x], TAC[%d]",
|
|
|
|
target_gnb_id, target_tai.tac.v);
|
|
|
|
ogs_debug(" Source : GNB_ID[0x%x], TAC[%d]",
|
|
|
|
source_gnb_id, source_tai.tac.v);
|
|
|
|
|
|
|
|
target_gnb = amf_gnb_find_by_gnb_id(target_gnb_id);
|
|
|
|
if (!target_gnb) {
|
|
|
|
ogs_error("Uplink RAN configuration transfer : "
|
|
|
|
"cannot find target gNB-id[0x%x]", target_gnb_id);
|
2023-01-23 01:37:22 +00:00
|
|
|
r = ngap_send_error_indication(gnb, NULL, NULL,
|
|
|
|
NGAP_Cause_PR_protocol, NGAP_CauseProtocol_semantic_error);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2021-01-28 19:23:54 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2023-01-23 01:37:22 +00:00
|
|
|
r = ngap_send_downlink_ran_configuration_transfer(
|
|
|
|
target_gnb, SONConfigurationTransfer);
|
|
|
|
ogs_expect(r == OGS_OK);
|
2023-01-25 14:16:59 +00:00
|
|
|
/* ogs_asn_copy_ie() could be failed from received packet.
|
|
|
|
* So we should not use ogs_assert(r != OGS_ERROR).*/
|
2021-01-28 19:23:54 +00:00
|
|
|
}
|
|
|
|
}
|
2020-10-15 02:56:18 +00:00
|
|
|
|
|
|
|
void ngap_handle_path_switch_request(
|
|
|
|
amf_gnb_t *gnb, ogs_ngap_message_t *message)
|
|
|
|
{
|
|
|
|
char buf[OGS_ADDRSTRLEN];
|
2023-01-23 01:37:22 +00:00
|
|
|
int i, r;
|
2020-10-15 02:56:18 +00:00
|
|
|
|
|
|
|
amf_ue_t *amf_ue = NULL;
|
|
|
|
ran_ue_t *ran_ue = NULL;
|
|
|
|
uint64_t amf_ue_ngap_id;
|
|
|
|
|
|
|
|
NGAP_InitiatingMessage_t *initiatingMessage = NULL;
|
|
|
|
NGAP_PathSwitchRequest_t *PathSwitchRequest = NULL;
|
2022-04-29 12:28:16 +00:00
|
|
|
|
2020-10-15 02:56:18 +00:00
|
|
|
NGAP_PathSwitchRequestIEs_t *ie = NULL;
|
|
|
|
NGAP_RAN_UE_NGAP_ID_t *RAN_UE_NGAP_ID = NULL;
|
|
|
|
NGAP_AMF_UE_NGAP_ID_t *AMF_UE_NGAP_ID = NULL;
|
2020-10-15 03:02:18 +00:00
|
|
|
NGAP_UserLocationInformation_t *UserLocationInformation = NULL;
|
2021-01-04 04:29:01 +00:00
|
|
|
NGAP_UserLocationInformationNR_t *UserLocationInformationNR = NULL;
|
2020-10-15 03:02:18 +00:00
|
|
|
NGAP_UESecurityCapabilities_t *UESecurityCapabilities = NULL;
|
|
|
|
NGAP_PDUSessionResourceToBeSwitchedDLList_t
|
|
|
|
*PDUSessionResourceToBeSwitchedDLList = NULL;
|
2020-10-15 02:56:18 +00:00
|
|
|
|
2020-10-15 03:02:18 +00:00
|
|
|
NGAP_NRencryptionAlgorithms_t *nRencryptionAlgorithms = NULL;
|
|
|
|
NGAP_NRintegrityProtectionAlgorithms_t
|
|
|
|
*nRintegrityProtectionAlgorithms = NULL;
|
|
|
|
NGAP_EUTRAencryptionAlgorithms_t *eUTRAencryptionAlgorithms = NULL;
|
|
|
|
NGAP_EUTRAintegrityProtectionAlgorithms_t
|
|
|
|
*eUTRAintegrityProtectionAlgorithms = NULL;
|
2021-01-08 03:26:06 +00:00
|
|
|
uint16_t nr_ea = 0, nr_ia = 0, eutra_ea = 0, eutra_ia = 0;
|
|
|
|
uint8_t nr_ea0 = 0, nr_ia0 = 0, eutra_ea0 = 0, eutra_ia0 = 0;
|
2020-10-15 02:56:18 +00:00
|
|
|
|
|
|
|
NGAP_PDUSessionResourceToBeSwitchedDLItem_t *PDUSessionItem = NULL;
|
|
|
|
OCTET_STRING_t *transfer = NULL;
|
|
|
|
|
2021-05-29 06:56:12 +00:00
|
|
|
amf_nsmf_pdusession_sm_context_param_t param;
|
2020-10-15 02:56:18 +00:00
|
|
|
|
|
|
|
ogs_assert(gnb);
|
2020-11-11 18:21:32 +00:00
|
|
|
ogs_assert(gnb->sctp.sock);
|
2020-10-15 02:56:18 +00:00
|
|
|
|
|
|
|
ogs_assert(message);
|
|
|
|
initiatingMessage = message->choice.initiatingMessage;
|
|
|
|
ogs_assert(initiatingMessage);
|
|
|
|
PathSwitchRequest = &initiatingMessage->value.choice.PathSwitchRequest;
|
|
|
|
ogs_assert(PathSwitchRequest);
|
|
|
|
|
2021-02-01 13:52:22 +00:00
|
|
|
ogs_info("PathSwitchRequest");
|
2022-04-29 12:28:16 +00:00
|
|
|
|
2020-10-15 03:02:18 +00:00
|
|
|
for (i = 0; i < PathSwitchRequest->protocolIEs.list.count; i++) {
|
2020-10-15 02:56:18 +00:00
|
|
|
ie = PathSwitchRequest->protocolIEs.list.array[i];
|
|
|
|
switch (ie->id) {
|
|
|
|
case NGAP_ProtocolIE_ID_id_RAN_UE_NGAP_ID:
|
|
|
|
RAN_UE_NGAP_ID = &ie->value.choice.RAN_UE_NGAP_ID;
|
|
|
|
break;
|
|
|
|
case NGAP_ProtocolIE_ID_id_SourceAMF_UE_NGAP_ID:
|
|
|
|
AMF_UE_NGAP_ID = &ie->value.choice.AMF_UE_NGAP_ID;
|
|
|
|
break;
|
|
|
|
case NGAP_ProtocolIE_ID_id_UserLocationInformation:
|
|
|
|
UserLocationInformation = &ie->value.choice.UserLocationInformation;
|
|
|
|
break;
|
|
|
|
case NGAP_ProtocolIE_ID_id_UESecurityCapabilities:
|
|
|
|
UESecurityCapabilities = &ie->value.choice.UESecurityCapabilities;
|
|
|
|
break;
|
|
|
|
case NGAP_ProtocolIE_ID_id_PDUSessionResourceToBeSwitchedDLList:
|
2020-10-15 03:02:18 +00:00
|
|
|
PDUSessionResourceToBeSwitchedDLList =
|
|
|
|
&ie->value.choice.PDUSessionResourceToBeSwitchedDLList;
|
2020-10-15 02:56:18 +00:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
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-10-15 02:56:18 +00:00
|
|
|
|
2021-05-08 08:01:45 +00:00
|
|
|
if (!RAN_UE_NGAP_ID) {
|
|
|
|
ogs_error("No RAN_UE_NGAP_ID");
|
2023-01-23 01:37:22 +00:00
|
|
|
r = ngap_send_error_indication(gnb, NULL, NULL,
|
|
|
|
NGAP_Cause_PR_protocol, NGAP_CauseProtocol_semantic_error);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2021-05-08 08:01:45 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2020-10-15 02:56:18 +00:00
|
|
|
if (!AMF_UE_NGAP_ID) {
|
|
|
|
ogs_error("No AMF_UE_NGAP_ID");
|
2023-01-23 01:37:22 +00:00
|
|
|
r = ngap_send_error_indication(gnb, (uint32_t *)RAN_UE_NGAP_ID, NULL,
|
|
|
|
NGAP_Cause_PR_protocol, NGAP_CauseProtocol_semantic_error);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2020-10-15 02:56:18 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (asn_INTEGER2ulong(AMF_UE_NGAP_ID,
|
|
|
|
(unsigned long *)&amf_ue_ngap_id) != 0) {
|
|
|
|
ogs_error("Invalid AMF_UE_NGAP_ID");
|
2023-01-23 01:37:22 +00:00
|
|
|
r = ngap_send_error_indication(gnb, (uint32_t *)RAN_UE_NGAP_ID, NULL,
|
|
|
|
NGAP_Cause_PR_protocol, NGAP_CauseProtocol_semantic_error);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2020-10-15 02:56:18 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
ran_ue = ran_ue_find_by_amf_ue_ngap_id(amf_ue_ngap_id);
|
|
|
|
if (!ran_ue) {
|
|
|
|
ogs_error("No RAN UE Context : AMF_UE_NGAP_ID[%lld]",
|
|
|
|
(long long)amf_ue_ngap_id);
|
2023-01-23 01:37:22 +00:00
|
|
|
r = ngap_send_error_indication(
|
2020-10-15 02:56:18 +00:00
|
|
|
gnb, (uint32_t *)RAN_UE_NGAP_ID, &amf_ue_ngap_id,
|
|
|
|
NGAP_Cause_PR_radioNetwork,
|
2023-01-23 01:37:22 +00:00
|
|
|
NGAP_CauseRadioNetwork_unknown_local_UE_NGAP_ID);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2020-10-15 02:56:18 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
amf_ue = ran_ue->amf_ue;
|
|
|
|
if (!amf_ue) {
|
|
|
|
ogs_error("Cannot find AMF-UE Context [%lld]",
|
|
|
|
(long long)amf_ue_ngap_id);
|
2023-01-23 01:37:22 +00:00
|
|
|
r = ngap_send_error_indication(
|
2020-10-15 02:56:18 +00:00
|
|
|
gnb, &ran_ue->ran_ue_ngap_id, &ran_ue->amf_ue_ngap_id,
|
|
|
|
NGAP_Cause_PR_radioNetwork,
|
2023-01-23 01:37:22 +00:00
|
|
|
NGAP_CauseRadioNetwork_unknown_local_UE_NGAP_ID);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2020-10-15 02:56:18 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2021-01-05 04:24:22 +00:00
|
|
|
ogs_info(" [OLD] RAN_UE_NGAP_ID[%d] AMF_UE_NGAP_ID[%lld] ",
|
2021-01-04 04:29:01 +00:00
|
|
|
ran_ue->ran_ue_ngap_id, (long long)ran_ue->amf_ue_ngap_id);
|
2021-01-05 04:24:22 +00:00
|
|
|
ogs_info(" [OLD] TAC[%d] CellID[0x%llx]",
|
2021-03-08 12:25:09 +00:00
|
|
|
amf_ue->nr_tai.tac.v, (long long)amf_ue->nr_cgi.cell_id);
|
2020-10-15 02:56:18 +00:00
|
|
|
|
2021-01-04 04:29:01 +00:00
|
|
|
/* Update RAN-UE-NGAP-ID */
|
|
|
|
ran_ue->ran_ue_ngap_id = *RAN_UE_NGAP_ID;
|
2021-01-03 05:50:59 +00:00
|
|
|
|
2021-01-04 04:29:01 +00:00
|
|
|
/* Change ran_ue to the NEW gNB */
|
|
|
|
ran_ue_switch_to_gnb(ran_ue, gnb);
|
|
|
|
|
|
|
|
if (!UserLocationInformation) {
|
|
|
|
ogs_error("No UserLocationInformation");
|
2023-01-23 01:37:22 +00:00
|
|
|
r = ngap_send_error_indication2(amf_ue,
|
|
|
|
NGAP_Cause_PR_protocol, NGAP_CauseProtocol_semantic_error);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2021-01-03 05:50:59 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2021-01-04 04:29:01 +00:00
|
|
|
if (UserLocationInformation->present !=
|
2020-10-15 02:56:18 +00:00
|
|
|
NGAP_UserLocationInformation_PR_userLocationInformationNR) {
|
|
|
|
ogs_error("Not implemented UserLocationInformation[%d]",
|
|
|
|
UserLocationInformation->present);
|
2023-01-23 01:37:22 +00:00
|
|
|
r = ngap_send_error_indication2(amf_ue,
|
|
|
|
NGAP_Cause_PR_protocol, NGAP_CauseProtocol_unspecified);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2021-01-03 05:50:59 +00:00
|
|
|
return;
|
|
|
|
}
|
2020-10-15 02:56:18 +00:00
|
|
|
|
2022-04-29 12:28:16 +00:00
|
|
|
if (!UESecurityCapabilities) {
|
|
|
|
ogs_error("No UESecurityCapabilities");
|
2023-01-23 01:37:22 +00:00
|
|
|
r = ngap_send_error_indication2(amf_ue,
|
|
|
|
NGAP_Cause_PR_protocol, NGAP_CauseProtocol_semantic_error);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2022-04-29 12:28:16 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!PDUSessionResourceToBeSwitchedDLList) {
|
|
|
|
ogs_error("No PDUSessionResourceToBeSwitchedDLList");
|
2023-01-23 01:37:22 +00:00
|
|
|
r = ngap_send_error_indication2(amf_ue,
|
|
|
|
NGAP_Cause_PR_protocol, NGAP_CauseProtocol_semantic_error);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2022-04-29 12:28:16 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!SECURITY_CONTEXT_IS_VALID(amf_ue)) {
|
|
|
|
ogs_error("No Security Context");
|
2023-01-23 01:37:22 +00:00
|
|
|
r = ngap_send_error_indication2(amf_ue,
|
|
|
|
NGAP_Cause_PR_nas, NGAP_CauseNas_authentication_failure);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2022-04-29 12:28:16 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2021-01-05 04:24:22 +00:00
|
|
|
ogs_info(" [NEW] RAN_UE_NGAP_ID[%d] AMF_UE_NGAP_ID[%lld] ",
|
2021-01-03 05:50:59 +00:00
|
|
|
ran_ue->ran_ue_ngap_id, (long long)ran_ue->amf_ue_ngap_id);
|
2021-01-04 04:29:01 +00:00
|
|
|
|
|
|
|
UserLocationInformationNR =
|
|
|
|
UserLocationInformation->choice.userLocationInformationNR;
|
|
|
|
ogs_assert(UserLocationInformationNR);
|
|
|
|
ogs_ngap_ASN_to_nr_cgi(
|
|
|
|
&UserLocationInformationNR->nR_CGI, &ran_ue->saved.nr_cgi);
|
|
|
|
ogs_ngap_ASN_to_5gs_tai(
|
2021-03-08 12:25:09 +00:00
|
|
|
&UserLocationInformationNR->tAI, &ran_ue->saved.nr_tai);
|
2021-01-03 05:50:59 +00:00
|
|
|
|
2021-01-28 19:23:54 +00:00
|
|
|
/* Copy Stream-No/TAI/ECGI from ran_ue */
|
2021-01-18 16:48:35 +00:00
|
|
|
amf_ue->gnb_ostream_id = ran_ue->gnb_ostream_id;
|
2021-03-08 12:25:09 +00:00
|
|
|
memcpy(&amf_ue->nr_tai, &ran_ue->saved.nr_tai, sizeof(ogs_5gs_tai_t));
|
2021-01-03 05:50:59 +00:00
|
|
|
memcpy(&amf_ue->nr_cgi, &ran_ue->saved.nr_cgi, sizeof(ogs_nr_cgi_t));
|
|
|
|
|
2021-01-05 04:24:22 +00:00
|
|
|
ogs_info(" [NEW] TAC[%d] CellID[0x%llx]",
|
2021-03-08 12:25:09 +00:00
|
|
|
amf_ue->nr_tai.tac.v, (long long)amf_ue->nr_cgi.cell_id);
|
2021-01-04 04:29:01 +00:00
|
|
|
|
2021-01-03 05:50:59 +00:00
|
|
|
nRencryptionAlgorithms = &UESecurityCapabilities->nRencryptionAlgorithms;
|
2020-10-15 02:56:18 +00:00
|
|
|
nRintegrityProtectionAlgorithms =
|
|
|
|
&UESecurityCapabilities->nRintegrityProtectionAlgorithms;
|
|
|
|
eUTRAencryptionAlgorithms =
|
|
|
|
&UESecurityCapabilities->eUTRAencryptionAlgorithms;
|
|
|
|
eUTRAintegrityProtectionAlgorithms =
|
|
|
|
&UESecurityCapabilities->eUTRAintegrityProtectionAlgorithms;
|
|
|
|
|
2021-01-08 03:26:06 +00:00
|
|
|
memcpy(&nr_ea, nRencryptionAlgorithms->buf, sizeof(nr_ea));
|
|
|
|
nr_ea = be16toh(nr_ea);
|
|
|
|
nr_ea0 = amf_ue->ue_security_capability.nr_ea0;
|
|
|
|
amf_ue->ue_security_capability.nr_ea = nr_ea >> 9;
|
|
|
|
amf_ue->ue_security_capability.nr_ea0 = nr_ea0;
|
|
|
|
|
|
|
|
memcpy(&nr_ia, nRintegrityProtectionAlgorithms->buf, sizeof(nr_ia));
|
|
|
|
nr_ia = be16toh(nr_ia);
|
|
|
|
nr_ia0 = amf_ue->ue_security_capability.nr_ia0;
|
|
|
|
amf_ue->ue_security_capability.nr_ia = nr_ia >> 9;
|
|
|
|
amf_ue->ue_security_capability.nr_ia0 = nr_ia0;
|
|
|
|
|
|
|
|
memcpy(&eutra_ea, eUTRAencryptionAlgorithms->buf, sizeof(eutra_ea));
|
|
|
|
eutra_ea = be16toh(eutra_ea);
|
|
|
|
eutra_ea0 = amf_ue->ue_security_capability.eutra_ea0;
|
|
|
|
amf_ue->ue_security_capability.eutra_ea = eutra_ea >> 9;
|
|
|
|
amf_ue->ue_security_capability.eutra_ea0 = eutra_ea0;
|
|
|
|
|
|
|
|
memcpy(&eutra_ia,
|
|
|
|
eUTRAintegrityProtectionAlgorithms->buf, sizeof(eutra_ia));
|
|
|
|
eutra_ia = be16toh(eutra_ia);
|
|
|
|
eutra_ia0 = amf_ue->ue_security_capability.eutra_ia0;
|
|
|
|
amf_ue->ue_security_capability.eutra_ia = eutra_ia >> 9;
|
|
|
|
amf_ue->ue_security_capability.eutra_ia0 = eutra_ia0;
|
2020-10-15 02:56:18 +00:00
|
|
|
|
2021-01-04 04:29:01 +00:00
|
|
|
/* Update Security Context (NextHop) */
|
|
|
|
amf_ue->nhcc++;
|
|
|
|
ogs_kdf_nh_gnb(amf_ue->kamf, amf_ue->nh, amf_ue->nh);
|
|
|
|
|
2020-10-15 02:56:18 +00:00
|
|
|
for (i = 0; i < PDUSessionResourceToBeSwitchedDLList->list.count; i++) {
|
|
|
|
amf_sess_t *sess = NULL;
|
|
|
|
PDUSessionItem = (NGAP_PDUSessionResourceToBeSwitchedDLItem_t *)
|
|
|
|
PDUSessionResourceToBeSwitchedDLList->list.array[i];
|
|
|
|
|
|
|
|
if (!PDUSessionItem) {
|
|
|
|
ogs_error("No NGAP_PDUSessionResourceToBeSwitchedDLItem");
|
2023-01-23 01:37:22 +00:00
|
|
|
r = ngap_send_error_indication2(amf_ue,
|
|
|
|
NGAP_Cause_PR_protocol, NGAP_CauseProtocol_semantic_error);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2020-10-15 02:56:18 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
transfer = &PDUSessionItem->pathSwitchRequestTransfer;
|
|
|
|
if (!transfer) {
|
|
|
|
ogs_error("No PDUSessionResourceSetupResponseTransfer");
|
2023-01-23 01:37:22 +00:00
|
|
|
r = ngap_send_error_indication2(amf_ue,
|
|
|
|
NGAP_Cause_PR_protocol, NGAP_CauseProtocol_semantic_error);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2020-10-15 02:56:18 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (PDUSessionItem->pDUSessionID ==
|
|
|
|
OGS_NAS_PDU_SESSION_IDENTITY_UNASSIGNED) {
|
|
|
|
ogs_error("PDU Session Identity is unassigned");
|
2023-01-23 01:37:22 +00:00
|
|
|
r = ngap_send_error_indication2(amf_ue,
|
|
|
|
NGAP_Cause_PR_protocol, NGAP_CauseProtocol_semantic_error);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2020-10-15 02:56:18 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
sess = amf_sess_find_by_psi(amf_ue, PDUSessionItem->pDUSessionID);
|
|
|
|
if (!sess) {
|
|
|
|
ogs_error("Cannot find PDU Session ID [%d]",
|
|
|
|
(int)PDUSessionItem->pDUSessionID);
|
2023-01-23 01:37:22 +00:00
|
|
|
r = ngap_send_error_indication2(amf_ue,
|
2020-10-15 02:56:18 +00:00
|
|
|
NGAP_Cause_PR_radioNetwork,
|
2023-01-23 01:37:22 +00:00
|
|
|
NGAP_CauseRadioNetwork_unknown_PDU_session_ID);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2020-10-15 02:56:18 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!SESSION_CONTEXT_IN_SMF(sess)) {
|
|
|
|
ogs_error("Session Context is not in SMF [%d]",
|
|
|
|
(int)PDUSessionItem->pDUSessionID);
|
2023-01-23 01:37:22 +00:00
|
|
|
r = ngap_send_error_indication2(amf_ue,
|
2020-10-15 02:56:18 +00:00
|
|
|
NGAP_Cause_PR_radioNetwork,
|
2023-01-23 01:37:22 +00:00
|
|
|
NGAP_CauseRadioNetwork_unknown_PDU_session_ID);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2020-10-15 02:56:18 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
memset(¶m, 0, sizeof(param));
|
|
|
|
param.n2smbuf = ogs_pkbuf_alloc(NULL, OGS_MAX_SDU_LEN);
|
|
|
|
ogs_assert(param.n2smbuf);
|
|
|
|
param.n2SmInfoType = OpenAPI_n2_sm_info_type_PATH_SWITCH_REQ;
|
|
|
|
ogs_pkbuf_put_data(param.n2smbuf, transfer->buf, transfer->size);
|
|
|
|
|
2023-01-31 10:38:17 +00:00
|
|
|
r = amf_sess_sbi_discover_and_send(
|
2022-08-26 15:12:22 +00:00
|
|
|
OGS_SBI_SERVICE_TYPE_NSMF_PDUSESSION, NULL,
|
2022-07-24 06:10:09 +00:00
|
|
|
amf_nsmf_pdusession_build_update_sm_context,
|
2023-01-31 10:38:17 +00:00
|
|
|
sess, AMF_UPDATE_SM_CONTEXT_PATH_SWITCH_REQUEST, ¶m);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2020-10-15 02:56:18 +00:00
|
|
|
|
|
|
|
ogs_pkbuf_free(param.n2smbuf);
|
|
|
|
}
|
|
|
|
}
|
2021-01-25 04:43:42 +00:00
|
|
|
|
2021-01-28 19:23:54 +00:00
|
|
|
void ngap_handle_handover_required(
|
|
|
|
amf_gnb_t *gnb, ogs_ngap_message_t *message)
|
|
|
|
{
|
|
|
|
char buf[OGS_ADDRSTRLEN];
|
2023-01-23 01:37:22 +00:00
|
|
|
int i, r;
|
2021-01-28 19:23:54 +00:00
|
|
|
|
|
|
|
amf_ue_t *amf_ue = NULL;
|
|
|
|
ran_ue_t *source_ue = NULL, *target_ue = NULL;
|
|
|
|
uint64_t amf_ue_ngap_id;
|
|
|
|
|
|
|
|
amf_gnb_t *target_gnb = NULL;
|
|
|
|
uint32_t target_gnb_id;
|
|
|
|
|
|
|
|
NGAP_InitiatingMessage_t *initiatingMessage = NULL;
|
|
|
|
NGAP_HandoverRequired_t *HandoverRequired = NULL;
|
|
|
|
|
|
|
|
NGAP_HandoverRequiredIEs_t *ie = NULL;
|
|
|
|
NGAP_RAN_UE_NGAP_ID_t *RAN_UE_NGAP_ID = NULL;
|
|
|
|
NGAP_AMF_UE_NGAP_ID_t *AMF_UE_NGAP_ID = NULL;
|
|
|
|
NGAP_HandoverType_t *HandoverType = NULL;
|
|
|
|
NGAP_Cause_t *Cause = NULL;
|
|
|
|
NGAP_TargetID_t *TargetID = NULL;
|
|
|
|
NGAP_TargetRANNodeID_t *targetRANNodeID = NULL;
|
|
|
|
NGAP_GlobalRANNodeID_t *globalRANNodeID = NULL;
|
|
|
|
NGAP_GlobalGNB_ID_t *globalGNB_ID = NULL;
|
|
|
|
NGAP_PDUSessionResourceListHORqd_t *PDUSessionList = NULL;
|
|
|
|
NGAP_PDUSessionResourceItemHORqd_t *PDUSessionItem = NULL;
|
|
|
|
OCTET_STRING_t *transfer = NULL;
|
|
|
|
|
|
|
|
NGAP_SourceToTarget_TransparentContainer_t
|
|
|
|
*SourceToTarget_TransparentContainer = NULL;
|
|
|
|
|
2021-05-29 06:56:12 +00:00
|
|
|
amf_nsmf_pdusession_sm_context_param_t param;
|
2021-01-28 19:23:54 +00:00
|
|
|
|
|
|
|
ogs_assert(gnb);
|
|
|
|
ogs_assert(gnb->sctp.sock);
|
|
|
|
|
|
|
|
ogs_assert(message);
|
|
|
|
initiatingMessage = message->choice.initiatingMessage;
|
|
|
|
ogs_assert(initiatingMessage);
|
|
|
|
HandoverRequired = &initiatingMessage->value.choice.HandoverRequired;
|
|
|
|
ogs_assert(HandoverRequired);
|
|
|
|
|
2021-02-01 13:52:22 +00:00
|
|
|
ogs_info("HandoverRequired");
|
2021-01-28 19:23:54 +00:00
|
|
|
|
|
|
|
for (i = 0; i < HandoverRequired->protocolIEs.list.count; i++) {
|
|
|
|
ie = HandoverRequired->protocolIEs.list.array[i];
|
|
|
|
switch (ie->id) {
|
|
|
|
case NGAP_ProtocolIE_ID_id_RAN_UE_NGAP_ID:
|
|
|
|
RAN_UE_NGAP_ID = &ie->value.choice.RAN_UE_NGAP_ID;
|
|
|
|
break;
|
|
|
|
case NGAP_ProtocolIE_ID_id_AMF_UE_NGAP_ID:
|
|
|
|
AMF_UE_NGAP_ID = &ie->value.choice.AMF_UE_NGAP_ID;
|
|
|
|
break;
|
|
|
|
case NGAP_ProtocolIE_ID_id_HandoverType:
|
|
|
|
HandoverType = &ie->value.choice.HandoverType;
|
|
|
|
break;
|
|
|
|
case NGAP_ProtocolIE_ID_id_Cause:
|
|
|
|
Cause = &ie->value.choice.Cause;
|
|
|
|
break;
|
|
|
|
case NGAP_ProtocolIE_ID_id_TargetID:
|
|
|
|
TargetID = &ie->value.choice.TargetID;
|
|
|
|
break;
|
|
|
|
case NGAP_ProtocolIE_ID_id_PDUSessionResourceListHORqd:
|
|
|
|
PDUSessionList = &ie->value.choice.PDUSessionResourceListHORqd;
|
|
|
|
break;
|
|
|
|
case NGAP_ProtocolIE_ID_id_SourceToTarget_TransparentContainer:
|
|
|
|
SourceToTarget_TransparentContainer =
|
|
|
|
&ie->value.choice.SourceToTarget_TransparentContainer;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
ogs_debug(" IP[%s] RAN_ID[%d]",
|
|
|
|
OGS_ADDR(gnb->sctp.addr, buf), gnb->gnb_id);
|
|
|
|
|
|
|
|
if (!AMF_UE_NGAP_ID) {
|
|
|
|
ogs_error("No AMF_UE_NGAP_ID");
|
2023-01-23 01:37:22 +00:00
|
|
|
r = ngap_send_error_indication(gnb, (uint32_t *)RAN_UE_NGAP_ID, NULL,
|
|
|
|
NGAP_Cause_PR_protocol, NGAP_CauseProtocol_semantic_error);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2021-01-28 19:23:54 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (asn_INTEGER2ulong(AMF_UE_NGAP_ID,
|
|
|
|
(unsigned long *)&amf_ue_ngap_id) != 0) {
|
|
|
|
ogs_error("Invalid AMF_UE_NGAP_ID");
|
2023-01-23 01:37:22 +00:00
|
|
|
r = ngap_send_error_indication(gnb, (uint32_t *)RAN_UE_NGAP_ID, NULL,
|
|
|
|
NGAP_Cause_PR_protocol, NGAP_CauseProtocol_semantic_error);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2021-01-28 19:23:54 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
source_ue = ran_ue_find_by_amf_ue_ngap_id(amf_ue_ngap_id);
|
|
|
|
if (!source_ue) {
|
|
|
|
ogs_error("No RAN UE Context : AMF_UE_NGAP_ID[%lld]",
|
|
|
|
(long long)amf_ue_ngap_id);
|
2023-01-23 01:37:22 +00:00
|
|
|
r = ngap_send_error_indication(
|
2021-01-28 19:23:54 +00:00
|
|
|
gnb, (uint32_t *)RAN_UE_NGAP_ID, &amf_ue_ngap_id,
|
|
|
|
NGAP_Cause_PR_radioNetwork,
|
2023-01-23 01:37:22 +00:00
|
|
|
NGAP_CauseRadioNetwork_unknown_local_UE_NGAP_ID);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2021-01-28 19:23:54 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
ogs_debug(" Source : RAN_UE_NGAP_ID[%d] AMF_UE_NGAP_ID[%lld] ",
|
|
|
|
source_ue->ran_ue_ngap_id, (long long)source_ue->amf_ue_ngap_id);
|
|
|
|
|
|
|
|
amf_ue = source_ue->amf_ue;
|
|
|
|
if (!amf_ue) {
|
|
|
|
ogs_error("Cannot find AMF-UE Context [%lld]",
|
|
|
|
(long long)amf_ue_ngap_id);
|
2023-01-23 01:37:22 +00:00
|
|
|
r = ngap_send_error_indication(
|
2021-01-28 19:23:54 +00:00
|
|
|
gnb, &source_ue->ran_ue_ngap_id, &source_ue->amf_ue_ngap_id,
|
|
|
|
NGAP_Cause_PR_radioNetwork,
|
2023-01-23 01:37:22 +00:00
|
|
|
NGAP_CauseRadioNetwork_unknown_local_UE_NGAP_ID);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2021-01-28 19:23:54 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!HandoverType) {
|
|
|
|
ogs_error("No HandoverType");
|
2023-01-23 01:37:22 +00:00
|
|
|
r = ngap_send_error_indication2(amf_ue,
|
|
|
|
NGAP_Cause_PR_protocol, NGAP_CauseProtocol_semantic_error);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2021-01-28 19:23:54 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!Cause) {
|
|
|
|
ogs_error("No Cause");
|
2023-01-23 01:37:22 +00:00
|
|
|
r = ngap_send_error_indication2(amf_ue,
|
|
|
|
NGAP_Cause_PR_protocol, NGAP_CauseProtocol_semantic_error);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2021-01-28 19:23:54 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!TargetID) {
|
|
|
|
ogs_error("No TargetID");
|
2023-01-23 01:37:22 +00:00
|
|
|
r = ngap_send_error_indication2(amf_ue,
|
|
|
|
NGAP_Cause_PR_protocol, NGAP_CauseProtocol_semantic_error);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2021-01-28 19:23:54 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (TargetID->present != NGAP_TargetID_PR_targetRANNodeID) {
|
|
|
|
ogs_error("Not implemented TargetID[%d]", TargetID->present);
|
2023-01-23 01:37:22 +00:00
|
|
|
r = ngap_send_error_indication2(amf_ue,
|
|
|
|
NGAP_Cause_PR_protocol, NGAP_CauseProtocol_semantic_error);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2021-01-28 19:23:54 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
targetRANNodeID = TargetID->choice.targetRANNodeID;
|
|
|
|
if (!targetRANNodeID) {
|
|
|
|
ogs_error("No targetRANNodeID");
|
2023-01-23 01:37:22 +00:00
|
|
|
r = ngap_send_error_indication2(amf_ue,
|
|
|
|
NGAP_Cause_PR_protocol, NGAP_CauseProtocol_semantic_error);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2021-01-28 19:23:54 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
globalRANNodeID = &targetRANNodeID->globalRANNodeID;
|
|
|
|
if (globalRANNodeID->present != NGAP_GlobalRANNodeID_PR_globalGNB_ID) {
|
|
|
|
ogs_error("Not implemented globalRANNodeID[%d]",
|
|
|
|
globalRANNodeID->present);
|
2023-01-23 01:37:22 +00:00
|
|
|
r = ngap_send_error_indication2(amf_ue,
|
|
|
|
NGAP_Cause_PR_protocol, NGAP_CauseProtocol_semantic_error);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2021-01-28 19:23:54 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
globalGNB_ID = globalRANNodeID->choice.globalGNB_ID;
|
|
|
|
if (!globalGNB_ID) {
|
|
|
|
ogs_error("No globalGNB_ID");
|
2023-01-23 01:37:22 +00:00
|
|
|
r = ngap_send_error_indication2(amf_ue,
|
|
|
|
NGAP_Cause_PR_protocol, NGAP_CauseProtocol_semantic_error);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2021-01-28 19:23:54 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
ogs_ngap_GNB_ID_to_uint32(&globalGNB_ID->gNB_ID, &target_gnb_id);
|
|
|
|
target_gnb = amf_gnb_find_by_gnb_id(target_gnb_id);
|
|
|
|
if (!target_gnb) {
|
|
|
|
ogs_error("Handover required : cannot find target gNB-id[0x%x]",
|
|
|
|
target_gnb_id);
|
2023-01-23 01:37:22 +00:00
|
|
|
r = ngap_send_error_indication2(amf_ue,
|
|
|
|
NGAP_Cause_PR_protocol, NGAP_CauseProtocol_semantic_error);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2021-01-28 19:23:54 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!PDUSessionList) {
|
|
|
|
ogs_error("No PDUSessionList");
|
2023-01-23 01:37:22 +00:00
|
|
|
r = ngap_send_error_indication2(amf_ue,
|
|
|
|
NGAP_Cause_PR_protocol, NGAP_CauseProtocol_semantic_error);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2021-01-28 19:23:54 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!SourceToTarget_TransparentContainer) {
|
|
|
|
ogs_error("No SourceToTarget_TransparentContainer");
|
2023-01-23 01:37:22 +00:00
|
|
|
r = ngap_send_error_indication2(amf_ue,
|
|
|
|
NGAP_Cause_PR_protocol, NGAP_CauseProtocol_semantic_error);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2021-01-28 19:23:54 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!SECURITY_CONTEXT_IS_VALID(amf_ue)) {
|
|
|
|
ogs_error("No Security Context");
|
2023-01-23 01:37:22 +00:00
|
|
|
r = ngap_send_error_indication2(amf_ue,
|
|
|
|
NGAP_Cause_PR_nas, NGAP_CauseNas_authentication_failure);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2021-01-28 19:23:54 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Target UE */
|
|
|
|
target_ue = ran_ue_add(target_gnb, INVALID_UE_NGAP_ID);
|
2022-10-07 05:31:34 +00:00
|
|
|
if (target_ue == NULL) {
|
2023-01-23 01:37:22 +00:00
|
|
|
r = ngap_send_error_indication2(amf_ue, NGAP_Cause_PR_misc,
|
|
|
|
NGAP_CauseMisc_control_processing_overload);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2022-10-07 05:31:34 +00:00
|
|
|
return;
|
|
|
|
}
|
2021-01-28 19:23:54 +00:00
|
|
|
|
|
|
|
/* Source UE - Target UE associated */
|
|
|
|
source_ue_associate_target_ue(source_ue, target_ue);
|
|
|
|
|
2021-04-23 06:16:18 +00:00
|
|
|
/* Context Transfer */
|
|
|
|
target_ue->ue_context_requested = source_ue->ue_context_requested;
|
|
|
|
target_ue->initial_context_setup_request_sent =
|
|
|
|
source_ue->initial_context_setup_request_sent;
|
|
|
|
|
2021-01-28 19:23:54 +00:00
|
|
|
ogs_debug(" Target : RAN_UE_NGAP_ID[%d] AMF_UE_NGAP_ID[%lld] ",
|
|
|
|
target_ue->ran_ue_ngap_id, (long long)target_ue->amf_ue_ngap_id);
|
|
|
|
|
|
|
|
/* Store HandoverType */
|
|
|
|
amf_ue->handover.type = *HandoverType;
|
|
|
|
|
|
|
|
/* Store Cause */
|
|
|
|
amf_ue->handover.group = Cause->present;
|
|
|
|
amf_ue->handover.cause = (int)Cause->choice.radioNetwork;
|
|
|
|
|
|
|
|
/* Update Security Context (NextHop) */
|
|
|
|
amf_ue->nhcc++;
|
|
|
|
ogs_kdf_nh_gnb(amf_ue->kamf, amf_ue->nh, amf_ue->nh);
|
|
|
|
|
|
|
|
/* Store Container */
|
|
|
|
OGS_ASN_STORE_DATA(&amf_ue->handover.container,
|
|
|
|
SourceToTarget_TransparentContainer);
|
|
|
|
|
|
|
|
for (i = 0; i < PDUSessionList->list.count; i++) {
|
|
|
|
amf_sess_t *sess = NULL;
|
|
|
|
PDUSessionItem = (NGAP_PDUSessionResourceItemHORqd_t *)
|
|
|
|
PDUSessionList->list.array[i];
|
|
|
|
|
|
|
|
if (!PDUSessionItem) {
|
|
|
|
ogs_error("No PDUSessionResourceItemHORqd");
|
2023-01-23 01:37:22 +00:00
|
|
|
r = ngap_send_error_indication2(amf_ue,
|
|
|
|
NGAP_Cause_PR_protocol, NGAP_CauseProtocol_semantic_error);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2021-01-28 19:23:54 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
transfer = &PDUSessionItem->handoverRequiredTransfer;
|
|
|
|
if (!transfer) {
|
|
|
|
ogs_error("No handoverRequiredTransfer");
|
2023-01-23 01:37:22 +00:00
|
|
|
r = ngap_send_error_indication2(amf_ue,
|
|
|
|
NGAP_Cause_PR_protocol, NGAP_CauseProtocol_semantic_error);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2021-01-28 19:23:54 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (PDUSessionItem->pDUSessionID ==
|
|
|
|
OGS_NAS_PDU_SESSION_IDENTITY_UNASSIGNED) {
|
|
|
|
ogs_error("PDU Session Identity is unassigned");
|
2023-01-23 01:37:22 +00:00
|
|
|
r = ngap_send_error_indication2(amf_ue,
|
|
|
|
NGAP_Cause_PR_protocol, NGAP_CauseProtocol_semantic_error);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2021-01-28 19:23:54 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
sess = amf_sess_find_by_psi(amf_ue, PDUSessionItem->pDUSessionID);
|
|
|
|
if (!sess) {
|
|
|
|
ogs_error("Cannot find PDU Session ID [%d]",
|
|
|
|
(int)PDUSessionItem->pDUSessionID);
|
2023-01-23 01:37:22 +00:00
|
|
|
r = ngap_send_error_indication2(amf_ue,
|
2021-01-28 19:23:54 +00:00
|
|
|
NGAP_Cause_PR_radioNetwork,
|
2023-01-23 01:37:22 +00:00
|
|
|
NGAP_CauseRadioNetwork_unknown_PDU_session_ID);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2021-01-28 19:23:54 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!SESSION_CONTEXT_IN_SMF(sess)) {
|
|
|
|
ogs_error("Session Context is not in SMF [%d]",
|
|
|
|
(int)PDUSessionItem->pDUSessionID);
|
2023-01-23 01:37:22 +00:00
|
|
|
r = ngap_send_error_indication2(amf_ue,
|
2021-01-28 19:23:54 +00:00
|
|
|
NGAP_Cause_PR_radioNetwork,
|
2023-01-23 01:37:22 +00:00
|
|
|
NGAP_CauseRadioNetwork_unknown_PDU_session_ID);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2021-01-28 19:23:54 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
memset(¶m, 0, sizeof(param));
|
|
|
|
param.n2smbuf = ogs_pkbuf_alloc(NULL, OGS_MAX_SDU_LEN);
|
|
|
|
ogs_assert(param.n2smbuf);
|
|
|
|
param.n2SmInfoType = OpenAPI_n2_sm_info_type_HANDOVER_REQUIRED;
|
|
|
|
ogs_pkbuf_put_data(param.n2smbuf, transfer->buf, transfer->size);
|
|
|
|
|
|
|
|
param.hoState = OpenAPI_ho_state_PREPARING;
|
|
|
|
param.TargetID = TargetID;
|
|
|
|
|
2023-01-31 10:38:17 +00:00
|
|
|
r = amf_sess_sbi_discover_and_send(
|
2022-08-26 15:12:22 +00:00
|
|
|
OGS_SBI_SERVICE_TYPE_NSMF_PDUSESSION, NULL,
|
2022-07-24 06:10:09 +00:00
|
|
|
amf_nsmf_pdusession_build_update_sm_context,
|
2023-01-31 10:38:17 +00:00
|
|
|
sess, AMF_UPDATE_SM_CONTEXT_HANDOVER_REQUIRED, ¶m);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2021-01-28 19:23:54 +00:00
|
|
|
|
|
|
|
ogs_pkbuf_free(param.n2smbuf);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void ngap_handle_handover_request_ack(
|
|
|
|
amf_gnb_t *gnb, ogs_ngap_message_t *message)
|
|
|
|
{
|
|
|
|
char buf[OGS_ADDRSTRLEN];
|
2023-01-23 01:37:22 +00:00
|
|
|
int i, r;
|
2021-01-28 19:23:54 +00:00
|
|
|
|
|
|
|
amf_ue_t *amf_ue = NULL;
|
|
|
|
ran_ue_t *source_ue = NULL, *target_ue = NULL;
|
|
|
|
uint64_t amf_ue_ngap_id;
|
2021-05-29 06:56:12 +00:00
|
|
|
amf_nsmf_pdusession_sm_context_param_t param;
|
2021-01-28 19:23:54 +00:00
|
|
|
|
|
|
|
NGAP_SuccessfulOutcome_t *successfulOutcome = NULL;
|
|
|
|
NGAP_HandoverRequestAcknowledge_t *HandoverRequestAcknowledge = NULL;
|
|
|
|
|
|
|
|
NGAP_HandoverRequestAcknowledgeIEs_t *ie = NULL;
|
|
|
|
NGAP_RAN_UE_NGAP_ID_t *RAN_UE_NGAP_ID = NULL;
|
|
|
|
NGAP_AMF_UE_NGAP_ID_t *AMF_UE_NGAP_ID = NULL;
|
|
|
|
NGAP_PDUSessionResourceAdmittedList_t *PDUSessionList = NULL;
|
|
|
|
NGAP_PDUSessionResourceAdmittedItem_t *PDUSessionItem = NULL;
|
|
|
|
OCTET_STRING_t *transfer = NULL;
|
|
|
|
|
|
|
|
NGAP_TargetToSource_TransparentContainer_t
|
|
|
|
*TargetToSource_TransparentContainer = NULL;
|
|
|
|
|
|
|
|
ogs_assert(gnb);
|
|
|
|
ogs_assert(gnb->sctp.sock);
|
|
|
|
|
|
|
|
ogs_assert(message);
|
|
|
|
successfulOutcome = message->choice.successfulOutcome;
|
|
|
|
ogs_assert(successfulOutcome);
|
|
|
|
HandoverRequestAcknowledge =
|
|
|
|
&successfulOutcome->value.choice.HandoverRequestAcknowledge;
|
|
|
|
ogs_assert(HandoverRequestAcknowledge);
|
|
|
|
|
2021-02-01 13:52:22 +00:00
|
|
|
ogs_debug("HandoverRequestAcknowledge");
|
2021-01-28 19:23:54 +00:00
|
|
|
|
|
|
|
for (i = 0; i < HandoverRequestAcknowledge->protocolIEs.list.count; i++) {
|
|
|
|
ie = HandoverRequestAcknowledge->protocolIEs.list.array[i];
|
|
|
|
switch (ie->id) {
|
|
|
|
case NGAP_ProtocolIE_ID_id_RAN_UE_NGAP_ID:
|
|
|
|
RAN_UE_NGAP_ID = &ie->value.choice.RAN_UE_NGAP_ID;
|
|
|
|
break;
|
|
|
|
case NGAP_ProtocolIE_ID_id_AMF_UE_NGAP_ID:
|
|
|
|
AMF_UE_NGAP_ID = &ie->value.choice.AMF_UE_NGAP_ID;
|
|
|
|
break;
|
|
|
|
case NGAP_ProtocolIE_ID_id_PDUSessionResourceAdmittedList:
|
|
|
|
PDUSessionList = &ie->value.choice.PDUSessionResourceAdmittedList;
|
|
|
|
break;
|
|
|
|
case NGAP_ProtocolIE_ID_id_TargetToSource_TransparentContainer:
|
|
|
|
TargetToSource_TransparentContainer =
|
|
|
|
&ie->value.choice.TargetToSource_TransparentContainer;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
ogs_debug(" IP[%s] RAN_ID[%d]",
|
|
|
|
OGS_ADDR(gnb->sctp.addr, buf), gnb->gnb_id);
|
|
|
|
|
2021-05-08 08:01:45 +00:00
|
|
|
if (!RAN_UE_NGAP_ID) {
|
|
|
|
ogs_error("No RAN_UE_NGAP_ID");
|
2023-01-23 01:37:22 +00:00
|
|
|
r = ngap_send_error_indication(gnb, NULL, NULL,
|
|
|
|
NGAP_Cause_PR_protocol, NGAP_CauseProtocol_semantic_error);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2021-05-08 08:01:45 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2021-01-28 19:23:54 +00:00
|
|
|
if (!AMF_UE_NGAP_ID) {
|
|
|
|
ogs_error("No AMF_UE_NGAP_ID");
|
2023-01-23 01:37:22 +00:00
|
|
|
r = ngap_send_error_indication(gnb, (uint32_t *)RAN_UE_NGAP_ID, NULL,
|
|
|
|
NGAP_Cause_PR_protocol, NGAP_CauseProtocol_semantic_error);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2021-01-28 19:23:54 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (asn_INTEGER2ulong(AMF_UE_NGAP_ID,
|
|
|
|
(unsigned long *)&amf_ue_ngap_id) != 0) {
|
|
|
|
ogs_error("Invalid AMF_UE_NGAP_ID");
|
2023-01-23 01:37:22 +00:00
|
|
|
r = ngap_send_error_indication(gnb, (uint32_t *)RAN_UE_NGAP_ID, NULL,
|
|
|
|
NGAP_Cause_PR_protocol, NGAP_CauseProtocol_semantic_error);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2021-01-28 19:23:54 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
target_ue = ran_ue_find_by_amf_ue_ngap_id(amf_ue_ngap_id);
|
|
|
|
if (!target_ue) {
|
|
|
|
ogs_error("No RAN UE Context : AMF_UE_NGAP_ID[%lld]",
|
|
|
|
(long long)amf_ue_ngap_id);
|
2023-01-23 01:37:22 +00:00
|
|
|
r = ngap_send_error_indication(
|
2021-01-28 19:23:54 +00:00
|
|
|
gnb, (uint32_t *)RAN_UE_NGAP_ID, &amf_ue_ngap_id,
|
|
|
|
NGAP_Cause_PR_radioNetwork,
|
2023-01-23 01:37:22 +00:00
|
|
|
NGAP_CauseRadioNetwork_unknown_local_UE_NGAP_ID);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2021-01-28 19:23:54 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!RAN_UE_NGAP_ID) {
|
|
|
|
ogs_error("No RAN_UE_NGAP_ID");
|
2023-01-23 01:37:22 +00:00
|
|
|
r = ngap_send_error_indication(gnb, NULL, NULL,
|
|
|
|
NGAP_Cause_PR_protocol, NGAP_CauseProtocol_semantic_error);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2021-01-28 19:23:54 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
target_ue->ran_ue_ngap_id = *RAN_UE_NGAP_ID;
|
|
|
|
|
|
|
|
source_ue = target_ue->source_ue;
|
|
|
|
if (!source_ue) {
|
|
|
|
ogs_error("Cannot find Source-UE Context [%lld]",
|
|
|
|
(long long)amf_ue_ngap_id);
|
2023-01-23 01:37:22 +00:00
|
|
|
r = ngap_send_error_indication(
|
2021-01-28 19:23:54 +00:00
|
|
|
gnb, &target_ue->ran_ue_ngap_id, &target_ue->amf_ue_ngap_id,
|
|
|
|
NGAP_Cause_PR_radioNetwork,
|
2023-01-23 01:37:22 +00:00
|
|
|
NGAP_CauseRadioNetwork_inconsistent_remote_UE_NGAP_ID);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2021-01-28 19:23:54 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
amf_ue = target_ue->amf_ue;
|
|
|
|
if (!amf_ue) {
|
|
|
|
ogs_error("Cannot find AMF-UE Context [%lld]",
|
|
|
|
(long long)amf_ue_ngap_id);
|
2023-01-23 01:37:22 +00:00
|
|
|
r = ngap_send_error_indication(
|
2021-01-28 19:23:54 +00:00
|
|
|
gnb, &target_ue->ran_ue_ngap_id, &target_ue->amf_ue_ngap_id,
|
|
|
|
NGAP_Cause_PR_radioNetwork,
|
2023-01-23 01:37:22 +00:00
|
|
|
NGAP_CauseRadioNetwork_unknown_local_UE_NGAP_ID);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2021-01-28 19:23:54 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
ogs_debug(" Source : RAN_UE_NGAP_ID[%d] AMF_UE_NGAP_ID[%lld] ",
|
|
|
|
source_ue->ran_ue_ngap_id, (long long)source_ue->amf_ue_ngap_id);
|
|
|
|
ogs_debug(" Target : RAN_UE_NGAP_ID[%d] AMF_UE_NGAP_ID[%lld] ",
|
|
|
|
target_ue->ran_ue_ngap_id, (long long)target_ue->amf_ue_ngap_id);
|
|
|
|
|
|
|
|
if (!PDUSessionList) {
|
|
|
|
ogs_error("No PDUSessionList");
|
2023-01-23 01:37:22 +00:00
|
|
|
r = ngap_send_error_indication2(amf_ue,
|
|
|
|
NGAP_Cause_PR_protocol, NGAP_CauseProtocol_semantic_error);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2021-01-28 19:23:54 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!TargetToSource_TransparentContainer) {
|
|
|
|
ogs_error("No TargetToSource_TransparentContainer");
|
2023-01-23 01:37:22 +00:00
|
|
|
r = ngap_send_error_indication2(amf_ue,
|
|
|
|
NGAP_Cause_PR_protocol, NGAP_CauseProtocol_semantic_error);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2021-01-28 19:23:54 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Store Container */
|
|
|
|
OGS_ASN_STORE_DATA(&amf_ue->handover.container,
|
|
|
|
TargetToSource_TransparentContainer);
|
|
|
|
|
|
|
|
for (i = 0; i < PDUSessionList->list.count; i++) {
|
|
|
|
amf_sess_t *sess = NULL;
|
|
|
|
PDUSessionItem = (NGAP_PDUSessionResourceAdmittedItem_t *)
|
|
|
|
PDUSessionList->list.array[i];
|
|
|
|
|
|
|
|
if (!PDUSessionItem) {
|
|
|
|
ogs_error("No PDUSessionResourceAdmittedItem");
|
2023-01-23 01:37:22 +00:00
|
|
|
r = ngap_send_error_indication2(amf_ue,
|
|
|
|
NGAP_Cause_PR_protocol, NGAP_CauseProtocol_semantic_error);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2021-01-28 19:23:54 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
transfer = &PDUSessionItem->handoverRequestAcknowledgeTransfer;
|
|
|
|
if (!transfer) {
|
|
|
|
ogs_error("No handoverRequestAcknowledgeTransfer");
|
2023-01-23 01:37:22 +00:00
|
|
|
r = ngap_send_error_indication2(amf_ue,
|
|
|
|
NGAP_Cause_PR_protocol, NGAP_CauseProtocol_semantic_error);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2021-01-28 19:23:54 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (PDUSessionItem->pDUSessionID ==
|
|
|
|
OGS_NAS_PDU_SESSION_IDENTITY_UNASSIGNED) {
|
|
|
|
ogs_error("PDU Session Identity is unassigned");
|
2023-01-23 01:37:22 +00:00
|
|
|
r = ngap_send_error_indication2(amf_ue,
|
|
|
|
NGAP_Cause_PR_protocol, NGAP_CauseProtocol_semantic_error);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2021-01-28 19:23:54 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
sess = amf_sess_find_by_psi(amf_ue, PDUSessionItem->pDUSessionID);
|
|
|
|
if (!sess) {
|
|
|
|
ogs_error("Cannot find PDU Session ID [%d]",
|
|
|
|
(int)PDUSessionItem->pDUSessionID);
|
2023-01-23 01:37:22 +00:00
|
|
|
r = ngap_send_error_indication2(amf_ue,
|
2021-01-28 19:23:54 +00:00
|
|
|
NGAP_Cause_PR_radioNetwork,
|
2023-01-23 01:37:22 +00:00
|
|
|
NGAP_CauseRadioNetwork_unknown_PDU_session_ID);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2021-01-28 19:23:54 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!SESSION_CONTEXT_IN_SMF(sess)) {
|
|
|
|
ogs_error("Session Context is not in SMF [%d]",
|
|
|
|
(int)PDUSessionItem->pDUSessionID);
|
2023-01-23 01:37:22 +00:00
|
|
|
r = ngap_send_error_indication2(amf_ue,
|
2021-01-28 19:23:54 +00:00
|
|
|
NGAP_Cause_PR_radioNetwork,
|
2023-01-23 01:37:22 +00:00
|
|
|
NGAP_CauseRadioNetwork_unknown_PDU_session_ID);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2021-01-28 19:23:54 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
memset(¶m, 0, sizeof(param));
|
|
|
|
param.n2smbuf = ogs_pkbuf_alloc(NULL, OGS_MAX_SDU_LEN);
|
|
|
|
ogs_assert(param.n2smbuf);
|
|
|
|
param.n2SmInfoType = OpenAPI_n2_sm_info_type_HANDOVER_REQ_ACK;
|
|
|
|
ogs_pkbuf_put_data(param.n2smbuf, transfer->buf, transfer->size);
|
|
|
|
|
|
|
|
param.hoState = OpenAPI_ho_state_PREPARED;
|
|
|
|
|
2023-01-31 10:38:17 +00:00
|
|
|
r = amf_sess_sbi_discover_and_send(
|
2022-08-26 15:12:22 +00:00
|
|
|
OGS_SBI_SERVICE_TYPE_NSMF_PDUSESSION, NULL,
|
2022-07-24 06:10:09 +00:00
|
|
|
amf_nsmf_pdusession_build_update_sm_context,
|
2023-01-31 10:38:17 +00:00
|
|
|
sess, AMF_UPDATE_SM_CONTEXT_HANDOVER_REQ_ACK, ¶m);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2021-01-28 19:23:54 +00:00
|
|
|
|
|
|
|
ogs_pkbuf_free(param.n2smbuf);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void ngap_handle_handover_failure(
|
|
|
|
amf_gnb_t *gnb, ogs_ngap_message_t *message)
|
|
|
|
{
|
|
|
|
char buf[OGS_ADDRSTRLEN];
|
2023-01-23 01:37:22 +00:00
|
|
|
int i, r;
|
2021-01-28 19:23:54 +00:00
|
|
|
|
|
|
|
ran_ue_t *source_ue = NULL, *target_ue = NULL;
|
|
|
|
uint64_t amf_ue_ngap_id;
|
|
|
|
|
|
|
|
NGAP_UnsuccessfulOutcome_t *unsuccessfulOutcome = NULL;
|
|
|
|
NGAP_HandoverFailure_t *HandoverFailure = NULL;
|
|
|
|
|
|
|
|
NGAP_HandoverFailureIEs_t *ie = NULL;
|
|
|
|
NGAP_AMF_UE_NGAP_ID_t *AMF_UE_NGAP_ID = NULL;
|
|
|
|
NGAP_Cause_t *Cause = NULL;
|
|
|
|
|
|
|
|
ogs_assert(gnb);
|
|
|
|
ogs_assert(gnb->sctp.sock);
|
|
|
|
|
|
|
|
ogs_assert(message);
|
|
|
|
unsuccessfulOutcome = message->choice.unsuccessfulOutcome;
|
|
|
|
ogs_assert(unsuccessfulOutcome);
|
|
|
|
HandoverFailure =
|
|
|
|
&unsuccessfulOutcome->value.choice.HandoverFailure;
|
|
|
|
ogs_assert(HandoverFailure);
|
|
|
|
|
2021-02-01 13:52:22 +00:00
|
|
|
ogs_debug("HandoverFailure");
|
2021-01-28 19:23:54 +00:00
|
|
|
|
|
|
|
for (i = 0; i < HandoverFailure->protocolIEs.list.count; i++) {
|
|
|
|
ie = HandoverFailure->protocolIEs.list.array[i];
|
|
|
|
switch (ie->id) {
|
|
|
|
case NGAP_ProtocolIE_ID_id_AMF_UE_NGAP_ID:
|
|
|
|
AMF_UE_NGAP_ID = &ie->value.choice.AMF_UE_NGAP_ID;
|
|
|
|
break;
|
|
|
|
case NGAP_ProtocolIE_ID_id_Cause:
|
|
|
|
Cause = &ie->value.choice.Cause;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
ogs_debug(" IP[%s] RAN_ID[%d]",
|
|
|
|
OGS_ADDR(gnb->sctp.addr, buf), gnb->gnb_id);
|
|
|
|
|
|
|
|
if (!AMF_UE_NGAP_ID) {
|
|
|
|
ogs_error("No AMF_UE_NGAP_ID");
|
2023-01-23 01:37:22 +00:00
|
|
|
r = ngap_send_error_indication(gnb, NULL, NULL,
|
|
|
|
NGAP_Cause_PR_protocol, NGAP_CauseProtocol_semantic_error);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2021-01-28 19:23:54 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (asn_INTEGER2ulong(AMF_UE_NGAP_ID,
|
|
|
|
(unsigned long *)&amf_ue_ngap_id) != 0) {
|
|
|
|
ogs_error("Invalid AMF_UE_NGAP_ID");
|
2023-01-23 01:37:22 +00:00
|
|
|
r = ngap_send_error_indication(gnb, NULL, NULL,
|
|
|
|
NGAP_Cause_PR_protocol, NGAP_CauseProtocol_semantic_error);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2021-01-28 19:23:54 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
target_ue = ran_ue_find_by_amf_ue_ngap_id(amf_ue_ngap_id);
|
|
|
|
if (!target_ue) {
|
|
|
|
ogs_error("No RAN UE Context : AMF_UE_NGAP_ID[%lld]",
|
|
|
|
(long long)amf_ue_ngap_id);
|
2023-01-23 01:37:22 +00:00
|
|
|
r = ngap_send_error_indication(
|
2021-01-28 19:23:54 +00:00
|
|
|
gnb, NULL, &amf_ue_ngap_id,
|
|
|
|
NGAP_Cause_PR_radioNetwork,
|
2023-01-23 01:37:22 +00:00
|
|
|
NGAP_CauseRadioNetwork_unknown_local_UE_NGAP_ID);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2021-01-28 19:23:54 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
source_ue = target_ue->source_ue;
|
|
|
|
if (!source_ue) {
|
|
|
|
ogs_error("Cannot find Source-UE Context [%lld]",
|
|
|
|
(long long)amf_ue_ngap_id);
|
2023-01-23 01:37:22 +00:00
|
|
|
r = ngap_send_error_indication(
|
2021-01-28 19:23:54 +00:00
|
|
|
gnb, &target_ue->ran_ue_ngap_id, &target_ue->amf_ue_ngap_id,
|
|
|
|
NGAP_Cause_PR_radioNetwork,
|
2023-01-23 01:37:22 +00:00
|
|
|
NGAP_CauseRadioNetwork_inconsistent_remote_UE_NGAP_ID);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2021-01-28 19:23:54 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
ogs_debug(" Source : RAN_UE_NGAP_ID[%d] AMF_UE_NGAP_ID[%lld] ",
|
|
|
|
source_ue->ran_ue_ngap_id, (long long)source_ue->amf_ue_ngap_id);
|
|
|
|
ogs_debug(" Target : RAN_UE_NGAP_ID[%d] AMF_UE_NGAP_ID[%lld] ",
|
|
|
|
target_ue->ran_ue_ngap_id, (long long)target_ue->amf_ue_ngap_id);
|
|
|
|
|
|
|
|
if (!Cause) {
|
|
|
|
ogs_error("No Cause");
|
2023-01-23 01:37:22 +00:00
|
|
|
r = ngap_send_error_indication(
|
2021-01-28 19:23:54 +00:00
|
|
|
gnb, &target_ue->ran_ue_ngap_id, &target_ue->amf_ue_ngap_id,
|
2023-01-23 01:37:22 +00:00
|
|
|
NGAP_Cause_PR_protocol, NGAP_CauseProtocol_semantic_error);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2021-01-28 19:23:54 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
ogs_debug(" Cause[Group:%d Cause:%d]",
|
|
|
|
Cause->present, (int)Cause->choice.radioNetwork);
|
|
|
|
|
2023-01-23 01:37:22 +00:00
|
|
|
r = ngap_send_handover_preparation_failure(source_ue, Cause);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2021-01-28 19:23:54 +00:00
|
|
|
|
2023-01-23 01:37:22 +00:00
|
|
|
r = ngap_send_ran_ue_context_release_command(target_ue,
|
2021-01-28 19:23:54 +00:00
|
|
|
NGAP_Cause_PR_radioNetwork, NGAP_CauseRadioNetwork_ho_failure_in_target_5GC_ngran_node_or_target_system,
|
2023-01-23 01:37:22 +00:00
|
|
|
NGAP_UE_CTX_REL_NG_HANDOVER_FAILURE, 0);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2021-01-28 19:23:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void ngap_handle_handover_cancel(
|
|
|
|
amf_gnb_t *gnb, ogs_ngap_message_t *message)
|
|
|
|
{
|
|
|
|
char buf[OGS_ADDRSTRLEN];
|
2023-01-23 01:37:22 +00:00
|
|
|
int i, r;
|
2021-01-28 19:23:54 +00:00
|
|
|
|
|
|
|
amf_ue_t *amf_ue = NULL;
|
|
|
|
amf_sess_t *sess = NULL;
|
|
|
|
ran_ue_t *source_ue = NULL, *target_ue = NULL;
|
|
|
|
uint64_t amf_ue_ngap_id;
|
2021-05-29 06:56:12 +00:00
|
|
|
amf_nsmf_pdusession_sm_context_param_t param;
|
2021-01-28 19:23:54 +00:00
|
|
|
|
|
|
|
NGAP_InitiatingMessage_t *initiatingMessage = NULL;
|
|
|
|
NGAP_HandoverCancel_t *HandoverCancel = NULL;
|
|
|
|
|
|
|
|
NGAP_HandoverCancelIEs_t *ie = NULL;
|
|
|
|
NGAP_RAN_UE_NGAP_ID_t *RAN_UE_NGAP_ID = NULL;
|
|
|
|
NGAP_AMF_UE_NGAP_ID_t *AMF_UE_NGAP_ID = NULL;
|
|
|
|
NGAP_Cause_t *Cause = NULL;
|
|
|
|
|
|
|
|
ogs_assert(gnb);
|
|
|
|
ogs_assert(gnb->sctp.sock);
|
|
|
|
|
|
|
|
ogs_assert(message);
|
|
|
|
initiatingMessage = message->choice.initiatingMessage;
|
|
|
|
ogs_assert(initiatingMessage);
|
|
|
|
HandoverCancel = &initiatingMessage->value.choice.HandoverCancel;
|
|
|
|
ogs_assert(HandoverCancel);
|
|
|
|
|
2021-02-01 13:52:22 +00:00
|
|
|
ogs_debug("HandoverCancel");
|
2021-01-28 19:23:54 +00:00
|
|
|
|
|
|
|
for (i = 0; i < HandoverCancel->protocolIEs.list.count; i++) {
|
|
|
|
ie = HandoverCancel->protocolIEs.list.array[i];
|
|
|
|
switch (ie->id) {
|
|
|
|
case NGAP_ProtocolIE_ID_id_RAN_UE_NGAP_ID:
|
|
|
|
RAN_UE_NGAP_ID = &ie->value.choice.RAN_UE_NGAP_ID;
|
|
|
|
break;
|
|
|
|
case NGAP_ProtocolIE_ID_id_AMF_UE_NGAP_ID:
|
|
|
|
AMF_UE_NGAP_ID = &ie->value.choice.AMF_UE_NGAP_ID;
|
|
|
|
break;
|
|
|
|
case NGAP_ProtocolIE_ID_id_Cause:
|
|
|
|
Cause = &ie->value.choice.Cause;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
ogs_debug(" IP[%s] RAN_ID[%d]",
|
|
|
|
OGS_ADDR(gnb->sctp.addr, buf), gnb->gnb_id);
|
|
|
|
|
|
|
|
if (!AMF_UE_NGAP_ID) {
|
|
|
|
ogs_error("No AMF_UE_NGAP_ID");
|
2023-01-23 01:37:22 +00:00
|
|
|
r = ngap_send_error_indication(gnb, (uint32_t *)RAN_UE_NGAP_ID, NULL,
|
|
|
|
NGAP_Cause_PR_protocol, NGAP_CauseProtocol_semantic_error);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2021-01-28 19:23:54 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (asn_INTEGER2ulong(AMF_UE_NGAP_ID,
|
|
|
|
(unsigned long *)&amf_ue_ngap_id) != 0) {
|
|
|
|
ogs_error("Invalid AMF_UE_NGAP_ID");
|
2023-01-23 01:37:22 +00:00
|
|
|
r = ngap_send_error_indication(gnb, (uint32_t *)RAN_UE_NGAP_ID, NULL,
|
|
|
|
NGAP_Cause_PR_protocol, NGAP_CauseProtocol_semantic_error);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2021-01-28 19:23:54 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
source_ue = ran_ue_find_by_amf_ue_ngap_id(amf_ue_ngap_id);
|
|
|
|
if (!source_ue) {
|
|
|
|
ogs_error("No RAN UE Context : AMF_UE_NGAP_ID[%lld]",
|
|
|
|
(long long)amf_ue_ngap_id);
|
2023-01-23 01:37:22 +00:00
|
|
|
r = ngap_send_error_indication(
|
2021-01-28 19:23:54 +00:00
|
|
|
gnb, (uint32_t *)RAN_UE_NGAP_ID, &amf_ue_ngap_id,
|
|
|
|
NGAP_Cause_PR_radioNetwork,
|
2023-01-23 01:37:22 +00:00
|
|
|
NGAP_CauseRadioNetwork_unknown_local_UE_NGAP_ID);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2021-01-28 19:23:54 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
target_ue = source_ue->target_ue;
|
|
|
|
if (!target_ue) {
|
|
|
|
ogs_error("Cannot find Source-UE Context [%lld]",
|
|
|
|
(long long)amf_ue_ngap_id);
|
2023-01-23 01:37:22 +00:00
|
|
|
r = ngap_send_error_indication(
|
2021-01-28 19:23:54 +00:00
|
|
|
gnb, &source_ue->ran_ue_ngap_id, &source_ue->amf_ue_ngap_id,
|
|
|
|
NGAP_Cause_PR_radioNetwork,
|
2023-01-23 01:37:22 +00:00
|
|
|
NGAP_CauseRadioNetwork_inconsistent_remote_UE_NGAP_ID);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2021-01-28 19:23:54 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
amf_ue = source_ue->amf_ue;
|
|
|
|
if (!amf_ue) {
|
|
|
|
ogs_error("Cannot find AMF-UE Context [%lld]",
|
|
|
|
(long long)amf_ue_ngap_id);
|
2023-01-23 01:37:22 +00:00
|
|
|
r = ngap_send_error_indication(
|
2021-01-28 19:23:54 +00:00
|
|
|
gnb, &source_ue->ran_ue_ngap_id, &source_ue->amf_ue_ngap_id,
|
|
|
|
NGAP_Cause_PR_radioNetwork,
|
2023-01-23 01:37:22 +00:00
|
|
|
NGAP_CauseRadioNetwork_unknown_local_UE_NGAP_ID);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2021-01-28 19:23:54 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
ogs_debug(" Source : RAN_UE_NGAP_ID[%d] AMF_UE_NGAP_ID[%lld] ",
|
|
|
|
source_ue->ran_ue_ngap_id, (long long)source_ue->amf_ue_ngap_id);
|
|
|
|
ogs_debug(" Target : RAN_UE_NGAP_ID[%d] AMF_UE_NGAP_ID[%lld] ",
|
|
|
|
target_ue->ran_ue_ngap_id, (long long)target_ue->amf_ue_ngap_id);
|
|
|
|
|
|
|
|
if (!Cause) {
|
|
|
|
ogs_error("No Cause");
|
2023-01-23 01:37:22 +00:00
|
|
|
r = ngap_send_error_indication(
|
2021-01-28 19:23:54 +00:00
|
|
|
gnb, &source_ue->ran_ue_ngap_id, &source_ue->amf_ue_ngap_id,
|
2023-01-23 01:37:22 +00:00
|
|
|
NGAP_Cause_PR_protocol, NGAP_CauseProtocol_semantic_error);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2021-01-28 19:23:54 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
ogs_debug(" Cause[Group:%d Cause:%d]",
|
|
|
|
Cause->present, (int)Cause->choice.radioNetwork);
|
|
|
|
|
|
|
|
ogs_list_for_each(&amf_ue->sess_list, sess) {
|
|
|
|
memset(¶m, 0, sizeof(param));
|
|
|
|
param.hoState = OpenAPI_ho_state_CANCELLED;
|
|
|
|
param.ngApCause.group = Cause->present;
|
|
|
|
param.ngApCause.value = (int)Cause->choice.radioNetwork;
|
|
|
|
|
2023-01-31 10:38:17 +00:00
|
|
|
r = amf_sess_sbi_discover_and_send(
|
2022-08-26 15:12:22 +00:00
|
|
|
OGS_SBI_SERVICE_TYPE_NSMF_PDUSESSION, NULL,
|
2022-07-24 06:10:09 +00:00
|
|
|
amf_nsmf_pdusession_build_update_sm_context,
|
2023-01-31 10:38:17 +00:00
|
|
|
sess, AMF_UPDATE_SM_CONTEXT_HANDOVER_CANCEL, ¶m);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2021-01-28 19:23:54 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void ngap_handle_uplink_ran_status_transfer(
|
|
|
|
amf_gnb_t *gnb, ogs_ngap_message_t *message)
|
|
|
|
{
|
|
|
|
char buf[OGS_ADDRSTRLEN];
|
2023-01-23 01:37:22 +00:00
|
|
|
int i, r;
|
2021-01-28 19:23:54 +00:00
|
|
|
|
|
|
|
amf_ue_t *amf_ue = NULL;
|
|
|
|
ran_ue_t *source_ue = NULL, *target_ue = NULL;
|
|
|
|
uint64_t amf_ue_ngap_id;
|
|
|
|
|
|
|
|
NGAP_InitiatingMessage_t *initiatingMessage = NULL;
|
|
|
|
NGAP_UplinkRANStatusTransfer_t *UplinkRANStatusTransfer = NULL;
|
|
|
|
|
|
|
|
NGAP_UplinkRANStatusTransferIEs_t *ie = NULL;
|
|
|
|
NGAP_RAN_UE_NGAP_ID_t *RAN_UE_NGAP_ID = NULL;
|
|
|
|
NGAP_AMF_UE_NGAP_ID_t *AMF_UE_NGAP_ID = NULL;
|
|
|
|
NGAP_RANStatusTransfer_TransparentContainer_t
|
|
|
|
*RANStatusTransfer_TransparentContainer = NULL;
|
|
|
|
|
|
|
|
ogs_assert(gnb);
|
|
|
|
ogs_assert(gnb->sctp.sock);
|
|
|
|
|
|
|
|
ogs_assert(message);
|
|
|
|
initiatingMessage = message->choice.initiatingMessage;
|
|
|
|
ogs_assert(initiatingMessage);
|
|
|
|
UplinkRANStatusTransfer =
|
|
|
|
&initiatingMessage->value.choice.UplinkRANStatusTransfer;
|
|
|
|
ogs_assert(UplinkRANStatusTransfer);
|
|
|
|
|
2021-02-01 13:52:22 +00:00
|
|
|
ogs_debug("UplinkRANStatusTransfer");
|
2021-01-28 19:23:54 +00:00
|
|
|
|
|
|
|
for (i = 0; i < UplinkRANStatusTransfer->protocolIEs.list.count; i++) {
|
|
|
|
ie = UplinkRANStatusTransfer->protocolIEs.list.array[i];
|
|
|
|
switch (ie->id) {
|
|
|
|
case NGAP_ProtocolIE_ID_id_RAN_UE_NGAP_ID:
|
|
|
|
RAN_UE_NGAP_ID = &ie->value.choice.RAN_UE_NGAP_ID;
|
|
|
|
break;
|
|
|
|
case NGAP_ProtocolIE_ID_id_AMF_UE_NGAP_ID:
|
|
|
|
AMF_UE_NGAP_ID = &ie->value.choice.AMF_UE_NGAP_ID;
|
|
|
|
break;
|
|
|
|
case NGAP_ProtocolIE_ID_id_RANStatusTransfer_TransparentContainer:
|
|
|
|
RANStatusTransfer_TransparentContainer =
|
|
|
|
&ie->value.choice.RANStatusTransfer_TransparentContainer;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
ogs_debug(" IP[%s] RAN_ID[%d]",
|
|
|
|
OGS_ADDR(gnb->sctp.addr, buf), gnb->gnb_id);
|
|
|
|
|
|
|
|
if (!AMF_UE_NGAP_ID) {
|
|
|
|
ogs_error("No AMF_UE_NGAP_ID");
|
2023-01-23 01:37:22 +00:00
|
|
|
r = ngap_send_error_indication(gnb, (uint32_t *)RAN_UE_NGAP_ID, NULL,
|
|
|
|
NGAP_Cause_PR_protocol, NGAP_CauseProtocol_semantic_error);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2021-01-28 19:23:54 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (asn_INTEGER2ulong(AMF_UE_NGAP_ID,
|
|
|
|
(unsigned long *)&amf_ue_ngap_id) != 0) {
|
|
|
|
ogs_error("Invalid AMF_UE_NGAP_ID");
|
2023-01-23 01:37:22 +00:00
|
|
|
r = ngap_send_error_indication(gnb, (uint32_t *)RAN_UE_NGAP_ID, NULL,
|
|
|
|
NGAP_Cause_PR_protocol, NGAP_CauseProtocol_semantic_error);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2021-01-28 19:23:54 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
source_ue = ran_ue_find_by_amf_ue_ngap_id(amf_ue_ngap_id);
|
|
|
|
if (!source_ue) {
|
|
|
|
ogs_error("No RAN UE Context : AMF_UE_NGAP_ID[%lld]",
|
|
|
|
(long long)amf_ue_ngap_id);
|
2023-01-23 01:37:22 +00:00
|
|
|
r = ngap_send_error_indication(
|
2021-01-28 19:23:54 +00:00
|
|
|
gnb, (uint32_t *)RAN_UE_NGAP_ID, &amf_ue_ngap_id,
|
|
|
|
NGAP_Cause_PR_radioNetwork,
|
2023-01-23 01:37:22 +00:00
|
|
|
NGAP_CauseRadioNetwork_unknown_local_UE_NGAP_ID);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2021-01-28 19:23:54 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
target_ue = source_ue->target_ue;
|
|
|
|
if (!target_ue) {
|
|
|
|
ogs_error("Cannot find Source-UE Context [%lld]",
|
|
|
|
(long long)amf_ue_ngap_id);
|
2023-01-23 01:37:22 +00:00
|
|
|
r = ngap_send_error_indication(
|
2021-01-28 19:23:54 +00:00
|
|
|
gnb, &source_ue->ran_ue_ngap_id, &source_ue->amf_ue_ngap_id,
|
|
|
|
NGAP_Cause_PR_radioNetwork,
|
2023-01-23 01:37:22 +00:00
|
|
|
NGAP_CauseRadioNetwork_inconsistent_remote_UE_NGAP_ID);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2021-01-28 19:23:54 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
amf_ue = source_ue->amf_ue;
|
|
|
|
if (!amf_ue) {
|
|
|
|
ogs_error("Cannot find AMF-UE Context [%lld]",
|
|
|
|
(long long)amf_ue_ngap_id);
|
2023-01-23 01:37:22 +00:00
|
|
|
r = ngap_send_error_indication(
|
2021-01-28 19:23:54 +00:00
|
|
|
gnb, &source_ue->ran_ue_ngap_id, &source_ue->amf_ue_ngap_id,
|
|
|
|
NGAP_Cause_PR_radioNetwork,
|
2023-01-23 01:37:22 +00:00
|
|
|
NGAP_CauseRadioNetwork_unknown_local_UE_NGAP_ID);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2021-01-28 19:23:54 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
ogs_debug(" Source : RAN_UE_NGAP_ID[%d] AMF_UE_NGAP_ID[%lld] ",
|
|
|
|
source_ue->ran_ue_ngap_id, (long long)source_ue->amf_ue_ngap_id);
|
|
|
|
ogs_debug(" Target : RAN_UE_NGAP_ID[%d] AMF_UE_NGAP_ID[%lld] ",
|
|
|
|
target_ue->ran_ue_ngap_id, (long long)target_ue->amf_ue_ngap_id);
|
|
|
|
|
2023-01-23 01:37:22 +00:00
|
|
|
r = ngap_send_downlink_ran_status_transfer(
|
|
|
|
target_ue, RANStatusTransfer_TransparentContainer);
|
|
|
|
ogs_expect(r == OGS_OK);
|
2023-01-25 14:16:59 +00:00
|
|
|
/* ogs_asn_copy_ie() could be failed from received packet.
|
|
|
|
* So we should not use ogs_assert(r != OGS_ERROR).*/
|
2021-01-28 19:23:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void ngap_handle_handover_notification(
|
|
|
|
amf_gnb_t *gnb, ogs_ngap_message_t *message)
|
|
|
|
{
|
|
|
|
char buf[OGS_ADDRSTRLEN];
|
2023-01-23 01:37:22 +00:00
|
|
|
int i, r;
|
2021-01-28 19:23:54 +00:00
|
|
|
|
|
|
|
amf_ue_t *amf_ue = NULL;
|
|
|
|
amf_sess_t *sess = NULL;
|
|
|
|
ran_ue_t *source_ue = NULL, *target_ue = NULL;
|
|
|
|
uint64_t amf_ue_ngap_id;
|
2021-05-29 06:56:12 +00:00
|
|
|
amf_nsmf_pdusession_sm_context_param_t param;
|
2021-01-28 19:23:54 +00:00
|
|
|
|
|
|
|
NGAP_InitiatingMessage_t *initiatingMessage = NULL;
|
|
|
|
NGAP_HandoverNotify_t *HandoverNotify = NULL;
|
|
|
|
|
|
|
|
NGAP_HandoverNotifyIEs_t *ie = NULL;
|
|
|
|
NGAP_RAN_UE_NGAP_ID_t *RAN_UE_NGAP_ID = NULL;
|
|
|
|
NGAP_AMF_UE_NGAP_ID_t *AMF_UE_NGAP_ID = NULL;
|
|
|
|
NGAP_UserLocationInformation_t *UserLocationInformation = NULL;
|
|
|
|
NGAP_UserLocationInformationNR_t *UserLocationInformationNR = NULL;
|
|
|
|
|
|
|
|
ogs_assert(gnb);
|
|
|
|
ogs_assert(gnb->sctp.sock);
|
|
|
|
|
|
|
|
ogs_assert(message);
|
|
|
|
initiatingMessage = message->choice.initiatingMessage;
|
|
|
|
ogs_assert(initiatingMessage);
|
|
|
|
HandoverNotify = &initiatingMessage->value.choice.HandoverNotify;
|
|
|
|
ogs_assert(HandoverNotify);
|
|
|
|
|
2021-02-01 13:52:22 +00:00
|
|
|
ogs_debug("HandoverNotify");
|
2021-01-28 19:23:54 +00:00
|
|
|
|
|
|
|
for (i = 0; i < HandoverNotify->protocolIEs.list.count; i++) {
|
|
|
|
ie = HandoverNotify->protocolIEs.list.array[i];
|
|
|
|
switch (ie->id) {
|
|
|
|
case NGAP_ProtocolIE_ID_id_RAN_UE_NGAP_ID:
|
|
|
|
RAN_UE_NGAP_ID = &ie->value.choice.RAN_UE_NGAP_ID;
|
|
|
|
break;
|
|
|
|
case NGAP_ProtocolIE_ID_id_AMF_UE_NGAP_ID:
|
|
|
|
AMF_UE_NGAP_ID = &ie->value.choice.AMF_UE_NGAP_ID;
|
|
|
|
break;
|
|
|
|
case NGAP_ProtocolIE_ID_id_UserLocationInformation:
|
|
|
|
UserLocationInformation = &ie->value.choice.UserLocationInformation;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
ogs_debug(" IP[%s] RAN_ID[%d]",
|
|
|
|
OGS_ADDR(gnb->sctp.addr, buf), gnb->gnb_id);
|
|
|
|
|
|
|
|
if (!AMF_UE_NGAP_ID) {
|
|
|
|
ogs_error("No AMF_UE_NGAP_ID");
|
2023-01-23 01:37:22 +00:00
|
|
|
r = ngap_send_error_indication(gnb, (uint32_t *)RAN_UE_NGAP_ID, NULL,
|
|
|
|
NGAP_Cause_PR_protocol, NGAP_CauseProtocol_semantic_error);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2021-01-28 19:23:54 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (asn_INTEGER2ulong(AMF_UE_NGAP_ID,
|
|
|
|
(unsigned long *)&amf_ue_ngap_id) != 0) {
|
|
|
|
ogs_error("Invalid AMF_UE_NGAP_ID");
|
2023-01-23 01:37:22 +00:00
|
|
|
r = ngap_send_error_indication(gnb, (uint32_t *)RAN_UE_NGAP_ID, NULL,
|
|
|
|
NGAP_Cause_PR_protocol, NGAP_CauseProtocol_semantic_error);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2021-01-28 19:23:54 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
target_ue = ran_ue_find_by_amf_ue_ngap_id(amf_ue_ngap_id);
|
|
|
|
if (!target_ue) {
|
|
|
|
ogs_error("No RAN UE Context : AMF_UE_NGAP_ID[%lld]",
|
|
|
|
(long long)amf_ue_ngap_id);
|
2023-01-23 01:37:22 +00:00
|
|
|
r = ngap_send_error_indication(
|
2021-01-28 19:23:54 +00:00
|
|
|
gnb, (uint32_t *)RAN_UE_NGAP_ID, &amf_ue_ngap_id,
|
|
|
|
NGAP_Cause_PR_radioNetwork,
|
2023-01-23 01:37:22 +00:00
|
|
|
NGAP_CauseRadioNetwork_unknown_local_UE_NGAP_ID);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2021-01-28 19:23:54 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
source_ue = target_ue->source_ue;
|
|
|
|
if (!source_ue) {
|
|
|
|
ogs_error("Cannot find Source-UE Context [%lld]",
|
|
|
|
(long long)amf_ue_ngap_id);
|
2023-01-23 01:37:22 +00:00
|
|
|
r = ngap_send_error_indication(
|
2021-01-28 19:23:54 +00:00
|
|
|
gnb, &target_ue->ran_ue_ngap_id, &target_ue->amf_ue_ngap_id,
|
|
|
|
NGAP_Cause_PR_radioNetwork,
|
2023-01-23 01:37:22 +00:00
|
|
|
NGAP_CauseRadioNetwork_inconsistent_remote_UE_NGAP_ID);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2021-01-28 19:23:54 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
amf_ue = target_ue->amf_ue;
|
|
|
|
if (!amf_ue) {
|
|
|
|
ogs_error("Cannot find AMF-UE Context [%lld]",
|
|
|
|
(long long)amf_ue_ngap_id);
|
2023-01-23 01:37:22 +00:00
|
|
|
r = ngap_send_error_indication(
|
2021-01-28 19:23:54 +00:00
|
|
|
gnb, &target_ue->ran_ue_ngap_id, &target_ue->amf_ue_ngap_id,
|
|
|
|
NGAP_Cause_PR_radioNetwork,
|
2023-01-23 01:37:22 +00:00
|
|
|
NGAP_CauseRadioNetwork_unknown_local_UE_NGAP_ID);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2021-01-28 19:23:54 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
amf_ue_associate_ran_ue(amf_ue, target_ue);
|
|
|
|
|
|
|
|
if (!UserLocationInformation) {
|
|
|
|
ogs_error("No UserLocationInformation");
|
2023-01-23 01:37:22 +00:00
|
|
|
r = ngap_send_error_indication(gnb, &target_ue->ran_ue_ngap_id, NULL,
|
|
|
|
NGAP_Cause_PR_protocol, NGAP_CauseProtocol_semantic_error);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2021-01-28 19:23:54 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (UserLocationInformation->present !=
|
|
|
|
NGAP_UserLocationInformation_PR_userLocationInformationNR) {
|
|
|
|
ogs_error("Not implemented UserLocationInformation[%d]",
|
|
|
|
UserLocationInformation->present);
|
2023-01-23 01:37:22 +00:00
|
|
|
r = ngap_send_error_indication(gnb, &target_ue->ran_ue_ngap_id, NULL,
|
|
|
|
NGAP_Cause_PR_protocol, NGAP_CauseProtocol_unspecified);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2021-01-28 19:23:54 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
UserLocationInformationNR =
|
|
|
|
UserLocationInformation->choice.userLocationInformationNR;
|
|
|
|
ogs_assert(UserLocationInformationNR);
|
|
|
|
ogs_ngap_ASN_to_nr_cgi(
|
|
|
|
&UserLocationInformationNR->nR_CGI, &target_ue->saved.nr_cgi);
|
|
|
|
ogs_ngap_ASN_to_5gs_tai(
|
2021-03-08 12:25:09 +00:00
|
|
|
&UserLocationInformationNR->tAI, &target_ue->saved.nr_tai);
|
2021-01-28 19:23:54 +00:00
|
|
|
|
|
|
|
ogs_debug(" Source : RAN_UE_NGAP_ID[%d] AMF_UE_NGAP_ID[%lld] ",
|
|
|
|
source_ue->ran_ue_ngap_id, (long long)source_ue->amf_ue_ngap_id);
|
|
|
|
ogs_debug(" Source : TAC[%d] CellID[0x%llx]",
|
2021-03-08 12:25:09 +00:00
|
|
|
source_ue->saved.nr_tai.tac.v,
|
|
|
|
(long long)source_ue->saved.nr_cgi.cell_id);
|
2021-01-28 19:23:54 +00:00
|
|
|
ogs_debug(" Target : RAN_UE_NGAP_ID[%d] AMF_UE_NGAP_ID[%lld] ",
|
|
|
|
target_ue->ran_ue_ngap_id, (long long)target_ue->amf_ue_ngap_id);
|
|
|
|
ogs_debug(" Target : TAC[%d] CellID[0x%llx]",
|
2021-03-08 12:25:09 +00:00
|
|
|
target_ue->saved.nr_tai.tac.v,
|
|
|
|
(long long)target_ue->saved.nr_cgi.cell_id);
|
2021-01-28 19:23:54 +00:00
|
|
|
|
|
|
|
/* Copy Stream-No/TAI/ECGI from ran_ue */
|
|
|
|
amf_ue->gnb_ostream_id = target_ue->gnb_ostream_id;
|
2021-03-08 12:25:09 +00:00
|
|
|
memcpy(&amf_ue->nr_tai, &target_ue->saved.nr_tai, sizeof(ogs_5gs_tai_t));
|
2021-01-28 19:23:54 +00:00
|
|
|
memcpy(&amf_ue->nr_cgi, &target_ue->saved.nr_cgi, sizeof(ogs_nr_cgi_t));
|
|
|
|
|
2023-01-23 01:37:22 +00:00
|
|
|
r = ngap_send_ran_ue_context_release_command(source_ue,
|
2021-02-01 04:01:15 +00:00
|
|
|
NGAP_Cause_PR_radioNetwork,
|
|
|
|
NGAP_CauseRadioNetwork_successful_handover,
|
|
|
|
NGAP_UE_CTX_REL_NG_HANDOVER_COMPLETE,
|
2023-01-23 01:37:22 +00:00
|
|
|
ogs_app()->time.handover.duration);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2021-02-01 04:01:15 +00:00
|
|
|
|
2021-01-28 19:23:54 +00:00
|
|
|
ogs_list_for_each(&amf_ue->sess_list, sess) {
|
|
|
|
memset(¶m, 0, sizeof(param));
|
|
|
|
param.hoState = OpenAPI_ho_state_COMPLETED;
|
|
|
|
|
2023-01-31 10:38:17 +00:00
|
|
|
r = amf_sess_sbi_discover_and_send(
|
2022-08-26 15:12:22 +00:00
|
|
|
OGS_SBI_SERVICE_TYPE_NSMF_PDUSESSION, NULL,
|
2022-07-24 06:10:09 +00:00
|
|
|
amf_nsmf_pdusession_build_update_sm_context,
|
2023-01-31 10:38:17 +00:00
|
|
|
sess, AMF_UPDATE_SM_CONTEXT_HANDOVER_NOTIFY, ¶m);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2021-01-28 19:23:54 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-04-16 07:26:13 +00:00
|
|
|
void ngap_handle_ran_configuration_update(
|
|
|
|
amf_gnb_t *gnb, ogs_ngap_message_t *message)
|
|
|
|
{
|
|
|
|
char buf[OGS_ADDRSTRLEN];
|
2023-01-23 01:37:22 +00:00
|
|
|
int i, j, k, r;
|
2021-04-16 07:26:13 +00:00
|
|
|
|
|
|
|
NGAP_InitiatingMessage_t *initiatingMessage = NULL;
|
|
|
|
NGAP_RANConfigurationUpdate_t *RANConfigurationUpdate = NULL;
|
|
|
|
|
|
|
|
NGAP_RANConfigurationUpdateIEs_t *ie = NULL;
|
|
|
|
NGAP_GlobalRANNodeID_t *GlobalRANNodeID = NULL;
|
|
|
|
NGAP_GlobalGNB_ID_t *globalGNB_ID = NULL;
|
|
|
|
NGAP_SupportedTAList_t *SupportedTAList = NULL;
|
|
|
|
NGAP_PagingDRX_t *PagingDRX = NULL;
|
|
|
|
|
|
|
|
NGAP_Cause_PR group = NGAP_Cause_PR_NOTHING;
|
|
|
|
long cause = 0;
|
|
|
|
|
|
|
|
uint32_t gnb_id;
|
|
|
|
|
|
|
|
ogs_assert(gnb);
|
|
|
|
ogs_assert(gnb->sctp.sock);
|
|
|
|
|
|
|
|
ogs_assert(message);
|
|
|
|
initiatingMessage = message->choice.initiatingMessage;
|
|
|
|
ogs_assert(initiatingMessage);
|
|
|
|
RANConfigurationUpdate = &initiatingMessage->value.choice.RANConfigurationUpdate;
|
|
|
|
ogs_assert(RANConfigurationUpdate);
|
|
|
|
|
|
|
|
ogs_debug("RANConfigurationUpdate");
|
|
|
|
|
|
|
|
for (i = 0; i < RANConfigurationUpdate->protocolIEs.list.count; i++) {
|
|
|
|
ie = RANConfigurationUpdate->protocolIEs.list.array[i];
|
|
|
|
switch (ie->id) {
|
|
|
|
case NGAP_ProtocolIE_ID_id_GlobalRANNodeID:
|
|
|
|
GlobalRANNodeID = &ie->value.choice.GlobalRANNodeID;
|
|
|
|
break;
|
|
|
|
case NGAP_ProtocolIE_ID_id_SupportedTAList:
|
|
|
|
SupportedTAList = &ie->value.choice.SupportedTAList;
|
|
|
|
break;
|
|
|
|
case NGAP_ProtocolIE_ID_id_DefaultPagingDRX:
|
|
|
|
PagingDRX = &ie->value.choice.PagingDRX;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (GlobalRANNodeID) {
|
|
|
|
globalGNB_ID = GlobalRANNodeID->choice.globalGNB_ID;
|
|
|
|
if (!globalGNB_ID) {
|
|
|
|
ogs_error("No globalGNB_ID");
|
|
|
|
group = NGAP_Cause_PR_protocol;
|
|
|
|
cause = NGAP_CauseProtocol_semantic_error;
|
2023-01-23 01:37:22 +00:00
|
|
|
r = ngap_send_ran_configuration_update_failure(gnb, group, cause);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2021-04-16 07:26:13 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
ogs_ngap_GNB_ID_to_uint32(&globalGNB_ID->gNB_ID, &gnb_id);
|
|
|
|
ogs_debug(" IP[%s] GNB_ID[0x%x]",
|
|
|
|
OGS_ADDR(gnb->sctp.addr, buf), gnb_id);
|
|
|
|
|
|
|
|
amf_gnb_set_gnb_id(gnb, gnb_id);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (SupportedTAList) {
|
|
|
|
/* Parse Supported TA */
|
|
|
|
for (i = 0, gnb->num_of_supported_ta_list = 0;
|
|
|
|
i < SupportedTAList->list.count &&
|
|
|
|
gnb->num_of_supported_ta_list < OGS_MAX_NUM_OF_TAI;
|
|
|
|
i++) {
|
|
|
|
NGAP_SupportedTAItem_t *SupportedTAItem = NULL;
|
|
|
|
|
|
|
|
SupportedTAItem = (NGAP_SupportedTAItem_t *)
|
|
|
|
SupportedTAList->list.array[i];
|
|
|
|
if (!SupportedTAItem) {
|
|
|
|
ogs_error("No SupportedTAItem");
|
|
|
|
group = NGAP_Cause_PR_protocol;
|
|
|
|
cause = NGAP_CauseProtocol_semantic_error;
|
2023-01-23 01:37:22 +00:00
|
|
|
r = ngap_send_ran_configuration_update_failure(
|
|
|
|
gnb, group, cause);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2021-04-16 07:26:13 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
ogs_asn_OCTET_STRING_to_uint24(&SupportedTAItem->tAC,
|
|
|
|
&gnb->supported_ta_list[i].tac);
|
|
|
|
|
|
|
|
ogs_debug(" TAC[%d]", gnb->supported_ta_list[i].tac.v);
|
|
|
|
|
|
|
|
for (j = 0, gnb->supported_ta_list[i].num_of_bplmn_list = 0;
|
|
|
|
j < SupportedTAItem->broadcastPLMNList.list.count &&
|
|
|
|
gnb->supported_ta_list[i].num_of_bplmn_list <
|
|
|
|
OGS_MAX_NUM_OF_BPLMN;
|
|
|
|
j++) {
|
|
|
|
|
|
|
|
NGAP_BroadcastPLMNItem_t *BroadcastPLMNItem = NULL;
|
|
|
|
NGAP_PLMNIdentity_t *pLMNIdentity = NULL;
|
|
|
|
|
|
|
|
BroadcastPLMNItem = (NGAP_BroadcastPLMNItem_t *)
|
|
|
|
SupportedTAItem->broadcastPLMNList.list.array[j];
|
|
|
|
if (!BroadcastPLMNItem) {
|
|
|
|
ogs_error("No BroadcastPLMNItem");
|
|
|
|
group = NGAP_Cause_PR_protocol;
|
|
|
|
cause = NGAP_CauseProtocol_semantic_error;
|
2023-01-23 01:37:22 +00:00
|
|
|
r = ngap_send_ran_configuration_update_failure(
|
|
|
|
gnb, group, cause);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2021-04-16 07:26:13 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
pLMNIdentity = (NGAP_PLMNIdentity_t *)
|
|
|
|
&BroadcastPLMNItem->pLMNIdentity;
|
|
|
|
ogs_assert(pLMNIdentity);
|
|
|
|
|
|
|
|
memcpy(&gnb->supported_ta_list[i].bplmn_list[j].plmn_id,
|
|
|
|
pLMNIdentity->buf, sizeof(ogs_plmn_id_t));
|
|
|
|
ogs_debug(" PLMN_ID[MCC:%d MNC:%d]",
|
|
|
|
ogs_plmn_id_mcc(&gnb->supported_ta_list[i].
|
|
|
|
bplmn_list[j].plmn_id),
|
|
|
|
ogs_plmn_id_mnc(&gnb->supported_ta_list[i].
|
|
|
|
bplmn_list[j].plmn_id));
|
|
|
|
|
|
|
|
for (k = 0, gnb->supported_ta_list[i].
|
|
|
|
bplmn_list[j].num_of_s_nssai = 0;
|
|
|
|
k < BroadcastPLMNItem->tAISliceSupportList.list.count &&
|
|
|
|
gnb->supported_ta_list[i].bplmn_list[j].num_of_s_nssai <
|
|
|
|
OGS_MAX_NUM_OF_SLICE;
|
|
|
|
k++) {
|
|
|
|
NGAP_SliceSupportItem_t *SliceSupportItem = NULL;
|
|
|
|
NGAP_S_NSSAI_t *s_NSSAI = NULL;
|
|
|
|
|
|
|
|
SliceSupportItem = (NGAP_SliceSupportItem_t *)
|
|
|
|
BroadcastPLMNItem->tAISliceSupportList.list.array[k];
|
|
|
|
if (!SliceSupportItem) {
|
|
|
|
ogs_error("No SliceSupportItem");
|
|
|
|
group = NGAP_Cause_PR_protocol;
|
|
|
|
cause = NGAP_CauseProtocol_semantic_error;
|
2023-01-23 01:37:22 +00:00
|
|
|
r = ngap_send_ran_configuration_update_failure(
|
|
|
|
gnb, group, cause);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2021-04-16 07:26:13 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
s_NSSAI = &SliceSupportItem->s_NSSAI;
|
|
|
|
ogs_assert(s_NSSAI);
|
|
|
|
|
|
|
|
ogs_asn_OCTET_STRING_to_uint8(&s_NSSAI->sST,
|
|
|
|
&gnb->supported_ta_list[i].
|
|
|
|
bplmn_list[j].s_nssai[k].sst);
|
|
|
|
if (!s_NSSAI->sD) {
|
|
|
|
gnb->supported_ta_list[i].bplmn_list[j].
|
|
|
|
s_nssai[k].sd.v = OGS_S_NSSAI_NO_SD_VALUE;
|
|
|
|
} else {
|
|
|
|
ogs_asn_OCTET_STRING_to_uint24(s_NSSAI->sD,
|
|
|
|
&gnb->supported_ta_list[i].bplmn_list[j].s_nssai[k].sd);
|
|
|
|
}
|
|
|
|
|
|
|
|
ogs_debug(" S_NSSAI[SST:%d SD:0x%x]",
|
|
|
|
gnb->supported_ta_list[i].bplmn_list[j].s_nssai[k].sst,
|
|
|
|
gnb->supported_ta_list[i].bplmn_list[j].
|
|
|
|
s_nssai[k].sd.v);
|
|
|
|
|
|
|
|
gnb->supported_ta_list[i].bplmn_list[j].num_of_s_nssai++;
|
|
|
|
}
|
|
|
|
|
|
|
|
gnb->supported_ta_list[i].num_of_bplmn_list++;
|
|
|
|
}
|
|
|
|
|
|
|
|
gnb->num_of_supported_ta_list++;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (gnb->num_of_supported_ta_list == 0) {
|
|
|
|
ogs_warn("RANConfigurationUpdate failure:");
|
|
|
|
ogs_warn(" No supported TA exist in request");
|
|
|
|
group = NGAP_Cause_PR_protocol;
|
|
|
|
cause =
|
|
|
|
NGAP_CauseProtocol_message_not_compatible_with_receiver_state;
|
|
|
|
|
2023-01-23 01:37:22 +00:00
|
|
|
r = ngap_send_ran_configuration_update_failure(gnb, group, cause);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2021-04-16 07:26:13 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!served_tai_is_found(gnb)) {
|
|
|
|
ogs_warn("RANConfigurationUpdate failure:");
|
|
|
|
ogs_warn(" Cannot find Served TAI. "
|
|
|
|
"Check 'amf.tai' configuration");
|
|
|
|
group = NGAP_Cause_PR_misc;
|
2021-12-28 08:38:11 +00:00
|
|
|
cause = NGAP_CauseMisc_unknown_PLMN_or_SNPN;
|
2021-04-16 07:26:13 +00:00
|
|
|
|
2023-01-23 01:37:22 +00:00
|
|
|
r = ngap_send_ran_configuration_update_failure(gnb, group, cause);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2021-04-16 07:26:13 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!s_nssai_is_found(gnb)) {
|
|
|
|
ogs_warn("RANConfigurationUpdate failure:");
|
|
|
|
ogs_warn(" Cannot find S_NSSAI. "
|
|
|
|
"Check 'amf.plmn_support.s_nssai' configuration");
|
2021-06-22 08:56:45 +00:00
|
|
|
group = NGAP_Cause_PR_radioNetwork;
|
|
|
|
cause = NGAP_CauseRadioNetwork_slice_not_supported;
|
2021-04-16 07:26:13 +00:00
|
|
|
|
2023-01-23 01:37:22 +00:00
|
|
|
r = ngap_send_ran_configuration_update_failure(gnb, group, cause);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2021-04-16 07:26:13 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (PagingDRX)
|
|
|
|
ogs_debug(" PagingDRX[%ld]", *PagingDRX);
|
|
|
|
|
2023-01-23 01:37:22 +00:00
|
|
|
ogs_expect(OGS_OK == ngap_send_ran_configuration_update_ack(gnb));
|
2021-04-16 07:26:13 +00:00
|
|
|
}
|
|
|
|
|
2021-01-25 04:43:42 +00:00
|
|
|
void ngap_handle_ng_reset(
|
|
|
|
amf_gnb_t *gnb, ogs_ngap_message_t *message)
|
|
|
|
{
|
|
|
|
char buf[OGS_ADDRSTRLEN];
|
2023-01-23 01:37:22 +00:00
|
|
|
int i, r, old_xact_count = 0, new_xact_count = 0;
|
2022-05-13 17:43:01 +00:00
|
|
|
|
2021-01-25 04:43:42 +00:00
|
|
|
NGAP_InitiatingMessage_t *initiatingMessage = NULL;
|
|
|
|
NGAP_NGReset_t *NGReset = NULL;
|
|
|
|
|
|
|
|
NGAP_NGResetIEs_t *ie = NULL;
|
|
|
|
NGAP_Cause_t *Cause = NULL;
|
|
|
|
NGAP_ResetType_t *ResetType = NULL;
|
|
|
|
NGAP_UE_associatedLogicalNG_connectionList_t *partOfNG_Interface = NULL;
|
2021-02-02 18:33:09 +00:00
|
|
|
|
|
|
|
ran_ue_t *iter = NULL;
|
2021-01-25 04:43:42 +00:00
|
|
|
|
|
|
|
ogs_assert(gnb);
|
|
|
|
ogs_assert(gnb->sctp.sock);
|
|
|
|
|
|
|
|
ogs_assert(message);
|
|
|
|
initiatingMessage = message->choice.initiatingMessage;
|
|
|
|
ogs_assert(initiatingMessage);
|
|
|
|
NGReset = &initiatingMessage->value.choice.NGReset;
|
|
|
|
ogs_assert(NGReset);
|
|
|
|
|
|
|
|
ogs_warn("NGReset");
|
|
|
|
|
|
|
|
for (i = 0; i < NGReset->protocolIEs.list.count; i++) {
|
|
|
|
ie = NGReset->protocolIEs.list.array[i];
|
|
|
|
switch (ie->id) {
|
|
|
|
case NGAP_ProtocolIE_ID_id_Cause:
|
|
|
|
Cause = &ie->value.choice.Cause;
|
|
|
|
break;
|
|
|
|
case NGAP_ProtocolIE_ID_id_ResetType:
|
|
|
|
ResetType = &ie->value.choice.ResetType;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
ogs_debug(" IP[%s] ENB_ID[%d]",
|
|
|
|
OGS_ADDR(gnb->sctp.addr, buf), gnb->gnb_id);
|
|
|
|
|
|
|
|
if (!Cause) {
|
|
|
|
ogs_error("No Cause");
|
2023-01-23 01:37:22 +00:00
|
|
|
r = ngap_send_error_indication(gnb, NULL, NULL,
|
|
|
|
NGAP_Cause_PR_protocol, NGAP_CauseProtocol_semantic_error);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2021-01-25 04:43:42 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
ogs_warn(" Cause[Group:%d Cause:%d]",
|
|
|
|
Cause->present, (int)Cause->choice.radioNetwork);
|
|
|
|
|
|
|
|
if (!ResetType) {
|
|
|
|
ogs_error("No ResetType");
|
2023-01-23 01:37:22 +00:00
|
|
|
r = ngap_send_error_indication(gnb, NULL, NULL,
|
|
|
|
NGAP_Cause_PR_protocol, NGAP_CauseProtocol_semantic_error);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2021-01-25 04:43:42 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (ResetType->present) {
|
|
|
|
case NGAP_ResetType_PR_nG_Interface:
|
|
|
|
ogs_warn(" NGAP_ResetType_PR_nG_Interface");
|
|
|
|
|
|
|
|
amf_sbi_send_deactivate_all_ue_in_gnb(
|
|
|
|
gnb, AMF_REMOVE_S1_CONTEXT_BY_RESET_ALL);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* TS38.413
|
|
|
|
*
|
|
|
|
* 8.7.4.2.1 NG Reset initiated by the AMF
|
|
|
|
* At reception of the NG RESET message the NG-RAN node shall release all
|
|
|
|
* allocated resources on NG and Uu related to the UE association(s)
|
|
|
|
* indicated explicitly or implicitly in the NG RESET message and
|
|
|
|
* remove the indicated UE contexts including NGAP ID.
|
|
|
|
*
|
|
|
|
* After the NG-RAN node has released all assigned NG resources and
|
|
|
|
* the UE NGAP IDs for all indicated UE associations which can be used
|
|
|
|
* for new UE-associated logical NG-connections over the NG interface,
|
|
|
|
* the NG-RAN node shall respond with the NG RESET ACKNOWLEDGE message.
|
|
|
|
*
|
|
|
|
* The NG-RAN node does not need to wait for the release of radio resources
|
|
|
|
* to be completed before returning the NG RESET ACKNOWLEDGE message.
|
|
|
|
*
|
|
|
|
* 8.7.4.2.2 NG Reset initiated by the NG-RAN node
|
|
|
|
*
|
|
|
|
* At reception of the NG RESET message the AMF shall release
|
|
|
|
* all allocated resources on NG related to the UE association(s)
|
|
|
|
* indicated explicitly or implicitly in the NG RESET message and
|
|
|
|
* remove the NGAP ID for the indicated UE associations.
|
|
|
|
*
|
|
|
|
* After the AMF has released all assigned NG resources and
|
|
|
|
* the UE NGAP IDs for all indicated UE associations which can be used
|
|
|
|
* for new UE-associated logical NG-connections over the NG interface,
|
|
|
|
* the AMF shall respond with the NG RESET ACKNOWLEDGE message.
|
|
|
|
*/
|
2023-01-23 01:37:22 +00:00
|
|
|
if (ogs_list_count(&gnb->ran_ue_list) == 0) {
|
|
|
|
r = ngap_send_ng_reset_ack(gnb, NULL);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
|
|
|
}
|
2021-01-25 04:43:42 +00:00
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
case NGAP_ResetType_PR_partOfNG_Interface:
|
|
|
|
ogs_warn(" NGAP_ResetType_PR_partOfNG_Interface");
|
2021-02-02 18:33:09 +00:00
|
|
|
|
2021-01-25 04:43:42 +00:00
|
|
|
partOfNG_Interface = ResetType->choice.partOfNG_Interface;
|
|
|
|
ogs_assert(partOfNG_Interface);
|
2021-11-30 13:22:41 +00:00
|
|
|
|
|
|
|
if (gnb->ng_reset_ack)
|
|
|
|
ogs_pkbuf_free(gnb->ng_reset_ack);
|
|
|
|
|
|
|
|
gnb->ng_reset_ack = ogs_ngap_build_ng_reset_ack(partOfNG_Interface);
|
2023-01-23 01:37:22 +00:00
|
|
|
if (!gnb->ng_reset_ack) {
|
|
|
|
ogs_error("ogs_ngap_build_ng_reset_ack() failed");
|
|
|
|
return;
|
|
|
|
}
|
2021-11-30 13:22:41 +00:00
|
|
|
|
2021-01-25 04:43:42 +00:00
|
|
|
for (i = 0; i < partOfNG_Interface->list.count; i++) {
|
2021-02-02 18:33:09 +00:00
|
|
|
NGAP_UE_associatedLogicalNG_connectionItem_t *item = NULL;
|
|
|
|
uint64_t amf_ue_ngap_id;
|
2021-01-25 04:43:42 +00:00
|
|
|
|
|
|
|
ran_ue_t *ran_ue = NULL;
|
|
|
|
amf_ue_t *amf_ue = NULL;
|
|
|
|
|
2021-02-02 18:33:09 +00:00
|
|
|
item = (NGAP_UE_associatedLogicalNG_connectionItem_t *)
|
|
|
|
partOfNG_Interface->list.array[i];
|
|
|
|
if (!item) {
|
|
|
|
ogs_error("No ResetType");
|
2021-11-30 13:22:41 +00:00
|
|
|
continue;
|
2021-02-02 18:33:09 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (item->aMF_UE_NGAP_ID) {
|
|
|
|
if (asn_INTEGER2ulong(item->aMF_UE_NGAP_ID,
|
|
|
|
(unsigned long *)&amf_ue_ngap_id) != 0) {
|
|
|
|
ogs_error("Invalid AMF_UE_NGAP_ID");
|
2021-11-30 13:22:41 +00:00
|
|
|
continue;
|
2021-02-02 18:33:09 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
ran_ue = ran_ue_find_by_amf_ue_ngap_id(amf_ue_ngap_id);
|
|
|
|
|
|
|
|
if (!ran_ue) {
|
|
|
|
ogs_error("No RAN UE Context : AMF_UE_NGAP_ID[%lld]",
|
|
|
|
(long long)amf_ue_ngap_id);
|
2021-11-30 13:22:41 +00:00
|
|
|
continue;
|
2021-02-02 18:33:09 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
} else if (item->rAN_UE_NGAP_ID) {
|
|
|
|
|
|
|
|
ran_ue = ran_ue_find_by_ran_ue_ngap_id(
|
|
|
|
gnb, *item->rAN_UE_NGAP_ID);
|
|
|
|
|
|
|
|
if (!ran_ue) {
|
|
|
|
ogs_error("No RAN UE Context : RAN_UE_NGAP_ID[%d]",
|
|
|
|
(int)*item->rAN_UE_NGAP_ID);
|
2021-11-30 13:22:41 +00:00
|
|
|
continue;
|
2021-02-02 18:33:09 +00:00
|
|
|
}
|
2021-05-08 06:09:10 +00:00
|
|
|
} else {
|
|
|
|
ogs_error("No UE NGAP ID");
|
2021-11-30 13:22:41 +00:00
|
|
|
continue;
|
2021-01-25 04:43:42 +00:00
|
|
|
}
|
|
|
|
|
2021-02-02 18:33:09 +00:00
|
|
|
ogs_assert(ran_ue);
|
|
|
|
|
|
|
|
/* RAN_UE Context where PartOfNG_interface was requested */
|
|
|
|
ran_ue->part_of_ng_reset_requested = true;
|
|
|
|
|
2021-01-25 04:43:42 +00:00
|
|
|
amf_ue = ran_ue->amf_ue;
|
2022-12-04 06:01:43 +00:00
|
|
|
/*
|
|
|
|
* Issues #1928
|
|
|
|
*
|
|
|
|
* By ran_ue_deassociate(amf_ue->ran_ue),
|
|
|
|
* 'ran_ue->amf_ue' could be NULL.
|
|
|
|
*
|
|
|
|
* As such, we should not use the ogs_assert() like the following.
|
|
|
|
* ogs_assert(ran_ue->amf_ue);
|
|
|
|
*/
|
|
|
|
if (amf_ue) {
|
|
|
|
old_xact_count = amf_sess_xact_count(amf_ue);
|
2022-05-13 17:43:01 +00:00
|
|
|
|
2022-12-04 06:01:43 +00:00
|
|
|
amf_sbi_send_deactivate_all_sessions(
|
|
|
|
amf_ue, AMF_REMOVE_S1_CONTEXT_BY_RESET_PARTIAL,
|
|
|
|
NGAP_Cause_PR_radioNetwork,
|
|
|
|
NGAP_CauseRadioNetwork_failure_in_radio_interface_procedure);
|
2022-05-13 17:43:01 +00:00
|
|
|
|
2022-12-04 06:01:43 +00:00
|
|
|
new_xact_count = amf_sess_xact_count(amf_ue);
|
|
|
|
} else {
|
|
|
|
ogs_warn("UE(amf-ue) context has already been removed");
|
|
|
|
ogs_warn(" AMF_UE_NGAP_ID[%lld] RAN_UE_NGAP_ID[%d]",
|
|
|
|
(long long)ran_ue->amf_ue_ngap_id,
|
|
|
|
ran_ue->ran_ue_ngap_id);
|
|
|
|
}
|
2022-05-13 17:43:01 +00:00
|
|
|
|
|
|
|
if (old_xact_count == new_xact_count) ran_ue_remove(ran_ue);
|
2021-01-25 04:43:42 +00:00
|
|
|
}
|
2021-02-02 18:33:09 +00:00
|
|
|
|
|
|
|
ogs_list_for_each(&gnb->ran_ue_list, iter) {
|
|
|
|
if (iter->part_of_ng_reset_requested == true) {
|
|
|
|
/* The GNB_UE context
|
|
|
|
* where PartOfNG_interface was requested
|
|
|
|
* still remains */
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* All GNB_UE context
|
|
|
|
* where PartOfNG_interface was requested
|
|
|
|
* REMOVED */
|
2021-11-30 13:22:41 +00:00
|
|
|
ogs_assert(gnb->ng_reset_ack);
|
2023-01-23 01:37:22 +00:00
|
|
|
r = ngap_send_to_gnb(gnb, gnb->ng_reset_ack, NGAP_NON_UE_SIGNALLING);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2021-02-02 18:33:09 +00:00
|
|
|
|
|
|
|
/* Clear NG-Reset Ack Buffer */
|
|
|
|
gnb->ng_reset_ack = NULL;
|
2021-01-25 04:43:42 +00:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
ogs_warn("Invalid ResetType[%d]", ResetType->present);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2022-05-13 17:43:01 +00:00
|
|
|
|
|
|
|
void ngap_handle_error_indication(amf_gnb_t *gnb, ogs_ngap_message_t *message)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
char buf[OGS_ADDRSTRLEN];
|
|
|
|
uint64_t amf_ue_ngap_id;
|
|
|
|
|
|
|
|
ran_ue_t *ran_ue = NULL;
|
|
|
|
|
|
|
|
NGAP_InitiatingMessage_t *initiatingMessage = NULL;
|
|
|
|
NGAP_ErrorIndication_t *ErrorIndication = NULL;
|
|
|
|
|
|
|
|
NGAP_ErrorIndicationIEs_t *ie = NULL;
|
|
|
|
NGAP_RAN_UE_NGAP_ID_t *RAN_UE_NGAP_ID = NULL;
|
|
|
|
NGAP_AMF_UE_NGAP_ID_t *AMF_UE_NGAP_ID = NULL;
|
|
|
|
NGAP_Cause_t *Cause = NULL;
|
|
|
|
|
|
|
|
ogs_assert(gnb);
|
|
|
|
ogs_assert(gnb->sctp.sock);
|
|
|
|
|
|
|
|
ogs_assert(message);
|
|
|
|
initiatingMessage = message->choice.initiatingMessage;
|
|
|
|
ogs_assert(initiatingMessage);
|
|
|
|
ErrorIndication = &initiatingMessage->value.choice.ErrorIndication;
|
|
|
|
ogs_assert(ErrorIndication);
|
|
|
|
|
|
|
|
ogs_warn("ErrorIndication");
|
|
|
|
|
|
|
|
for (i = 0; i < ErrorIndication->protocolIEs.list.count; i++) {
|
|
|
|
ie = ErrorIndication->protocolIEs.list.array[i];
|
|
|
|
switch (ie->id) {
|
|
|
|
case NGAP_ProtocolIE_ID_id_RAN_UE_NGAP_ID:
|
|
|
|
RAN_UE_NGAP_ID = &ie->value.choice.RAN_UE_NGAP_ID;
|
|
|
|
break;
|
|
|
|
case NGAP_ProtocolIE_ID_id_AMF_UE_NGAP_ID:
|
|
|
|
AMF_UE_NGAP_ID = &ie->value.choice.AMF_UE_NGAP_ID;
|
|
|
|
break;
|
|
|
|
case NGAP_ProtocolIE_ID_id_Cause:
|
|
|
|
Cause = &ie->value.choice.Cause;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
ogs_warn(" IP[%s] RAN_ID[%d]",
|
|
|
|
OGS_ADDR(gnb->sctp.addr, buf), gnb->gnb_id);
|
|
|
|
|
|
|
|
if (AMF_UE_NGAP_ID) {
|
|
|
|
|
|
|
|
if (asn_INTEGER2ulong(AMF_UE_NGAP_ID,
|
|
|
|
(unsigned long *)&amf_ue_ngap_id) != 0) {
|
|
|
|
ogs_warn("Invalid AMF_UE_NGAP_ID");
|
|
|
|
}
|
|
|
|
|
|
|
|
ran_ue = ran_ue_find_by_amf_ue_ngap_id(amf_ue_ngap_id);
|
|
|
|
if (!ran_ue)
|
|
|
|
ogs_warn("No RAN UE Context : AMF_UE_NGAP_ID[%lld]",
|
|
|
|
(long long)amf_ue_ngap_id);
|
|
|
|
else
|
|
|
|
ogs_warn(" RAN_UE_NGAP_ID[%d] AMF_UE_NGAP_ID[%lld]",
|
|
|
|
ran_ue->ran_ue_ngap_id, (long long)ran_ue->amf_ue_ngap_id);
|
|
|
|
|
|
|
|
} else if (RAN_UE_NGAP_ID) {
|
|
|
|
ran_ue = ran_ue_find_by_ran_ue_ngap_id(gnb, *RAN_UE_NGAP_ID);
|
|
|
|
if (!ran_ue)
|
|
|
|
ogs_warn("No RAN UE Context : RAN_UE_NGAP_ID[%d]",
|
|
|
|
(int)*RAN_UE_NGAP_ID);
|
|
|
|
else
|
|
|
|
ogs_warn(" RAN_UE_NGAP_ID[%d] AMF_UE_NGAP_ID[%lld]",
|
|
|
|
ran_ue->ran_ue_ngap_id, (long long)ran_ue->amf_ue_ngap_id);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (Cause) {
|
|
|
|
ogs_warn(" Cause[Group:%d Cause:%d]",
|
|
|
|
Cause->present, (int)Cause->choice.radioNetwork);
|
|
|
|
}
|
|
|
|
}
|