diff --git a/configs/310014.yaml.in b/configs/310014.yaml.in index 1ca21daf4..2465326af 100644 --- a/configs/310014.yaml.in +++ b/configs/310014.yaml.in @@ -4,6 +4,7 @@ logger: parameter: # no_nrf: true +# no_scp: true # no_amf: true # no_smf: true # no_upf: true @@ -194,6 +195,11 @@ nrf: - ::1 port: 7777 +scp: + sbi: + - addr: 127.0.1.10 + port: 7777 + ausf: sbi: - addr: 127.0.0.11 diff --git a/configs/csfb.yaml.in b/configs/csfb.yaml.in index 53c2c5457..60dd81f8f 100644 --- a/configs/csfb.yaml.in +++ b/configs/csfb.yaml.in @@ -4,6 +4,7 @@ logger: parameter: # no_nrf: true +# no_scp: true # no_amf: true # no_smf: true # no_upf: true diff --git a/configs/non3gpp.yaml.in b/configs/non3gpp.yaml.in index 36882612a..bbbb5992a 100644 --- a/configs/non3gpp.yaml.in +++ b/configs/non3gpp.yaml.in @@ -4,6 +4,7 @@ logger: parameter: # no_nrf: true +# no_scp: true # no_amf: true # no_smf: true # no_upf: true diff --git a/configs/open5gs/meson.build b/configs/open5gs/meson.build index 80fe9124c..9b0849210 100644 --- a/configs/open5gs/meson.build +++ b/configs/open5gs/meson.build @@ -29,6 +29,7 @@ open5gs_conf = ''' hss.yaml pcrf.yaml nrf.yaml + scp.yaml ausf.yaml udm.yaml udr.yaml diff --git a/configs/open5gs/scp.yaml.in b/configs/open5gs/scp.yaml.in new file mode 100644 index 000000000..7ca6543a8 --- /dev/null +++ b/configs/open5gs/scp.yaml.in @@ -0,0 +1,213 @@ +db_uri: mongodb://localhost/open5gs + +# +# logger: +# +# o Set OGS_LOG_INFO to all domain level +# - If `level` is omitted, the default level is OGS_LOG_INFO) +# - If `domain` is omitted, the all domain level is set from 'level' +# (Nothing is needed) +# +# o Set OGS_LOG_ERROR to all domain level +# - `level` can be set with none, fatal, error, warn, info, debug, trace +# level: error +# +# o Set OGS_LOG_DEBUG to mme/emm domain level +# level: debug +# domain: mme,emm +# +# o Set OGS_LOG_TRACE to all domain level +# level: trace +# domain: core,sbi,scp,event,tlv,mem,sock +# +logger: + file: @localstatedir@/log/open5gs/scp.log + +# +# scp: +# +# +# +# o SBI Server(http://:80) +# sbi: +# +# o SBI Server(http://:80) +# sbi: +# - addr: +# - 0.0.0.0 +# - ::0 +# port: 7777 +# +# o SBI Server(https://:443) +# sbi: +# - tls: +# key: scp.key +# pem: scp.pem +# +# o SBI Server(https://127.0.1.10:443, http://[::1]:80) +# sbi: +# - addr: 127.0.1.10 +# tls: +# key: scp.key +# pem: scp.pem +# - addr: ::1 +# +# o SBI Server(http://scp.open5gs.org:80) +# sbi: +# - name: scp.open5gs.org +# +# o SBI Server(http://127.0.1.10:7777) +# sbi: +# - addr: 127.0.1.10 +# port: 7777 +# +# o SBI Server(http://:80) +# sbi: +# - dev: eth0 +# +# o Provide custom SBI address to be advertised to NRF +# sbi: +# - dev: eth0 +# advertise: open5gs-scp.svc.local +# +# sbi: +# - addr: localhost +# advertise: +# - 127.0.0.99 +# - ::1 +# +# o SBI Option (Default) +# - tcp_nodelay : true +# - so_linger.l_onoff : false +# +# sbi: +# addr: 127.0.1.10 +# option: +# tcp_nodelay: false +# so_linger: +# l_onoff: true +# l_linger: 10 +# +# +# +# o Next hop SCP Server(https://127.0.1.11:7777) +# next_scp: +# sbi: +# - addr: 127.0.1.11 +# port: 7777 +# +# +# +# o NF Discovery and Selection +# for indirect communication with Delegated Discovery; +# +# o delegated: +# o auto: (Default) +# Use next-hop SCP if next-hop SCP avaiable. Otherwise NRF is used. +# => App fails if both next-hop SCP and NRF are unavailable. +# o yes: Use next-hop SCP always. +# => App fails if no next-hop SCP available. +# o no: Don't use next-hop SCP server. +# => App fails if no NRF available. +# +# next_scp: +# sbi: +# - addr: 127.0.1.11 +# port: 7777 +# discovery: +# delegated: auto|yes|no +# +scp: + sbi: + - addr: 127.0.1.10 + port: 7777 + +# +# nrf: +# +# > +# +# o SBI Client(http://127.0.0.10:7777) +# sbi: +# addr: 127.0.0.10 +# port: 7777 +# +# o SBI Client(https://127.0.0.10:443, http://nrf.open5gs.org:80) +# sbi: +# - addr: 127.0.0.10 +# tls: +# key: nrf.key +# pem: nrf.pem +# - name: nrf.open5gs.org +# +# o SBI Client(http://[fd69:f21d:873c:fa::1]:80) +# If prefer_ipv4 is true, http://127.0.0.10:80 is selected. +# +# sbi: +# addr: +# - 127.0.0.10 +# - fd69:f21d:873c:fa::1 +# +# o SBI Option (Default) +# - tcp_nodelay : true +# - so_linger.l_onoff : false +# +# sbi: +# addr: 127.0.0.10 +# option: +# tcp_nodelay: false +# so_linger: +# l_onoff: true +# l_linger: 10 +# +nrf: + sbi: + - addr: + - 127.0.0.10 + - ::1 + port: 7777 + +# +# parameter: +# +# o Disable use of IPv4 addresses (only IPv6) +# no_ipv4: true +# +# o Disable use of IPv6 addresses (only IPv4) +# no_ipv6: true +# +# o Prefer IPv4 instead of IPv6 for estabishing new GTP connections. +# prefer_ipv4: true +# +parameter: + +# +# max: +# +# o Maximum Number of UE per AMF/MME +# ue: 1024 +# o Maximum Number of gNB/eNB per AMF/MME +# gnb: 64 +# +max: + +# +# time: +# +# o NF Instance Heartbeat (Default : 0) +# NFs will not send heart-beat timer in NFProfile +# NRF will send heart-beat timer in NFProfile +# +# o NF Instance Heartbeat (20 seconds) +# NFs will send heart-beat timer (20 seconds) in NFProfile +# NRF can change heart-beat timer in NFProfile +# +# nf_instance: +# heartbeat: 20 +# +# o Message Wait Duration (Default : 10,000 ms = 10 seconds) +# +# o Message Wait Duration (3000 ms) +# message: +# duration: 3000 +time: diff --git a/configs/sample.yaml.in b/configs/sample.yaml.in index e9efe8e01..ae4e41b1d 100644 --- a/configs/sample.yaml.in +++ b/configs/sample.yaml.in @@ -4,6 +4,7 @@ logger: parameter: # no_nrf: true +# no_scp: true # no_amf: true # no_smf: true # no_upf: true @@ -194,6 +195,70 @@ nrf: - ::1 port: 7777 +# +# scp: +# +# > +# +# o SBI Client(http://127.0.0.10:7777) +# sbi: +# addr: 127.0.0.10 +# port: 7777 +# +# o SBI Client(https://127.0.0.10:443, http://scp.open5gs.org:80) +# sbi: +# - addr: 127.0.0.10 +# tls: +# key: scp.key +# pem: scp.pem +# - name: scp.open5gs.org +# +# o SBI Client(http://[fd69:f21d:873c:fa::1]:80) +# If prefer_ipv4 is true, http://127.0.0.10:80 is selected. +# +# sbi: +# addr: +# - 127.0.0.10 +# - fd69:f21d:873c:fa::1 +# +# o SBI Option (Default) +# - tcp_nodelay : true +# - so_linger.l_onoff : false +# +# sbi: +# addr: 127.0.0.10 +# option: +# tcp_nodelay: false +# so_linger: +# l_onoff: true +# l_linger: 10 +# +# +# +# o NF Discovery and Selection +# for indirect communication with Delegated Discovery; +# +# o delegated: +# o auto: (Default) +# Use SCP if SCP avaiable. Otherwise NRF is used. +# => App fails if both NRF and SCP are unavailable. +# o yes: Use SCP always. +# => App fails if no SCP available. +# o no: Don't use SCP server. +# => App fails if no NRF available. +# +# scp: +# sbi: +# - addr: 127.0.1.10 +# port: 7777 +# discovery: +# delegated: auto|yes|no +# +scp: + sbi: + - addr: 127.0.1.10 + port: 7777 + ausf: sbi: - addr: 127.0.0.11 diff --git a/configs/slice.yaml.in b/configs/slice.yaml.in index d48f77908..1d21c1fd1 100644 --- a/configs/slice.yaml.in +++ b/configs/slice.yaml.in @@ -4,6 +4,7 @@ logger: parameter: # no_nrf: true + no_scp: true # no_amf: true # no_smf: true # no_upf: true diff --git a/configs/srslte.yaml.in b/configs/srslte.yaml.in index f18bc3ca0..b6811c5c5 100644 --- a/configs/srslte.yaml.in +++ b/configs/srslte.yaml.in @@ -4,6 +4,7 @@ logger: parameter: # no_nrf: true +# no_scp: true # no_amf: true # no_smf: true # no_upf: true diff --git a/configs/volte.yaml.in b/configs/volte.yaml.in index 37f9de6c2..90b9805c5 100644 --- a/configs/volte.yaml.in +++ b/configs/volte.yaml.in @@ -4,6 +4,7 @@ logger: parameter: # no_nrf: true +# no_scp: true # no_amf: true # no_smf: true # no_upf: true diff --git a/configs/vonr.yaml.in b/configs/vonr.yaml.in index 616bbd72f..93a4910f3 100644 --- a/configs/vonr.yaml.in +++ b/configs/vonr.yaml.in @@ -4,6 +4,7 @@ logger: parameter: # no_nrf: true +# no_scp: true # no_amf: true # no_smf: true # no_upf: true @@ -199,6 +200,11 @@ nrf: - ::1 port: 7777 +scp: + sbi: + - addr: 127.0.1.10 + port: 7777 + ausf: sbi: - addr: 127.0.0.11 diff --git a/lib/app/ogs-app.h b/lib/app/ogs-app.h index 78a446c29..c6b13cf5d 100644 --- a/lib/app/ogs-app.h +++ b/lib/app/ogs-app.h @@ -94,6 +94,9 @@ void smf_terminate(void); int amf_initialize(void); void amf_terminate(void); +int scp_initialize(void); +void scp_terminate(void); + #ifdef __cplusplus } #endif diff --git a/lib/app/ogs-context.c b/lib/app/ogs-context.c index 0df85204b..709333e50 100644 --- a/lib/app/ogs-context.c +++ b/lib/app/ogs-context.c @@ -113,7 +113,7 @@ static void regenerate_all_timer_duration(void) ogs_max(ogs_time_from_sec(3), self.time.message.sbi.client_wait_duration + ogs_time_from_sec(1)); self.time.message.sbi.nf_register_interval_in_exception = - ogs_time_from_msec(300); + ogs_time_from_sec(2); #define PFCP_N1_RESPONSE_RETRY_COUNT 3 self.time.message.pfcp.n1_response_rcount = PFCP_N1_RESPONSE_RETRY_COUNT; @@ -316,6 +316,9 @@ int ogs_app_context_parse_config(void) } else if (!strcmp(parameter_key, "no_nrf")) { self.parameter.no_nrf = ogs_yaml_iter_bool(¶meter_iter); + } else if (!strcmp(parameter_key, "no_scp")) { + self.parameter.no_scp = + ogs_yaml_iter_bool(¶meter_iter); } else if (!strcmp(parameter_key, "no_amf")) { self.parameter.no_amf = ogs_yaml_iter_bool(¶meter_iter); diff --git a/lib/app/ogs-context.h b/lib/app/ogs-context.h index a8cfc099d..92cf59b8e 100644 --- a/lib/app/ogs-context.h +++ b/lib/app/ogs-context.h @@ -64,6 +64,7 @@ typedef struct ogs_app_context_s { int no_nssf; int no_bsf; int no_udr; + int no_scp; int no_nrf; /* Network */ diff --git a/lib/sbi/client.c b/lib/sbi/client.c index b8377c2cf..c0ae099df 100644 --- a/lib/sbi/client.c +++ b/lib/sbi/client.c @@ -176,6 +176,26 @@ ogs_sbi_client_t *ogs_sbi_client_find(ogs_sockaddr_t *addr) return client; } +void ogs_sbi_client_stop(ogs_sbi_client_t *client) +{ + connection_t *conn = NULL; + + ogs_assert(client); + + ogs_list_for_each(&client->connection_list, conn) { + ogs_assert(conn->client_cb); + conn->client_cb(OGS_DONE, NULL, conn->data); + } +} + +void ogs_sbi_client_stop_all(void) +{ + ogs_sbi_client_t *client = NULL; + + ogs_list_for_each(&ogs_sbi_self()->client_list, client) + ogs_sbi_client_stop(client); +} + #define mycase(code) \ case code: s = OGS_STRINGIFY(code) @@ -246,6 +266,8 @@ static char *add_params_to_uri(CURL *easy, char *uri, ogs_hash_t *params) return uri; } +static void _connection_remove(connection_t *conn); + static connection_t *connection_add( ogs_sbi_client_t *client, ogs_sbi_client_cb_f client_cb, ogs_sbi_request_t *request, void *data) @@ -269,19 +291,31 @@ static connection_t *connection_add( conn->data = data; conn->method = ogs_strdup(request->h.method); - ogs_expect_or_return_val(conn->method, NULL); + if (!conn->method) { + ogs_error("conn->method is NULL"); + _connection_remove(conn); + return NULL; + } conn->num_of_header = ogs_hash_count(request->http.headers); if (conn->num_of_header) { conn->headers = ogs_calloc(conn->num_of_header, sizeof(char *)); - ogs_expect_or_return_val(conn->headers, NULL); + if (!conn->headers) { + ogs_error("conn->headers is NULL"); + _connection_remove(conn); + return NULL; + } for (hi = ogs_hash_first(request->http.headers), i = 0; hi && i < conn->num_of_header; hi = ogs_hash_next(hi), i++) { const char *key = ogs_hash_this_key(hi); char *val = ogs_hash_this_val(hi); conn->headers[i] = ogs_msprintf("%s: %s", key, val); - ogs_expect_or_return_val(conn->headers[i], NULL); + if (!conn->headers[i]) { + ogs_error("conn->headers[i=%d] is NULL", i); + _connection_remove(conn); + return NULL; + } conn->header_list = curl_slist_append( conn->header_list, conn->headers[i]); } @@ -289,9 +323,11 @@ static connection_t *connection_add( conn->timer = ogs_timer_add( ogs_app()->timer_mgr, connection_timer_expired, conn); - ogs_expect_or_return_val(conn->timer, NULL); - - ogs_list_add(&client->connection_list, conn); + if (!conn->timer) { + ogs_error("conn->timer is NULL"); + _connection_remove(conn); + return NULL; + } /* If http response is not received within deadline, * Open5GS will discard this request. */ @@ -299,7 +335,23 @@ static connection_t *connection_add( ogs_app()->time.message.sbi.connection_deadline); conn->easy = curl_easy_init(); - ogs_assert(conn->easy); + if (!conn->easy) { + ogs_error("conn->easy is NULL"); + _connection_remove(conn); + return NULL; + } + + if (ogs_hash_count(request->http.params)) { + char *uri = add_params_to_uri(conn->easy, + request->h.uri, request->http.params); + if (!uri) { + ogs_error("add_params_to_uri() failed"); + _connection_remove(conn); + return NULL; + } + + request->h.uri = uri; + } /* HTTP Method */ if (strcmp(request->h.method, OGS_SBI_HTTP_METHOD_PUT) == 0 || @@ -312,7 +364,11 @@ static connection_t *connection_add( if (request->http.content) { conn->content = ogs_memdup( request->http.content, request->http.content_length); - ogs_assert(conn->content); + if (!conn->content) { + ogs_error("conn->content is NULL"); + _connection_remove(conn); + return NULL; + } curl_easy_setopt(conn->easy, CURLOPT_POSTFIELDS, conn->content); curl_easy_setopt(conn->easy, @@ -336,11 +392,7 @@ static connection_t *connection_add( CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_2_PRIOR_KNOWLEDGE); #endif - if (ogs_hash_count(request->http.params)) { - request->h.uri = add_params_to_uri(conn->easy, - request->h.uri, request->http.params); - ogs_expect_or_return_val(request->h.uri, NULL); - } + ogs_list_add(&client->connection_list, conn); curl_easy_setopt(conn->easy, CURLOPT_URL, request->h.uri); @@ -358,27 +410,11 @@ static connection_t *connection_add( return conn; } -static void connection_remove(connection_t *conn) +static void _connection_remove(connection_t *conn) { - ogs_sbi_client_t *client = NULL; int i; ogs_assert(conn); - client = conn->client; - ogs_assert(client); - - ogs_list_remove(&client->connection_list, conn); - - ogs_assert(conn->timer); - ogs_timer_delete(conn->timer); - - ogs_assert(conn->easy); - ogs_assert(client->multi); - curl_multi_remove_handle(client->multi, conn->easy); - curl_easy_cleanup(conn->easy); - - ogs_assert(conn->method); - ogs_free(conn->method); if (conn->content) ogs_free(conn->content); @@ -386,19 +422,45 @@ static void connection_remove(connection_t *conn) if (conn->location) ogs_free(conn->location); + if (conn->memory) + ogs_free(conn->memory); + + if (conn->easy) + curl_easy_cleanup(conn->easy); + + if (conn->timer) + ogs_timer_delete(conn->timer); + if (conn->num_of_header) { for (i = 0; i < conn->num_of_header; i++) - ogs_free(conn->headers[i]); + if (conn->headers[i]) + ogs_free(conn->headers[i]); ogs_free(conn->headers); } curl_slist_free_all(conn->header_list); - if (conn->memory) - ogs_free(conn->memory); + if (conn->method) + ogs_free(conn->method); ogs_pool_free(&connection_pool, conn); } +static void connection_remove(connection_t *conn) +{ + ogs_sbi_client_t *client = NULL; + + ogs_assert(conn); + client = conn->client; + ogs_assert(client); + + ogs_list_remove(&client->connection_list, conn); + + ogs_assert(client->multi); + curl_multi_remove_handle(client->multi, conn->easy); + + _connection_remove(conn); +} + static void connection_remove_all(ogs_sbi_client_t *client) { connection_t *conn = NULL, *next_conn = NULL; @@ -416,6 +478,11 @@ static void connection_timer_expired(void *data) conn = data; ogs_assert(conn); + ogs_error("Connection timer expired"); + + ogs_assert(conn->client_cb); + conn->client_cb(OGS_TIMEUP, NULL, conn->data); + connection_remove(conn); } @@ -487,12 +554,12 @@ static void check_multi_info(ogs_sbi_client_t *client) if (conn->location) ogs_sbi_header_set(response->http.headers, OGS_SBI_LOCATION, conn->location); - - ogs_assert(conn->client_cb); - conn->client_cb(response, conn->data); } else ogs_warn("[%d] %s", res, conn->error); + ogs_assert(conn->client_cb); + conn->client_cb(res == CURLE_OK ? OGS_OK : OGS_ERROR, + response, conn->data); connection_remove(conn); break; default: @@ -502,7 +569,7 @@ static void check_multi_info(ogs_sbi_client_t *client) } } -bool ogs_sbi_client_send_request( +bool ogs_sbi_client_send_reqmem_persistent( ogs_sbi_client_t *client, ogs_sbi_client_cb_f client_cb, ogs_sbi_request_t *request, void *data) { @@ -513,17 +580,128 @@ bool ogs_sbi_client_send_request( if (request->h.uri == NULL) { request->h.uri = ogs_sbi_client_uri(client, &request->h); + ogs_expect_or_return_val(request->h.uri, false); } ogs_debug("[%s] %s", request->h.method, request->h.uri); conn = connection_add(client, client_cb, request, data); ogs_expect_or_return_val(conn, false); + return true; +} + +bool ogs_sbi_client_send_request( + ogs_sbi_client_t *client, ogs_sbi_client_cb_f client_cb, + ogs_sbi_request_t *request, void *data) +{ + bool rc; + + ogs_assert(client); + ogs_assert(request); + + rc = ogs_sbi_client_send_reqmem_persistent( + client, client_cb, request, data); + ogs_expect(rc == true); + ogs_sbi_request_free(request); + return rc; +} + +bool ogs_sbi_scp_send_reqmem_persistent( + ogs_sbi_client_t *client, ogs_sbi_client_cb_f client_cb, + ogs_sbi_request_t *request, void *data) +{ + ogs_sbi_nf_instance_t *scp_instance = NULL; + connection_t *conn = NULL; + char *apiroot = NULL; + + ogs_assert(client); + ogs_assert(request); + + scp_instance = ogs_sbi_self()->scp_instance; + + if (scp_instance) { + /* + * In case of indirect communication using SCP, + * add 3gpp-Sbi-Target-apiRoot to HTTP header and + * change CLIENT instance to SCP. + */ + apiroot = ogs_sbi_client_apiroot(client); + ogs_assert(apiroot); + + ogs_sbi_header_set(request->http.headers, + OGS_SBI_CUSTOM_TARGET_APIROOT, apiroot); + + ogs_free(apiroot); + + client = scp_instance->client; + ogs_assert(client); + } + + if (request->h.uri == NULL) { + /* + * Regardless of direct or indirect communication, + * if there is no URI, we automatically creates a URI + * with Client Address and request->h + */ + request->h.uri = ogs_sbi_client_uri(client, &request->h); + ogs_assert(request->h.uri); + + ogs_debug("[%s] %s", request->h.method, request->h.uri); + + } else if (scp_instance) { + /* + * In case of indirect communication using SCP, + * If the full URI is already defined, change full URI to SCP as below. + * + * OLD: http://127.0.0.5:7777/nnrf-nfm/v1/nf-status-notify + * NEW: https://scp.open5gs.org/nnrf-nfm/v1/nf-status-notify + */ + char *path = NULL; + char *old = NULL; + + old = request->h.uri; + + apiroot = ogs_sbi_client_apiroot(client); + ogs_assert(apiroot); + + path = ogs_sbi_getpath_from_uri(request->h.uri); + ogs_assert(path); + + request->h.uri = ogs_msprintf("%s/%s", apiroot, path); + ogs_assert(request->h.uri); + + ogs_free(apiroot); + ogs_free(path); + ogs_free(old); + + ogs_debug("[%s] %s", request->h.method, request->h.uri); + } + + conn = connection_add(client, client_cb, request, data); + ogs_expect_or_return_val(conn, false); + return true; } +bool ogs_sbi_scp_send_request( + ogs_sbi_client_t *client, ogs_sbi_client_cb_f client_cb, + ogs_sbi_request_t *request, void *data) +{ + bool rc; + + ogs_assert(client); + ogs_assert(request); + + rc = ogs_sbi_scp_send_reqmem_persistent(client, client_cb, request, data); + ogs_expect(rc == true); + + ogs_sbi_request_free(request); + + return rc; +} + static size_t write_cb(void *contents, size_t size, size_t nmemb, void *data) { size_t realsize = 0; diff --git a/lib/sbi/client.h b/lib/sbi/client.h index 84dd3cd8a..ae93a961e 100644 --- a/lib/sbi/client.h +++ b/lib/sbi/client.h @@ -53,7 +53,8 @@ extern "C" { (__pClient)->reference_count); \ } while(0) -typedef int (*ogs_sbi_client_cb_f)(ogs_sbi_response_t *response, void *data); +typedef int (*ogs_sbi_client_cb_f)( + int status, ogs_sbi_response_t *response, void *data); typedef struct ogs_sbi_client_s { ogs_socknode_t node; @@ -84,10 +85,23 @@ void ogs_sbi_client_remove(ogs_sbi_client_t *client); void ogs_sbi_client_remove_all(void); ogs_sbi_client_t *ogs_sbi_client_find(ogs_sockaddr_t *addr); +void ogs_sbi_client_stop(ogs_sbi_client_t *client); +void ogs_sbi_client_stop_all(void); + +bool ogs_sbi_client_send_reqmem_persistent( + ogs_sbi_client_t *client, ogs_sbi_client_cb_f client_cb, + ogs_sbi_request_t *request, void *data); bool ogs_sbi_client_send_request( ogs_sbi_client_t *client, ogs_sbi_client_cb_f client_cb, ogs_sbi_request_t *request, void *data); +bool ogs_sbi_scp_send_reqmem_persistent( + ogs_sbi_client_t *client, ogs_sbi_client_cb_f client_cb, + ogs_sbi_request_t *request, void *data); +bool ogs_sbi_scp_send_request( + ogs_sbi_client_t *client, ogs_sbi_client_cb_f client_cb, + ogs_sbi_request_t *request, void *data); + #ifdef __cplusplus } #endif diff --git a/lib/sbi/context.c b/lib/sbi/context.c index 253f024d6..0228bd19e 100644 --- a/lib/sbi/context.c +++ b/lib/sbi/context.c @@ -111,7 +111,8 @@ static int ogs_sbi_context_prepare(void) return OGS_OK; } -static int ogs_sbi_context_validation(const char *local) +static int ogs_sbi_context_validation( + const char *local, const char *nrf, const char *scp) { /* If SMF is only used in 4G EPC, no SBI interface is required. */ if (strcmp(local, "smf") != 0 && @@ -120,10 +121,48 @@ static int ogs_sbi_context_validation(const char *local) return OGS_ERROR; } + if (context_initialized == 1) { + switch (self.discovery_config.delegated) { + case OGS_SBI_DISCOVERY_DELEGATED_AUTO: + if (strcmp(local, "nrf") != 0 && /* Skip NRF */ + strcmp(local, "smf") != 0 && /* Skip SMF since SMF can run 4G */ + ogs_sbi_self()->nrf_instance == NULL && + ogs_sbi_self()->scp_instance == NULL) { + ogs_error("DELEGATED_AUTO - Both NRF and %s are unavailable", + strcmp(scp, "next_scp") == 0 ? "Next-hop SCP" : "SCP"); + return OGS_ERROR; + } + break; + case OGS_SBI_DISCOVERY_DELEGATED_YES: + if (ogs_sbi_self()->scp_instance == NULL) { + ogs_error("DELEGATED_YES - no %s available", + strcmp(scp, "next_scp") == 0 ? "Next-hop SCP" : "SCP"); + return OGS_ERROR; + } + break; + case OGS_SBI_DISCOVERY_DELEGATED_NO: + if (ogs_sbi_self()->nrf_instance == NULL) { + ogs_error("DELEGATED_NO - no NRF available"); + return OGS_ERROR; + } + break; + default: + ogs_fatal("Invalid dicovery-config delegated [%d]", + self.discovery_config.delegated); + ogs_assert_if_reached(); + } + } + return OGS_OK; } -int ogs_sbi_context_parse_config(const char *local, const char *remote) +ogs_sbi_nf_instance_t *ogs_sbi_scp_instance(void) +{ + return NULL; +} + +int ogs_sbi_context_parse_config( + const char *local, const char *nrf, const char *scp) { int rv; yaml_document_t *document = NULL; @@ -363,17 +402,17 @@ int ogs_sbi_context_parse_config(const char *local, const char *remote) } } } - } else if (remote && !strcmp(root_key, remote)) { - ogs_yaml_iter_t remote_iter; - ogs_yaml_iter_recurse(&root_iter, &remote_iter); - while (ogs_yaml_iter_next(&remote_iter)) { - const char *remote_key = ogs_yaml_iter_key(&remote_iter); - ogs_assert(remote_key); - if (!strcmp(remote_key, "sbi")) { + } else if (nrf && !strcmp(root_key, nrf)) { + ogs_yaml_iter_t nrf_iter; + ogs_yaml_iter_recurse(&root_iter, &nrf_iter); + while (ogs_yaml_iter_next(&nrf_iter)) { + const char *nrf_key = ogs_yaml_iter_key(&nrf_iter); + ogs_assert(nrf_key); + if (!strcmp(nrf_key, "sbi")) { ogs_yaml_iter_t sbi_array, sbi_iter; - ogs_yaml_iter_recurse(&remote_iter, &sbi_array); + ogs_yaml_iter_recurse(&nrf_iter, &sbi_array); do { - ogs_sbi_nf_instance_t *nf_instance = NULL; + ogs_sbi_nf_instance_t *nrf_instance = NULL; ogs_sbi_client_t *client = NULL; ogs_sockaddr_t *addr = NULL; int family = AF_UNSPEC; @@ -476,12 +515,13 @@ int ogs_sbi_context_parse_config(const char *local, const char *remote) client = ogs_sbi_client_add(addr); ogs_assert(client); - nf_instance = ogs_sbi_nf_instance_add(); - ogs_assert(nf_instance); + ogs_sbi_self()->nrf_instance = + nrf_instance = ogs_sbi_nf_instance_add(); + ogs_assert(nrf_instance); ogs_sbi_nf_instance_set_type( - nf_instance, OpenAPI_nf_type_NRF); + nrf_instance, OpenAPI_nf_type_NRF); - OGS_SBI_SETUP_CLIENT(nf_instance, client); + OGS_SBI_SETUP_CLIENT(nrf_instance, client); if (key) client->tls.key = key; if (pem) client->tls.pem = pem; @@ -492,10 +532,175 @@ int ogs_sbi_context_parse_config(const char *local, const char *remote) YAML_SEQUENCE_NODE); } } + } else if (scp && !strcmp(root_key, scp)) { + ogs_yaml_iter_t scp_iter; + ogs_yaml_iter_recurse(&root_iter, &scp_iter); + while (ogs_yaml_iter_next(&scp_iter)) { + const char *scp_key = ogs_yaml_iter_key(&scp_iter); + ogs_assert(scp_key); + if (!strcmp(scp_key, "sbi")) { + ogs_yaml_iter_t sbi_array, sbi_iter; + ogs_yaml_iter_recurse(&scp_iter, &sbi_array); + do { + ogs_sbi_nf_instance_t *scp_instance = NULL; + ogs_sbi_client_t *client = NULL; + ogs_sockaddr_t *addr = NULL; + int family = AF_UNSPEC; + int i, num = 0; + const char *hostname[OGS_MAX_NUM_OF_HOSTNAME]; + uint16_t port = self.sbi_port; + const char *key = NULL; + const char *pem = NULL; + + if (ogs_yaml_iter_type(&sbi_array) == + YAML_MAPPING_NODE) { + memcpy(&sbi_iter, &sbi_array, + sizeof(ogs_yaml_iter_t)); + } else if (ogs_yaml_iter_type(&sbi_array) == + YAML_SEQUENCE_NODE) { + if (!ogs_yaml_iter_next(&sbi_array)) + break; + ogs_yaml_iter_recurse(&sbi_array, &sbi_iter); + } else if (ogs_yaml_iter_type(&sbi_array) == + YAML_SCALAR_NODE) { + break; + } else + ogs_assert_if_reached(); + + while (ogs_yaml_iter_next(&sbi_iter)) { + const char *sbi_key = + ogs_yaml_iter_key(&sbi_iter); + ogs_assert(sbi_key); + if (!strcmp(sbi_key, "family")) { + const char *v = ogs_yaml_iter_value(&sbi_iter); + if (v) family = atoi(v); + if (family != AF_UNSPEC && + family != AF_INET && family != AF_INET6) { + ogs_warn("Ignore family(%d) : " + "AF_UNSPEC(%d), " + "AF_INET(%d), AF_INET6(%d) ", + family, AF_UNSPEC, AF_INET, AF_INET6); + family = AF_UNSPEC; + } + } else if (!strcmp(sbi_key, "addr") || + !strcmp(sbi_key, "name")) { + ogs_yaml_iter_t hostname_iter; + ogs_yaml_iter_recurse(&sbi_iter, + &hostname_iter); + ogs_assert(ogs_yaml_iter_type(&hostname_iter) != + YAML_MAPPING_NODE); + + do { + if (ogs_yaml_iter_type(&hostname_iter) == + YAML_SEQUENCE_NODE) { + if (!ogs_yaml_iter_next(&hostname_iter)) + break; + } + + ogs_assert(num < OGS_MAX_NUM_OF_HOSTNAME); + hostname[num++] = + ogs_yaml_iter_value(&hostname_iter); + } while ( + ogs_yaml_iter_type(&hostname_iter) == + YAML_SEQUENCE_NODE); + } else if (!strcmp(sbi_key, "port")) { + const char *v = ogs_yaml_iter_value(&sbi_iter); + if (v) port = atoi(v); + } else if (!strcmp(sbi_key, "tls")) { + ogs_yaml_iter_t tls_iter; + ogs_yaml_iter_recurse(&sbi_iter, &tls_iter); + + while (ogs_yaml_iter_next(&tls_iter)) { + const char *tls_key = + ogs_yaml_iter_key(&tls_iter); + ogs_assert(tls_key); + + if (!strcmp(tls_key, "key")) { + key = ogs_yaml_iter_value(&tls_iter); + } else if (!strcmp(tls_key, "pem")) { + pem = ogs_yaml_iter_value(&tls_iter); + } else + ogs_warn("unknown key `%s`", tls_key); + } + } else if (!strcmp(sbi_key, "advertise")) { + /* Nothing in client */ + } else + ogs_warn("unknown key `%s`", sbi_key); + } + + addr = NULL; + for (i = 0; i < num; i++) { + rv = ogs_addaddrinfo(&addr, + family, hostname[i], port, 0); + ogs_assert(rv == OGS_OK); + } + + ogs_filter_ip_version(&addr, + ogs_app()->parameter.no_ipv4, + ogs_app()->parameter.no_ipv6, + ogs_app()->parameter.prefer_ipv4); + + if (addr == NULL) continue; + + client = ogs_sbi_client_add(addr); + ogs_assert(client); + + ogs_sbi_self()->scp_instance = + scp_instance = ogs_sbi_nf_instance_add(); + ogs_assert(scp_instance); + ogs_sbi_nf_instance_set_type( + scp_instance, OpenAPI_nf_type_SCP); + + OGS_SBI_SETUP_CLIENT(scp_instance, client); + + if (key) client->tls.key = key; + if (pem) client->tls.pem = pem; + + ogs_freeaddrinfo(addr); + + } while (ogs_yaml_iter_type(&sbi_array) == + YAML_SEQUENCE_NODE); + } else if (!strcmp(scp_key, "discovery")) { + ogs_yaml_iter_t discovery_iter; + yaml_node_t *node = yaml_document_get_node( + document, scp_iter.pair->value); + ogs_assert(node); + ogs_assert(node->type == YAML_MAPPING_NODE); + ogs_yaml_iter_recurse(&scp_iter, &discovery_iter); + while (ogs_yaml_iter_next(&discovery_iter)) { + const char *discovery_key = + ogs_yaml_iter_key(&discovery_iter); + ogs_assert(discovery_key); + if (!strcmp(discovery_key, "delegated")) { + yaml_node_t *discovery_node = + yaml_document_get_node(document, + discovery_iter.pair->value); + ogs_assert(discovery_node->type == + YAML_SCALAR_NODE); + const char* delegated = + ogs_yaml_iter_value(&discovery_iter); + if (!strcmp(delegated, "auto")) + self.discovery_config.delegated = + OGS_SBI_DISCOVERY_DELEGATED_AUTO; + else if (!strcmp(delegated, "yes")) + self.discovery_config.delegated = + OGS_SBI_DISCOVERY_DELEGATED_YES; + else if (!strcmp(delegated, "no")) + self.discovery_config.delegated = + OGS_SBI_DISCOVERY_DELEGATED_NO; + else + ogs_warn("unknown 'delegated' value `%s`", + delegated); + } else + ogs_warn("unknown key `%s`", + discovery_key); + } + } + } } } - rv = ogs_sbi_context_validation(local); + rv = ogs_sbi_context_validation(local, nrf, scp); if (rv != OGS_OK) return rv; return OGS_OK; @@ -515,19 +720,6 @@ ogs_sbi_nf_instance_t *ogs_sbi_nf_instance_add(void) nf_instance->time.heartbeat_interval = ogs_app()->time.nf_instance.heartbeat_interval; - nf_instance->t_registration_interval = ogs_timer_add( - ogs_app()->timer_mgr, NULL, nf_instance); - ogs_assert(nf_instance->t_registration_interval); - nf_instance->t_heartbeat_interval = ogs_timer_add( - ogs_app()->timer_mgr, NULL, nf_instance); - ogs_assert(nf_instance->t_heartbeat_interval); - nf_instance->t_no_heartbeat = ogs_timer_add( - ogs_app()->timer_mgr, NULL, nf_instance); - ogs_assert(nf_instance->t_no_heartbeat); - nf_instance->t_validity = ogs_timer_add( - ogs_app()->timer_mgr, NULL, nf_instance); - ogs_assert(nf_instance->t_validity); - nf_instance->priority = OGS_SBI_DEFAULT_PRIORITY; nf_instance->capacity = OGS_SBI_DEFAULT_CAPACITY; nf_instance->load = OGS_SBI_DEFAULT_LOAD; @@ -625,11 +817,6 @@ void ogs_sbi_nf_instance_remove(ogs_sbi_nf_instance_t *nf_instance) ogs_free(nf_instance->id); } - ogs_timer_delete(nf_instance->t_registration_interval); - ogs_timer_delete(nf_instance->t_heartbeat_interval); - ogs_timer_delete(nf_instance->t_no_heartbeat); - ogs_timer_delete(nf_instance->t_validity); - if (nf_instance->client) ogs_sbi_client_remove(nf_instance->client); diff --git a/lib/sbi/context.h b/lib/sbi/context.h index cb14da7ee..77a6d58e2 100644 --- a/lib/sbi/context.h +++ b/lib/sbi/context.h @@ -36,8 +36,20 @@ typedef struct ogs_sbi_client_s ogs_sbi_client_t; typedef struct ogs_sbi_smf_info_s ogs_sbi_smf_info_t; typedef struct ogs_sbi_nf_instance_s ogs_sbi_nf_instance_t; +typedef enum { + OGS_SBI_DISCOVERY_DELEGATED_AUTO = 0, + OGS_SBI_DISCOVERY_DELEGATED_YES, + OGS_SBI_DISCOVERY_DELEGATED_NO, +} ogs_sbi_discovery_delegated_mode; + +typedef struct ogs_sbi_discovery_config_s { + ogs_sbi_discovery_delegated_mode delegated; +} ogs_sbi_discovery_config_t; + typedef struct ogs_sbi_context_s { - uint32_t sbi_port; /* SBI local port */ + ogs_sbi_discovery_config_t discovery_config; /* SCP Discovery Delegated */ + + uint32_t sbi_port; /* SBI local port */ ogs_list_t server_list; ogs_list_t client_list; @@ -47,25 +59,28 @@ typedef struct ogs_sbi_context_s { ogs_list_t nf_instance_list; ogs_list_t subscription_list; - ogs_sbi_nf_instance_t *nf_instance; /* SELF NF Instance */ + ogs_sbi_nf_instance_t *nf_instance; /* SELF NF Instance */ + ogs_sbi_nf_instance_t *nrf_instance; /* NRF Instance */ + ogs_sbi_nf_instance_t *scp_instance; /* SCP Instance */ const char *content_encoding; + } ogs_sbi_context_t; typedef struct ogs_sbi_nf_instance_s { ogs_lnode_t lnode; - ogs_fsm_t sm; /* A state machine */ - ogs_timer_t *t_registration_interval; /* timer to retry - to register peer node */ + ogs_fsm_t sm; /* A state machine */ + ogs_timer_t *t_registration_interval; /* timer to retry + to register peer node */ struct { int heartbeat_interval; int validity_duration; } time; - ogs_timer_t *t_heartbeat_interval; /* heartbeat interval */ - ogs_timer_t *t_no_heartbeat; /* check heartbeat */ - ogs_timer_t *t_validity; /* check validation */ + ogs_timer_t *t_heartbeat_interval; /* heartbeat interval */ + ogs_timer_t *t_no_heartbeat; /* check heartbeat */ + ogs_timer_t *t_validity; /* check validation */ #define NF_INSTANCE_IS_SELF(_iD) \ (_iD) && ogs_sbi_self()->nf_instance && \ @@ -77,7 +92,7 @@ typedef struct ogs_sbi_nf_instance_s { #define NF_INSTANCE_IS_NRF(__nFInstance) \ ((__nFInstance->nf_type) == OpenAPI_nf_type_NRF) - char *id; /* NFInstanceId */ + char *id; /* NFInstanceId */ OpenAPI_nf_type_e nf_type; OpenAPI_nf_status_e nf_status; @@ -103,12 +118,12 @@ typedef struct ogs_sbi_nf_instance_s { ogs_list_t nf_service_list; - void *client; /* only used in CLIENT */ - unsigned int reference_count; /* reference count for memory free */ + void *client; /* only used in CLIENT */ + unsigned int reference_count; /* reference count for memory free */ ogs_list_t nf_info_list; - OpenAPI_nf_profile_t *nf_profile; /* stored NF Profile */ + OpenAPI_nf_profile_t *nf_profile; /* stored NF Profile */ } ogs_sbi_nf_instance_t; typedef struct ogs_sbi_nf_type_array_s { @@ -196,19 +211,19 @@ typedef struct ogs_sbi_subscription_s { int validity_duration; } time; - ogs_timer_t *t_validity; /* check validation */ + ogs_timer_t *t_validity; /* check validation */ - char *id; /* SubscriptionId */ - char *req_nf_instance_id; /* reqNfInstanceId */ - OpenAPI_nf_type_e req_nf_type; /* reqNfType */ + char *id; /* SubscriptionId */ + char *req_nf_instance_id; /* reqNfInstanceId */ + OpenAPI_nf_type_e req_nf_type; /* reqNfType */ OpenAPI_nf_status_e nf_status; char *notification_uri; struct { - OpenAPI_nf_type_e nf_type; /* nfType */ + OpenAPI_nf_type_e nf_type; /* nfType */ } subscr_cond; - void *client; /* only used in SERVER */ + void *client; /* only used in SERVER */ } ogs_sbi_subscription_t; typedef struct ogs_sbi_smf_info_s { @@ -249,7 +264,10 @@ typedef struct ogs_sbi_nf_info_s { void ogs_sbi_context_init(void); void ogs_sbi_context_final(void); ogs_sbi_context_t *ogs_sbi_self(void); -int ogs_sbi_context_parse_config(const char *local, const char *remote); +int ogs_sbi_context_parse_config( + const char *local, const char *nrf, const char *scp); + +ogs_sbi_nf_instance_t *ogs_sbi_scp_instance(void); ogs_sbi_nf_instance_t *ogs_sbi_nf_instance_add(void); void ogs_sbi_nf_instance_set_id(ogs_sbi_nf_instance_t *nf_instance, char *id); diff --git a/lib/sbi/conv.c b/lib/sbi/conv.c index 9da454554..f7a071235 100644 --- a/lib/sbi/conv.c +++ b/lib/sbi/conv.c @@ -29,7 +29,6 @@ char *ogs_uridup(bool https, ogs_sockaddr_t *addr, ogs_sbi_header_t *h) char *hostname = NULL; ogs_assert(addr); - ogs_assert(h); p = uri; last = uri + OGS_HUGE_LEN; @@ -61,16 +60,18 @@ char *ogs_uridup(bool https, ogs_sockaddr_t *addr, ogs_sbi_header_t *h) } /* API */ - ogs_assert(h->service.name); - p = ogs_slprintf(p, last, "/%s", h->service.name); - ogs_assert(h->api.version); - p = ogs_slprintf(p, last, "/%s", h->api.version); + if (h) { + ogs_assert(h->service.name); + p = ogs_slprintf(p, last, "/%s", h->service.name); + ogs_assert(h->api.version); + p = ogs_slprintf(p, last, "/%s", h->api.version); - /* Resource */ - ogs_assert(h->resource.component[0]); - for (i = 0; i < OGS_SBI_MAX_NUM_OF_RESOURCE_COMPONENT && - h->resource.component[i]; i++) - p = ogs_slprintf(p, last, "/%s", h->resource.component[i]); + /* Resource */ + ogs_assert(h->resource.component[0]); + for (i = 0; i < OGS_SBI_MAX_NUM_OF_RESOURCE_COMPONENT && + h->resource.component[i]; i++) + p = ogs_slprintf(p, last, "/%s", h->resource.component[i]); + } return ogs_strdup(uri); } @@ -81,7 +82,6 @@ char *ogs_sbi_server_uri(ogs_sbi_server_t *server, ogs_sbi_header_t *h) bool https = false; ogs_assert(server); - ogs_assert(h); if (server->tls.key && server->tls.pem) https = true; @@ -100,7 +100,6 @@ char *ogs_sbi_client_uri(ogs_sbi_client_t *client, ogs_sbi_header_t *h) bool https = false; ogs_assert(client); - ogs_assert(h); if (client->tls.key && client->tls.pem) https = true; @@ -108,6 +107,11 @@ char *ogs_sbi_client_uri(ogs_sbi_client_t *client, ogs_sbi_header_t *h) return ogs_uridup(https, client->node.addr, h); } +char *ogs_sbi_client_apiroot(ogs_sbi_client_t *client) +{ + return ogs_sbi_client_uri(client, NULL); +} + /** * Returns a url-decoded version of str * IMPORTANT: be sure to free() the returned string after use @@ -207,6 +211,57 @@ ogs_sockaddr_t *ogs_sbi_getaddr_from_uri(char *uri) return addr; } +char *ogs_sbi_getpath_from_uri(char *uri) +{ + int rv; + struct yuarel yuarel; + char *p = NULL; + char *path = NULL; + + p = ogs_strdup(uri); + + rv = yuarel_parse(&yuarel, p); + if (rv != OGS_OK) { + ogs_free(p); + ogs_error("yuarel_parse() failed [%s]", uri); + return NULL; + } + + if (!yuarel.scheme) { + ogs_error("No http.scheme found [%s]", uri); + ogs_free(p); + return NULL; + } + + if (strcmp(yuarel.scheme, "https") == 0) { + + } else if (strcmp(yuarel.scheme, "http") == 0) { + + } else { + ogs_error("Invalid http.scheme [%s:%s]", yuarel.scheme, uri); + ogs_free(p); + return NULL; + } + + if (!yuarel.host) { + ogs_error("No http.host found [%s]", uri); + ogs_free(p); + return NULL; + } + + if (!yuarel.path) { + ogs_error("No http.path found [%s]", uri); + ogs_free(p); + return NULL; + } + + path = ogs_strdup(yuarel.path); + ogs_assert(path); + + ogs_free(p); + return path; +} + char *ogs_sbi_bitrate_to_string(uint64_t bitrate, int unit) { if (unit == OGS_SBI_BITRATE_KBPS) { diff --git a/lib/sbi/conv.h b/lib/sbi/conv.h index 774ef7b79..523a499c9 100644 --- a/lib/sbi/conv.h +++ b/lib/sbi/conv.h @@ -34,10 +34,13 @@ typedef struct ogs_sbi_header_s ogs_sbi_header_t; char *ogs_uridup(bool https, ogs_sockaddr_t *addr, ogs_sbi_header_t *h); char *ogs_sbi_server_uri(ogs_sbi_server_t *server, ogs_sbi_header_t *h); +char *ogs_sbi_client_apiroot(ogs_sbi_client_t *client); char *ogs_sbi_client_uri(ogs_sbi_client_t *client, ogs_sbi_header_t *h); char *ogs_sbi_parse_uri(char *uri, const char *delim, char **saveptr); + ogs_sockaddr_t *ogs_sbi_getaddr_from_uri(char *uri); +char *ogs_sbi_getpath_from_uri(char *uri); #define OGS_SBI_BITRATE_BPS 0 #define OGS_SBI_BITRATE_KBPS 1 diff --git a/lib/sbi/message.c b/lib/sbi/message.c index ec80b132c..dadcab7a5 100644 --- a/lib/sbi/message.c +++ b/lib/sbi/message.c @@ -252,7 +252,6 @@ ogs_sbi_request_t *ogs_sbi_build_request(ogs_sbi_message_t *message) ogs_expect_or_return_val(message->h.method, NULL); request->h.method = ogs_strdup(message->h.method); if (message->h.uri) { - ogs_expect_or_return_val(message->h.uri, NULL); request->h.uri = ogs_strdup(message->h.uri); ogs_expect_or_return_val(request->h.uri, NULL); } else { @@ -547,6 +546,11 @@ int ogs_sbi_parse_request( for (hi = ogs_hash_first(request->http.headers); hi; hi = ogs_hash_next(hi)) { + /* + * + * Each header field consists of a name followed by a colon (":") + * and the field value. Field names are case-insensitive. + */ if (!ogs_strcasecmp(ogs_hash_this_key(hi), OGS_SBI_ACCEPT_ENCODING)) { message->http.content_encoding = ogs_hash_this_val(hi); } else if (!ogs_strcasecmp( @@ -620,7 +624,7 @@ int ogs_sbi_parse_header(ogs_sbi_message_t *message, ogs_sbi_header_t *header) { struct yuarel yuarel; char *saveptr = NULL; - char *uri = NULL, *p = NULL;; + char *uri = NULL, *p = NULL; char *component = NULL; int i = 0; @@ -691,6 +695,21 @@ void ogs_sbi_header_free(ogs_sbi_header_t *h) ogs_free(h->resource.component[i]); } +void ogs_sbi_http_hash_free(ogs_hash_t *hash) +{ + ogs_hash_index_t *hi; + + ogs_assert(hash); + + for (hi = ogs_hash_first(hash); hi; hi = ogs_hash_next(hi)) { + char *key = (char *)ogs_hash_this_key(hi); + char *val = ogs_hash_this_val(hi); + ogs_hash_set(hash, key, strlen(key), NULL); + ogs_free(key); + ogs_free(val); + } + ogs_hash_destroy(hash); +} static char *build_json(ogs_sbi_message_t *message) { @@ -2152,29 +2171,12 @@ static void http_message_free(ogs_sbi_http_message_t *http) int i; ogs_assert(http); - if (http->params) { - ogs_hash_index_t *hi; - for (hi = ogs_hash_first(http->params); hi; hi = ogs_hash_next(hi)) { - char *key = (char *)ogs_hash_this_key(hi); - char *val = ogs_hash_this_val(hi); - ogs_hash_set(http->params, key, strlen(key), NULL); - ogs_free(key); - ogs_free(val); - } - ogs_hash_destroy(http->params); - } + if (http->params) + ogs_sbi_http_hash_free(http->params); + + if (http->headers) + ogs_sbi_http_hash_free(http->headers); - if (http->headers) { - ogs_hash_index_t *hi; - for (hi = ogs_hash_first(http->headers); hi; hi = ogs_hash_next(hi)) { - char *key = (char *)ogs_hash_this_key(hi); - char *val = ogs_hash_this_val(hi); - ogs_hash_set(http->headers, key, strlen(key), NULL); - ogs_free(key); - ogs_free(val); - } - ogs_hash_destroy(http->headers); - } if (http->content) ogs_free(http->content); diff --git a/lib/sbi/message.h b/lib/sbi/message.h index 164325c49..d64aa44ec 100644 --- a/lib/sbi/message.h +++ b/lib/sbi/message.h @@ -274,6 +274,21 @@ extern "C" { #define OGS_SBI_APPLICATION_5GNAS_TYPE "vnd.3gpp.5gnas" #define OGS_SBI_APPLICATION_NGAP_TYPE "vnd.3gpp.ngap" +#define OGS_SBI_CUSTOM_3GPP_COMMON "3gpp-Sbi-" +#define OGS_SBI_CUSTOM_MESSAGE_PRIORITY "3gpp-Sbi-Message-Priority" +#define OGS_SBI_CUSTOM_CALLBACK "3gpp-Sbi-Callback" +#define OGS_SBI_CUSTOM_TARGET_APIROOT "3gpp-Sbi-Target-apiRoot" +#define OGS_SBI_CUSTOM_ROUTING_BINDING "3gpp-Sbi-Routing-Binding" +#define OGS_SBI_CUSTOM_BINDING "3gpp-Sbi-Binding" +#define OGS_SBI_CUSTOM_DISCOVERY_COMMON "3gpp-Sbi-Discovery-" +#define OGS_SBI_CUSTOM_PRODUCER_ID "3gpp-Sbi-Producer-Id" +#define OGS_SBI_CUSTOM_OCI "3gpp-Sbi-Oci" +#define OGS_SBI_CUSTOM_CLIENT_CREDENTIALS "3gpp-Sbi-Client-Credentials" +#define OGS_SBI_CUSTOM_NRF_URI "3gpp-Sbi-Nrf-Uri" +#define OGS_SBI_CUSTOM_TARGET_NF_ID "3gpp-Sbi-Target-Nf-Id" +#define OGS_SBI_CUSTOM_ACCESS_SCOPE "3gpp-Sbi-Access-Scope" +#define OGS_SBI_CUSTOM_ACCESS_TOKEN "3gpp-Sbi-Access-Token" + #define OGS_SBI_CONTENT_JSON_TYPE \ OGS_SBI_APPLICATION_TYPE "/" OGS_SBI_APPLICATION_JSON_TYPE #define OGS_SBI_CONTENT_PROBLEM_TYPE \ @@ -477,6 +492,8 @@ ogs_pkbuf_t *ogs_sbi_find_part_by_content_id( int ogs_sbi_parse_header(ogs_sbi_message_t *message, ogs_sbi_header_t *header); void ogs_sbi_header_free(ogs_sbi_header_t *h); +void ogs_sbi_http_hash_free(ogs_hash_t *hash); + #ifdef __cplusplus } #endif diff --git a/lib/sbi/mhd-server.c b/lib/sbi/mhd-server.c index 279e4d035..e22ebc569 100644 --- a/lib/sbi/mhd-server.c +++ b/lib/sbi/mhd-server.c @@ -35,6 +35,8 @@ static int server_start(ogs_sbi_server_t *server, int (*cb)(ogs_sbi_request_t *request, void *data)); static void server_stop(ogs_sbi_server_t *server); +static bool server_send_rspmem_persistent( + ogs_sbi_stream_t *stream, ogs_sbi_response_t *response); static bool server_send_response( ogs_sbi_stream_t *stream, ogs_sbi_response_t *response); @@ -47,7 +49,9 @@ const ogs_sbi_server_actions_t ogs_mhd_server_actions = { server_start, server_stop, + server_send_rspmem_persistent, server_send_response, + server_from_stream, }; @@ -296,7 +300,7 @@ static void free_callback(void *cls) } #endif -static bool server_send_response( +static bool server_send_rspmem_persistent( ogs_sbi_stream_t *stream, ogs_sbi_response_t *response) { int ret; @@ -312,10 +316,14 @@ static bool server_send_response( ogs_sbi_request_t *request = NULL; ogs_sbi_session_t *sbi_sess = NULL; - sbi_sess = (ogs_sbi_session_t *)stream; - ogs_assert(sbi_sess); ogs_assert(response); + sbi_sess = ogs_pool_cycle(&session_pool, (ogs_sbi_session_t *)stream); + if (!sbi_sess) { + ogs_error("session has already been removed"); + return true; + } + connection = sbi_sess->connection; ogs_assert(connection); @@ -370,7 +378,6 @@ static bool server_send_response( request = sbi_sess->request; ogs_assert(request); - ogs_sbi_response_free(response); session_remove(sbi_sess); request->poll.write = ogs_pollset_add(ogs_app()->pollset, @@ -387,6 +394,20 @@ static bool server_send_response( return true; } +static bool server_send_response( + ogs_sbi_stream_t *stream, ogs_sbi_response_t *response) +{ + bool rc; + + ogs_assert(response); + + rc = server_send_rspmem_persistent(stream, response); + + ogs_sbi_response_free(response); + + return rc; +} + static void run(short when, ogs_socket_t fd, void *data) { struct MHD_Daemon *mhd_daemon = data; @@ -539,19 +560,15 @@ suspend: sbi_sess = session_add(server, request, connection); ogs_assert(sbi_sess); - if (server->cb) { - if (server->cb(request, sbi_sess) != OGS_OK) { - ogs_warn("server callback error"); - ogs_assert(true == - ogs_sbi_server_send_error((ogs_sbi_stream_t *)sbi_sess, - OGS_SBI_HTTP_STATUS_INTERNAL_SERVER_ERROR, NULL, - "server callback error", NULL)); + ogs_assert(server->cb); + if (server->cb(request, sbi_sess) != OGS_OK) { + ogs_error("server callback error"); + ogs_assert(true == + ogs_sbi_server_send_error((ogs_sbi_stream_t *)sbi_sess, + OGS_SBI_HTTP_STATUS_INTERNAL_SERVER_ERROR, NULL, + "server callback error", NULL)); - return MHD_YES; - } - } else { - ogs_fatal("server callback is not registered"); - ogs_assert_if_reached(); + return MHD_YES; } return MHD_YES; diff --git a/lib/sbi/nghttp2-server.c b/lib/sbi/nghttp2-server.c index eb0247b5f..3366afc3d 100644 --- a/lib/sbi/nghttp2-server.c +++ b/lib/sbi/nghttp2-server.c @@ -33,6 +33,8 @@ static int server_start(ogs_sbi_server_t *server, int (*cb)(ogs_sbi_request_t *request, void *data)); static void server_stop(ogs_sbi_server_t *server); +static bool server_send_rspmem_persistent( + ogs_sbi_stream_t *stream, ogs_sbi_response_t *response); static bool server_send_response( ogs_sbi_stream_t *stream, ogs_sbi_response_t *response); @@ -45,7 +47,9 @@ const ogs_sbi_server_actions_t ogs_nghttp2_server_actions = { server_start, server_stop, + server_send_rspmem_persistent, server_send_response, + server_from_stream, }; @@ -284,7 +288,7 @@ static ssize_t response_read_callback(nghttp2_session *session, return response->http.content_length; } -static bool server_send_response( +static bool server_send_rspmem_persistent( ogs_sbi_stream_t *stream, ogs_sbi_response_t *response) { ogs_sbi_session_t *sbi_sess = NULL; @@ -299,11 +303,17 @@ static bool server_send_response( char srv_version[128]; char clen[128]; - ogs_assert(stream); + ogs_assert(response); + + stream = ogs_pool_cycle(&stream_pool, stream); + if (!stream) { + ogs_error("stream has already been closed"); + return true; + } + sbi_sess = stream->session; ogs_assert(sbi_sess); ogs_assert(sbi_sess->session); - ogs_assert(response); sock = sbi_sess->sock; ogs_assert(sock); @@ -375,12 +385,25 @@ static bool server_send_response( session_remove(sbi_sess); } - ogs_sbi_response_free(response); ogs_free(nva); return true; } +static bool server_send_response( + ogs_sbi_stream_t *stream, ogs_sbi_response_t *response) +{ + bool rc; + + ogs_assert(response); + + rc = server_send_rspmem_persistent(stream, response); + + ogs_sbi_response_free(response); + + return rc; +} + static ogs_sbi_server_t *server_from_stream(ogs_sbi_stream_t *stream) { ogs_sbi_session_t *sbi_sess = NULL; diff --git a/lib/sbi/path.c b/lib/sbi/path.c index 9e78b9b0e..328514b4d 100644 --- a/lib/sbi/path.c +++ b/lib/sbi/path.c @@ -68,13 +68,12 @@ bool ogs_sbi_send(ogs_sbi_nf_instance_t *nf_instance, ogs_freeaddrinfo(addr); } + /* ogs_sbi_xact_remove() will call ogs_sbi_request_free() + * As such, we'll use ogs_sbi_client_send_reqmem_persistent() */ ogs_expect_or_return_val(true == - ogs_sbi_client_send_request( + ogs_sbi_scp_send_reqmem_persistent( client, client_cb, request, xact), false); - /* Prevent ogs_sbi_request_free() in ogs_sbi_xact_remove() */ - xact->request = NULL; - return true; } @@ -125,6 +124,23 @@ bool ogs_sbi_discover_and_send(ogs_sbi_xact_t *xact, return false; } +bool ogs_nnrf_nfm_send_nf_register( + ogs_sbi_nf_instance_t *nf_instance, ogs_sbi_request_t *(*build)(void)) +{ + ogs_sbi_request_t *request = NULL; + ogs_sbi_client_t *client = NULL; + + ogs_assert(nf_instance); + client = nf_instance->client; + ogs_assert(client); + ogs_assert(build); + + request = (*build)(); + ogs_expect_or_return_val(request, false); + + return ogs_sbi_scp_send_request(client, client->cb, request, nf_instance); +} + bool ogs_nnrf_nfm_send_nf_update(ogs_sbi_nf_instance_t *nf_instance) { ogs_sbi_request_t *request = NULL; @@ -137,8 +153,7 @@ bool ogs_nnrf_nfm_send_nf_update(ogs_sbi_nf_instance_t *nf_instance) request = ogs_nnrf_nfm_build_update(); ogs_expect_or_return_val(request, false); - return ogs_sbi_client_send_request( - client, client->cb, request, nf_instance); + return ogs_sbi_scp_send_request(client, client->cb, request, nf_instance); } bool ogs_nnrf_nfm_send_nf_de_register(ogs_sbi_nf_instance_t *nf_instance) @@ -153,8 +168,7 @@ bool ogs_nnrf_nfm_send_nf_de_register(ogs_sbi_nf_instance_t *nf_instance) request = ogs_nnrf_nfm_build_de_register(); ogs_expect_or_return_val(request, false); - return ogs_sbi_client_send_request( - client, client->cb, request, nf_instance); + return ogs_sbi_scp_send_request(client, client->cb, request, nf_instance); } bool ogs_nnrf_nfm_send_nf_status_subscribe(ogs_sbi_client_t *client, @@ -180,7 +194,7 @@ bool ogs_nnrf_nfm_send_nf_status_subscribe(ogs_sbi_client_t *client, request = ogs_nnrf_nfm_build_status_subscribe(subscription); ogs_expect_or_return_val(request, false); - return ogs_sbi_client_send_request( + return ogs_sbi_scp_send_request( client, client->cb, request, subscription); } @@ -191,13 +205,14 @@ bool ogs_nnrf_nfm_send_nf_status_unsubscribe( ogs_sbi_client_t *client = NULL; ogs_assert(subscription); - client = subscription->client; - ogs_assert(client); request = ogs_nnrf_nfm_build_status_unsubscribe(subscription); ogs_expect_or_return_val(request, false); - return ogs_sbi_client_send_request( + client = subscription->client; + ogs_assert(client); + + return ogs_sbi_scp_send_request( client, client->cb, request, subscription); } @@ -208,15 +223,15 @@ bool ogs_nnrf_disc_send_nf_discover(ogs_sbi_nf_instance_t *nf_instance, ogs_sbi_request_t *request = NULL; ogs_assert(nf_instance); - ogs_assert(nf_instance->nf_type); - client = nf_instance->client; - ogs_assert(client); ogs_assert(ogs_sbi_self()->nf_instance); request = ogs_nnrf_disc_build_discover( target_nf_type, ogs_sbi_self()->nf_instance->nf_type); ogs_expect_or_return_val(request, false); + client = nf_instance->client; + ogs_assert(client); + return ogs_sbi_client_send_request(client, client->cb, request, data); } diff --git a/lib/sbi/path.h b/lib/sbi/path.h index dbfb94716..396948f21 100644 --- a/lib/sbi/path.h +++ b/lib/sbi/path.h @@ -31,6 +31,8 @@ bool ogs_sbi_send(ogs_sbi_nf_instance_t *nf_instance, bool ogs_sbi_discover_and_send(ogs_sbi_xact_t *xact, ogs_fsm_handler_t nf_state_registered, ogs_sbi_client_cb_f client_cb); +bool ogs_nnrf_nfm_send_nf_register( + ogs_sbi_nf_instance_t *nf_instance, ogs_sbi_request_t *(*build)(void)); bool ogs_nnrf_nfm_send_nf_update(ogs_sbi_nf_instance_t *nf_instance); bool ogs_nnrf_nfm_send_nf_de_register(ogs_sbi_nf_instance_t *nf_instance); diff --git a/lib/sbi/server.c b/lib/sbi/server.c index c52225bff..f97e785f6 100644 --- a/lib/sbi/server.c +++ b/lib/sbi/server.c @@ -133,6 +133,12 @@ void ogs_sbi_server_stop_all(void) ogs_sbi_server_actions.stop(server); } +bool ogs_sbi_server_send_rspmem_persistent( + ogs_sbi_stream_t *stream, ogs_sbi_response_t *response) +{ + return ogs_sbi_server_actions.send_rspmem_persistent(stream, response); +} + bool ogs_sbi_server_send_response( ogs_sbi_stream_t *stream, ogs_sbi_response_t *response) { diff --git a/lib/sbi/server.h b/lib/sbi/server.h index 28f27c5d7..4820b2cad 100644 --- a/lib/sbi/server.h +++ b/lib/sbi/server.h @@ -53,6 +53,8 @@ typedef struct ogs_sbi_server_actions_s { int (*cb)(ogs_sbi_request_t *request, void *data)); void (*stop)(ogs_sbi_server_t *server); + bool (*send_rspmem_persistent)( + ogs_sbi_stream_t *stream, ogs_sbi_response_t *response); bool (*send_response)( ogs_sbi_stream_t *stream, ogs_sbi_response_t *response); @@ -74,6 +76,8 @@ int ogs_sbi_server_start_all( int (*cb)(ogs_sbi_request_t *request, void *data)); void ogs_sbi_server_stop_all(void); +bool ogs_sbi_server_send_rspmem_persistent( + ogs_sbi_stream_t *stream, ogs_sbi_response_t *response); bool ogs_sbi_server_send_response( ogs_sbi_stream_t *stream, ogs_sbi_response_t *response); bool ogs_sbi_server_send_error(ogs_sbi_stream_t *stream, diff --git a/misc/ipv6_netconf.sh b/misc/ipv6_netconf.sh index 94dc0a8b5..7870358ae 100755 --- a/misc/ipv6_netconf.sh +++ b/misc/ipv6_netconf.sh @@ -31,6 +31,7 @@ if [ "$SYSTEM" = "Linux" ]; then ip addr del fd69:f21d:873c:fa::18 dev lo 2> /dev/null ip addr del fd69:f21d:873c:fa::19 dev lo 2> /dev/null ip addr del fd69:f21d:873c:fa::20 dev lo 2> /dev/null + ip addr del fd69:f21d:873c:fb::10 dev lo 2> /dev/null ip addr add fd69:f21d:873c:fa::1 dev lo ip addr add fd69:f21d:873c:fa::2 dev lo ip addr add fd69:f21d:873c:fa::3 dev lo @@ -51,11 +52,8 @@ if [ "$SYSTEM" = "Linux" ]; then ip addr add fd69:f21d:873c:fa::18 dev lo ip addr add fd69:f21d:873c:fa::19 dev lo ip addr add fd69:f21d:873c:fa::20 dev lo + ip addr add fd69:f21d:873c:fb::10 dev lo else - ifconfig lo0 alias 127.0.0.2 netmask 255.255.255.255 - ifconfig lo0 alias 127.0.0.3 netmask 255.255.255.255 - ifconfig lo0 alias 127.0.0.4 netmask 255.255.255.255 - ifconfig lo0 alias 127.0.0.5 netmask 255.255.255.255 sysctl -w net.inet.ip.forwarding=1 sysctl -w net.inet6.ip6.forwarding=1 ifconfig lo0 alias 127.0.0.2 netmask 255.255.255.255 @@ -77,6 +75,7 @@ else ifconfig lo0 alias 127.0.0.18 netmask 255.255.255.255 ifconfig lo0 alias 127.0.0.19 netmask 255.255.255.255 ifconfig lo0 alias 127.0.0.20 netmask 255.255.255.255 + ifconfig lo0 alias 127.0.1.10 netmask 255.255.255.255 ifconfig lo0 inet6 delete fd69:f21d:873c:fa::1 prefixlen 128 2> /dev/null ifconfig lo0 inet6 delete fd69:f21d:873c:fa::2 prefixlen 128 2> /dev/null ifconfig lo0 inet6 delete fd69:f21d:873c:fa::3 prefixlen 128 2> /dev/null @@ -97,6 +96,7 @@ else ifconfig lo0 inet6 delete fd69:f21d:873c:fa::18 prefixlen 128 2> /dev/null ifconfig lo0 inet6 delete fd69:f21d:873c:fa::19 prefixlen 128 2> /dev/null ifconfig lo0 inet6 delete fd69:f21d:873c:fa::20 prefixlen 128 2> /dev/null + ifconfig lo0 inet6 delete fd69:f21d:873c:fb::10 prefixlen 128 2> /dev/null ifconfig lo0 inet6 add fd69:f21d:873c:fa::1 prefixlen 128 ifconfig lo0 inet6 add fd69:f21d:873c:fa::2 prefixlen 128 ifconfig lo0 inet6 add fd69:f21d:873c:fa::3 prefixlen 128 @@ -117,6 +117,7 @@ else ifconfig lo0 inet6 add fd69:f21d:873c:fa::18 prefixlen 128 ifconfig lo0 inet6 add fd69:f21d:873c:fa::19 prefixlen 128 ifconfig lo0 inet6 add fd69:f21d:873c:fa::20 prefixlen 128 + ifconfig lo0 inet6 add fd69:f21d:873c:fb::10 prefixlen 128 if [ "$SYSTEM" = "Darwin" ]; then if ! test -f /etc/pf.anchors/org.open5gs; then sudo sh -c "echo 'nat on {en0} from 10.45.0.0/16 to any -> {en0}' > /etc/pf.anchors/org.open5gs" diff --git a/misc/netconf.sh b/misc/netconf.sh index e6025cdba..79fd2442d 100755 --- a/misc/netconf.sh +++ b/misc/netconf.sh @@ -37,6 +37,7 @@ else ifconfig lo0 alias 127.0.0.18 netmask 255.255.255.255 ifconfig lo0 alias 127.0.0.19 netmask 255.255.255.255 ifconfig lo0 alias 127.0.0.20 netmask 255.255.255.255 + ifconfig lo0 alias 127.0.1.10 netmask 255.255.255.255 if [ "$SYSTEM" = "Darwin" ]; then if ! test -f /etc/pf.anchors/org.open5gs; then sudo sh -c "echo 'nat on {en0} from 10.45.0.0/16 to any -> {en0}' > /etc/pf.anchors/org.open5gs" diff --git a/src/amf/event.c b/src/amf/event.c index 8a53d70ee..31e61c4cd 100644 --- a/src/amf/event.c +++ b/src/amf/event.c @@ -119,7 +119,7 @@ void amf_sctp_event_push(amf_event_e id, rv = ogs_queue_push(ogs_app()->queue, e); if (rv != OGS_OK) { - ogs_warn("ogs_queue_push() failed:%d", (int)rv); + ogs_error("ogs_queue_push() failed:%d", (int)rv); ogs_free(e->ngap.addr); if (e->pkbuf) ogs_pkbuf_free(e->pkbuf); diff --git a/src/amf/init.c b/src/amf/init.c index 9738b0ef9..a58de7c89 100644 --- a/src/amf/init.c +++ b/src/amf/init.c @@ -35,7 +35,7 @@ int amf_initialize() amf_context_init(); amf_event_init(); - rv = ogs_sbi_context_parse_config("amf", "nrf"); + rv = ogs_sbi_context_parse_config("amf", "nrf", "scp"); if (rv != OGS_OK) return rv; rv = ogs_metrics_context_parse_config(); diff --git a/src/amf/nf-sm.c b/src/amf/nf-sm.c index b8f61fd80..3b19227e0 100644 --- a/src/amf/nf-sm.c +++ b/src/amf/nf-sm.c @@ -61,16 +61,18 @@ void amf_nf_state_initial(ogs_fsm_t *s, amf_event_t *e) nf_instance = e->sbi.data; ogs_assert(nf_instance); + nf_instance->t_registration_interval = ogs_timer_add(ogs_app()->timer_mgr, + amf_timer_nf_instance_registration_interval, nf_instance); ogs_assert(nf_instance->t_registration_interval); - nf_instance->t_registration_interval->cb = - amf_timer_nf_instance_registration_interval; + nf_instance->t_heartbeat_interval = ogs_timer_add(ogs_app()->timer_mgr, + amf_timer_nf_instance_heartbeat_interval, nf_instance); ogs_assert(nf_instance->t_heartbeat_interval); - nf_instance->t_heartbeat_interval->cb = - amf_timer_nf_instance_heartbeat_interval; + nf_instance->t_no_heartbeat = ogs_timer_add(ogs_app()->timer_mgr, + amf_timer_nf_instance_no_heartbeat, nf_instance); ogs_assert(nf_instance->t_no_heartbeat); - nf_instance->t_no_heartbeat->cb = amf_timer_nf_instance_no_heartbeat; + nf_instance->t_validity = ogs_timer_add(ogs_app()->timer_mgr, + amf_timer_nf_instance_validity, nf_instance); ogs_assert(nf_instance->t_validity); - nf_instance->t_validity->cb = amf_timer_nf_instance_validity; if (NF_INSTANCE_IS_NRF(nf_instance)) { OGS_FSM_TRAN(s, &amf_nf_state_will_register); @@ -82,10 +84,20 @@ void amf_nf_state_initial(ogs_fsm_t *s, amf_event_t *e) void amf_nf_state_final(ogs_fsm_t *s, amf_event_t *e) { + ogs_sbi_nf_instance_t *nf_instance = NULL; + ogs_assert(s); ogs_assert(e); amf_sm_debug(e); + + nf_instance = e->sbi.data; + ogs_assert(nf_instance); + + ogs_timer_delete(nf_instance->t_registration_interval); + ogs_timer_delete(nf_instance->t_heartbeat_interval); + ogs_timer_delete(nf_instance->t_no_heartbeat); + ogs_timer_delete(nf_instance->t_validity); } void amf_nf_state_will_register(ogs_fsm_t *s, amf_event_t *e) @@ -110,7 +122,8 @@ void amf_nf_state_will_register(ogs_fsm_t *s, amf_event_t *e) ogs_timer_start(nf_instance->t_registration_interval, ogs_app()->time.message.sbi.nf_register_interval); - ogs_assert(true == amf_nnrf_nfm_send_nf_register(nf_instance)); + ogs_assert(true == ogs_nnrf_nfm_send_nf_register( + nf_instance, amf_nnrf_nfm_build_register)); break; case OGS_FSM_EXIT_SIG: @@ -166,7 +179,8 @@ void amf_nf_state_will_register(ogs_fsm_t *s, amf_event_t *e) ogs_timer_start(nf_instance->t_registration_interval, ogs_app()->time.message.sbi.nf_register_interval); - ogs_assert(true == amf_nnrf_nfm_send_nf_register(nf_instance)); + ogs_assert(true == ogs_nnrf_nfm_send_nf_register( + nf_instance, amf_nnrf_nfm_build_register)); break; default: diff --git a/src/amf/ngap-path.c b/src/amf/ngap-path.c index 2b22d8bff..ec2a485fa 100644 --- a/src/amf/ngap-path.c +++ b/src/amf/ngap-path.c @@ -128,7 +128,7 @@ int ngap_send_to_5gsm(amf_ue_t *amf_ue, ogs_pkbuf_t *esmbuf) e->pkbuf = esmbuf; rv = ogs_queue_push(ogs_app()->queue, e); if (rv != OGS_OK) { - ogs_warn("ogs_queue_push() failed:%d", (int)rv); + ogs_error("ogs_queue_push() failed:%d", (int)rv); ogs_pkbuf_free(e->pkbuf); amf_event_free(e); } @@ -214,7 +214,7 @@ int ngap_send_to_nas(ran_ue_t *ran_ue, e->pkbuf = nasbuf; rv = ogs_queue_push(ogs_app()->queue, e); if (rv != OGS_OK) { - ogs_warn("ngap_send_to_nas() failed:%d", (int)rv); + ogs_error("ngap_send_to_nas() failed:%d", (int)rv); ogs_pkbuf_free(e->pkbuf); amf_event_free(e); } diff --git a/src/amf/sbi-path.c b/src/amf/sbi-path.c index 470feba2a..7d8937bf0 100644 --- a/src/amf/sbi-path.c +++ b/src/amf/sbi-path.c @@ -37,7 +37,8 @@ static int server_cb(ogs_sbi_request_t *request, void *data) rv = ogs_queue_push(ogs_app()->queue, e); if (rv != OGS_OK) { - ogs_warn("ogs_queue_push() failed:%d", (int)rv); + ogs_error("ogs_queue_push() failed:%d", (int)rv); + ogs_sbi_request_free(request); amf_event_free(e); return OGS_ERROR; } @@ -45,11 +46,18 @@ static int server_cb(ogs_sbi_request_t *request, void *data) return OGS_OK; } -static int client_cb(ogs_sbi_response_t *response, void *data) +static int client_cb(int status, ogs_sbi_response_t *response, void *data) { amf_event_t *e = NULL; int rv; + if (status != OGS_OK) { + ogs_log_message( + status == OGS_DONE ? OGS_LOG_DEBUG : OGS_LOG_WARN, 0, + "client_cb() failed [%d]", status); + return OGS_ERROR; + } + ogs_assert(response); e = amf_event_new(AMF_EVT_SBI_CLIENT); @@ -59,7 +67,8 @@ static int client_cb(ogs_sbi_response_t *response, void *data) rv = ogs_queue_push(ogs_app()->queue, e); if (rv != OGS_OK) { - ogs_warn("ogs_queue_push() failed:%d", (int)rv); + ogs_error("ogs_queue_push() failed:%d", (int)rv); + ogs_sbi_response_free(response); amf_event_free(e); return OGS_ERROR; } @@ -91,20 +100,30 @@ int amf_sbi_open(void) (char*)OGS_SBI_API_V1_0_0, NULL); ogs_sbi_nf_service_add_allowed_nf_type(service, OpenAPI_nf_type_SMF); + /* Initialize SCP NF Instance */ + nf_instance = ogs_sbi_self()->scp_instance; + if (nf_instance) { + ogs_sbi_client_t *client = NULL; + + /* Client callback is only used when NF sends to SCP */ + client = nf_instance->client; + ogs_assert(client); + client->cb = client_cb; + } + /* Initialize NRF NF Instance */ - ogs_list_for_each(&ogs_sbi_self()->nf_instance_list, nf_instance) { - if (NF_INSTANCE_IS_NRF(nf_instance)) { - ogs_sbi_client_t *client = NULL; + nf_instance = ogs_sbi_self()->nrf_instance; + if (nf_instance) { + ogs_sbi_client_t *client = NULL; - /* Client callback is only used when NF sends to NRF */ - client = nf_instance->client; - ogs_assert(client); - client->cb = client_cb; + /* Client callback is only used when NF sends to NRF */ + client = nf_instance->client; + ogs_assert(client); + client->cb = client_cb; - /* NFRegister is sent and the response is received - * by the above client callback. */ - amf_nf_fsm_init(nf_instance); - } + /* NFRegister is sent and the response is received + * by the above client callback. */ + amf_nf_fsm_init(nf_instance); } return OGS_OK; @@ -112,25 +131,10 @@ int amf_sbi_open(void) void amf_sbi_close(void) { + ogs_sbi_client_stop_all(); ogs_sbi_server_stop_all(); } -bool amf_nnrf_nfm_send_nf_register(ogs_sbi_nf_instance_t *nf_instance) -{ - ogs_sbi_request_t *request = NULL; - ogs_sbi_client_t *client = NULL; - - ogs_assert(nf_instance); - client = nf_instance->client; - ogs_assert(client); - - request = amf_nnrf_nfm_build_register(); - ogs_expect_or_return_val(request, false); - - return ogs_sbi_client_send_request( - client, client->cb, request, nf_instance); -} - bool amf_sbi_send(ogs_sbi_nf_instance_t *nf_instance, ogs_sbi_xact_t *xact) { return ogs_sbi_send(nf_instance, client_cb, xact); @@ -203,13 +207,21 @@ bool amf_sess_sbi_discover_and_send(OpenAPI_nf_type_e target_nf_type, return true; } -static int client_discover_cb(ogs_sbi_response_t *response, void *data) +static int client_discover_cb( + int status, ogs_sbi_response_t *response, void *data) { int rv; ogs_sbi_message_t message; amf_sess_t *sess = data; + if (status != OGS_OK) { + ogs_log_message( + status == OGS_DONE ? OGS_LOG_DEBUG : OGS_LOG_WARN, 0, + "client_discover_cb() failed [%d]", status); + return OGS_ERROR; + } + ogs_assert(response); ogs_assert(sess); ogs_assert(sess->sbi.type == OGS_SBI_OBJ_SESS_TYPE); @@ -395,12 +407,19 @@ void amf_sbi_send_release_all_sessions(amf_ue_t *amf_ue, int state) } } -static int client_notify_cb(ogs_sbi_response_t *response, void *data) +static int client_notify_cb( + int status, ogs_sbi_response_t *response, void *data) { int rv; - ogs_sbi_message_t message; + if (status != OGS_OK) { + ogs_log_message( + status == OGS_DONE ? OGS_LOG_DEBUG : OGS_LOG_WARN, 0, + "client_notify_cb() failed [%d]", status); + return OGS_ERROR; + } + ogs_assert(response); rv = ogs_sbi_parse_response(&message, response); diff --git a/src/amf/sbi-path.h b/src/amf/sbi-path.h index a631f11f3..954f797c7 100644 --- a/src/amf/sbi-path.h +++ b/src/amf/sbi-path.h @@ -34,8 +34,6 @@ extern "C" { int amf_sbi_open(void); void amf_sbi_close(void); -bool amf_nnrf_nfm_send_nf_register(ogs_sbi_nf_instance_t *nf_instance); - bool amf_sbi_send(ogs_sbi_nf_instance_t *nf_instance, ogs_sbi_xact_t *xact); bool amf_ue_sbi_discover_and_send(OpenAPI_nf_type_e target_nf_type, amf_ue_t *amf_ue, void *data, diff --git a/src/amf/timer.c b/src/amf/timer.c index 6dece8d73..c3efd1b27 100644 --- a/src/amf/timer.c +++ b/src/amf/timer.c @@ -109,7 +109,7 @@ void amf_timer_ng_delayed_send(void *data) rv = ogs_queue_push(ogs_app()->queue, e); if (rv != OGS_OK) { - ogs_warn("ogs_queue_push() failed:%d", (int)rv); + ogs_error("ogs_queue_push() failed:%d", (int)rv); ogs_timer_delete(e->timer); amf_event_free(e); } @@ -153,7 +153,7 @@ static void sbi_timer_send_event(int timer_id, void *data) rv = ogs_queue_push(ogs_app()->queue, e); if (rv != OGS_OK) { - ogs_warn("ogs_queue_push() failed [%d] in %s", + ogs_error("ogs_queue_push() failed [%d] in %s", (int)rv, amf_timer_get_name(e->timer_id)); amf_event_free(e); } @@ -203,7 +203,7 @@ static void gmm_timer_event_send( rv = ogs_queue_push(ogs_app()->queue, e); if (rv != OGS_OK) { - ogs_warn("ogs_queue_push() failed:%d", (int)rv); + ogs_error("ogs_queue_push() failed:%d", (int)rv); amf_event_free(e); } } @@ -250,7 +250,7 @@ void amf_timer_ng_holding_timer_expire(void *data) rv = ogs_queue_push(ogs_app()->queue, e); if (rv != OGS_OK) { - ogs_warn("ogs_queue_push() failed:%d", (int)rv); + ogs_error("ogs_queue_push() failed:%d", (int)rv); amf_event_free(e); } } diff --git a/src/ausf/init.c b/src/ausf/init.c index 250e9df16..1b8a96722 100644 --- a/src/ausf/init.c +++ b/src/ausf/init.c @@ -32,7 +32,7 @@ int ausf_initialize() ausf_context_init(); ausf_event_init(); - rv = ogs_sbi_context_parse_config("ausf", "nrf"); + rv = ogs_sbi_context_parse_config("ausf", "nrf", "scp"); if (rv != OGS_OK) return rv; rv = ausf_context_parse_config(); diff --git a/src/ausf/nf-sm.c b/src/ausf/nf-sm.c index a82d2b0fc..22873df82 100644 --- a/src/ausf/nf-sm.c +++ b/src/ausf/nf-sm.c @@ -61,16 +61,18 @@ void ausf_nf_state_initial(ogs_fsm_t *s, ausf_event_t *e) nf_instance = e->sbi.data; ogs_assert(nf_instance); + nf_instance->t_registration_interval = ogs_timer_add(ogs_app()->timer_mgr, + ausf_timer_nf_instance_registration_interval, nf_instance); ogs_assert(nf_instance->t_registration_interval); - nf_instance->t_registration_interval->cb = - ausf_timer_nf_instance_registration_interval; + nf_instance->t_heartbeat_interval = ogs_timer_add(ogs_app()->timer_mgr, + ausf_timer_nf_instance_heartbeat_interval, nf_instance); ogs_assert(nf_instance->t_heartbeat_interval); - nf_instance->t_heartbeat_interval->cb = - ausf_timer_nf_instance_heartbeat_interval; + nf_instance->t_no_heartbeat = ogs_timer_add(ogs_app()->timer_mgr, + ausf_timer_nf_instance_no_heartbeat, nf_instance); ogs_assert(nf_instance->t_no_heartbeat); - nf_instance->t_no_heartbeat->cb = ausf_timer_nf_instance_no_heartbeat; + nf_instance->t_validity = ogs_timer_add(ogs_app()->timer_mgr, + ausf_timer_nf_instance_validity, nf_instance); ogs_assert(nf_instance->t_validity); - nf_instance->t_validity->cb = ausf_timer_nf_instance_validity; if (NF_INSTANCE_IS_NRF(nf_instance)) { OGS_FSM_TRAN(s, &ausf_nf_state_will_register); @@ -82,10 +84,20 @@ void ausf_nf_state_initial(ogs_fsm_t *s, ausf_event_t *e) void ausf_nf_state_final(ogs_fsm_t *s, ausf_event_t *e) { + ogs_sbi_nf_instance_t *nf_instance = NULL; + ogs_assert(s); ogs_assert(e); ausf_sm_debug(e); + + nf_instance = e->sbi.data; + ogs_assert(nf_instance); + + ogs_timer_delete(nf_instance->t_registration_interval); + ogs_timer_delete(nf_instance->t_heartbeat_interval); + ogs_timer_delete(nf_instance->t_no_heartbeat); + ogs_timer_delete(nf_instance->t_validity); } void ausf_nf_state_will_register(ogs_fsm_t *s, ausf_event_t *e) @@ -110,7 +122,8 @@ void ausf_nf_state_will_register(ogs_fsm_t *s, ausf_event_t *e) ogs_timer_start(nf_instance->t_registration_interval, ogs_app()->time.message.sbi.nf_register_interval); - ogs_assert(true == ausf_nnrf_nfm_send_nf_register(nf_instance)); + ogs_assert(true == ogs_nnrf_nfm_send_nf_register( + nf_instance, ausf_nnrf_nfm_build_register)); break; case OGS_FSM_EXIT_SIG: @@ -166,7 +179,8 @@ void ausf_nf_state_will_register(ogs_fsm_t *s, ausf_event_t *e) ogs_timer_start(nf_instance->t_registration_interval, ogs_app()->time.message.sbi.nf_register_interval); - ogs_assert(true == ausf_nnrf_nfm_send_nf_register(nf_instance)); + ogs_assert(true == ogs_nnrf_nfm_send_nf_register( + nf_instance, ausf_nnrf_nfm_build_register)); break; default: diff --git a/src/ausf/sbi-path.c b/src/ausf/sbi-path.c index 59ab56859..a2e05b2f2 100644 --- a/src/ausf/sbi-path.c +++ b/src/ausf/sbi-path.c @@ -35,7 +35,8 @@ static int server_cb(ogs_sbi_request_t *request, void *data) rv = ogs_queue_push(ogs_app()->queue, e); if (rv != OGS_OK) { - ogs_warn("ogs_queue_push() failed:%d", (int)rv); + ogs_error("ogs_queue_push() failed:%d", (int)rv); + ogs_sbi_request_free(request); ausf_event_free(e); return OGS_ERROR; } @@ -43,11 +44,18 @@ static int server_cb(ogs_sbi_request_t *request, void *data) return OGS_OK; } -static int client_cb(ogs_sbi_response_t *response, void *data) +static int client_cb(int status, ogs_sbi_response_t *response, void *data) { ausf_event_t *e = NULL; int rv; + if (status != OGS_OK) { + ogs_log_message( + status == OGS_DONE ? OGS_LOG_DEBUG : OGS_LOG_WARN, 0, + "client_cb() failed [%d]", status); + return OGS_ERROR; + } + ogs_assert(response); e = ausf_event_new(AUSF_EVT_SBI_CLIENT); @@ -57,7 +65,8 @@ static int client_cb(ogs_sbi_response_t *response, void *data) rv = ogs_queue_push(ogs_app()->queue, e); if (rv != OGS_OK) { - ogs_warn("ogs_queue_push() failed:%d", (int)rv); + ogs_error("ogs_queue_push() failed:%d", (int)rv); + ogs_sbi_response_free(response); ausf_event_free(e); return OGS_ERROR; } @@ -110,25 +119,10 @@ int ausf_sbi_open(void) void ausf_sbi_close(void) { + ogs_sbi_client_stop_all(); ogs_sbi_server_stop_all(); } -bool ausf_nnrf_nfm_send_nf_register(ogs_sbi_nf_instance_t *nf_instance) -{ - ogs_sbi_request_t *request = NULL; - ogs_sbi_client_t *client = NULL; - - ogs_assert(nf_instance); - client = nf_instance->client; - ogs_assert(client); - - request = ausf_nnrf_nfm_build_register(); - ogs_expect_or_return_val(request, false); - - return ogs_sbi_client_send_request( - client, client->cb, request, nf_instance); -} - bool ausf_sbi_send(ogs_sbi_nf_instance_t *nf_instance, ogs_sbi_xact_t *xact) { return ogs_sbi_send(nf_instance, client_cb, xact); diff --git a/src/ausf/sbi-path.h b/src/ausf/sbi-path.h index f6f6552d2..17ebeca3e 100644 --- a/src/ausf/sbi-path.h +++ b/src/ausf/sbi-path.h @@ -30,8 +30,6 @@ extern "C" { int ausf_sbi_open(void); void ausf_sbi_close(void); -bool ausf_nnrf_nfm_send_nf_register(ogs_sbi_nf_instance_t *nf_instance); - bool ausf_sbi_send(ogs_sbi_nf_instance_t *nf_instance, ogs_sbi_xact_t *xact); bool ausf_sbi_discover_and_send(OpenAPI_nf_type_e target_nf_type, ausf_ue_t *ausf_ue, ogs_sbi_stream_t *stream, void *data, diff --git a/src/ausf/timer.c b/src/ausf/timer.c index c51778aa4..a022238ff 100644 --- a/src/ausf/timer.c +++ b/src/ausf/timer.c @@ -79,7 +79,7 @@ static void sbi_timer_send_event(int timer_id, void *data) rv = ogs_queue_push(ogs_app()->queue, e); if (rv != OGS_OK) { - ogs_warn("ogs_queue_push() failed [%d] in %s", + ogs_error("ogs_queue_push() failed [%d] in %s", (int)rv, ausf_timer_get_name(e->timer_id)); ausf_event_free(e); } diff --git a/src/bsf/init.c b/src/bsf/init.c index 95a9c24ea..247cd86ea 100644 --- a/src/bsf/init.c +++ b/src/bsf/init.c @@ -34,7 +34,7 @@ int bsf_initialize() bsf_context_init(); bsf_event_init(); - rv = ogs_sbi_context_parse_config("bsf", "nrf"); + rv = ogs_sbi_context_parse_config("bsf", "nrf", "scp"); if (rv != OGS_OK) return rv; rv = bsf_context_parse_config(); diff --git a/src/bsf/nf-sm.c b/src/bsf/nf-sm.c index 389cfbd7b..503777285 100644 --- a/src/bsf/nf-sm.c +++ b/src/bsf/nf-sm.c @@ -61,16 +61,18 @@ void bsf_nf_state_initial(ogs_fsm_t *s, bsf_event_t *e) nf_instance = e->sbi.data; ogs_assert(nf_instance); + nf_instance->t_registration_interval = ogs_timer_add(ogs_app()->timer_mgr, + bsf_timer_nf_instance_registration_interval, nf_instance); ogs_assert(nf_instance->t_registration_interval); - nf_instance->t_registration_interval->cb = - bsf_timer_nf_instance_registration_interval; + nf_instance->t_heartbeat_interval = ogs_timer_add(ogs_app()->timer_mgr, + bsf_timer_nf_instance_heartbeat_interval, nf_instance); ogs_assert(nf_instance->t_heartbeat_interval); - nf_instance->t_heartbeat_interval->cb = - bsf_timer_nf_instance_heartbeat_interval; + nf_instance->t_no_heartbeat = ogs_timer_add(ogs_app()->timer_mgr, + bsf_timer_nf_instance_no_heartbeat, nf_instance); ogs_assert(nf_instance->t_no_heartbeat); - nf_instance->t_no_heartbeat->cb = bsf_timer_nf_instance_no_heartbeat; + nf_instance->t_validity = ogs_timer_add(ogs_app()->timer_mgr, + bsf_timer_nf_instance_validity, nf_instance); ogs_assert(nf_instance->t_validity); - nf_instance->t_validity->cb = bsf_timer_nf_instance_validity; if (NF_INSTANCE_IS_NRF(nf_instance)) { OGS_FSM_TRAN(s, &bsf_nf_state_will_register); @@ -82,10 +84,20 @@ void bsf_nf_state_initial(ogs_fsm_t *s, bsf_event_t *e) void bsf_nf_state_final(ogs_fsm_t *s, bsf_event_t *e) { + ogs_sbi_nf_instance_t *nf_instance = NULL; + ogs_assert(s); ogs_assert(e); bsf_sm_debug(e); + + nf_instance = e->sbi.data; + ogs_assert(nf_instance); + + ogs_timer_delete(nf_instance->t_registration_interval); + ogs_timer_delete(nf_instance->t_heartbeat_interval); + ogs_timer_delete(nf_instance->t_no_heartbeat); + ogs_timer_delete(nf_instance->t_validity); } void bsf_nf_state_will_register(ogs_fsm_t *s, bsf_event_t *e) @@ -110,7 +122,8 @@ void bsf_nf_state_will_register(ogs_fsm_t *s, bsf_event_t *e) ogs_timer_start(nf_instance->t_registration_interval, ogs_app()->time.message.sbi.nf_register_interval); - ogs_assert(true == bsf_nnrf_nfm_send_nf_register(nf_instance)); + ogs_assert(true == ogs_nnrf_nfm_send_nf_register( + nf_instance, bsf_nnrf_nfm_build_register)); break; case OGS_FSM_EXIT_SIG: @@ -166,7 +179,8 @@ void bsf_nf_state_will_register(ogs_fsm_t *s, bsf_event_t *e) ogs_timer_start(nf_instance->t_registration_interval, ogs_app()->time.message.sbi.nf_register_interval); - ogs_assert(true == bsf_nnrf_nfm_send_nf_register(nf_instance)); + ogs_assert(true == ogs_nnrf_nfm_send_nf_register( + nf_instance, bsf_nnrf_nfm_build_register)); break; default: diff --git a/src/bsf/sbi-path.c b/src/bsf/sbi-path.c index 36cd59af8..b59ed8ac5 100644 --- a/src/bsf/sbi-path.c +++ b/src/bsf/sbi-path.c @@ -35,7 +35,8 @@ static int server_cb(ogs_sbi_request_t *request, void *data) rv = ogs_queue_push(ogs_app()->queue, e); if (rv != OGS_OK) { - ogs_warn("ogs_queue_push() failed:%d", (int)rv); + ogs_error("ogs_queue_push() failed:%d", (int)rv); + ogs_sbi_request_free(request); bsf_event_free(e); return OGS_ERROR; } @@ -43,11 +44,18 @@ static int server_cb(ogs_sbi_request_t *request, void *data) return OGS_OK; } -static int client_cb(ogs_sbi_response_t *response, void *data) +static int client_cb(int status, ogs_sbi_response_t *response, void *data) { bsf_event_t *e = NULL; int rv; + if (status != OGS_OK) { + ogs_log_message( + status == OGS_DONE ? OGS_LOG_DEBUG : OGS_LOG_WARN, 0, + "client_cb() failed [%d]", status); + return OGS_ERROR; + } + ogs_assert(response); e = bsf_event_new(BSF_EVT_SBI_CLIENT); @@ -57,7 +65,8 @@ static int client_cb(ogs_sbi_response_t *response, void *data) rv = ogs_queue_push(ogs_app()->queue, e); if (rv != OGS_OK) { - ogs_warn("ogs_queue_push() failed:%d", (int)rv); + ogs_error("ogs_queue_push() failed:%d", (int)rv); + ogs_sbi_response_free(response); bsf_event_free(e); return OGS_ERROR; } @@ -110,25 +119,10 @@ int bsf_sbi_open(void) void bsf_sbi_close(void) { + ogs_sbi_client_stop_all(); ogs_sbi_server_stop_all(); } -bool bsf_nnrf_nfm_send_nf_register(ogs_sbi_nf_instance_t *nf_instance) -{ - ogs_sbi_request_t *request = NULL; - ogs_sbi_client_t *client = NULL; - - ogs_assert(nf_instance); - client = nf_instance->client; - ogs_assert(client); - - request = bsf_nnrf_nfm_build_register(); - ogs_expect_or_return_val(request, false); - - return ogs_sbi_client_send_request( - client, client->cb, request, nf_instance); -} - bool bsf_sbi_send(ogs_sbi_nf_instance_t *nf_instance, ogs_sbi_xact_t *xact) { return ogs_sbi_send(nf_instance, client_cb, xact); diff --git a/src/bsf/sbi-path.h b/src/bsf/sbi-path.h index ab847624b..3996af7c0 100644 --- a/src/bsf/sbi-path.h +++ b/src/bsf/sbi-path.h @@ -29,8 +29,6 @@ extern "C" { int bsf_sbi_open(void); void bsf_sbi_close(void); -bool bsf_nnrf_nfm_send_nf_register(ogs_sbi_nf_instance_t *nf_instance); - bool bsf_sbi_send(ogs_sbi_nf_instance_t *nf_instance, ogs_sbi_xact_t *xact); bool bsf_sbi_discover_and_send(OpenAPI_nf_type_e target_nf_type, diff --git a/src/bsf/timer.c b/src/bsf/timer.c index c3bbb8864..35e47e936 100644 --- a/src/bsf/timer.c +++ b/src/bsf/timer.c @@ -81,7 +81,7 @@ static void timer_send_event(int timer_id, void *data) rv = ogs_queue_push(ogs_app()->queue, e); if (rv != OGS_OK) { - ogs_warn("ogs_queue_push() failed [%d] in %s", + ogs_error("ogs_queue_push() failed [%d] in %s", (int)rv, bsf_timer_get_name(e->timer_id)); bsf_event_free(e); } diff --git a/src/meson.build b/src/meson.build index e86a1896b..d53fce06b 100644 --- a/src/meson.build +++ b/src/meson.build @@ -36,6 +36,8 @@ subdir('sgwu') subdir('pcrf') subdir('nrf') +subdir('scp') + subdir('udr') subdir('udm') subdir('pcf') diff --git a/src/mme/mme-event.c b/src/mme/mme-event.c index 46c674879..b5482a853 100644 --- a/src/mme/mme-event.c +++ b/src/mme/mme-event.c @@ -125,7 +125,7 @@ void mme_sctp_event_push(mme_event_e id, rv = ogs_queue_push(ogs_app()->queue, e); if (rv != OGS_OK) { - ogs_warn("ogs_queue_push() failed:%d", (int)rv); + ogs_error("ogs_queue_push() failed:%d", (int)rv); ogs_free(e->addr); if (e->pkbuf) ogs_pkbuf_free(e->pkbuf); diff --git a/src/mme/mme-timer.c b/src/mme/mme-timer.c index 97a75cc7e..7cfde96f4 100644 --- a/src/mme/mme-timer.c +++ b/src/mme/mme-timer.c @@ -111,7 +111,7 @@ void mme_timer_s1_delayed_send(void *data) rv = ogs_queue_push(ogs_app()->queue, e); if (rv != OGS_OK) { - ogs_warn("ogs_queue_push() failed:%d", (int)rv); + ogs_error("ogs_queue_push() failed:%d", (int)rv); ogs_timer_delete(e->timer); mme_event_free(e); } @@ -131,7 +131,7 @@ static void emm_timer_event_send( rv = ogs_queue_push(ogs_app()->queue, e); if (rv != OGS_OK) { - ogs_warn("ogs_queue_push() failed:%d", (int)rv); + ogs_error("ogs_queue_push() failed:%d", (int)rv); mme_event_free(e); } } @@ -174,7 +174,7 @@ static void esm_timer_event_send( rv = ogs_queue_push(ogs_app()->queue, e); if (rv != OGS_OK) { - ogs_warn("ogs_queue_push() failed:%d", (int)rv); + ogs_error("ogs_queue_push() failed:%d", (int)rv); mme_event_free(e); } } @@ -196,7 +196,7 @@ void mme_timer_sgs_cli_conn_to_srv(void *data) rv = ogs_queue_push(ogs_app()->queue, e); if (rv != OGS_OK) { - ogs_warn("ogs_queue_push() failed:%d", (int)rv); + ogs_error("ogs_queue_push() failed:%d", (int)rv); mme_event_free(e); } } @@ -217,7 +217,7 @@ void mme_timer_s1_holding_timer_expire(void *data) rv = ogs_queue_push(ogs_app()->queue, e); if (rv != OGS_OK) { - ogs_warn("ogs_queue_push() failed:%d", (int)rv); + ogs_error("ogs_queue_push() failed:%d", (int)rv); mme_event_free(e); } } @@ -238,7 +238,7 @@ void mme_timer_s11_holding_timer_expire(void *data) rv = ogs_queue_push(ogs_app()->queue, e); if (rv != OGS_OK) { - ogs_warn("ogs_queue_push() failed:%d", (int)rv); + ogs_error("ogs_queue_push() failed:%d", (int)rv); mme_event_free(e); } } diff --git a/src/mme/s1ap-path.c b/src/mme/s1ap-path.c index f43c093d7..03ad82922 100644 --- a/src/mme/s1ap-path.c +++ b/src/mme/s1ap-path.c @@ -133,7 +133,7 @@ int s1ap_send_to_esm( e->create_action = create_action; rv = ogs_queue_push(ogs_app()->queue, e); if (rv != OGS_OK) { - ogs_warn("ogs_queue_push() failed:%d", (int)rv); + ogs_error("ogs_queue_push() failed:%d", (int)rv); ogs_pkbuf_free(e->pkbuf); mme_event_free(e); } @@ -221,7 +221,7 @@ int s1ap_send_to_nas(enb_ue_t *enb_ue, e->pkbuf = nasbuf; rv = ogs_queue_push(ogs_app()->queue, e); if (rv != OGS_OK) { - ogs_warn("s1ap_send_to_nas() failed:%d", (int)rv); + ogs_error("s1ap_send_to_nas() failed:%d", (int)rv); ogs_pkbuf_free(e->pkbuf); mme_event_free(e); } diff --git a/src/nrf/init.c b/src/nrf/init.c index 26f8b3999..5733a2441 100644 --- a/src/nrf/init.c +++ b/src/nrf/init.c @@ -32,7 +32,7 @@ int nrf_initialize() nrf_context_init(); nrf_event_init(); - rv = ogs_sbi_context_parse_config("nrf", NULL); + rv = ogs_sbi_context_parse_config("nrf", NULL, "scp"); if (rv != OGS_OK) return rv; rv = nrf_context_parse_config(); diff --git a/src/nrf/nnrf-build.c b/src/nrf/nnrf-build.c index bdaf15608..3c51c0226 100644 --- a/src/nrf/nnrf-build.c +++ b/src/nrf/nnrf-build.c @@ -20,7 +20,7 @@ #include "nnrf-build.h" ogs_sbi_request_t *nrf_nnrf_nfm_build_nf_status_notify( - ogs_sbi_client_t *client, ogs_sbi_subscription_t *subscription, + ogs_sbi_subscription_t *subscription, OpenAPI_notification_event_type_e event, ogs_sbi_nf_instance_t *nf_instance) { @@ -32,7 +32,6 @@ ogs_sbi_request_t *nrf_nnrf_nfm_build_nf_status_notify( OpenAPI_notification_data_t *NotificationData = NULL; - ogs_assert(client); ogs_assert(subscription); ogs_assert(event); ogs_assert(nf_instance); diff --git a/src/nrf/nnrf-build.h b/src/nrf/nnrf-build.h index da71d174b..b465c411d 100644 --- a/src/nrf/nnrf-build.h +++ b/src/nrf/nnrf-build.h @@ -28,7 +28,7 @@ extern "C" { #endif ogs_sbi_request_t *nrf_nnrf_nfm_build_nf_status_notify( - ogs_sbi_client_t *client, ogs_sbi_subscription_t *subscription, + ogs_sbi_subscription_t *subscription, OpenAPI_notification_event_type_e event, ogs_sbi_nf_instance_t *nf_instance); diff --git a/src/nrf/sbi-path.c b/src/nrf/sbi-path.c index 7724c7c17..9deeb6796 100644 --- a/src/nrf/sbi-path.c +++ b/src/nrf/sbi-path.c @@ -35,7 +35,11 @@ static int server_cb(ogs_sbi_request_t *request, void *data) rv = ogs_queue_push(ogs_app()->queue, e); if (rv != OGS_OK) { - ogs_warn("ogs_queue_push() failed:%d", (int)rv); + if (rv != OGS_DONE) + ogs_error("ogs_queue_push() failed:%d", (int)rv); + else + ogs_warn("ogs_queue_push() failed:%d", (int)rv); + ogs_sbi_request_free(request); nrf_event_free(e); return OGS_ERROR; } @@ -43,12 +47,19 @@ static int server_cb(ogs_sbi_request_t *request, void *data) return OGS_OK; } -static int client_notify_cb(ogs_sbi_response_t *response, void *data) +static int client_notify_cb( + int status, ogs_sbi_response_t *response, void *data) { int rv; - ogs_sbi_message_t message; + if (status != OGS_OK) { + ogs_log_message( + status == OGS_DONE ? OGS_LOG_DEBUG : OGS_LOG_WARN, 0, + "client_notify_cb() failed [%d]", status); + return OGS_ERROR; + } + ogs_assert(response); rv = ogs_sbi_parse_response(&message, response); @@ -69,14 +80,28 @@ static int client_notify_cb(ogs_sbi_response_t *response, void *data) int nrf_sbi_open(void) { + ogs_sbi_nf_instance_t *nf_instance = NULL; + if (ogs_sbi_server_start_all(server_cb) != OGS_OK) return OGS_ERROR; + /* Initialize SCP NF Instance */ + nf_instance = ogs_sbi_self()->scp_instance; + if (nf_instance) { + ogs_sbi_client_t *client = NULL; + + /* Client callback is only used when NF sends to SCP */ + client = nf_instance->client; + ogs_assert(client); + client->cb = client_notify_cb; + } + return OGS_OK; } void nrf_sbi_close(void) { + ogs_sbi_client_stop_all(); ogs_sbi_server_stop_all(); } @@ -92,10 +117,10 @@ bool nrf_nnrf_nfm_send_nf_status_notify(ogs_sbi_subscription_t *subscription, ogs_assert(client); request = nrf_nnrf_nfm_build_nf_status_notify( - client, subscription, event, nf_instance); + subscription, event, nf_instance); ogs_expect_or_return_val(request, false); - return ogs_sbi_client_send_request(client, client_notify_cb, request, NULL); + return ogs_sbi_scp_send_request(client, client_notify_cb, request, NULL); } bool nrf_nnrf_nfm_send_nf_status_notify_all( diff --git a/src/nrf/timer.c b/src/nrf/timer.c index b79679867..749a38eed 100644 --- a/src/nrf/timer.c +++ b/src/nrf/timer.c @@ -68,7 +68,7 @@ static void timer_send_event(int timer_id, void *data) rv = ogs_queue_push(ogs_app()->queue, e); if (rv != OGS_OK) { - ogs_warn("ogs_queue_push() failed:%d", (int)rv); + ogs_error("ogs_queue_push() failed:%d", (int)rv); nrf_event_free(e); } } diff --git a/src/nssf/init.c b/src/nssf/init.c index 49df3a7ce..1648d2c5c 100644 --- a/src/nssf/init.c +++ b/src/nssf/init.c @@ -32,7 +32,7 @@ int nssf_initialize() nssf_context_init(); nssf_event_init(); - rv = ogs_sbi_context_parse_config("nssf", "nrf"); + rv = ogs_sbi_context_parse_config("nssf", "nrf", "scp"); if (rv != OGS_OK) return rv; rv = nssf_context_parse_config(); diff --git a/src/nssf/nf-sm.c b/src/nssf/nf-sm.c index b4bc2f670..6f9f9897b 100644 --- a/src/nssf/nf-sm.c +++ b/src/nssf/nf-sm.c @@ -61,16 +61,18 @@ void nssf_nf_state_initial(ogs_fsm_t *s, nssf_event_t *e) nf_instance = e->sbi.data; ogs_assert(nf_instance); + nf_instance->t_registration_interval = ogs_timer_add(ogs_app()->timer_mgr, + nssf_timer_nf_instance_registration_interval, nf_instance); ogs_assert(nf_instance->t_registration_interval); - nf_instance->t_registration_interval->cb = - nssf_timer_nf_instance_registration_interval; + nf_instance->t_heartbeat_interval = ogs_timer_add(ogs_app()->timer_mgr, + nssf_timer_nf_instance_heartbeat_interval, nf_instance); ogs_assert(nf_instance->t_heartbeat_interval); - nf_instance->t_heartbeat_interval->cb = - nssf_timer_nf_instance_heartbeat_interval; + nf_instance->t_no_heartbeat = ogs_timer_add(ogs_app()->timer_mgr, + nssf_timer_nf_instance_no_heartbeat, nf_instance); ogs_assert(nf_instance->t_no_heartbeat); - nf_instance->t_no_heartbeat->cb = nssf_timer_nf_instance_no_heartbeat; + nf_instance->t_validity = ogs_timer_add(ogs_app()->timer_mgr, + nssf_timer_nf_instance_validity, nf_instance); ogs_assert(nf_instance->t_validity); - nf_instance->t_validity->cb = nssf_timer_nf_instance_validity; if (NF_INSTANCE_IS_NRF(nf_instance)) { OGS_FSM_TRAN(s, &nssf_nf_state_will_register); @@ -82,10 +84,20 @@ void nssf_nf_state_initial(ogs_fsm_t *s, nssf_event_t *e) void nssf_nf_state_final(ogs_fsm_t *s, nssf_event_t *e) { + ogs_sbi_nf_instance_t *nf_instance = NULL; + ogs_assert(s); ogs_assert(e); nssf_sm_debug(e); + + nf_instance = e->sbi.data; + ogs_assert(nf_instance); + + ogs_timer_delete(nf_instance->t_registration_interval); + ogs_timer_delete(nf_instance->t_heartbeat_interval); + ogs_timer_delete(nf_instance->t_no_heartbeat); + ogs_timer_delete(nf_instance->t_validity); } void nssf_nf_state_will_register(ogs_fsm_t *s, nssf_event_t *e) @@ -110,7 +122,8 @@ void nssf_nf_state_will_register(ogs_fsm_t *s, nssf_event_t *e) ogs_timer_start(nf_instance->t_registration_interval, ogs_app()->time.message.sbi.nf_register_interval); - ogs_assert(true == nssf_nnrf_nfm_send_nf_register(nf_instance)); + ogs_assert(true == ogs_nnrf_nfm_send_nf_register( + nf_instance, nssf_nnrf_nfm_build_register)); break; case OGS_FSM_EXIT_SIG: @@ -166,7 +179,8 @@ void nssf_nf_state_will_register(ogs_fsm_t *s, nssf_event_t *e) ogs_timer_start(nf_instance->t_registration_interval, ogs_app()->time.message.sbi.nf_register_interval); - ogs_assert(true == nssf_nnrf_nfm_send_nf_register(nf_instance)); + ogs_assert(true == ogs_nnrf_nfm_send_nf_register( + nf_instance, nssf_nnrf_nfm_build_register)); break; default: diff --git a/src/nssf/sbi-path.c b/src/nssf/sbi-path.c index f7c548180..139d160bc 100644 --- a/src/nssf/sbi-path.c +++ b/src/nssf/sbi-path.c @@ -35,7 +35,8 @@ static int server_cb(ogs_sbi_request_t *request, void *data) rv = ogs_queue_push(ogs_app()->queue, e); if (rv != OGS_OK) { - ogs_warn("ogs_queue_push() failed:%d", (int)rv); + ogs_error("ogs_queue_push() failed:%d", (int)rv); + ogs_sbi_request_free(request); nssf_event_free(e); return OGS_ERROR; } @@ -43,11 +44,18 @@ static int server_cb(ogs_sbi_request_t *request, void *data) return OGS_OK; } -static int client_cb(ogs_sbi_response_t *response, void *data) +static int client_cb(int status, ogs_sbi_response_t *response, void *data) { nssf_event_t *e = NULL; int rv; + if (status != OGS_OK) { + ogs_log_message( + status == OGS_DONE ? OGS_LOG_DEBUG : OGS_LOG_WARN, 0, + "client_cb() failed [%d]", status); + return OGS_ERROR; + } + ogs_assert(response); e = nssf_event_new(NSSF_EVT_SBI_CLIENT); @@ -57,7 +65,8 @@ static int client_cb(ogs_sbi_response_t *response, void *data) rv = ogs_queue_push(ogs_app()->queue, e); if (rv != OGS_OK) { - ogs_warn("ogs_queue_push() failed:%d", (int)rv); + ogs_error("ogs_queue_push() failed:%d", (int)rv); + ogs_sbi_response_free(response); nssf_event_free(e); return OGS_ERROR; } @@ -110,21 +119,6 @@ int nssf_sbi_open(void) void nssf_sbi_close(void) { + ogs_sbi_client_stop_all(); ogs_sbi_server_stop_all(); } - -bool nssf_nnrf_nfm_send_nf_register(ogs_sbi_nf_instance_t *nf_instance) -{ - ogs_sbi_request_t *request = NULL; - ogs_sbi_client_t *client = NULL; - - ogs_assert(nf_instance); - client = nf_instance->client; - ogs_assert(client); - - request = nssf_nnrf_nfm_build_register(); - ogs_expect_or_return_val(request, false); - - return ogs_sbi_client_send_request( - client, client->cb, request, nf_instance); -} diff --git a/src/nssf/sbi-path.h b/src/nssf/sbi-path.h index c1414bad4..bb733041e 100644 --- a/src/nssf/sbi-path.h +++ b/src/nssf/sbi-path.h @@ -29,8 +29,6 @@ extern "C" { int nssf_sbi_open(void); void nssf_sbi_close(void); -bool nssf_nnrf_nfm_send_nf_register(ogs_sbi_nf_instance_t *nf_instance); - #ifdef __cplusplus } #endif diff --git a/src/nssf/timer.c b/src/nssf/timer.c index e5456ddfd..ec77556a6 100644 --- a/src/nssf/timer.c +++ b/src/nssf/timer.c @@ -64,7 +64,7 @@ static void sbi_timer_send_event(int timer_id, void *data) rv = ogs_queue_push(ogs_app()->queue, e); if (rv != OGS_OK) { - ogs_warn("ogs_queue_push() failed [%d] in %s", + ogs_error("ogs_queue_push() failed [%d] in %s", (int)rv, nssf_timer_get_name(e->timer_id)); nssf_event_free(e); } diff --git a/src/pcf/init.c b/src/pcf/init.c index dd6fabc72..91332c9f7 100644 --- a/src/pcf/init.c +++ b/src/pcf/init.c @@ -32,7 +32,7 @@ int pcf_initialize() pcf_context_init(); pcf_event_init(); - rv = ogs_sbi_context_parse_config("pcf", "nrf"); + rv = ogs_sbi_context_parse_config("pcf", "nrf", "scp"); if (rv != OGS_OK) return rv; rv = pcf_context_parse_config(); diff --git a/src/pcf/nf-sm.c b/src/pcf/nf-sm.c index ba51df645..b6fc57506 100644 --- a/src/pcf/nf-sm.c +++ b/src/pcf/nf-sm.c @@ -61,16 +61,18 @@ void pcf_nf_state_initial(ogs_fsm_t *s, pcf_event_t *e) nf_instance = e->sbi.data; ogs_assert(nf_instance); + nf_instance->t_registration_interval = ogs_timer_add(ogs_app()->timer_mgr, + pcf_timer_nf_instance_registration_interval, nf_instance); ogs_assert(nf_instance->t_registration_interval); - nf_instance->t_registration_interval->cb = - pcf_timer_nf_instance_registration_interval; + nf_instance->t_heartbeat_interval = ogs_timer_add(ogs_app()->timer_mgr, + pcf_timer_nf_instance_heartbeat_interval, nf_instance); ogs_assert(nf_instance->t_heartbeat_interval); - nf_instance->t_heartbeat_interval->cb = - pcf_timer_nf_instance_heartbeat_interval; + nf_instance->t_no_heartbeat = ogs_timer_add(ogs_app()->timer_mgr, + pcf_timer_nf_instance_no_heartbeat, nf_instance); ogs_assert(nf_instance->t_no_heartbeat); - nf_instance->t_no_heartbeat->cb = pcf_timer_nf_instance_no_heartbeat; + nf_instance->t_validity = ogs_timer_add(ogs_app()->timer_mgr, + pcf_timer_nf_instance_validity, nf_instance); ogs_assert(nf_instance->t_validity); - nf_instance->t_validity->cb = pcf_timer_nf_instance_validity; if (NF_INSTANCE_IS_NRF(nf_instance)) { OGS_FSM_TRAN(s, &pcf_nf_state_will_register); @@ -82,10 +84,20 @@ void pcf_nf_state_initial(ogs_fsm_t *s, pcf_event_t *e) void pcf_nf_state_final(ogs_fsm_t *s, pcf_event_t *e) { + ogs_sbi_nf_instance_t *nf_instance = NULL; + ogs_assert(s); ogs_assert(e); pcf_sm_debug(e); + + nf_instance = e->sbi.data; + ogs_assert(nf_instance); + + ogs_timer_delete(nf_instance->t_registration_interval); + ogs_timer_delete(nf_instance->t_heartbeat_interval); + ogs_timer_delete(nf_instance->t_no_heartbeat); + ogs_timer_delete(nf_instance->t_validity); } void pcf_nf_state_will_register(ogs_fsm_t *s, pcf_event_t *e) @@ -110,7 +122,8 @@ void pcf_nf_state_will_register(ogs_fsm_t *s, pcf_event_t *e) ogs_timer_start(nf_instance->t_registration_interval, ogs_app()->time.message.sbi.nf_register_interval); - ogs_assert(true == pcf_nnrf_nfm_send_nf_register(nf_instance)); + ogs_assert(true == ogs_nnrf_nfm_send_nf_register( + nf_instance, pcf_nnrf_nfm_build_register)); break; case OGS_FSM_EXIT_SIG: @@ -167,7 +180,8 @@ void pcf_nf_state_will_register(ogs_fsm_t *s, pcf_event_t *e) ogs_timer_start(nf_instance->t_registration_interval, ogs_app()->time.message.sbi.nf_register_interval); - ogs_assert(true == pcf_nnrf_nfm_send_nf_register(nf_instance)); + ogs_assert(true == ogs_nnrf_nfm_send_nf_register( + nf_instance, pcf_nnrf_nfm_build_register)); break; default: diff --git a/src/pcf/sbi-path.c b/src/pcf/sbi-path.c index 1b5a42108..7c547f990 100644 --- a/src/pcf/sbi-path.c +++ b/src/pcf/sbi-path.c @@ -35,7 +35,8 @@ static int server_cb(ogs_sbi_request_t *request, void *data) rv = ogs_queue_push(ogs_app()->queue, e); if (rv != OGS_OK) { - ogs_warn("ogs_queue_push() failed:%d", (int)rv); + ogs_error("ogs_queue_push() failed:%d", (int)rv); + ogs_sbi_request_free(request); pcf_event_free(e); return OGS_ERROR; } @@ -43,11 +44,18 @@ static int server_cb(ogs_sbi_request_t *request, void *data) return OGS_OK; } -static int client_cb(ogs_sbi_response_t *response, void *data) +static int client_cb(int status, ogs_sbi_response_t *response, void *data) { pcf_event_t *e = NULL; int rv; + if (status != OGS_OK) { + ogs_log_message( + status == OGS_DONE ? OGS_LOG_DEBUG : OGS_LOG_WARN, 0, + "client_cb() failed [%d]", status); + return OGS_ERROR; + } + ogs_assert(response); e = pcf_event_new(PCF_EVT_SBI_CLIENT); @@ -57,7 +65,8 @@ static int client_cb(ogs_sbi_response_t *response, void *data) rv = ogs_queue_push(ogs_app()->queue, e); if (rv != OGS_OK) { - ogs_warn("ogs_queue_push() failed:%d", (int)rv); + ogs_error("ogs_queue_push() failed:%d", (int)rv); + ogs_sbi_response_free(response); pcf_event_free(e); return OGS_ERROR; } @@ -123,25 +132,10 @@ int pcf_sbi_open(void) void pcf_sbi_close(void) { + ogs_sbi_client_stop_all(); ogs_sbi_server_stop_all(); } -bool pcf_nnrf_nfm_send_nf_register(ogs_sbi_nf_instance_t *nf_instance) -{ - ogs_sbi_request_t *request = NULL; - ogs_sbi_client_t *client = NULL; - - ogs_assert(nf_instance); - client = nf_instance->client; - ogs_assert(client); - - request = pcf_nnrf_nfm_build_register(); - ogs_expect_or_return_val(request, false); - - return ogs_sbi_client_send_request( - client, client->cb, request, nf_instance); -} - bool pcf_sbi_send(ogs_sbi_nf_instance_t *nf_instance, ogs_sbi_xact_t *xact) { return ogs_sbi_send(nf_instance, client_cb, xact); @@ -209,12 +203,19 @@ bool pcf_sess_sbi_discover_and_send(OpenAPI_nf_type_e target_nf_type, return true; } -static int client_notify_cb(ogs_sbi_response_t *response, void *data) +static int client_notify_cb( + int status, ogs_sbi_response_t *response, void *data) { int rv; - ogs_sbi_message_t message; + if (status != OGS_OK) { + ogs_log_message( + status == OGS_DONE ? OGS_LOG_DEBUG : OGS_LOG_WARN, 0, + "client_notify_cb() failed [%d]", status); + return OGS_ERROR; + } + ogs_assert(response); rv = ogs_sbi_parse_response(&message, response); @@ -234,12 +235,13 @@ static int client_notify_cb(ogs_sbi_response_t *response, void *data) return OGS_OK; } -static int client_delete_notify_cb(ogs_sbi_response_t *response, void *data) +static int client_delete_notify_cb( + int status, ogs_sbi_response_t *response, void *data) { pcf_app_t *app_session = data; ogs_assert(app_session); - client_notify_cb(response, data); + client_notify_cb(status, response, data); pcf_app_remove(app_session); diff --git a/src/pcf/sbi-path.h b/src/pcf/sbi-path.h index 7004e290e..85d6b8dfe 100644 --- a/src/pcf/sbi-path.h +++ b/src/pcf/sbi-path.h @@ -34,8 +34,6 @@ extern "C" { int pcf_sbi_open(void); void pcf_sbi_close(void); -bool pcf_nnrf_nfm_send_nf_register(ogs_sbi_nf_instance_t *nf_instance); - bool pcf_sbi_send(ogs_sbi_nf_instance_t *nf_instance, ogs_sbi_xact_t *xact); bool pcf_ue_sbi_discover_and_send(OpenAPI_nf_type_e target_nf_type, pcf_ue_t *pcf_ue, ogs_sbi_stream_t *stream, void *data, diff --git a/src/pcf/timer.c b/src/pcf/timer.c index 6cd58fd6d..3fb493d1e 100644 --- a/src/pcf/timer.c +++ b/src/pcf/timer.c @@ -79,7 +79,7 @@ static void sbi_timer_send_event(int timer_id, void *data) rv = ogs_queue_push(ogs_app()->queue, e); if (rv != OGS_OK) { - ogs_warn("ogs_queue_push() failed [%d] in %s", + ogs_error("ogs_queue_push() failed [%d] in %s", (int)rv, pcf_timer_get_name(e->timer_id)); pcf_event_free(e); } diff --git a/src/scp/app.c b/src/scp/app.c new file mode 100644 index 000000000..dd4b94cd2 --- /dev/null +++ b/src/scp/app.c @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2019-2022 by Sukchan Lee + * + * This file is part of Open5GS. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "ogs-app.h" + +int app_initialize(const char *const argv[]) +{ + int rv; + + rv = scp_initialize(); + if (rv != OGS_OK) { + ogs_error("Failed to intialize SCP"); + return rv; + } + ogs_info("SCP initialize...done"); + + return OGS_OK; +} + +void app_terminate(void) +{ + scp_terminate(); + ogs_info("SCP terminate...done"); +} diff --git a/src/scp/context.c b/src/scp/context.c new file mode 100644 index 000000000..8ee3b4764 --- /dev/null +++ b/src/scp/context.c @@ -0,0 +1,163 @@ +/* + * Copyright (C) 2019-2022 by Sukchan Lee + * + * This file is part of Open5GS. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "context.h" + +static scp_context_t self; + +int __scp_log_domain; + +static OGS_POOL(scp_conn_pool, scp_conn_t); + +static int context_initialized = 0; + +static int max_num_of_scp_conn = 0; + +void scp_context_init(void) +{ + ogs_assert(context_initialized == 0); + + /* Initialize SCP context */ + memset(&self, 0, sizeof(scp_context_t)); + + ogs_log_install_domain(&__scp_log_domain, "scp", ogs_core()->log.level); + +#define MAX_NUM_OF_SCP_CONN 8 + max_num_of_scp_conn = ogs_app()->max.ue * MAX_NUM_OF_SCP_CONN; + + ogs_pool_init(&scp_conn_pool, max_num_of_scp_conn); + + context_initialized = 1; +} + +void scp_context_final(void) +{ + ogs_assert(context_initialized == 1); + + scp_conn_remove_all(); + + ogs_pool_final(&scp_conn_pool); + + context_initialized = 0; +} + +scp_context_t *scp_self(void) +{ + return &self; +} + +static int scp_context_prepare(void) +{ + return OGS_OK; +} + +static int scp_context_validation(void) +{ + return OGS_OK; +} + +int scp_context_parse_config(void) +{ + int rv; + yaml_document_t *document = NULL; + ogs_yaml_iter_t root_iter; + + document = ogs_app()->document; + ogs_assert(document); + + rv = scp_context_prepare(); + if (rv != OGS_OK) return rv; + + ogs_yaml_iter_init(&root_iter, document); + while (ogs_yaml_iter_next(&root_iter)) { + const char *root_key = ogs_yaml_iter_key(&root_iter); + ogs_assert(root_key); + if (!strcmp(root_key, "scp")) { + ogs_yaml_iter_t scp_iter; + ogs_yaml_iter_recurse(&root_iter, &scp_iter); + while (ogs_yaml_iter_next(&scp_iter)) { + const char *scp_key = ogs_yaml_iter_key(&scp_iter); + ogs_assert(scp_key); + if (!strcmp(scp_key, "sbi")) { + /* handle config in sbi library */ + } else + ogs_warn("unknown key `%s`", scp_key); + } + } + } + + rv = scp_context_validation(); + if (rv != OGS_OK) return rv; + + return OGS_OK; +} + +scp_conn_t *scp_conn_add(ogs_sbi_stream_t *stream) +{ + scp_conn_t *conn = NULL; + + ogs_assert(stream); + + ogs_pool_alloc(&scp_conn_pool, &conn); + if (!conn) { + ogs_error("Maximum number of connection[%d] reached", + max_num_of_scp_conn); + return NULL; + } + memset(conn, 0, sizeof *conn); + + conn->stream = stream; + + ogs_list_add(&self.conn_list, conn); + + return conn; +} + +void scp_conn_remove(scp_conn_t *conn) +{ + ogs_assert(conn); + + ogs_list_remove(&self.conn_list, conn); + + if (conn->client) + ogs_sbi_client_remove(conn->client); + + ogs_pool_free(&scp_conn_pool, conn); +} + +void scp_conn_remove_all(void) +{ + scp_conn_t *conn = NULL, *next_conn = NULL; + + ogs_list_for_each_safe(&self.conn_list, next_conn, conn) + scp_conn_remove(conn); +} + +scp_conn_t *scp_conn_find(uint32_t index) +{ + return ogs_pool_find(&scp_conn_pool, index); +} + +void scp_conn_select_nf(scp_conn_t *sess, OpenAPI_nf_type_e nf_type) +{ + ogs_assert(sess); + ogs_assert(nf_type); + + ogs_sbi_select_nf(&sess->sbi, nf_type, scp_nf_state_registered); +} diff --git a/src/scp/context.h b/src/scp/context.h new file mode 100644 index 000000000..db4198c7f --- /dev/null +++ b/src/scp/context.h @@ -0,0 +1,88 @@ +/* + * Copyright (C) 2019-2022 by Sukchan Lee + * + * This file is part of Open5GS. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef SCP_CONTEXT_H +#define SCP_CONTEXT_H + +#include "ogs-sbi.h" +#include "ogs-app.h" + +#include "timer.h" +#include "scp-sm.h" + +#ifdef __cplusplus +extern "C" { +#endif + +extern int __scp_log_domain; + +#undef OGS_LOG_DOMAIN +#define OGS_LOG_DOMAIN __scp_log_domain + +typedef struct scp_context_s { + ogs_list_t conn_list; +} scp_context_t; + +#define SCP_NF_INSTANCE_CLEAR(_cAUSE, _nFInstance) \ + do { \ + ogs_assert(_nFInstance); \ + if ((_nFInstance)->reference_count == 1) { \ + ogs_info("[%s] (%s) NF removed", (_nFInstance)->id, (_cAUSE)); \ + scp_nf_fsm_fini((_nFInstance)); \ + } else { \ + /* There is an assocation with other context */ \ + ogs_info("[%s:%d] (%s) NF suspended", \ + _nFInstance->id, _nFInstance->reference_count, (_cAUSE)); \ + OGS_FSM_TRAN(&_nFInstance->sm, scp_nf_state_de_registered); \ + ogs_fsm_dispatch(&_nFInstance->sm, NULL); \ + } \ + ogs_sbi_nf_instance_remove(_nFInstance); \ + } while(0) + +typedef struct scp_conn_s scp_conn_t; + +typedef struct scp_conn_s { + ogs_sbi_object_t sbi; + + ogs_sbi_client_t *client; + + ogs_sbi_stream_t *stream; + ogs_sbi_request_t *request; + +} scp_conn_t; + +void scp_context_init(void); +void scp_context_final(void); +scp_context_t *scp_self(void); + +int scp_context_parse_config(void); + +scp_conn_t *scp_conn_add(ogs_sbi_stream_t *stream); +void scp_conn_remove(scp_conn_t *sess); +void scp_conn_remove_all(void); + +scp_conn_t *scp_conn_find(uint32_t index); + +void scp_conn_select_nf(scp_conn_t *sess, OpenAPI_nf_type_e nf_type); + +#ifdef __cplusplus +} +#endif + +#endif /* SCP_CONTEXT_H */ diff --git a/src/scp/event.c b/src/scp/event.c new file mode 100644 index 000000000..e4736a0d4 --- /dev/null +++ b/src/scp/event.c @@ -0,0 +1,77 @@ +/* + * Copyright (C) 2019-2022 by Sukchan Lee + * + * This file is part of Open5GS. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "event.h" +#include "context.h" + +static OGS_POOL(pool, scp_event_t); + +void scp_event_init(void) +{ + ogs_pool_init(&pool, ogs_app()->pool.event); +} + +void scp_event_final(void) +{ + ogs_pool_final(&pool); +} + +scp_event_t *scp_event_new(scp_event_e id) +{ + scp_event_t *e = NULL; + + ogs_pool_alloc(&pool, &e); + ogs_assert(e); + memset(e, 0, sizeof(*e)); + + e->id = id; + + return e; +} + +void scp_event_free(scp_event_t *e) +{ + ogs_assert(e); + ogs_pool_free(&pool, e); +} + +const char *scp_event_get_name(scp_event_t *e) +{ + if (e == NULL) + return OGS_FSM_NAME_INIT_SIG; + + switch (e->id) { + case OGS_FSM_ENTRY_SIG: + return OGS_FSM_NAME_ENTRY_SIG; + case OGS_FSM_EXIT_SIG: + return OGS_FSM_NAME_EXIT_SIG; + + case SCP_EVT_SBI_SERVER: + return "SCP_EVT_SBI_SERVER"; + case SCP_EVT_SBI_CLIENT: + return "SCP_EVT_SBI_CLIENT"; + case SCP_EVT_SBI_TIMER: + return "SCP_EVT_SBI_TIMER"; + + default: + break; + } + + return "UNKNOWN_EVENT"; +} diff --git a/src/scp/event.h b/src/scp/event.h new file mode 100644 index 000000000..29983261d --- /dev/null +++ b/src/scp/event.h @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2019-2022 by Sukchan Lee + * + * This file is part of Open5GS. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef SCP_EVENT_H +#define SCP_EVENT_H + +#include "ogs-core.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct scp_sess_s scp_sess_t; +typedef struct ogs_sbi_request_s ogs_sbi_request_t; +typedef struct ogs_sbi_response_s ogs_sbi_response_t; +typedef struct ogs_sbi_message_s ogs_sbi_message_t; +typedef struct ogs_sbi_nf_instance_s ogs_sbi_nf_instance_t; + +typedef enum { + SCP_EVT_BASE = OGS_FSM_USER_SIG, + + SCP_EVT_SBI_SERVER, + SCP_EVT_SBI_CLIENT, + SCP_EVT_SBI_TIMER, + + SCP_EVT_TOP, + +} scp_event_e; + +typedef struct scp_event_s { + int id; + ogs_pkbuf_t *pkbuf; + int timer_id; + + struct { + ogs_sbi_request_t *request; + ogs_sbi_response_t *response; + void *data; + int state; + + ogs_sbi_message_t *message; + } sbi; + + ogs_sbi_nf_instance_t *nf_instance; + scp_sess_t *sess; +} scp_event_t; + +void scp_event_init(void); +void scp_event_final(void); + +scp_event_t *scp_event_new(scp_event_e id); +void scp_event_free(scp_event_t *e); + +const char *scp_event_get_name(scp_event_t *e); + +#ifdef __cplusplus +} +#endif + +#endif /* SCP_EVENT_H */ diff --git a/src/scp/init.c b/src/scp/init.c new file mode 100644 index 000000000..d0250d72c --- /dev/null +++ b/src/scp/init.c @@ -0,0 +1,143 @@ +/* + * Copyright (C) 2019-2022 by Sukchan Lee + * + * This file is part of Open5GS. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "context.h" +#include "sbi-path.h" + +static ogs_thread_t *thread; +static void scp_main(void *data); + +static int initialized = 0; + +int scp_initialize() +{ + int rv; + + ogs_sbi_context_init(); + + scp_context_init(); + scp_event_init(); + + rv = ogs_sbi_context_parse_config("scp", "nrf", "next_scp"); + if (rv != OGS_OK) return rv; + + rv = scp_context_parse_config(); + if (rv != OGS_OK) return rv; + + rv = ogs_log_config_domain( + ogs_app()->logger.domain, ogs_app()->logger.level); + if (rv != OGS_OK) return rv; + + rv = scp_sbi_open(); + if (rv != 0) return OGS_ERROR; + + thread = ogs_thread_create(scp_main, NULL); + if (!thread) return OGS_ERROR; + + initialized = 1; + + return OGS_OK; +} + +static ogs_timer_t *t_termination_holding = NULL; + +static void event_termination(void) +{ + ogs_sbi_nf_instance_t *nf_instance = NULL; + + /* Sending NF Instance De-registeration to NRF */ + ogs_list_for_each(&ogs_sbi_self()->nf_instance_list, nf_instance) + scp_nf_fsm_fini(nf_instance); + + /* Starting holding timer */ + t_termination_holding = ogs_timer_add(ogs_app()->timer_mgr, NULL, NULL); + ogs_assert(t_termination_holding); +#define TERMINATION_HOLDING_TIME ogs_time_from_msec(300) + ogs_timer_start(t_termination_holding, TERMINATION_HOLDING_TIME); + + /* Sending termination event to the queue */ + ogs_queue_term(ogs_app()->queue); + ogs_pollset_notify(ogs_app()->pollset); +} + +void scp_terminate(void) +{ + if (!initialized) return; + + /* Daemon terminating */ + event_termination(); + ogs_thread_destroy(thread); + ogs_timer_delete(t_termination_holding); + + scp_sbi_close(); + + scp_context_final(); + + ogs_sbi_context_final(); + + scp_event_final(); /* Destroy event */ +} + +static void scp_main(void *data) +{ + ogs_fsm_t scp_sm; + int rv; + + ogs_fsm_create(&scp_sm, scp_state_initial, scp_state_final); + ogs_fsm_init(&scp_sm, 0); + + for ( ;; ) { + ogs_pollset_poll(ogs_app()->pollset, + ogs_timer_mgr_next(ogs_app()->timer_mgr)); + + /* + * After ogs_pollset_poll(), ogs_timer_mgr_expire() must be called. + * + * The reason is why ogs_timer_mgr_next() can get the corrent value + * when ogs_timer_stop() is called internally in ogs_timer_mgr_expire(). + * + * You should not use event-queue before ogs_timer_mgr_expire(). + * In this case, ogs_timer_mgr_expire() does not work + * because 'if rv == OGS_DONE' statement is exiting and + * not calling ogs_timer_mgr_expire(). + */ + ogs_timer_mgr_expire(ogs_app()->timer_mgr); + + for ( ;; ) { + scp_event_t *e = NULL; + + rv = ogs_queue_trypop(ogs_app()->queue, (void**)&e); + ogs_assert(rv != OGS_ERROR); + + if (rv == OGS_DONE) + goto done; + + if (rv == OGS_RETRY) + break; + + ogs_assert(e); + ogs_fsm_dispatch(&scp_sm, e); + scp_event_free(e); + } + } +done: + + ogs_fsm_fini(&scp_sm, 0); + ogs_fsm_delete(&scp_sm); +} diff --git a/src/scp/meson.build b/src/scp/meson.build new file mode 100644 index 000000000..b8249f40b --- /dev/null +++ b/src/scp/meson.build @@ -0,0 +1,59 @@ +# Copyright (C) 2019-2022 by Sukchan Lee + +# This file is part of Open5GS. + +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +libscp_sources = files(''' + context.c + event.c + timer.c + + nnrf-build.c + nnrf-handler.c + nf-sm.c + + nscp-handler.c + + sbi-path.c + scp-sm.c + + init.c +'''.split()) + +libscp = static_library('scp', + sources : libscp_sources, + dependencies : [libapp_dep, + libcrypt_dep, + libsbi_dep], + install : false) + +libscp_dep = declare_dependency( + link_with : libscp, + dependencies : [libapp_dep, + libcrypt_dep, + libsbi_dep]) + +scp_sources = files(''' + app.c + ../main.c +'''.split()) + +executable('open5gs-scpd', + sources : scp_sources, + c_args : '-DDEFAULT_CONFIG_FILENAME="@0@/scp.yaml"'.format(open5gs_sysconfdir), + include_directories : srcinc, + dependencies : libscp_dep, + install_rpath : libdir, + install : true) diff --git a/src/scp/nf-sm.c b/src/scp/nf-sm.c new file mode 100644 index 000000000..ecd3af198 --- /dev/null +++ b/src/scp/nf-sm.c @@ -0,0 +1,442 @@ +/* + * Copyright (C) 2019-2022 by Sukchan Lee + * + * This file is part of Open5GS. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "context.h" + +#include "sbi-path.h" +#include "nnrf-handler.h" + +void scp_nf_fsm_init(ogs_sbi_nf_instance_t *nf_instance) +{ + scp_event_t e; + + ogs_assert(nf_instance); + + memset(&e, 0, sizeof(e)); + e.sbi.data = nf_instance; + + ogs_fsm_create(&nf_instance->sm, + scp_nf_state_initial, scp_nf_state_final); + ogs_fsm_init(&nf_instance->sm, &e); +} + +void scp_nf_fsm_fini(ogs_sbi_nf_instance_t *nf_instance) +{ + scp_event_t e; + + ogs_assert(nf_instance); + + memset(&e, 0, sizeof(e)); + e.sbi.data = nf_instance; + + ogs_fsm_fini(&nf_instance->sm, &e); + ogs_fsm_delete(&nf_instance->sm); +} + +void scp_nf_state_initial(ogs_fsm_t *s, scp_event_t *e) +{ + ogs_sbi_nf_instance_t *nf_instance = NULL; + + ogs_assert(s); + ogs_assert(e); + + scp_sm_debug(e); + + nf_instance = e->sbi.data; + ogs_assert(nf_instance); + + nf_instance->t_registration_interval = ogs_timer_add(ogs_app()->timer_mgr, + scp_timer_nf_instance_registration_interval, nf_instance); + ogs_assert(nf_instance->t_registration_interval); + nf_instance->t_heartbeat_interval = ogs_timer_add(ogs_app()->timer_mgr, + scp_timer_nf_instance_heartbeat_interval, nf_instance); + ogs_assert(nf_instance->t_heartbeat_interval); + nf_instance->t_no_heartbeat = ogs_timer_add(ogs_app()->timer_mgr, + scp_timer_nf_instance_no_heartbeat, nf_instance); + ogs_assert(nf_instance->t_no_heartbeat); + nf_instance->t_validity = ogs_timer_add(ogs_app()->timer_mgr, + scp_timer_nf_instance_validity, nf_instance); + ogs_assert(nf_instance->t_validity); + + if (NF_INSTANCE_IS_NRF(nf_instance)) { + OGS_FSM_TRAN(s, &scp_nf_state_will_register); + } else { + ogs_assert(nf_instance->id); + OGS_FSM_TRAN(s, &scp_nf_state_registered); + } +} + +void scp_nf_state_final(ogs_fsm_t *s, scp_event_t *e) +{ + ogs_sbi_nf_instance_t *nf_instance = NULL; + + ogs_assert(s); + ogs_assert(e); + + scp_sm_debug(e); + + nf_instance = e->sbi.data; + ogs_assert(nf_instance); + + ogs_timer_delete(nf_instance->t_registration_interval); + ogs_timer_delete(nf_instance->t_heartbeat_interval); + ogs_timer_delete(nf_instance->t_no_heartbeat); + ogs_timer_delete(nf_instance->t_validity); +} + +void scp_nf_state_will_register(ogs_fsm_t *s, scp_event_t *e) +{ + ogs_sbi_nf_instance_t *nf_instance = NULL; + ogs_sbi_client_t *client = NULL; + ogs_sbi_message_t *message = NULL; + ogs_sockaddr_t *addr = NULL; + + ogs_assert(s); + ogs_assert(e); + + scp_sm_debug(e); + + nf_instance = e->sbi.data; + ogs_assert(nf_instance); + ogs_assert(ogs_sbi_self()->nf_instance); + ogs_assert(NF_INSTANCE_IS_NRF(nf_instance)); + + switch (e->id) { + case OGS_FSM_ENTRY_SIG: + ogs_timer_start(nf_instance->t_registration_interval, + ogs_app()->time.message.sbi.nf_register_interval); + + ogs_assert(true == ogs_nnrf_nfm_send_nf_register( + nf_instance, scp_nnrf_nfm_build_register)); + break; + + case OGS_FSM_EXIT_SIG: + ogs_timer_stop(nf_instance->t_registration_interval); + break; + + case SCP_EVT_SBI_CLIENT: + message = e->sbi.message; + ogs_assert(message); + + SWITCH(message->h.service.name) + CASE(OGS_SBI_SERVICE_NAME_NNRF_NFM) + + SWITCH(message->h.resource.component[0]) + CASE(OGS_SBI_RESOURCE_NAME_NF_INSTANCES) + + if (message->res_status == OGS_SBI_HTTP_STATUS_OK || + message->res_status == OGS_SBI_HTTP_STATUS_CREATED) { + scp_nnrf_handle_nf_register(nf_instance, message); + OGS_FSM_TRAN(s, &scp_nf_state_registered); + } else { + ogs_error("[%s] HTTP Response Status Code [%d]", + ogs_sbi_self()->nf_instance->id, + message->res_status); + OGS_FSM_TRAN(s, &scp_nf_state_exception); + } + break; + + DEFAULT + ogs_error("[%s] Invalid resource name [%s]", + ogs_sbi_self()->nf_instance->id, + message->h.resource.component[0]); + END + break; + + DEFAULT + ogs_error("[%s] Invalid API name [%s]", + ogs_sbi_self()->nf_instance->id, message->h.service.name); + END + break; + + case SCP_EVT_SBI_TIMER: + switch(e->timer_id) { + case SCP_TIMER_NF_INSTANCE_REGISTRATION_INTERVAL: + client = nf_instance->client; + ogs_assert(client); + addr = client->node.addr; + ogs_assert(addr); + + ogs_warn("[%s] Retry to registration with NRF", + ogs_sbi_self()->nf_instance->id); + + ogs_timer_start(nf_instance->t_registration_interval, + ogs_app()->time.message.sbi.nf_register_interval); + + ogs_assert(true == ogs_nnrf_nfm_send_nf_register( + nf_instance, scp_nnrf_nfm_build_register)); + break; + + default: + ogs_error("[%s] Unknown timer[%s:%d]", + ogs_sbi_self()->nf_instance->id, + scp_timer_get_name(e->timer_id), e->timer_id); + } + break; + + default: + ogs_error("[%s] Unknown event %s", + ogs_sbi_self()->nf_instance->id, scp_event_get_name(e)); + break; + } +} + +void scp_nf_state_registered(ogs_fsm_t *s, scp_event_t *e) +{ + ogs_sbi_nf_instance_t *nf_instance = NULL; + ogs_sbi_client_t *client = NULL; + ogs_sbi_message_t *message = NULL; + ogs_assert(s); + ogs_assert(e); + + scp_sm_debug(e); + + nf_instance = e->sbi.data; + ogs_assert(nf_instance); + ogs_assert(ogs_sbi_self()->nf_instance); + + switch (e->id) { + case OGS_FSM_ENTRY_SIG: + if (NF_INSTANCE_IS_NRF(nf_instance)) { + ogs_info("[%s] NF registered [Heartbeat:%ds]", + ogs_sbi_self()->nf_instance->id, + nf_instance->time.heartbeat_interval); + + client = nf_instance->client; + ogs_assert(client); + + if (nf_instance->time.heartbeat_interval) { + ogs_timer_start(nf_instance->t_heartbeat_interval, + ogs_time_from_sec(nf_instance->time.heartbeat_interval)); + ogs_timer_start(nf_instance->t_no_heartbeat, + ogs_time_from_sec( + nf_instance->time.heartbeat_interval + + ogs_app()->time.nf_instance.no_heartbeat_margin)); + } + } + + break; + + case OGS_FSM_EXIT_SIG: + if (NF_INSTANCE_IS_NRF(nf_instance)) { + ogs_info("[%s] NF de-registered", ogs_sbi_self()->nf_instance->id); + + if (nf_instance->time.heartbeat_interval) { + ogs_timer_stop(nf_instance->t_heartbeat_interval); + ogs_timer_stop(nf_instance->t_no_heartbeat); + } + + if (!OGS_FSM_CHECK(&nf_instance->sm, scp_nf_state_exception)) { + ogs_assert(true == + ogs_nnrf_nfm_send_nf_de_register(nf_instance)); + } + } + break; + + case SCP_EVT_SBI_CLIENT: + message = e->sbi.message; + ogs_assert(message); + + SWITCH(message->h.service.name) + CASE(OGS_SBI_SERVICE_NAME_NNRF_NFM) + + SWITCH(message->h.resource.component[0]) + CASE(OGS_SBI_RESOURCE_NAME_NF_INSTANCES) + + if (message->res_status == OGS_SBI_HTTP_STATUS_NO_CONTENT || + message->res_status == OGS_SBI_HTTP_STATUS_OK) { + if (nf_instance->time.heartbeat_interval) + ogs_timer_start(nf_instance->t_no_heartbeat, + ogs_time_from_sec( + nf_instance->time.heartbeat_interval + + ogs_app()->time.nf_instance. + no_heartbeat_margin)); + } else { + ogs_warn("[%s] HTTP response error [%d]", + ogs_sbi_self()->nf_instance->id, + message->res_status); + OGS_FSM_TRAN(s, &scp_nf_state_exception); + } + + break; + + DEFAULT + ogs_error("[%s] Invalid resource name [%s]", + ogs_sbi_self()->nf_instance->id, + message->h.resource.component[0]); + END + break; + + DEFAULT + ogs_error("[%s] Invalid API name [%s]", + ogs_sbi_self()->nf_instance->id, message->h.service.name); + END + break; + + case SCP_EVT_SBI_TIMER: + switch(e->timer_id) { + case SCP_TIMER_NF_INSTANCE_HEARTBEAT_INTERVAL: + if (nf_instance->time.heartbeat_interval) + ogs_timer_start(nf_instance->t_heartbeat_interval, + ogs_time_from_sec(nf_instance->time.heartbeat_interval)); + + ogs_assert(true == ogs_nnrf_nfm_send_nf_update(nf_instance)); + break; + + case SCP_TIMER_NF_INSTANCE_NO_HEARTBEAT: + ogs_error("[%s] No heartbeat", ogs_sbi_self()->nf_instance->id); + OGS_FSM_TRAN(s, &scp_nf_state_will_register); + break; + + case SCP_TIMER_NF_INSTANCE_VALIDITY: + ogs_assert(!NF_INSTANCE_IS_NRF(nf_instance)); + ogs_assert(nf_instance->id); + + ogs_info("[%s] NF expired", nf_instance->id); + OGS_FSM_TRAN(s, &scp_nf_state_de_registered); + break; + + default: + ogs_error("[%s:%s] Unknown timer[%s:%d]", + OpenAPI_nf_type_ToString(nf_instance->nf_type), + nf_instance->id ? nf_instance->id : "Undefined", + scp_timer_get_name(e->timer_id), e->timer_id); + } + break; + + default: + ogs_error("[%s:%s] Unknown event %s", + OpenAPI_nf_type_ToString(nf_instance->nf_type), + nf_instance->id ? nf_instance->id : "Undefined", + scp_event_get_name(e)); + break; + } +} + +void scp_nf_state_de_registered(ogs_fsm_t *s, scp_event_t *e) +{ + ogs_sbi_nf_instance_t *nf_instance = NULL; + ogs_assert(s); + ogs_assert(e); + + scp_sm_debug(e); + + nf_instance = e->sbi.data; + ogs_assert(nf_instance); + ogs_assert(ogs_sbi_self()->nf_instance); + + switch (e->id) { + case OGS_FSM_ENTRY_SIG: + if (NF_INSTANCE_IS_NRF(nf_instance)) { + ogs_info("[%s] NF de-registered", ogs_sbi_self()->nf_instance->id); + } + break; + + case OGS_FSM_EXIT_SIG: + break; + + default: + ogs_error("[%s:%s] Unknown event %s", + OpenAPI_nf_type_ToString(nf_instance->nf_type), + nf_instance->id ? nf_instance->id : "Undefined", + scp_event_get_name(e)); + break; + } +} + +void scp_nf_state_exception(ogs_fsm_t *s, scp_event_t *e) +{ + ogs_sbi_nf_instance_t *nf_instance = NULL; + ogs_sbi_client_t *client = NULL; + ogs_sbi_message_t *message = NULL; + ogs_sockaddr_t *addr = NULL; + ogs_assert(s); + ogs_assert(e); + + scp_sm_debug(e); + + nf_instance = e->sbi.data; + ogs_assert(nf_instance); + ogs_assert(ogs_sbi_self()->nf_instance); + + switch (e->id) { + case OGS_FSM_ENTRY_SIG: + if (NF_INSTANCE_IS_NRF(nf_instance)) { + ogs_timer_start(nf_instance->t_registration_interval, + ogs_app()->time.message.sbi. + nf_register_interval_in_exception); + } + break; + + case OGS_FSM_EXIT_SIG: + if (NF_INSTANCE_IS_NRF(nf_instance)) { + ogs_timer_stop(nf_instance->t_registration_interval); + } + break; + + case SCP_EVT_SBI_TIMER: + switch(e->timer_id) { + case SCP_TIMER_NF_INSTANCE_REGISTRATION_INTERVAL: + client = nf_instance->client; + ogs_assert(client); + addr = client->node.addr; + ogs_assert(addr); + + ogs_warn("[%s] Retry to registration with NRF", + ogs_sbi_self()->nf_instance->id); + + OGS_FSM_TRAN(s, &scp_nf_state_will_register); + break; + + default: + ogs_error("[%s:%s] Unknown timer[%s:%d]", + OpenAPI_nf_type_ToString(nf_instance->nf_type), + nf_instance->id ? nf_instance->id : "Undefined", + scp_timer_get_name(e->timer_id), e->timer_id); + } + break; + + case SCP_EVT_SBI_CLIENT: + message = e->sbi.message; + ogs_assert(message); + + SWITCH(message->h.service.name) + CASE(OGS_SBI_SERVICE_NAME_NNRF_NFM) + + SWITCH(message->h.resource.component[0]) + CASE(OGS_SBI_RESOURCE_NAME_NF_INSTANCES) + break; + DEFAULT + ogs_error("Invalid resource name [%s]", + message->h.resource.component[0]); + END + break; + DEFAULT + ogs_error("Invalid API name [%s]", message->h.service.name); + END + break; + + default: + ogs_error("[%s:%s] Unknown event %s", + OpenAPI_nf_type_ToString(nf_instance->nf_type), + nf_instance->id ? nf_instance->id : "Undefined", + scp_event_get_name(e)); + break; + } +} diff --git a/src/scp/nnrf-build.c b/src/scp/nnrf-build.c new file mode 100644 index 000000000..7c7b42c13 --- /dev/null +++ b/src/scp/nnrf-build.c @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2019-2022 by Sukchan Lee + * + * This file is part of Open5GS. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "nnrf-build.h" + +ogs_sbi_request_t *scp_nnrf_nfm_build_register(void) +{ + ogs_sbi_nf_instance_t *nf_instance = NULL; + + ogs_sbi_message_t message; + ogs_sbi_request_t *request = NULL; + + OpenAPI_nf_profile_t *NFProfile = NULL; + + nf_instance = ogs_sbi_self()->nf_instance; + ogs_assert(nf_instance); + ogs_assert(nf_instance->id); + + memset(&message, 0, sizeof(message)); + message.h.method = (char *)OGS_SBI_HTTP_METHOD_PUT; + message.h.service.name = (char *)OGS_SBI_SERVICE_NAME_NNRF_NFM; + message.h.api.version = (char *)OGS_SBI_API_V1; + message.h.resource.component[0] = + (char *)OGS_SBI_RESOURCE_NAME_NF_INSTANCES; + message.h.resource.component[1] = nf_instance->id; + + message.http.content_encoding = (char*)ogs_sbi_self()->content_encoding; + + NFProfile = ogs_nnrf_nfm_build_nf_profile(); + ogs_expect_or_return_val(NFProfile, NULL); + + message.NFProfile = NFProfile; + + request = ogs_sbi_build_request(&message); + + ogs_sbi_nnrf_free_nf_profile(NFProfile); + + return request; +} diff --git a/src/scp/nnrf-build.h b/src/scp/nnrf-build.h new file mode 100644 index 000000000..9ae01aee2 --- /dev/null +++ b/src/scp/nnrf-build.h @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2019-2022 by Sukchan Lee + * + * This file is part of Open5GS. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef SCP_NNRF_BUILD_H +#define SCP_NNRF_BUILD_H + +#include "context.h" + +#ifdef __cplusplus +extern "C" { +#endif + +ogs_sbi_request_t *scp_nnrf_nfm_build_register(void); + +#ifdef __cplusplus +} +#endif + +#endif /* SCP_NNRF_BUILD_H */ diff --git a/src/scp/nnrf-handler.c b/src/scp/nnrf-handler.c new file mode 100644 index 000000000..c58781dd6 --- /dev/null +++ b/src/scp/nnrf-handler.c @@ -0,0 +1,348 @@ +/* + * Copyright (C) 2019-2022 by Sukchan Lee + * + * This file is part of Open5GS. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "sbi-path.h" +#include "nnrf-handler.h" + +void scp_nnrf_handle_nf_register( + ogs_sbi_nf_instance_t *nf_instance, ogs_sbi_message_t *recvmsg) +{ + OpenAPI_nf_profile_t *NFProfile = NULL; + ogs_sbi_client_t *client = NULL; + + ogs_assert(recvmsg); + ogs_assert(nf_instance); + client = nf_instance->client; + ogs_assert(client); + + NFProfile = recvmsg->NFProfile; + if (!NFProfile) { + ogs_error("No NFProfile"); + return; + } + + /* TIME : Update heartbeat from NRF */ + if (NFProfile->is_heart_beat_timer == true) + nf_instance->time.heartbeat_interval = NFProfile->heart_beat_timer; +} + +void scp_nnrf_handle_nf_status_subscribe( + ogs_sbi_subscription_t *subscription, ogs_sbi_message_t *recvmsg) +{ + OpenAPI_subscription_data_t *SubscriptionData = NULL; + ogs_sbi_client_t *client = NULL; + + ogs_assert(recvmsg); + ogs_assert(subscription); + client = subscription->client; + ogs_assert(client); + + SubscriptionData = recvmsg->SubscriptionData; + if (!SubscriptionData) { + ogs_error("No SubscriptionData"); + return; + } + + if (!SubscriptionData->subscription_id) { + ogs_error("No SubscriptionId"); + return; + } + ogs_sbi_subscription_set_id( + subscription, SubscriptionData->subscription_id); + + if (SubscriptionData->validity_time) { +#define VALIDITY_MINIMUM (10LL * OGS_USEC_PER_SEC) /* 10 seconds */ + ogs_time_t time, duration; + if (ogs_sbi_time_from_string( + &time, SubscriptionData->validity_time) == true) { + duration = time - ogs_time_now(); + if (duration < VALIDITY_MINIMUM) { + duration = VALIDITY_MINIMUM; + ogs_warn("[%s] Forced to %lld seconds", subscription->id, + (long long)ogs_time_sec(VALIDITY_MINIMUM)); + } + subscription->t_validity = ogs_timer_add(ogs_app()->timer_mgr, + scp_timer_subscription_validity, subscription); + ogs_assert(subscription->t_validity); + ogs_timer_start(subscription->t_validity, duration); + } else { + ogs_error("Cannot parse validitiyTime [%s]", + SubscriptionData->validity_time); + } + } +} + +bool scp_nnrf_handle_nf_status_notify( + ogs_sbi_stream_t *stream, ogs_sbi_message_t *recvmsg) +{ + int rv; + bool handled; + + ogs_sbi_response_t *response = NULL; + OpenAPI_notification_data_t *NotificationData = NULL; + ogs_sbi_nf_instance_t *nf_instance = NULL; + + ogs_sbi_message_t message; + ogs_sbi_header_t header; + + ogs_assert(stream); + ogs_assert(recvmsg); + + NotificationData = recvmsg->NotificationData; + if (!NotificationData) { + ogs_error("No NotificationData"); + ogs_assert(true == + ogs_sbi_server_send_error(stream, OGS_SBI_HTTP_STATUS_BAD_REQUEST, + recvmsg, "No NotificationData", NULL)); + return false; + } + + if (!NotificationData->nf_instance_uri) { + ogs_error("No nfInstanceUri"); + ogs_assert(true == + ogs_sbi_server_send_error(stream, OGS_SBI_HTTP_STATUS_BAD_REQUEST, + recvmsg, "No nfInstanceUri", NULL)); + return false; + } + + memset(&header, 0, sizeof(header)); + header.uri = NotificationData->nf_instance_uri; + + rv = ogs_sbi_parse_header(&message, &header); + if (rv != OGS_OK) { + ogs_error("Cannot parse nfInstanceUri [%s]", header.uri); + ogs_assert(true == + ogs_sbi_server_send_error(stream, OGS_SBI_HTTP_STATUS_BAD_REQUEST, + recvmsg, "Cannot parse nfInstanceUri", header.uri)); + return false; + } + + if (!message.h.resource.component[1]) { + ogs_error("No nfInstanceId [%s]", header.uri); + ogs_assert(true == + ogs_sbi_server_send_error(stream, OGS_SBI_HTTP_STATUS_BAD_REQUEST, + recvmsg, "Cannot parse nfInstanceUri", header.uri)); + ogs_sbi_header_free(&header); + return false; + } + + if (NF_INSTANCE_IS_SELF(message.h.resource.component[1])) { + ogs_warn("[%s] The notification is not allowed", + message.h.resource.component[1]); + ogs_assert(true == + ogs_sbi_server_send_error(stream, OGS_SBI_HTTP_STATUS_FORBIDDEN, + recvmsg, "The notification is not allowed", + message.h.resource.component[1])); + ogs_sbi_header_free(&header); + return false; + } + + if (NotificationData->event == + OpenAPI_notification_event_type_NF_REGISTERED) { + + OpenAPI_nf_profile_t *NFProfile = NULL; + + NFProfile = NotificationData->nf_profile; + if (!NFProfile) { + ogs_error("No NFProfile"); + ogs_assert(true == + ogs_sbi_server_send_error( + stream, OGS_SBI_HTTP_STATUS_BAD_REQUEST, + recvmsg, "No NFProfile", NULL)); + ogs_sbi_header_free(&header); + return false; + } + + nf_instance = ogs_sbi_nf_instance_find(message.h.resource.component[1]); + if (!nf_instance) { + nf_instance = ogs_sbi_nf_instance_add(); + ogs_assert(nf_instance); + ogs_sbi_nf_instance_set_id(nf_instance, + message.h.resource.component[1]); + + scp_nf_fsm_init(nf_instance); + + ogs_info("[%s] (NRF-notify) NF registered", nf_instance->id); + + } else { + nf_instance->reference_count++; + + OGS_FSM_TRAN(&nf_instance->sm, scp_nf_state_registered); + ogs_fsm_dispatch(&nf_instance->sm, NULL); + + ogs_warn("[%s] (NRF-notify) NF has already been added", + message.h.resource.component[1]); + + } + + handled = ogs_sbi_nnrf_handle_nf_profile( + nf_instance, NFProfile, stream, recvmsg); + if (!handled) { + SCP_NF_INSTANCE_CLEAR("NRF-notify", nf_instance); + ogs_sbi_header_free(&header); + return false; + } + + ogs_info("[%s] (NRF-notify) NF Profile updated", nf_instance->id); + + handled = ogs_sbi_client_associate(nf_instance); + if (!handled) { + ogs_error("[%s] Cannot associate NF EndPoint", nf_instance->id); + ogs_assert(true == + ogs_sbi_server_send_error(stream, + OGS_SBI_HTTP_STATUS_BAD_REQUEST, + recvmsg, "Cannot find NF EndPoint", nf_instance->id)); + SCP_NF_INSTANCE_CLEAR("NRF-notify", nf_instance); + ogs_sbi_header_free(&header); + return false; + } + + } else if (NotificationData->event == + OpenAPI_notification_event_type_NF_DEREGISTERED) { + nf_instance = ogs_sbi_nf_instance_find(message.h.resource.component[1]); + if (nf_instance) { + SCP_NF_INSTANCE_CLEAR("NRF-notify", nf_instance); + } else { + ogs_warn("[%s] (NRF-notify) Not found", + message.h.resource.component[1]); + ogs_assert(true == + ogs_sbi_server_send_error(stream, + OGS_SBI_HTTP_STATUS_NOT_FOUND, + recvmsg, "Not found", message.h.resource.component[1])); + ogs_sbi_header_free(&header); + return false; + } + } else { + char *eventstr = OpenAPI_notification_event_type_ToString( + NotificationData->event); + ogs_error("Not supported event [%d:%s]", + NotificationData->event, eventstr ? eventstr : "Unknown"); + ogs_assert(true == + ogs_sbi_server_send_error(stream, OGS_SBI_HTTP_STATUS_BAD_REQUEST, + recvmsg, "Not supported event", + eventstr ? eventstr : "Unknown")); + ogs_sbi_header_free(&header); + return false; + } + + response = ogs_sbi_build_response(recvmsg, OGS_SBI_HTTP_STATUS_NO_CONTENT); + ogs_assert(response); + ogs_assert(true == ogs_sbi_server_send_response(stream, response)); + + ogs_sbi_header_free(&header); + return true; +} + +void scp_nnrf_handle_nf_discover( + 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_search_result_t *SearchResult = NULL; + OpenAPI_lnode_t *node = NULL; + bool handled; + + ogs_assert(xact); + sbi_object = xact->sbi_object; + ogs_assert(sbi_object); + ogs_assert(recvmsg); + + SearchResult = recvmsg->SearchResult; + if (!SearchResult) { + ogs_error("No SearchResult"); + return; + } + + OpenAPI_list_for_each(SearchResult->nf_instances, node) { + OpenAPI_nf_profile_t *NFProfile = NULL; + + if (!node->data) continue; + + NFProfile = node->data; + + 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); + + scp_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, scp_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)) { + scp_conn_t *conn = 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); + SCP_NF_INSTANCE_CLEAR("NRF-discover", nf_instance); + continue; + } + + handled = ogs_sbi_client_associate(nf_instance); + if (!handled) { + ogs_error("[%s] Cannot assciate NF EndPoint", nf_instance->id); + SCP_NF_INSTANCE_CLEAR("NRF-discover", nf_instance); + continue; + } + + conn = (scp_conn_t *)sbi_object; + ogs_assert(conn); + scp_conn_select_nf(conn, nf_instance->nf_type); + + /* TIME : Update validity from NRF */ + if (SearchResult->is_validity_period && + SearchResult->validity_period) { + nf_instance->time.validity_duration = + SearchResult->validity_period; + + ogs_assert(nf_instance->t_validity); + ogs_timer_start(nf_instance->t_validity, + ogs_time_from_sec(nf_instance->time.validity_duration)); + + } else + ogs_warn("[%s] NF Instance validity-time should not 0", + nf_instance->id); + + ogs_info("[%s] (NF-discover) NF Profile updated", nf_instance->id); + } + } + + ogs_assert(xact->target_nf_type); + nf_instance = OGS_SBI_NF_INSTANCE(sbi_object, xact->target_nf_type); + if (!nf_instance) { + ogs_error("(NF discover) No [%s]", + OpenAPI_nf_type_ToString(xact->target_nf_type)); + } else { + scp_sbi_send(nf_instance, xact); + } +} diff --git a/src/scp/nnrf-handler.h b/src/scp/nnrf-handler.h new file mode 100644 index 000000000..736851433 --- /dev/null +++ b/src/scp/nnrf-handler.h @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2019-2022 by Sukchan Lee + * + * This file is part of Open5GS. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef SCP_NNRF_HANDLER_H +#define SCP_NNRF_HANDLER_H + +#include "context.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void scp_nnrf_handle_nf_register( + ogs_sbi_nf_instance_t *nf_instance, ogs_sbi_message_t *recvmsg); +void scp_nnrf_handle_nf_status_subscribe( + ogs_sbi_subscription_t *subscription, ogs_sbi_message_t *recvmsg); + +bool scp_nnrf_handle_nf_status_notify( + ogs_sbi_stream_t *stream, ogs_sbi_message_t *recvmsg); + +void scp_nnrf_handle_nf_discover( + ogs_sbi_xact_t *xact, ogs_sbi_message_t *recvmsg); + +#ifdef __cplusplus +} +#endif + +#endif /* SCP_NNRF_HANDLER_H */ diff --git a/src/scp/nscp-handler.c b/src/scp/nscp-handler.c new file mode 100644 index 000000000..091ba8206 --- /dev/null +++ b/src/scp/nscp-handler.c @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2019-2022 by Sukchan Lee + * + * This file is part of Open5GS. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "sbi-path.h" +#include "nscp-handler.h" + +bool scp_nscp_management_handle_pcf_binding( + scp_conn_t *conn, ogs_sbi_stream_t *stream, ogs_sbi_message_t *recvmsg) +{ + return true; +} diff --git a/src/scp/nscp-handler.h b/src/scp/nscp-handler.h new file mode 100644 index 000000000..01f7dadc8 --- /dev/null +++ b/src/scp/nscp-handler.h @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2019-2022 by Sukchan Lee + * + * This file is part of Open5GS. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef SCP_NSCP_HANDLER_H +#define SCP_NSCP_HANDLER_H + +#include "context.h" + +#ifdef __cplusplus +extern "C" { +#endif + +bool scp_nscp_management_handle_pcf_binding( + scp_conn_t *conn, ogs_sbi_stream_t *stream, ogs_sbi_message_t *recvmsg); + +#ifdef __cplusplus +} +#endif + +#endif /* SCP_NSCP_HANDLER_H */ diff --git a/src/scp/sbi-path.c b/src/scp/sbi-path.c new file mode 100644 index 000000000..3c101c761 --- /dev/null +++ b/src/scp/sbi-path.c @@ -0,0 +1,410 @@ +/* + * Copyright (C) 2019-2022 by Sukchan Lee + * + * This file is part of Open5GS. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "sbi-path.h" + +static int request_handler(ogs_sbi_request_t *request, void *data); +static int response_handler( + int status, ogs_sbi_response_t *response, void *data); + +static int client_cb(int status, ogs_sbi_response_t *response, void *data); + +int scp_sbi_open(void) +{ + ogs_sbi_nf_instance_t *nf_instance = NULL; + + if (ogs_sbi_server_start_all(request_handler) != OGS_OK) + return OGS_ERROR; + + /* Add SELF NF instance */ + nf_instance = ogs_sbi_self()->nf_instance; + ogs_assert(nf_instance); + + /* Build NF instance information. It will be transmitted to NRF. */ + ogs_sbi_nf_instance_build_default(nf_instance, OpenAPI_nf_type_SCP); + + /* Initialize SCP NF Instance */ + nf_instance = ogs_sbi_self()->scp_instance; + if (nf_instance) { + ogs_sbi_client_t *client = NULL; + + /* Client callback is only used when NF sends to SCP */ + client = nf_instance->client; + ogs_assert(client); + client->cb = client_cb; + } + + /* Initialize NRF NF Instance */ + nf_instance = ogs_sbi_self()->nrf_instance; + if (nf_instance) { + ogs_sbi_client_t *client = NULL; + + /* Client callback is only used when NF sends to NRF */ + client = nf_instance->client; + ogs_assert(client); + client->cb = client_cb; + + /* NFRegister is sent and the response is received + * by the above client callback. */ + scp_nf_fsm_init(nf_instance); + } + + return OGS_OK; +} + +void scp_sbi_close(void) +{ + ogs_sbi_client_stop_all(); + ogs_sbi_server_stop_all(); +} + +static int request_handler(ogs_sbi_request_t *source, void *data) +{ + int rv; + ogs_hash_index_t *hi; + ogs_sbi_stream_t *stream = data; + + struct { + char *target_apiroot; + char *discovery; + char *accept; + char *content_type; + char *content_encoding; + } headers; + + ogs_assert(source); + ogs_assert(source->h.uri); + ogs_assert(stream); + + memset(&headers, 0, sizeof(headers)); + + /* Extract HTTP Header */ + for (hi = ogs_hash_first(source->http.headers); + hi; hi = ogs_hash_next(hi)) { + char *key = (char *)ogs_hash_this_key(hi); + char *val = ogs_hash_this_val(hi); + + if (!key || !val) { + ogs_error("No Key[%s] Value[%s]", key, val); + continue; + } + + /* + * + * Each header field consists of a name followed by a colon (":") + * and the field value. Field names are case-insensitive. + */ + if (!strcasecmp(key, OGS_SBI_CUSTOM_TARGET_APIROOT)) { + headers.target_apiroot = val; + } else if (!strncasecmp(key, + OGS_SBI_CUSTOM_DISCOVERY_COMMON, + strlen(OGS_SBI_CUSTOM_DISCOVERY_COMMON))) { + headers.discovery = val; + } else if (!strcasecmp(key, OGS_SBI_ACCEPT)) { + headers.accept = val; + } else if (!strcasecmp(key, OGS_SBI_CONTENT_TYPE)) { + headers.content_type = val; + } else if (!strcasecmp(key, OGS_SBI_ACCEPT_ENCODING)) { + headers.content_encoding = val; + } + } + + if (headers.target_apiroot) { + ogs_sbi_nf_instance_t *scp_instance = NULL; + ogs_sbi_client_t *client = NULL; + ogs_sbi_request_t target; + + scp_conn_t *conn = NULL; + + memset(&target, 0, sizeof(target)); + + conn = scp_conn_add(stream); + if (!conn) { + ogs_error("scp_conn_add() failed"); + ogs_sbi_request_free(source); + return OGS_ERROR; + } + + if (ogs_sbi_self()->discovery_config.delegated == + OGS_SBI_DISCOVERY_DELEGATED_AUTO) { + scp_instance = ogs_sbi_self()->scp_instance; + } else if (ogs_sbi_self()->discovery_config.delegated == + OGS_SBI_DISCOVERY_DELEGATED_YES) { + scp_instance = ogs_sbi_self()->scp_instance; + ogs_assert(scp_instance); + } + + /* HTTP Method */ + target.h.method = source->h.method; + + /* HTTP Headers + * + * To remove the followings, + * Scheme - https + * Authority - scp.open5gs.org + * + * We regenerate the HTTP Headers. + */ + target.http.headers = ogs_hash_make(); + ogs_assert(target.http.headers); + + if (headers.content_type) + ogs_sbi_header_set(target.http.headers, + OGS_SBI_CONTENT_TYPE, headers.content_type); + if (headers.accept) + ogs_sbi_header_set(target.http.headers, + OGS_SBI_ACCEPT, headers.accept); + if (headers.content_encoding) + ogs_sbi_header_set(target.http.headers, + OGS_SBI_ACCEPT_ENCODING, headers.content_encoding); + + /* HTTP Params */ + target.http.params = source->http.params; + + /* HTTP Content */ + target.http.content = source->http.content; + target.http.content_length = source->http.content_length; + + if (scp_instance) { + char *apiroot = NULL; + + if (headers.target_apiroot) + ogs_sbi_header_set(target.http.headers, + OGS_SBI_CUSTOM_TARGET_APIROOT, headers.target_apiroot); + + /* Client Instance */ + client = scp_instance->client; + ogs_assert(client); + + /* Client ApiRoot */ + apiroot = ogs_sbi_client_apiroot(client); + ogs_assert(apiroot); + + /* Setup New URI */ + target.h.uri = ogs_msprintf("%s%s", apiroot, source->h.uri); + ogs_assert(target.h.uri); + + ogs_free(apiroot); + + } else { + ogs_sockaddr_t *addr = NULL; + + /* Find or Add Client Instance */ + addr = ogs_sbi_getaddr_from_uri(headers.target_apiroot); + if (!addr) { + ogs_error("Invalid Target-apiRoot [%s]", + headers.target_apiroot); + ogs_sbi_http_hash_free(target.http.headers); + ogs_free(target.h.uri); + + ogs_sbi_request_free(source); + scp_conn_remove(conn); + return OGS_ERROR; + } + + client = ogs_sbi_client_find(addr); + if (!client) { + client = ogs_sbi_client_add(addr); + ogs_assert(client); + client->cb = client_cb; + } + OGS_SBI_SETUP_CLIENT(conn, client); + + ogs_freeaddrinfo(addr); + + /* Setup New URI */ + target.h.uri = ogs_msprintf("%s%s", + headers.target_apiroot, source->h.uri); + ogs_assert(target.h.uri); + } + + /* Send the HTTP Request with New URI and HTTP Headers */ + if (ogs_sbi_client_send_reqmem_persistent( + client, response_handler, &target, conn) != true) { + ogs_error("ogs_sbi_client_send_request() failed"); + ogs_sbi_http_hash_free(target.http.headers); + ogs_free(target.h.uri); + + ogs_sbi_request_free(source); + scp_conn_remove(conn); + return OGS_ERROR; + } + + ogs_sbi_http_hash_free(target.http.headers); + ogs_free(target.h.uri); + + } else if (headers.discovery) { + scp_event_t *e = NULL; + + e = scp_event_new(SCP_EVT_SBI_SERVER); + ogs_assert(e); + + e->sbi.request = source; + e->sbi.data = stream; + + rv = ogs_queue_push(ogs_app()->queue, e); + if (rv != OGS_OK) { + ogs_error("ogs_queue_push() failed:%d", (int)rv); + ogs_sbi_request_free(source); + scp_event_free(e); + return OGS_ERROR; + } + } else { + ogs_sbi_message_t message; + + ogs_error("Unknown HTTP Headers"); + ogs_error(" [%s:%s]", source->h.method, source->h.uri); + for (hi = ogs_hash_first(source->http.headers); + hi; hi = ogs_hash_next(hi)) { + char *key = (char *)ogs_hash_this_key(hi); + char *val = ogs_hash_this_val(hi); + ogs_error(" [%s:%s]", key, val); + } + + rv = ogs_sbi_parse_request(&message, source); + if (rv != OGS_OK) { + ogs_error("cannot parse HTTP sbi_message"); + ogs_assert(true == + ogs_sbi_server_send_error( + stream, OGS_SBI_HTTP_STATUS_BAD_REQUEST, + NULL, "cannot parse HTTP sbi_message", NULL)); + return OGS_ERROR; + } + + ogs_assert(true == + ogs_sbi_server_send_error( + stream, OGS_SBI_HTTP_STATUS_BAD_REQUEST, + &message, "SCP - HTTP Client", NULL)); + + ogs_sbi_message_free(&message); + + return OGS_OK; + } + + return OGS_OK; +} + +static int response_handler( + int status, ogs_sbi_response_t *response, void *data) +{ + scp_conn_t *conn = data; + ogs_sbi_stream_t *stream = NULL; + + ogs_assert(conn); + stream = conn->stream; + ogs_assert(stream); + + if (status != OGS_OK) { + + ogs_log_message( + status == OGS_DONE ? OGS_LOG_DEBUG : OGS_LOG_WARN, 0, + "response_handler() failed [%d]", status); + + ogs_assert(true == + ogs_sbi_server_send_error(stream, + OGS_SBI_HTTP_STATUS_INTERNAL_SERVER_ERROR, NULL, + "response_handler() failed", NULL)); + + scp_conn_remove(conn); + + return OGS_ERROR; + } + + ogs_assert(response); + ogs_assert(true == ogs_sbi_server_send_response(stream, response)); + scp_conn_remove(conn); + + return OGS_OK; +} + +static int client_cb(int status, ogs_sbi_response_t *response, void *data) +{ + scp_event_t *e = NULL; + int rv; + + if (status != OGS_OK) { + ogs_log_message( + status == OGS_DONE ? OGS_LOG_DEBUG : OGS_LOG_WARN, 0, + "client_cb() failed [%d]", status); + return OGS_ERROR; + } + + ogs_assert(response); + + e = scp_event_new(SCP_EVT_SBI_CLIENT); + ogs_assert(e); + e->sbi.response = response; + e->sbi.data = data; + + rv = ogs_queue_push(ogs_app()->queue, e); + if (rv != OGS_OK) { + ogs_error("ogs_queue_push() failed:%d", (int)rv); + ogs_sbi_response_free(response); + scp_event_free(e); + return OGS_ERROR; + } + + return OGS_OK; +} + + +bool scp_sbi_send(ogs_sbi_nf_instance_t *nf_instance, ogs_sbi_xact_t *xact) +{ + return ogs_sbi_send(nf_instance, client_cb, xact); +} + +bool scp_sbi_discover_and_send(OpenAPI_nf_type_e target_nf_type, + scp_conn_t *conn, ogs_sbi_stream_t *stream, void *data, + ogs_sbi_request_t *(*build)(scp_conn_t *conn, void *data)) +{ + ogs_sbi_xact_t *xact = NULL; + + ogs_assert(target_nf_type); + + ogs_assert(conn); + ogs_assert(stream); + ogs_assert(build); + + xact = ogs_sbi_xact_add(target_nf_type, &conn->sbi, + (ogs_sbi_build_f)build, conn, data, + scp_timer_sbi_client_wait_expire); + if (!xact) { + ogs_error("scp_sbi_discover_and_send() failed"); + ogs_assert(true == + ogs_sbi_server_send_error(stream, + OGS_SBI_HTTP_STATUS_GATEWAY_TIMEOUT, NULL, + "Cannot discover", NULL)); + return false; + } + + xact->assoc_stream = stream; + + if (ogs_sbi_discover_and_send(xact, + (ogs_fsm_handler_t)scp_nf_state_registered, client_cb) != true) { + ogs_error("scp_sbi_discover_and_send() failed"); + ogs_sbi_xact_remove(xact); + ogs_assert(true == + ogs_sbi_server_send_error(stream, + OGS_SBI_HTTP_STATUS_GATEWAY_TIMEOUT, NULL, + "Cannot discover", NULL)); + return false; + } + + return true; +} diff --git a/src/scp/sbi-path.h b/src/scp/sbi-path.h new file mode 100644 index 000000000..04a2aeda7 --- /dev/null +++ b/src/scp/sbi-path.h @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2019-2022 by Sukchan Lee + * + * This file is part of Open5GS. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef SCP_SBI_PATH_H +#define SCP_SBI_PATH_H + +#include "nnrf-build.h" + +#ifdef __cplusplus +extern "C" { +#endif + +int scp_sbi_open(void); +void scp_sbi_close(void); + +bool scp_sbi_send(ogs_sbi_nf_instance_t *nf_instance, ogs_sbi_xact_t *xact); + +bool scp_sbi_discover_and_send(OpenAPI_nf_type_e target_nf_type, + scp_conn_t *conn, ogs_sbi_stream_t *stream, void *data, + ogs_sbi_request_t *(*build)(scp_conn_t *conn, void *data)); + +#ifdef __cplusplus +} +#endif + +#endif /* SCP_SBI_PATH_H */ diff --git a/src/scp/scp-sm.c b/src/scp/scp-sm.c new file mode 100644 index 000000000..c5580ece3 --- /dev/null +++ b/src/scp/scp-sm.c @@ -0,0 +1,369 @@ +/* + * Copyright (C) 2019-2022 by Sukchan Lee + * + * This file is part of Open5GS. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "sbi-path.h" +#include "nnrf-handler.h" +#include "nscp-handler.h" + +void scp_state_initial(ogs_fsm_t *s, scp_event_t *e) +{ + scp_sm_debug(e); + + ogs_assert(s); + + OGS_FSM_TRAN(s, &scp_state_operational); +} + +void scp_state_final(ogs_fsm_t *s, scp_event_t *e) +{ + scp_sm_debug(e); + + ogs_assert(s); +} + +void scp_state_operational(ogs_fsm_t *s, scp_event_t *e) +{ + int rv; + + ogs_sbi_stream_t *stream = NULL; + ogs_sbi_request_t *request = NULL; + + ogs_sbi_nf_instance_t *nf_instance = NULL; + ogs_sbi_subscription_t *subscription = NULL; + ogs_sbi_response_t *response = NULL; + ogs_sbi_message_t message; + ogs_sbi_xact_t *sbi_xact = NULL; + + scp_sm_debug(e); + + ogs_assert(s); + + switch (e->id) { + case OGS_FSM_ENTRY_SIG: + break; + + case OGS_FSM_EXIT_SIG: + break; + + case SCP_EVT_SBI_SERVER: + request = e->sbi.request; + ogs_assert(request); + stream = e->sbi.data; + ogs_assert(stream); + + rv = ogs_sbi_parse_request(&message, request); + if (rv != OGS_OK) { + /* 'sbi_message' buffer is released in ogs_sbi_parse_request() */ + ogs_error("cannot parse HTTP sbi_message"); + ogs_assert(true == + ogs_sbi_server_send_error( + stream, OGS_SBI_HTTP_STATUS_BAD_REQUEST, + NULL, "cannot parse HTTP sbi_message", NULL)); + break; + } + + if (strcmp(message.h.api.version, OGS_SBI_API_V1) != 0) { + ogs_error("Not supported version [%s]", message.h.api.version); + ogs_assert(true == + ogs_sbi_server_send_error( + stream, OGS_SBI_HTTP_STATUS_BAD_REQUEST, + &message, "Not supported version", NULL)); + ogs_sbi_message_free(&message); + break; + } + + SWITCH(message.h.service.name) + CASE(OGS_SBI_SERVICE_NAME_NNRF_NFM) + + SWITCH(message.h.resource.component[0]) + CASE(OGS_SBI_RESOURCE_NAME_NF_STATUS_NOTIFY) + SWITCH(message.h.method) + CASE(OGS_SBI_HTTP_METHOD_POST) + scp_nnrf_handle_nf_status_notify(stream, &message); + break; + + DEFAULT + ogs_error("Invalid HTTP method [%s]", message.h.method); + ogs_assert(true == + ogs_sbi_server_send_error(stream, + OGS_SBI_HTTP_STATUS_FORBIDDEN, &message, + "Invalid HTTP method", message.h.method)); + END + break; + + DEFAULT + ogs_error("Invalid resource name [%s]", + message.h.resource.component[0]); + ogs_assert(true == + ogs_sbi_server_send_error(stream, + OGS_SBI_HTTP_STATUS_BAD_REQUEST, &message, + "Invalid resource name", + message.h.resource.component[0])); + END + break; + +#if 0 + CASE(OGS_SBI_SERVICE_NAME_NBSF_MANAGEMENT) + SWITCH(message.h.resource.component[0]) + CASE(OGS_SBI_RESOURCE_NAME_PCF_BINDINGS) + if (message.h.resource.component[1]) { + sess = scp_sess_find_by_binding_id( + message.h.resource.component[1]); + } else { + SWITCH(message.h.method) + CASE(OGS_SBI_HTTP_METHOD_POST) + if (message.PcfBinding && + message.PcfBinding->snssai && + message.PcfBinding->dnn) { + ogs_s_nssai_t s_nssai; + + s_nssai.sst = message.PcfBinding->snssai->sst; + s_nssai.sd = ogs_s_nssai_sd_from_string( + message.PcfBinding->snssai->sd); + + sess = scp_sess_find_by_snssai_and_dnn( + &s_nssai, message.PcfBinding->dnn); + if (!sess) { + sess = scp_sess_add_by_snssai_and_dnn( + &s_nssai, message.PcfBinding->dnn); + ogs_assert(sess); + } + } + break; + CASE(OGS_SBI_HTTP_METHOD_GET) + if (!sess && message.param.ipv4addr) + sess = scp_sess_find_by_ipv4addr( + message.param.ipv4addr); + if (!sess && message.param.ipv6prefix) + sess = scp_sess_find_by_ipv6prefix( + message.param.ipv6prefix); + break; + DEFAULT + ogs_error("Invalid HTTP method [%s]", message.h.method); + END + } + + if (!sess) { + ogs_error("Not found [%s]", message.h.uri); + ogs_assert(true == + ogs_sbi_server_send_error(stream, + OGS_SBI_HTTP_STATUS_NOT_FOUND, + &message, "Not found", message.h.uri)); + break; + } + + scp_nscp_management_handle_pcf_binding(sess, stream, &message); + break; + + DEFAULT + ogs_error("Invalid resource name [%s]", + message.h.resource.component[0]); + ogs_assert(true == + ogs_sbi_server_send_error(stream, + OGS_SBI_HTTP_STATUS_BAD_REQUEST, &message, + "Invalid resource name", + message.h.resource.component[0])); + END + break; +#endif + + DEFAULT + ogs_error("Invalid API name [%s]", message.h.service.name); + ogs_assert(true == + ogs_sbi_server_send_error(stream, + OGS_SBI_HTTP_STATUS_BAD_REQUEST, &message, + "Invalid API name", message.h.service.name)); + END + + /* In lib/sbi/server.c, notify_completed() releases 'request' buffer. */ + ogs_sbi_message_free(&message); + break; + + case SCP_EVT_SBI_CLIENT: + ogs_assert(e); + + response = e->sbi.response; + ogs_assert(response); + rv = ogs_sbi_parse_response(&message, response); + if (rv != OGS_OK) { + ogs_error("cannot parse HTTP response"); + ogs_sbi_message_free(&message); + ogs_sbi_response_free(response); + break; + } + + if (strcmp(message.h.api.version, OGS_SBI_API_V1) != 0) { + ogs_error("Not supported version [%s]", message.h.api.version); + ogs_sbi_message_free(&message); + ogs_sbi_response_free(response); + break; + } + + SWITCH(message.h.service.name) + CASE(OGS_SBI_SERVICE_NAME_NNRF_NFM) + + SWITCH(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 = &message; + ogs_fsm_dispatch(&nf_instance->sm, e); + break; + + CASE(OGS_SBI_RESOURCE_NAME_SUBSCRIPTIONS) + subscription = e->sbi.data; + ogs_assert(subscription); + + SWITCH(message.h.method) + CASE(OGS_SBI_HTTP_METHOD_POST) + if (message.res_status == OGS_SBI_HTTP_STATUS_CREATED || + message.res_status == OGS_SBI_HTTP_STATUS_OK) { + scp_nnrf_handle_nf_status_subscribe( + subscription, &message); + } else { + ogs_error("HTTP response error : %d", + message.res_status); + } + break; + + CASE(OGS_SBI_HTTP_METHOD_DELETE) + if (message.res_status == OGS_SBI_HTTP_STATUS_NO_CONTENT) { + ogs_sbi_subscription_remove(subscription); + } else { + ogs_error("HTTP response error : %d", + message.res_status); + } + break; + + DEFAULT + ogs_error("Invalid HTTP method [%s]", message.h.method); + ogs_assert_if_reached(); + END + break; + + DEFAULT + ogs_error("Invalid resource name [%s]", + message.h.resource.component[0]); + ogs_assert_if_reached(); + END + break; + + CASE(OGS_SBI_SERVICE_NAME_NNRF_DISC) + SWITCH(message.h.resource.component[0]) + CASE(OGS_SBI_RESOURCE_NAME_NF_INSTANCES) + sbi_xact = e->sbi.data; + ogs_assert(sbi_xact); + + SWITCH(message.h.method) + CASE(OGS_SBI_HTTP_METHOD_GET) + if (message.res_status == OGS_SBI_HTTP_STATUS_OK) + scp_nnrf_handle_nf_discover(sbi_xact, &message); + else + ogs_error("HTTP response error [%d]", + message.res_status); + break; + + DEFAULT + ogs_error("Invalid HTTP method [%s]", message.h.method); + ogs_assert_if_reached(); + END + break; + + DEFAULT + ogs_error("Invalid resource name [%s]", + message.h.resource.component[0]); + ogs_assert_if_reached(); + END + break; + + DEFAULT + ogs_error("Invalid service name [%s]", message.h.service.name); + ogs_assert_if_reached(); + END + + ogs_sbi_message_free(&message); + ogs_sbi_response_free(response); + break; + + case SCP_EVT_SBI_TIMER: + ogs_assert(e); + + switch(e->timer_id) { + case SCP_TIMER_NF_INSTANCE_REGISTRATION_INTERVAL: + case SCP_TIMER_NF_INSTANCE_HEARTBEAT_INTERVAL: + case SCP_TIMER_NF_INSTANCE_NO_HEARTBEAT: + case SCP_TIMER_NF_INSTANCE_VALIDITY: + nf_instance = e->sbi.data; + ogs_assert(nf_instance); + ogs_assert(OGS_FSM_STATE(&nf_instance->sm)); + + ogs_fsm_dispatch(&nf_instance->sm, e); + if (OGS_FSM_CHECK(&nf_instance->sm, scp_nf_state_exception)) + ogs_error("[%s:%s] State machine exception [%d]", + OpenAPI_nf_type_ToString(nf_instance->nf_type), + nf_instance->id, e->timer_id); + break; + + case SCP_TIMER_SUBSCRIPTION_VALIDITY: + subscription = e->sbi.data; + ogs_assert(subscription); + + ogs_assert(ogs_sbi_self()->nf_instance); + ogs_assert(true == + ogs_nnrf_nfm_send_nf_status_subscribe(subscription->client, + ogs_sbi_self()->nf_instance->nf_type, + subscription->req_nf_instance_id, + subscription->subscr_cond.nf_type)); + + ogs_info("Subscription validity expired [%s]", subscription->id); + ogs_sbi_subscription_remove(subscription); + break; + + case SCP_TIMER_SBI_CLIENT_WAIT: + sbi_xact = e->sbi.data; + ogs_assert(sbi_xact); + + stream = sbi_xact->assoc_stream; + /* Here, we should not use ogs_assert(stream) + * since 'namf-comm' service has no an associated stream. */ + + ogs_sbi_xact_remove(sbi_xact); + + ogs_error("Cannot receive SBI message"); + if (stream) { + ogs_assert(true == + ogs_sbi_server_send_error(stream, + OGS_SBI_HTTP_STATUS_GATEWAY_TIMEOUT, NULL, + "Cannot receive SBI message", NULL)); + } + break; + + default: + ogs_error("Unknown timer[%s:%d]", + scp_timer_get_name(e->timer_id), e->timer_id); + } + break; + + default: + ogs_error("No handler for event %s", scp_event_get_name(e)); + break; + } +} diff --git a/src/scp/scp-sm.h b/src/scp/scp-sm.h new file mode 100644 index 000000000..41b84a49d --- /dev/null +++ b/src/scp/scp-sm.h @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2019-2022 by Sukchan Lee + * + * This file is part of Open5GS. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef SCP_SM_H +#define SCP_SM_H + +#include "event.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void scp_state_initial(ogs_fsm_t *s, scp_event_t *e); +void scp_state_final(ogs_fsm_t *s, scp_event_t *e); +void scp_state_operational(ogs_fsm_t *s, scp_event_t *e); +void scp_state_exception(ogs_fsm_t *s, scp_event_t *e); + +void scp_nf_fsm_init(ogs_sbi_nf_instance_t *nf_instance); +void scp_nf_fsm_fini(ogs_sbi_nf_instance_t *nf_instance); + +void scp_nf_state_initial(ogs_fsm_t *s, scp_event_t *e); +void scp_nf_state_final(ogs_fsm_t *s, scp_event_t *e); +void scp_nf_state_will_register(ogs_fsm_t *s, scp_event_t *e); +void scp_nf_state_registered(ogs_fsm_t *s, scp_event_t *e); +void scp_nf_state_de_registered(ogs_fsm_t *s, scp_event_t *e); +void scp_nf_state_exception(ogs_fsm_t *s, scp_event_t *e); + +#define scp_sm_debug(__pe) \ + ogs_debug("%s(): %s", __func__, scp_event_get_name(__pe)) + +#ifdef __cplusplus +} +#endif + +#endif /* SCP_SM_H */ diff --git a/src/scp/timer.c b/src/scp/timer.c new file mode 100644 index 000000000..86d0fd0c6 --- /dev/null +++ b/src/scp/timer.c @@ -0,0 +1,118 @@ +/* + * Copyright (C) 2019-2022 by Sukchan Lee + * + * This file is part of Open5GS. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "timer.h" +#include "event.h" +#include "context.h" + +const char *scp_timer_get_name(scp_timer_e id) +{ + switch (id) { + case SCP_TIMER_NF_INSTANCE_REGISTRATION_INTERVAL: + return "SCP_TIMER_NF_INSTANCE_REGISTRATION_INTERVAL"; + case SCP_TIMER_NF_INSTANCE_HEARTBEAT_INTERVAL: + return "SCP_TIMER_NF_INSTANCE_HEARTBEAT_INTERVAL"; + case SCP_TIMER_NF_INSTANCE_NO_HEARTBEAT: + return "SCP_TIMER_NF_INSTANCE_NO_HEARTBEAT"; + case SCP_TIMER_NF_INSTANCE_VALIDITY: + return "SCP_TIMER_NF_INSTANCE_VALIDITY"; + case SCP_TIMER_SUBSCRIPTION_VALIDITY: + return "SCP_TIMER_SUBSCRIPTION_VALIDITY"; + case SCP_TIMER_SBI_CLIENT_WAIT: + return "SCP_TIMER_SBI_CLIENT_WAIT"; + default: + break; + } + + return "UNKNOWN_TIMER"; +} + +static void timer_send_event(int timer_id, void *data) +{ + int rv; + scp_event_t *e = NULL; + ogs_assert(data); + + switch (timer_id) { + case SCP_TIMER_NF_INSTANCE_REGISTRATION_INTERVAL: + case SCP_TIMER_NF_INSTANCE_HEARTBEAT_INTERVAL: + case SCP_TIMER_NF_INSTANCE_NO_HEARTBEAT: + case SCP_TIMER_NF_INSTANCE_VALIDITY: + case SCP_TIMER_SUBSCRIPTION_VALIDITY: + e = scp_event_new(SCP_EVT_SBI_TIMER); + ogs_assert(e); + e->timer_id = timer_id; + e->sbi.data = data; + break; + case SCP_TIMER_SBI_CLIENT_WAIT: + e = scp_event_new(SCP_EVT_SBI_TIMER); + if (!e) { + ogs_sbi_xact_t *sbi_xact = data; + ogs_assert(sbi_xact); + + ogs_error("timer_send_event() failed"); + ogs_sbi_xact_remove(sbi_xact); + return; + } + e->timer_id = timer_id; + e->sbi.data = data; + break; + default: + ogs_fatal("Unknown timer id[%d]", timer_id); + ogs_assert_if_reached(); + break; + } + + rv = ogs_queue_push(ogs_app()->queue, e); + if (rv != OGS_OK) { + ogs_warn("ogs_queue_push() failed [%d] in %s", + (int)rv, scp_timer_get_name(e->timer_id)); + scp_event_free(e); + } +} + +void scp_timer_nf_instance_registration_interval(void *data) +{ + timer_send_event(SCP_TIMER_NF_INSTANCE_REGISTRATION_INTERVAL, data); +} + +void scp_timer_nf_instance_heartbeat_interval(void *data) +{ + timer_send_event(SCP_TIMER_NF_INSTANCE_HEARTBEAT_INTERVAL, data); +} + +void scp_timer_nf_instance_no_heartbeat(void *data) +{ + timer_send_event(SCP_TIMER_NF_INSTANCE_NO_HEARTBEAT, data); +} + +void scp_timer_nf_instance_validity(void *data) +{ + timer_send_event(SCP_TIMER_NF_INSTANCE_VALIDITY, data); +} + +void scp_timer_subscription_validity(void *data) +{ + timer_send_event(SCP_TIMER_SUBSCRIPTION_VALIDITY, data); +} + +void scp_timer_sbi_client_wait_expire(void *data) +{ + timer_send_event(SCP_TIMER_SBI_CLIENT_WAIT, data); +} diff --git a/src/scp/timer.h b/src/scp/timer.h new file mode 100644 index 000000000..4dcd8c59e --- /dev/null +++ b/src/scp/timer.h @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2019-2022 by Sukchan Lee + * + * This file is part of Open5GS. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef SCP_TIMER_H +#define SCP_TIMER_H + +#include "ogs-core.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* forward declaration */ +typedef enum { + SCP_TIMER_BASE = 0, + + SCP_TIMER_NF_INSTANCE_REGISTRATION_INTERVAL, + SCP_TIMER_NF_INSTANCE_HEARTBEAT_INTERVAL, + SCP_TIMER_NF_INSTANCE_NO_HEARTBEAT, + SCP_TIMER_NF_INSTANCE_VALIDITY, + SCP_TIMER_SUBSCRIPTION_VALIDITY, + SCP_TIMER_SBI_CLIENT_WAIT, + + MAX_NUM_OF_SCP_TIMER, + +} scp_timer_e; + +const char *scp_timer_get_name(scp_timer_e id); + +void scp_timer_nf_instance_registration_interval(void *data); +void scp_timer_nf_instance_heartbeat_interval(void *data); +void scp_timer_nf_instance_no_heartbeat(void *data); +void scp_timer_nf_instance_validity(void *data); +void scp_timer_subscription_validity(void *data); +void scp_timer_sbi_client_wait_expire(void *data); + +#ifdef __cplusplus +} +#endif + +#endif /* SCP_TIMER_H */ diff --git a/src/sgwc/pfcp-path.c b/src/sgwc/pfcp-path.c index 59bacf2d3..709784221 100644 --- a/src/sgwc/pfcp-path.c +++ b/src/sgwc/pfcp-path.c @@ -117,7 +117,7 @@ static void pfcp_recv_cb(short when, ogs_socket_t fd, void *data) rv = ogs_queue_push(ogs_app()->queue, e); if (rv != OGS_OK) { - ogs_warn("ogs_queue_push() failed:%d", (int)rv); + ogs_error("ogs_queue_push() failed:%d", (int)rv); ogs_pkbuf_free(e->pkbuf); sgwc_event_free(e); } @@ -212,6 +212,8 @@ int sgwc_pfcp_send_bearer_to_modify_list( ogs_assert(sess); ogs_assert(xact); + xact->local_seid = sess->sgwc_sxa_seid; + memset(&h, 0, sizeof(ogs_pfcp_header_t)); h.type = OGS_PFCP_SESSION_MODIFICATION_REQUEST_TYPE; h.seid = sess->sgwu_sxa_seid; @@ -377,6 +379,7 @@ int sgwc_pfcp_send_session_report_response( ogs_pfcp_header_t h; ogs_assert(xact); + xact->local_seid = sess->sgwc_sxa_seid; memset(&h, 0, sizeof(ogs_pfcp_header_t)); h.type = OGS_PFCP_SESSION_REPORT_RESPONSE_TYPE; diff --git a/src/sgwc/pfcp-sm.c b/src/sgwc/pfcp-sm.c index f232dc20e..c12465d7c 100644 --- a/src/sgwc/pfcp-sm.c +++ b/src/sgwc/pfcp-sm.c @@ -316,7 +316,7 @@ static void node_timeout(ogs_pfcp_xact_t *xact, void *data) rv = ogs_queue_push(ogs_app()->queue, e); if (rv != OGS_OK) { - ogs_warn("ogs_queue_push() failed:%d", (int)rv); + ogs_error("ogs_queue_push() failed:%d", (int)rv); sgwc_event_free(e); } break; diff --git a/src/sgwc/s11-handler.c b/src/sgwc/s11-handler.c index 708679a19..5fea1f8e5 100644 --- a/src/sgwc/s11-handler.c +++ b/src/sgwc/s11-handler.c @@ -689,6 +689,7 @@ void sgwc_s11_handle_create_bearer_response( ogs_gtp2_f_teid_t *sgw_s1u_teid = NULL, *enb_s1u_teid = NULL; ogs_gtp2_uli_t uli; + ogs_assert(sgwc_ue); ogs_assert(message); rsp = &message->create_bearer_response; ogs_assert(rsp); @@ -715,30 +716,10 @@ void sgwc_s11_handle_create_bearer_response( rv = ogs_gtp_xact_commit(s11_xact); ogs_expect(rv == OGS_OK); - /************************ - * Check SGWC-UE Context - ************************/ - cause_value = OGS_GTP2_CAUSE_REQUEST_ACCEPTED; - - if (!sgwc_ue) { - ogs_error("No Context in TEID"); - cause_value = OGS_GTP2_CAUSE_CONTEXT_NOT_FOUND; - } - - if (cause_value != OGS_GTP2_CAUSE_REQUEST_ACCEPTED) { - ogs_assert(OGS_OK == - sgwc_pfcp_send_bearer_modification_request( - bearer, NULL, NULL, - OGS_PFCP_MODIFY_UL_ONLY|OGS_PFCP_MODIFY_REMOVE)); - ogs_gtp_send_error_message(s5c_xact, sess ? sess->pgw_s5c_teid : 0, - OGS_GTP2_CREATE_BEARER_RESPONSE_TYPE, cause_value); - return; - } - /***************************************** * Check Mandatory/Conditional IE Missing *****************************************/ - ogs_assert(cause_value == OGS_GTP2_CAUSE_REQUEST_ACCEPTED); + cause_value = OGS_GTP2_CAUSE_REQUEST_ACCEPTED; if (rsp->bearer_contexts.presence == 0) { ogs_error("No Bearer"); @@ -873,6 +854,7 @@ void sgwc_s11_handle_update_bearer_response( sgwc_bearer_t *bearer = NULL; ogs_gtp2_update_bearer_response_t *rsp = NULL; + ogs_assert(sgwc_ue); ogs_assert(message); rsp = &message->update_bearer_response; ogs_assert(rsp); @@ -899,26 +881,10 @@ void sgwc_s11_handle_update_bearer_response( rv = ogs_gtp_xact_commit(s11_xact); ogs_expect(rv == OGS_OK); - /************************ - * Check SGWC-UE Context - ************************/ - cause_value = OGS_GTP2_CAUSE_REQUEST_ACCEPTED; - - if (!sgwc_ue) { - ogs_error("No Context in TEID"); - cause_value = OGS_GTP2_CAUSE_CONTEXT_NOT_FOUND; - } - - if (cause_value != OGS_GTP2_CAUSE_REQUEST_ACCEPTED) { - ogs_gtp_send_error_message(s5c_xact, sess ? sess->pgw_s5c_teid : 0, - OGS_GTP2_UPDATE_BEARER_RESPONSE_TYPE, cause_value); - return; - } - /***************************************** * Check Mandatory/Conditional IE Missing *****************************************/ - ogs_assert(cause_value == OGS_GTP2_CAUSE_REQUEST_ACCEPTED); + cause_value = OGS_GTP2_CAUSE_REQUEST_ACCEPTED; if (rsp->bearer_contexts.presence == 0) { ogs_error("No Bearer"); @@ -1005,6 +971,7 @@ void sgwc_s11_handle_delete_bearer_response( sgwc_bearer_t *bearer = NULL; ogs_gtp2_delete_bearer_response_t *rsp = NULL; + ogs_assert(sgwc_ue); ogs_assert(message); rsp = &message->delete_bearer_response; ogs_assert(rsp); @@ -1036,11 +1003,6 @@ void sgwc_s11_handle_delete_bearer_response( ************************/ cause_value = OGS_GTP2_CAUSE_REQUEST_ACCEPTED; - if (!sgwc_ue) { - ogs_error("No Context in TEID"); - cause_value = OGS_GTP2_CAUSE_CONTEXT_NOT_FOUND; - } - if (rsp->linked_eps_bearer_id.presence) { /* * << Linked EPS Bearer ID >> @@ -1112,10 +1074,8 @@ void sgwc_s11_handle_delete_bearer_response( ogs_error("No Cause"); } - if (sgwc_ue) { - ogs_debug(" MME_S11_TEID[%d] SGW_S11_TEID[%d]", - sgwc_ue->mme_s11_teid, sgwc_ue->sgw_s11_teid); - } + ogs_debug(" MME_S11_TEID[%d] SGW_S11_TEID[%d]", + sgwc_ue->mme_s11_teid, sgwc_ue->sgw_s11_teid); ogs_debug(" SGW_S5C_TEID[0x%x] PGW_S5C_TEID[0x%x]", sess->sgw_s5c_teid, sess->pgw_s5c_teid); @@ -1514,6 +1474,7 @@ void sgwc_s11_handle_bearer_resource_command( s5c_xact = ogs_gtp_xact_local_create( sess->gnode, &message->h, pkbuf, gtp_bearer_timeout, bearer); ogs_expect_or_return(s5c_xact); + s5c_xact->local_teid = sess->sgw_s5c_teid; ogs_gtp_xact_associate(s11_xact, s5c_xact); diff --git a/src/sgwc/s5c-handler.c b/src/sgwc/s5c-handler.c index b76440a9b..63f88e128 100644 --- a/src/sgwc/s5c-handler.c +++ b/src/sgwc/s5c-handler.c @@ -79,6 +79,9 @@ void sgwc_s5c_handle_create_session_response( ogs_gtp_xact_t *s11_xact = NULL; ogs_gtp_node_t *pgw = NULL; + ogs_assert(sess); + sgwc_ue = sess->sgwc_ue; + ogs_assert(sgwc_ue); ogs_assert(gtpbuf); ogs_assert(message); rsp = &message->create_session_response; @@ -96,30 +99,10 @@ void sgwc_s5c_handle_create_session_response( rv = ogs_gtp_xact_commit(s5c_xact); ogs_expect(rv == OGS_OK); - /************************ - * Check Session Context - ************************/ - cause_value = OGS_GTP2_CAUSE_REQUEST_ACCEPTED; - - if (!sess) { - ogs_error("No Context in TEID"); - cause_value = OGS_GTP2_CAUSE_CONTEXT_NOT_FOUND; - } else { - sgwc_ue = sess->sgwc_ue; - ogs_assert(sgwc_ue); - } - - if (cause_value != OGS_GTP2_CAUSE_REQUEST_ACCEPTED) { - ogs_gtp_send_error_message( - s11_xact, sgwc_ue ? sgwc_ue->mme_s11_teid : 0, - OGS_GTP2_CREATE_SESSION_RESPONSE_TYPE, cause_value); - return; - } - /***************************************** * Check Mandatory/Conditional IE Missing *****************************************/ - ogs_assert(cause_value == OGS_GTP2_CAUSE_REQUEST_ACCEPTED); + cause_value = OGS_GTP2_CAUSE_REQUEST_ACCEPTED; if (rsp->pgw_s5_s8__s2a_s2b_f_teid_for_pmip_based_interface_or_for_gtp_based_control_plane_interface.presence == 0) { ogs_error("No GTP TEID"); @@ -282,108 +265,6 @@ void sgwc_s5c_handle_create_session_response( OGS_PFCP_MODIFY_UL_ONLY|OGS_PFCP_MODIFY_ACTIVATE)); } -void sgwc_s5c_handle_delete_session_response( - sgwc_sess_t *sess, ogs_gtp_xact_t *s5c_xact, - ogs_pkbuf_t *gtpbuf, ogs_gtp2_message_t *message) -{ - int rv; - ogs_gtp2_cause_t *cause = NULL; - uint8_t cause_value; - - sgwc_ue_t *sgwc_ue = NULL; - - ogs_gtp_xact_t *s11_xact = NULL; - ogs_gtp2_delete_session_response_t *rsp = NULL; - - ogs_assert(message); - rsp = &message->delete_session_response; - ogs_assert(rsp); - - ogs_debug("Delete Session Response"); - - /******************** - * Check Transaction - ********************/ - ogs_assert(s5c_xact); - s11_xact = s5c_xact->assoc_xact; - ogs_assert(s11_xact); - - rv = ogs_gtp_xact_commit(s5c_xact); - ogs_expect(rv == OGS_OK); - - /************************ - * Check Session Context - ************************/ - cause_value = OGS_GTP2_CAUSE_REQUEST_ACCEPTED; - - if (!sess) { - ogs_error("No Context in TEID"); - cause_value = OGS_GTP2_CAUSE_CONTEXT_NOT_FOUND; - } else { - sgwc_ue = sess->sgwc_ue; - ogs_assert(sgwc_ue); - } - - if (cause_value != OGS_GTP2_CAUSE_REQUEST_ACCEPTED) { - ogs_gtp_send_error_message( - s11_xact, sgwc_ue ? sgwc_ue->mme_s11_teid : 0, - OGS_GTP2_DELETE_SESSION_RESPONSE_TYPE, cause_value); - return; - } - - /***************************************** - * Check Mandatory/Conditional IE Missing - *****************************************/ - ogs_assert(cause_value == OGS_GTP2_CAUSE_REQUEST_ACCEPTED); - - if (rsp->cause.presence == 0) { - ogs_error("No Cause"); - cause_value = OGS_GTP2_CAUSE_MANDATORY_IE_MISSING; - } - - if (cause_value != OGS_GTP2_CAUSE_REQUEST_ACCEPTED) { - ogs_gtp_send_error_message( - s11_xact, sgwc_ue ? sgwc_ue->mme_s11_teid : 0, - OGS_GTP2_DELETE_SESSION_RESPONSE_TYPE, cause_value); - return; - } - - /******************** - * Check Cause Value - ********************/ - ogs_assert(cause_value == OGS_GTP2_CAUSE_REQUEST_ACCEPTED); - - cause = rsp->cause.data; - ogs_assert(cause); - cause_value = cause->value; - if (cause_value != OGS_GTP2_CAUSE_REQUEST_ACCEPTED) { - ogs_error("GTP Failed [CAUSE:%d]", cause_value); - ogs_gtp_send_error_message( - s11_xact, sgwc_ue ? sgwc_ue->mme_s11_teid : 0, - OGS_GTP2_DELETE_SESSION_RESPONSE_TYPE, cause_value); - return; - } - - /******************** - * Check ALL Context - ********************/ - ogs_assert(sess); - ogs_assert(sgwc_ue); - - /* Remove a pgw session */ - ogs_debug(" MME_S11_TEID[%d] SGW_S11_TEID[%d]", - sgwc_ue->mme_s11_teid, sgwc_ue->sgw_s11_teid); - ogs_debug(" SGW_S5C_TEID[0x%x] PGW_S5C_TEID[0x%x]", - sess->sgw_s5c_teid, sess->pgw_s5c_teid); - - /* - * 1. MME sends Delete Session Request to SGW/SMF. - * 2. SMF sends Delete Session Response to SGW/MME. - */ - ogs_assert(OGS_OK == - sgwc_pfcp_send_session_deletion_request(sess, s11_xact, gtpbuf)); -} - void sgwc_s5c_handle_modify_bearer_response( sgwc_sess_t *sess, ogs_gtp_xact_t *s5c_xact, ogs_pkbuf_t *gtpbuf, ogs_gtp2_message_t *message) @@ -399,6 +280,9 @@ void sgwc_s5c_handle_modify_bearer_response( ogs_gtp_xact_t *s11_xact = NULL; ogs_gtp2_modify_bearer_response_t *rsp = NULL; + ogs_assert(sess); + sgwc_ue = sess->sgwc_ue; + ogs_assert(sgwc_ue); ogs_assert(message); rsp = &message->modify_bearer_response; ogs_assert(rsp); @@ -416,35 +300,10 @@ void sgwc_s5c_handle_modify_bearer_response( rv = ogs_gtp_xact_commit(s5c_xact); ogs_expect(rv == OGS_OK); - /************************ - * Check Session Context - ************************/ - cause_value = OGS_GTP2_CAUSE_REQUEST_ACCEPTED; - - if (!sess) { - ogs_error("No Context in TEID"); - cause_value = OGS_GTP2_CAUSE_CONTEXT_NOT_FOUND; - } else { - sgwc_ue = sess->sgwc_ue; - ogs_assert(sgwc_ue); - } - - if (cause_value != OGS_GTP2_CAUSE_REQUEST_ACCEPTED) { - if (modify_action == OGS_GTP_MODIFY_IN_PATH_SWITCH_REQUEST) - ogs_gtp_send_error_message( - s11_xact, sgwc_ue ? sgwc_ue->mme_s11_teid : 0, - OGS_GTP2_CREATE_SESSION_RESPONSE_TYPE, cause_value); - else - ogs_gtp_send_error_message( - s11_xact, sgwc_ue ? sgwc_ue->mme_s11_teid : 0, - OGS_GTP2_MODIFY_BEARER_RESPONSE_TYPE, cause_value); - return; - } - /***************************************** * Check Mandatory/Conditional IE Missing *****************************************/ - ogs_assert(cause_value == OGS_GTP2_CAUSE_REQUEST_ACCEPTED); + cause_value = OGS_GTP2_CAUSE_REQUEST_ACCEPTED; if (rsp->cause.presence == 0) { ogs_error("No Cause"); @@ -513,6 +372,91 @@ void sgwc_s5c_handle_modify_bearer_response( } } +void sgwc_s5c_handle_delete_session_response( + sgwc_sess_t *sess, ogs_gtp_xact_t *s5c_xact, + ogs_pkbuf_t *gtpbuf, ogs_gtp2_message_t *message) +{ + int rv; + ogs_gtp2_cause_t *cause = NULL; + uint8_t cause_value; + + sgwc_ue_t *sgwc_ue = NULL; + + ogs_gtp_xact_t *s11_xact = NULL; + ogs_gtp2_delete_session_response_t *rsp = NULL; + + ogs_assert(sess); + sgwc_ue = sess->sgwc_ue; + ogs_assert(sgwc_ue); + ogs_assert(message); + rsp = &message->delete_session_response; + ogs_assert(rsp); + + ogs_debug("Delete Session Response"); + + /******************** + * Check Transaction + ********************/ + ogs_assert(s5c_xact); + s11_xact = s5c_xact->assoc_xact; + ogs_assert(s11_xact); + + rv = ogs_gtp_xact_commit(s5c_xact); + ogs_expect(rv == OGS_OK); + + /***************************************** + * Check Mandatory/Conditional IE Missing + *****************************************/ + cause_value = OGS_GTP2_CAUSE_REQUEST_ACCEPTED; + + if (rsp->cause.presence == 0) { + ogs_error("No Cause"); + cause_value = OGS_GTP2_CAUSE_MANDATORY_IE_MISSING; + } + + if (cause_value != OGS_GTP2_CAUSE_REQUEST_ACCEPTED) { + ogs_gtp_send_error_message( + s11_xact, sgwc_ue ? sgwc_ue->mme_s11_teid : 0, + OGS_GTP2_DELETE_SESSION_RESPONSE_TYPE, cause_value); + return; + } + + /******************** + * Check Cause Value + ********************/ + ogs_assert(cause_value == OGS_GTP2_CAUSE_REQUEST_ACCEPTED); + + cause = rsp->cause.data; + ogs_assert(cause); + cause_value = cause->value; + if (cause_value != OGS_GTP2_CAUSE_REQUEST_ACCEPTED) { + ogs_error("GTP Failed [CAUSE:%d]", cause_value); + ogs_gtp_send_error_message( + s11_xact, sgwc_ue ? sgwc_ue->mme_s11_teid : 0, + OGS_GTP2_DELETE_SESSION_RESPONSE_TYPE, cause_value); + return; + } + + /******************** + * Check ALL Context + ********************/ + ogs_assert(sess); + ogs_assert(sgwc_ue); + + /* Remove a pgw session */ + ogs_debug(" MME_S11_TEID[%d] SGW_S11_TEID[%d]", + sgwc_ue->mme_s11_teid, sgwc_ue->sgw_s11_teid); + ogs_debug(" SGW_S5C_TEID[0x%x] PGW_S5C_TEID[0x%x]", + sess->sgw_s5c_teid, sess->pgw_s5c_teid); + + /* + * 1. MME sends Delete Session Request to SGW/SMF. + * 2. SMF sends Delete Session Response to SGW/MME. + */ + ogs_assert(OGS_OK == + sgwc_pfcp_send_session_deletion_request(sess, s11_xact, gtpbuf)); +} + void sgwc_s5c_handle_create_bearer_request( sgwc_sess_t *sess, ogs_gtp_xact_t *s5c_xact, ogs_pkbuf_t *gtpbuf, ogs_gtp2_message_t *message) @@ -725,6 +669,7 @@ void sgwc_s5c_handle_update_bearer_request( rv = ogs_gtp_xact_update_tx(s11_xact, &message->h, pkbuf); ogs_expect_or_return(rv == OGS_OK); } + s11_xact->local_teid = sgwc_ue->sgw_s11_teid; rv = ogs_gtp_xact_commit(s11_xact); ogs_expect(rv == OGS_OK); @@ -874,6 +819,7 @@ void sgwc_s5c_handle_delete_bearer_request( rv = ogs_gtp_xact_update_tx(s11_xact, &message->h, pkbuf); ogs_expect_or_return(rv == OGS_OK); } + s11_xact->local_teid = sgwc_ue->sgw_s11_teid; rv = ogs_gtp_xact_commit(s11_xact); ogs_expect(rv == OGS_OK); @@ -889,6 +835,9 @@ void sgwc_s5c_handle_bearer_resource_failure_indication( sgwc_ue_t *sgwc_ue = NULL; + ogs_assert(sess); + sgwc_ue = sess->sgwc_ue; + ogs_assert(sgwc_ue); ogs_assert(message); ind = &message->bearer_resource_failure_indication; ogs_assert(ind); @@ -902,17 +851,6 @@ void sgwc_s5c_handle_bearer_resource_failure_indication( s11_xact = s5c_xact->assoc_xact; ogs_assert(s11_xact); - /************************ - * Check Session Context - ************************/ - if (!sess) { - ogs_error("No Context in TEID"); - cause_value = OGS_GTP2_CAUSE_CONTEXT_NOT_FOUND; - } else { - sgwc_ue = sess->sgwc_ue; - ogs_assert(sgwc_ue); - } - /******************** * Check Cause Value ********************/ diff --git a/src/sgwc/sgwc-sm.c b/src/sgwc/sgwc-sm.c index 7265f95a8..b6e1d4a63 100644 --- a/src/sgwc/sgwc-sm.c +++ b/src/sgwc/sgwc-sm.c @@ -157,7 +157,7 @@ void sgwc_state_operational(ogs_fsm_t *s, sgwc_event_t *e) if (gtp_message.h.teid_presence && gtp_message.h.teid != 0) { /* Cause is not "Context not found" */ sgwc_ue = sgwc_ue_find_by_teid(gtp_message.h.teid); - } else if (gtp_xact->local_teid) { /* rx no TEID or TEID=0 */ + } else if (gtp_xact->local_teid) { /* rx no TEID or TEID=0 */ /* 3GPP TS 29.274 5.5.2: we receive TEID=0 under some * conditions, such as cause "Session context not found". In those * cases, we still want to identify the local session which diff --git a/src/sgwc/sxa-handler.c b/src/sgwc/sxa-handler.c index fe13b36cc..a4f5ca277 100644 --- a/src/sgwc/sxa-handler.c +++ b/src/sgwc/sxa-handler.c @@ -157,6 +157,7 @@ void sgwc_sxa_handle_session_establishment_response( ogs_debug("Session Establishment Response"); + ogs_assert(sess); ogs_assert(pfcp_xact); ogs_assert(pfcp_rsp); ogs_assert(recv_message); @@ -171,11 +172,6 @@ void sgwc_sxa_handle_session_establishment_response( cause_value = OGS_GTP2_CAUSE_REQUEST_ACCEPTED; - if (!sess) { - ogs_warn("No Context"); - cause_value = OGS_GTP2_CAUSE_CONTEXT_NOT_FOUND; - } - if (pfcp_rsp->up_f_seid.presence == 0) { ogs_error("No UP F-SEID"); cause_value = OGS_GTP2_CAUSE_MANDATORY_IE_MISSING; @@ -453,6 +449,7 @@ void sgwc_sxa_handle_session_modification_response( ogs_debug("Session Modification Response"); + ogs_assert(sess); ogs_assert(pfcp_xact); ogs_assert(pfcp_rsp); @@ -462,30 +459,12 @@ void sgwc_sxa_handle_session_modification_response( cause_value = OGS_GTP2_CAUSE_REQUEST_ACCEPTED; if (flags & OGS_PFCP_MODIFY_SESSION) { - if (!sess) { - ogs_warn("No Context"); - - sess = pfcp_xact->data; - ogs_assert(sess); - - cause_value = OGS_GTP2_CAUSE_CONTEXT_NOT_FOUND; - } sgwc_ue = sess->sgwc_ue; ogs_assert(sgwc_ue); } else { bearer = pfcp_xact->data; ogs_assert(bearer); - - if (!sess) { - ogs_warn("No Context"); - - sess = bearer->sess; - ogs_assert(sess); - - cause_value = OGS_GTP2_CAUSE_CONTEXT_NOT_FOUND; - } - sgwc_ue = bearer->sgwc_ue; ogs_assert(sgwc_ue); } @@ -1206,16 +1185,12 @@ void sgwc_sxa_handle_session_deletion_response( ogs_debug("Session Deletion Response"); + ogs_assert(sess); ogs_assert(pfcp_xact); ogs_assert(pfcp_rsp); cause_value = OGS_GTP2_CAUSE_REQUEST_ACCEPTED; - if (!sess) { - ogs_warn("No Context"); - cause_value = OGS_GTP2_CAUSE_CONTEXT_NOT_FOUND; - } - if (pfcp_rsp->cause.presence) { if (pfcp_rsp->cause.u8 != OGS_PFCP_CAUSE_REQUEST_ACCEPTED) { ogs_warn("PFCP Cause[%d] : Not Accepted", pfcp_rsp->cause.u8); @@ -1324,16 +1299,12 @@ void sgwc_sxa_handle_session_report_request( ogs_debug("Session Report Request"); + ogs_assert(sess); ogs_assert(pfcp_xact); ogs_assert(pfcp_req); cause_value = OGS_GTP2_CAUSE_REQUEST_ACCEPTED; - if (!sess) { - ogs_warn("No Context"); - cause_value = OGS_PFCP_CAUSE_SESSION_CONTEXT_NOT_FOUND; - } - if (pfcp_req->report_type.presence == 0) { ogs_error("No Report Type"); cause_value = OGS_GTP2_CAUSE_MANDATORY_IE_MISSING; diff --git a/src/sgwc/timer.c b/src/sgwc/timer.c index 863f8d505..85d5f8c84 100644 --- a/src/sgwc/timer.c +++ b/src/sgwc/timer.c @@ -57,7 +57,7 @@ static void timer_send_event(int timer_id, void *data) rv = ogs_queue_push(ogs_app()->queue, e); if (rv != OGS_OK) { - ogs_warn("ogs_queue_push() failed [%d] in %s", + ogs_error("ogs_queue_push() failed [%d] in %s", (int)rv, sgwc_timer_get_name(e->timer_id)); sgwc_event_free(e); } diff --git a/src/sgwu/pfcp-path.c b/src/sgwu/pfcp-path.c index 4ed17d9f0..bd0e5c438 100644 --- a/src/sgwu/pfcp-path.c +++ b/src/sgwu/pfcp-path.c @@ -117,7 +117,7 @@ static void pfcp_recv_cb(short when, ogs_socket_t fd, void *data) rv = ogs_queue_push(ogs_app()->queue, e); if (rv != OGS_OK) { - ogs_warn("ogs_queue_push() failed:%d", (int)rv); + ogs_error("ogs_queue_push() failed:%d", (int)rv); ogs_pkbuf_free(e->pkbuf); sgwu_event_free(e); } diff --git a/src/sgwu/pfcp-sm.c b/src/sgwu/pfcp-sm.c index c7513acef..7d8d7cb06 100644 --- a/src/sgwu/pfcp-sm.c +++ b/src/sgwu/pfcp-sm.c @@ -295,7 +295,7 @@ static void node_timeout(ogs_pfcp_xact_t *xact, void *data) rv = ogs_queue_push(ogs_app()->queue, e); if (rv != OGS_OK) { - ogs_warn("ogs_queue_push() failed:%d", (int)rv); + ogs_error("ogs_queue_push() failed:%d", (int)rv); sgwu_event_free(e); } break; diff --git a/src/sgwu/timer.c b/src/sgwu/timer.c index 0b05ae74a..c7cabe67e 100644 --- a/src/sgwu/timer.c +++ b/src/sgwu/timer.c @@ -45,7 +45,7 @@ static void timer_send_event(int timer_id, void *data) rv = ogs_queue_push(ogs_app()->queue, e); if (rv != OGS_OK) { - ogs_warn("ogs_queue_push() failed:%d", (int)rv); + ogs_error("ogs_queue_push() failed:%d", (int)rv); sgwu_event_free(e); } } diff --git a/src/smf/gtp-path.c b/src/smf/gtp-path.c index f5b35d7a7..7146c211b 100644 --- a/src/smf/gtp-path.c +++ b/src/smf/gtp-path.c @@ -106,7 +106,7 @@ static void _gtpv1v2_c_recv_cb(short when, ogs_socket_t fd, void *data) rv = ogs_queue_push(ogs_app()->queue, e); if (rv != OGS_OK) { - ogs_warn("ogs_queue_push() failed:%d", (int)rv); + ogs_error("ogs_queue_push() failed:%d", (int)rv); ogs_pkbuf_free(e->pkbuf); smf_event_free(e); } diff --git a/src/smf/gx-path.c b/src/smf/gx-path.c index bbed59729..6957697c9 100644 --- a/src/smf/gx-path.c +++ b/src/smf/gx-path.c @@ -1005,7 +1005,7 @@ out: e->gtp_xact = xact; rv = ogs_queue_push(ogs_app()->queue, e); if (rv != OGS_OK) { - ogs_warn("ogs_queue_push() failed:%d", (int)rv); + ogs_error("ogs_queue_push() failed:%d", (int)rv); ogs_session_data_free(&gx_message->session_data); ogs_free(gx_message); smf_event_free(e); @@ -1248,7 +1248,7 @@ static int smf_gx_rar_cb( struct msg **msg, struct avp *avp, e->gx_message = gx_message; rv = ogs_queue_push(ogs_app()->queue, e); if (rv != OGS_OK) { - ogs_warn("ogs_queue_push() failed:%d", (int)rv); + ogs_error("ogs_queue_push() failed:%d", (int)rv); ogs_session_data_free(&gx_message->session_data); ogs_free(gx_message); smf_event_free(e); diff --git a/src/smf/gy-path.c b/src/smf/gy-path.c index 2357d6ba3..ecbda74dd 100644 --- a/src/smf/gy-path.c +++ b/src/smf/gy-path.c @@ -1104,7 +1104,7 @@ out: } rv = ogs_queue_push(ogs_app()->queue, e); if (rv != OGS_OK) { - ogs_warn("ogs_queue_push() failed:%d", (int)rv); + ogs_error("ogs_queue_push() failed:%d", (int)rv); ogs_free(gy_message); smf_event_free(e); } else { @@ -1233,7 +1233,7 @@ static int smf_gy_rar_cb( struct msg **msg, struct avp *avp, e->gy_message = gy_message; rv = ogs_queue_push(ogs_app()->queue, e); if (rv != OGS_OK) { - ogs_warn("ogs_queue_push() failed:%d", (int)rv); + ogs_error("ogs_queue_push() failed:%d", (int)rv); ogs_free(gy_message); smf_event_free(e); } else { diff --git a/src/smf/init.c b/src/smf/init.c index 329f2b122..b56f8be00 100644 --- a/src/smf/init.c +++ b/src/smf/init.c @@ -53,7 +53,7 @@ int smf_initialize() rv = ogs_pfcp_context_parse_config("smf", "upf"); if (rv != OGS_OK) return rv; - rv = ogs_sbi_context_parse_config("smf", "nrf"); + rv = ogs_sbi_context_parse_config("smf", "nrf", "scp"); if (rv != OGS_OK) return rv; rv = ogs_metrics_context_parse_config(); diff --git a/src/smf/n4-handler.c b/src/smf/n4-handler.c index 66a367dbe..3c3d251b6 100644 --- a/src/smf/n4-handler.c +++ b/src/smf/n4-handler.c @@ -255,6 +255,7 @@ void smf_5gc_n4_handle_session_modification_response( ogs_debug("Session Modification Response [5gc]"); + ogs_assert(sess); ogs_assert(xact); ogs_assert(rsp); @@ -279,11 +280,6 @@ void smf_5gc_n4_handle_session_modification_response( status = OGS_SBI_HTTP_STATUS_OK; - if (!sess) { - ogs_warn("No Context"); - status = OGS_SBI_HTTP_STATUS_NOT_FOUND; - } - if (rsp->cause.presence) { if (rsp->cause.u8 != OGS_PFCP_CAUSE_REQUEST_ACCEPTED) { ogs_warn("PFCP Cause [%d] : Not Accepted", rsp->cause.u8); @@ -624,10 +620,7 @@ int smf_5gc_n4_handle_session_deletion_response( status = OGS_SBI_HTTP_STATUS_OK; - if (!sess) { - ogs_warn("No Context"); - status = OGS_SBI_HTTP_STATUS_NOT_FOUND; - } + ogs_assert(sess); if (rsp->cause.presence) { if (rsp->cause.u8 != OGS_PFCP_CAUSE_REQUEST_ACCEPTED) { @@ -669,8 +662,6 @@ int smf_5gc_n4_handle_session_deletion_response( return status; } - ogs_assert(sess); - return status; } @@ -803,6 +794,7 @@ void smf_epc_n4_handle_session_modification_response( OGS_LIST(pdr_to_create_list); + ogs_assert(sess); ogs_assert(xact); ogs_assert(rsp); @@ -831,11 +823,6 @@ void smf_epc_n4_handle_session_modification_response( ogs_pfcp_xact_commit(xact); - if (!sess) { - ogs_error("No Context"); - return; - } - if (rsp->cause.presence) { if (rsp->cause.u8 != OGS_PFCP_CAUSE_REQUEST_ACCEPTED) { ogs_error("PFCP Cause [%d] : Not Accepted", rsp->cause.u8); @@ -1111,6 +1098,7 @@ void smf_n4_handle_session_report_request( uint16_t pdr_id = 0; unsigned int i; + ogs_assert(sess); ogs_assert(pfcp_xact); ogs_assert(pfcp_req); @@ -1118,11 +1106,6 @@ void smf_n4_handle_session_report_request( cause_value = OGS_GTP2_CAUSE_REQUEST_ACCEPTED; - if (!sess) { - ogs_warn("No Context"); - cause_value = OGS_PFCP_CAUSE_SESSION_CONTEXT_NOT_FOUND; - } - if (pfcp_req->report_type.presence == 0) { ogs_error("No Report Type"); cause_value = OGS_GTP2_CAUSE_MANDATORY_IE_MISSING; @@ -1135,7 +1118,6 @@ void smf_n4_handle_session_report_request( return; } - ogs_assert(sess); report_type.value = pfcp_req->report_type.u8; if (report_type.downlink_data_report) { diff --git a/src/smf/nf-sm.c b/src/smf/nf-sm.c index 018f05133..334be8892 100644 --- a/src/smf/nf-sm.c +++ b/src/smf/nf-sm.c @@ -61,16 +61,18 @@ void smf_nf_state_initial(ogs_fsm_t *s, smf_event_t *e) nf_instance = e->sbi.data; ogs_assert(nf_instance); + nf_instance->t_registration_interval = ogs_timer_add(ogs_app()->timer_mgr, + smf_timer_nf_instance_registration_interval, nf_instance); ogs_assert(nf_instance->t_registration_interval); - nf_instance->t_registration_interval->cb = - smf_timer_nf_instance_registration_interval; + nf_instance->t_heartbeat_interval = ogs_timer_add(ogs_app()->timer_mgr, + smf_timer_nf_instance_heartbeat_interval, nf_instance); ogs_assert(nf_instance->t_heartbeat_interval); - nf_instance->t_heartbeat_interval->cb = - smf_timer_nf_instance_heartbeat_interval; + nf_instance->t_no_heartbeat = ogs_timer_add(ogs_app()->timer_mgr, + smf_timer_nf_instance_no_heartbeat, nf_instance); ogs_assert(nf_instance->t_no_heartbeat); - nf_instance->t_no_heartbeat->cb = smf_timer_nf_instance_no_heartbeat; + nf_instance->t_validity = ogs_timer_add(ogs_app()->timer_mgr, + smf_timer_nf_instance_validity, nf_instance); ogs_assert(nf_instance->t_validity); - nf_instance->t_validity->cb = smf_timer_nf_instance_validity; if (NF_INSTANCE_IS_NRF(nf_instance)) { OGS_FSM_TRAN(s, &smf_nf_state_will_register); @@ -82,10 +84,20 @@ void smf_nf_state_initial(ogs_fsm_t *s, smf_event_t *e) void smf_nf_state_final(ogs_fsm_t *s, smf_event_t *e) { + ogs_sbi_nf_instance_t *nf_instance = NULL; + ogs_assert(s); ogs_assert(e); smf_sm_debug(e); + + nf_instance = e->sbi.data; + ogs_assert(nf_instance); + + ogs_timer_delete(nf_instance->t_registration_interval); + ogs_timer_delete(nf_instance->t_heartbeat_interval); + ogs_timer_delete(nf_instance->t_no_heartbeat); + ogs_timer_delete(nf_instance->t_validity); } void smf_nf_state_will_register(ogs_fsm_t *s, smf_event_t *e) @@ -110,7 +122,8 @@ void smf_nf_state_will_register(ogs_fsm_t *s, smf_event_t *e) ogs_timer_start(nf_instance->t_registration_interval, ogs_app()->time.message.sbi.nf_register_interval); - ogs_assert(true == smf_nnrf_nfm_send_nf_register(nf_instance)); + ogs_assert(true == ogs_nnrf_nfm_send_nf_register( + nf_instance, smf_nnrf_nfm_build_register)); break; case OGS_FSM_EXIT_SIG: @@ -166,7 +179,8 @@ void smf_nf_state_will_register(ogs_fsm_t *s, smf_event_t *e) ogs_timer_start(nf_instance->t_registration_interval, ogs_app()->time.message.sbi.nf_register_interval); - ogs_assert(true == smf_nnrf_nfm_send_nf_register(nf_instance)); + ogs_assert(true == ogs_nnrf_nfm_send_nf_register( + nf_instance, smf_nnrf_nfm_build_register)); break; default: diff --git a/src/smf/pfcp-path.c b/src/smf/pfcp-path.c index 0c9425ccd..ebb2cd9cb 100644 --- a/src/smf/pfcp-path.c +++ b/src/smf/pfcp-path.c @@ -157,7 +157,7 @@ static void pfcp_recv_cb(short when, ogs_socket_t fd, void *data) rv = ogs_queue_push(ogs_app()->queue, e); if (rv != OGS_OK) { - ogs_warn("ogs_queue_push() failed:%d", (int)rv); + ogs_error("ogs_queue_push() failed:%d", (int)rv); ogs_pkbuf_free(e->pkbuf); smf_event_free(e); } @@ -329,6 +329,8 @@ int smf_pfcp_send_modify_list( ogs_assert(sess); ogs_assert(xact); + xact->local_seid = sess->smf_n4_seid; + memset(&h, 0, sizeof(ogs_pfcp_header_t)); h.type = OGS_PFCP_SESSION_MODIFICATION_REQUEST_TYPE; h.seid = sess->upf_n4_seid; diff --git a/src/smf/pfcp-sm.c b/src/smf/pfcp-sm.c index 226c2fe54..07f48b45d 100644 --- a/src/smf/pfcp-sm.c +++ b/src/smf/pfcp-sm.c @@ -348,7 +348,7 @@ static void node_timeout(ogs_pfcp_xact_t *xact, void *data) rv = ogs_queue_push(ogs_app()->queue, e); if (rv != OGS_OK) { - ogs_warn("ogs_queue_push() failed:%d", (int)rv); + ogs_error("ogs_queue_push() failed:%d", (int)rv); smf_event_free(e); } break; diff --git a/src/smf/s5c-handler.c b/src/smf/s5c-handler.c index cbc232056..e72f4fa75 100644 --- a/src/smf/s5c-handler.c +++ b/src/smf/s5c-handler.c @@ -596,6 +596,7 @@ void smf_s5c_handle_create_bearer_response( smf_bearer_t *bearer = NULL; ogs_pfcp_far_t *dl_far = NULL; + ogs_assert(sess); ogs_assert(rsp); ogs_debug("Create Bearer Response"); @@ -615,11 +616,6 @@ void smf_s5c_handle_create_bearer_response( ************************/ cause_value = OGS_GTP2_CAUSE_REQUEST_ACCEPTED; - if (!sess) { - ogs_error("No Context in TEID"); - cause_value = OGS_GTP2_CAUSE_CONTEXT_NOT_FOUND; - } - if (cause_value != OGS_GTP2_CAUSE_REQUEST_ACCEPTED) { ogs_assert(OGS_OK == smf_epc_pfcp_send_one_bearer_modification_request( @@ -771,6 +767,7 @@ void smf_s5c_handle_update_bearer_response( uint64_t pfcp_flags = 0; smf_bearer_t *bearer = NULL; + ogs_assert(sess); ogs_assert(rsp); ogs_debug("Update Bearer Response"); @@ -787,24 +784,10 @@ void smf_s5c_handle_update_bearer_response( rv = ogs_gtp_xact_commit(xact); ogs_expect(rv == OGS_OK); - /************************ - * Check Session Context - ************************/ - cause_value = OGS_GTP2_CAUSE_REQUEST_ACCEPTED; - - if (!sess) { - ogs_error("No Context in TEID"); - cause_value = OGS_GTP2_CAUSE_CONTEXT_NOT_FOUND; - } - - if (cause_value != OGS_GTP2_CAUSE_REQUEST_ACCEPTED) { - return; - } - /***************************************** * Check Mandatory/Conditional IE Missing *****************************************/ - ogs_assert(cause_value == OGS_GTP2_CAUSE_REQUEST_ACCEPTED); + cause_value = OGS_GTP2_CAUSE_REQUEST_ACCEPTED; if (rsp->bearer_contexts.presence == 0) { ogs_error("No Bearer"); @@ -888,6 +871,7 @@ bool smf_s5c_handle_delete_bearer_response( uint8_t cause_value; smf_bearer_t *bearer = NULL; + ogs_assert(sess); ogs_assert(rsp); ogs_debug("Delete Bearer Response"); @@ -902,18 +886,10 @@ bool smf_s5c_handle_delete_bearer_response( rv = ogs_gtp_xact_commit(xact); ogs_expect(rv == OGS_OK); - /************************ - * Check Session Context - ************************/ - if (!sess) - ogs_error("No Context in TEID"); - /******************** * Check ALL Context ********************/ ogs_assert(bearer); - sess = bearer->sess; - ogs_assert(sess); if (rsp->linked_eps_bearer_id.presence) { /* diff --git a/src/smf/s6b-path.c b/src/smf/s6b-path.c index 141e3bad2..fdd9922ae 100644 --- a/src/smf/s6b-path.c +++ b/src/smf/s6b-path.c @@ -712,7 +712,7 @@ static void smf_s6b_sta_cb(void *data, struct msg **msg) e->s6b_message = s6b_message; rv = ogs_queue_push(ogs_app()->queue, e); if (rv != OGS_OK) { - ogs_warn("ogs_queue_push() failed:%d", (int)rv); + ogs_error("ogs_queue_push() failed:%d", (int)rv); ogs_free(s6b_message); smf_event_free(e); } else { diff --git a/src/smf/sbi-path.c b/src/smf/sbi-path.c index 476075c08..17fe88c50 100644 --- a/src/smf/sbi-path.c +++ b/src/smf/sbi-path.c @@ -37,7 +37,8 @@ static int server_cb(ogs_sbi_request_t *request, void *data) rv = ogs_queue_push(ogs_app()->queue, e); if (rv != OGS_OK) { - ogs_warn("ogs_queue_push() failed:%d", (int)rv); + ogs_error("ogs_queue_push() failed:%d", (int)rv); + ogs_sbi_request_free(request); smf_event_free(e); return OGS_ERROR; } @@ -45,11 +46,18 @@ static int server_cb(ogs_sbi_request_t *request, void *data) return OGS_OK; } -static int client_cb(ogs_sbi_response_t *response, void *data) +static int client_cb(int status, ogs_sbi_response_t *response, void *data) { smf_event_t *e = NULL; int rv; + if (status != OGS_OK) { + ogs_log_message( + status == OGS_DONE ? OGS_LOG_DEBUG : OGS_LOG_WARN, 0, + "client_cb() failed [%d]", status); + return OGS_ERROR; + } + ogs_assert(response); e = smf_event_new(SMF_EVT_SBI_CLIENT); @@ -59,7 +67,8 @@ static int client_cb(ogs_sbi_response_t *response, void *data) rv = ogs_queue_push(ogs_app()->queue, e); if (rv != OGS_OK) { - ogs_warn("ogs_queue_push() failed:%d", (int)rv); + ogs_error("ogs_queue_push() failed:%d", (int)rv); + ogs_sbi_response_free(response); smf_event_free(e); return OGS_ERROR; } @@ -112,24 +121,10 @@ int smf_sbi_open(void) void smf_sbi_close(void) { + ogs_sbi_client_stop_all(); ogs_sbi_server_stop_all(); } -bool smf_nnrf_nfm_send_nf_register(ogs_sbi_nf_instance_t *nf_instance) -{ - ogs_sbi_request_t *request = NULL; - ogs_sbi_client_t *client = NULL; - - ogs_assert(nf_instance); - client = nf_instance->client; - ogs_assert(client); - - request = smf_nnrf_nfm_build_register(); - ogs_expect_or_return_val(request, false); - return ogs_sbi_client_send_request( - client, client->cb, request, nf_instance); -} - bool smf_sbi_send(ogs_sbi_nf_instance_t *nf_instance, ogs_sbi_xact_t *xact) { return ogs_sbi_send(nf_instance, client_cb, xact); @@ -388,12 +383,19 @@ void smf_sbi_send_sm_context_update_error( ogs_pkbuf_free(n2smbuf); } -static int client_notify_cb(ogs_sbi_response_t *response, void *data) +static int client_notify_cb( + int status, ogs_sbi_response_t *response, void *data) { int rv; - ogs_sbi_message_t message; + if (status != OGS_OK) { + ogs_log_message( + status == OGS_DONE ? OGS_LOG_DEBUG : OGS_LOG_WARN, 0, + "client_notify_cb() failed [%d]", status); + return OGS_ERROR; + } + ogs_assert(response); rv = ogs_sbi_parse_response(&message, response); diff --git a/src/smf/sbi-path.h b/src/smf/sbi-path.h index 333dde30a..0de2b6324 100644 --- a/src/smf/sbi-path.h +++ b/src/smf/sbi-path.h @@ -34,8 +34,6 @@ extern "C" { int smf_sbi_open(void); void smf_sbi_close(void); -bool smf_nnrf_nfm_send_nf_register(ogs_sbi_nf_instance_t *nf_instance); - bool smf_sbi_send(ogs_sbi_nf_instance_t *nf_instance, ogs_sbi_xact_t *xact); bool smf_sbi_discover_and_send(OpenAPI_nf_type_e target_nf_type, diff --git a/src/smf/timer.c b/src/smf/timer.c index b25ac204c..1e475396d 100644 --- a/src/smf/timer.c +++ b/src/smf/timer.c @@ -92,7 +92,7 @@ static void timer_send_event(int timer_id, void *data) rv = ogs_queue_push(ogs_app()->queue, e); if (rv != OGS_OK) { - ogs_warn("ogs_queue_push() failed [%d] in %s", + ogs_error("ogs_queue_push() failed [%d] in %s", (int)rv, smf_timer_get_name(e->timer_id)); smf_event_free(e); } diff --git a/src/udm/init.c b/src/udm/init.c index f64f08538..f48f26804 100644 --- a/src/udm/init.c +++ b/src/udm/init.c @@ -32,7 +32,7 @@ int udm_initialize() udm_context_init(); udm_event_init(); - rv = ogs_sbi_context_parse_config("udm", "nrf"); + rv = ogs_sbi_context_parse_config("udm", "nrf", "scp"); if (rv != OGS_OK) return rv; rv = udm_context_parse_config(); diff --git a/src/udm/nf-sm.c b/src/udm/nf-sm.c index 9aff494b4..6172fc558 100644 --- a/src/udm/nf-sm.c +++ b/src/udm/nf-sm.c @@ -61,16 +61,18 @@ void udm_nf_state_initial(ogs_fsm_t *s, udm_event_t *e) nf_instance = e->sbi.data; ogs_assert(nf_instance); + nf_instance->t_registration_interval = ogs_timer_add(ogs_app()->timer_mgr, + udm_timer_nf_instance_registration_interval, nf_instance); ogs_assert(nf_instance->t_registration_interval); - nf_instance->t_registration_interval->cb = - udm_timer_nf_instance_registration_interval; + nf_instance->t_heartbeat_interval = ogs_timer_add(ogs_app()->timer_mgr, + udm_timer_nf_instance_heartbeat_interval, nf_instance); ogs_assert(nf_instance->t_heartbeat_interval); - nf_instance->t_heartbeat_interval->cb = - udm_timer_nf_instance_heartbeat_interval; + nf_instance->t_no_heartbeat = ogs_timer_add(ogs_app()->timer_mgr, + udm_timer_nf_instance_no_heartbeat, nf_instance); ogs_assert(nf_instance->t_no_heartbeat); - nf_instance->t_no_heartbeat->cb = udm_timer_nf_instance_no_heartbeat; + nf_instance->t_validity = ogs_timer_add(ogs_app()->timer_mgr, + udm_timer_nf_instance_validity, nf_instance); ogs_assert(nf_instance->t_validity); - nf_instance->t_validity->cb = udm_timer_nf_instance_validity; if (NF_INSTANCE_IS_NRF(nf_instance)) { OGS_FSM_TRAN(s, &udm_nf_state_will_register); @@ -82,10 +84,20 @@ void udm_nf_state_initial(ogs_fsm_t *s, udm_event_t *e) void udm_nf_state_final(ogs_fsm_t *s, udm_event_t *e) { + ogs_sbi_nf_instance_t *nf_instance = NULL; + ogs_assert(s); ogs_assert(e); udm_sm_debug(e); + + nf_instance = e->sbi.data; + ogs_assert(nf_instance); + + ogs_timer_delete(nf_instance->t_registration_interval); + ogs_timer_delete(nf_instance->t_heartbeat_interval); + ogs_timer_delete(nf_instance->t_no_heartbeat); + ogs_timer_delete(nf_instance->t_validity); } void udm_nf_state_will_register(ogs_fsm_t *s, udm_event_t *e) @@ -110,7 +122,8 @@ void udm_nf_state_will_register(ogs_fsm_t *s, udm_event_t *e) ogs_timer_start(nf_instance->t_registration_interval, ogs_app()->time.message.sbi.nf_register_interval); - ogs_assert(true == udm_nnrf_nfm_send_nf_register(nf_instance)); + ogs_assert(true == ogs_nnrf_nfm_send_nf_register( + nf_instance, udm_nnrf_nfm_build_register)); break; case OGS_FSM_EXIT_SIG: @@ -166,7 +179,8 @@ void udm_nf_state_will_register(ogs_fsm_t *s, udm_event_t *e) ogs_timer_start(nf_instance->t_registration_interval, ogs_app()->time.message.sbi.nf_register_interval); - ogs_assert(true == udm_nnrf_nfm_send_nf_register(nf_instance)); + ogs_assert(true == ogs_nnrf_nfm_send_nf_register( + nf_instance, udm_nnrf_nfm_build_register)); break; default: diff --git a/src/udm/sbi-path.c b/src/udm/sbi-path.c index b12f054f2..83cc9f3b0 100644 --- a/src/udm/sbi-path.c +++ b/src/udm/sbi-path.c @@ -35,7 +35,8 @@ static int server_cb(ogs_sbi_request_t *request, void *data) rv = ogs_queue_push(ogs_app()->queue, e); if (rv != OGS_OK) { - ogs_warn("ogs_queue_push() failed:%d", (int)rv); + ogs_error("ogs_queue_push() failed:%d", (int)rv); + ogs_sbi_request_free(request); udm_event_free(e); return OGS_ERROR; } @@ -43,11 +44,18 @@ static int server_cb(ogs_sbi_request_t *request, void *data) return OGS_OK; } -static int client_cb(ogs_sbi_response_t *response, void *data) +static int client_cb(int status, ogs_sbi_response_t *response, void *data) { udm_event_t *e = NULL; int rv; + if (status != OGS_OK) { + ogs_log_message( + status == OGS_DONE ? OGS_LOG_DEBUG : OGS_LOG_WARN, 0, + "client_cb() failed [%d]", status); + return OGS_ERROR; + } + ogs_assert(response); e = udm_event_new(UDM_EVT_SBI_CLIENT); @@ -57,7 +65,8 @@ static int client_cb(ogs_sbi_response_t *response, void *data) rv = ogs_queue_push(ogs_app()->queue, e); if (rv != OGS_OK) { - ogs_warn("ogs_queue_push() failed:%d", (int)rv); + ogs_error("ogs_queue_push() failed:%d", (int)rv); + ogs_sbi_response_free(response); udm_event_free(e); return OGS_ERROR; } @@ -125,24 +134,10 @@ int udm_sbi_open(void) void udm_sbi_close(void) { + ogs_sbi_client_stop_all(); ogs_sbi_server_stop_all(); } -bool udm_nnrf_nfm_send_nf_register(ogs_sbi_nf_instance_t *nf_instance) -{ - ogs_sbi_request_t *request = NULL; - ogs_sbi_client_t *client = NULL; - - ogs_assert(nf_instance); - client = nf_instance->client; - ogs_assert(client); - - request = udm_nnrf_nfm_build_register(); - ogs_expect_or_return_val(request, false); - return ogs_sbi_client_send_request( - client, client->cb, request, nf_instance); -} - bool udm_sbi_send(ogs_sbi_nf_instance_t *nf_instance, ogs_sbi_xact_t *xact) { return ogs_sbi_send(nf_instance, client_cb, xact); diff --git a/src/udm/sbi-path.h b/src/udm/sbi-path.h index 984d12bb4..32252ca6f 100644 --- a/src/udm/sbi-path.h +++ b/src/udm/sbi-path.h @@ -30,8 +30,6 @@ extern "C" { int udm_sbi_open(void); void udm_sbi_close(void); -bool udm_nnrf_nfm_send_nf_register(ogs_sbi_nf_instance_t *nf_instance); - bool udm_sbi_send(ogs_sbi_nf_instance_t *nf_instance, ogs_sbi_xact_t *xact); bool udm_sbi_discover_and_send(OpenAPI_nf_type_e target_nf_type, udm_ue_t *udm_ue, ogs_sbi_stream_t *stream, void *data, diff --git a/src/udm/timer.c b/src/udm/timer.c index d4fc33188..95a9d5216 100644 --- a/src/udm/timer.c +++ b/src/udm/timer.c @@ -79,7 +79,7 @@ static void sbi_timer_send_event(int timer_id, void *data) rv = ogs_queue_push(ogs_app()->queue, e); if (rv != OGS_OK) { - ogs_warn("ogs_queue_push() failed [%d] in %s", + ogs_error("ogs_queue_push() failed [%d] in %s", (int)rv, udm_timer_get_name(e->timer_id)); udm_event_free(e); } diff --git a/src/udr/init.c b/src/udr/init.c index d61b237ba..fd1a08388 100644 --- a/src/udr/init.c +++ b/src/udr/init.c @@ -32,7 +32,7 @@ int udr_initialize() udr_context_init(); udr_event_init(); - rv = ogs_sbi_context_parse_config("udr", "nrf"); + rv = ogs_sbi_context_parse_config("udr", "nrf", "scp"); if (rv != OGS_OK) return rv; rv = udr_context_parse_config(); diff --git a/src/udr/nf-sm.c b/src/udr/nf-sm.c index 15a96a613..4c760a96f 100644 --- a/src/udr/nf-sm.c +++ b/src/udr/nf-sm.c @@ -61,16 +61,18 @@ void udr_nf_state_initial(ogs_fsm_t *s, udr_event_t *e) nf_instance = e->sbi.data; ogs_assert(nf_instance); + nf_instance->t_registration_interval = ogs_timer_add(ogs_app()->timer_mgr, + udr_timer_nf_instance_registration_interval, nf_instance); ogs_assert(nf_instance->t_registration_interval); - nf_instance->t_registration_interval->cb = - udr_timer_nf_instance_registration_interval; + nf_instance->t_heartbeat_interval = ogs_timer_add(ogs_app()->timer_mgr, + udr_timer_nf_instance_heartbeat_interval, nf_instance); ogs_assert(nf_instance->t_heartbeat_interval); - nf_instance->t_heartbeat_interval->cb = - udr_timer_nf_instance_heartbeat_interval; + nf_instance->t_no_heartbeat = ogs_timer_add(ogs_app()->timer_mgr, + udr_timer_nf_instance_no_heartbeat, nf_instance); ogs_assert(nf_instance->t_no_heartbeat); - nf_instance->t_no_heartbeat->cb = udr_timer_nf_instance_no_heartbeat; + nf_instance->t_validity = ogs_timer_add(ogs_app()->timer_mgr, + udr_timer_nf_instance_validity, nf_instance); ogs_assert(nf_instance->t_validity); - nf_instance->t_validity->cb = udr_timer_nf_instance_validity; if (NF_INSTANCE_IS_NRF(nf_instance)) { OGS_FSM_TRAN(s, &udr_nf_state_will_register); @@ -82,10 +84,20 @@ void udr_nf_state_initial(ogs_fsm_t *s, udr_event_t *e) void udr_nf_state_final(ogs_fsm_t *s, udr_event_t *e) { + ogs_sbi_nf_instance_t *nf_instance = NULL; + ogs_assert(s); ogs_assert(e); udr_sm_debug(e); + + nf_instance = e->sbi.data; + ogs_assert(nf_instance); + + ogs_timer_delete(nf_instance->t_registration_interval); + ogs_timer_delete(nf_instance->t_heartbeat_interval); + ogs_timer_delete(nf_instance->t_no_heartbeat); + ogs_timer_delete(nf_instance->t_validity); } void udr_nf_state_will_register(ogs_fsm_t *s, udr_event_t *e) @@ -110,7 +122,8 @@ void udr_nf_state_will_register(ogs_fsm_t *s, udr_event_t *e) ogs_timer_start(nf_instance->t_registration_interval, ogs_app()->time.message.sbi.nf_register_interval); - ogs_assert(true == udr_nnrf_nfm_send_nf_register(nf_instance)); + ogs_assert(true == ogs_nnrf_nfm_send_nf_register( + nf_instance, udr_nnrf_nfm_build_register)); break; case OGS_FSM_EXIT_SIG: @@ -166,7 +179,8 @@ void udr_nf_state_will_register(ogs_fsm_t *s, udr_event_t *e) ogs_timer_start(nf_instance->t_registration_interval, ogs_app()->time.message.sbi.nf_register_interval); - ogs_assert(true == udr_nnrf_nfm_send_nf_register(nf_instance)); + ogs_assert(true == ogs_nnrf_nfm_send_nf_register( + nf_instance, udr_nnrf_nfm_build_register)); break; default: diff --git a/src/udr/sbi-path.c b/src/udr/sbi-path.c index 9b559ac6a..d4bce2155 100644 --- a/src/udr/sbi-path.c +++ b/src/udr/sbi-path.c @@ -35,7 +35,8 @@ static int server_cb(ogs_sbi_request_t *request, void *data) rv = ogs_queue_push(ogs_app()->queue, e); if (rv != OGS_OK) { - ogs_warn("ogs_queue_push() failed:%d", (int)rv); + ogs_error("ogs_queue_push() failed:%d", (int)rv); + ogs_sbi_request_free(request); udr_event_free(e); return OGS_ERROR; } @@ -43,11 +44,18 @@ static int server_cb(ogs_sbi_request_t *request, void *data) return OGS_OK; } -static int client_cb(ogs_sbi_response_t *response, void *data) +static int client_cb(int status, ogs_sbi_response_t *response, void *data) { udr_event_t *e = NULL; int rv; + if (status != OGS_OK) { + ogs_log_message( + status == OGS_DONE ? OGS_LOG_DEBUG : OGS_LOG_WARN, 0, + "client_cb() failed [%d]", status); + return OGS_ERROR; + } + ogs_assert(response); e = udr_event_new(UDR_EVT_SBI_CLIENT); @@ -57,7 +65,8 @@ static int client_cb(ogs_sbi_response_t *response, void *data) rv = ogs_queue_push(ogs_app()->queue, e); if (rv != OGS_OK) { - ogs_warn("ogs_queue_push() failed:%d", (int)rv); + ogs_error("ogs_queue_push() failed:%d", (int)rv); + ogs_sbi_response_free(response); udr_event_free(e); return OGS_ERROR; } @@ -112,19 +121,6 @@ int udr_sbi_open(void) void udr_sbi_close(void) { + ogs_sbi_client_stop_all(); ogs_sbi_server_stop_all(); } - -bool udr_nnrf_nfm_send_nf_register(ogs_sbi_nf_instance_t *nf_instance) -{ - ogs_sbi_request_t *request = NULL; - ogs_sbi_client_t *client = NULL; - - ogs_assert(nf_instance); - client = nf_instance->client; - ogs_assert(client); - - request = udr_nnrf_nfm_build_register(); - ogs_expect_or_return_val(request, false); - return ogs_sbi_client_send_request(client, client->cb, request, nf_instance); -} diff --git a/src/udr/sbi-path.h b/src/udr/sbi-path.h index 16dfa33f7..f0a0e29f3 100644 --- a/src/udr/sbi-path.h +++ b/src/udr/sbi-path.h @@ -29,8 +29,6 @@ extern "C" { int udr_sbi_open(void); void udr_sbi_close(void); -bool udr_nnrf_nfm_send_nf_register(ogs_sbi_nf_instance_t *nf_instance); - #ifdef __cplusplus } #endif diff --git a/src/udr/timer.c b/src/udr/timer.c index 1a1d802a9..f567ba0b0 100644 --- a/src/udr/timer.c +++ b/src/udr/timer.c @@ -64,7 +64,7 @@ static void sbi_timer_send_event(int timer_id, void *data) rv = ogs_queue_push(ogs_app()->queue, e); if (rv != OGS_OK) { - ogs_warn("ogs_queue_push() failed [%d] in %s", + ogs_error("ogs_queue_push() failed [%d] in %s", (int)rv, udr_timer_get_name(e->timer_id)); udr_event_free(e); } diff --git a/src/upf/pfcp-path.c b/src/upf/pfcp-path.c index 184164534..4888d1627 100644 --- a/src/upf/pfcp-path.c +++ b/src/upf/pfcp-path.c @@ -120,7 +120,7 @@ static void pfcp_recv_cb(short when, ogs_socket_t fd, void *data) rv = ogs_queue_push(ogs_app()->queue, e); if (rv != OGS_OK) { - ogs_warn("ogs_queue_push() failed:%d", (int)rv); + ogs_error("ogs_queue_push() failed:%d", (int)rv); ogs_pkbuf_free(e->pkbuf); upf_event_free(e); } diff --git a/src/upf/pfcp-sm.c b/src/upf/pfcp-sm.c index 6f890d392..c4c3e10fe 100644 --- a/src/upf/pfcp-sm.c +++ b/src/upf/pfcp-sm.c @@ -300,7 +300,7 @@ static void node_timeout(ogs_pfcp_xact_t *xact, void *data) rv = ogs_queue_push(ogs_app()->queue, e); if (rv != OGS_OK) { - ogs_warn("ogs_queue_push() failed:%d", (int)rv); + ogs_error("ogs_queue_push() failed:%d", (int)rv); upf_event_free(e); } break; diff --git a/src/upf/timer.c b/src/upf/timer.c index 9ebcee565..442bdb534 100644 --- a/src/upf/timer.c +++ b/src/upf/timer.c @@ -47,7 +47,7 @@ static void timer_send_event(int timer_id, void *data) rv = ogs_queue_push(ogs_app()->queue, e); if (rv != OGS_OK) { - ogs_warn("ogs_queue_push() failed:%d", (int)rv); + ogs_error("ogs_queue_push() failed:%d", (int)rv); upf_event_free(e); } } diff --git a/tests/af/init.c b/tests/af/init.c index aaa64ffcb..9fafca223 100644 --- a/tests/af/init.c +++ b/tests/af/init.c @@ -34,7 +34,7 @@ int af_initialize() af_context_init(); af_event_init(); - rv = ogs_sbi_context_parse_config("af", "nrf"); + rv = ogs_sbi_context_parse_config("af", "nrf", "scp"); if (rv != OGS_OK) return rv; rv = af_context_parse_config(); diff --git a/tests/af/local.c b/tests/af/local.c index 5c56d9c68..9e7fd0e97 100644 --- a/tests/af/local.c +++ b/tests/af/local.c @@ -50,7 +50,7 @@ void af_local_discover_and_send(OpenAPI_nf_type_e target_nf_type, rv = ogs_queue_push(ogs_app()->queue, e); if (rv != OGS_OK) { - ogs_warn("ogs_queue_push() failed [%d] in %s", + ogs_error("ogs_queue_push() failed [%d] in %s", (int)rv, af_timer_get_name(e->timer_id)); af_event_free(e); } else { @@ -76,7 +76,7 @@ void af_local_send_to_pcf( rv = ogs_queue_push(ogs_app()->queue, e); if (rv != OGS_OK) { - ogs_warn("ogs_queue_push() failed [%d] in %s", + ogs_error("ogs_queue_push() failed [%d] in %s", (int)rv, af_timer_get_name(e->timer_id)); af_event_free(e); } else { diff --git a/tests/af/nf-sm.c b/tests/af/nf-sm.c index 5096902f7..6fc9daefb 100644 --- a/tests/af/nf-sm.c +++ b/tests/af/nf-sm.c @@ -61,16 +61,18 @@ void af_nf_state_initial(ogs_fsm_t *s, af_event_t *e) nf_instance = e->sbi.data; ogs_assert(nf_instance); + nf_instance->t_registration_interval = ogs_timer_add(ogs_app()->timer_mgr, + af_timer_nf_instance_registration_interval, nf_instance); ogs_assert(nf_instance->t_registration_interval); - nf_instance->t_registration_interval->cb = - af_timer_nf_instance_registration_interval; + nf_instance->t_heartbeat_interval = ogs_timer_add(ogs_app()->timer_mgr, + af_timer_nf_instance_heartbeat_interval, nf_instance); ogs_assert(nf_instance->t_heartbeat_interval); - nf_instance->t_heartbeat_interval->cb = - af_timer_nf_instance_heartbeat_interval; + nf_instance->t_no_heartbeat = ogs_timer_add(ogs_app()->timer_mgr, + af_timer_nf_instance_no_heartbeat, nf_instance); ogs_assert(nf_instance->t_no_heartbeat); - nf_instance->t_no_heartbeat->cb = af_timer_nf_instance_no_heartbeat; + nf_instance->t_validity = ogs_timer_add(ogs_app()->timer_mgr, + af_timer_nf_instance_validity, nf_instance); ogs_assert(nf_instance->t_validity); - nf_instance->t_validity->cb = af_timer_nf_instance_validity; if (NF_INSTANCE_IS_NRF(nf_instance)) { OGS_FSM_TRAN(s, &af_nf_state_will_register); @@ -82,10 +84,20 @@ void af_nf_state_initial(ogs_fsm_t *s, af_event_t *e) void af_nf_state_final(ogs_fsm_t *s, af_event_t *e) { + ogs_sbi_nf_instance_t *nf_instance = NULL; + ogs_assert(s); ogs_assert(e); af_sm_debug(e); + + nf_instance = e->sbi.data; + ogs_assert(nf_instance); + + ogs_timer_delete(nf_instance->t_registration_interval); + ogs_timer_delete(nf_instance->t_heartbeat_interval); + ogs_timer_delete(nf_instance->t_no_heartbeat); + ogs_timer_delete(nf_instance->t_validity); } void af_nf_state_will_register(ogs_fsm_t *s, af_event_t *e) diff --git a/tests/af/sbi-path.c b/tests/af/sbi-path.c index ec4901833..6a81d652b 100644 --- a/tests/af/sbi-path.c +++ b/tests/af/sbi-path.c @@ -35,7 +35,8 @@ static int server_cb(ogs_sbi_request_t *request, void *data) rv = ogs_queue_push(ogs_app()->queue, e); if (rv != OGS_OK) { - ogs_warn("ogs_queue_push() failed:%d", (int)rv); + ogs_error("ogs_queue_push() failed:%d", (int)rv); + ogs_sbi_request_free(request); af_event_free(e); return OGS_ERROR; } @@ -43,11 +44,18 @@ static int server_cb(ogs_sbi_request_t *request, void *data) return OGS_OK; } -static int client_cb(ogs_sbi_response_t *response, void *data) +static int client_cb(int status, ogs_sbi_response_t *response, void *data) { af_event_t *e = NULL; int rv; + if (status != OGS_OK) { + ogs_log_message( + status == OGS_DONE ? OGS_LOG_DEBUG : OGS_LOG_WARN, 0, + "client_cb() failed [%d]", status); + return OGS_ERROR; + } + ogs_assert(response); e = af_event_new(AF_EVT_SBI_CLIENT); @@ -57,7 +65,8 @@ static int client_cb(ogs_sbi_response_t *response, void *data) rv = ogs_queue_push(ogs_app()->queue, e); if (rv != OGS_OK) { - ogs_warn("ogs_queue_push() failed:%d", (int)rv); + ogs_error("ogs_queue_push() failed:%d", (int)rv); + ogs_sbi_response_free(response); af_event_free(e); return OGS_ERROR; } @@ -108,6 +117,7 @@ int af_sbi_open(void) void af_sbi_close(void) { + ogs_sbi_client_stop_all(); ogs_sbi_server_stop_all(); } diff --git a/tests/af/timer.c b/tests/af/timer.c index 3a0fd038e..de25eee47 100644 --- a/tests/af/timer.c +++ b/tests/af/timer.c @@ -79,7 +79,7 @@ static void timer_send_event(int timer_id, void *data) rv = ogs_queue_push(ogs_app()->queue, e); if (rv != OGS_OK) { - ogs_warn("ogs_queue_push() failed [%d] in %s", + ogs_error("ogs_queue_push() failed [%d] in %s", (int)rv, af_timer_get_name(e->timer_id)); af_event_free(e); } diff --git a/tests/app/5gc-init.c b/tests/app/5gc-init.c index 0b8158f1e..b1ad017ac 100644 --- a/tests/app/5gc-init.c +++ b/tests/app/5gc-init.c @@ -20,6 +20,7 @@ #include "test-app.h" static ogs_thread_t *nrf_thread = NULL; +static ogs_thread_t *scp_thread = NULL; static ogs_thread_t *upf_thread = NULL; static ogs_thread_t *smf_thread = NULL; static ogs_thread_t *amf_thread = NULL; @@ -52,6 +53,8 @@ int app_initialize(const char *const argv[]) if (ogs_app()->parameter.no_nrf == 0) nrf_thread = test_child_create("nrf", argv_out); + if (ogs_app()->parameter.no_scp == 0) + scp_thread = test_child_create("scp", argv_out); if (ogs_app()->parameter.no_upf == 0) upf_thread = test_child_create("upf", argv_out); @@ -98,6 +101,7 @@ void app_terminate(void) if (udm_thread) ogs_thread_destroy(udm_thread); if (ausf_thread) ogs_thread_destroy(ausf_thread); + if (scp_thread) ogs_thread_destroy(scp_thread); if (nrf_thread) ogs_thread_destroy(nrf_thread); } diff --git a/tests/app/app-init.c b/tests/app/app-init.c index 623c3f732..b09a7fbfe 100644 --- a/tests/app/app-init.c +++ b/tests/app/app-init.c @@ -20,6 +20,7 @@ #include "test-app.h" static ogs_thread_t *nrf_thread = NULL; +static ogs_thread_t *scp_thread = NULL; static ogs_thread_t *pcrf_thread = NULL; static ogs_thread_t *hss_thread = NULL; static ogs_thread_t *upf_thread = NULL; @@ -57,6 +58,8 @@ int app_initialize(const char *const argv[]) if (ogs_app()->parameter.no_nrf == 0) nrf_thread = test_child_create("nrf", argv_out); + if (ogs_app()->parameter.no_scp == 0) + scp_thread = test_child_create("scp", argv_out); if (ogs_app()->parameter.no_hss == 0) hss_thread = test_child_create("hss", argv_out); if (ogs_app()->parameter.no_pcrf == 0) @@ -120,6 +123,7 @@ void app_terminate(void) if (hss_thread) ogs_thread_destroy(hss_thread); if (pcrf_thread) ogs_thread_destroy(pcrf_thread); + if (scp_thread) ogs_thread_destroy(scp_thread); if (nrf_thread) ogs_thread_destroy(nrf_thread); }