From cc03c91bdd2223afc9d1060dcf78f99d6143195c Mon Sep 17 00:00:00 2001 From: Sukchan Lee Date: Tue, 13 Apr 2021 17:34:25 +0900 Subject: [PATCH] [AMF] 5G-GUTI generation changed (#910) 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. --- src/amf/context.c | 68 ++++++++++++++++++---------- src/amf/context.h | 8 ++-- src/amf/gmm-build.c | 33 +++++++++++--- src/amf/gmm-build.h | 1 + src/amf/gmm-handler.c | 8 ++-- src/amf/gmm-sm.c | 28 +++++++++--- src/amf/ngap-build.c | 6 +-- src/amf/ngap-handler.c | 35 +++++++++++--- src/mme/emm-build.c | 38 ++++++++-------- src/mme/emm-handler.c | 6 +-- src/mme/emm-sm.c | 13 ++++-- src/mme/mme-context.c | 57 +++++++++++++++-------- src/mme/mme-context.h | 9 ++-- src/mme/s1ap-build.c | 6 +-- src/mme/s1ap-handler.c | 6 +-- tests/attach/guti-test.c | 2 - tests/attach/ue-context-test.c | 4 -- tests/common/gmm-handler.c | 22 +++++++++ tests/common/gmm-handler.h | 3 ++ tests/common/nas-path.c | 2 + tests/registration/dereg-test.c | 23 ++++++---- tests/registration/guti-test.c | 29 +++++++++++- tests/registration/identity-test.c | 3 -- tests/registration/paging-test.c | 39 ++++++++++++++++ tests/registration/ue-context-test.c | 14 +++++- 25 files changed, 337 insertions(+), 126 deletions(-) diff --git a/src/amf/context.c b/src/amf/context.c index 8b365479e..f521cfe7c 100644 --- a/src/amf/context.c +++ b/src/amf/context.c @@ -1041,27 +1041,47 @@ ran_ue_t *ran_ue_cycle(ran_ue_t *ran_ue) void amf_ue_new_guti(amf_ue_t *amf_ue) { - if (amf_ue->m_tmsi) { + if (amf_ue->next.m_tmsi) { + ogs_warn("GUTI has already been allocated"); + return; + } + + memset(&amf_ue->next.guti, 0, sizeof(ogs_nas_5gs_guti_t)); + + ogs_assert(amf_ue->guami); + ogs_nas_from_plmn_id( + &amf_ue->next.guti.nas_plmn_id, &amf_ue->guami->plmn_id); + memcpy(&amf_ue->next.guti.amf_id, + &amf_ue->guami->amf_id, sizeof(ogs_amf_id_t)); + + amf_ue->next.m_tmsi = amf_m_tmsi_alloc(); + ogs_assert(amf_ue->next.m_tmsi); + amf_ue->next.guti.m_tmsi = *(amf_ue->next.m_tmsi); +} + +void amf_ue_confirm_guti(amf_ue_t *amf_ue) +{ + ogs_assert(amf_ue->next.m_tmsi); + + if (amf_ue->current.m_tmsi) { /* AMF has a VALID GUTI * As such, we need to remove previous GUTI in hash table */ ogs_hash_set(self.guti_ue_hash, - &amf_ue->guti, sizeof(ogs_nas_5gs_guti_t), NULL); - ogs_assert(amf_m_tmsi_free(amf_ue->m_tmsi) == OGS_OK); + &amf_ue->current.guti, sizeof(ogs_nas_5gs_guti_t), NULL); + ogs_assert(amf_m_tmsi_free(amf_ue->current.m_tmsi) == OGS_OK); } - memset(&amf_ue->guti, 0, sizeof(ogs_nas_5gs_guti_t)); + /* Copying from Current to Next Guti */ + amf_ue->current.m_tmsi = amf_ue->next.m_tmsi; + memcpy(&amf_ue->current.guti, + &amf_ue->next.guti, sizeof(ogs_nas_5gs_guti_t)); - ogs_assert(amf_ue->guami); - ogs_nas_from_plmn_id(&amf_ue->guti.nas_plmn_id, &amf_ue->guami->plmn_id); - memcpy(&amf_ue->guti.amf_id, &amf_ue->guami->amf_id, sizeof(ogs_amf_id_t)); - - amf_ue->m_tmsi = amf_m_tmsi_alloc(); - ogs_assert(amf_ue->m_tmsi); - amf_ue->guti.m_tmsi = *(amf_ue->m_tmsi); + /* Hashing Current GUTI */ ogs_hash_set(self.guti_ue_hash, - &amf_ue->guti, sizeof(ogs_nas_5gs_guti_t), amf_ue); + &amf_ue->current.guti, sizeof(ogs_nas_5gs_guti_t), amf_ue); - amf_ue->guti_present = true; + /* Clear Next GUTI */ + amf_ue->next.m_tmsi = NULL; } amf_ue_t *amf_ue_add(ran_ue_t *ran_ue) @@ -1131,14 +1151,22 @@ void amf_ue_remove(amf_ue_t *amf_ue) amf_ue_fsm_fini(amf_ue); + /* Clear Paging Info */ + AMF_UE_CLEAR_PAGING_INFO(amf_ue); + + /* Clear N2 Transfer */ + AMF_UE_CLEAR_N2_TRANSFER(amf_ue, pdu_session_resource_setup_request); + /* Remove all session context */ amf_sess_remove_all(amf_ue); - /* Clear hash table */ - if (amf_ue->m_tmsi) { + if (amf_ue->current.m_tmsi) { ogs_hash_set(self.guti_ue_hash, - &amf_ue->guti, sizeof(ogs_nas_5gs_guti_t), NULL); - ogs_assert(amf_m_tmsi_free(amf_ue->m_tmsi) == OGS_OK); + &amf_ue->current.guti, sizeof(ogs_nas_5gs_guti_t), NULL); + ogs_assert(amf_m_tmsi_free(amf_ue->current.m_tmsi) == OGS_OK); + } + if (amf_ue->next.m_tmsi) { + ogs_assert(amf_m_tmsi_free(amf_ue->next.m_tmsi) == OGS_OK); } if (amf_ue->suci) { ogs_hash_set(self.suci_hash, amf_ue->suci, strlen(amf_ue->suci), NULL); @@ -1172,12 +1200,6 @@ void amf_ue_remove(amf_ue_t *amf_ue) /* Clear Transparent Container */ OGS_ASN_CLEAR_DATA(&amf_ue->handover.container); - /* Clear Paging Info */ - AMF_UE_CLEAR_PAGING_INFO(amf_ue); - - /* Clear N2 Transfer */ - AMF_UE_CLEAR_N2_TRANSFER(amf_ue, pdu_session_resource_setup_request); - /* Delete All Timers */ CLEAR_AMF_UE_ALL_TIMERS(amf_ue); ogs_timer_delete(amf_ue->t3513.timer); diff --git a/src/amf/context.h b/src/amf/context.h index 5e246245a..d8ba4d58d 100644 --- a/src/amf/context.h +++ b/src/amf/context.h @@ -261,9 +261,10 @@ struct amf_ue_s { int num_of_msisdn; char *msisdn[OGS_MAX_NUM_OF_MSISDN]; - amf_m_tmsi_t *m_tmsi; - ogs_nas_5gs_guti_t guti; - bool guti_present; + struct { + amf_m_tmsi_t *m_tmsi; + ogs_nas_5gs_guti_t guti; + } current, next; /* UE Info */ ogs_guami_t *guami; @@ -600,6 +601,7 @@ ran_ue_t *ran_ue_find_by_amf_ue_ngap_id(uint64_t amf_ue_ngap_id); ran_ue_t *ran_ue_cycle(ran_ue_t *ran_ue); void amf_ue_new_guti(amf_ue_t *amf_ue); +void amf_ue_confirm_guti(amf_ue_t *amf_ue); amf_ue_t *amf_ue_add(ran_ue_t *ran_ue); void amf_ue_remove(amf_ue_t *amf_ue); diff --git a/src/amf/gmm-build.c b/src/amf/gmm-build.c index 03cec3aac..7e1bfe124 100644 --- a/src/amf/gmm-build.c +++ b/src/amf/gmm-build.c @@ -70,14 +70,16 @@ ogs_pkbuf_t *gmm_build_registration_accept(amf_ue_t *amf_ue) registration_result->value = amf_ue->nas.access_type; /* Set GUTI */ - ogs_debug("[%s] %s 5G-S_GUTI[AMF_ID:0x%x,M_TMSI:0x%x]", amf_ue->supi, - amf_ue->guti_present == true ? "[V]" : "[N]", - ogs_amf_id_hexdump(&amf_ue->guti.amf_id), amf_ue->guti.m_tmsi); - if (amf_ue->guti_present == true) { - registration_accept->presencemask |= OGS_NAS_5GS_REGISTRATION_ACCEPT_5G_GUTI_PRESENT; + if (amf_ue->next.m_tmsi) { + registration_accept->presencemask |= + OGS_NAS_5GS_REGISTRATION_ACCEPT_5G_GUTI_PRESENT; + + ogs_debug("[%s] 5G-S_GUTI[AMF_ID:0x%x,M_TMSI:0x%x]", amf_ue->supi, + ogs_amf_id_hexdump(&amf_ue->next.guti.amf_id), + amf_ue->next.guti.m_tmsi); ogs_nas_5gs_nas_guti_to_mobility_identity_guti( - &amf_ue->guti, &mobile_identity_guti); + &amf_ue->next.guti, &mobile_identity_guti); mobile_identity->length = sizeof(mobile_identity_guti); mobile_identity->buffer = &mobile_identity_guti; @@ -455,6 +457,9 @@ ogs_pkbuf_t *gmm_build_configuration_update_command( ogs_nas_configuration_update_indication_t *configuration_update_indication = &configuration_update_command->configuration_update_indication; + ogs_nas_5gs_mobile_identity_t *mobile_identity = + &configuration_update_command->guti; + ogs_nas_5gs_mobile_identity_guti_t mobile_identity_guti; struct timeval tv; struct tm gmt, local; @@ -543,6 +548,22 @@ ogs_pkbuf_t *gmm_build_configuration_update_command( network_daylight_saving_time->length = 1; } + if (param->guti) { + configuration_update_command->presencemask |= + OGS_NAS_5GS_CONFIGURATION_UPDATE_COMMAND_5G_GUTI_PRESENT; + + ogs_assert(amf_ue->next.m_tmsi); + ogs_info("[%s] 5G-S_GUTI[AMF_ID:0x%x,M_TMSI:0x%x]", amf_ue->supi, + ogs_amf_id_hexdump(&amf_ue->next.guti.amf_id), + amf_ue->next.guti.m_tmsi); + + ogs_nas_5gs_nas_guti_to_mobility_identity_guti( + &amf_ue->next.guti, &mobile_identity_guti); + + mobile_identity->length = sizeof(mobile_identity_guti); + mobile_identity->buffer = &mobile_identity_guti; + } + return nas_5gs_security_encode(amf_ue, &message); } diff --git a/src/amf/gmm-build.h b/src/amf/gmm-build.h index 5d5dc3e41..dba3034b0 100644 --- a/src/amf/gmm-build.h +++ b/src/amf/gmm-build.h @@ -45,6 +45,7 @@ typedef struct gmm_configuration_update_command_param_s { int registration_requested; int acknowledgement_requested; int nitz; + int guti; } gmm_configuration_update_command_param_t; ogs_pkbuf_t *gmm_build_configuration_update_command( diff --git a/src/amf/gmm-handler.c b/src/amf/gmm-handler.c index 3c9a920af..fb9d9ef2d 100644 --- a/src/amf/gmm-handler.c +++ b/src/amf/gmm-handler.c @@ -117,6 +117,9 @@ int gmm_handle_registration_request(amf_ue_t *amf_ue, amf_ue->nhcc = 1; } + /* Create New GUTI */ + amf_ue_new_guti(amf_ue); + ogs_debug(" OLD TAI[PLMN_ID:%06x,TAC:%d]", ogs_plmn_id_hexdump(&amf_ue->nr_tai.plmn_id), amf_ue->nr_tai.tac.v); ogs_debug(" OLD NR_CGI[PLMN_ID:%06x,CELL_ID:0x%llx]", @@ -343,10 +346,8 @@ int gmm_handle_service_request(amf_ue_t *amf_ue, /* * REGISTRATION_REQUEST * SERVICE_REQUEST - * Clear Paging Info * Clear Timer and Message */ - AMF_UE_CLEAR_PAGING_INFO(amf_ue); CLEAR_AMF_UE_ALL_TIMERS(amf_ue); if (SECURITY_CONTEXT_IS_VALID(amf_ue)) { @@ -389,7 +390,8 @@ int gmm_handle_service_request(amf_ue_t *amf_ue, ogs_info("[%s] 5G-S_GUTI[AMF_ID:0x%x,M_TMSI:0x%x]", AMF_UE_HAVE_SUCI(amf_ue) ? amf_ue->suci : "Unknown ID", - ogs_amf_id_hexdump(&amf_ue->guti.amf_id), amf_ue->guti.m_tmsi); + ogs_amf_id_hexdump(&amf_ue->current.guti.amf_id), + amf_ue->current.guti.m_tmsi); return OGS_OK; } diff --git a/src/amf/gmm-sm.c b/src/amf/gmm-sm.c index 72a6bf377..adb42a59f 100644 --- a/src/amf/gmm-sm.c +++ b/src/amf/gmm-sm.c @@ -194,7 +194,10 @@ static void common_register_state(ogs_fsm_t *s, amf_event_t *e) nas_5gs_send_registration_accept(amf_ue); } - OGS_FSM_TRAN(s, &gmm_state_registered); + if (amf_ue->next.m_tmsi) + OGS_FSM_TRAN(s, &gmm_state_initial_context_setup); + else + OGS_FSM_TRAN(s, &gmm_state_registered); } else { @@ -292,6 +295,13 @@ static void common_register_state(ogs_fsm_t *s, amf_event_t *e) case OGS_NAS_5GS_CONFIGURATION_UPDATE_COMPLETE: ogs_debug("[%s] Configuration update complete", amf_ue->supi); + /* Confirm GUTI */ + if (amf_ue->next.m_tmsi) { + amf_ue_confirm_guti(amf_ue); + } else { + ogs_error("[%s] No GUTI allocated", amf_ue->supi); + } + CLEAR_AMF_UE_TIMER(amf_ue->t3555); break; @@ -690,9 +700,6 @@ void gmm_state_security_mode(ogs_fsm_t *s, amf_event_t *e) ogs_kdf_nh_gnb(amf_ue->kamf, amf_ue->kgnb, amf_ue->nh); amf_ue->nhcc = 1; - /* Create New GUTI */ - amf_ue_new_guti(amf_ue); - amf_ue_sbi_discover_and_send(OpenAPI_nf_type_UDM, amf_ue, NULL, amf_nudm_uecm_build_registration); @@ -953,8 +960,12 @@ void gmm_state_initial_context_setup(ogs_fsm_t *s, amf_event_t *e) case OGS_NAS_5GS_REGISTRATION_COMPLETE: ogs_info("[%s] Registration complete", amf_ue->supi); - /* Clear GUTI present */ - amf_ue->guti_present = false; + /* Confirm GUTI */ + if (amf_ue->next.m_tmsi) { + amf_ue_confirm_guti(amf_ue); + } else { + ogs_error("[%s] No GUTI allocated", amf_ue->supi); + } /* * TS24.501 @@ -1165,7 +1176,10 @@ void gmm_state_exception(ogs_fsm_t *s, amf_event_t *e) nas_5gs_send_registration_accept(amf_ue); } - OGS_FSM_TRAN(s, &gmm_state_registered); + if (amf_ue->next.m_tmsi) + OGS_FSM_TRAN(s, &gmm_state_initial_context_setup); + else + OGS_FSM_TRAN(s, &gmm_state_registered); } else { diff --git a/src/amf/ngap-build.c b/src/amf/ngap-build.c index f55796c52..882898533 100644 --- a/src/amf/ngap-build.c +++ b/src/amf/ngap-build.c @@ -1514,10 +1514,10 @@ ogs_pkbuf_t *ngap_build_paging(amf_ue_t *amf_ue) fiveG_TMSI = &fiveG_S_TMSI->fiveG_TMSI; ogs_ngap_uint16_to_AMFSetID( - ogs_amf_set_id(&amf_ue->guti.amf_id), aMFSetID); + ogs_amf_set_id(&amf_ue->current.guti.amf_id), aMFSetID); ogs_ngap_uint8_to_AMFPointer( - ogs_amf_pointer(&amf_ue->guti.amf_id), aMFPointer); - ogs_asn_uint32_to_OCTET_STRING(amf_ue->guti.m_tmsi, fiveG_TMSI); + ogs_amf_pointer(&amf_ue->current.guti.amf_id), aMFPointer); + ogs_asn_uint32_to_OCTET_STRING(amf_ue->current.guti.m_tmsi, fiveG_TMSI); ie = CALLOC(1, sizeof(NGAP_PagingIEs_t)); ASN_SEQUENCE_ADD(&Paging->protocolIEs, ie); diff --git a/src/amf/ngap-handler.c b/src/amf/ngap-handler.c index c2082f193..f4ba60fa9 100644 --- a/src/amf/ngap-handler.c +++ b/src/amf/ngap-handler.c @@ -20,6 +20,7 @@ #include "ngap-handler.h" #include "ngap-path.h" #include "sbi-path.h" +#include "nas-path.h" static bool served_tai_is_found(amf_gnb_t *gnb) { @@ -420,8 +421,8 @@ void ngap_handle_initial_ue_message(amf_gnb_t *gnb, ogs_ngap_message_t *message) } else { ogs_info("[%s] 5G-S_TMSI[AMF_ID:0x%x,M_TMSI:0x%x]", AMF_UE_HAVE_SUCI(amf_ue) ? amf_ue->suci : "Unknown ID", - ogs_amf_id_hexdump(&amf_ue->guti.amf_id), - amf_ue->guti.m_tmsi); + ogs_amf_id_hexdump(&amf_ue->current.guti.amf_id), + amf_ue->current.guti.m_tmsi); /* If NAS(amf_ue_t) has already been associated with * older NG(ran_ue_t) context */ if (CM_CONNECTED(amf_ue)) { @@ -727,9 +728,12 @@ void ngap_handle_initial_context_setup_response( amf_ue_t *amf_ue = NULL; ran_ue_t *ran_ue = NULL; + amf_sess_t *sess = NULL; uint64_t amf_ue_ngap_id; amf_nsmf_pdusession_update_sm_context_param_t param; + bool paging_ongoing = false; + NGAP_SuccessfulOutcome_t *successfulOutcome = NULL; NGAP_InitialContextSetupResponse_t *InitialContextSetupResponse = NULL; @@ -802,9 +806,6 @@ void ngap_handle_initial_context_setup_response( 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 (!PDUSessionList) /* No PDUSessionList */ - return; - amf_ue = ran_ue->amf_ue; if (!amf_ue) { ogs_error("Cannot find AMF-UE Context [%lld]", @@ -816,8 +817,7 @@ void ngap_handle_initial_context_setup_response( return; } - for (i = 0; i < PDUSessionList->list.count; i++) { - amf_sess_t *sess = NULL; + for (i = 0; PDUSessionList && i < PDUSessionList->list.count; i++) { PDUSessionItem = (NGAP_PDUSessionResourceSetupItemCxtRes_t *) PDUSessionList->list.array[i]; @@ -875,6 +875,27 @@ void ngap_handle_initial_context_setup_response( ogs_pkbuf_free(param.n2smbuf); } + + ogs_list_for_each(&amf_ue->sess_list, sess) { + if (sess->paging.ongoing == true) { + paging_ongoing = true; + break; + } + } + + if (paging_ongoing == true) { + gmm_configuration_update_command_param_t param; + + /* Create New GUTI */ + amf_ue_new_guti(amf_ue); + + memset(¶m, 0, sizeof(param)); + param.acknowledgement_requested = 1; + param.guti = 1; + nas_5gs_send_configuration_update_command(amf_ue, ¶m); + } + + AMF_UE_CLEAR_PAGING_INFO(amf_ue); } void ngap_handle_initial_context_setup_failure( diff --git a/src/mme/emm-build.c b/src/mme/emm-build.c index e0fa6b5c8..ff2b00b6f 100644 --- a/src/mme/emm-build.c +++ b/src/mme/emm-build.c @@ -77,19 +77,20 @@ ogs_pkbuf_t *emm_build_attach_accept( attach_accept->esm_message_container.buffer = esmbuf->data; attach_accept->esm_message_container.length = esmbuf->len; - ogs_debug(" %s GUTI[G:%d,C:%d,M_TMSI:0x%x] IMSI:[%s]", - mme_ue->guti_present == true ? "[V]" : "[N]", - mme_ue->guti.mme_gid, mme_ue->guti.mme_code, - mme_ue->guti.m_tmsi, mme_ue->imsi_bcd); - if (mme_ue->guti_present == true) { + if (mme_ue->next.m_tmsi) { attach_accept->presencemask |= OGS_NAS_EPS_ATTACH_ACCEPT_GUTI_PRESENT; + + ogs_debug("[%s] GUTI[G:%d,C:%d,M_TMSI:0x%x]", + mme_ue->imsi_bcd, + mme_ue->next.guti.mme_gid, mme_ue->next.guti.mme_code, + mme_ue->next.guti.m_tmsi); nas_guti->length = sizeof(ogs_nas_eps_mobile_identity_guti_t); nas_guti->guti.odd_even = OGS_NAS_MOBILE_IDENTITY_EVEN; nas_guti->guti.type = OGS_NAS_EPS_MOBILE_IDENTITY_GUTI; - nas_guti->guti.nas_plmn_id = mme_ue->guti.nas_plmn_id; - nas_guti->guti.mme_gid = mme_ue->guti.mme_gid; - nas_guti->guti.mme_code = mme_ue->guti.mme_code; - nas_guti->guti.m_tmsi = mme_ue->guti.m_tmsi; + nas_guti->guti.nas_plmn_id = mme_ue->next.guti.nas_plmn_id; + nas_guti->guti.mme_gid = mme_ue->next.guti.mme_gid; + nas_guti->guti.mme_code = mme_ue->next.guti.mme_code; + nas_guti->guti.m_tmsi = mme_ue->next.guti.m_tmsi; } #if 0 /* Need not to include T3402 */ @@ -409,20 +410,21 @@ ogs_pkbuf_t *emm_build_tau_accept(mme_ue_t *mme_ue) tau_accept->t3412_value.unit = OGS_NAS_GRPS_TIMER_UNIT_MULTIPLES_OF_DECI_HH; tau_accept->t3412_value.value = 9; - ogs_debug(" %s GUTI[G:%d,C:%d,M_TMSI:0x%x] IMSI:[%s]", - mme_ue->guti_present == true ? "[V]" : "[N]", - mme_ue->guti.mme_gid, mme_ue->guti.mme_code, - mme_ue->guti.m_tmsi, mme_ue->imsi_bcd); - if (mme_ue->guti_present == true) { + if (mme_ue->next.m_tmsi) { tau_accept->presencemask |= OGS_NAS_EPS_TRACKING_AREA_UPDATE_ACCEPT_GUTI_PRESENT; + + ogs_debug("[%s] GUTI[G:%d,C:%d,M_TMSI:0x%x]", + mme_ue->imsi_bcd, + mme_ue->next.guti.mme_gid, mme_ue->next.guti.mme_code, + mme_ue->next.guti.m_tmsi); nas_guti->length = sizeof(ogs_nas_eps_mobile_identity_guti_t); nas_guti->guti.odd_even = OGS_NAS_MOBILE_IDENTITY_EVEN; nas_guti->guti.type = OGS_NAS_EPS_MOBILE_IDENTITY_GUTI; - nas_guti->guti.nas_plmn_id = mme_ue->guti.nas_plmn_id; - nas_guti->guti.mme_gid = mme_ue->guti.mme_gid; - nas_guti->guti.mme_code = mme_ue->guti.mme_code; - nas_guti->guti.m_tmsi = mme_ue->guti.m_tmsi; + nas_guti->guti.nas_plmn_id = mme_ue->next.guti.nas_plmn_id; + nas_guti->guti.mme_gid = mme_ue->next.guti.mme_gid; + nas_guti->guti.mme_code = mme_ue->next.guti.mme_code; + nas_guti->guti.m_tmsi = mme_ue->next.guti.m_tmsi; } /* Set TAI */ diff --git a/src/mme/emm-handler.c b/src/mme/emm-handler.c index f217332ea..b5a7fd175 100644 --- a/src/mme/emm-handler.c +++ b/src/mme/emm-handler.c @@ -422,9 +422,9 @@ int emm_handle_service_request( } ogs_info(" GUTI[G:%d,C:%d,M_TMSI:0x%x] IMSI[%s]", - mme_ue->guti.mme_gid, - mme_ue->guti.mme_code, - mme_ue->guti.m_tmsi, + mme_ue->current.guti.mme_gid, + mme_ue->current.guti.mme_code, + mme_ue->current.guti.m_tmsi, MME_UE_HAVE_IMSI(mme_ue) ? mme_ue->imsi_bcd : "Unknown"); return OGS_OK; diff --git a/src/mme/emm-sm.c b/src/mme/emm-sm.c index 65b23238d..3651595d6 100644 --- a/src/mme/emm-sm.c +++ b/src/mme/emm-sm.c @@ -305,8 +305,12 @@ static void common_register_state(ogs_fsm_t *s, mme_event_t *e) ogs_info("Tracking area update complete"); ogs_info(" IMSI[%s]", mme_ue->imsi_bcd); - /* Clear GUTI present */ - mme_ue->guti_present = false; + /* Confirm GUTI */ + if (mme_ue->next.m_tmsi) { + mme_ue_confirm_guti(mme_ue); + } else { + ogs_error("[%s] No GUTI allocated", mme_ue->imsi_bcd); + } break; case OGS_NAS_EPS_EXTENDED_SERVICE_REQUEST: @@ -921,8 +925,9 @@ void emm_state_initial_context_setup(ogs_fsm_t *s, mme_event_t *e) break; } - /* Clear GUTI present */ - mme_ue->guti_present = false; + /* Confirm GUTI */ + if (mme_ue->next.m_tmsi) + mme_ue_confirm_guti(mme_ue); if (MME_P_TMSI_IS_AVAILABLE(mme_ue)) sgsap_send_tmsi_reallocation_complete(mme_ue); diff --git a/src/mme/mme-context.c b/src/mme/mme-context.c index 6027d799e..cb1c38993 100644 --- a/src/mme/mme-context.c +++ b/src/mme/mme-context.c @@ -1999,28 +1999,47 @@ void mme_ue_new_guti(mme_ue_t *mme_ue) ogs_assert(served_gummei->num_of_mme_gid > 0); ogs_assert(served_gummei->num_of_mme_code > 0); - if (mme_ue->m_tmsi) { + if (mme_ue->next.m_tmsi) { + ogs_warn("GUTI has already been allocated"); + return; + } + + memset(&mme_ue->next.guti, 0, sizeof(ogs_nas_eps_guti_t)); + + /* Use the first configured plmn_id and mme group id */ + ogs_nas_from_plmn_id( + &mme_ue->next.guti.nas_plmn_id, &served_gummei->plmn_id[0]); + mme_ue->next.guti.mme_gid = served_gummei->mme_gid[0]; + mme_ue->next.guti.mme_code = served_gummei->mme_code[0]; + + mme_ue->next.m_tmsi = mme_m_tmsi_alloc(); + ogs_assert(mme_ue->next.m_tmsi); + mme_ue->next.guti.m_tmsi = *(mme_ue->next.m_tmsi); +} + +void mme_ue_confirm_guti(mme_ue_t *mme_ue) +{ + ogs_assert(mme_ue->next.m_tmsi); + + if (mme_ue->current.m_tmsi) { /* MME has a VALID GUTI * As such, we need to remove previous GUTI in hash table */ ogs_hash_set(self.guti_ue_hash, - &mme_ue->guti, sizeof(ogs_nas_eps_guti_t), NULL); - ogs_assert(mme_m_tmsi_free(mme_ue->m_tmsi) == OGS_OK); + &mme_ue->current.guti, sizeof(ogs_nas_eps_guti_t), NULL); + ogs_assert(mme_m_tmsi_free(mme_ue->current.m_tmsi) == OGS_OK); } - memset(&mme_ue->guti, 0, sizeof(ogs_nas_eps_guti_t)); + /* Copying from Current to Next Guti */ + mme_ue->current.m_tmsi = mme_ue->next.m_tmsi; + memcpy(&mme_ue->current.guti, + &mme_ue->next.guti, sizeof(ogs_nas_eps_guti_t)); - /* Use the first configured plmn_id and mme group id */ - ogs_nas_from_plmn_id(&mme_ue->guti.nas_plmn_id, &served_gummei->plmn_id[0]); - mme_ue->guti.mme_gid = served_gummei->mme_gid[0]; - mme_ue->guti.mme_code = served_gummei->mme_code[0]; - - mme_ue->m_tmsi = mme_m_tmsi_alloc(); - ogs_assert(mme_ue->m_tmsi); - mme_ue->guti.m_tmsi = *(mme_ue->m_tmsi); + /* Hashing Current GUTI */ ogs_hash_set(self.guti_ue_hash, - &mme_ue->guti, sizeof(ogs_nas_eps_guti_t), mme_ue); + &mme_ue->current.guti, sizeof(ogs_nas_eps_guti_t), mme_ue); - mme_ue->guti_present = true; + /* Clear Next GUTI */ + mme_ue->next.m_tmsi = NULL; } static bool compare_ue_info(mme_sgw_t *node, enb_ue_t *enb_ue) @@ -2134,11 +2153,13 @@ void mme_ue_remove(mme_ue_t *mme_ue) mme_ue_fsm_fini(mme_ue); - /* Clear hash table */ - if (mme_ue->m_tmsi) { + if (mme_ue->current.m_tmsi) { ogs_hash_set(self.guti_ue_hash, - &mme_ue->guti, sizeof(ogs_nas_eps_guti_t), NULL); - ogs_assert(mme_m_tmsi_free(mme_ue->m_tmsi) == OGS_OK); + &mme_ue->current.guti, sizeof(ogs_nas_eps_guti_t), NULL); + ogs_assert(mme_m_tmsi_free(mme_ue->current.m_tmsi) == OGS_OK); + } + if (mme_ue->next.m_tmsi) { + ogs_assert(mme_m_tmsi_free(mme_ue->next.m_tmsi) == OGS_OK); } if (mme_ue->imsi_len != 0) ogs_hash_set(self.imsi_ue_hash, mme_ue->imsi, mme_ue->imsi_len, NULL); diff --git a/src/mme/mme-context.h b/src/mme/mme-context.h index 7369ef61f..23420660d 100644 --- a/src/mme/mme-context.h +++ b/src/mme/mme-context.h @@ -312,10 +312,12 @@ struct mme_ue_s { int a_msisdn_len; char a_msisdn_bcd[OGS_MAX_MSISDN_BCD_LEN+1]; - mme_m_tmsi_t *m_tmsi; mme_p_tmsi_t p_tmsi; - ogs_nas_eps_guti_t guti; - bool guti_present; + + struct { + mme_m_tmsi_t *m_tmsi; + ogs_nas_eps_guti_t guti; + } current, next; uint32_t mme_s11_teid; /* MME-S11-TEID is derived from INDEX */ uint32_t sgw_s11_teid; /* SGW-S11-TEID is received from SGW */ @@ -687,6 +689,7 @@ enb_ue_t *enb_ue_find_by_mme_ue_s1ap_id(uint32_t mme_ue_s1ap_id); enb_ue_t *enb_ue_cycle(enb_ue_t *enb_ue); void mme_ue_new_guti(mme_ue_t *mme_ue); +void mme_ue_confirm_guti(mme_ue_t *mme_ue); mme_ue_t *mme_ue_add(enb_ue_t *enb_ue); void mme_ue_remove(mme_ue_t *mme_ue); diff --git a/src/mme/s1ap-build.c b/src/mme/s1ap-build.c index d58455fd9..a711fd932 100644 --- a/src/mme/s1ap-build.c +++ b/src/mme/s1ap-build.c @@ -1416,14 +1416,14 @@ ogs_pkbuf_t *s1ap_build_paging( /* Set Paging Identity */ UEPagingID->present = S1AP_UEPagingID_PR_s_TMSI; UEPagingID->choice.s_TMSI = CALLOC(1, sizeof(S1AP_S_TMSI_t)); - ogs_asn_uint8_to_OCTET_STRING(mme_ue->guti.mme_code, + ogs_asn_uint8_to_OCTET_STRING(mme_ue->current.guti.mme_code, &UEPagingID->choice.s_TMSI->mMEC); - ogs_asn_uint32_to_OCTET_STRING(mme_ue->guti.m_tmsi, + ogs_asn_uint32_to_OCTET_STRING(mme_ue->current.guti.m_tmsi, &UEPagingID->choice.s_TMSI->m_TMSI); ogs_debug(" MME_CODE[%d] M_TMSI[0x%x]", - mme_ue->guti.mme_code, mme_ue->guti.m_tmsi); + mme_ue->current.guti.mme_code, mme_ue->current.guti.m_tmsi); ogs_debug(" CN_DOMAIN[%s]", cn_domain == S1AP_CNDomain_cs ? "CS" : cn_domain == S1AP_CNDomain_ps ? "PS" : "Unknown"); diff --git a/src/mme/s1ap-handler.c b/src/mme/s1ap-handler.c index 38aec24bb..e70ce7a27 100644 --- a/src/mme/s1ap-handler.c +++ b/src/mme/s1ap-handler.c @@ -284,9 +284,9 @@ void s1ap_handle_initial_ue_message(mme_enb_t *enb, ogs_s1ap_message_t *message) nas_guti.mme_gid, nas_guti.mme_code, nas_guti.m_tmsi); } else { ogs_info(" S_TMSI[G:%d,C:%d,M_TMSI:0x%x] IMSI:[%s]", - mme_ue->guti.mme_gid, - mme_ue->guti.mme_code, - mme_ue->guti.m_tmsi, + mme_ue->current.guti.mme_gid, + mme_ue->current.guti.mme_code, + mme_ue->current.guti.m_tmsi, MME_UE_HAVE_IMSI(mme_ue) ? mme_ue->imsi_bcd : "Unknown"); diff --git a/tests/attach/guti-test.c b/tests/attach/guti-test.c index e59e2cc63..fbfb9195c 100644 --- a/tests/attach/guti-test.c +++ b/tests/attach/guti-test.c @@ -1361,8 +1361,6 @@ static void test4_func(abts_case *tc, void *data) memset(&test_ue->attach_request_param, 0, sizeof(test_ue->attach_request_param)); - test_ue->attach_request_param.integrity_protected = 1; - test_ue->attach_request_param.guti = 1; test_ue->attach_request_param.last_visited_registered_tai = 1; test_ue->attach_request_param.old_guti_type = 1; emmbuf = testemm_build_attach_request(test_ue, esmbuf); diff --git a/tests/attach/ue-context-test.c b/tests/attach/ue-context-test.c index 5d8a0530a..984f8e4b3 100644 --- a/tests/attach/ue-context-test.c +++ b/tests/attach/ue-context-test.c @@ -350,8 +350,6 @@ static void test2_func(abts_case *tc, void *data) memset(&test_ue->attach_request_param, 0, sizeof(test_ue->attach_request_param)); - test_ue->attach_request_param.integrity_protected = 1; - test_ue->attach_request_param.guti = 1; test_ue->attach_request_param.last_visited_registered_tai = 1; test_ue->attach_request_param.old_guti_type = 1; emmbuf = testemm_build_attach_request(test_ue, esmbuf); @@ -634,8 +632,6 @@ static void test3_func(abts_case *tc, void *data) memset(&test_ue->attach_request_param, 0, sizeof(test_ue->attach_request_param)); - test_ue->attach_request_param.integrity_protected = 1; - test_ue->attach_request_param.guti = 1; test_ue->attach_request_param.last_visited_registered_tai = 1; test_ue->attach_request_param.old_guti_type = 1; emmbuf = testemm_build_attach_request(test_ue, esmbuf); diff --git a/tests/common/gmm-handler.c b/tests/common/gmm-handler.c index 5c0c558e1..f4a5ecf66 100644 --- a/tests/common/gmm-handler.c +++ b/tests/common/gmm-handler.c @@ -181,6 +181,28 @@ void testgmm_handle_security_mode_command(test_ue_t *test_ue, test_ue->security_context_available = 1; } +void testgmm_handle_configuration_update_command(test_ue_t *test_ue, + ogs_nas_5gs_configuration_update_command_t + *configuration_update_command) +{ + ogs_assert(test_ue); + ogs_assert(configuration_update_command); + if (configuration_update_command->presencemask & + OGS_NAS_5GS_CONFIGURATION_UPDATE_COMMAND_5G_GUTI_PRESENT) { + ogs_nas_5gs_mobile_identity_t *mobile_identity = NULL; + ogs_nas_5gs_mobile_identity_guti_t *mobile_identity_guti = NULL; + + mobile_identity = &configuration_update_command->guti; + mobile_identity_guti = mobile_identity->buffer; + + memcpy(&test_ue->nas_5gs_guti.nas_plmn_id, + &mobile_identity_guti->nas_plmn_id, OGS_PLMN_ID_LEN); + memcpy(&test_ue->nas_5gs_guti.amf_id, + &mobile_identity_guti->amf_id, sizeof(ogs_amf_id_t)); + test_ue->nas_5gs_guti.m_tmsi = be32toh(mobile_identity_guti->m_tmsi); + } +} + void testgmm_handle_dl_nas_transport(test_ue_t *test_ue, ogs_nas_5gs_dl_nas_transport_t *dl_nas_transport) { diff --git a/tests/common/gmm-handler.h b/tests/common/gmm-handler.h index 2d3aaf572..833169a1d 100644 --- a/tests/common/gmm-handler.h +++ b/tests/common/gmm-handler.h @@ -36,6 +36,9 @@ void testgmm_handle_authentication_request(test_ue_t *test_ue, ogs_nas_5gs_authentication_request_t *authentication_request); void testgmm_handle_security_mode_command(test_ue_t *test_ue, ogs_nas_5gs_security_mode_command_t *security_mode_command); +void testgmm_handle_configuration_update_command(test_ue_t *test_ue, + ogs_nas_5gs_configuration_update_command_t + *configuration_update_command); void testgmm_handle_dl_nas_transport(test_ue_t *test_ue, ogs_nas_5gs_dl_nas_transport_t *dl_nas_transport); diff --git a/tests/common/nas-path.c b/tests/common/nas-path.c index 6a76dde9b..8ee5f92a0 100644 --- a/tests/common/nas-path.c +++ b/tests/common/nas-path.c @@ -56,6 +56,8 @@ void testgmm_recv(test_ue_t *test_ue, ogs_pkbuf_t *pkbuf) case OGS_NAS_5GS_SECURITY_MODE_COMMAND: break; case OGS_NAS_5GS_CONFIGURATION_UPDATE_COMMAND: + testgmm_handle_configuration_update_command( + test_ue, &message.gmm.configuration_update_command); break; case OGS_NAS_5GS_DL_NAS_TRANSPORT: testgmm_handle_dl_nas_transport(test_ue, &message.gmm.dl_nas_transport); diff --git a/tests/registration/dereg-test.c b/tests/registration/dereg-test.c index 25d453b14..e03e3cac2 100644 --- a/tests/registration/dereg-test.c +++ b/tests/registration/dereg-test.c @@ -168,16 +168,6 @@ static void test1_func(abts_case *tc, void *data) ABTS_PTR_NOTNULL(tc, recvbuf); testngap_recv(test_ue, recvbuf); -#if 0 - /* Send Configuration update complete */ - gmmbuf = testgmm_build_configuration_update_complete(test_ue); - ABTS_PTR_NOTNULL(tc, gmmbuf); - sendbuf = testngap_build_uplink_nas_transport(test_ue, gmmbuf); - ABTS_PTR_NOTNULL(tc, sendbuf); - rv = testgnb_ngap_send(ngap, sendbuf); - ABTS_INT_EQUAL(tc, OGS_OK, rv); -#endif - /* Send PDU session establishment request */ sess = test_sess_add_by_dnn_and_psi(test_ue, "internet", 5); ogs_assert(sess); @@ -803,6 +793,19 @@ static void test3_func(abts_case *tc, void *data) rv = testgnb_ngap_send(ngap, sendbuf); ABTS_INT_EQUAL(tc, OGS_OK, rv); + /* Send Registration complete */ + gmmbuf = testgmm_build_registration_complete(test_ue); + ABTS_PTR_NOTNULL(tc, gmmbuf); + sendbuf = testngap_build_uplink_nas_transport(test_ue, gmmbuf); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive Configuration update command */ + recvbuf = testgnb_ngap_read(ngap); + ABTS_PTR_NOTNULL(tc, recvbuf); + testngap_recv(test_ue, recvbuf); + /* Send PDU session establishment request */ sess->ul_nas_transport_param.request_type = OGS_NAS_5GS_REQUEST_TYPE_INITIAL; diff --git a/tests/registration/guti-test.c b/tests/registration/guti-test.c index a1524708d..6c00f986c 100644 --- a/tests/registration/guti-test.c +++ b/tests/registration/guti-test.c @@ -328,8 +328,7 @@ static void test1_func(abts_case *tc, void *data) test_ue->nas.registration.value = OGS_NAS_5GS_REGISTRATION_TYPE_PERIODIC_UPDATING; - /* Send Registration request - INVALID_GUTI */ - test_ue->nas_5gs_guti.m_tmsi = 0x1234; + /* Send Registration request without Registration complete */ gmmbuf = testgmm_build_registration_request(test_ue, NULL); ABTS_PTR_NOTNULL(tc, gmmbuf); @@ -784,12 +783,25 @@ static void test2_func(abts_case *tc, void *data) test_ue->ngap_procedure_code); ABTS_INT_EQUAL(tc, 0x0000, test_ue->pdu_session_reactivation_result); + /* Send Registration complete */ + gmmbuf = testgmm_build_registration_complete(test_ue); + ABTS_PTR_NOTNULL(tc, gmmbuf); + sendbuf = testngap_build_uplink_nas_transport(test_ue, gmmbuf); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + /* Send InitialContextSetupResponse */ sendbuf = testngap_build_initial_context_setup_response(test_ue, true); ABTS_PTR_NOTNULL(tc, sendbuf); rv = testgnb_ngap_send(ngap, sendbuf); ABTS_INT_EQUAL(tc, OGS_OK, rv); + /* Receive Configuration update command */ + recvbuf = testgnb_ngap_read(ngap); + ABTS_PTR_NOTNULL(tc, recvbuf); + testngap_recv(test_ue, recvbuf); + /* Send GTP-U ICMP Packet */ qos_flow = test_qos_flow_find_by_qfi(sess, 1); ogs_assert(qos_flow); @@ -844,6 +856,19 @@ static void test2_func(abts_case *tc, void *data) rv = testgnb_ngap_send(ngap, sendbuf); ABTS_INT_EQUAL(tc, OGS_OK, rv); + /* Send Registration complete */ + gmmbuf = testgmm_build_registration_complete(test_ue); + ABTS_PTR_NOTNULL(tc, gmmbuf); + sendbuf = testngap_build_uplink_nas_transport(test_ue, gmmbuf); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive Configuration update command */ + recvbuf = testgnb_ngap_read(ngap); + ABTS_PTR_NOTNULL(tc, recvbuf); + testngap_recv(test_ue, recvbuf); + /* Send PDU session establishment request */ sess->ul_nas_transport_param.request_type = OGS_NAS_5GS_REQUEST_TYPE_INITIAL; diff --git a/tests/registration/identity-test.c b/tests/registration/identity-test.c index 2b0501ec3..5da9e0eb6 100644 --- a/tests/registration/identity-test.c +++ b/tests/registration/identity-test.c @@ -280,9 +280,6 @@ static void test1_func(abts_case *tc, void *data) test_ue->nas.registration.value = OGS_NAS_5GS_REGISTRATION_TYPE_PERIODIC_UPDATING; - /* INVALID GUTI */ - test_ue->nas_5gs_guti.m_tmsi = 0x1234; - /* Send Registration request */ gmmbuf = testgmm_build_registration_request(test_ue, NULL); diff --git a/tests/registration/paging-test.c b/tests/registration/paging-test.c index 6326cc505..29aec87a3 100644 --- a/tests/registration/paging-test.c +++ b/tests/registration/paging-test.c @@ -301,6 +301,19 @@ static void cm_idle_paging_func(abts_case *tc, void *data) rv = testgnb_ngap_send(ngap, sendbuf); ABTS_INT_EQUAL(tc, OGS_OK, rv); + /* Receive Configuration update command */ + recvbuf = testgnb_ngap_read(ngap); + ABTS_PTR_NOTNULL(tc, recvbuf); + testngap_recv(test_ue, recvbuf); + + /* Send Configuration update complete */ + gmmbuf = testgmm_build_configuration_update_complete(test_ue); + ABTS_PTR_NOTNULL(tc, gmmbuf); + sendbuf = testngap_build_uplink_nas_transport(test_ue, gmmbuf); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + /* Receive GTP-U ICMP Packet */ recvbuf = testgnb_gtpu_read(gtpu); ABTS_PTR_NOTNULL(tc, recvbuf); @@ -506,6 +519,19 @@ static void cm_idle_paging_func(abts_case *tc, void *data) rv = testgnb_ngap_send(ngap, sendbuf); ABTS_INT_EQUAL(tc, OGS_OK, rv); + /* Receive Configuration update command */ + recvbuf = testgnb_ngap_read(ngap); + ABTS_PTR_NOTNULL(tc, recvbuf); + testngap_recv(test_ue, recvbuf); + + /* Send Configuration update complete */ + gmmbuf = testgmm_build_configuration_update_complete(test_ue); + ABTS_PTR_NOTNULL(tc, gmmbuf); + sendbuf = testngap_build_uplink_nas_transport(test_ue, gmmbuf); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + /* Receive GTP-U ICMP Packet */ recvbuf = testgnb_gtpu_read(gtpu); ABTS_PTR_NOTNULL(tc, recvbuf); @@ -837,6 +863,19 @@ static void cm_idle_error_indication_func(abts_case *tc, void *data) rv = testgnb_ngap_send(ngap, sendbuf); ABTS_INT_EQUAL(tc, OGS_OK, rv); + /* Receive Configuration update command */ + recvbuf = testgnb_ngap_read(ngap); + ABTS_PTR_NOTNULL(tc, recvbuf); + testngap_recv(test_ue, recvbuf); + + /* Send Configuration update complete */ + gmmbuf = testgmm_build_configuration_update_complete(test_ue); + ABTS_PTR_NOTNULL(tc, gmmbuf); + sendbuf = testngap_build_uplink_nas_transport(test_ue, gmmbuf); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + /* Wait to setup N3 data connection. * Otherwise, network-triggered service request is initiated */ ogs_msleep(100); diff --git a/tests/registration/ue-context-test.c b/tests/registration/ue-context-test.c index 009f9335e..f3ea7e07e 100644 --- a/tests/registration/ue-context-test.c +++ b/tests/registration/ue-context-test.c @@ -302,7 +302,6 @@ static void test2_func(abts_case *tc, void *data) test_ue->ngap_procedure_code); /* Send Registration request */ - test_ue->registration_request_param.guti = 1; gmmbuf = testgmm_build_registration_request(test_ue, NULL); ABTS_PTR_NOTNULL(tc, gmmbuf); @@ -730,6 +729,19 @@ static void test3_func(abts_case *tc, void *data) rv = testgnb_ngap_send(ngap, sendbuf); ABTS_INT_EQUAL(tc, OGS_OK, rv); + /* Send Registration complete */ + gmmbuf = testgmm_build_registration_complete(test_ue); + ABTS_PTR_NOTNULL(tc, gmmbuf); + sendbuf = testngap_build_uplink_nas_transport(test_ue, gmmbuf); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive Configuration update command */ + recvbuf = testgnb_ngap_read(ngap); + ABTS_PTR_NOTNULL(tc, recvbuf); + testngap_recv(test_ue, recvbuf); + /* Send GTP-U ICMP Packet */ qos_flow = test_qos_flow_find_by_qfi(sess, 1); ogs_assert(qos_flow);