diff --git a/README.md b/README.md index 4558a27cc2..a03e0a2d2a 100644 --- a/README.md +++ b/README.md @@ -31,4 +31,7 @@ In our specific deployment context, we lean heavily on the CUPS split and locate Wherever possible, we have changed PFCP messages/operations from an action-based model to a state-based one, with the understanding/assumption that the CPS is always authoritative/correct over the UPS. In this design, the UPS should use messages to infer the state that the CPS wants, and silently recover into this state if able. For Session Establishment messages, this means that if the UPS already has an existing session for the given SEID, it should simply wipe out the preexisting session, create a new one according to the CPS details, and return OGS_PFCP_CAUSE_REQUEST_ACCEPTED. Similarly, for Session Delete messages where the SEID does not exist, the UPS can return OGS_PFCP_CAUSE_REQUEST_ACCEPTED without doing anything. ##### PFCP Session Re-Establishment: -When a UPS re-associates itself with the CPS after a period of disconnectivity, their respective states may have diverged substantially. We handle this using a reassociation process wherein (1) the CPS sends a Session-Set-Delete message, effectively instructing the UPS to delete any/all current sessions, and then (2) the CPS re-sends a Session Establishment message for each active session. This creates a bit more chatter over the wire than you might expect, but works incredibly well in our context. \ No newline at end of file +When a UPS re-associates itself with the CPS after a period of disconnectivity, their respective states may have diverged substantially. We handle this using a reassociation process wherein (1) the CPS sends a Session-Set-Delete message, effectively instructing the UPS to delete any/all current sessions, and then (2) the CPS re-sends a Session Establishment message for each active session. This creates a bit more chatter over the wire than you might expect, but works incredibly well in our context. + +## Fine-Grained Timers +Stock open5gs has one configurable parameter (`message.duration`) which sets the timeout value for *all* messages sent or received by the program in question. We keep this parameter as the default, but have also added several different ones pertaining to each message protocol to allow us to have finer-grained control over these timers, which is highly recommended by the 3GPP. Specifically, `message.duration` has been supplemented by `message.sbi_duration`, `message.gtp_duration`, `message.pfcp_duration` and `message.diameter_timeout`. diff --git a/lib/app/ogs-config.c b/lib/app/ogs-config.c index a641d5617f..2071af9acf 100644 --- a/lib/app/ogs-config.c +++ b/lib/app/ogs-config.c @@ -329,9 +329,25 @@ int ogs_app_parse_global_conf(ogs_yaml_iter_t *parent) static void regenerate_all_timer_duration(void) { ogs_assert(local_conf.time.message.duration); + ogs_assert(local_conf.time.message.sbi_duration); + ogs_assert(local_conf.time.message.gtp_duration); + ogs_assert(local_conf.time.message.pfcp_duration); + + // if message.duration is set, it overrides the default for all + // durations *except* any that were individually set + if (!local_conf.time.message.sbi_set) { + local_conf.time.message.sbi_duration = local_conf.time.message.duration; + } + if (!local_conf.time.message.gtp_set) { + local_conf.time.message.gtp_duration = local_conf.time.message.duration; + } + if (!local_conf.time.message.pfcp_set) { + local_conf.time.message.pfcp_duration = local_conf.time.message.duration; + } + local_conf.time.message.sbi.client_wait_duration = - local_conf.time.message.duration; + local_conf.time.message.sbi_duration; local_conf.time.message.sbi.connection_deadline = local_conf.time.message.sbi.client_wait_duration + ogs_time_from_sec(1); local_conf.time.message.sbi.reconnect_interval = @@ -341,11 +357,8 @@ static void regenerate_all_timer_duration(void) local_conf.time.message.sbi.reconnect_interval_in_exception = ogs_time_from_sec(2); -#define PFCP_N1_RESPONSE_RETRY_COUNT 3 - local_conf.time.message.pfcp.n1_response_rcount = - PFCP_N1_RESPONSE_RETRY_COUNT; local_conf.time.message.pfcp.t1_response_duration = - (local_conf.time.message.duration / + (local_conf.time.message.pfcp_duration / (local_conf.time.message.pfcp.n1_response_rcount + 1)); ogs_assert(local_conf.time.message.pfcp.t1_response_duration); @@ -367,11 +380,8 @@ static void regenerate_all_timer_duration(void) local_conf.time.message.sbi.client_wait_duration + ogs_time_from_sec(1)); -#define GTP_N3_RESPONSE_RETRY_COUNT 3 - local_conf.time.message.gtp.n3_response_rcount = - GTP_N3_RESPONSE_RETRY_COUNT; local_conf.time.message.gtp.t3_response_duration = - (local_conf.time.message.duration / + (local_conf.time.message.gtp_duration / (local_conf.time.message.gtp.n3_response_rcount + 1)); ogs_assert(local_conf.time.message.gtp.t3_response_duration); @@ -383,8 +393,11 @@ static void regenerate_all_timer_duration(void) ogs_assert(local_conf.time.message.gtp.t3_holding_duration); #if 0 - ogs_trace("%lld, %lld, %lld, %d, %lld, %d %lld, %d, %lld, %d, %lld", + ogs_trace("%lld, %lld, %lld, %lld, %lld, %lld, %d, %lld, %d %lld, %d, %lld, %d, %lld", (long long)local_conf.time.message.duration, + (long long)local_conf.time.message.sbi_duration, + (long long)local_conf.time.message.gtp_duration, + (long long)local_conf.time.message.pfcp_duration, (long long)local_conf.time.message.sbi.client_wait_duration, (long long)local_conf.time.message.sbi.connection_deadline, local_conf.time.message.pfcp.n1_response_rcount, @@ -413,7 +426,6 @@ static int local_conf_prepare(void) /* 86400 seconds = 1 day */ local_conf.time.subscription.validity_duration = 86400; - /* * Message Wait Duration : 10 seconds (Default) * @@ -423,7 +435,15 @@ static int local_conf_prepare(void) * the paging failure result to GTPv2-C or HTTP2(SBI). */ local_conf.time.message.duration = ogs_time_from_sec(10); + local_conf.time.message.sbi_set = false; + local_conf.time.message.gtp_set = false; + local_conf.time.message.pfcp_set = false; + +#define PFCP_N1_RESPONSE_RETRY_COUNT 3 +#define GTP_N3_RESPONSE_RETRY_COUNT 3 + local_conf.time.message.pfcp.n1_response_rcount = PFCP_N1_RESPONSE_RETRY_COUNT; + local_conf.time.message.gtp.n3_response_rcount = GTP_N3_RESPONSE_RETRY_COUNT; /* * Handover Wait Duration : 300 ms (Default) * @@ -588,6 +608,45 @@ int ogs_app_parse_local_conf(const char *local) ogs_time_from_msec(atoll(v)); regenerate_all_timer_duration(); } + } else if (!strcmp(msg_key, "sbi_duration")) { + const char *v = + ogs_yaml_iter_value(&msg_iter); + if (v) { + local_conf.time.message.sbi_set = true; + local_conf.time.message.sbi_duration = + ogs_time_from_msec(atoll(v)); + regenerate_all_timer_duration(); + } + } else if (!strcmp(msg_key, "gtp_duration")) { + const char *v = + ogs_yaml_iter_value(&msg_iter); + if (v) { + local_conf.time.message.gtp_set = true; + local_conf.time.message.gtp_duration = + ogs_time_from_msec(atoll(v)); + regenerate_all_timer_duration(); + } + } else if (!strcmp(msg_key, "pfcp_duration")) { + const char *v = + ogs_yaml_iter_value(&msg_iter); + if (v) { + local_conf.time.message.pfcp_set = true; + local_conf.time.message.pfcp_duration = + ogs_time_from_msec(atoll(v)); + regenerate_all_timer_duration(); + } + } else if (!strcmp(msg_key, "pfcp_n1")) { + const char *v = ogs_yaml_iter_value(&msg_iter); + if (v) { + local_conf.time.message.pfcp.n1_response_rcount = atoi(v); + regenerate_all_timer_duration(); + } + } else if (!strcmp(msg_key, "gtp_n3")) { + const char *v = ogs_yaml_iter_value(&msg_iter); + if (v) { + local_conf.time.message.gtp.n3_response_rcount = atoi(v); + regenerate_all_timer_duration(); + } } else ogs_warn("unknown key `%s`", msg_key); } diff --git a/lib/app/ogs-config.h b/lib/app/ogs-config.h index 3085943a2e..841c2075c3 100644 --- a/lib/app/ogs-config.h +++ b/lib/app/ogs-config.h @@ -94,6 +94,13 @@ typedef struct ogs_local_conf_s { struct { ogs_time_t duration; + ogs_time_t sbi_duration; + ogs_time_t gtp_duration; + ogs_time_t pfcp_duration; + bool sbi_set; + bool gtp_set; + bool pfcp_set; + struct { ogs_time_t client_wait_duration; ogs_time_t connection_deadline; diff --git a/lib/sbi/message.c b/lib/sbi/message.c index f7c99a4b3f..850ca4ab59 100644 --- a/lib/sbi/message.c +++ b/lib/sbi/message.c @@ -679,9 +679,9 @@ ogs_sbi_request_t *ogs_sbi_build_request(ogs_sbi_message_t *message) ogs_sbi_header_set(request->http.headers, OGS_SBI_OPTIONAL_CUSTOM_SENDER_TIMESTAMP, sender_timestamp); - ogs_assert(ogs_time_to_msec(ogs_local_conf()->time.message.duration)); + ogs_assert(ogs_time_to_msec(ogs_local_conf()->time.message.sbi_duration)); max_rsp_time = ogs_msprintf("%d", - (int)ogs_time_to_msec(ogs_local_conf()->time.message.duration)); + (int)ogs_time_to_msec(ogs_local_conf()->time.message.sbi_duration)); ogs_sbi_header_set(request->http.headers, OGS_SBI_OPTIONAL_CUSTOM_MAX_RSP_TIME, max_rsp_time); ogs_free(max_rsp_time);