From 7e6568d800fc4cc5ca763b90c697d81f1219c80b Mon Sep 17 00:00:00 2001 From: Bostjan Meglic Date: Wed, 20 Jul 2022 12:01:52 +0000 Subject: [PATCH] [SMF] Send PDU Session Establish Accept to serving AMF In case there are multiple AMF registered to NRF, SMF would pick only the first AMF from the list. In the case of sending PDU Session Establishment Accept from SMF to AMF, this would mean a high chance of failure since the AMF might be different than the original requester, and would not know about a particular UE. Modify SMF to use ServingNfId field from original request SmContextCreateData from AMF to determine to which AMF should it send PDU Session Establishment Accept message. --- src/smf/context.c | 2 ++ src/smf/context.h | 3 ++ src/smf/nnrf-handler.c | 73 ++++++++++++++++++++++++++++++++++++++++++ src/smf/nnrf-handler.h | 2 ++ src/smf/nsmf-handler.c | 6 ++++ src/smf/sbi-path.c | 9 ++++-- src/smf/smf-sm.c | 25 ++++++++++++--- 7 files changed, 113 insertions(+), 7 deletions(-) diff --git a/src/smf/context.c b/src/smf/context.c index 510d746b0..cfc094c8a 100644 --- a/src/smf/context.c +++ b/src/smf/context.c @@ -1658,6 +1658,8 @@ void smf_sess_remove(smf_sess_t *sess) if (sess->pcf_id) ogs_free(sess->pcf_id); + if (sess->serving_nf_id) + ogs_free(sess->serving_nf_id); /* Free SBI object memory */ ogs_sbi_object_free(&sess->sbi); diff --git a/src/smf/context.h b/src/smf/context.h index 5d89e0175..29d6b5b62 100644 --- a/src/smf/context.h +++ b/src/smf/context.h @@ -300,6 +300,9 @@ typedef struct smf_sess_s { /* PCF ID */ char *pcf_id; + /* Serving NF (AMF) Id */ + char *serving_nf_id; + /* Integrity protection maximum data rate */ struct { uint8_t mbr_dl; diff --git a/src/smf/nnrf-handler.c b/src/smf/nnrf-handler.c index 46c111a1c..417114b2e 100644 --- a/src/smf/nnrf-handler.c +++ b/src/smf/nnrf-handler.c @@ -346,3 +346,76 @@ void smf_nnrf_handle_nf_discover( ogs_assert(true == smf_sbi_send(nf_instance, xact)); } } + +void smf_nnrf_handle_nf_profile_retrieve( + ogs_sbi_xact_t *xact, ogs_sbi_message_t *recvmsg) +{ + ogs_sbi_object_t *sbi_object = NULL; + ogs_sbi_nf_instance_t *nf_instance = NULL; + + OpenAPI_nf_profile_t *NFProfile = NULL; + bool handled; + + ogs_assert(xact); + sbi_object = xact->sbi_object; + ogs_assert(sbi_object); + ogs_assert(recvmsg); + + NFProfile = recvmsg->NFProfile; + if (!NFProfile) { + ogs_error("No NFProfile"); + return; + } + + nf_instance = ogs_sbi_nf_instance_find(NFProfile->nf_instance_id); + if (!nf_instance) { + nf_instance = ogs_sbi_nf_instance_add(); + ogs_assert(nf_instance); + ogs_sbi_nf_instance_set_id(nf_instance, NFProfile->nf_instance_id); + + smf_nf_fsm_init(nf_instance); + + ogs_info("[%s] (NF-discover) NF registered", nf_instance->id); + } else { + nf_instance->reference_count++; + + OGS_FSM_TRAN(&nf_instance->sm, smf_nf_state_registered); + ogs_fsm_dispatch(&nf_instance->sm, NULL); + + ogs_warn("[%s] (NF-discover) NF has already been added", + NFProfile->nf_instance_id); + } + + if (NF_INSTANCE_IS_OTHERS(nf_instance->id)) { + smf_sess_t *sess = NULL; + + handled = ogs_sbi_nnrf_handle_nf_profile( + nf_instance, NFProfile, NULL, NULL); + if (!handled) { + ogs_error("ogs_sbi_nnrf_handle_nf_profile() failed [%s]", + nf_instance->id); + SMF_NF_INSTANCE_CLEAR("NRF-discover", nf_instance); + return; + } + + handled = ogs_sbi_client_associate(nf_instance); + if (!handled) { + ogs_error("[%s] Cannot assciate NF EndPoint", nf_instance->id); + SMF_NF_INSTANCE_CLEAR("NRF-discover", nf_instance); + return; + } + + sess = (smf_sess_t *)sbi_object; + ogs_assert(sess); + smf_sess_select_nf(sess, nf_instance->nf_type); + + ogs_info("[%s] (NF-discover) NF Profile updated", nf_instance->id); + } + + if (!nf_instance) { + ogs_error("(NF discover) No [%s]", + OpenAPI_nf_type_ToString(xact->target_nf_type)); + } else { + ogs_assert(true == smf_sbi_send(nf_instance, xact)); + } +} diff --git a/src/smf/nnrf-handler.h b/src/smf/nnrf-handler.h index 431b6c933..d159d8b3e 100644 --- a/src/smf/nnrf-handler.h +++ b/src/smf/nnrf-handler.h @@ -36,6 +36,8 @@ bool smf_nnrf_handle_nf_status_notify( void smf_nnrf_handle_nf_discover( ogs_sbi_xact_t *xact, ogs_sbi_message_t *recvmsg); +void smf_nnrf_handle_nf_profile_retrieve( + ogs_sbi_xact_t *xact, ogs_sbi_message_t *recvmsg); #ifdef __cplusplus } diff --git a/src/smf/nsmf-handler.c b/src/smf/nsmf-handler.c index d47f0ea0b..1b22f9831 100644 --- a/src/smf/nsmf-handler.c +++ b/src/smf/nsmf-handler.c @@ -197,6 +197,12 @@ bool smf_nsmf_handle_create_sm_context( ogs_assert(sess->pcf_id); } + if (SmContextCreateData->serving_nf_id) { + if (sess->serving_nf_id) ogs_free(sess->serving_nf_id); + sess->serving_nf_id = ogs_strdup(SmContextCreateData->serving_nf_id); + ogs_assert(sess->serving_nf_id); + } + /* * NOTE : The pkbuf created in the SBI message will be removed * from ogs_sbi_message_free(). diff --git a/src/smf/sbi-path.c b/src/smf/sbi-path.c index 17fe88c50..553541355 100644 --- a/src/smf/sbi-path.c +++ b/src/smf/sbi-path.c @@ -200,8 +200,13 @@ void smf_namf_comm_send_n1_n2_message_transfer( xact->state = param->state; - ogs_sbi_discover_and_send(xact, - (ogs_fsm_handler_t)smf_nf_state_registered, client_cb); + if (ogs_sbi_discover_by_nf_instanceid_and_send(xact, + (ogs_fsm_handler_t)smf_nf_state_registered, client_cb, + sess->serving_nf_id) != true) + { + ogs_error("smf_namf_comm_send_n1_n2_message_transfer() failed"); + ogs_sbi_xact_remove(xact); + } } void smf_sbi_send_sm_context_create_error( diff --git a/src/smf/smf-sm.c b/src/smf/smf-sm.c index f3ae98f32..f91618067 100644 --- a/src/smf/smf-sm.c +++ b/src/smf/smf-sm.c @@ -658,12 +658,27 @@ void smf_state_operational(ogs_fsm_t *s, smf_event_t *e) SWITCH(sbi_message.h.resource.component[0]) CASE(OGS_SBI_RESOURCE_NAME_NF_INSTANCES) - nf_instance = e->sbi.data; - ogs_assert(nf_instance); - ogs_assert(OGS_FSM_STATE(&nf_instance->sm)); - e->sbi.message = &sbi_message; - ogs_fsm_dispatch(&nf_instance->sm, e); + SWITCH(sbi_message.h.method) + CASE(OGS_SBI_HTTP_METHOD_GET) + sbi_xact = e->sbi.data; + ogs_assert(sbi_xact); + + if (sbi_message.res_status == OGS_SBI_HTTP_STATUS_OK) + smf_nnrf_handle_nf_profile_retrieve( + sbi_xact, &sbi_message); + else + ogs_error("HTTP response error [%d]", + sbi_message.res_status); + break; + DEFAULT + nf_instance = e->sbi.data; + ogs_assert(nf_instance); + ogs_assert(OGS_FSM_STATE(&nf_instance->sm)); + + e->sbi.message = &sbi_message; + ogs_fsm_dispatch(&nf_instance->sm, e); + END break; CASE(OGS_SBI_RESOURCE_NAME_SUBSCRIPTIONS)