mirror of
https://github.com/open5gs/open5gs.git
synced 2026-04-28 03:19:31 +00:00
sbi: avoid duplicate NF status subscriptions and clean up local entries on DELETE
This patch addresses a potential subscription_data pool exhaustion issue observed during repeated NF re-registration with the NRF. Two improvements are introduced: 1) Prevent duplicate NF status subscriptions Before sending a new NF status subscription request, the code now checks whether an equivalent subscription already exists in the local subscription_data list. If a matching subscription (based on req_nf_instance_id and subscr_cond) is found and it is not already marked with DELETE_SENT, the new subscription request is skipped. This prevents repeated subscription creation during re-registration loops. 2) Ensure local cleanup after DELETE response When handling HTTP DELETE responses for NF status subscriptions, the local subscription_data entry is now removed regardless of the response status. Previously, the entry was only removed on HTTP 204 (No Content), which could leave stale entries in the local list when the NRF returned other statuses (e.g., 404). Keeping stale entries could lead to unbounded growth of subscription_data and eventual pool exhaustion. Additionally, successful DELETE operations are logged to improve debugging visibility. This change affects all NF state machines that handle subscription DELETE responses (AMF, AUSF, BSF, NSSF, PCF, SCP, SEPP, SMF, UDM, UDR, and AF test code). Issues: #4207
This commit is contained in:
parent
88116fd1c6
commit
783b1dc26f
12 changed files with 134 additions and 49 deletions
|
|
@ -275,6 +275,52 @@ void ogs_sbi_nf_state_will_register(ogs_fsm_t *s, ogs_event_t *e)
|
|||
}
|
||||
}
|
||||
|
||||
static bool nf_status_subscription_exists(
|
||||
const char *req_nf_instance_id,
|
||||
OpenAPI_nf_type_e nf_type,
|
||||
const char *service_name)
|
||||
{
|
||||
ogs_sbi_subscription_data_t *s = NULL;
|
||||
bool same_nf_type = false;
|
||||
bool same_service_name = false;
|
||||
bool nf_type_present = false;
|
||||
bool service_name_present = false;
|
||||
|
||||
ogs_assert(req_nf_instance_id);
|
||||
|
||||
nf_type_present = (nf_type != OpenAPI_nf_type_NULL);
|
||||
service_name_present = (service_name != NULL);
|
||||
|
||||
ogs_list_for_each(&ogs_sbi_self()->subscription_data_list, s) {
|
||||
if (!s->req_nf_instance_id)
|
||||
continue;
|
||||
|
||||
if (strcmp(s->req_nf_instance_id, req_nf_instance_id) != 0)
|
||||
continue;
|
||||
|
||||
if (s->flags & OGS_SBI_SUBSCRIPTION_DELETE_SENT)
|
||||
continue;
|
||||
|
||||
same_nf_type = false;
|
||||
same_service_name = false;
|
||||
|
||||
if (nf_type_present &&
|
||||
s->subscr_cond.nf_type != OpenAPI_nf_type_NULL &&
|
||||
s->subscr_cond.nf_type == nf_type)
|
||||
same_nf_type = true;
|
||||
|
||||
if (service_name_present &&
|
||||
s->subscr_cond.service_name &&
|
||||
strcmp(s->subscr_cond.service_name, service_name) == 0)
|
||||
same_service_name = true;
|
||||
|
||||
if (same_nf_type || same_service_name)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void ogs_sbi_nf_state_registered(ogs_fsm_t *s, ogs_event_t *e)
|
||||
{
|
||||
ogs_sbi_nf_instance_t *nf_instance = NULL;
|
||||
|
|
@ -308,6 +354,15 @@ void ogs_sbi_nf_state_registered(ogs_fsm_t *s, ogs_event_t *e)
|
|||
|
||||
ogs_list_for_each(
|
||||
&ogs_sbi_self()->subscription_spec_list, subscription_spec) {
|
||||
if (nf_status_subscription_exists(
|
||||
ogs_sbi_self()->nf_instance->id,
|
||||
subscription_spec->subscr_cond.nf_type,
|
||||
subscription_spec->subscr_cond.service_name)) {
|
||||
ogs_warn("[%s] NF status subscription already exists, skip",
|
||||
ogs_sbi_self()->nf_instance->id);
|
||||
continue;
|
||||
}
|
||||
|
||||
ogs_nnrf_nfm_send_nf_status_subscribe(
|
||||
ogs_sbi_self()->nf_instance->nf_type,
|
||||
ogs_sbi_self()->nf_instance->id,
|
||||
|
|
|
|||
|
|
@ -417,14 +417,17 @@ void amf_state_operational(ogs_fsm_t *s, amf_event_t *e)
|
|||
|
||||
CASE(OGS_SBI_HTTP_METHOD_DELETE)
|
||||
if (sbi_message.res_status ==
|
||||
OGS_SBI_HTTP_STATUS_NO_CONTENT) {
|
||||
ogs_sbi_subscription_data_remove(subscription_data);
|
||||
} else {
|
||||
OGS_SBI_HTTP_STATUS_NO_CONTENT)
|
||||
ogs_info("[%s] Subscription deleted",
|
||||
subscription_data->id ?
|
||||
subscription_data->id : "Unknown");
|
||||
else
|
||||
ogs_error("[%s] HTTP response error [%d]",
|
||||
subscription_data->id ?
|
||||
subscription_data->id : "Unknown",
|
||||
sbi_message.res_status);
|
||||
}
|
||||
|
||||
ogs_sbi_subscription_data_remove(subscription_data);
|
||||
break;
|
||||
|
||||
DEFAULT
|
||||
|
|
|
|||
|
|
@ -274,15 +274,17 @@ void ausf_state_operational(ogs_fsm_t *s, ausf_event_t *e)
|
|||
break;
|
||||
|
||||
CASE(OGS_SBI_HTTP_METHOD_DELETE)
|
||||
if (message.res_status ==
|
||||
OGS_SBI_HTTP_STATUS_NO_CONTENT) {
|
||||
ogs_sbi_subscription_data_remove(subscription_data);
|
||||
} else {
|
||||
if (message.res_status == OGS_SBI_HTTP_STATUS_NO_CONTENT)
|
||||
ogs_info("[%s] Subscription deleted",
|
||||
subscription_data->id ?
|
||||
subscription_data->id : "Unknown");
|
||||
else
|
||||
ogs_error("[%s] HTTP response error [%d]",
|
||||
subscription_data->id ?
|
||||
subscription_data->id : "Unknown",
|
||||
message.res_status);
|
||||
}
|
||||
|
||||
ogs_sbi_subscription_data_remove(subscription_data);
|
||||
break;
|
||||
|
||||
DEFAULT
|
||||
|
|
|
|||
|
|
@ -293,14 +293,17 @@ void bsf_state_operational(ogs_fsm_t *s, bsf_event_t *e)
|
|||
break;
|
||||
|
||||
CASE(OGS_SBI_HTTP_METHOD_DELETE)
|
||||
if (message.res_status == OGS_SBI_HTTP_STATUS_NO_CONTENT) {
|
||||
ogs_sbi_subscription_data_remove(subscription_data);
|
||||
} else {
|
||||
if (message.res_status == OGS_SBI_HTTP_STATUS_NO_CONTENT)
|
||||
ogs_info("[%s] Subscription deleted",
|
||||
subscription_data->id ?
|
||||
subscription_data->id : "Unknown");
|
||||
else
|
||||
ogs_error("[%s] HTTP response error [%d]",
|
||||
subscription_data->id ?
|
||||
subscription_data->id : "Unknown",
|
||||
message.res_status);
|
||||
}
|
||||
|
||||
ogs_sbi_subscription_data_remove(subscription_data);
|
||||
break;
|
||||
|
||||
DEFAULT
|
||||
|
|
|
|||
|
|
@ -280,15 +280,17 @@ void nssf_state_operational(ogs_fsm_t *s, nssf_event_t *e)
|
|||
break;
|
||||
|
||||
CASE(OGS_SBI_HTTP_METHOD_DELETE)
|
||||
if (message.res_status ==
|
||||
OGS_SBI_HTTP_STATUS_NO_CONTENT) {
|
||||
ogs_sbi_subscription_data_remove(subscription_data);
|
||||
} else {
|
||||
if (message.res_status == OGS_SBI_HTTP_STATUS_NO_CONTENT)
|
||||
ogs_info("[%s] Subscription deleted",
|
||||
subscription_data->id ?
|
||||
subscription_data->id : "Unknown");
|
||||
else
|
||||
ogs_error("[%s] HTTP response error [%d]",
|
||||
subscription_data->id ?
|
||||
subscription_data->id : "Unknown",
|
||||
message.res_status);
|
||||
}
|
||||
|
||||
ogs_sbi_subscription_data_remove(subscription_data);
|
||||
break;
|
||||
|
||||
DEFAULT
|
||||
|
|
|
|||
|
|
@ -440,15 +440,17 @@ void pcf_state_operational(ogs_fsm_t *s, pcf_event_t *e)
|
|||
break;
|
||||
|
||||
CASE(OGS_SBI_HTTP_METHOD_DELETE)
|
||||
if (message.res_status ==
|
||||
OGS_SBI_HTTP_STATUS_NO_CONTENT) {
|
||||
ogs_sbi_subscription_data_remove(subscription_data);
|
||||
} else {
|
||||
if (message.res_status == OGS_SBI_HTTP_STATUS_NO_CONTENT)
|
||||
ogs_info("[%s] Subscription deleted",
|
||||
subscription_data->id ?
|
||||
subscription_data->id : "Unknown");
|
||||
else
|
||||
ogs_error("[%s] HTTP response error [%d]",
|
||||
subscription_data->id ?
|
||||
subscription_data->id : "Unknown",
|
||||
message.res_status);
|
||||
}
|
||||
|
||||
ogs_sbi_subscription_data_remove(subscription_data);
|
||||
break;
|
||||
|
||||
DEFAULT
|
||||
|
|
|
|||
|
|
@ -226,14 +226,17 @@ void scp_state_operational(ogs_fsm_t *s, scp_event_t *e)
|
|||
break;
|
||||
|
||||
CASE(OGS_SBI_HTTP_METHOD_DELETE)
|
||||
if (message.res_status == OGS_SBI_HTTP_STATUS_NO_CONTENT) {
|
||||
ogs_sbi_subscription_data_remove(subscription_data);
|
||||
} else {
|
||||
if (message.res_status == OGS_SBI_HTTP_STATUS_NO_CONTENT)
|
||||
ogs_info("[%s] Subscription deleted",
|
||||
subscription_data->id ?
|
||||
subscription_data->id : "Unknown");
|
||||
else
|
||||
ogs_error("[%s] HTTP response error [%d]",
|
||||
subscription_data->id ?
|
||||
subscription_data->id : "Unknown",
|
||||
message.res_status);
|
||||
}
|
||||
|
||||
ogs_sbi_subscription_data_remove(subscription_data);
|
||||
break;
|
||||
|
||||
DEFAULT
|
||||
|
|
|
|||
|
|
@ -330,14 +330,17 @@ void sepp_state_operational(ogs_fsm_t *s, sepp_event_t *e)
|
|||
break;
|
||||
|
||||
CASE(OGS_SBI_HTTP_METHOD_DELETE)
|
||||
if (message.res_status == OGS_SBI_HTTP_STATUS_NO_CONTENT) {
|
||||
ogs_sbi_subscription_data_remove(subscription_data);
|
||||
} else {
|
||||
if (message.res_status == OGS_SBI_HTTP_STATUS_NO_CONTENT)
|
||||
ogs_info("[%s] Subscription deleted",
|
||||
subscription_data->id ?
|
||||
subscription_data->id : "Unknown");
|
||||
else
|
||||
ogs_error("[%s] HTTP response error [%d]",
|
||||
subscription_data->id ?
|
||||
subscription_data->id : "Unknown",
|
||||
message.res_status);
|
||||
}
|
||||
|
||||
ogs_sbi_subscription_data_remove(subscription_data);
|
||||
break;
|
||||
|
||||
DEFAULT
|
||||
|
|
|
|||
|
|
@ -903,14 +903,17 @@ void smf_state_operational(ogs_fsm_t *s, smf_event_t *e)
|
|||
|
||||
CASE(OGS_SBI_HTTP_METHOD_DELETE)
|
||||
if (sbi_message.res_status ==
|
||||
OGS_SBI_HTTP_STATUS_NO_CONTENT) {
|
||||
ogs_sbi_subscription_data_remove(subscription_data);
|
||||
} else {
|
||||
OGS_SBI_HTTP_STATUS_NO_CONTENT)
|
||||
ogs_info("[%s] Subscription deleted",
|
||||
subscription_data->id ?
|
||||
subscription_data->id : "Unknown");
|
||||
else
|
||||
ogs_error("[%s] HTTP response error [%d]",
|
||||
subscription_data->id ?
|
||||
subscription_data->id : "Unknown",
|
||||
sbi_message.res_status);
|
||||
}
|
||||
|
||||
ogs_sbi_subscription_data_remove(subscription_data);
|
||||
break;
|
||||
|
||||
DEFAULT
|
||||
|
|
|
|||
|
|
@ -364,15 +364,17 @@ void udm_state_operational(ogs_fsm_t *s, udm_event_t *e)
|
|||
break;
|
||||
|
||||
CASE(OGS_SBI_HTTP_METHOD_DELETE)
|
||||
if (message.res_status ==
|
||||
OGS_SBI_HTTP_STATUS_NO_CONTENT) {
|
||||
ogs_sbi_subscription_data_remove(subscription_data);
|
||||
} else {
|
||||
if (message.res_status == OGS_SBI_HTTP_STATUS_NO_CONTENT)
|
||||
ogs_info("[%s] Subscription deleted",
|
||||
subscription_data->id ?
|
||||
subscription_data->id : "Unknown");
|
||||
else
|
||||
ogs_error("[%s] HTTP response error [%d]",
|
||||
subscription_data->id ?
|
||||
subscription_data->id : "Unknown",
|
||||
message.res_status);
|
||||
}
|
||||
|
||||
ogs_sbi_subscription_data_remove(subscription_data);
|
||||
break;
|
||||
|
||||
DEFAULT
|
||||
|
|
|
|||
|
|
@ -284,17 +284,20 @@ void udr_state_operational(ogs_fsm_t *s, udr_event_t *e)
|
|||
break;
|
||||
|
||||
CASE(OGS_SBI_HTTP_METHOD_DELETE)
|
||||
if (message.res_status ==
|
||||
OGS_SBI_HTTP_STATUS_NO_CONTENT) {
|
||||
ogs_sbi_subscription_data_remove(subscription_data);
|
||||
} else {
|
||||
if (message.res_status == OGS_SBI_HTTP_STATUS_NO_CONTENT)
|
||||
ogs_info("[%s] Subscription deleted",
|
||||
subscription_data->id ?
|
||||
subscription_data->id : "Unknown");
|
||||
else
|
||||
ogs_error("[%s] HTTP response error [%d]",
|
||||
subscription_data->id ?
|
||||
subscription_data->id : "Unknown",
|
||||
message.res_status);
|
||||
}
|
||||
|
||||
ogs_sbi_subscription_data_remove(subscription_data);
|
||||
break;
|
||||
|
||||
|
||||
DEFAULT
|
||||
ogs_error("[%s] Invalid HTTP method [%s]",
|
||||
subscription_data->id, message.h.method);
|
||||
|
|
|
|||
|
|
@ -262,16 +262,20 @@ void af_state_operational(ogs_fsm_t *s, af_event_t *e)
|
|||
break;
|
||||
|
||||
CASE(OGS_SBI_HTTP_METHOD_DELETE)
|
||||
if (message.res_status == OGS_SBI_HTTP_STATUS_NO_CONTENT) {
|
||||
ogs_sbi_subscription_data_remove(subscription_data);
|
||||
} else {
|
||||
if (message.res_status == OGS_SBI_HTTP_STATUS_NO_CONTENT)
|
||||
ogs_info("[%s] Subscription deleted",
|
||||
subscription_data->id ?
|
||||
subscription_data->id : "Unknown");
|
||||
else
|
||||
ogs_error("[%s] HTTP response error [%d]",
|
||||
subscription_data->id ?
|
||||
subscription_data->id : "Unknown",
|
||||
message.res_status);
|
||||
}
|
||||
|
||||
ogs_sbi_subscription_data_remove(subscription_data);
|
||||
break;
|
||||
|
||||
|
||||
DEFAULT
|
||||
ogs_error("Invalid HTTP method [%s]", message.h.method);
|
||||
ogs_assert_if_reached();
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue