[SCP] Support of Indirect Communication

This commit is contained in:
Sukchan Lee 2022-07-16 13:27:18 +09:00
parent 1518a4f334
commit 5e18b2bd13
128 changed files with 4284 additions and 777 deletions

View File

@ -4,6 +4,7 @@ logger:
parameter: parameter:
# no_nrf: true # no_nrf: true
# no_scp: true
# no_amf: true # no_amf: true
# no_smf: true # no_smf: true
# no_upf: true # no_upf: true
@ -194,6 +195,11 @@ nrf:
- ::1 - ::1
port: 7777 port: 7777
scp:
sbi:
- addr: 127.0.1.10
port: 7777
ausf: ausf:
sbi: sbi:
- addr: 127.0.0.11 - addr: 127.0.0.11

View File

@ -4,6 +4,7 @@ logger:
parameter: parameter:
# no_nrf: true # no_nrf: true
# no_scp: true
# no_amf: true # no_amf: true
# no_smf: true # no_smf: true
# no_upf: true # no_upf: true

View File

@ -4,6 +4,7 @@ logger:
parameter: parameter:
# no_nrf: true # no_nrf: true
# no_scp: true
# no_amf: true # no_amf: true
# no_smf: true # no_smf: true
# no_upf: true # no_upf: true

View File

