Skip to content

Commit

Permalink
Send deregistration event from AMF to UDM (#1599)
Browse files Browse the repository at this point in the history
* [SBI] Fix converting PatchItem to JSON

* [UDR] Add support for endpoint for patching subscription data

Add support for PATCH HTTP method for the following endpoint:
/subscription-data/{ueId}/context-data/amf-3gpp-access

Currently does not change any data in the database.

* [UDM] Add support for endpoint for patching subscription data

Add support for the following endpoint, HTTP PATCH method:
/nudm-uecm/v1/{ueId}/registrations/amf-3gpp-access

The endpoint is used when UE deregisters from the core, and AMF
sends a subscription modification request with "purgeFlag" set.

* [UDM] Add check for same GUAMI when patching subscription data

* [AMF] Send deregistration event to UDM

When UE sends deregistration request, AMF needs to send a
Nudm_UECM_Deregistration request to UDM.
The order of requests is now the following:
- send PDU session release to SMF
- send deregistration event to UDM
- send AM policy control release to PCF
  • Loading branch information
bmeglic committed Jun 14, 2022
1 parent 720b4d3 commit 7be7029
Show file tree
Hide file tree
Showing 15 changed files with 336 additions and 10 deletions.
2 changes: 1 addition & 1 deletion lib/sbi/custom/patch_item.c
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ cJSON *OpenAPI_patch_item_convertToJSON(OpenAPI_patch_item_t *patch_item)
}
} else if (OpenAPI_IsBool(patch_item->value)) {
if (cJSON_AddBoolToObject(
item, "value", OpenAPI_IsTrue(patch_item->value))) {
item, "value", OpenAPI_IsTrue(patch_item->value)) == NULL) {
ogs_error("OpenAPI_patch_item_convertToJSON() failed [value]");
goto end;
}
Expand Down
38 changes: 31 additions & 7 deletions lib/sbi/message.c
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,9 @@ void ogs_sbi_message_free(ogs_sbi_message_t *message)
if (message->Amf3GppAccessRegistration)
OpenAPI_amf3_gpp_access_registration_free(
message->Amf3GppAccessRegistration);
if (message->Amf3GppAccessRegistrationModification)
OpenAPI_amf3_gpp_access_registration_modification_free(
message->Amf3GppAccessRegistrationModification);
if (message->AccessAndMobilitySubscriptionData)
OpenAPI_access_and_mobility_subscription_data_free(
message->AccessAndMobilitySubscriptionData);
Expand Down Expand Up @@ -760,6 +763,10 @@ static char *build_json(ogs_sbi_message_t *message)
item = OpenAPI_amf3_gpp_access_registration_convertToJSON(
message->Amf3GppAccessRegistration);
ogs_assert(item);
} else if (message->Amf3GppAccessRegistrationModification) {
item = OpenAPI_amf3_gpp_access_registration_modification_convertToJSON(
message->Amf3GppAccessRegistrationModification);
ogs_assert(item);
} else if (message->AccessAndMobilitySubscriptionData) {
item = OpenAPI_access_and_mobility_subscription_data_convertToJSON(
message->AccessAndMobilitySubscriptionData);
Expand Down Expand Up @@ -1098,13 +1105,30 @@ static int parse_json(ogs_sbi_message_t *message,
CASE(OGS_SBI_RESOURCE_NAME_REGISTRATIONS)
SWITCH(message->h.resource.component[2])
CASE(OGS_SBI_RESOURCE_NAME_AMF_3GPP_ACCESS)
message->Amf3GppAccessRegistration =
OpenAPI_amf3_gpp_access_registration_parseFromJSON(
item);
if (!message->Amf3GppAccessRegistration) {
rv = OGS_ERROR;
ogs_error("JSON parse error");
}

SWITCH(message->h.method)
CASE(OGS_SBI_HTTP_METHOD_PUT)
message->Amf3GppAccessRegistration =
OpenAPI_amf3_gpp_access_registration_parseFromJSON(
item);
if (!message->Amf3GppAccessRegistration) {
rv = OGS_ERROR;
ogs_error("JSON parse error");
}
break;
CASE(OGS_SBI_HTTP_METHOD_PATCH)
message->Amf3GppAccessRegistrationModification =
OpenAPI_amf3_gpp_access_registration_modification_parseFromJSON(
item);
if (!message->Amf3GppAccessRegistrationModification) {
rv = OGS_ERROR;
ogs_error("JSON parse error");
}
break;
DEFAULT
rv = OGS_ERROR;
ogs_error("Unknown method [%s]", message->h.method);
END
break;
DEFAULT
rv = OGS_ERROR;
Expand Down
2 changes: 2 additions & 0 deletions lib/sbi/message.h
Original file line number Diff line number Diff line change
Expand Up @@ -373,6 +373,8 @@ typedef struct ogs_sbi_message_s {
OpenAPI_confirmation_data_response_t *ConfirmationDataResponse;
OpenAPI_auth_event_t *AuthEvent;
OpenAPI_amf3_gpp_access_registration_t *Amf3GppAccessRegistration;
OpenAPI_amf3_gpp_access_registration_modification_t
*Amf3GppAccessRegistrationModification;
OpenAPI_access_and_mobility_subscription_data_t
*AccessAndMobilitySubscriptionData;
OpenAPI_smf_selection_subscription_data_t *SmfSelectionSubscriptionData;
Expand Down
1 change: 1 addition & 0 deletions lib/sbi/ogs-sbi.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
#include "model/confirmation_data_response.h"
#include "model/auth_event.h"
#include "model/amf3_gpp_access_registration.h"
#include "model/amf3_gpp_access_registration_modification.h"
#include "model/access_and_mobility_subscription_data.h"
#include "model/smf_selection_subscription_data.h"
#include "model/ue_context_in_smf_data.h"
Expand Down
33 changes: 33 additions & 0 deletions src/amf/gmm-sm.c
Original file line number Diff line number Diff line change
Expand Up @@ -450,6 +450,39 @@ static void common_register_state(ogs_fsm_t *s, amf_event_t *e)
END
break;

CASE(OGS_SBI_SERVICE_NAME_NUDM_UECM)
SWITCH(sbi_message->h.resource.component[1])
CASE(OGS_SBI_RESOURCE_NAME_REGISTRATIONS)
SWITCH(sbi_message->h.resource.component[2])
CASE(OGS_SBI_RESOURCE_NAME_AMF_3GPP_ACCESS)
SWITCH(sbi_message->h.method)
CASE(OGS_SBI_HTTP_METHOD_PATCH)

ogs_assert(true ==
amf_ue_sbi_discover_and_send(
OpenAPI_nf_type_PCF, amf_ue,
NULL, amf_npcf_am_policy_control_build_delete));

break;

DEFAULT
ogs_error("Unknown method [%s]", sbi_message->h.method);
ogs_assert_if_reached();
END
break;
DEFAULT
ogs_error("Invalid resource name [%s]",
sbi_message->h.resource.component[2]);
ogs_assert_if_reached();
END
break;

DEFAULT
ogs_error("Invalid resource name [%s]",
sbi_message->h.resource.component[1]);
ogs_assert_if_reached();
END
break;
DEFAULT
ogs_error("Invalid service name [%s]", sbi_message->h.service.name);
ogs_assert_if_reached();
Expand Down
4 changes: 2 additions & 2 deletions src/amf/nsmf-handler.c
Original file line number Diff line number Diff line change
Expand Up @@ -886,8 +886,8 @@ int amf_nsmf_pdusession_handle_release_sm_context(amf_sess_t *sess, int state)

ogs_assert(true ==
amf_ue_sbi_discover_and_send(
OpenAPI_nf_type_PCF, amf_ue,
NULL, amf_npcf_am_policy_control_build_delete));
OpenAPI_nf_type_UDM, amf_ue,
NULL, amf_nudm_uecm_build_registration_delete));

} else if (OGS_FSM_CHECK(&amf_ue->sm, gmm_state_registered)) {
/*
Expand Down
42 changes: 42 additions & 0 deletions src/amf/nudm-build.c
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,48 @@ ogs_sbi_request_t *amf_nudm_uecm_build_registration(
return request;
}

ogs_sbi_request_t *amf_nudm_uecm_build_registration_delete(
amf_ue_t *amf_ue, void *data)
{
ogs_sbi_message_t message;
ogs_sbi_request_t *request = NULL;

OpenAPI_amf3_gpp_access_registration_modification_t
Amf3GppAccessRegistrationModification;

ogs_assert(amf_ue);
ogs_assert(amf_ue->supi);

memset(&message, 0, sizeof(message));
message.h.method = (char *)OGS_SBI_HTTP_METHOD_PATCH;
message.h.service.name = (char *)OGS_SBI_SERVICE_NAME_NUDM_UECM;
message.h.api.version = (char *)OGS_SBI_API_V1;
message.h.resource.component[0] = amf_ue->supi;
message.h.resource.component[1] =
(char *)OGS_SBI_RESOURCE_NAME_REGISTRATIONS;
message.h.resource.component[2] =
(char *)OGS_SBI_RESOURCE_NAME_AMF_3GPP_ACCESS;

memset(&Amf3GppAccessRegistrationModification, 0,
sizeof(Amf3GppAccessRegistrationModification));

Amf3GppAccessRegistrationModification.guami =
ogs_sbi_build_guami(amf_ue->guami);
Amf3GppAccessRegistrationModification.is_purge_flag = true;
Amf3GppAccessRegistrationModification.purge_flag = 1;

message.Amf3GppAccessRegistrationModification =
&Amf3GppAccessRegistrationModification;

request = ogs_sbi_build_request(&message);
ogs_assert(request);

if (Amf3GppAccessRegistrationModification.guami)
ogs_sbi_free_guami(Amf3GppAccessRegistrationModification.guami);

return request;
}

ogs_sbi_request_t *amf_nudm_sdm_build_get(amf_ue_t *amf_ue, void *data)
{
ogs_sbi_message_t message;
Expand Down
2 changes: 2 additions & 0 deletions src/amf/nudm-build.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ extern "C" {

ogs_sbi_request_t *amf_nudm_uecm_build_registration(
amf_ue_t *amf_ue, void *data);
ogs_sbi_request_t *amf_nudm_uecm_build_registration_delete(
amf_ue_t *amf_ue, void *data);
ogs_sbi_request_t *amf_nudm_sdm_build_get(amf_ue_t *amf_ue, void *data);

#ifdef __cplusplus
Expand Down
107 changes: 107 additions & 0 deletions src/udm/nudm-handler.c
Original file line number Diff line number Diff line change
Expand Up @@ -336,6 +336,113 @@ bool udm_nudm_uecm_handle_registration(
return true;
}

bool udm_nudm_uecm_handle_registration_update(
udm_ue_t *udm_ue, ogs_sbi_stream_t *stream, ogs_sbi_message_t *message)
{
OpenAPI_amf3_gpp_access_registration_modification_t
*Amf3GppAccessRegistrationModification = NULL;
OpenAPI_guami_t *Guami = NULL;
ogs_guami_t recv_guami;
OpenAPI_list_t *PatchItemList = NULL;
OpenAPI_patch_item_t item;

ogs_assert(udm_ue);
ogs_assert(stream);
ogs_assert(message);

Amf3GppAccessRegistrationModification = message->Amf3GppAccessRegistrationModification;
if (!Amf3GppAccessRegistrationModification) {
ogs_error("[%s] No Amf3GppAccessRegistrationModification", udm_ue->supi);
ogs_assert(true ==
ogs_sbi_server_send_error(stream, OGS_SBI_HTTP_STATUS_BAD_REQUEST,
message, "No Amf3GppAccessRegistrationModification", udm_ue->supi));
return false;
}

Guami = Amf3GppAccessRegistrationModification->guami;
if (!Guami) {
ogs_error("[%s] No Guami", udm_ue->supi);
ogs_assert(true ==
ogs_sbi_server_send_error(stream, OGS_SBI_HTTP_STATUS_BAD_REQUEST,
message, "No Guami", udm_ue->supi));
return false;
}

if (!Guami->amf_id) {
ogs_error("[%s] No Guami.AmfId", udm_ue->supi);
ogs_assert(true ==
ogs_sbi_server_send_error(stream, OGS_SBI_HTTP_STATUS_BAD_REQUEST,
message, "No Guami.AmfId", udm_ue->supi));
return false;
}

if (!Guami->plmn_id) {
ogs_error("[%s] No PlmnId", udm_ue->supi);
ogs_assert(true ==
ogs_sbi_server_send_error(stream, OGS_SBI_HTTP_STATUS_BAD_REQUEST,
message, "No PlmnId", udm_ue->supi));
return false;
}

if (!Guami->plmn_id->mnc) {
ogs_error("[%s] No PlmnId.Mnc", udm_ue->supi);
ogs_assert(true ==
ogs_sbi_server_send_error(stream, OGS_SBI_HTTP_STATUS_BAD_REQUEST,
message, "No PlmnId.Mnc", udm_ue->supi));
return false;
}

if (!Guami->plmn_id->mcc) {
ogs_error("[%s] No PlmnId.Mcc", udm_ue->supi);
ogs_assert(true ==
ogs_sbi_server_send_error(stream, OGS_SBI_HTTP_STATUS_BAD_REQUEST,
message, "No PlmnId.Mcc", udm_ue->supi));
return false;
}

/* TS 29.503: 5.3.2.4.2 AMF deregistration for 3GPP access
* 2a. The UDM shall check whether the received GUAMI matches the stored
* GUAMI. If so, the UDM shall set the PurgeFlag. The UDM responds with
* "204 No Content".
* 2b. Otherwise the UDM responds with "403 Forbidden". */
ogs_sbi_parse_guami(&recv_guami, Guami);
if (memcmp(&recv_guami, &udm_ue->guami, sizeof(recv_guami)) != 0) {
ogs_error("[%s] Guami mismatch", udm_ue->supi);
ogs_assert(true ==
ogs_sbi_server_send_error(stream, OGS_SBI_HTTP_STATUS_FORBIDDEN,
message, "Guami mismatch", udm_ue->supi));
}


if (Amf3GppAccessRegistrationModification->is_purge_flag) {
udm_ue->amf_3gpp_access_registration->is_purge_flag =
Amf3GppAccessRegistrationModification->is_purge_flag;
udm_ue->amf_3gpp_access_registration->purge_flag =
Amf3GppAccessRegistrationModification->purge_flag;
}

PatchItemList = OpenAPI_list_create();
ogs_assert(PatchItemList);


if (Amf3GppAccessRegistrationModification->is_purge_flag) {
memset(&item, 0, sizeof(item));
item.op = OpenAPI_patch_operation_replace;
item.path = (char *)"PurgeFlag";
item.value = OpenAPI_any_type_create_bool(
Amf3GppAccessRegistrationModification->purge_flag);
ogs_assert(item.value);

OpenAPI_list_add(PatchItemList, &item);
}

ogs_assert(true ==
udm_sbi_discover_and_send(OpenAPI_nf_type_UDR, udm_ue, stream,
PatchItemList, udm_nudr_dr_build_patch_amf_context));

return true;
}

bool udm_nudm_sdm_handle_subscription_provisioned(
udm_ue_t *udm_ue, ogs_sbi_stream_t *stream, ogs_sbi_message_t *recvmsg)
{
Expand Down
2 changes: 2 additions & 0 deletions src/udm/nudm-handler.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ bool udm_nudm_ueau_handle_result_confirmation_inform(

bool udm_nudm_uecm_handle_registration(
udm_ue_t *udm_ue, ogs_sbi_stream_t *stream, ogs_sbi_message_t *message);
bool udm_nudm_uecm_handle_registration_update(
udm_ue_t *udm_ue, ogs_sbi_stream_t *stream, ogs_sbi_message_t *message);

bool udm_nudm_sdm_handle_subscription_provisioned(
udm_ue_t *udm_ue, ogs_sbi_stream_t *stream, ogs_sbi_message_t *recvmsg);
Expand Down
44 changes: 44 additions & 0 deletions src/udm/nudr-build.c
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,50 @@ ogs_sbi_request_t *udm_nudr_dr_build_update_amf_context(
return request;
}

ogs_sbi_request_t *udm_nudr_dr_build_patch_amf_context(
udm_ue_t *udm_ue, void *data)
{
ogs_sbi_message_t message;
ogs_sbi_request_t *request = NULL;

OpenAPI_patch_item_t *pitem = NULL;
OpenAPI_lnode_t *node = NULL;

OpenAPI_list_t *PatchItemList = (OpenAPI_list_t *)data;

ogs_assert(udm_ue);
ogs_assert(PatchItemList);

memset(&message, 0, sizeof(message));
message.http.content_type = (char *)OGS_SBI_CONTENT_PATCH_TYPE;
message.h.method = (char *)OGS_SBI_HTTP_METHOD_PATCH;
message.h.service.name = (char *)OGS_SBI_SERVICE_NAME_NUDR_DR;
message.h.api.version = (char *)OGS_SBI_API_V1;
message.h.resource.component[0] =
(char *)OGS_SBI_RESOURCE_NAME_SUBSCRIPTION_DATA;
message.h.resource.component[1] = (char *)udm_ue->supi;
message.h.resource.component[2] =
(char *)OGS_SBI_RESOURCE_NAME_CONTEXT_DATA;
message.h.resource.component[3] =
(char *)OGS_SBI_RESOURCE_NAME_AMF_3GPP_ACCESS;

message.PatchItemList = PatchItemList;

request = ogs_sbi_build_request(&message);
ogs_assert(request);

if (PatchItemList) {
OpenAPI_list_for_each(PatchItemList, node) {
pitem = node->data;
if (pitem)
OpenAPI_any_type_free(pitem->value);
}
OpenAPI_list_free(PatchItemList);
}

return request;
}

ogs_sbi_request_t *udm_nudr_dr_build_query_subscription_provisioned(
udm_ue_t *udm_ue, void *data)
{
Expand Down
2 changes: 2 additions & 0 deletions src/udm/nudr-build.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ ogs_sbi_request_t *udm_nudr_dr_build_update_authentication_status(
udm_ue_t *udm_ue, void *data);
ogs_sbi_request_t *udm_nudr_dr_build_update_amf_context(
udm_ue_t *udm_ue, void *data);
ogs_sbi_request_t *udm_nudr_dr_build_patch_amf_context(
udm_ue_t *udm_ue, void *data);

#ifdef __cplusplus
}
Expand Down

0 comments on commit 7be7029

Please sign in to comment.