@ -29,6 +29,7 @@ open5gs_conf = '''
hss.yaml hss.yaml
pcrf.yaml pcrf.yaml
nrf.yaml nrf.yaml
scp.yaml
ausf.yaml ausf.yaml
udm.yaml udm.yaml
udr.yaml udr.yaml

213
configs/open5gs/scp.yaml.in Normal file
View File

@ -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:
#
# <SBI Server>
#
# o SBI Server(http://<all address available>:80)
# sbi:
#
# o SBI Server(http://<any address>:80)
# sbi:
# - addr:
# - 0.0.0.0
# - ::0
# port: 7777
#
# o SBI Server(https://<all address avaiable>: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://<eth0 IP address>: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
#
# <Next hop SCP>
#
# o Next hop SCP Server(https://127.0.1.11:7777)
# next_scp:
# sbi:
# - addr: 127.0.1.11
# port: 7777
#
# <Discovery>
#
# 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:
#
# <SBI Client>>
#
# 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:

View File

@ -4,6 +4,7 @@ logger:
parameter: parameter:
# no_nrf: true # no_nrf: true
# no_scp: true
# no_amf: true # no_amf: true
# no_smf: true # no_smf: true
# no_upf: true # no_upf: true
@ -194,6 +195,70 @@ nrf:
- ::1 - ::1
port: 7777 port: 7777
#
# scp:
#
# <SBI Client>>
#
# 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
#
# <Discovery>
#
# 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: ausf:
sbi: sbi:
- addr: 127.0.0.11 - addr: 127.0.0.11

View File

@ -4,6 +4,7 @@ logger:
parameter: parameter:
# no_nrf: true # no_nrf: true
no_scp: true
# no_amf: true # no_amf: true
# no_smf: true # no_smf: true
# no_upf: true # no_upf: true

View File

@ -4,6 +4,7 @@ logger:
parameter: parameter:
# no_nrf: true # no_nrf: true
# no_scp: true
# no_amf: true # no_amf: true
# no_smf: true # no_smf: true
# no_upf: true # no_upf: true

View File

@ -4,6 +4,7 @@ logger:
parameter: parameter:
# no_nrf: true # no_nrf: true
# no_scp: true
# no_amf: true # no_amf: true
# no_smf: true # no_smf: true
# no_upf: true # no_upf: true

View File

@ -4,6 +4,7 @@ logger:
parameter: parameter:
# no_nrf: true # no_nrf: true
# no_scp: true
# no_amf: true # no_amf: true
# no_smf: true # no_smf: true
# no_upf: true # no_upf: true
@ -199,6 +200,11 @@ nrf:
- ::1 - ::1
port: 7777 port: 7777
scp:
sbi:
- addr: 127.0.1.10
port: 7777
ausf: ausf:
sbi: sbi:
- addr: 127.0.0.11 - addr: 127.0.0.11

View File

@ -94,6 +94,9 @@ void smf_terminate(void);
int amf_initialize(void); int amf_initialize(void);
void amf_terminate(void); void amf_terminate(void);
int scp_initialize(void);
void scp_terminate(void);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View File

@ -113,7 +113,7 @@ static void regenerate_all_timer_duration(void)
ogs_max(ogs_time_from_sec(3), ogs_max(ogs_time_from_sec(3),
self.time.message.sbi.client_wait_duration + ogs_time_from_sec(1)); self.time.message.sbi.client_wait_duration + ogs_time_from_sec(1));
self.time.message.sbi.nf_register_interval_in_exception = 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 #define PFCP_N1_RESPONSE_RETRY_COUNT 3
self.time.message.pfcp.n1_response_rcount = PFCP_N1_RESPONSE_RETRY_COUNT; 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")) { } else if (!strcmp(parameter_key, "no_nrf")) {
self.parameter.no_nrf = self.parameter.no_nrf =
ogs_yaml_iter_bool(&parameter_iter); ogs_yaml_iter_bool(&parameter_iter);
} else if (!strcmp(parameter_key, "no_scp")) {
self.parameter.no_scp =
ogs_yaml_iter_bool(&parameter_iter);
} else if (!strcmp(parameter_key, "no_amf")) { } else if (!strcmp(parameter_key, "no_amf")) {
self.parameter.no_amf = self.parameter.no_amf =
ogs_yaml_iter_bool(&parameter_iter); ogs_yaml_iter_bool(&parameter_iter);

View File

@ -64,6 +64,7 @@ typedef struct ogs_app_context_s {
int no_nssf; int no_nssf;
int no_bsf; int no_bsf;
int no_udr; int no_udr;
int no_scp;
int no_nrf; int no_nrf;
/* Network */ /* Network */

View File

@ -176,6 +176,26 @@ ogs_sbi_client_t *ogs_sbi_client_find(ogs_sockaddr_t *addr)
return client; 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) \ #define mycase(code) \
case code: s = OGS_STRINGIFY(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; return uri;
} }
static void _connection_remove(connection_t *conn);
static connection_t *connection_add( static connection_t *connection_add(
ogs_sbi_client_t *client, ogs_sbi_client_cb_f client_cb, ogs_sbi_client_t *client, ogs_sbi_client_cb_f client_cb,
ogs_sbi_request_t *request, void *data) ogs_sbi_request_t *request, void *data)
@ -269,19 +291,31 @@ static connection_t *connection_add(
conn->data = data; conn->data = data;
conn->method = ogs_strdup(request->h.method); 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); conn->num_of_header = ogs_hash_count(request->http.headers);
if (conn->num_of_header) { if (conn->num_of_header) {
conn->headers = ogs_calloc(conn->num_of_header, sizeof(char *)); 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; for (hi = ogs_hash_first(request->http.headers), i = 0;
hi && i < conn->num_of_header; hi = ogs_hash_next(hi), i++) { hi && i < conn->num_of_header; hi = ogs_hash_next(hi), i++) {
const char *key = ogs_hash_this_key(hi); const char *key = ogs_hash_this_key(hi);
char *val = ogs_hash_this_val(hi); char *val = ogs_hash_this_val(hi);
conn->headers[i] = ogs_msprintf("%s: %s", key, val); 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 = curl_slist_append(
conn->header_list, conn->headers[i]); conn->header_list, conn->headers[i]);
} }
@ -289,9 +323,11 @@ static connection_t *connection_add(
conn->timer = ogs_timer_add( conn->timer = ogs_timer_add(
ogs_app()->timer_mgr, connection_timer_expired, conn); ogs_app()->timer_mgr, connection_timer_expired, conn);
ogs_expect_or_return_val(conn->timer, NULL); if (!conn->timer) {
ogs_error("conn->timer is NULL");
ogs_list_add(&client->connection_list, conn); _connection_remove(conn);
return NULL;
}
/* If http response is not received within deadline, /* If http response is not received within deadline,
* Open5GS will discard this request. */ * Open5GS will discard this request. */
@ -299,7 +335,23 @@ static connection_t *connection_add(
ogs_app()->time.message.sbi.connection_deadline); ogs_app()->time.message.sbi.connection_deadline);
conn->easy = curl_easy_init(); 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 */ /* HTTP Method */
if (strcmp(request->h.method, OGS_SBI_HTTP_METHOD_PUT) == 0 || if (strcmp(request->h.method, OGS_SBI_HTTP_METHOD_PUT) == 0 ||
@ -312,7 +364,11 @@ static connection_t *connection_add(
if (request->http.content) { if (request->http.content) {
conn->content = ogs_memdup( conn->content = ogs_memdup(
request->http.content, request->http.content_length); 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, curl_easy_setopt(conn->easy,
CURLOPT_POSTFIELDS, conn->content); CURLOPT_POSTFIELDS, conn->content);
curl_easy_setopt(conn->easy, curl_easy_setopt(conn->easy,
@ -336,11 +392,7 @@ static connection_t *connection_add(
CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_2_PRIOR_KNOWLEDGE); CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_2_PRIOR_KNOWLEDGE);
#endif #endif
if (ogs_hash_count(request->http.params)) { ogs_list_add(&client->connection_list, conn);
request->h.uri = add_params_to_uri(conn->easy,
request->h.uri, request->http.params);
ogs_expect_or_return_val(request->h.uri, NULL);
}
curl_easy_setopt(conn->easy, CURLOPT_URL, request->h.uri); curl_easy_setopt(conn->easy, CURLOPT_URL, request->h.uri);
@ -358,27 +410,11 @@ static connection_t *connection_add(
return conn; return conn;
} }
static void connection_remove(connection_t *conn) static void _connection_remove(connection_t *conn)
{ {
ogs_sbi_client_t *client = NULL;
int i; int i;
ogs_assert(conn); 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) if (conn->content)
ogs_free(conn->content); ogs_free(conn->content);
@ -386,19 +422,45 @@ static void connection_remove(connection_t *conn)
if (conn->location) if (conn->location)
ogs_free(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) { if (conn->num_of_header) {
for (i = 0; i < conn->num_of_header; i++) 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); ogs_free(conn->headers);
} }
curl_slist_free_all(conn->header_list); curl_slist_free_all(conn->header_list);
if (conn->memory) if (conn->method)
ogs_free(conn->memory); ogs_free(conn->method);
ogs_pool_free(&connection_pool, conn); 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) static void connection_remove_all(ogs_sbi_client_t *client)
{ {
connection_t *conn = NULL, *next_conn = NULL; connection_t *conn = NULL, *next_conn = NULL;
@ -416,6 +478,11 @@ static void connection_timer_expired(void *data)
conn = data; conn = data;
ogs_assert(conn); ogs_assert(conn);
ogs_error("Connection timer expired");
ogs_assert(conn->client_cb);
conn->client_cb(OGS_TIMEUP, NULL, conn->data);
connection_remove(conn); connection_remove(conn);
} }
@ -487,12 +554,12 @@ static void check_multi_info(ogs_sbi_client_t *client)
if (conn->location) if (conn->location)
ogs_sbi_header_set(response->http.headers, ogs_sbi_header_set(response->http.headers,
OGS_SBI_LOCATION, conn->location); OGS_SBI_LOCATION, conn->location);
ogs_assert(conn->client_cb);
conn->client_cb(response, conn->data);
} else } else
ogs_warn("[%d] %s", res, conn->error); 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); connection_remove(conn);
break; break;
default: 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_client_t *client, ogs_sbi_client_cb_f client_cb,
ogs_sbi_request_t *request, void *data) ogs_sbi_request_t *request, void *data)
{ {
@ -513,17 +580,128 @@ bool ogs_sbi_client_send_request(
if (request->h.uri == NULL) { if (request->h.uri == NULL) {
request->h.uri = ogs_sbi_client_uri(client, &request->h); 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); ogs_debug("[%s] %s", request->h.method, request->h.uri);
conn = connection_add(client, client_cb, request, data); conn = connection_add(client, client_cb, request, data);
ogs_expect_or_return_val(conn, false); 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); 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; 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) static size_t write_cb(void *contents, size_t size, size_t nmemb, void *data)
{ {
size_t realsize = 0; size_t realsize = 0;

View File

@ -53,7 +53,8 @@ extern "C" {
(__pClient)->reference_count); \ (__pClient)->reference_count); \
} while(0) } 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 { typedef struct ogs_sbi_client_s {
ogs_socknode_t node; 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); void ogs_sbi_client_remove_all(void);
ogs_sbi_client_t *ogs_sbi_client_find(ogs_sockaddr_t *addr); 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( bool ogs_sbi_client_send_request(
ogs_sbi_client_t *client, ogs_sbi_client_cb_f client_cb, ogs_sbi_client_t *client, ogs_sbi_client_cb_f client_cb,
ogs_sbi_request_t *request, void *data); 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 #ifdef __cplusplus
} }
#endif #endif

View File

@ -111,7 +111,8 @@ static int ogs_sbi_context_prepare(void)
return OGS_OK; 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 SMF is only used in 4G EPC, no SBI interface is required. */
if (strcmp(local, "smf") != 0 && if (strcmp(local, "smf") != 0 &&
@ -120,10 +121,48 @@ static int ogs_sbi_context_validation(const char *local)
return OGS_ERROR; 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; 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; int rv;
yaml_document_t *document = NULL; 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)) { } else if (nrf && !strcmp(root_key, nrf)) {
ogs_yaml_iter_t remote_iter; ogs_yaml_iter_t nrf_iter;
ogs_yaml_iter_recurse(&root_iter, &remote_iter); ogs_yaml_iter_recurse(&root_iter, &nrf_iter);
while (ogs_yaml_iter_next(&remote_iter)) { while (ogs_yaml_iter_next(&nrf_iter)) {
const char *remote_key = ogs_yaml_iter_key(&remote_iter); const char *nrf_key = ogs_yaml_iter_key(&nrf_iter);
ogs_assert(remote_key); ogs_assert(nrf_key);
if (!strcmp(remote_key, "sbi")) { if (!strcmp(nrf_key, "sbi")) {
ogs_yaml_iter_t sbi_array, sbi_iter; 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 { do {
ogs_sbi_nf_instance_t *nf_instance = NULL; ogs_sbi_nf_instance_t *nrf_instance = NULL;
ogs_sbi_client_t *client = NULL; ogs_sbi_client_t *client = NULL;
ogs_sockaddr_t *addr = NULL; ogs_sockaddr_t *addr = NULL;
int family = AF_UNSPEC; 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); client = ogs_sbi_client_add(addr);
ogs_assert(client); ogs_assert(client);
nf_instance = ogs_sbi_nf_instance_add(); ogs_sbi_self()->nrf_instance =
ogs_assert(nf_instance); nrf_instance = ogs_sbi_nf_instance_add();
ogs_assert(nrf_instance);
ogs_sbi_nf_instance_set_type( 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 (key) client->tls.key = key;
if (pem) client->tls.pem = pem; 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); 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; if (rv != OGS_OK) return rv;
return OGS_OK; return OGS_OK;
@ -515,19 +720,6 @@ ogs_sbi_nf_instance_t *ogs_sbi_nf_instance_add(void)
nf_instance->time.heartbeat_interval = nf_instance->time.heartbeat_interval =
ogs_app()->time.nf_instance.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->priority = OGS_SBI_DEFAULT_PRIORITY;
nf_instance->capacity = OGS_SBI_DEFAULT_CAPACITY; nf_instance->capacity = OGS_SBI_DEFAULT_CAPACITY;
nf_instance->load = OGS_SBI_DEFAULT_LOAD; 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_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) if (nf_instance->client)
ogs_sbi_client_remove(nf_instance->client); ogs_sbi_client_remove(nf_instance->client);

View File

@ -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_smf_info_s ogs_sbi_smf_info_t;
typedef struct ogs_sbi_nf_instance_s ogs_sbi_nf_instance_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 { 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 server_list;
ogs_list_t client_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 nf_instance_list;
ogs_list_t subscription_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; const char *content_encoding;
} ogs_sbi_context_t; } ogs_sbi_context_t;
typedef struct ogs_sbi_nf_instance_s { typedef struct ogs_sbi_nf_instance_s {
ogs_lnode_t lnode; ogs_lnode_t lnode;
ogs_fsm_t sm; /* A state machine */ ogs_fsm_t sm; /* A state machine */
ogs_timer_t *t_registration_interval; /* timer to retry ogs_timer_t *t_registration_interval; /* timer to retry
to register peer node */ to register peer node */
struct { struct {
int heartbeat_interval; int heartbeat_interval;
int validity_duration; int validity_duration;
} time; } time;
ogs_timer_t *t_heartbeat_interval; /* heartbeat interval */ ogs_timer_t *t_heartbeat_interval; /* heartbeat interval */
ogs_timer_t *t_no_heartbeat; /* check heartbeat */ ogs_timer_t *t_no_heartbeat; /* check heartbeat */
ogs_timer_t *t_validity; /* check validation */ ogs_timer_t *t_validity; /* check validation */
#define NF_INSTANCE_IS_SELF(_iD) \ #define NF_INSTANCE_IS_SELF(_iD) \
(_iD) && ogs_sbi_self()->nf_instance && \ (_iD) && ogs_sbi_self()->nf_instance && \
@ -77,7 +92,7 @@ typedef struct ogs_sbi_nf_instance_s {
#define NF_INSTANCE_IS_NRF(__nFInstance) \ #define NF_INSTANCE_IS_NRF(__nFInstance) \
((__nFInstance->nf_type) == OpenAPI_nf_type_NRF) ((__nFInstance->nf_type) == OpenAPI_nf_type_NRF)
char *id; /* NFInstanceId */ char *id; /* NFInstanceId */
OpenAPI_nf_type_e nf_type; OpenAPI_nf_type_e nf_type;
OpenAPI_nf_status_e nf_status; OpenAPI_nf_status_e nf_status;
@ -103,12 +118,12 @@ typedef struct ogs_sbi_nf_instance_s {
ogs_list_t nf_service_list; ogs_list_t nf_service_list;
void *client; /* only used in CLIENT */ void *client; /* only used in CLIENT */
unsigned int reference_count; /* reference count for memory free */ unsigned int reference_count; /* reference count for memory free */
ogs_list_t nf_info_list; 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; } ogs_sbi_nf_instance_t;
typedef struct ogs_sbi_nf_type_array_s { typedef struct ogs_sbi_nf_type_array_s {
@ -196,19 +211,19 @@ typedef struct ogs_sbi_subscription_s {
int validity_duration; int validity_duration;
} time; } time;
ogs_timer_t *t_validity; /* check validation */ ogs_timer_t *t_validity; /* check validation */
char *id; /* SubscriptionId */ char *id; /* SubscriptionId */
char *req_nf_instance_id; /* reqNfInstanceId */ char *req_nf_instance_id; /* reqNfInstanceId */
OpenAPI_nf_type_e req_nf_type; /* reqNfType */ OpenAPI_nf_type_e req_nf_type; /* reqNfType */
OpenAPI_nf_status_e nf_status; OpenAPI_nf_status_e nf_status;
char *notification_uri; char *notification_uri;
struct { struct {
OpenAPI_nf_type_e nf_type; /* nfType */ OpenAPI_nf_type_e nf_type; /* nfType */
} subscr_cond; } subscr_cond;
void *client; /* only used in SERVER */ void *client; /* only used in SERVER */
} ogs_sbi_subscription_t; } ogs_sbi_subscription_t;
typedef struct ogs_sbi_smf_info_s { 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_init(void);
void ogs_sbi_context_final(void); void ogs_sbi_context_final(void);
ogs_sbi_context_t *ogs_sbi_self(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); 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); void ogs_sbi_nf_instance_set_id(ogs_sbi_nf_instance_t *nf_instance, char *id);

View File

@ -29,7 +29,6 @@ char *ogs_uridup(bool https, ogs_sockaddr_t *addr, ogs_sbi_header_t *h)
char *hostname = NULL; char *hostname = NULL;
ogs_assert(addr); ogs_assert(addr);
ogs_assert(h);
p = uri; p = uri;
last = uri + OGS_HUGE_LEN; last = uri + OGS_HUGE_LEN;
@ -61,16 +60,18 @@ char *ogs_uridup(bool https, ogs_sockaddr_t *addr, ogs_sbi_header_t *h)
} }
/* API */ /* API */
ogs_assert(h->service.name); if (h) {
p = ogs_slprintf(p, last, "/%s", h->service.name); ogs_assert(h->service.name);
ogs_assert(h->api.version); p = ogs_slprintf(p, last, "/%s", h->service.name);
p = ogs_slprintf(p, last, "/%s", h->api.version); ogs_assert(h->api.version);
p = ogs_slprintf(p, last, "/%s", h->api.version);
/* Resource */ /* Resource */
ogs_assert(h->resource.component[0]); ogs_assert(h->resource.component[0]);
for (i = 0; i < OGS_SBI_MAX_NUM_OF_RESOURCE_COMPONENT && for (i = 0; i < OGS_SBI_MAX_NUM_OF_RESOURCE_COMPONENT &&
h->resource.component[i]; i++) h->resource.component[i]; i++)
p = ogs_slprintf(p, last, "/%s", h->resource.component[i]); p = ogs_slprintf(p, last, "/%s", h->resource.component[i]);
}
return ogs_strdup(uri); 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; bool https = false;
ogs_assert(server); ogs_assert(server);
ogs_assert(h);
if (server->tls.key && server->tls.pem) if (server->tls.key && server->tls.pem)
https = true; https = true;
@ -100,7 +100,6 @@ char *ogs_sbi_client_uri(ogs_sbi_client_t *client, ogs_sbi_header_t *h)
bool https = false; bool https = false;
ogs_assert(client); ogs_assert(client);
ogs_assert(h);
if (client->tls.key && client->tls.pem) if (client->tls.key && client->tls.pem)
https = true; 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); 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 * Returns a url-decoded version of str
* IMPORTANT: be sure to free() the returned string after use * 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; 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) char *ogs_sbi_bitrate_to_string(uint64_t bitrate, int unit)
{ {
if (unit == OGS_SBI_BITRATE_KBPS) { if (unit == OGS_SBI_BITRATE_KBPS) {

View File

@ -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_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_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_client_uri(ogs_sbi_client_t *client, ogs_sbi_header_t *h);
char *ogs_sbi_parse_uri(char *uri, const char *delim, char **saveptr); char *ogs_sbi_parse_uri(char *uri, const char *delim, char **saveptr);
ogs_sockaddr_t *ogs_sbi_getaddr_from_uri(char *uri); 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_BPS 0
#define OGS_SBI_BITRATE_KBPS 1 #define OGS_SBI_BITRATE_KBPS 1

View File

@ -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); ogs_expect_or_return_val(message->h.method, NULL);
request->h.method = ogs_strdup(message->h.method); request->h.method = ogs_strdup(message->h.method);
if (message->h.uri) { if (message->h.uri) {
ogs_expect_or_return_val(message->h.uri, NULL);
request->h.uri = ogs_strdup(message->h.uri); request->h.uri = ogs_strdup(message->h.uri);
ogs_expect_or_return_val(request->h.uri, NULL); ogs_expect_or_return_val(request->h.uri, NULL);
} else { } else {
@ -547,6 +546,11 @@ int ogs_sbi_parse_request(
for (hi = ogs_hash_first(request->http.headers); for (hi = ogs_hash_first(request->http.headers);
hi; hi = ogs_hash_next(hi)) { hi; hi = ogs_hash_next(hi)) {
/*
* <RFC 2616>
* 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)) { if (!ogs_strcasecmp(ogs_hash_this_key(hi), OGS_SBI_ACCEPT_ENCODING)) {
message->http.content_encoding = ogs_hash_this_val(hi); message->http.content_encoding = ogs_hash_this_val(hi);
} else if (!ogs_strcasecmp( } 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; struct yuarel yuarel;
char *saveptr = NULL; char *saveptr = NULL;
char *uri = NULL, *p = NULL;; char *uri = NULL, *p = NULL;
char *component = NULL; char *component = NULL;
int i = 0; int i = 0;
@ -691,6 +695,21 @@ void ogs_sbi_header_free(ogs_sbi_header_t *h)
ogs_free(h->resource.component[i]); 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) 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; int i;
ogs_assert(http); ogs_assert(http);
if (http->params) { if (http->params)
ogs_hash_index_t *hi; ogs_sbi_http_hash_free(http->params);
for (hi = ogs_hash_first(http->params); hi; hi = ogs_hash_next(hi)) {
char *key = (char *)ogs_hash_this_key(hi); if (http->headers)
char *val = ogs_hash_this_val(hi); ogs_sbi_http_hash_free(http->headers);
ogs_hash_set(http->params, key, strlen(key), NULL);
ogs_free(key);
ogs_free(val);
}
ogs_hash_destroy(http->params);
}
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) if (http->content)
ogs_free(http->content); ogs_free(http->content);

View File

@ -274,6 +274,21 @@ extern "C" {
#define OGS_SBI_APPLICATION_5GNAS_TYPE "vnd.3gpp.5gnas" #define OGS_SBI_APPLICATION_5GNAS_TYPE "vnd.3gpp.5gnas"
#define OGS_SBI_APPLICATION_NGAP_TYPE "vnd.3gpp.ngap" #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 \ #define OGS_SBI_CONTENT_JSON_TYPE \
OGS_SBI_APPLICATION_TYPE "/" OGS_SBI_APPLICATION_JSON_TYPE OGS_SBI_APPLICATION_TYPE "/" OGS_SBI_APPLICATION_JSON_TYPE
#define OGS_SBI_CONTENT_PROBLEM_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); 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_header_free(ogs_sbi_header_t *h);
void ogs_sbi_http_hash_free(ogs_hash_t *hash);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View File

@ -35,6 +35,8 @@ static int server_start(ogs_sbi_server_t *server,
int (*cb)(ogs_sbi_request_t *request, void *data)); int (*cb)(ogs_sbi_request_t *request, void *data));
static void server_stop(ogs_sbi_server_t *server); 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( static bool server_send_response(
ogs_sbi_stream_t *stream, ogs_sbi_response_t *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_start,
server_stop, server_stop,
server_send_rspmem_persistent,
server_send_response, server_send_response,
server_from_stream, server_from_stream,
}; };
@ -296,7 +300,7 @@ static void free_callback(void *cls)
} }
#endif #endif
static bool server_send_response( static bool server_send_rspmem_persistent(
ogs_sbi_stream_t *stream, ogs_sbi_response_t *response) ogs_sbi_stream_t *stream, ogs_sbi_response_t *response)
{ {
int ret; int ret;
@ -312,10 +316,14 @@ static bool server_send_response(
ogs_sbi_request_t *request = NULL; ogs_sbi_request_t *request = NULL;
ogs_sbi_session_t *sbi_sess = NULL; ogs_sbi_session_t *sbi_sess = NULL;
sbi_sess = (ogs_sbi_session_t *)stream;
ogs_assert(sbi_sess);
ogs_assert(response); 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; connection = sbi_sess->connection;
ogs_assert(connection); ogs_assert(connection);
@ -370,7 +378,6 @@ static bool server_send_response(
request = sbi_sess->request; request = sbi_sess->request;
ogs_assert(request); ogs_assert(request);
ogs_sbi_response_free(response);
session_remove(sbi_sess); session_remove(sbi_sess);
request->poll.write = ogs_pollset_add(ogs_app()->pollset, request->poll.write = ogs_pollset_add(ogs_app()->pollset,
@ -387,6 +394,20 @@ static bool server_send_response(
return true; 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) static void run(short when, ogs_socket_t fd, void *data)
{ {
struct MHD_Daemon *mhd_daemon = data; struct MHD_Daemon *mhd_daemon = data;
@ -539,19 +560,15 @@ suspend:
sbi_sess = session_add(server, request, connection); sbi_sess = session_add(server, request, connection);
ogs_assert(sbi_sess); ogs_assert(sbi_sess);
if (server->cb) { ogs_assert(server->cb);
if (server->cb(request, sbi_sess) != OGS_OK) { if (server->cb(request, sbi_sess) != OGS_OK) {
ogs_warn("server callback error"); ogs_error("server callback error");
ogs_assert(true == ogs_assert(true ==
ogs_sbi_server_send_error((ogs_sbi_stream_t *)sbi_sess, ogs_sbi_server_send_error((ogs_sbi_stream_t *)sbi_sess,
OGS_SBI_HTTP_STATUS_INTERNAL_SERVER_ERROR, NULL, OGS_SBI_HTTP_STATUS_INTERNAL_SERVER_ERROR, NULL,
"server callback error", NULL)); "server callback error", NULL));
return MHD_YES; return MHD_YES;
}
} else {
ogs_fatal("server callback is not registered");
ogs_assert_if_reached();
} }
return MHD_YES; return MHD_YES;

View File

@ -33,6 +33,8 @@ static int server_start(ogs_sbi_server_t *server,
int (*cb)(ogs_sbi_request_t *request, void *data)); int (*cb)(ogs_sbi_request_t *request, void *data));
static void server_stop(ogs_sbi_server_t *server); 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( static bool server_send_response(
ogs_sbi_stream_t *stream, ogs_sbi_response_t *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_start,
server_stop, server_stop,
server_send_rspmem_persistent,
server_send_response, server_send_response,
server_from_stream, server_from_stream,
}; };
@ -284,7 +288,7 @@ static ssize_t response_read_callback(nghttp2_session *session,
return response->http.content_length; 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_stream_t *stream, ogs_sbi_response_t *response)
{ {
ogs_sbi_session_t *sbi_sess = NULL; ogs_sbi_session_t *sbi_sess = NULL;
@ -299,11 +303,17 @@ static bool server_send_response(
char srv_version[128]; char srv_version[128];
char clen[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; sbi_sess = stream->session;
ogs_assert(sbi_sess); ogs_assert(sbi_sess);
ogs_assert(sbi_sess->session); ogs_assert(sbi_sess->session);
ogs_assert(response);
sock = sbi_sess->sock; sock = sbi_sess->sock;
ogs_assert(sock); ogs_assert(sock);
@ -375,12 +385,25 @@ static bool server_send_response(
session_remove(sbi_sess); session_remove(sbi_sess);
} }
ogs_sbi_response_free(response);
ogs_free(nva); ogs_free(nva);
return true; 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) static ogs_sbi_server_t *server_from_stream(ogs_sbi_stream_t *stream)
{ {
ogs_sbi_session_t *sbi_sess = NULL; ogs_sbi_session_t *sbi_sess = NULL;

View File

@ -68,13 +68,12 @@ bool ogs_sbi_send(ogs_sbi_nf_instance_t *nf_instance,
ogs_freeaddrinfo(addr); 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_expect_or_return_val(true ==
ogs_sbi_client_send_request( ogs_sbi_scp_send_reqmem_persistent(
client, client_cb, request, xact), false); client, client_cb, request, xact), false);
/* Prevent ogs_sbi_request_free() in ogs_sbi_xact_remove() */
xact->request = NULL;
return true; return true;
} }
@ -125,6 +124,23 @@ bool ogs_sbi_discover_and_send(ogs_sbi_xact_t *xact,
return false; 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) bool ogs_nnrf_nfm_send_nf_update(ogs_sbi_nf_instance_t *nf_instance)
{ {
ogs_sbi_request_t *request = NULL; 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(); request = ogs_nnrf_nfm_build_update();
ogs_expect_or_return_val(request, false); ogs_expect_or_return_val(request, false);
return ogs_sbi_client_send_request( return ogs_sbi_scp_send_request(client, client->cb, request, nf_instance);
client, client->cb, request, nf_instance);
} }
bool ogs_nnrf_nfm_send_nf_de_register(ogs_sbi_nf_instance_t *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(); request = ogs_nnrf_nfm_build_de_register();
ogs_expect_or_return_val(request, false); ogs_expect_or_return_val(request, false);
return ogs_sbi_client_send_request( return ogs_sbi_scp_send_request(client, client->cb, request, nf_instance);
client, client->cb, request, nf_instance);
} }
bool ogs_nnrf_nfm_send_nf_status_subscribe(ogs_sbi_client_t *client, 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); request = ogs_nnrf_nfm_build_status_subscribe(subscription);
ogs_expect_or_return_val(request, false); ogs_expect_or_return_val(request, false);
return ogs_sbi_client_send_request( return ogs_sbi_scp_send_request(
client, client->cb, request, subscription); client, client->cb, request, subscription);
} }
@ -191,13 +205,14 @@ bool ogs_nnrf_nfm_send_nf_status_unsubscribe(
ogs_sbi_client_t *client = NULL; ogs_sbi_client_t *client = NULL;
ogs_assert(subscription); ogs_assert(subscription);
client = subscription->client;
ogs_assert(client);
request = ogs_nnrf_nfm_build_status_unsubscribe(subscription); request = ogs_nnrf_nfm_build_status_unsubscribe(subscription);
ogs_expect_or_return_val(request, false); 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); 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_sbi_request_t *request = NULL;
ogs_assert(nf_instance); ogs_assert(nf_instance);
ogs_assert(nf_instance->nf_type);
client = nf_instance->client;
ogs_assert(client);
ogs_assert(ogs_sbi_self()->nf_instance); ogs_assert(ogs_sbi_self()->nf_instance);
request = ogs_nnrf_disc_build_discover( request = ogs_nnrf_disc_build_discover(
target_nf_type, ogs_sbi_self()->nf_instance->nf_type); target_nf_type, ogs_sbi_self()->nf_instance->nf_type);
ogs_expect_or_return_val(request, false); 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); return ogs_sbi_client_send_request(client, client->cb, request, data);
} }

View File

@ -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, 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); 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_update(ogs_sbi_nf_instance_t *nf_instance);
bool ogs_nnrf_nfm_send_nf_de_register(ogs_sbi_nf_instance_t *nf_instance); bool ogs_nnrf_nfm_send_nf_de_register(ogs_sbi_nf_instance_t *nf_instance);

View File

@ -133,6 +133,12 @@ void ogs_sbi_server_stop_all(void)
ogs_sbi_server_actions.stop(server); 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( bool ogs_sbi_server_send_response(
ogs_sbi_stream_t *stream, ogs_sbi_response_t *response) ogs_sbi_stream_t *stream, ogs_sbi_response_t *response)
{ {

View File

@ -53,6 +53,8 @@ typedef struct ogs_sbi_server_actions_s {
int (*cb)(ogs_sbi_request_t *request, void *data)); int (*cb)(ogs_sbi_request_t *request, void *data));
void (*stop)(ogs_sbi_server_t *server); void (*stop)(ogs_sbi_server_t *server);
bool (*send_rspmem_persistent)(
ogs_sbi_stream_t *stream, ogs_sbi_response_t *response);
bool (*send_response)( bool (*send_response)(
ogs_sbi_stream_t *stream, ogs_sbi_response_t *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)); int (*cb)(ogs_sbi_request_t *request, void *data));
void ogs_sbi_server_stop_all(void); 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( bool ogs_sbi_server_send_response(
ogs_sbi_stream_t *stream, ogs_sbi_response_t *response); ogs_sbi_stream_t *stream, ogs_sbi_response_t *response);
bool ogs_sbi_server_send_error(ogs_sbi_stream_t *stream, bool ogs_sbi_server_send_error(ogs_sbi_stream_t *stream,

View File

@ -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::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::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: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::1 dev lo
ip addr add fd69:f21d:873c:fa::2 dev lo ip addr add fd69:f21d:873c:fa::2 dev lo
ip addr add fd69:f21d:873c:fa::3 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::18 dev lo
ip addr add fd69:f21d:873c:fa::19 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:fa::20 dev lo
ip addr add fd69:f21d:873c:fb::10 dev lo
else 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.inet.ip.forwarding=1
sysctl -w net.inet6.ip6.forwarding=1 sysctl -w net.inet6.ip6.forwarding=1
ifconfig lo0 alias 127.0.0.2 netmask 255.255.255.255 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.18 netmask 255.255.255.255
ifconfig lo0 alias 127.0.0.19 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.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::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::2 prefixlen 128 2> /dev/null
ifconfig lo0 inet6 delete fd69:f21d:873c:fa::3 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::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::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: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::1 prefixlen 128
ifconfig lo0 inet6 add fd69:f21d:873c:fa::2 prefixlen 128 ifconfig lo0 inet6 add fd69:f21d:873c:fa::2 prefixlen 128
ifconfig lo0 inet6 add fd69:f21d:873c:fa::3 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::18 prefixlen 128
ifconfig lo0 inet6 add fd69:f21d:873c:fa::19 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:fa::20 prefixlen 128
ifconfig lo0 inet6 add fd69:f21d:873c:fb::10 prefixlen 128
if [ "$SYSTEM" = "Darwin" ]; then if [ "$SYSTEM" = "Darwin" ]; then
if ! test -f /etc/pf.anchors/org.open5gs; 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" sudo sh -c "echo 'nat on {en0} from 10.45.0.0/16 to any -> {en0}' > /etc/pf.anchors/org.open5gs"

View File

@ -37,6 +37,7 @@ else
ifconfig lo0 alias 127.0.0.18 netmask 255.255.255.255 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.19 netmask 255.255.255.255
ifconfig lo0 alias 127.0.0.20 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 [ "$SYSTEM" = "Darwin" ]; then
if ! test -f /etc/pf.anchors/org.open5gs; 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" sudo sh -c "echo 'nat on {en0} from 10.45.0.0/16 to any -> {en0}' > /etc/pf.anchors/org.open5gs"

View File

@ -119,7 +119,7 @@ void amf_sctp_event_push(amf_event_e id,
rv = ogs_queue_push(ogs_app()->queue, e); rv = ogs_queue_push(ogs_app()->queue, e);
if (rv != OGS_OK) { 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); ogs_free(e->ngap.addr);
if (e->pkbuf) if (e->pkbuf)
ogs_pkbuf_free(e->pkbuf); ogs_pkbuf_free(e->pkbuf);

View File

@ -35,7 +35,7 @@ int amf_initialize()
amf_context_init(); amf_context_init();
amf_event_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; if (rv != OGS_OK) return rv;
rv = ogs_metrics_context_parse_config(); rv = ogs_metrics_context_parse_config();

View File

@ -61,16 +61,18 @@ void amf_nf_state_initial(ogs_fsm_t *s, amf_event_t *e)
nf_instance = e->sbi.data; nf_instance = e->sbi.data;
ogs_assert(nf_instance); 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); ogs_assert(nf_instance->t_registration_interval);
nf_instance->t_registration_interval->cb = nf_instance->t_heartbeat_interval = ogs_timer_add(ogs_app()->timer_mgr,
amf_timer_nf_instance_registration_interval; amf_timer_nf_instance_heartbeat_interval, nf_instance);
ogs_assert(nf_instance->t_heartbeat_interval); ogs_assert(nf_instance->t_heartbeat_interval);
nf_instance->t_heartbeat_interval->cb = nf_instance->t_no_heartbeat = ogs_timer_add(ogs_app()->timer_mgr,
amf_timer_nf_instance_heartbeat_interval; amf_timer_nf_instance_no_heartbeat, nf_instance);
ogs_assert(nf_instance->t_no_heartbeat); 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); ogs_assert(nf_instance->t_validity);
nf_instance->t_validity->cb = amf_timer_nf_instance_validity;
if (NF_INSTANCE_IS_NRF(nf_instance)) { if (NF_INSTANCE_IS_NRF(nf_instance)) {
OGS_FSM_TRAN(s, &amf_nf_state_will_register); 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) 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(s);
ogs_assert(e); ogs_assert(e);
amf_sm_debug(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) 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_timer_start(nf_instance->t_registration_interval,
ogs_app()->time.message.sbi.nf_register_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; break;
case OGS_FSM_EXIT_SIG: 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_timer_start(nf_instance->t_registration_interval,
ogs_app()->time.message.sbi.nf_register_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; break;
default: default:

View File

@ -128,7 +128,7 @@ int ngap_send_to_5gsm(amf_ue_t *amf_ue, ogs_pkbuf_t *esmbuf)
e->pkbuf = esmbuf; e->pkbuf = esmbuf;
rv = ogs_queue_push(ogs_app()->queue, e); rv = ogs_queue_push(ogs_app()->queue, e);
if (rv != OGS_OK) { 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); ogs_pkbuf_free(e->pkbuf);
amf_event_free(e); amf_event_free(e);
} }
@ -214,7 +214,7 @@ int ngap_send_to_nas(ran_ue_t *ran_ue,
e->pkbuf = nasbuf; e->pkbuf = nasbuf;
rv = ogs_queue_push(ogs_app()->queue, e); rv = ogs_queue_push(ogs_app()->queue, e);
if (rv != OGS_OK) { 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); ogs_pkbuf_free(e->pkbuf);
amf_event_free(e); amf_event_free(e);
} }

View File

@ -37,7 +37,8 @@ static int server_cb(ogs_sbi_request_t *request, void *data)
rv = ogs_queue_push(ogs_app()->queue, e); rv = ogs_queue_push(ogs_app()->queue, e);
if (rv != OGS_OK) { 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); amf_event_free(e);
return OGS_ERROR; return OGS_ERROR;
} }
@ -45,11 +46,18 @@ static int server_cb(ogs_sbi_request_t *request, void *data)
return OGS_OK; 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; amf_event_t *e = NULL;
int rv; 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); ogs_assert(response);
e = amf_event_new(AMF_EVT_SBI_CLIENT); 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); rv = ogs_queue_push(ogs_app()->queue, e);
if (rv != OGS_OK) { 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); amf_event_free(e);
return OGS_ERROR; return OGS_ERROR;
} }
@ -91,20 +100,30 @@ int amf_sbi_open(void)
(char*)OGS_SBI_API_V1_0_0, NULL); (char*)OGS_SBI_API_V1_0_0, NULL);
ogs_sbi_nf_service_add_allowed_nf_type(service, OpenAPI_nf_type_SMF); 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 */ /* Initialize NRF NF Instance */
ogs_list_for_each(&ogs_sbi_self()->nf_instance_list, nf_instance) { nf_instance = ogs_sbi_self()->nrf_instance;
if (NF_INSTANCE_IS_NRF(nf_instance)) { if (nf_instance) {
ogs_sbi_client_t *client = NULL; ogs_sbi_client_t *client = NULL;
/* Client callback is only used when NF sends to NRF */ /* Client callback is only used when NF sends to NRF */
client = nf_instance->client; client = nf_instance->client;
ogs_assert(client); ogs_assert(client);
client->cb = client_cb; client->cb = client_cb;
/* NFRegister is sent and the response is received /* NFRegister is sent and the response is received
* by the above client callback. */ * by the above client callback. */
amf_nf_fsm_init(nf_instance); amf_nf_fsm_init(nf_instance);
}
} }
return OGS_OK; return OGS_OK;
@ -112,25 +131,10 @@ int amf_sbi_open(void)
void amf_sbi_close(void) void amf_sbi_close(void)
{ {
ogs_sbi_client_stop_all();
ogs_sbi_server_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) 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); 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; 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; int rv;
ogs_sbi_message_t message; ogs_sbi_message_t message;
amf_sess_t *sess = data; 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(response);
ogs_assert(sess); ogs_assert(sess);
ogs_assert(sess->sbi.type == OGS_SBI_OBJ_SESS_TYPE); 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; int rv;
ogs_sbi_message_t message; 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); ogs_assert(response);
rv = ogs_sbi_parse_response(&message, response); rv = ogs_sbi_parse_response(&message, response);

View File

@ -34,8 +34,6 @@ extern "C" {
int amf_sbi_open(void); int amf_sbi_open(void);
void amf_sbi_close(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_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, bool amf_ue_sbi_discover_and_send(OpenAPI_nf_type_e target_nf_type,
amf_ue_t *amf_ue, void *data, amf_ue_t *amf_ue, void *data,

View File

@ -109,7 +109,7 @@ void amf_timer_ng_delayed_send(void *data)
rv = ogs_queue_push(ogs_app()->queue, e); rv = ogs_queue_push(ogs_app()->queue, e);
if (rv != OGS_OK) { 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); ogs_timer_delete(e->timer);
amf_event_free(e); 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); rv = ogs_queue_push(ogs_app()->queue, e);
if (rv != OGS_OK) { 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)); (int)rv, amf_timer_get_name(e->timer_id));
amf_event_free(e); amf_event_free(e);
} }
@ -203,7 +203,7 @@ static void gmm_timer_event_send(
rv = ogs_queue_push(ogs_app()->queue, e); rv = ogs_queue_push(ogs_app()->queue, e);
if (rv != OGS_OK) { 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); 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); rv = ogs_queue_push(ogs_app()->queue, e);
if (rv != OGS_OK) { 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); amf_event_free(e);
} }
} }

View File

@ -32,7 +32,7 @@ int ausf_initialize()
ausf_context_init(); ausf_context_init();
ausf_event_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; if (rv != OGS_OK) return rv;
rv = ausf_context_parse_config(); rv = ausf_context_parse_config();

View File

@ -61,16 +61,18 @@ void ausf_nf_state_initial(ogs_fsm_t *s, ausf_event_t *e)
nf_instance = e->sbi.data; nf_instance = e->sbi.data;
ogs_assert(nf_instance); 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); ogs_assert(nf_instance->t_registration_interval);
nf_instance->t_registration_interval->cb = nf_instance->t_heartbeat_interval = ogs_timer_add(ogs_app()->timer_mgr,
ausf_timer_nf_instance_registration_interval; ausf_timer_nf_instance_heartbeat_interval, nf_instance);
ogs_assert(nf_instance->t_heartbeat_interval); ogs_assert(nf_instance->t_heartbeat_interval);
nf_instance->t_heartbeat_interval->cb = nf_instance->t_no_heartbeat = ogs_timer_add(ogs_app()->timer_mgr,
ausf_timer_nf_instance_heartbeat_interval; ausf_timer_nf_instance_no_heartbeat, nf_instance);
ogs_assert(nf_instance->t_no_heartbeat); 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); ogs_assert(nf_instance->t_validity);
nf_instance->t_validity->cb = ausf_timer_nf_instance_validity;
if (NF_INSTANCE_IS_NRF(nf_instance)) { if (NF_INSTANCE_IS_NRF(nf_instance)) {
OGS_FSM_TRAN(s, &ausf_nf_state_will_register); 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) 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(s);
ogs_assert(e); ogs_assert(e);
ausf_sm_debug(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) 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_timer_start(nf_instance->t_registration_interval,
ogs_app()->time.message.sbi.nf_register_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; break;
case OGS_FSM_EXIT_SIG: 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_timer_start(nf_instance->t_registration_interval,
ogs_app()->time.message.sbi.nf_register_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; break;
default: default:

View File

@ -35,7 +35,8 @@ static int server_cb(ogs_sbi_request_t *request, void *data)
rv = ogs_queue_push(ogs_app()->queue, e); rv = ogs_queue_push(ogs_app()->queue, e);
if (rv != OGS_OK) { 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); ausf_event_free(e);
return OGS_ERROR; return OGS_ERROR;
} }
@ -43,11 +44,18 @@ static int server_cb(ogs_sbi_request_t *request, void *data)
return OGS_OK; 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; ausf_event_t *e = NULL;
int rv; 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); ogs_assert(response);
e = ausf_event_new(AUSF_EVT_SBI_CLIENT); 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); rv = ogs_queue_push(ogs_app()->queue, e);
if (rv != OGS_OK) { 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); ausf_event_free(e);
return OGS_ERROR; return OGS_ERROR;
} }
@ -110,25 +119,10 @@ int ausf_sbi_open(void)
void ausf_sbi_close(void) void ausf_sbi_close(void)
{ {
ogs_sbi_client_stop_all();
ogs_sbi_server_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) 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); return ogs_sbi_send(nf_instance, client_cb, xact);

View File

@ -30,8 +30,6 @@ extern "C" {
int ausf_sbi_open(void); int ausf_sbi_open(void);
void ausf_sbi_close(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_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, 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, ausf_ue_t *ausf_ue, ogs_sbi_stream_t *stream, void *data,

View File

@ -79,7 +79,7 @@ static void sbi_timer_send_event(int timer_id, void *data)
rv = ogs_queue_push(ogs_app()->queue, e); rv = ogs_queue_push(ogs_app()->queue, e);
if (rv != OGS_OK) { 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)); (int)rv, ausf_timer_get_name(e->timer_id));
ausf_event_free(e); ausf_event_free(e);
} }

View File

@ -34,7 +34,7 @@ int bsf_initialize()
bsf_context_init(); bsf_context_init();
bsf_event_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; if (rv != OGS_OK) return rv;
rv = bsf_context_parse_config(); rv = bsf_context_parse_config();

View File

@ -61,16 +61,18 @@ void bsf_nf_state_initial(ogs_fsm_t *s, bsf_event_t *e)
nf_instance = e->sbi.data; nf_instance = e->sbi.data;
ogs_assert(nf_instance); 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); ogs_assert(nf_instance->t_registration_interval);
nf_instance->t_registration_interval->cb = nf_instance->t_heartbeat_interval = ogs_timer_add(ogs_app()->timer_mgr,
bsf_timer_nf_instance_registration_interval; bsf_timer_nf_instance_heartbeat_interval, nf_instance);
ogs_assert(nf_instance->t_heartbeat_interval); ogs_assert(nf_instance->t_heartbeat_interval);
nf_instance->t_heartbeat_interval->cb = nf_instance->t_no_heartbeat = ogs_timer_add(ogs_app()->timer_mgr,
bsf_timer_nf_instance_heartbeat_interval; bsf_timer_nf_instance_no_heartbeat, nf_instance);
ogs_assert(nf_instance->t_no_heartbeat); 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); ogs_assert(nf_instance->t_validity);
nf_instance->t_validity->cb = bsf_timer_nf_instance_validity;
if (NF_INSTANCE_IS_NRF(nf_instance)) { if (NF_INSTANCE_IS_NRF(nf_instance)) {
OGS_FSM_TRAN(s, &bsf_nf_state_will_register); 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) 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(s);
ogs_assert(e); ogs_assert(e);
bsf_sm_debug(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) 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_timer_start(nf_instance->t_registration_interval,
ogs_app()->time.message.sbi.nf_register_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; break;
case OGS_FSM_EXIT_SIG: 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_timer_start(nf_instance->t_registration_interval,
ogs_app()->time.message.sbi.nf_register_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; break;
default: default:

View File

@ -35,7 +35,8 @@ static int server_cb(ogs_sbi_request_t *request, void *data)
rv = ogs_queue_push(ogs_app()->queue, e); rv = ogs_queue_push(ogs_app()->queue, e);
if (rv != OGS_OK) { 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); bsf_event_free(e);
return OGS_ERROR; return OGS_ERROR;
} }
@ -43,11 +44,18 @@ static int server_cb(ogs_sbi_request_t *request, void *data)
return OGS_OK; 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; bsf_event_t *e = NULL;
int rv; 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); ogs_assert(response);
e = bsf_event_new(BSF_EVT_SBI_CLIENT); 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); rv = ogs_queue_push(ogs_app()->queue, e);
if (rv != OGS_OK) { 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); bsf_event_free(e);
return OGS_ERROR; return OGS_ERROR;
} }
@ -110,25 +119,10 @@ int bsf_sbi_open(void)
void bsf_sbi_close(void) void bsf_sbi_close(void)
{ {
ogs_sbi_client_stop_all();
ogs_sbi_server_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) 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); return ogs_sbi_send(nf_instance, client_cb, xact);

View File

@ -29,8 +29,6 @@ extern "C" {
int bsf_sbi_open(void); int bsf_sbi_open(void);
void bsf_sbi_close(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_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, bool bsf_sbi_discover_and_send(OpenAPI_nf_type_e target_nf_type,

View File

@ -81,7 +81,7 @@ static void timer_send_event(int timer_id, void *data)
rv = ogs_queue_push(ogs_app()->queue, e); rv = ogs_queue_push(ogs_app()->queue, e);
if (rv != OGS_OK) { 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)); (int)rv, bsf_timer_get_name(e->timer_id));
bsf_event_free(e); bsf_event_free(e);
} }

View File

@ -36,6 +36,8 @@ subdir('sgwu')
subdir('pcrf') subdir('pcrf')
subdir('nrf') subdir('nrf')
subdir('scp')
subdir('udr') subdir('udr')
subdir('udm') subdir('udm')
subdir('pcf') subdir('pcf')

View File

@ -125,7 +125,7 @@ void mme_sctp_event_push(mme_event_e id,
rv = ogs_queue_push(ogs_app()->queue, e); rv = ogs_queue_push(ogs_app()->queue, e);
if (rv != OGS_OK) { 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); ogs_free(e->addr);
if (e->pkbuf) if (e->pkbuf)
ogs_pkbuf_free(e->pkbuf); ogs_pkbuf_free(e->pkbuf);

View File

@ -111,7 +111,7 @@ void mme_timer_s1_delayed_send(void *data)
rv = ogs_queue_push(ogs_app()->queue, e); rv = ogs_queue_push(ogs_app()->queue, e);
if (rv != OGS_OK) { 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); ogs_timer_delete(e->timer);
mme_event_free(e); mme_event_free(e);
} }
@ -131,7 +131,7 @@ static void emm_timer_event_send(
rv = ogs_queue_push(ogs_app()->queue, e); rv = ogs_queue_push(ogs_app()->queue, e);
if (rv != OGS_OK) { 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); mme_event_free(e);
} }
} }
@ -174,7 +174,7 @@ static void esm_timer_event_send(
rv = ogs_queue_push(ogs_app()->queue, e); rv = ogs_queue_push(ogs_app()->queue, e);
if (rv != OGS_OK) { 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); 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); rv = ogs_queue_push(ogs_app()->queue, e);
if (rv != OGS_OK) { 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); 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); rv = ogs_queue_push(ogs_app()->queue, e);
if (rv != OGS_OK) { 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); 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); rv = ogs_queue_push(ogs_app()->queue, e);
if (rv != OGS_OK) { 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); mme_event_free(e);
} }
} }

View File

@ -133,7 +133,7 @@ int s1ap_send_to_esm(
e->create_action = create_action; e->create_action = create_action;
rv = ogs_queue_push(ogs_app()->queue, e); rv = ogs_queue_push(ogs_app()->queue, e);
if (rv != OGS_OK) { 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); ogs_pkbuf_free(e->pkbuf);
mme_event_free(e); mme_event_free(e);
} }
@ -221,7 +221,7 @@ int s1ap_send_to_nas(enb_ue_t *enb_ue,
e->pkbuf = nasbuf; e->pkbuf = nasbuf;
rv = ogs_queue_push(ogs_app()->queue, e); rv = ogs_queue_push(ogs_app()->queue, e);
if (rv != OGS_OK) { 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); ogs_pkbuf_free(e->pkbuf);
mme_event_free(e); mme_event_free(e);
} }

View File

@ -32,7 +32,7 @@ int nrf_initialize()
nrf_context_init(); nrf_context_init();
nrf_event_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; if (rv != OGS_OK) return rv;
rv = nrf_context_parse_config(); rv = nrf_context_parse_config();

View File

@ -20,7 +20,7 @@
#include "nnrf-build.h" #include "nnrf-build.h"
ogs_sbi_request_t *nrf_nnrf_nfm_build_nf_status_notify( 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, OpenAPI_notification_event_type_e event,
ogs_sbi_nf_instance_t *nf_instance) 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; OpenAPI_notification_data_t *NotificationData = NULL;
ogs_assert(client);
ogs_assert(subscription); ogs_assert(subscription);
ogs_assert(event); ogs_assert(event);
ogs_assert(nf_instance); ogs_assert(nf_instance);

View File

@ -28,7 +28,7 @@ extern "C" {
#endif #endif
ogs_sbi_request_t *nrf_nnrf_nfm_build_nf_status_notify( 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, OpenAPI_notification_event_type_e event,
ogs_sbi_nf_instance_t *nf_instance); ogs_sbi_nf_instance_t *nf_instance);

View File

@ -35,7 +35,11 @@ static int server_cb(ogs_sbi_request_t *request, void *data)
rv = ogs_queue_push(ogs_app()->queue, e); rv = ogs_queue_push(ogs_app()->queue, e);
if (rv != OGS_OK) { 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); nrf_event_free(e);
return OGS_ERROR; return OGS_ERROR;
} }
@ -43,12 +47,19 @@ static int server_cb(ogs_sbi_request_t *request, void *data)
return OGS_OK; 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; int rv;
ogs_sbi_message_t message; 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); ogs_assert(response);
rv = ogs_sbi_parse_response(&message, 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) int nrf_sbi_open(void)
{ {
ogs_sbi_nf_instance_t *nf_instance = NULL;
if (ogs_sbi_server_start_all(server_cb) != OGS_OK) if (ogs_sbi_server_start_all(server_cb) != OGS_OK)
return OGS_ERROR; 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; return OGS_OK;
} }
void nrf_sbi_close(void) void nrf_sbi_close(void)
{ {
ogs_sbi_client_stop_all();
ogs_sbi_server_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); ogs_assert(client);
request = nrf_nnrf_nfm_build_nf_status_notify( request = nrf_nnrf_nfm_build_nf_status_notify(
client, subscription, event, nf_instance); subscription, event, nf_instance);
ogs_expect_or_return_val(request, false); 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( bool nrf_nnrf_nfm_send_nf_status_notify_all(

View File

@ -68,7 +68,7 @@ static void timer_send_event(int timer_id, void *data)
rv = ogs_queue_push(ogs_app()->queue, e); rv = ogs_queue_push(ogs_app()->queue, e);
if (rv != OGS_OK) { 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); nrf_event_free(e);
} }
} }

View File

@ -32,7 +32,7 @@ int nssf_initialize()
nssf_context_init(); nssf_context_init();
nssf_event_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; if (rv != OGS_OK) return rv;
rv = nssf_context_parse_config(); rv = nssf_context_parse_config();

View File

@ -61,16 +61,18 @@ void nssf_nf_state_initial(ogs_fsm_t *s, nssf_event_t *e)
nf_instance = e->sbi.data; nf_instance = e->sbi.data;
ogs_assert(nf_instance); 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); ogs_assert(nf_instance->t_registration_interval);
nf_instance->t_registration_interval->cb = nf_instance->t_heartbeat_interval = ogs_timer_add(ogs_app()->timer_mgr,
nssf_timer_nf_instance_registration_interval; nssf_timer_nf_instance_heartbeat_interval, nf_instance);
ogs_assert(nf_instance->t_heartbeat_interval); ogs_assert(nf_instance->t_heartbeat_interval);
nf_instance->t_heartbeat_interval->cb = nf_instance->t_no_heartbeat = ogs_timer_add(ogs_app()->timer_mgr,
nssf_timer_nf_instance_heartbeat_interval; nssf_timer_nf_instance_no_heartbeat, nf_instance);
ogs_assert(nf_instance->t_no_heartbeat); 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); ogs_assert(nf_instance->t_validity);
nf_instance->t_validity->cb = nssf_timer_nf_instance_validity;
if (NF_INSTANCE_IS_NRF(nf_instance)) { if (NF_INSTANCE_IS_NRF(nf_instance)) {
OGS_FSM_TRAN(s, &nssf_nf_state_will_register); 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) 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(s);
ogs_assert(e); ogs_assert(e);
nssf_sm_debug(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) 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_timer_start(nf_instance->t_registration_interval,
ogs_app()->time.message.sbi.nf_register_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; break;
case OGS_FSM_EXIT_SIG: 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_timer_start(nf_instance->t_registration_interval,
ogs_app()->time.message.sbi.nf_register_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; break;
default: default:

View File

@ -35,7 +35,8 @@ static int server_cb(ogs_sbi_request_t *request, void *data)
rv = ogs_queue_push(ogs_app()->queue, e); rv = ogs_queue_push(ogs_app()->queue, e);
if (rv != OGS_OK) { 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); nssf_event_free(e);
return OGS_ERROR; return OGS_ERROR;
} }
@ -43,11 +44,18 @@ static int server_cb(ogs_sbi_request_t *request, void *data)
return OGS_OK; 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; nssf_event_t *e = NULL;
int rv; 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); ogs_assert(response);
e = nssf_event_new(NSSF_EVT_SBI_CLIENT); 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); rv = ogs_queue_push(ogs_app()->queue, e);
if (rv != OGS_OK) { 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); nssf_event_free(e);
return OGS_ERROR; return OGS_ERROR;
} }
@ -110,21 +119,6 @@ int nssf_sbi_open(void)
void nssf_sbi_close(void) void nssf_sbi_close(void)
{ {
ogs_sbi_client_stop_all();
ogs_sbi_server_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);
}

View File

@ -29,8 +29,6 @@ extern "C" {
int nssf_sbi_open(void); int nssf_sbi_open(void);
void nssf_sbi_close(void); void nssf_sbi_close(void);
bool nssf_nnrf_nfm_send_nf_register(ogs_sbi_nf_instance_t *nf_instance);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View File

@ -64,7 +64,7 @@ static void sbi_timer_send_event(int timer_id, void *data)
rv = ogs_queue_push(ogs_app()->queue, e); rv = ogs_queue_push(ogs_app()->queue, e);
if (rv != OGS_OK) { 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)); (int)rv, nssf_timer_get_name(e->timer_id));
nssf_event_free(e); nssf_event_free(e);
} }

View File

@ -32,7 +32,7 @@ int pcf_initialize()
pcf_context_init(); pcf_context_init();
pcf_event_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; if (rv != OGS_OK) return rv;
rv = pcf_context_parse_config(); rv = pcf_context_parse_config();

View File

@ -61,16 +61,18 @@ void pcf_nf_state_initial(ogs_fsm_t *s, pcf_event_t *e)
nf_instance = e->sbi.data; nf_instance = e->sbi.data;
ogs_assert(nf_instance); 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); ogs_assert(nf_instance->t_registration_interval);
nf_instance->t_registration_interval->cb = nf_instance->t_heartbeat_interval = ogs_timer_add(ogs_app()->timer_mgr,
pcf_timer_nf_instance_registration_interval; pcf_timer_nf_instance_heartbeat_interval, nf_instance);
ogs_assert(nf_instance->t_heartbeat_interval); ogs_assert(nf_instance->t_heartbeat_interval);
nf_instance->t_heartbeat_interval->cb = nf_instance->t_no_heartbeat = ogs_timer_add(ogs_app()->timer_mgr,
pcf_timer_nf_instance_heartbeat_interval; pcf_timer_nf_instance_no_heartbeat, nf_instance);
ogs_assert(nf_instance->t_no_heartbeat); 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); ogs_assert(nf_instance->t_validity);
nf_instance->t_validity->cb = pcf_timer_nf_instance_validity;
if (NF_INSTANCE_IS_NRF(nf_instance)) { if (NF_INSTANCE_IS_NRF(nf_instance)) {
OGS_FSM_TRAN(s, &pcf_nf_state_will_register); 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) 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(s);
ogs_assert(e); ogs_assert(e);
pcf_sm_debug(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) 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_timer_start(nf_instance->t_registration_interval,
ogs_app()->time.message.sbi.nf_register_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; break;
case OGS_FSM_EXIT_SIG: 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_timer_start(nf_instance->t_registration_interval,
ogs_app()->time.message.sbi.nf_register_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; break;
default: default:

View File

@ -35,7 +35,8 @@ static int server_cb(ogs_sbi_request_t *request, void *data)
rv = ogs_queue_push(ogs_app()->queue, e); rv = ogs_queue_push(ogs_app()->queue, e);
if (rv != OGS_OK) { 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); pcf_event_free(e);
return OGS_ERROR; return OGS_ERROR;
} }
@ -43,11 +44,18 @@ static int server_cb(ogs_sbi_request_t *request, void *data)
return OGS_OK; 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; pcf_event_t *e = NULL;
int rv; 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); ogs_assert(response);
e = pcf_event_new(PCF_EVT_SBI_CLIENT); 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); rv = ogs_queue_push(ogs_app()->queue, e);
if (rv != OGS_OK) { 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); pcf_event_free(e);
return OGS_ERROR; return OGS_ERROR;
} }
@ -123,25 +132,10 @@ int pcf_sbi_open(void)
void pcf_sbi_close(void) void pcf_sbi_close(void)
{ {
ogs_sbi_client_stop_all();
ogs_sbi_server_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) 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); 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; 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; int rv;
ogs_sbi_message_t message; 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); ogs_assert(response);
rv = ogs_sbi_parse_response(&message, 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; 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; pcf_app_t *app_session = data;
ogs_assert(app_session); ogs_assert(app_session);
client_notify_cb(response, data); client_notify_cb(status, response, data);
pcf_app_remove(app_session); pcf_app_remove(app_session);

View File

@ -34,8 +34,6 @@ extern "C" {
int pcf_sbi_open(void); int pcf_sbi_open(void);
void pcf_sbi_close(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_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, 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, pcf_ue_t *pcf_ue, ogs_sbi_stream_t *stream, void *data,

View File

@ -79,7 +79,7 @@ static void sbi_timer_send_event(int timer_id, void *data)
rv = ogs_queue_push(ogs_app()->queue, e); rv = ogs_queue_push(ogs_app()->queue, e);
if (rv != OGS_OK) { 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)); (int)rv, pcf_timer_get_name(e->timer_id));
pcf_event_free(e); pcf_event_free(e);
} }

40
src/scp/app.c Normal file
View File

@ -0,0 +1,40 @@
/*
* Copyright (C) 2019-2022 by Sukchan Lee <acetcom@gmail.com>
*
* 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 <https://www.gnu.org/licenses/>.
*/
#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");
}

163
src/scp/context.c Normal file
View File

@ -0,0 +1,163 @@
/*
* Copyright (C) 2019-2022 by Sukchan Lee <acetcom@gmail.com>
*
* 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 <https://www.gnu.org/licenses/>.
*/
#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);
}

88
src/scp/context.h Normal file
View File

@ -0,0 +1,88 @@
/*
* Copyright (C) 2019-2022 by Sukchan Lee <acetcom@gmail.com>
*
* 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 <https://www.gnu.org/licenses/>.
*/
#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 */

77
src/scp/event.c Normal file
View File

@ -0,0 +1,77 @@
/*
* Copyright (C) 2019-2022 by Sukchan Lee <acetcom@gmail.com>
*
* 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 <https://www.gnu.org/licenses/>.
*/
#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";
}

76
src/scp/event.h Normal file
View File

@ -0,0 +1,76 @@
/*
* Copyright (C) 2019-2022 by Sukchan Lee <acetcom@gmail.com>
*
* 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 <https://www.gnu.org/licenses/>.
*/
#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 */

143
src/scp/init.c Normal file
View File

@ -0,0 +1,143 @@
/*
* Copyright (C) 2019-2022 by Sukchan Lee <acetcom@gmail.com>
*
* 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 <https://www.gnu.org/licenses/>.
*/
#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);
}

59
src/scp/meson.build Normal file
View File

@ -0,0 +1,59 @@
# Copyright (C) 2019-2022 by Sukchan Lee <acetcom@gmail.com>
# 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 <https://www.gnu.org/licenses/>.
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)

442
src/scp/nf-sm.c Normal file
View File

@ -0,0 +1,442 @@
/*
* Copyright (C) 2019-2022 by Sukchan Lee <acetcom@gmail.com>
*
* 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 <https://www.gnu.org/licenses/>.
*/
#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;
}
}

55
src/scp/nnrf-build.c Normal file
View File

@ -0,0 +1,55 @@
/*
* Copyright (C) 2019-2022 by Sukchan Lee <acetcom@gmail.com>
*
* 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 <https://www.gnu.org/licenses/>.
*/
#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;
}

35
src/scp/nnrf-build.h Normal file
View File

@ -0,0 +1,35 @@
/*
* Copyright (C) 2019-2022 by Sukchan Lee <acetcom@gmail.com>
*
* 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 <https://www.gnu.org/licenses/>.
*/
#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 */

348
src/scp/nnrf-handler.c Normal file
View File

@ -0,0 +1,348 @@
/*
* Copyright (C) 2019-2022 by Sukchan Lee <acetcom@gmail.com>
*
* 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 <https://www.gnu.org/licenses/>.
*/
#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);
}
}

44
src/scp/nnrf-handler.h Normal file
View File

@ -0,0 +1,44 @@
/*
* Copyright (C) 2019-2022 by Sukchan Lee <acetcom@gmail.com>
*
* 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 <https://www.gnu.org/licenses/>.
*/
#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 */

27
src/scp/nscp-handler.c Normal file
View File

@ -0,0 +1,27 @@
/*
* Copyright (C) 2019-2022 by Sukchan Lee <acetcom@gmail.com>
*
* 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 <https://www.gnu.org/licenses/>.
*/
#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;
}

36
src/scp/nscp-handler.h Normal file
View File

@ -0,0 +1,36 @@
/*
* Copyright (C) 2019-2022 by Sukchan Lee <acetcom@gmail.com>
*
* 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 <https://www.gnu.org/licenses/>.
*/
#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 */

410
src/scp/sbi-path.c Normal file
View File

@ -0,0 +1,410 @@
/*
* Copyright (C) 2019-2022 by Sukchan Lee <acetcom@gmail.com>
*
* 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 <https://www.gnu.org/licenses/>.
*/
#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;
}
/*
* <RFC 2616>
* 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;
}

42
src/scp/sbi-path.h Normal file
View File

@ -0,0 +1,42 @@
/*
* Copyright (C) 2019-2022 by Sukchan Lee <acetcom@gmail.com>
*
* 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 <https://www.gnu.org/licenses/>.
*/
#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 */

369
src/scp/scp-sm.c Normal file
View File

@ -0,0 +1,369 @@
/*
* Copyright (C) 2019-2022 by Sukchan Lee <acetcom@gmail.com>
*
* 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 <https://www.gnu.org/licenses/>.
*/
#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;
}
}

51
src/scp/scp-sm.h Normal file
View File

@ -0,0 +1,51 @@
/*
* Copyright (C) 2019-2022 by Sukchan Lee <acetcom@gmail.com>
*
* 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 <https://www.gnu.org/licenses/>.
*/
#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 */

118
src/scp/timer.c Normal file
View File

@ -0,0 +1,118 @@
/*
* Copyright (C) 2019-2022 by Sukchan Lee <acetcom@gmail.com>
*
* 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 <https://www.gnu.org/licenses/>.
*/
#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);
}

57
src/scp/timer.h Normal file
View File

@ -0,0 +1,57 @@
/*
* Copyright (C) 2019-2022 by Sukchan Lee <acetcom@gmail.com>
*
* 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 <https://www.gnu.org/licenses/>.
*/
#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 */

View File

@ -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); rv = ogs_queue_push(ogs_app()->queue, e);
if (rv != OGS_OK) { 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); ogs_pkbuf_free(e->pkbuf);
sgwc_event_free(e); sgwc_event_free(e);
} }
@ -212,6 +212,8 @@ int sgwc_pfcp_send_bearer_to_modify_list(
ogs_assert(sess); ogs_assert(sess);
ogs_assert(xact); ogs_assert(xact);
xact->local_seid = sess->sgwc_sxa_seid;
memset(&h, 0, sizeof(ogs_pfcp_header_t)); memset(&h, 0, sizeof(ogs_pfcp_header_t));
h.type = OGS_PFCP_SESSION_MODIFICATION_REQUEST_TYPE; h.type = OGS_PFCP_SESSION_MODIFICATION_REQUEST_TYPE;
h.seid = sess->sgwu_sxa_seid; h.seid = sess->sgwu_sxa_seid;
@ -377,6 +379,7 @@ int sgwc_pfcp_send_session_report_response(
ogs_pfcp_header_t h; ogs_pfcp_header_t h;
ogs_assert(xact); ogs_assert(xact);
xact->local_seid = sess->sgwc_sxa_seid;
memset(&h, 0, sizeof(ogs_pfcp_header_t)); memset(&h, 0, sizeof(ogs_pfcp_header_t));
h.type = OGS_PFCP_SESSION_REPORT_RESPONSE_TYPE; h.type = OGS_PFCP_SESSION_REPORT_RESPONSE_TYPE;

View File

@ -316,7 +316,7 @@ static void node_timeout(ogs_pfcp_xact_t *xact, void *data)
rv = ogs_queue_push(ogs_app()->queue, e); rv = ogs_queue_push(ogs_app()->queue, e);
if (rv != OGS_OK) { 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); sgwc_event_free(e);
} }
break; break;

View File

@ -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_f_teid_t *sgw_s1u_teid = NULL, *enb_s1u_teid = NULL;
ogs_gtp2_uli_t uli; ogs_gtp2_uli_t uli;
ogs_assert(sgwc_ue);
ogs_assert(message); ogs_assert(message);
rsp = &message->create_bearer_response; rsp = &message->create_bearer_response;
ogs_assert(rsp); ogs_assert(rsp);
@ -715,30 +716,10 @@ void sgwc_s11_handle_create_bearer_response(
rv = ogs_gtp_xact_commit(s11_xact); rv = ogs_gtp_xact_commit(s11_xact);
ogs_expect(rv == OGS_OK); 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 * 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) { if (rsp->bearer_contexts.presence == 0) {
ogs_error("No Bearer"); ogs_error("No Bearer");
@ -873,6 +854,7 @@ void sgwc_s11_handle_update_bearer_response(
sgwc_bearer_t *bearer = NULL; sgwc_bearer_t *bearer = NULL;
ogs_gtp2_update_bearer_response_t *rsp = NULL; ogs_gtp2_update_bearer_response_t *rsp = NULL;
ogs_assert(sgwc_ue);
ogs_assert(message); ogs_assert(message);
rsp = &message->update_bearer_response; rsp = &message->update_bearer_response;
ogs_assert(rsp); ogs_assert(rsp);
@ -899,26 +881,10 @@ void sgwc_s11_handle_update_bearer_response(
rv = ogs_gtp_xact_commit(s11_xact); rv = ogs_gtp_xact_commit(s11_xact);
ogs_expect(rv == OGS_OK); 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 * 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) { if (rsp->bearer_contexts.presence == 0) {
ogs_error("No Bearer"); ogs_error("No Bearer");
@ -1005,6 +971,7 @@ void sgwc_s11_handle_delete_bearer_response(
sgwc_bearer_t *bearer = NULL; sgwc_bearer_t *bearer = NULL;
ogs_gtp2_delete_bearer_response_t *rsp = NULL; ogs_gtp2_delete_bearer_response_t *rsp = NULL;
ogs_assert(sgwc_ue);
ogs_assert(message); ogs_assert(message);
rsp = &message->delete_bearer_response; rsp = &message->delete_bearer_response;
ogs_assert(rsp); ogs_assert(rsp);
@ -1036,11 +1003,6 @@ void sgwc_s11_handle_delete_bearer_response(
************************/ ************************/
cause_value = OGS_GTP2_CAUSE_REQUEST_ACCEPTED; 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) { if (rsp->linked_eps_bearer_id.presence) {
/* /*
* << Linked EPS Bearer ID >> * << Linked EPS Bearer ID >>
@ -1112,10 +1074,8 @@ void sgwc_s11_handle_delete_bearer_response(
ogs_error("No Cause"); ogs_error("No Cause");
} }
if (sgwc_ue) { ogs_debug(" MME_S11_TEID[%d] SGW_S11_TEID[%d]",
ogs_debug(" MME_S11_TEID[%d] SGW_S11_TEID[%d]", sgwc_ue->mme_s11_teid, sgwc_ue->sgw_s11_teid);
sgwc_ue->mme_s11_teid, sgwc_ue->sgw_s11_teid);
}
ogs_debug(" SGW_S5C_TEID[0x%x] PGW_S5C_TEID[0x%x]", ogs_debug(" SGW_S5C_TEID[0x%x] PGW_S5C_TEID[0x%x]",
sess->sgw_s5c_teid, sess->pgw_s5c_teid); 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( s5c_xact = ogs_gtp_xact_local_create(
sess->gnode, &message->h, pkbuf, gtp_bearer_timeout, bearer); sess->gnode, &message->h, pkbuf, gtp_bearer_timeout, bearer);
ogs_expect_or_return(s5c_xact); ogs_expect_or_return(s5c_xact);
s5c_xact->local_teid = sess->sgw_s5c_teid;
ogs_gtp_xact_associate(s11_xact, s5c_xact); ogs_gtp_xact_associate(s11_xact, s5c_xact);

View File

@ -79,6 +79,9 @@ void sgwc_s5c_handle_create_session_response(
ogs_gtp_xact_t *s11_xact = NULL; ogs_gtp_xact_t *s11_xact = NULL;
ogs_gtp_node_t *pgw = NULL; ogs_gtp_node_t *pgw = NULL;
ogs_assert(sess);
sgwc_ue = sess->sgwc_ue;
ogs_assert(sgwc_ue);
ogs_assert(gtpbuf); ogs_assert(gtpbuf);
ogs_assert(message); ogs_assert(message);
rsp = &message->create_session_response; rsp = &message->create_session_response;
@ -96,30 +99,10 @@ void sgwc_s5c_handle_create_session_response(
rv = ogs_gtp_xact_commit(s5c_xact); rv = ogs_gtp_xact_commit(s5c_xact);
ogs_expect(rv == OGS_OK); 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 * 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) { 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"); 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)); 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( void sgwc_s5c_handle_modify_bearer_response(
sgwc_sess_t *sess, ogs_gtp_xact_t *s5c_xact, sgwc_sess_t *sess, ogs_gtp_xact_t *s5c_xact,
ogs_pkbuf_t *gtpbuf, ogs_gtp2_message_t *message) 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_gtp_xact_t *s11_xact = NULL;
ogs_gtp2_modify_bearer_response_t *rsp = NULL; ogs_gtp2_modify_bearer_response_t *rsp = NULL;
ogs_assert(sess);
sgwc_ue = sess->sgwc_ue;
ogs_assert(sgwc_ue);
ogs_assert(message); ogs_assert(message);
rsp = &message->modify_bearer_response; rsp = &message->modify_bearer_response;
ogs_assert(rsp); ogs_assert(rsp);
@ -416,35 +300,10 @@ void sgwc_s5c_handle_modify_bearer_response(
rv = ogs_gtp_xact_commit(s5c_xact); rv = ogs_gtp_xact_commit(s5c_xact);
ogs_expect(rv == OGS_OK); 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 * 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) { if (rsp->cause.presence == 0) {
ogs_error("No Cause"); 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( void sgwc_s5c_handle_create_bearer_request(
sgwc_sess_t *sess, ogs_gtp_xact_t *s5c_xact, sgwc_sess_t *sess, ogs_gtp_xact_t *s5c_xact,
ogs_pkbuf_t *gtpbuf, ogs_gtp2_message_t *message) 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); rv = ogs_gtp_xact_update_tx(s11_xact, &message->h, pkbuf);
ogs_expect_or_return(rv == OGS_OK); ogs_expect_or_return(rv == OGS_OK);
} }
s11_xact->local_teid = sgwc_ue->sgw_s11_teid;
rv = ogs_gtp_xact_commit(s11_xact); rv = ogs_gtp_xact_commit(s11_xact);
ogs_expect(rv == OGS_OK); 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); rv = ogs_gtp_xact_update_tx(s11_xact, &message->h, pkbuf);
ogs_expect_or_return(rv == OGS_OK); ogs_expect_or_return(rv == OGS_OK);
} }
s11_xact->local_teid = sgwc_ue->sgw_s11_teid;
rv = ogs_gtp_xact_commit(s11_xact); rv = ogs_gtp_xact_commit(s11_xact);
ogs_expect(rv == OGS_OK); ogs_expect(rv == OGS_OK);
@ -889,6 +835,9 @@ void sgwc_s5c_handle_bearer_resource_failure_indication(
sgwc_ue_t *sgwc_ue = NULL; sgwc_ue_t *sgwc_ue = NULL;
ogs_assert(sess);
sgwc_ue = sess->sgwc_ue;
ogs_assert(sgwc_ue);
ogs_assert(message); ogs_assert(message);
ind = &message->bearer_resource_failure_indication; ind = &message->bearer_resource_failure_indication;
ogs_assert(ind); ogs_assert(ind);
@ -902,17 +851,6 @@ void sgwc_s5c_handle_bearer_resource_failure_indication(
s11_xact = s5c_xact->assoc_xact; s11_xact = s5c_xact->assoc_xact;
ogs_assert(s11_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 * Check Cause Value
********************/ ********************/

View File

@ -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) { if (gtp_message.h.teid_presence && gtp_message.h.teid != 0) {
/* Cause is not "Context not found" */ /* Cause is not "Context not found" */
sgwc_ue = sgwc_ue_find_by_teid(gtp_message.h.teid); 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 /* 3GPP TS 29.274 5.5.2: we receive TEID=0 under some
* conditions, such as cause "Session context not found". In those * conditions, such as cause "Session context not found". In those
* cases, we still want to identify the local session which * cases, we still want to identify the local session which

View File

@ -157,6 +157,7 @@ void sgwc_sxa_handle_session_establishment_response(
ogs_debug("Session Establishment Response"); ogs_debug("Session Establishment Response");
ogs_assert(sess);
ogs_assert(pfcp_xact); ogs_assert(pfcp_xact);
ogs_assert(pfcp_rsp); ogs_assert(pfcp_rsp);
ogs_assert(recv_message); ogs_assert(recv_message);
@ -171,11 +172,6 @@ void sgwc_sxa_handle_session_establishment_response(
cause_value = OGS_GTP2_CAUSE_REQUEST_ACCEPTED; 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) { if (pfcp_rsp->up_f_seid.presence == 0) {
ogs_error("No UP F-SEID"); ogs_error("No UP F-SEID");
cause_value = OGS_GTP2_CAUSE_MANDATORY_IE_MISSING; 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_debug("Session Modification Response");
ogs_assert(sess);
ogs_assert(pfcp_xact); ogs_assert(pfcp_xact);
ogs_assert(pfcp_rsp); ogs_assert(pfcp_rsp);
@ -462,30 +459,12 @@ void sgwc_sxa_handle_session_modification_response(
cause_value = OGS_GTP2_CAUSE_REQUEST_ACCEPTED; cause_value = OGS_GTP2_CAUSE_REQUEST_ACCEPTED;
if (flags & OGS_PFCP_MODIFY_SESSION) { 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; sgwc_ue = sess->sgwc_ue;
ogs_assert(sgwc_ue); ogs_assert(sgwc_ue);
} else { } else {
bearer = pfcp_xact->data; bearer = pfcp_xact->data;
ogs_assert(bearer); 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; sgwc_ue = bearer->sgwc_ue;
ogs_assert(sgwc_ue); ogs_assert(sgwc_ue);
} }
@ -1206,16 +1185,12 @@ void sgwc_sxa_handle_session_deletion_response(
ogs_debug("Session Deletion Response"); ogs_debug("Session Deletion Response");
ogs_assert(sess);
ogs_assert(pfcp_xact); ogs_assert(pfcp_xact);
ogs_assert(pfcp_rsp); ogs_assert(pfcp_rsp);
cause_value = OGS_GTP2_CAUSE_REQUEST_ACCEPTED; 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.presence) {
if (pfcp_rsp->cause.u8 != OGS_PFCP_CAUSE_REQUEST_ACCEPTED) { if (pfcp_rsp->cause.u8 != OGS_PFCP_CAUSE_REQUEST_ACCEPTED) {
ogs_warn("PFCP Cause[%d] : Not Accepted", pfcp_rsp->cause.u8); 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_debug("Session Report Request");
ogs_assert(sess);
ogs_assert(pfcp_xact); ogs_assert(pfcp_xact);
ogs_assert(pfcp_req); ogs_assert(pfcp_req);
cause_value = OGS_GTP2_CAUSE_REQUEST_ACCEPTED; 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) { if (pfcp_req->report_type.presence == 0) {
ogs_error("No Report Type"); ogs_error("No Report Type");
cause_value = OGS_GTP2_CAUSE_MANDATORY_IE_MISSING; cause_value = OGS_GTP2_CAUSE_MANDATORY_IE_MISSING;

View File

@ -57,7 +57,7 @@ static void timer_send_event(int timer_id, void *data)
rv = ogs_queue_push(ogs_app()->queue, e); rv = ogs_queue_push(ogs_app()->queue, e);
if (rv != OGS_OK) { 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)); (int)rv, sgwc_timer_get_name(e->timer_id));
sgwc_event_free(e); sgwc_event_free(e);
} }

View File

@ -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); rv = ogs_queue_push(ogs_app()->queue, e);
if (rv != OGS_OK) { 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); ogs_pkbuf_free(e->pkbuf);
sgwu_event_free(e); sgwu_event_free(e);
} }

View File

@ -295,7 +295,7 @@ static void node_timeout(ogs_pfcp_xact_t *xact, void *data)
rv = ogs_queue_push(ogs_app()->queue, e); rv = ogs_queue_push(ogs_app()->queue, e);
if (rv != OGS_OK) { 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); sgwu_event_free(e);
} }
break; break;

View File

@ -45,7 +45,7 @@ static void timer_send_event(int timer_id, void *data)
rv = ogs_queue_push(ogs_app()->queue, e); rv = ogs_queue_push(ogs_app()->queue, e);
if (rv != OGS_OK) { 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); sgwu_event_free(e);
} }
} }

View File

@ -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); rv = ogs_queue_push(ogs_app()->queue, e);
if (rv != OGS_OK) { 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); ogs_pkbuf_free(e->pkbuf);
smf_event_free(e); smf_event_free(e);
} }

View File

@ -1005,7 +1005,7 @@ out:
e->gtp_xact = xact; e->gtp_xact = xact;
rv = ogs_queue_push(ogs_app()->queue, e); rv = ogs_queue_push(ogs_app()->queue, e);
if (rv != OGS_OK) { 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_session_data_free(&gx_message->session_data);
ogs_free(gx_message); ogs_free(gx_message);
smf_event_free(e); 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; e->gx_message = gx_message;
rv = ogs_queue_push(ogs_app()->queue, e); rv = ogs_queue_push(ogs_app()->queue, e);
if (rv != OGS_OK) { 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_session_data_free(&gx_message->session_data);
ogs_free(gx_message); ogs_free(gx_message);
smf_event_free(e); smf_event_free(e);

View File

@ -1104,7 +1104,7 @@ out:
} }
rv = ogs_queue_push(ogs_app()->queue, e); rv = ogs_queue_push(ogs_app()->queue, e);
if (rv != OGS_OK) { 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); ogs_free(gy_message);
smf_event_free(e); smf_event_free(e);
} else { } else {
@ -1233,7 +1233,7 @@ static int smf_gy_rar_cb( struct msg **msg, struct avp *avp,
e->gy_message = gy_message; e->gy_message = gy_message;
rv = ogs_queue_push(ogs_app()->queue, e); rv = ogs_queue_push(ogs_app()->queue, e);
if (rv != OGS_OK) { 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); ogs_free(gy_message);
smf_event_free(e); smf_event_free(e);
} else { } else {

View File

@ -53,7 +53,7 @@ int smf_initialize()
rv = ogs_pfcp_context_parse_config("smf", "upf"); rv = ogs_pfcp_context_parse_config("smf", "upf");
if (rv != OGS_OK) return rv; 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; if (rv != OGS_OK) return rv;
rv = ogs_metrics_context_parse_config(); rv = ogs_metrics_context_parse_config();

View File

@ -255,6 +255,7 @@ void smf_5gc_n4_handle_session_modification_response(
ogs_debug("Session Modification Response [5gc]"); ogs_debug("Session Modification Response [5gc]");
ogs_assert(sess);
ogs_assert(xact); ogs_assert(xact);
ogs_assert(rsp); ogs_assert(rsp);
@ -279,11 +280,6 @@ void smf_5gc_n4_handle_session_modification_response(
status = OGS_SBI_HTTP_STATUS_OK; 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.presence) {
if (rsp->cause.u8 != OGS_PFCP_CAUSE_REQUEST_ACCEPTED) { if (rsp->cause.u8 != OGS_PFCP_CAUSE_REQUEST_ACCEPTED) {
ogs_warn("PFCP Cause [%d] : Not Accepted", rsp->cause.u8); 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; status = OGS_SBI_HTTP_STATUS_OK;
if (!sess) { ogs_assert(sess);
ogs_warn("No Context");
status = OGS_SBI_HTTP_STATUS_NOT_FOUND;
}
if (rsp->cause.presence) { if (rsp->cause.presence) {
if (rsp->cause.u8 != OGS_PFCP_CAUSE_REQUEST_ACCEPTED) { if (rsp->cause.u8 != OGS_PFCP_CAUSE_REQUEST_ACCEPTED) {
@ -669,8 +662,6 @@ int smf_5gc_n4_handle_session_deletion_response(
return status; return status;
} }
ogs_assert(sess);
return status; return status;
} }
@ -803,6 +794,7 @@ void smf_epc_n4_handle_session_modification_response(
OGS_LIST(pdr_to_create_list); OGS_LIST(pdr_to_create_list);
ogs_assert(sess);
ogs_assert(xact); ogs_assert(xact);
ogs_assert(rsp); ogs_assert(rsp);
@ -831,11 +823,6 @@ void smf_epc_n4_handle_session_modification_response(
ogs_pfcp_xact_commit(xact); ogs_pfcp_xact_commit(xact);
if (!sess) {
ogs_error("No Context");
return;
}
if (rsp->cause.presence) { if (rsp->cause.presence) {
if (rsp->cause.u8 != OGS_PFCP_CAUSE_REQUEST_ACCEPTED) { if (rsp->cause.u8 != OGS_PFCP_CAUSE_REQUEST_ACCEPTED) {
ogs_error("PFCP Cause [%d] : Not Accepted", rsp->cause.u8); 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; uint16_t pdr_id = 0;
unsigned int i; unsigned int i;
ogs_assert(sess);
ogs_assert(pfcp_xact); ogs_assert(pfcp_xact);
ogs_assert(pfcp_req); ogs_assert(pfcp_req);
@ -1118,11 +1106,6 @@ void smf_n4_handle_session_report_request(
cause_value = OGS_GTP2_CAUSE_REQUEST_ACCEPTED; 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) { if (pfcp_req->report_type.presence == 0) {
ogs_error("No Report Type"); ogs_error("No Report Type");
cause_value = OGS_GTP2_CAUSE_MANDATORY_IE_MISSING; cause_value = OGS_GTP2_CAUSE_MANDATORY_IE_MISSING;
@ -1135,7 +1118,6 @@ void smf_n4_handle_session_report_request(
return; return;
} }
ogs_assert(sess);
report_type.value = pfcp_req->report_type.u8; report_type.value = pfcp_req->report_type.u8;
if (report_type.downlink_data_report) { if (report_type.downlink_data_report) {

Some files were not shown because too many files have changed in this diff Show More