[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:
# no_nrf: true
# no_scp: true
# no_amf: true
# no_smf: true
# no_upf: true
@ -194,6 +195,11 @@ nrf:
- ::1
port: 7777
scp:
sbi:
- addr: 127.0.1.10
port: 7777
ausf:
sbi:
- addr: 127.0.0.11

View File

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

View File

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

View File

@ -29,6 +29,7 @@ open5gs_conf = '''
hss.yaml
pcrf.yaml
nrf.yaml
scp.yaml
ausf.yaml
udm.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:
# no_nrf: true
# no_scp: true
# no_amf: true
# no_smf: true
# no_upf: true
@ -194,6 +195,70 @@ nrf:
- ::1
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:
sbi:
- addr: 127.0.0.11

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -176,6 +176,26 @@ ogs_sbi_client_t *ogs_sbi_client_find(ogs_sockaddr_t *addr)
return client;
}
void ogs_sbi_client_stop(ogs_sbi_client_t *client)
{
connection_t *conn = NULL;
ogs_assert(client);
ogs_list_for_each(&client->connection_list, conn) {
ogs_assert(conn->client_cb);
conn->client_cb(OGS_DONE, NULL, conn->data);
}
}
void ogs_sbi_client_stop_all(void)
{
ogs_sbi_client_t *client = NULL;
ogs_list_for_each(&ogs_sbi_self()->client_list, client)
ogs_sbi_client_stop(client);
}
#define mycase(code) \
case code: s = OGS_STRINGIFY(code)
@ -246,6 +266,8 @@ static char *add_params_to_uri(CURL *easy, char *uri, ogs_hash_t *params)
return uri;
}
static void _connection_remove(connection_t *conn);
static connection_t *connection_add(
ogs_sbi_client_t *client, ogs_sbi_client_cb_f client_cb,
ogs_sbi_request_t *request, void *data)
@ -269,19 +291,31 @@ static connection_t *connection_add(
conn->data = data;
conn->method = ogs_strdup(request->h.method);
ogs_expect_or_return_val(conn->method, NULL);
if (!conn->method) {
ogs_error("conn->method is NULL");
_connection_remove(conn);
return NULL;
}
conn->num_of_header = ogs_hash_count(request->http.headers);
if (conn->num_of_header) {
conn->headers = ogs_calloc(conn->num_of_header, sizeof(char *));
ogs_expect_or_return_val(conn->headers, NULL);
if (!conn->headers) {
ogs_error("conn->headers is NULL");
_connection_remove(conn);
return NULL;
}
for (hi = ogs_hash_first(request->http.headers), i = 0;
hi && i < conn->num_of_header; hi = ogs_hash_next(hi), i++) {
const char *key = ogs_hash_this_key(hi);
char *val = ogs_hash_this_val(hi);
conn->headers[i] = ogs_msprintf("%s: %s", key, val);
ogs_expect_or_return_val(conn->headers[i], NULL);
if (!conn->headers[i]) {
ogs_error("conn->headers[i=%d] is NULL", i);
_connection_remove(conn);
return NULL;
}
conn->header_list = curl_slist_append(
conn->header_list, conn->headers[i]);
}
@ -289,9 +323,11 @@ static connection_t *connection_add(
conn->timer = ogs_timer_add(
ogs_app()->timer_mgr, connection_timer_expired, conn);
ogs_expect_or_return_val(conn->timer, NULL);
ogs_list_add(&client->connection_list, conn);
if (!conn->timer) {
ogs_error("conn->timer is NULL");
_connection_remove(conn);
return NULL;
}
/* If http response is not received within deadline,
* Open5GS will discard this request. */
@ -299,7 +335,23 @@ static connection_t *connection_add(
ogs_app()->time.message.sbi.connection_deadline);
conn->easy = curl_easy_init();
ogs_assert(conn->easy);
if (!conn->easy) {
ogs_error("conn->easy is NULL");
_connection_remove(conn);
return NULL;
}
if (ogs_hash_count(request->http.params)) {
char *uri = add_params_to_uri(conn->easy,
request->h.uri, request->http.params);
if (!uri) {
ogs_error("add_params_to_uri() failed");
_connection_remove(conn);
return NULL;
}
request->h.uri = uri;
}
/* HTTP Method */
if (strcmp(request->h.method, OGS_SBI_HTTP_METHOD_PUT) == 0 ||
@ -312,7 +364,11 @@ static connection_t *connection_add(
if (request->http.content) {
conn->content = ogs_memdup(
request->http.content, request->http.content_length);
ogs_assert(conn->content);
if (!conn->content) {
ogs_error("conn->content is NULL");
_connection_remove(conn);
return NULL;
}
curl_easy_setopt(conn->easy,
CURLOPT_POSTFIELDS, conn->content);
curl_easy_setopt(conn->easy,
@ -336,11 +392,7 @@ static connection_t *connection_add(
CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_2_PRIOR_KNOWLEDGE);
#endif
if (ogs_hash_count(request->http.params)) {
request->h.uri = add_params_to_uri(conn->easy,
request->h.uri, request->http.params);
ogs_expect_or_return_val(request->h.uri, NULL);
}
ogs_list_add(&client->connection_list, conn);
curl_easy_setopt(conn->easy, CURLOPT_URL, request->h.uri);
@ -358,27 +410,11 @@ static connection_t *connection_add(
return conn;
}
static void connection_remove(connection_t *conn)
static void _connection_remove(connection_t *conn)
{
ogs_sbi_client_t *client = NULL;
int i;
ogs_assert(conn);
client = conn->client;
ogs_assert(client);
ogs_list_remove(&client->connection_list, conn);
ogs_assert(conn->timer);
ogs_timer_delete(conn->timer);
ogs_assert(conn->easy);
ogs_assert(client->multi);
curl_multi_remove_handle(client->multi, conn->easy);
curl_easy_cleanup(conn->easy);
ogs_assert(conn->method);
ogs_free(conn->method);
if (conn->content)
ogs_free(conn->content);
@ -386,19 +422,45 @@ static void connection_remove(connection_t *conn)
if (conn->location)
ogs_free(conn->location);
if (conn->memory)
ogs_free(conn->memory);
if (conn->easy)
curl_easy_cleanup(conn->easy);
if (conn->timer)
ogs_timer_delete(conn->timer);
if (conn->num_of_header) {
for (i = 0; i < conn->num_of_header; i++)
ogs_free(conn->headers[i]);
if (conn->headers[i])
ogs_free(conn->headers[i]);
ogs_free(conn->headers);
}
curl_slist_free_all(conn->header_list);
if (conn->memory)
ogs_free(conn->memory);
if (conn->method)
ogs_free(conn->method);
ogs_pool_free(&connection_pool, conn);
}
static void connection_remove(connection_t *conn)
{
ogs_sbi_client_t *client = NULL;
ogs_assert(conn);
client = conn->client;
ogs_assert(client);
ogs_list_remove(&client->connection_list, conn);
ogs_assert(client->multi);
curl_multi_remove_handle(client->multi, conn->easy);
_connection_remove(conn);
}
static void connection_remove_all(ogs_sbi_client_t *client)
{
connection_t *conn = NULL, *next_conn = NULL;
@ -416,6 +478,11 @@ static void connection_timer_expired(void *data)
conn = data;
ogs_assert(conn);
ogs_error("Connection timer expired");
ogs_assert(conn->client_cb);
conn->client_cb(OGS_TIMEUP, NULL, conn->data);
connection_remove(conn);
}
@ -487,12 +554,12 @@ static void check_multi_info(ogs_sbi_client_t *client)
if (conn->location)
ogs_sbi_header_set(response->http.headers,
OGS_SBI_LOCATION, conn->location);
ogs_assert(conn->client_cb);
conn->client_cb(response, conn->data);
} else
ogs_warn("[%d] %s", res, conn->error);
ogs_assert(conn->client_cb);
conn->client_cb(res == CURLE_OK ? OGS_OK : OGS_ERROR,
response, conn->data);
connection_remove(conn);
break;
default:
@ -502,7 +569,7 @@ static void check_multi_info(ogs_sbi_client_t *client)
}
}
bool ogs_sbi_client_send_request(
bool ogs_sbi_client_send_reqmem_persistent(
ogs_sbi_client_t *client, ogs_sbi_client_cb_f client_cb,
ogs_sbi_request_t *request, void *data)
{
@ -513,17 +580,128 @@ bool ogs_sbi_client_send_request(
if (request->h.uri == NULL) {
request->h.uri = ogs_sbi_client_uri(client, &request->h);
ogs_expect_or_return_val(request->h.uri, false);
}
ogs_debug("[%s] %s", request->h.method, request->h.uri);
conn = connection_add(client, client_cb, request, data);
ogs_expect_or_return_val(conn, false);
return true;
}
bool ogs_sbi_client_send_request(
ogs_sbi_client_t *client, ogs_sbi_client_cb_f client_cb,
ogs_sbi_request_t *request, void *data)
{
bool rc;
ogs_assert(client);
ogs_assert(request);
rc = ogs_sbi_client_send_reqmem_persistent(
client, client_cb, request, data);
ogs_expect(rc == true);
ogs_sbi_request_free(request);
return rc;
}
bool ogs_sbi_scp_send_reqmem_persistent(
ogs_sbi_client_t *client, ogs_sbi_client_cb_f client_cb,
ogs_sbi_request_t *request, void *data)
{
ogs_sbi_nf_instance_t *scp_instance = NULL;
connection_t *conn = NULL;
char *apiroot = NULL;
ogs_assert(client);
ogs_assert(request);
scp_instance = ogs_sbi_self()->scp_instance;
if (scp_instance) {
/*
* In case of indirect communication using SCP,
* add 3gpp-Sbi-Target-apiRoot to HTTP header and
* change CLIENT instance to SCP.
*/
apiroot = ogs_sbi_client_apiroot(client);
ogs_assert(apiroot);
ogs_sbi_header_set(request->http.headers,
OGS_SBI_CUSTOM_TARGET_APIROOT, apiroot);
ogs_free(apiroot);
client = scp_instance->client;
ogs_assert(client);
}
if (request->h.uri == NULL) {
/*
* Regardless of direct or indirect communication,
* if there is no URI, we automatically creates a URI
* with Client Address and request->h
*/
request->h.uri = ogs_sbi_client_uri(client, &request->h);
ogs_assert(request->h.uri);
ogs_debug("[%s] %s", request->h.method, request->h.uri);
} else if (scp_instance) {
/*
* In case of indirect communication using SCP,
* If the full URI is already defined, change full URI to SCP as below.
*
* OLD: http://127.0.0.5:7777/nnrf-nfm/v1/nf-status-notify
* NEW: https://scp.open5gs.org/nnrf-nfm/v1/nf-status-notify
*/
char *path = NULL;
char *old = NULL;
old = request->h.uri;
apiroot = ogs_sbi_client_apiroot(client);
ogs_assert(apiroot);
path = ogs_sbi_getpath_from_uri(request->h.uri);
ogs_assert(path);
request->h.uri = ogs_msprintf("%s/%s", apiroot, path);
ogs_assert(request->h.uri);
ogs_free(apiroot);
ogs_free(path);
ogs_free(old);
ogs_debug("[%s] %s", request->h.method, request->h.uri);
}
conn = connection_add(client, client_cb, request, data);
ogs_expect_or_return_val(conn, false);
return true;
}
bool ogs_sbi_scp_send_request(
ogs_sbi_client_t *client, ogs_sbi_client_cb_f client_cb,
ogs_sbi_request_t *request, void *data)
{
bool rc;
ogs_assert(client);
ogs_assert(request);
rc = ogs_sbi_scp_send_reqmem_persistent(client, client_cb, request, data);
ogs_expect(rc == true);
ogs_sbi_request_free(request);
return rc;
}
static size_t write_cb(void *contents, size_t size, size_t nmemb, void *data)
{
size_t realsize = 0;

View File

@ -53,7 +53,8 @@ extern "C" {
(__pClient)->reference_count); \
} while(0)
typedef int (*ogs_sbi_client_cb_f)(ogs_sbi_response_t *response, void *data);
typedef int (*ogs_sbi_client_cb_f)(
int status, ogs_sbi_response_t *response, void *data);
typedef struct ogs_sbi_client_s {
ogs_socknode_t node;
@ -84,10 +85,23 @@ void ogs_sbi_client_remove(ogs_sbi_client_t *client);
void ogs_sbi_client_remove_all(void);
ogs_sbi_client_t *ogs_sbi_client_find(ogs_sockaddr_t *addr);
void ogs_sbi_client_stop(ogs_sbi_client_t *client);
void ogs_sbi_client_stop_all(void);
bool ogs_sbi_client_send_reqmem_persistent(
ogs_sbi_client_t *client, ogs_sbi_client_cb_f client_cb,
ogs_sbi_request_t *request, void *data);
bool ogs_sbi_client_send_request(
ogs_sbi_client_t *client, ogs_sbi_client_cb_f client_cb,
ogs_sbi_request_t *request, void *data);
bool ogs_sbi_scp_send_reqmem_persistent(
ogs_sbi_client_t *client, ogs_sbi_client_cb_f client_cb,
ogs_sbi_request_t *request, void *data);
bool ogs_sbi_scp_send_request(
ogs_sbi_client_t *client, ogs_sbi_client_cb_f client_cb,
ogs_sbi_request_t *request, void *data);
#ifdef __cplusplus
}
#endif

View File

@ -111,7 +111,8 @@ static int ogs_sbi_context_prepare(void)
return OGS_OK;
}
static int ogs_sbi_context_validation(const char *local)
static int ogs_sbi_context_validation(
const char *local, const char *nrf, const char *scp)
{
/* If SMF is only used in 4G EPC, no SBI interface is required. */
if (strcmp(local, "smf") != 0 &&
@ -120,10 +121,48 @@ static int ogs_sbi_context_validation(const char *local)
return OGS_ERROR;
}
if (context_initialized == 1) {
switch (self.discovery_config.delegated) {
case OGS_SBI_DISCOVERY_DELEGATED_AUTO:
if (strcmp(local, "nrf") != 0 && /* Skip NRF */
strcmp(local, "smf") != 0 && /* Skip SMF since SMF can run 4G */
ogs_sbi_self()->nrf_instance == NULL &&
ogs_sbi_self()->scp_instance == NULL) {
ogs_error("DELEGATED_AUTO - Both NRF and %s are unavailable",
strcmp(scp, "next_scp") == 0 ? "Next-hop SCP" : "SCP");
return OGS_ERROR;
}
break;
case OGS_SBI_DISCOVERY_DELEGATED_YES:
if (ogs_sbi_self()->scp_instance == NULL) {
ogs_error("DELEGATED_YES - no %s available",
strcmp(scp, "next_scp") == 0 ? "Next-hop SCP" : "SCP");
return OGS_ERROR;
}
break;
case OGS_SBI_DISCOVERY_DELEGATED_NO:
if (ogs_sbi_self()->nrf_instance == NULL) {
ogs_error("DELEGATED_NO - no NRF available");
return OGS_ERROR;
}
break;
default:
ogs_fatal("Invalid dicovery-config delegated [%d]",
self.discovery_config.delegated);
ogs_assert_if_reached();
}
}
return OGS_OK;
}
int ogs_sbi_context_parse_config(const char *local, const char *remote)
ogs_sbi_nf_instance_t *ogs_sbi_scp_instance(void)
{
return NULL;
}
int ogs_sbi_context_parse_config(
const char *local, const char *nrf, const char *scp)
{
int rv;
yaml_document_t *document = NULL;
@ -363,17 +402,17 @@ int ogs_sbi_context_parse_config(const char *local, const char *remote)
}
}
}
} else if (remote && !strcmp(root_key, remote)) {
ogs_yaml_iter_t remote_iter;
ogs_yaml_iter_recurse(&root_iter, &remote_iter);
while (ogs_yaml_iter_next(&remote_iter)) {
const char *remote_key = ogs_yaml_iter_key(&remote_iter);
ogs_assert(remote_key);
if (!strcmp(remote_key, "sbi")) {
} else if (nrf && !strcmp(root_key, nrf)) {
ogs_yaml_iter_t nrf_iter;
ogs_yaml_iter_recurse(&root_iter, &nrf_iter);
while (ogs_yaml_iter_next(&nrf_iter)) {
const char *nrf_key = ogs_yaml_iter_key(&nrf_iter);
ogs_assert(nrf_key);
if (!strcmp(nrf_key, "sbi")) {
ogs_yaml_iter_t sbi_array, sbi_iter;
ogs_yaml_iter_recurse(&remote_iter, &sbi_array);
ogs_yaml_iter_recurse(&nrf_iter, &sbi_array);
do {
ogs_sbi_nf_instance_t *nf_instance = NULL;
ogs_sbi_nf_instance_t *nrf_instance = NULL;
ogs_sbi_client_t *client = NULL;
ogs_sockaddr_t *addr = NULL;
int family = AF_UNSPEC;
@ -476,12 +515,13 @@ int ogs_sbi_context_parse_config(const char *local, const char *remote)
client = ogs_sbi_client_add(addr);
ogs_assert(client);
nf_instance = ogs_sbi_nf_instance_add();
ogs_assert(nf_instance);
ogs_sbi_self()->nrf_instance =
nrf_instance = ogs_sbi_nf_instance_add();
ogs_assert(nrf_instance);
ogs_sbi_nf_instance_set_type(
nf_instance, OpenAPI_nf_type_NRF);
nrf_instance, OpenAPI_nf_type_NRF);
OGS_SBI_SETUP_CLIENT(nf_instance, client);
OGS_SBI_SETUP_CLIENT(nrf_instance, client);
if (key) client->tls.key = key;
if (pem) client->tls.pem = pem;
@ -492,10 +532,175 @@ int ogs_sbi_context_parse_config(const char *local, const char *remote)
YAML_SEQUENCE_NODE);
}
}
} else if (scp && !strcmp(root_key, scp)) {
ogs_yaml_iter_t scp_iter;
ogs_yaml_iter_recurse(&root_iter, &scp_iter);
while (ogs_yaml_iter_next(&scp_iter)) {
const char *scp_key = ogs_yaml_iter_key(&scp_iter);
ogs_assert(scp_key);
if (!strcmp(scp_key, "sbi")) {
ogs_yaml_iter_t sbi_array, sbi_iter;
ogs_yaml_iter_recurse(&scp_iter, &sbi_array);
do {
ogs_sbi_nf_instance_t *scp_instance = NULL;
ogs_sbi_client_t *client = NULL;
ogs_sockaddr_t *addr = NULL;
int family = AF_UNSPEC;
int i, num = 0;
const char *hostname[OGS_MAX_NUM_OF_HOSTNAME];
uint16_t port = self.sbi_port;
const char *key = NULL;
const char *pem = NULL;
if (ogs_yaml_iter_type(&sbi_array) ==
YAML_MAPPING_NODE) {
memcpy(&sbi_iter, &sbi_array,
sizeof(ogs_yaml_iter_t));
} else if (ogs_yaml_iter_type(&sbi_array) ==
YAML_SEQUENCE_NODE) {
if (!ogs_yaml_iter_next(&sbi_array))
break;
ogs_yaml_iter_recurse(&sbi_array, &sbi_iter);
} else if (ogs_yaml_iter_type(&sbi_array) ==
YAML_SCALAR_NODE) {
break;
} else
ogs_assert_if_reached();
while (ogs_yaml_iter_next(&sbi_iter)) {
const char *sbi_key =
ogs_yaml_iter_key(&sbi_iter);
ogs_assert(sbi_key);
if (!strcmp(sbi_key, "family")) {
const char *v = ogs_yaml_iter_value(&sbi_iter);
if (v) family = atoi(v);
if (family != AF_UNSPEC &&
family != AF_INET && family != AF_INET6) {
ogs_warn("Ignore family(%d) : "
"AF_UNSPEC(%d), "
"AF_INET(%d), AF_INET6(%d) ",
family, AF_UNSPEC, AF_INET, AF_INET6);
family = AF_UNSPEC;
}
} else if (!strcmp(sbi_key, "addr") ||
!strcmp(sbi_key, "name")) {
ogs_yaml_iter_t hostname_iter;
ogs_yaml_iter_recurse(&sbi_iter,
&hostname_iter);
ogs_assert(ogs_yaml_iter_type(&hostname_iter) !=
YAML_MAPPING_NODE);
do {
if (ogs_yaml_iter_type(&hostname_iter) ==
YAML_SEQUENCE_NODE) {
if (!ogs_yaml_iter_next(&hostname_iter))
break;
}
ogs_assert(num < OGS_MAX_NUM_OF_HOSTNAME);
hostname[num++] =
ogs_yaml_iter_value(&hostname_iter);
} while (
ogs_yaml_iter_type(&hostname_iter) ==
YAML_SEQUENCE_NODE);
} else if (!strcmp(sbi_key, "port")) {
const char *v = ogs_yaml_iter_value(&sbi_iter);
if (v) port = atoi(v);
} else if (!strcmp(sbi_key, "tls")) {
ogs_yaml_iter_t tls_iter;
ogs_yaml_iter_recurse(&sbi_iter, &tls_iter);
while (ogs_yaml_iter_next(&tls_iter)) {
const char *tls_key =
ogs_yaml_iter_key(&tls_iter);
ogs_assert(tls_key);
if (!strcmp(tls_key, "key")) {
key = ogs_yaml_iter_value(&tls_iter);
} else if (!strcmp(tls_key, "pem")) {
pem = ogs_yaml_iter_value(&tls_iter);
} else
ogs_warn("unknown key `%s`", tls_key);
}
} else if (!strcmp(sbi_key, "advertise")) {
/* Nothing in client */
} else
ogs_warn("unknown key `%s`", sbi_key);
}
addr = NULL;
for (i = 0; i < num; i++) {
rv = ogs_addaddrinfo(&addr,
family, hostname[i], port, 0);
ogs_assert(rv == OGS_OK);
}
ogs_filter_ip_version(&addr,
ogs_app()->parameter.no_ipv4,
ogs_app()->parameter.no_ipv6,
ogs_app()->parameter.prefer_ipv4);
if (addr == NULL) continue;
client = ogs_sbi_client_add(addr);
ogs_assert(client);
ogs_sbi_self()->scp_instance =
scp_instance = ogs_sbi_nf_instance_add();
ogs_assert(scp_instance);
ogs_sbi_nf_instance_set_type(
scp_instance, OpenAPI_nf_type_SCP);
OGS_SBI_SETUP_CLIENT(scp_instance, client);
if (key) client->tls.key = key;
if (pem) client->tls.pem = pem;
ogs_freeaddrinfo(addr);
} while (ogs_yaml_iter_type(&sbi_array) ==
YAML_SEQUENCE_NODE);
} else if (!strcmp(scp_key, "discovery")) {
ogs_yaml_iter_t discovery_iter;
yaml_node_t *node = yaml_document_get_node(
document, scp_iter.pair->value);
ogs_assert(node);
ogs_assert(node->type == YAML_MAPPING_NODE);
ogs_yaml_iter_recurse(&scp_iter, &discovery_iter);
while (ogs_yaml_iter_next(&discovery_iter)) {
const char *discovery_key =
ogs_yaml_iter_key(&discovery_iter);
ogs_assert(discovery_key);
if (!strcmp(discovery_key, "delegated")) {
yaml_node_t *discovery_node =
yaml_document_get_node(document,
discovery_iter.pair->value);
ogs_assert(discovery_node->type ==
YAML_SCALAR_NODE);
const char* delegated =
ogs_yaml_iter_value(&discovery_iter);
if (!strcmp(delegated, "auto"))
self.discovery_config.delegated =
OGS_SBI_DISCOVERY_DELEGATED_AUTO;
else if (!strcmp(delegated, "yes"))
self.discovery_config.delegated =
OGS_SBI_DISCOVERY_DELEGATED_YES;
else if (!strcmp(delegated, "no"))
self.discovery_config.delegated =
OGS_SBI_DISCOVERY_DELEGATED_NO;
else
ogs_warn("unknown 'delegated' value `%s`",
delegated);
} else
ogs_warn("unknown key `%s`",
discovery_key);
}
}
}
}
}
rv = ogs_sbi_context_validation(local);
rv = ogs_sbi_context_validation(local, nrf, scp);
if (rv != OGS_OK) return rv;
return OGS_OK;
@ -515,19 +720,6 @@ ogs_sbi_nf_instance_t *ogs_sbi_nf_instance_add(void)
nf_instance->time.heartbeat_interval =
ogs_app()->time.nf_instance.heartbeat_interval;
nf_instance->t_registration_interval = ogs_timer_add(
ogs_app()->timer_mgr, NULL, nf_instance);
ogs_assert(nf_instance->t_registration_interval);
nf_instance->t_heartbeat_interval = ogs_timer_add(
ogs_app()->timer_mgr, NULL, nf_instance);
ogs_assert(nf_instance->t_heartbeat_interval);
nf_instance->t_no_heartbeat = ogs_timer_add(
ogs_app()->timer_mgr, NULL, nf_instance);
ogs_assert(nf_instance->t_no_heartbeat);
nf_instance->t_validity = ogs_timer_add(
ogs_app()->timer_mgr, NULL, nf_instance);
ogs_assert(nf_instance->t_validity);
nf_instance->priority = OGS_SBI_DEFAULT_PRIORITY;
nf_instance->capacity = OGS_SBI_DEFAULT_CAPACITY;
nf_instance->load = OGS_SBI_DEFAULT_LOAD;
@ -625,11 +817,6 @@ void ogs_sbi_nf_instance_remove(ogs_sbi_nf_instance_t *nf_instance)
ogs_free(nf_instance->id);
}
ogs_timer_delete(nf_instance->t_registration_interval);
ogs_timer_delete(nf_instance->t_heartbeat_interval);
ogs_timer_delete(nf_instance->t_no_heartbeat);
ogs_timer_delete(nf_instance->t_validity);
if (nf_instance->client)
ogs_sbi_client_remove(nf_instance->client);

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_nf_instance_s ogs_sbi_nf_instance_t;
typedef enum {
OGS_SBI_DISCOVERY_DELEGATED_AUTO = 0,
OGS_SBI_DISCOVERY_DELEGATED_YES,
OGS_SBI_DISCOVERY_DELEGATED_NO,
} ogs_sbi_discovery_delegated_mode;
typedef struct ogs_sbi_discovery_config_s {
ogs_sbi_discovery_delegated_mode delegated;
} ogs_sbi_discovery_config_t;
typedef struct ogs_sbi_context_s {
uint32_t sbi_port; /* SBI local port */
ogs_sbi_discovery_config_t discovery_config; /* SCP Discovery Delegated */
uint32_t sbi_port; /* SBI local port */
ogs_list_t server_list;
ogs_list_t client_list;
@ -47,25 +59,28 @@ typedef struct ogs_sbi_context_s {
ogs_list_t nf_instance_list;
ogs_list_t subscription_list;
ogs_sbi_nf_instance_t *nf_instance; /* SELF NF Instance */
ogs_sbi_nf_instance_t *nf_instance; /* SELF NF Instance */
ogs_sbi_nf_instance_t *nrf_instance; /* NRF Instance */
ogs_sbi_nf_instance_t *scp_instance; /* SCP Instance */
const char *content_encoding;
} ogs_sbi_context_t;
typedef struct ogs_sbi_nf_instance_s {
ogs_lnode_t lnode;
ogs_fsm_t sm; /* A state machine */
ogs_timer_t *t_registration_interval; /* timer to retry
to register peer node */
ogs_fsm_t sm; /* A state machine */
ogs_timer_t *t_registration_interval; /* timer to retry
to register peer node */
struct {
int heartbeat_interval;
int validity_duration;
} time;
ogs_timer_t *t_heartbeat_interval; /* heartbeat interval */
ogs_timer_t *t_no_heartbeat; /* check heartbeat */
ogs_timer_t *t_validity; /* check validation */
ogs_timer_t *t_heartbeat_interval; /* heartbeat interval */
ogs_timer_t *t_no_heartbeat; /* check heartbeat */
ogs_timer_t *t_validity; /* check validation */
#define NF_INSTANCE_IS_SELF(_iD) \
(_iD) && ogs_sbi_self()->nf_instance && \
@ -77,7 +92,7 @@ typedef struct ogs_sbi_nf_instance_s {
#define NF_INSTANCE_IS_NRF(__nFInstance) \
((__nFInstance->nf_type) == OpenAPI_nf_type_NRF)
char *id; /* NFInstanceId */
char *id; /* NFInstanceId */
OpenAPI_nf_type_e nf_type;
OpenAPI_nf_status_e nf_status;
@ -103,12 +118,12 @@ typedef struct ogs_sbi_nf_instance_s {
ogs_list_t nf_service_list;
void *client; /* only used in CLIENT */
unsigned int reference_count; /* reference count for memory free */
void *client; /* only used in CLIENT */
unsigned int reference_count; /* reference count for memory free */
ogs_list_t nf_info_list;
OpenAPI_nf_profile_t *nf_profile; /* stored NF Profile */
OpenAPI_nf_profile_t *nf_profile; /* stored NF Profile */
} ogs_sbi_nf_instance_t;
typedef struct ogs_sbi_nf_type_array_s {
@ -196,19 +211,19 @@ typedef struct ogs_sbi_subscription_s {
int validity_duration;
} time;
ogs_timer_t *t_validity; /* check validation */
ogs_timer_t *t_validity; /* check validation */
char *id; /* SubscriptionId */
char *req_nf_instance_id; /* reqNfInstanceId */
OpenAPI_nf_type_e req_nf_type; /* reqNfType */
char *id; /* SubscriptionId */
char *req_nf_instance_id; /* reqNfInstanceId */
OpenAPI_nf_type_e req_nf_type; /* reqNfType */
OpenAPI_nf_status_e nf_status;
char *notification_uri;
struct {
OpenAPI_nf_type_e nf_type; /* nfType */
OpenAPI_nf_type_e nf_type; /* nfType */
} subscr_cond;
void *client; /* only used in SERVER */
void *client; /* only used in SERVER */
} ogs_sbi_subscription_t;
typedef struct ogs_sbi_smf_info_s {
@ -249,7 +264,10 @@ typedef struct ogs_sbi_nf_info_s {
void ogs_sbi_context_init(void);
void ogs_sbi_context_final(void);
ogs_sbi_context_t *ogs_sbi_self(void);
int ogs_sbi_context_parse_config(const char *local, const char *remote);
int ogs_sbi_context_parse_config(
const char *local, const char *nrf, const char *scp);
ogs_sbi_nf_instance_t *ogs_sbi_scp_instance(void);
ogs_sbi_nf_instance_t *ogs_sbi_nf_instance_add(void);
void ogs_sbi_nf_instance_set_id(ogs_sbi_nf_instance_t *nf_instance, char *id);

View File

@ -29,7 +29,6 @@ char *ogs_uridup(bool https, ogs_sockaddr_t *addr, ogs_sbi_header_t *h)
char *hostname = NULL;
ogs_assert(addr);
ogs_assert(h);
p = uri;
last = uri + OGS_HUGE_LEN;
@ -61,16 +60,18 @@ char *ogs_uridup(bool https, ogs_sockaddr_t *addr, ogs_sbi_header_t *h)
}
/* API */
ogs_assert(h->service.name);
p = ogs_slprintf(p, last, "/%s", h->service.name);
ogs_assert(h->api.version);
p = ogs_slprintf(p, last, "/%s", h->api.version);
if (h) {
ogs_assert(h->service.name);
p = ogs_slprintf(p, last, "/%s", h->service.name);
ogs_assert(h->api.version);
p = ogs_slprintf(p, last, "/%s", h->api.version);
/* Resource */
ogs_assert(h->resource.component[0]);
for (i = 0; i < OGS_SBI_MAX_NUM_OF_RESOURCE_COMPONENT &&
h->resource.component[i]; i++)
p = ogs_slprintf(p, last, "/%s", h->resource.component[i]);
/* Resource */
ogs_assert(h->resource.component[0]);
for (i = 0; i < OGS_SBI_MAX_NUM_OF_RESOURCE_COMPONENT &&
h->resource.component[i]; i++)
p = ogs_slprintf(p, last, "/%s", h->resource.component[i]);
}
return ogs_strdup(uri);
}
@ -81,7 +82,6 @@ char *ogs_sbi_server_uri(ogs_sbi_server_t *server, ogs_sbi_header_t *h)
bool https = false;
ogs_assert(server);
ogs_assert(h);
if (server->tls.key && server->tls.pem)
https = true;
@ -100,7 +100,6 @@ char *ogs_sbi_client_uri(ogs_sbi_client_t *client, ogs_sbi_header_t *h)
bool https = false;
ogs_assert(client);
ogs_assert(h);
if (client->tls.key && client->tls.pem)
https = true;
@ -108,6 +107,11 @@ char *ogs_sbi_client_uri(ogs_sbi_client_t *client, ogs_sbi_header_t *h)
return ogs_uridup(https, client->node.addr, h);
}
char *ogs_sbi_client_apiroot(ogs_sbi_client_t *client)
{
return ogs_sbi_client_uri(client, NULL);
}
/**
* Returns a url-decoded version of str
* IMPORTANT: be sure to free() the returned string after use
@ -207,6 +211,57 @@ ogs_sockaddr_t *ogs_sbi_getaddr_from_uri(char *uri)
return addr;
}
char *ogs_sbi_getpath_from_uri(char *uri)
{
int rv;
struct yuarel yuarel;
char *p = NULL;
char *path = NULL;
p = ogs_strdup(uri);
rv = yuarel_parse(&yuarel, p);
if (rv != OGS_OK) {
ogs_free(p);
ogs_error("yuarel_parse() failed [%s]", uri);
return NULL;
}
if (!yuarel.scheme) {
ogs_error("No http.scheme found [%s]", uri);
ogs_free(p);
return NULL;
}
if (strcmp(yuarel.scheme, "https") == 0) {
} else if (strcmp(yuarel.scheme, "http") == 0) {
} else {
ogs_error("Invalid http.scheme [%s:%s]", yuarel.scheme, uri);
ogs_free(p);
return NULL;
}
if (!yuarel.host) {
ogs_error("No http.host found [%s]", uri);
ogs_free(p);
return NULL;
}
if (!yuarel.path) {
ogs_error("No http.path found [%s]", uri);
ogs_free(p);
return NULL;
}
path = ogs_strdup(yuarel.path);
ogs_assert(path);
ogs_free(p);
return path;
}
char *ogs_sbi_bitrate_to_string(uint64_t bitrate, int unit)
{
if (unit == OGS_SBI_BITRATE_KBPS) {

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_sbi_server_uri(ogs_sbi_server_t *server, ogs_sbi_header_t *h);
char *ogs_sbi_client_apiroot(ogs_sbi_client_t *client);
char *ogs_sbi_client_uri(ogs_sbi_client_t *client, ogs_sbi_header_t *h);
char *ogs_sbi_parse_uri(char *uri, const char *delim, char **saveptr);
ogs_sockaddr_t *ogs_sbi_getaddr_from_uri(char *uri);
char *ogs_sbi_getpath_from_uri(char *uri);
#define OGS_SBI_BITRATE_BPS 0
#define OGS_SBI_BITRATE_KBPS 1

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

View File

@ -274,6 +274,21 @@ extern "C" {
#define OGS_SBI_APPLICATION_5GNAS_TYPE "vnd.3gpp.5gnas"
#define OGS_SBI_APPLICATION_NGAP_TYPE "vnd.3gpp.ngap"
#define OGS_SBI_CUSTOM_3GPP_COMMON "3gpp-Sbi-"
#define OGS_SBI_CUSTOM_MESSAGE_PRIORITY "3gpp-Sbi-Message-Priority"
#define OGS_SBI_CUSTOM_CALLBACK "3gpp-Sbi-Callback"
#define OGS_SBI_CUSTOM_TARGET_APIROOT "3gpp-Sbi-Target-apiRoot"
#define OGS_SBI_CUSTOM_ROUTING_BINDING "3gpp-Sbi-Routing-Binding"
#define OGS_SBI_CUSTOM_BINDING "3gpp-Sbi-Binding"
#define OGS_SBI_CUSTOM_DISCOVERY_COMMON "3gpp-Sbi-Discovery-"
#define OGS_SBI_CUSTOM_PRODUCER_ID "3gpp-Sbi-Producer-Id"
#define OGS_SBI_CUSTOM_OCI "3gpp-Sbi-Oci"
#define OGS_SBI_CUSTOM_CLIENT_CREDENTIALS "3gpp-Sbi-Client-Credentials"
#define OGS_SBI_CUSTOM_NRF_URI "3gpp-Sbi-Nrf-Uri"
#define OGS_SBI_CUSTOM_TARGET_NF_ID "3gpp-Sbi-Target-Nf-Id"
#define OGS_SBI_CUSTOM_ACCESS_SCOPE "3gpp-Sbi-Access-Scope"
#define OGS_SBI_CUSTOM_ACCESS_TOKEN "3gpp-Sbi-Access-Token"
#define OGS_SBI_CONTENT_JSON_TYPE \
OGS_SBI_APPLICATION_TYPE "/" OGS_SBI_APPLICATION_JSON_TYPE
#define OGS_SBI_CONTENT_PROBLEM_TYPE \
@ -477,6 +492,8 @@ ogs_pkbuf_t *ogs_sbi_find_part_by_content_id(
int ogs_sbi_parse_header(ogs_sbi_message_t *message, ogs_sbi_header_t *header);
void ogs_sbi_header_free(ogs_sbi_header_t *h);
void ogs_sbi_http_hash_free(ogs_hash_t *hash);
#ifdef __cplusplus
}
#endif

View File

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

View File

@ -33,6 +33,8 @@ static int server_start(ogs_sbi_server_t *server,
int (*cb)(ogs_sbi_request_t *request, void *data));
static void server_stop(ogs_sbi_server_t *server);
static bool server_send_rspmem_persistent(
ogs_sbi_stream_t *stream, ogs_sbi_response_t *response);
static bool server_send_response(
ogs_sbi_stream_t *stream, ogs_sbi_response_t *response);
@ -45,7 +47,9 @@ const ogs_sbi_server_actions_t ogs_nghttp2_server_actions = {
server_start,
server_stop,
server_send_rspmem_persistent,
server_send_response,
server_from_stream,
};
@ -284,7 +288,7 @@ static ssize_t response_read_callback(nghttp2_session *session,
return response->http.content_length;
}
static bool server_send_response(
static bool server_send_rspmem_persistent(
ogs_sbi_stream_t *stream, ogs_sbi_response_t *response)
{
ogs_sbi_session_t *sbi_sess = NULL;
@ -299,11 +303,17 @@ static bool server_send_response(
char srv_version[128];
char clen[128];
ogs_assert(stream);
ogs_assert(response);
stream = ogs_pool_cycle(&stream_pool, stream);
if (!stream) {
ogs_error("stream has already been closed");
return true;
}
sbi_sess = stream->session;
ogs_assert(sbi_sess);
ogs_assert(sbi_sess->session);
ogs_assert(response);
sock = sbi_sess->sock;
ogs_assert(sock);
@ -375,12 +385,25 @@ static bool server_send_response(
session_remove(sbi_sess);
}
ogs_sbi_response_free(response);
ogs_free(nva);
return true;
}
static bool server_send_response(
ogs_sbi_stream_t *stream, ogs_sbi_response_t *response)
{
bool rc;
ogs_assert(response);
rc = server_send_rspmem_persistent(stream, response);
ogs_sbi_response_free(response);
return rc;
}
static ogs_sbi_server_t *server_from_stream(ogs_sbi_stream_t *stream)
{
ogs_sbi_session_t *sbi_sess = NULL;

View File

@ -68,13 +68,12 @@ bool ogs_sbi_send(ogs_sbi_nf_instance_t *nf_instance,
ogs_freeaddrinfo(addr);
}
/* ogs_sbi_xact_remove() will call ogs_sbi_request_free()
* As such, we'll use ogs_sbi_client_send_reqmem_persistent() */
ogs_expect_or_return_val(true ==
ogs_sbi_client_send_request(
ogs_sbi_scp_send_reqmem_persistent(
client, client_cb, request, xact), false);
/* Prevent ogs_sbi_request_free() in ogs_sbi_xact_remove() */
xact->request = NULL;
return true;
}
@ -125,6 +124,23 @@ bool ogs_sbi_discover_and_send(ogs_sbi_xact_t *xact,
return false;
}
bool ogs_nnrf_nfm_send_nf_register(
ogs_sbi_nf_instance_t *nf_instance, ogs_sbi_request_t *(*build)(void))
{
ogs_sbi_request_t *request = NULL;
ogs_sbi_client_t *client = NULL;
ogs_assert(nf_instance);
client = nf_instance->client;
ogs_assert(client);
ogs_assert(build);
request = (*build)();
ogs_expect_or_return_val(request, false);
return ogs_sbi_scp_send_request(client, client->cb, request, nf_instance);
}
bool ogs_nnrf_nfm_send_nf_update(ogs_sbi_nf_instance_t *nf_instance)
{
ogs_sbi_request_t *request = NULL;
@ -137,8 +153,7 @@ bool ogs_nnrf_nfm_send_nf_update(ogs_sbi_nf_instance_t *nf_instance)
request = ogs_nnrf_nfm_build_update();
ogs_expect_or_return_val(request, false);
return ogs_sbi_client_send_request(
client, client->cb, request, nf_instance);
return ogs_sbi_scp_send_request(client, client->cb, request, nf_instance);
}
bool ogs_nnrf_nfm_send_nf_de_register(ogs_sbi_nf_instance_t *nf_instance)
@ -153,8 +168,7 @@ bool ogs_nnrf_nfm_send_nf_de_register(ogs_sbi_nf_instance_t *nf_instance)
request = ogs_nnrf_nfm_build_de_register();
ogs_expect_or_return_val(request, false);
return ogs_sbi_client_send_request(
client, client->cb, request, nf_instance);
return ogs_sbi_scp_send_request(client, client->cb, request, nf_instance);
}
bool ogs_nnrf_nfm_send_nf_status_subscribe(ogs_sbi_client_t *client,
@ -180,7 +194,7 @@ bool ogs_nnrf_nfm_send_nf_status_subscribe(ogs_sbi_client_t *client,
request = ogs_nnrf_nfm_build_status_subscribe(subscription);
ogs_expect_or_return_val(request, false);
return ogs_sbi_client_send_request(
return ogs_sbi_scp_send_request(
client, client->cb, request, subscription);
}
@ -191,13 +205,14 @@ bool ogs_nnrf_nfm_send_nf_status_unsubscribe(
ogs_sbi_client_t *client = NULL;
ogs_assert(subscription);
client = subscription->client;
ogs_assert(client);
request = ogs_nnrf_nfm_build_status_unsubscribe(subscription);
ogs_expect_or_return_val(request, false);
return ogs_sbi_client_send_request(
client = subscription->client;
ogs_assert(client);
return ogs_sbi_scp_send_request(
client, client->cb, request, subscription);
}
@ -208,15 +223,15 @@ bool ogs_nnrf_disc_send_nf_discover(ogs_sbi_nf_instance_t *nf_instance,
ogs_sbi_request_t *request = NULL;
ogs_assert(nf_instance);
ogs_assert(nf_instance->nf_type);
client = nf_instance->client;
ogs_assert(client);
ogs_assert(ogs_sbi_self()->nf_instance);
request = ogs_nnrf_disc_build_discover(
target_nf_type, ogs_sbi_self()->nf_instance->nf_type);
ogs_expect_or_return_val(request, false);
client = nf_instance->client;
ogs_assert(client);
return ogs_sbi_client_send_request(client, client->cb, request, data);
}

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,
ogs_fsm_handler_t nf_state_registered, ogs_sbi_client_cb_f client_cb);
bool ogs_nnrf_nfm_send_nf_register(
ogs_sbi_nf_instance_t *nf_instance, ogs_sbi_request_t *(*build)(void));
bool ogs_nnrf_nfm_send_nf_update(ogs_sbi_nf_instance_t *nf_instance);
bool ogs_nnrf_nfm_send_nf_de_register(ogs_sbi_nf_instance_t *nf_instance);

View File

@ -133,6 +133,12 @@ void ogs_sbi_server_stop_all(void)
ogs_sbi_server_actions.stop(server);
}
bool ogs_sbi_server_send_rspmem_persistent(
ogs_sbi_stream_t *stream, ogs_sbi_response_t *response)
{
return ogs_sbi_server_actions.send_rspmem_persistent(stream, response);
}
bool ogs_sbi_server_send_response(
ogs_sbi_stream_t *stream, ogs_sbi_response_t *response)
{

View File

@ -53,6 +53,8 @@ typedef struct ogs_sbi_server_actions_s {
int (*cb)(ogs_sbi_request_t *request, void *data));
void (*stop)(ogs_sbi_server_t *server);
bool (*send_rspmem_persistent)(
ogs_sbi_stream_t *stream, ogs_sbi_response_t *response);
bool (*send_response)(
ogs_sbi_stream_t *stream, ogs_sbi_response_t *response);
@ -74,6 +76,8 @@ int ogs_sbi_server_start_all(
int (*cb)(ogs_sbi_request_t *request, void *data));
void ogs_sbi_server_stop_all(void);
bool ogs_sbi_server_send_rspmem_persistent(
ogs_sbi_stream_t *stream, ogs_sbi_response_t *response);
bool ogs_sbi_server_send_response(
ogs_sbi_stream_t *stream, ogs_sbi_response_t *response);
bool ogs_sbi_server_send_error(ogs_sbi_stream_t *stream,

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

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

View File

@ -119,7 +119,7 @@ void amf_sctp_event_push(amf_event_e id,
rv = ogs_queue_push(ogs_app()->queue, e);
if (rv != OGS_OK) {
ogs_warn("ogs_queue_push() failed:%d", (int)rv);
ogs_error("ogs_queue_push() failed:%d", (int)rv);
ogs_free(e->ngap.addr);
if (e->pkbuf)
ogs_pkbuf_free(e->pkbuf);

View File

@ -35,7 +35,7 @@ int amf_initialize()
amf_context_init();
amf_event_init();
rv = ogs_sbi_context_parse_config("amf", "nrf");
rv = ogs_sbi_context_parse_config("amf", "nrf", "scp");
if (rv != OGS_OK) return rv;
rv = ogs_metrics_context_parse_config();

View File

@ -61,16 +61,18 @@ void amf_nf_state_initial(ogs_fsm_t *s, amf_event_t *e)
nf_instance = e->sbi.data;
ogs_assert(nf_instance);
nf_instance->t_registration_interval = ogs_timer_add(ogs_app()->timer_mgr,
amf_timer_nf_instance_registration_interval, nf_instance);
ogs_assert(nf_instance->t_registration_interval);
nf_instance->t_registration_interval->cb =
amf_timer_nf_instance_registration_interval;
nf_instance->t_heartbeat_interval = ogs_timer_add(ogs_app()->timer_mgr,
amf_timer_nf_instance_heartbeat_interval, nf_instance);
ogs_assert(nf_instance->t_heartbeat_interval);
nf_instance->t_heartbeat_interval->cb =
amf_timer_nf_instance_heartbeat_interval;
nf_instance->t_no_heartbeat = ogs_timer_add(ogs_app()->timer_mgr,
amf_timer_nf_instance_no_heartbeat, nf_instance);
ogs_assert(nf_instance->t_no_heartbeat);
nf_instance->t_no_heartbeat->cb = amf_timer_nf_instance_no_heartbeat;
nf_instance->t_validity = ogs_timer_add(ogs_app()->timer_mgr,
amf_timer_nf_instance_validity, nf_instance);
ogs_assert(nf_instance->t_validity);
nf_instance->t_validity->cb = amf_timer_nf_instance_validity;
if (NF_INSTANCE_IS_NRF(nf_instance)) {
OGS_FSM_TRAN(s, &amf_nf_state_will_register);
@ -82,10 +84,20 @@ void amf_nf_state_initial(ogs_fsm_t *s, amf_event_t *e)
void amf_nf_state_final(ogs_fsm_t *s, amf_event_t *e)
{
ogs_sbi_nf_instance_t *nf_instance = NULL;
ogs_assert(s);
ogs_assert(e);
amf_sm_debug(e);
nf_instance = e->sbi.data;
ogs_assert(nf_instance);
ogs_timer_delete(nf_instance->t_registration_interval);
ogs_timer_delete(nf_instance->t_heartbeat_interval);
ogs_timer_delete(nf_instance->t_no_heartbeat);
ogs_timer_delete(nf_instance->t_validity);
}
void amf_nf_state_will_register(ogs_fsm_t *s, amf_event_t *e)
@ -110,7 +122,8 @@ void amf_nf_state_will_register(ogs_fsm_t *s, amf_event_t *e)
ogs_timer_start(nf_instance->t_registration_interval,
ogs_app()->time.message.sbi.nf_register_interval);
ogs_assert(true == amf_nnrf_nfm_send_nf_register(nf_instance));
ogs_assert(true == ogs_nnrf_nfm_send_nf_register(
nf_instance, amf_nnrf_nfm_build_register));
break;
case OGS_FSM_EXIT_SIG:
@ -166,7 +179,8 @@ void amf_nf_state_will_register(ogs_fsm_t *s, amf_event_t *e)
ogs_timer_start(nf_instance->t_registration_interval,
ogs_app()->time.message.sbi.nf_register_interval);
ogs_assert(true == amf_nnrf_nfm_send_nf_register(nf_instance));
ogs_assert(true == ogs_nnrf_nfm_send_nf_register(
nf_instance, amf_nnrf_nfm_build_register));
break;
default:

View File

@ -128,7 +128,7 @@ int ngap_send_to_5gsm(amf_ue_t *amf_ue, ogs_pkbuf_t *esmbuf)
e->pkbuf = esmbuf;
rv = ogs_queue_push(ogs_app()->queue, e);
if (rv != OGS_OK) {
ogs_warn("ogs_queue_push() failed:%d", (int)rv);
ogs_error("ogs_queue_push() failed:%d", (int)rv);
ogs_pkbuf_free(e->pkbuf);
amf_event_free(e);
}
@ -214,7 +214,7 @@ int ngap_send_to_nas(ran_ue_t *ran_ue,
e->pkbuf = nasbuf;
rv = ogs_queue_push(ogs_app()->queue, e);
if (rv != OGS_OK) {
ogs_warn("ngap_send_to_nas() failed:%d", (int)rv);
ogs_error("ngap_send_to_nas() failed:%d", (int)rv);
ogs_pkbuf_free(e->pkbuf);
amf_event_free(e);
}

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);
if (rv != OGS_OK) {
ogs_warn("ogs_queue_push() failed:%d", (int)rv);
ogs_error("ogs_queue_push() failed:%d", (int)rv);
ogs_sbi_request_free(request);
amf_event_free(e);
return OGS_ERROR;
}
@ -45,11 +46,18 @@ static int server_cb(ogs_sbi_request_t *request, void *data)
return OGS_OK;
}
static int client_cb(ogs_sbi_response_t *response, void *data)
static int client_cb(int status, ogs_sbi_response_t *response, void *data)
{
amf_event_t *e = NULL;
int rv;
if (status != OGS_OK) {
ogs_log_message(
status == OGS_DONE ? OGS_LOG_DEBUG : OGS_LOG_WARN, 0,
"client_cb() failed [%d]", status);
return OGS_ERROR;
}
ogs_assert(response);
e = amf_event_new(AMF_EVT_SBI_CLIENT);
@ -59,7 +67,8 @@ static int client_cb(ogs_sbi_response_t *response, void *data)
rv = ogs_queue_push(ogs_app()->queue, e);
if (rv != OGS_OK) {
ogs_warn("ogs_queue_push() failed:%d", (int)rv);
ogs_error("ogs_queue_push() failed:%d", (int)rv);
ogs_sbi_response_free(response);
amf_event_free(e);
return OGS_ERROR;
}
@ -91,20 +100,30 @@ int amf_sbi_open(void)
(char*)OGS_SBI_API_V1_0_0, NULL);
ogs_sbi_nf_service_add_allowed_nf_type(service, OpenAPI_nf_type_SMF);
/* Initialize SCP NF Instance */
nf_instance = ogs_sbi_self()->scp_instance;
if (nf_instance) {
ogs_sbi_client_t *client = NULL;
/* Client callback is only used when NF sends to SCP */
client = nf_instance->client;
ogs_assert(client);
client->cb = client_cb;
}
/* Initialize NRF NF Instance */
ogs_list_for_each(&ogs_sbi_self()->nf_instance_list, nf_instance) {
if (NF_INSTANCE_IS_NRF(nf_instance)) {
ogs_sbi_client_t *client = NULL;
nf_instance = ogs_sbi_self()->nrf_instance;
if (nf_instance) {
ogs_sbi_client_t *client = NULL;
/* Client callback is only used when NF sends to NRF */
client = nf_instance->client;
ogs_assert(client);
client->cb = client_cb;
/* Client callback is only used when NF sends to NRF */
client = nf_instance->client;
ogs_assert(client);
client->cb = client_cb;
/* NFRegister is sent and the response is received
* by the above client callback. */
amf_nf_fsm_init(nf_instance);
}
/* NFRegister is sent and the response is received
* by the above client callback. */
amf_nf_fsm_init(nf_instance);
}
return OGS_OK;
@ -112,25 +131,10 @@ int amf_sbi_open(void)
void amf_sbi_close(void)
{
ogs_sbi_client_stop_all();
ogs_sbi_server_stop_all();
}
bool amf_nnrf_nfm_send_nf_register(ogs_sbi_nf_instance_t *nf_instance)
{
ogs_sbi_request_t *request = NULL;
ogs_sbi_client_t *client = NULL;
ogs_assert(nf_instance);
client = nf_instance->client;
ogs_assert(client);
request = amf_nnrf_nfm_build_register();
ogs_expect_or_return_val(request, false);
return ogs_sbi_client_send_request(
client, client->cb, request, nf_instance);
}
bool amf_sbi_send(ogs_sbi_nf_instance_t *nf_instance, ogs_sbi_xact_t *xact)
{
return ogs_sbi_send(nf_instance, client_cb, xact);
@ -203,13 +207,21 @@ bool amf_sess_sbi_discover_and_send(OpenAPI_nf_type_e target_nf_type,
return true;
}
static int client_discover_cb(ogs_sbi_response_t *response, void *data)
static int client_discover_cb(
int status, ogs_sbi_response_t *response, void *data)
{
int rv;
ogs_sbi_message_t message;
amf_sess_t *sess = data;
if (status != OGS_OK) {
ogs_log_message(
status == OGS_DONE ? OGS_LOG_DEBUG : OGS_LOG_WARN, 0,
"client_discover_cb() failed [%d]", status);
return OGS_ERROR;
}
ogs_assert(response);
ogs_assert(sess);
ogs_assert(sess->sbi.type == OGS_SBI_OBJ_SESS_TYPE);
@ -395,12 +407,19 @@ void amf_sbi_send_release_all_sessions(amf_ue_t *amf_ue, int state)
}
}
static int client_notify_cb(ogs_sbi_response_t *response, void *data)
static int client_notify_cb(
int status, ogs_sbi_response_t *response, void *data)
{
int rv;
ogs_sbi_message_t message;
if (status != OGS_OK) {
ogs_log_message(
status == OGS_DONE ? OGS_LOG_DEBUG : OGS_LOG_WARN, 0,
"client_notify_cb() failed [%d]", status);
return OGS_ERROR;
}
ogs_assert(response);
rv = ogs_sbi_parse_response(&message, response);

View File

@ -34,8 +34,6 @@ extern "C" {
int amf_sbi_open(void);
void amf_sbi_close(void);
bool amf_nnrf_nfm_send_nf_register(ogs_sbi_nf_instance_t *nf_instance);
bool amf_sbi_send(ogs_sbi_nf_instance_t *nf_instance, ogs_sbi_xact_t *xact);
bool amf_ue_sbi_discover_and_send(OpenAPI_nf_type_e target_nf_type,
amf_ue_t *amf_ue, void *data,

View File

@ -109,7 +109,7 @@ void amf_timer_ng_delayed_send(void *data)
rv = ogs_queue_push(ogs_app()->queue, e);
if (rv != OGS_OK) {
ogs_warn("ogs_queue_push() failed:%d", (int)rv);
ogs_error("ogs_queue_push() failed:%d", (int)rv);
ogs_timer_delete(e->timer);
amf_event_free(e);
}
@ -153,7 +153,7 @@ static void sbi_timer_send_event(int timer_id, void *data)
rv = ogs_queue_push(ogs_app()->queue, e);
if (rv != OGS_OK) {
ogs_warn("ogs_queue_push() failed [%d] in %s",
ogs_error("ogs_queue_push() failed [%d] in %s",
(int)rv, amf_timer_get_name(e->timer_id));
amf_event_free(e);
}
@ -203,7 +203,7 @@ static void gmm_timer_event_send(
rv = ogs_queue_push(ogs_app()->queue, e);
if (rv != OGS_OK) {
ogs_warn("ogs_queue_push() failed:%d", (int)rv);
ogs_error("ogs_queue_push() failed:%d", (int)rv);
amf_event_free(e);
}
}
@ -250,7 +250,7 @@ void amf_timer_ng_holding_timer_expire(void *data)
rv = ogs_queue_push(ogs_app()->queue, e);
if (rv != OGS_OK) {
ogs_warn("ogs_queue_push() failed:%d", (int)rv);
ogs_error("ogs_queue_push() failed:%d", (int)rv);
amf_event_free(e);
}
}

View File

@ -32,7 +32,7 @@ int ausf_initialize()
ausf_context_init();
ausf_event_init();
rv = ogs_sbi_context_parse_config("ausf", "nrf");
rv = ogs_sbi_context_parse_config("ausf", "nrf", "scp");
if (rv != OGS_OK) return rv;
rv = ausf_context_parse_config();

View File

@ -61,16 +61,18 @@ void ausf_nf_state_initial(ogs_fsm_t *s, ausf_event_t *e)
nf_instance = e->sbi.data;
ogs_assert(nf_instance);
nf_instance->t_registration_interval = ogs_timer_add(ogs_app()->timer_mgr,
ausf_timer_nf_instance_registration_interval, nf_instance);
ogs_assert(nf_instance->t_registration_interval);
nf_instance->t_registration_interval->cb =
ausf_timer_nf_instance_registration_interval;
nf_instance->t_heartbeat_interval = ogs_timer_add(ogs_app()->timer_mgr,
ausf_timer_nf_instance_heartbeat_interval, nf_instance);
ogs_assert(nf_instance->t_heartbeat_interval);
nf_instance->t_heartbeat_interval->cb =
ausf_timer_nf_instance_heartbeat_interval;
nf_instance->t_no_heartbeat = ogs_timer_add(ogs_app()->timer_mgr,
ausf_timer_nf_instance_no_heartbeat, nf_instance);
ogs_assert(nf_instance->t_no_heartbeat);
nf_instance->t_no_heartbeat->cb = ausf_timer_nf_instance_no_heartbeat;
nf_instance->t_validity = ogs_timer_add(ogs_app()->timer_mgr,
ausf_timer_nf_instance_validity, nf_instance);
ogs_assert(nf_instance->t_validity);
nf_instance->t_validity->cb = ausf_timer_nf_instance_validity;
if (NF_INSTANCE_IS_NRF(nf_instance)) {
OGS_FSM_TRAN(s, &ausf_nf_state_will_register);
@ -82,10 +84,20 @@ void ausf_nf_state_initial(ogs_fsm_t *s, ausf_event_t *e)
void ausf_nf_state_final(ogs_fsm_t *s, ausf_event_t *e)
{
ogs_sbi_nf_instance_t *nf_instance = NULL;
ogs_assert(s);
ogs_assert(e);
ausf_sm_debug(e);
nf_instance = e->sbi.data;
ogs_assert(nf_instance);
ogs_timer_delete(nf_instance->t_registration_interval);
ogs_timer_delete(nf_instance->t_heartbeat_interval);
ogs_timer_delete(nf_instance->t_no_heartbeat);
ogs_timer_delete(nf_instance->t_validity);
}
void ausf_nf_state_will_register(ogs_fsm_t *s, ausf_event_t *e)
@ -110,7 +122,8 @@ void ausf_nf_state_will_register(ogs_fsm_t *s, ausf_event_t *e)
ogs_timer_start(nf_instance->t_registration_interval,
ogs_app()->time.message.sbi.nf_register_interval);
ogs_assert(true == ausf_nnrf_nfm_send_nf_register(nf_instance));
ogs_assert(true == ogs_nnrf_nfm_send_nf_register(
nf_instance, ausf_nnrf_nfm_build_register));
break;
case OGS_FSM_EXIT_SIG:
@ -166,7 +179,8 @@ void ausf_nf_state_will_register(ogs_fsm_t *s, ausf_event_t *e)
ogs_timer_start(nf_instance->t_registration_interval,
ogs_app()->time.message.sbi.nf_register_interval);
ogs_assert(true == ausf_nnrf_nfm_send_nf_register(nf_instance));
ogs_assert(true == ogs_nnrf_nfm_send_nf_register(
nf_instance, ausf_nnrf_nfm_build_register));
break;
default:

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);
if (rv != OGS_OK) {
ogs_warn("ogs_queue_push() failed:%d", (int)rv);
ogs_error("ogs_queue_push() failed:%d", (int)rv);
ogs_sbi_request_free(request);
ausf_event_free(e);
return OGS_ERROR;
}
@ -43,11 +44,18 @@ static int server_cb(ogs_sbi_request_t *request, void *data)
return OGS_OK;
}
static int client_cb(ogs_sbi_response_t *response, void *data)
static int client_cb(int status, ogs_sbi_response_t *response, void *data)
{
ausf_event_t *e = NULL;
int rv;
if (status != OGS_OK) {
ogs_log_message(
status == OGS_DONE ? OGS_LOG_DEBUG : OGS_LOG_WARN, 0,
"client_cb() failed [%d]", status);
return OGS_ERROR;
}
ogs_assert(response);
e = ausf_event_new(AUSF_EVT_SBI_CLIENT);
@ -57,7 +65,8 @@ static int client_cb(ogs_sbi_response_t *response, void *data)
rv = ogs_queue_push(ogs_app()->queue, e);
if (rv != OGS_OK) {
ogs_warn("ogs_queue_push() failed:%d", (int)rv);
ogs_error("ogs_queue_push() failed:%d", (int)rv);
ogs_sbi_response_free(response);
ausf_event_free(e);
return OGS_ERROR;
}
@ -110,25 +119,10 @@ int ausf_sbi_open(void)
void ausf_sbi_close(void)
{
ogs_sbi_client_stop_all();
ogs_sbi_server_stop_all();
}
bool ausf_nnrf_nfm_send_nf_register(ogs_sbi_nf_instance_t *nf_instance)
{
ogs_sbi_request_t *request = NULL;
ogs_sbi_client_t *client = NULL;
ogs_assert(nf_instance);
client = nf_instance->client;
ogs_assert(client);
request = ausf_nnrf_nfm_build_register();
ogs_expect_or_return_val(request, false);
return ogs_sbi_client_send_request(
client, client->cb, request, nf_instance);
}
bool ausf_sbi_send(ogs_sbi_nf_instance_t *nf_instance, ogs_sbi_xact_t *xact)
{
return ogs_sbi_send(nf_instance, client_cb, xact);

View File

@ -30,8 +30,6 @@ extern "C" {
int ausf_sbi_open(void);
void ausf_sbi_close(void);
bool ausf_nnrf_nfm_send_nf_register(ogs_sbi_nf_instance_t *nf_instance);
bool ausf_sbi_send(ogs_sbi_nf_instance_t *nf_instance, ogs_sbi_xact_t *xact);
bool ausf_sbi_discover_and_send(OpenAPI_nf_type_e target_nf_type,
ausf_ue_t *ausf_ue, ogs_sbi_stream_t *stream, void *data,

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);
if (rv != OGS_OK) {
ogs_warn("ogs_queue_push() failed [%d] in %s",
ogs_error("ogs_queue_push() failed [%d] in %s",
(int)rv, ausf_timer_get_name(e->timer_id));
ausf_event_free(e);
}

View File

@ -34,7 +34,7 @@ int bsf_initialize()
bsf_context_init();
bsf_event_init();
rv = ogs_sbi_context_parse_config("bsf", "nrf");
rv = ogs_sbi_context_parse_config("bsf", "nrf", "scp");
if (rv != OGS_OK) return rv;
rv = bsf_context_parse_config();

View File

@ -61,16 +61,18 @@ void bsf_nf_state_initial(ogs_fsm_t *s, bsf_event_t *e)
nf_instance = e->sbi.data;
ogs_assert(nf_instance);
nf_instance->t_registration_interval = ogs_timer_add(ogs_app()->timer_mgr,
bsf_timer_nf_instance_registration_interval, nf_instance);
ogs_assert(nf_instance->t_registration_interval);
nf_instance->t_registration_interval->cb =
bsf_timer_nf_instance_registration_interval;
nf_instance->t_heartbeat_interval = ogs_timer_add(ogs_app()->timer_mgr,
bsf_timer_nf_instance_heartbeat_interval, nf_instance);
ogs_assert(nf_instance->t_heartbeat_interval);
nf_instance->t_heartbeat_interval->cb =
bsf_timer_nf_instance_heartbeat_interval;
nf_instance->t_no_heartbeat = ogs_timer_add(ogs_app()->timer_mgr,
bsf_timer_nf_instance_no_heartbeat, nf_instance);
ogs_assert(nf_instance->t_no_heartbeat);
nf_instance->t_no_heartbeat->cb = bsf_timer_nf_instance_no_heartbeat;
nf_instance->t_validity = ogs_timer_add(ogs_app()->timer_mgr,
bsf_timer_nf_instance_validity, nf_instance);
ogs_assert(nf_instance->t_validity);
nf_instance->t_validity->cb = bsf_timer_nf_instance_validity;
if (NF_INSTANCE_IS_NRF(nf_instance)) {
OGS_FSM_TRAN(s, &bsf_nf_state_will_register);
@ -82,10 +84,20 @@ void bsf_nf_state_initial(ogs_fsm_t *s, bsf_event_t *e)
void bsf_nf_state_final(ogs_fsm_t *s, bsf_event_t *e)
{
ogs_sbi_nf_instance_t *nf_instance = NULL;
ogs_assert(s);
ogs_assert(e);
bsf_sm_debug(e);
nf_instance = e->sbi.data;
ogs_assert(nf_instance);
ogs_timer_delete(nf_instance->t_registration_interval);
ogs_timer_delete(nf_instance->t_heartbeat_interval);
ogs_timer_delete(nf_instance->t_no_heartbeat);
ogs_timer_delete(nf_instance->t_validity);
}
void bsf_nf_state_will_register(ogs_fsm_t *s, bsf_event_t *e)
@ -110,7 +122,8 @@ void bsf_nf_state_will_register(ogs_fsm_t *s, bsf_event_t *e)
ogs_timer_start(nf_instance->t_registration_interval,
ogs_app()->time.message.sbi.nf_register_interval);
ogs_assert(true == bsf_nnrf_nfm_send_nf_register(nf_instance));
ogs_assert(true == ogs_nnrf_nfm_send_nf_register(
nf_instance, bsf_nnrf_nfm_build_register));
break;
case OGS_FSM_EXIT_SIG:
@ -166,7 +179,8 @@ void bsf_nf_state_will_register(ogs_fsm_t *s, bsf_event_t *e)
ogs_timer_start(nf_instance->t_registration_interval,
ogs_app()->time.message.sbi.nf_register_interval);
ogs_assert(true == bsf_nnrf_nfm_send_nf_register(nf_instance));
ogs_assert(true == ogs_nnrf_nfm_send_nf_register(
nf_instance, bsf_nnrf_nfm_build_register));
break;
default:

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);
if (rv != OGS_OK) {
ogs_warn("ogs_queue_push() failed:%d", (int)rv);
ogs_error("ogs_queue_push() failed:%d", (int)rv);
ogs_sbi_request_free(request);
bsf_event_free(e);
return OGS_ERROR;
}
@ -43,11 +44,18 @@ static int server_cb(ogs_sbi_request_t *request, void *data)
return OGS_OK;
}
static int client_cb(ogs_sbi_response_t *response, void *data)
static int client_cb(int status, ogs_sbi_response_t *response, void *data)
{
bsf_event_t *e = NULL;
int rv;
if (status != OGS_OK) {
ogs_log_message(
status == OGS_DONE ? OGS_LOG_DEBUG : OGS_LOG_WARN, 0,
"client_cb() failed [%d]", status);
return OGS_ERROR;
}
ogs_assert(response);
e = bsf_event_new(BSF_EVT_SBI_CLIENT);
@ -57,7 +65,8 @@ static int client_cb(ogs_sbi_response_t *response, void *data)
rv = ogs_queue_push(ogs_app()->queue, e);
if (rv != OGS_OK) {
ogs_warn("ogs_queue_push() failed:%d", (int)rv);
ogs_error("ogs_queue_push() failed:%d", (int)rv);
ogs_sbi_response_free(response);
bsf_event_free(e);
return OGS_ERROR;
}
@ -110,25 +119,10 @@ int bsf_sbi_open(void)
void bsf_sbi_close(void)
{
ogs_sbi_client_stop_all();
ogs_sbi_server_stop_all();
}
bool bsf_nnrf_nfm_send_nf_register(ogs_sbi_nf_instance_t *nf_instance)
{
ogs_sbi_request_t *request = NULL;
ogs_sbi_client_t *client = NULL;
ogs_assert(nf_instance);
client = nf_instance->client;
ogs_assert(client);
request = bsf_nnrf_nfm_build_register();
ogs_expect_or_return_val(request, false);
return ogs_sbi_client_send_request(
client, client->cb, request, nf_instance);
}
bool bsf_sbi_send(ogs_sbi_nf_instance_t *nf_instance, ogs_sbi_xact_t *xact)
{
return ogs_sbi_send(nf_instance, client_cb, xact);

View File

@ -29,8 +29,6 @@ extern "C" {
int bsf_sbi_open(void);
void bsf_sbi_close(void);
bool bsf_nnrf_nfm_send_nf_register(ogs_sbi_nf_instance_t *nf_instance);
bool bsf_sbi_send(ogs_sbi_nf_instance_t *nf_instance, ogs_sbi_xact_t *xact);
bool bsf_sbi_discover_and_send(OpenAPI_nf_type_e target_nf_type,

View File

@ -81,7 +81,7 @@ static void timer_send_event(int timer_id, void *data)
rv = ogs_queue_push(ogs_app()->queue, e);
if (rv != OGS_OK) {
ogs_warn("ogs_queue_push() failed [%d] in %s",
ogs_error("ogs_queue_push() failed [%d] in %s",
(int)rv, bsf_timer_get_name(e->timer_id));
bsf_event_free(e);
}

View File

@ -36,6 +36,8 @@ subdir('sgwu')
subdir('pcrf')
subdir('nrf')
subdir('scp')
subdir('udr')
subdir('udm')
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);
if (rv != OGS_OK) {
ogs_warn("ogs_queue_push() failed:%d", (int)rv);
ogs_error("ogs_queue_push() failed:%d", (int)rv);
ogs_free(e->addr);
if (e->pkbuf)
ogs_pkbuf_free(e->pkbuf);

View File

@ -111,7 +111,7 @@ void mme_timer_s1_delayed_send(void *data)
rv = ogs_queue_push(ogs_app()->queue, e);
if (rv != OGS_OK) {
ogs_warn("ogs_queue_push() failed:%d", (int)rv);
ogs_error("ogs_queue_push() failed:%d", (int)rv);
ogs_timer_delete(e->timer);
mme_event_free(e);
}
@ -131,7 +131,7 @@ static void emm_timer_event_send(
rv = ogs_queue_push(ogs_app()->queue, e);
if (rv != OGS_OK) {
ogs_warn("ogs_queue_push() failed:%d", (int)rv);
ogs_error("ogs_queue_push() failed:%d", (int)rv);
mme_event_free(e);
}
}
@ -174,7 +174,7 @@ static void esm_timer_event_send(
rv = ogs_queue_push(ogs_app()->queue, e);
if (rv != OGS_OK) {
ogs_warn("ogs_queue_push() failed:%d", (int)rv);
ogs_error("ogs_queue_push() failed:%d", (int)rv);
mme_event_free(e);
}
}
@ -196,7 +196,7 @@ void mme_timer_sgs_cli_conn_to_srv(void *data)
rv = ogs_queue_push(ogs_app()->queue, e);
if (rv != OGS_OK) {
ogs_warn("ogs_queue_push() failed:%d", (int)rv);
ogs_error("ogs_queue_push() failed:%d", (int)rv);
mme_event_free(e);
}
}
@ -217,7 +217,7 @@ void mme_timer_s1_holding_timer_expire(void *data)
rv = ogs_queue_push(ogs_app()->queue, e);
if (rv != OGS_OK) {
ogs_warn("ogs_queue_push() failed:%d", (int)rv);
ogs_error("ogs_queue_push() failed:%d", (int)rv);
mme_event_free(e);
}
}
@ -238,7 +238,7 @@ void mme_timer_s11_holding_timer_expire(void *data)
rv = ogs_queue_push(ogs_app()->queue, e);
if (rv != OGS_OK) {
ogs_warn("ogs_queue_push() failed:%d", (int)rv);
ogs_error("ogs_queue_push() failed:%d", (int)rv);
mme_event_free(e);
}
}

View File

@ -133,7 +133,7 @@ int s1ap_send_to_esm(
e->create_action = create_action;
rv = ogs_queue_push(ogs_app()->queue, e);
if (rv != OGS_OK) {
ogs_warn("ogs_queue_push() failed:%d", (int)rv);
ogs_error("ogs_queue_push() failed:%d", (int)rv);
ogs_pkbuf_free(e->pkbuf);
mme_event_free(e);
}
@ -221,7 +221,7 @@ int s1ap_send_to_nas(enb_ue_t *enb_ue,
e->pkbuf = nasbuf;
rv = ogs_queue_push(ogs_app()->queue, e);
if (rv != OGS_OK) {
ogs_warn("s1ap_send_to_nas() failed:%d", (int)rv);
ogs_error("s1ap_send_to_nas() failed:%d", (int)rv);
ogs_pkbuf_free(e->pkbuf);
mme_event_free(e);
}

View File

@ -32,7 +32,7 @@ int nrf_initialize()
nrf_context_init();
nrf_event_init();
rv = ogs_sbi_context_parse_config("nrf", NULL);
rv = ogs_sbi_context_parse_config("nrf", NULL, "scp");
if (rv != OGS_OK) return rv;
rv = nrf_context_parse_config();

View File

@ -20,7 +20,7 @@
#include "nnrf-build.h"
ogs_sbi_request_t *nrf_nnrf_nfm_build_nf_status_notify(
ogs_sbi_client_t *client, ogs_sbi_subscription_t *subscription,
ogs_sbi_subscription_t *subscription,
OpenAPI_notification_event_type_e event,
ogs_sbi_nf_instance_t *nf_instance)
{
@ -32,7 +32,6 @@ ogs_sbi_request_t *nrf_nnrf_nfm_build_nf_status_notify(
OpenAPI_notification_data_t *NotificationData = NULL;
ogs_assert(client);
ogs_assert(subscription);
ogs_assert(event);
ogs_assert(nf_instance);

View File

@ -28,7 +28,7 @@ extern "C" {
#endif
ogs_sbi_request_t *nrf_nnrf_nfm_build_nf_status_notify(
ogs_sbi_client_t *client, ogs_sbi_subscription_t *subscription,
ogs_sbi_subscription_t *subscription,
OpenAPI_notification_event_type_e event,
ogs_sbi_nf_instance_t *nf_instance);

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);
if (rv != OGS_OK) {
ogs_warn("ogs_queue_push() failed:%d", (int)rv);
if (rv != OGS_DONE)
ogs_error("ogs_queue_push() failed:%d", (int)rv);
else
ogs_warn("ogs_queue_push() failed:%d", (int)rv);
ogs_sbi_request_free(request);
nrf_event_free(e);
return OGS_ERROR;
}
@ -43,12 +47,19 @@ static int server_cb(ogs_sbi_request_t *request, void *data)
return OGS_OK;
}
static int client_notify_cb(ogs_sbi_response_t *response, void *data)
static int client_notify_cb(
int status, ogs_sbi_response_t *response, void *data)
{
int rv;
ogs_sbi_message_t message;
if (status != OGS_OK) {
ogs_log_message(
status == OGS_DONE ? OGS_LOG_DEBUG : OGS_LOG_WARN, 0,
"client_notify_cb() failed [%d]", status);
return OGS_ERROR;
}
ogs_assert(response);
rv = ogs_sbi_parse_response(&message, response);
@ -69,14 +80,28 @@ static int client_notify_cb(ogs_sbi_response_t *response, void *data)
int nrf_sbi_open(void)
{
ogs_sbi_nf_instance_t *nf_instance = NULL;
if (ogs_sbi_server_start_all(server_cb) != OGS_OK)
return OGS_ERROR;
/* Initialize SCP NF Instance */
nf_instance = ogs_sbi_self()->scp_instance;
if (nf_instance) {
ogs_sbi_client_t *client = NULL;
/* Client callback is only used when NF sends to SCP */
client = nf_instance->client;
ogs_assert(client);
client->cb = client_notify_cb;
}
return OGS_OK;
}
void nrf_sbi_close(void)
{
ogs_sbi_client_stop_all();
ogs_sbi_server_stop_all();
}
@ -92,10 +117,10 @@ bool nrf_nnrf_nfm_send_nf_status_notify(ogs_sbi_subscription_t *subscription,
ogs_assert(client);
request = nrf_nnrf_nfm_build_nf_status_notify(
client, subscription, event, nf_instance);
subscription, event, nf_instance);
ogs_expect_or_return_val(request, false);
return ogs_sbi_client_send_request(client, client_notify_cb, request, NULL);
return ogs_sbi_scp_send_request(client, client_notify_cb, request, NULL);
}
bool nrf_nnrf_nfm_send_nf_status_notify_all(

View File

@ -68,7 +68,7 @@ static void timer_send_event(int timer_id, void *data)
rv = ogs_queue_push(ogs_app()->queue, e);
if (rv != OGS_OK) {
ogs_warn("ogs_queue_push() failed:%d", (int)rv);
ogs_error("ogs_queue_push() failed:%d", (int)rv);
nrf_event_free(e);
}
}

View File

@ -32,7 +32,7 @@ int nssf_initialize()
nssf_context_init();
nssf_event_init();
rv = ogs_sbi_context_parse_config("nssf", "nrf");
rv = ogs_sbi_context_parse_config("nssf", "nrf", "scp");
if (rv != OGS_OK) return rv;
rv = nssf_context_parse_config();

View File

@ -61,16 +61,18 @@ void nssf_nf_state_initial(ogs_fsm_t *s, nssf_event_t *e)
nf_instance = e->sbi.data;
ogs_assert(nf_instance);
nf_instance->t_registration_interval = ogs_timer_add(ogs_app()->timer_mgr,
nssf_timer_nf_instance_registration_interval, nf_instance);
ogs_assert(nf_instance->t_registration_interval);
nf_instance->t_registration_interval->cb =
nssf_timer_nf_instance_registration_interval;
nf_instance->t_heartbeat_interval = ogs_timer_add(ogs_app()->timer_mgr,
nssf_timer_nf_instance_heartbeat_interval, nf_instance);
ogs_assert(nf_instance->t_heartbeat_interval);
nf_instance->t_heartbeat_interval->cb =
nssf_timer_nf_instance_heartbeat_interval;
nf_instance->t_no_heartbeat = ogs_timer_add(ogs_app()->timer_mgr,
nssf_timer_nf_instance_no_heartbeat, nf_instance);
ogs_assert(nf_instance->t_no_heartbeat);
nf_instance->t_no_heartbeat->cb = nssf_timer_nf_instance_no_heartbeat;
nf_instance->t_validity = ogs_timer_add(ogs_app()->timer_mgr,
nssf_timer_nf_instance_validity, nf_instance);
ogs_assert(nf_instance->t_validity);
nf_instance->t_validity->cb = nssf_timer_nf_instance_validity;
if (NF_INSTANCE_IS_NRF(nf_instance)) {
OGS_FSM_TRAN(s, &nssf_nf_state_will_register);
@ -82,10 +84,20 @@ void nssf_nf_state_initial(ogs_fsm_t *s, nssf_event_t *e)
void nssf_nf_state_final(ogs_fsm_t *s, nssf_event_t *e)
{
ogs_sbi_nf_instance_t *nf_instance = NULL;
ogs_assert(s);
ogs_assert(e);
nssf_sm_debug(e);
nf_instance = e->sbi.data;
ogs_assert(nf_instance);
ogs_timer_delete(nf_instance->t_registration_interval);
ogs_timer_delete(nf_instance->t_heartbeat_interval);
ogs_timer_delete(nf_instance->t_no_heartbeat);
ogs_timer_delete(nf_instance->t_validity);
}
void nssf_nf_state_will_register(ogs_fsm_t *s, nssf_event_t *e)
@ -110,7 +122,8 @@ void nssf_nf_state_will_register(ogs_fsm_t *s, nssf_event_t *e)
ogs_timer_start(nf_instance->t_registration_interval,
ogs_app()->time.message.sbi.nf_register_interval);
ogs_assert(true == nssf_nnrf_nfm_send_nf_register(nf_instance));
ogs_assert(true == ogs_nnrf_nfm_send_nf_register(
nf_instance, nssf_nnrf_nfm_build_register));
break;
case OGS_FSM_EXIT_SIG:
@ -166,7 +179,8 @@ void nssf_nf_state_will_register(ogs_fsm_t *s, nssf_event_t *e)
ogs_timer_start(nf_instance->t_registration_interval,
ogs_app()->time.message.sbi.nf_register_interval);
ogs_assert(true == nssf_nnrf_nfm_send_nf_register(nf_instance));
ogs_assert(true == ogs_nnrf_nfm_send_nf_register(
nf_instance, nssf_nnrf_nfm_build_register));
break;
default:

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);
if (rv != OGS_OK) {
ogs_warn("ogs_queue_push() failed:%d", (int)rv);
ogs_error("ogs_queue_push() failed:%d", (int)rv);
ogs_sbi_request_free(request);
nssf_event_free(e);
return OGS_ERROR;
}
@ -43,11 +44,18 @@ static int server_cb(ogs_sbi_request_t *request, void *data)
return OGS_OK;
}
static int client_cb(ogs_sbi_response_t *response, void *data)
static int client_cb(int status, ogs_sbi_response_t *response, void *data)
{
nssf_event_t *e = NULL;
int rv;
if (status != OGS_OK) {
ogs_log_message(
status == OGS_DONE ? OGS_LOG_DEBUG : OGS_LOG_WARN, 0,
"client_cb() failed [%d]", status);
return OGS_ERROR;
}
ogs_assert(response);
e = nssf_event_new(NSSF_EVT_SBI_CLIENT);
@ -57,7 +65,8 @@ static int client_cb(ogs_sbi_response_t *response, void *data)
rv = ogs_queue_push(ogs_app()->queue, e);
if (rv != OGS_OK) {
ogs_warn("ogs_queue_push() failed:%d", (int)rv);
ogs_error("ogs_queue_push() failed:%d", (int)rv);
ogs_sbi_response_free(response);
nssf_event_free(e);
return OGS_ERROR;
}
@ -110,21 +119,6 @@ int nssf_sbi_open(void)
void nssf_sbi_close(void)
{
ogs_sbi_client_stop_all();
ogs_sbi_server_stop_all();
}
bool nssf_nnrf_nfm_send_nf_register(ogs_sbi_nf_instance_t *nf_instance)
{
ogs_sbi_request_t *request = NULL;
ogs_sbi_client_t *client = NULL;
ogs_assert(nf_instance);
client = nf_instance->client;
ogs_assert(client);
request = nssf_nnrf_nfm_build_register();
ogs_expect_or_return_val(request, false);
return ogs_sbi_client_send_request(
client, client->cb, request, nf_instance);
}

View File

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

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);
if (rv != OGS_OK) {
ogs_warn("ogs_queue_push() failed [%d] in %s",
ogs_error("ogs_queue_push() failed [%d] in %s",
(int)rv, nssf_timer_get_name(e->timer_id));
nssf_event_free(e);
}

View File

@ -32,7 +32,7 @@ int pcf_initialize()
pcf_context_init();
pcf_event_init();
rv = ogs_sbi_context_parse_config("pcf", "nrf");
rv = ogs_sbi_context_parse_config("pcf", "nrf", "scp");
if (rv != OGS_OK) return rv;
rv = pcf_context_parse_config();

View File

@ -61,16 +61,18 @@ void pcf_nf_state_initial(ogs_fsm_t *s, pcf_event_t *e)
nf_instance = e->sbi.data;
ogs_assert(nf_instance);
nf_instance->t_registration_interval = ogs_timer_add(ogs_app()->timer_mgr,
pcf_timer_nf_instance_registration_interval, nf_instance);
ogs_assert(nf_instance->t_registration_interval);
nf_instance->t_registration_interval->cb =
pcf_timer_nf_instance_registration_interval;
nf_instance->t_heartbeat_interval = ogs_timer_add(ogs_app()->timer_mgr,
pcf_timer_nf_instance_heartbeat_interval, nf_instance);
ogs_assert(nf_instance->t_heartbeat_interval);
nf_instance->t_heartbeat_interval->cb =
pcf_timer_nf_instance_heartbeat_interval;
nf_instance->t_no_heartbeat = ogs_timer_add(ogs_app()->timer_mgr,
pcf_timer_nf_instance_no_heartbeat, nf_instance);
ogs_assert(nf_instance->t_no_heartbeat);
nf_instance->t_no_heartbeat->cb = pcf_timer_nf_instance_no_heartbeat;
nf_instance->t_validity = ogs_timer_add(ogs_app()->timer_mgr,
pcf_timer_nf_instance_validity, nf_instance);
ogs_assert(nf_instance->t_validity);
nf_instance->t_validity->cb = pcf_timer_nf_instance_validity;
if (NF_INSTANCE_IS_NRF(nf_instance)) {
OGS_FSM_TRAN(s, &pcf_nf_state_will_register);
@ -82,10 +84,20 @@ void pcf_nf_state_initial(ogs_fsm_t *s, pcf_event_t *e)
void pcf_nf_state_final(ogs_fsm_t *s, pcf_event_t *e)
{
ogs_sbi_nf_instance_t *nf_instance = NULL;
ogs_assert(s);
ogs_assert(e);
pcf_sm_debug(e);
nf_instance = e->sbi.data;
ogs_assert(nf_instance);
ogs_timer_delete(nf_instance->t_registration_interval);
ogs_timer_delete(nf_instance->t_heartbeat_interval);
ogs_timer_delete(nf_instance->t_no_heartbeat);
ogs_timer_delete(nf_instance->t_validity);
}
void pcf_nf_state_will_register(ogs_fsm_t *s, pcf_event_t *e)
@ -110,7 +122,8 @@ void pcf_nf_state_will_register(ogs_fsm_t *s, pcf_event_t *e)
ogs_timer_start(nf_instance->t_registration_interval,
ogs_app()->time.message.sbi.nf_register_interval);
ogs_assert(true == pcf_nnrf_nfm_send_nf_register(nf_instance));
ogs_assert(true == ogs_nnrf_nfm_send_nf_register(
nf_instance, pcf_nnrf_nfm_build_register));
break;
case OGS_FSM_EXIT_SIG:
@ -167,7 +180,8 @@ void pcf_nf_state_will_register(ogs_fsm_t *s, pcf_event_t *e)
ogs_timer_start(nf_instance->t_registration_interval,
ogs_app()->time.message.sbi.nf_register_interval);
ogs_assert(true == pcf_nnrf_nfm_send_nf_register(nf_instance));
ogs_assert(true == ogs_nnrf_nfm_send_nf_register(
nf_instance, pcf_nnrf_nfm_build_register));
break;
default:

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);
if (rv != OGS_OK) {
ogs_warn("ogs_queue_push() failed:%d", (int)rv);
ogs_error("ogs_queue_push() failed:%d", (int)rv);
ogs_sbi_request_free(request);
pcf_event_free(e);
return OGS_ERROR;
}
@ -43,11 +44,18 @@ static int server_cb(ogs_sbi_request_t *request, void *data)
return OGS_OK;
}
static int client_cb(ogs_sbi_response_t *response, void *data)
static int client_cb(int status, ogs_sbi_response_t *response, void *data)
{
pcf_event_t *e = NULL;
int rv;
if (status != OGS_OK) {
ogs_log_message(
status == OGS_DONE ? OGS_LOG_DEBUG : OGS_LOG_WARN, 0,
"client_cb() failed [%d]", status);
return OGS_ERROR;
}
ogs_assert(response);
e = pcf_event_new(PCF_EVT_SBI_CLIENT);
@ -57,7 +65,8 @@ static int client_cb(ogs_sbi_response_t *response, void *data)
rv = ogs_queue_push(ogs_app()->queue, e);
if (rv != OGS_OK) {
ogs_warn("ogs_queue_push() failed:%d", (int)rv);
ogs_error("ogs_queue_push() failed:%d", (int)rv);
ogs_sbi_response_free(response);
pcf_event_free(e);
return OGS_ERROR;
}
@ -123,25 +132,10 @@ int pcf_sbi_open(void)
void pcf_sbi_close(void)
{
ogs_sbi_client_stop_all();
ogs_sbi_server_stop_all();
}
bool pcf_nnrf_nfm_send_nf_register(ogs_sbi_nf_instance_t *nf_instance)
{
ogs_sbi_request_t *request = NULL;
ogs_sbi_client_t *client = NULL;
ogs_assert(nf_instance);
client = nf_instance->client;
ogs_assert(client);
request = pcf_nnrf_nfm_build_register();
ogs_expect_or_return_val(request, false);
return ogs_sbi_client_send_request(
client, client->cb, request, nf_instance);
}
bool pcf_sbi_send(ogs_sbi_nf_instance_t *nf_instance, ogs_sbi_xact_t *xact)
{
return ogs_sbi_send(nf_instance, client_cb, xact);
@ -209,12 +203,19 @@ bool pcf_sess_sbi_discover_and_send(OpenAPI_nf_type_e target_nf_type,
return true;
}
static int client_notify_cb(ogs_sbi_response_t *response, void *data)
static int client_notify_cb(
int status, ogs_sbi_response_t *response, void *data)
{
int rv;
ogs_sbi_message_t message;
if (status != OGS_OK) {
ogs_log_message(
status == OGS_DONE ? OGS_LOG_DEBUG : OGS_LOG_WARN, 0,
"client_notify_cb() failed [%d]", status);
return OGS_ERROR;
}
ogs_assert(response);
rv = ogs_sbi_parse_response(&message, response);
@ -234,12 +235,13 @@ static int client_notify_cb(ogs_sbi_response_t *response, void *data)
return OGS_OK;
}
static int client_delete_notify_cb(ogs_sbi_response_t *response, void *data)
static int client_delete_notify_cb(
int status, ogs_sbi_response_t *response, void *data)
{
pcf_app_t *app_session = data;
ogs_assert(app_session);
client_notify_cb(response, data);
client_notify_cb(status, response, data);
pcf_app_remove(app_session);

View File

@ -34,8 +34,6 @@ extern "C" {
int pcf_sbi_open(void);
void pcf_sbi_close(void);
bool pcf_nnrf_nfm_send_nf_register(ogs_sbi_nf_instance_t *nf_instance);
bool pcf_sbi_send(ogs_sbi_nf_instance_t *nf_instance, ogs_sbi_xact_t *xact);
bool pcf_ue_sbi_discover_and_send(OpenAPI_nf_type_e target_nf_type,
pcf_ue_t *pcf_ue, ogs_sbi_stream_t *stream, void *data,

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);
if (rv != OGS_OK) {
ogs_warn("ogs_queue_push() failed [%d] in %s",
ogs_error("ogs_queue_push() failed [%d] in %s",
(int)rv, pcf_timer_get_name(e->timer_id));
pcf_event_free(e);
}

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

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);
if (rv != OGS_OK) {
ogs_warn("ogs_queue_push() failed:%d", (int)rv);
ogs_error("ogs_queue_push() failed:%d", (int)rv);
sgwc_event_free(e);
}
break;

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_uli_t uli;
ogs_assert(sgwc_ue);
ogs_assert(message);
rsp = &message->create_bearer_response;
ogs_assert(rsp);
@ -715,30 +716,10 @@ void sgwc_s11_handle_create_bearer_response(
rv = ogs_gtp_xact_commit(s11_xact);
ogs_expect(rv == OGS_OK);
/************************
* Check SGWC-UE Context
************************/
cause_value = OGS_GTP2_CAUSE_REQUEST_ACCEPTED;
if (!sgwc_ue) {
ogs_error("No Context in TEID");
cause_value = OGS_GTP2_CAUSE_CONTEXT_NOT_FOUND;
}
if (cause_value != OGS_GTP2_CAUSE_REQUEST_ACCEPTED) {
ogs_assert(OGS_OK ==
sgwc_pfcp_send_bearer_modification_request(
bearer, NULL, NULL,
OGS_PFCP_MODIFY_UL_ONLY|OGS_PFCP_MODIFY_REMOVE));
ogs_gtp_send_error_message(s5c_xact, sess ? sess->pgw_s5c_teid : 0,
OGS_GTP2_CREATE_BEARER_RESPONSE_TYPE, cause_value);
return;
}
/*****************************************
* Check Mandatory/Conditional IE Missing
*****************************************/
ogs_assert(cause_value == OGS_GTP2_CAUSE_REQUEST_ACCEPTED);
cause_value = OGS_GTP2_CAUSE_REQUEST_ACCEPTED;
if (rsp->bearer_contexts.presence == 0) {
ogs_error("No Bearer");
@ -873,6 +854,7 @@ void sgwc_s11_handle_update_bearer_response(
sgwc_bearer_t *bearer = NULL;
ogs_gtp2_update_bearer_response_t *rsp = NULL;
ogs_assert(sgwc_ue);
ogs_assert(message);
rsp = &message->update_bearer_response;
ogs_assert(rsp);
@ -899,26 +881,10 @@ void sgwc_s11_handle_update_bearer_response(
rv = ogs_gtp_xact_commit(s11_xact);
ogs_expect(rv == OGS_OK);
/************************
* Check SGWC-UE Context
************************/
cause_value = OGS_GTP2_CAUSE_REQUEST_ACCEPTED;
if (!sgwc_ue) {
ogs_error("No Context in TEID");
cause_value = OGS_GTP2_CAUSE_CONTEXT_NOT_FOUND;
}
if (cause_value != OGS_GTP2_CAUSE_REQUEST_ACCEPTED) {
ogs_gtp_send_error_message(s5c_xact, sess ? sess->pgw_s5c_teid : 0,
OGS_GTP2_UPDATE_BEARER_RESPONSE_TYPE, cause_value);
return;
}
/*****************************************
* Check Mandatory/Conditional IE Missing
*****************************************/
ogs_assert(cause_value == OGS_GTP2_CAUSE_REQUEST_ACCEPTED);
cause_value = OGS_GTP2_CAUSE_REQUEST_ACCEPTED;
if (rsp->bearer_contexts.presence == 0) {
ogs_error("No Bearer");
@ -1005,6 +971,7 @@ void sgwc_s11_handle_delete_bearer_response(
sgwc_bearer_t *bearer = NULL;
ogs_gtp2_delete_bearer_response_t *rsp = NULL;
ogs_assert(sgwc_ue);
ogs_assert(message);
rsp = &message->delete_bearer_response;
ogs_assert(rsp);
@ -1036,11 +1003,6 @@ void sgwc_s11_handle_delete_bearer_response(
************************/
cause_value = OGS_GTP2_CAUSE_REQUEST_ACCEPTED;
if (!sgwc_ue) {
ogs_error("No Context in TEID");
cause_value = OGS_GTP2_CAUSE_CONTEXT_NOT_FOUND;
}
if (rsp->linked_eps_bearer_id.presence) {
/*
* << Linked EPS Bearer ID >>
@ -1112,10 +1074,8 @@ void sgwc_s11_handle_delete_bearer_response(
ogs_error("No Cause");
}
if (sgwc_ue) {
ogs_debug(" MME_S11_TEID[%d] SGW_S11_TEID[%d]",
sgwc_ue->mme_s11_teid, sgwc_ue->sgw_s11_teid);
}
ogs_debug(" MME_S11_TEID[%d] SGW_S11_TEID[%d]",
sgwc_ue->mme_s11_teid, sgwc_ue->sgw_s11_teid);
ogs_debug(" SGW_S5C_TEID[0x%x] PGW_S5C_TEID[0x%x]",
sess->sgw_s5c_teid, sess->pgw_s5c_teid);
@ -1514,6 +1474,7 @@ void sgwc_s11_handle_bearer_resource_command(
s5c_xact = ogs_gtp_xact_local_create(
sess->gnode, &message->h, pkbuf, gtp_bearer_timeout, bearer);
ogs_expect_or_return(s5c_xact);
s5c_xact->local_teid = sess->sgw_s5c_teid;
ogs_gtp_xact_associate(s11_xact, s5c_xact);

View File

@ -79,6 +79,9 @@ void sgwc_s5c_handle_create_session_response(
ogs_gtp_xact_t *s11_xact = NULL;
ogs_gtp_node_t *pgw = NULL;
ogs_assert(sess);
sgwc_ue = sess->sgwc_ue;
ogs_assert(sgwc_ue);
ogs_assert(gtpbuf);
ogs_assert(message);
rsp = &message->create_session_response;
@ -96,30 +99,10 @@ void sgwc_s5c_handle_create_session_response(
rv = ogs_gtp_xact_commit(s5c_xact);
ogs_expect(rv == OGS_OK);
/************************
* Check Session Context
************************/
cause_value = OGS_GTP2_CAUSE_REQUEST_ACCEPTED;
if (!sess) {
ogs_error("No Context in TEID");
cause_value = OGS_GTP2_CAUSE_CONTEXT_NOT_FOUND;
} else {
sgwc_ue = sess->sgwc_ue;
ogs_assert(sgwc_ue);
}
if (cause_value != OGS_GTP2_CAUSE_REQUEST_ACCEPTED) {
ogs_gtp_send_error_message(
s11_xact, sgwc_ue ? sgwc_ue->mme_s11_teid : 0,
OGS_GTP2_CREATE_SESSION_RESPONSE_TYPE, cause_value);
return;
}
/*****************************************
* Check Mandatory/Conditional IE Missing
*****************************************/
ogs_assert(cause_value == OGS_GTP2_CAUSE_REQUEST_ACCEPTED);
cause_value = OGS_GTP2_CAUSE_REQUEST_ACCEPTED;
if (rsp->pgw_s5_s8__s2a_s2b_f_teid_for_pmip_based_interface_or_for_gtp_based_control_plane_interface.presence == 0) {
ogs_error("No GTP TEID");
@ -282,108 +265,6 @@ void sgwc_s5c_handle_create_session_response(
OGS_PFCP_MODIFY_UL_ONLY|OGS_PFCP_MODIFY_ACTIVATE));
}
void sgwc_s5c_handle_delete_session_response(
sgwc_sess_t *sess, ogs_gtp_xact_t *s5c_xact,
ogs_pkbuf_t *gtpbuf, ogs_gtp2_message_t *message)
{
int rv;
ogs_gtp2_cause_t *cause = NULL;
uint8_t cause_value;
sgwc_ue_t *sgwc_ue = NULL;
ogs_gtp_xact_t *s11_xact = NULL;
ogs_gtp2_delete_session_response_t *rsp = NULL;
ogs_assert(message);
rsp = &message->delete_session_response;
ogs_assert(rsp);
ogs_debug("Delete Session Response");
/********************
* Check Transaction
********************/
ogs_assert(s5c_xact);
s11_xact = s5c_xact->assoc_xact;
ogs_assert(s11_xact);
rv = ogs_gtp_xact_commit(s5c_xact);
ogs_expect(rv == OGS_OK);
/************************
* Check Session Context
************************/
cause_value = OGS_GTP2_CAUSE_REQUEST_ACCEPTED;
if (!sess) {
ogs_error("No Context in TEID");
cause_value = OGS_GTP2_CAUSE_CONTEXT_NOT_FOUND;
} else {
sgwc_ue = sess->sgwc_ue;
ogs_assert(sgwc_ue);
}
if (cause_value != OGS_GTP2_CAUSE_REQUEST_ACCEPTED) {
ogs_gtp_send_error_message(
s11_xact, sgwc_ue ? sgwc_ue->mme_s11_teid : 0,
OGS_GTP2_DELETE_SESSION_RESPONSE_TYPE, cause_value);
return;
}
/*****************************************
* Check Mandatory/Conditional IE Missing
*****************************************/
ogs_assert(cause_value == OGS_GTP2_CAUSE_REQUEST_ACCEPTED);
if (rsp->cause.presence == 0) {
ogs_error("No Cause");
cause_value = OGS_GTP2_CAUSE_MANDATORY_IE_MISSING;
}
if (cause_value != OGS_GTP2_CAUSE_REQUEST_ACCEPTED) {
ogs_gtp_send_error_message(
s11_xact, sgwc_ue ? sgwc_ue->mme_s11_teid : 0,
OGS_GTP2_DELETE_SESSION_RESPONSE_TYPE, cause_value);
return;
}
/********************
* Check Cause Value
********************/
ogs_assert(cause_value == OGS_GTP2_CAUSE_REQUEST_ACCEPTED);
cause = rsp->cause.data;
ogs_assert(cause);
cause_value = cause->value;
if (cause_value != OGS_GTP2_CAUSE_REQUEST_ACCEPTED) {
ogs_error("GTP Failed [CAUSE:%d]", cause_value);
ogs_gtp_send_error_message(
s11_xact, sgwc_ue ? sgwc_ue->mme_s11_teid : 0,
OGS_GTP2_DELETE_SESSION_RESPONSE_TYPE, cause_value);
return;
}
/********************
* Check ALL Context
********************/
ogs_assert(sess);
ogs_assert(sgwc_ue);
/* Remove a pgw session */
ogs_debug(" MME_S11_TEID[%d] SGW_S11_TEID[%d]",
sgwc_ue->mme_s11_teid, sgwc_ue->sgw_s11_teid);
ogs_debug(" SGW_S5C_TEID[0x%x] PGW_S5C_TEID[0x%x]",
sess->sgw_s5c_teid, sess->pgw_s5c_teid);
/*
* 1. MME sends Delete Session Request to SGW/SMF.
* 2. SMF sends Delete Session Response to SGW/MME.
*/
ogs_assert(OGS_OK ==
sgwc_pfcp_send_session_deletion_request(sess, s11_xact, gtpbuf));
}
void sgwc_s5c_handle_modify_bearer_response(
sgwc_sess_t *sess, ogs_gtp_xact_t *s5c_xact,
ogs_pkbuf_t *gtpbuf, ogs_gtp2_message_t *message)
@ -399,6 +280,9 @@ void sgwc_s5c_handle_modify_bearer_response(
ogs_gtp_xact_t *s11_xact = NULL;
ogs_gtp2_modify_bearer_response_t *rsp = NULL;
ogs_assert(sess);
sgwc_ue = sess->sgwc_ue;
ogs_assert(sgwc_ue);
ogs_assert(message);
rsp = &message->modify_bearer_response;
ogs_assert(rsp);
@ -416,35 +300,10 @@ void sgwc_s5c_handle_modify_bearer_response(
rv = ogs_gtp_xact_commit(s5c_xact);
ogs_expect(rv == OGS_OK);
/************************
* Check Session Context
************************/
cause_value = OGS_GTP2_CAUSE_REQUEST_ACCEPTED;
if (!sess) {
ogs_error("No Context in TEID");
cause_value = OGS_GTP2_CAUSE_CONTEXT_NOT_FOUND;
} else {
sgwc_ue = sess->sgwc_ue;
ogs_assert(sgwc_ue);
}
if (cause_value != OGS_GTP2_CAUSE_REQUEST_ACCEPTED) {
if (modify_action == OGS_GTP_MODIFY_IN_PATH_SWITCH_REQUEST)
ogs_gtp_send_error_message(
s11_xact, sgwc_ue ? sgwc_ue->mme_s11_teid : 0,
OGS_GTP2_CREATE_SESSION_RESPONSE_TYPE, cause_value);
else
ogs_gtp_send_error_message(
s11_xact, sgwc_ue ? sgwc_ue->mme_s11_teid : 0,
OGS_GTP2_MODIFY_BEARER_RESPONSE_TYPE, cause_value);
return;
}
/*****************************************
* Check Mandatory/Conditional IE Missing
*****************************************/
ogs_assert(cause_value == OGS_GTP2_CAUSE_REQUEST_ACCEPTED);
cause_value = OGS_GTP2_CAUSE_REQUEST_ACCEPTED;
if (rsp->cause.presence == 0) {
ogs_error("No Cause");
@ -513,6 +372,91 @@ void sgwc_s5c_handle_modify_bearer_response(
}
}
void sgwc_s5c_handle_delete_session_response(
sgwc_sess_t *sess, ogs_gtp_xact_t *s5c_xact,
ogs_pkbuf_t *gtpbuf, ogs_gtp2_message_t *message)
{
int rv;
ogs_gtp2_cause_t *cause = NULL;
uint8_t cause_value;
sgwc_ue_t *sgwc_ue = NULL;
ogs_gtp_xact_t *s11_xact = NULL;
ogs_gtp2_delete_session_response_t *rsp = NULL;
ogs_assert(sess);
sgwc_ue = sess->sgwc_ue;
ogs_assert(sgwc_ue);
ogs_assert(message);
rsp = &message->delete_session_response;
ogs_assert(rsp);
ogs_debug("Delete Session Response");
/********************
* Check Transaction
********************/
ogs_assert(s5c_xact);
s11_xact = s5c_xact->assoc_xact;
ogs_assert(s11_xact);
rv = ogs_gtp_xact_commit(s5c_xact);
ogs_expect(rv == OGS_OK);
/*****************************************
* Check Mandatory/Conditional IE Missing
*****************************************/
cause_value = OGS_GTP2_CAUSE_REQUEST_ACCEPTED;
if (rsp->cause.presence == 0) {
ogs_error("No Cause");
cause_value = OGS_GTP2_CAUSE_MANDATORY_IE_MISSING;
}
if (cause_value != OGS_GTP2_CAUSE_REQUEST_ACCEPTED) {
ogs_gtp_send_error_message(
s11_xact, sgwc_ue ? sgwc_ue->mme_s11_teid : 0,
OGS_GTP2_DELETE_SESSION_RESPONSE_TYPE, cause_value);
return;
}
/********************
* Check Cause Value
********************/
ogs_assert(cause_value == OGS_GTP2_CAUSE_REQUEST_ACCEPTED);
cause = rsp->cause.data;
ogs_assert(cause);
cause_value = cause->value;
if (cause_value != OGS_GTP2_CAUSE_REQUEST_ACCEPTED) {
ogs_error("GTP Failed [CAUSE:%d]", cause_value);
ogs_gtp_send_error_message(
s11_xact, sgwc_ue ? sgwc_ue->mme_s11_teid : 0,
OGS_GTP2_DELETE_SESSION_RESPONSE_TYPE, cause_value);
return;
}
/********************
* Check ALL Context
********************/
ogs_assert(sess);
ogs_assert(sgwc_ue);
/* Remove a pgw session */
ogs_debug(" MME_S11_TEID[%d] SGW_S11_TEID[%d]",
sgwc_ue->mme_s11_teid, sgwc_ue->sgw_s11_teid);
ogs_debug(" SGW_S5C_TEID[0x%x] PGW_S5C_TEID[0x%x]",
sess->sgw_s5c_teid, sess->pgw_s5c_teid);
/*
* 1. MME sends Delete Session Request to SGW/SMF.
* 2. SMF sends Delete Session Response to SGW/MME.
*/
ogs_assert(OGS_OK ==
sgwc_pfcp_send_session_deletion_request(sess, s11_xact, gtpbuf));
}
void sgwc_s5c_handle_create_bearer_request(
sgwc_sess_t *sess, ogs_gtp_xact_t *s5c_xact,
ogs_pkbuf_t *gtpbuf, ogs_gtp2_message_t *message)
@ -725,6 +669,7 @@ void sgwc_s5c_handle_update_bearer_request(
rv = ogs_gtp_xact_update_tx(s11_xact, &message->h, pkbuf);
ogs_expect_or_return(rv == OGS_OK);
}
s11_xact->local_teid = sgwc_ue->sgw_s11_teid;
rv = ogs_gtp_xact_commit(s11_xact);
ogs_expect(rv == OGS_OK);
@ -874,6 +819,7 @@ void sgwc_s5c_handle_delete_bearer_request(
rv = ogs_gtp_xact_update_tx(s11_xact, &message->h, pkbuf);
ogs_expect_or_return(rv == OGS_OK);
}
s11_xact->local_teid = sgwc_ue->sgw_s11_teid;
rv = ogs_gtp_xact_commit(s11_xact);
ogs_expect(rv == OGS_OK);
@ -889,6 +835,9 @@ void sgwc_s5c_handle_bearer_resource_failure_indication(
sgwc_ue_t *sgwc_ue = NULL;
ogs_assert(sess);
sgwc_ue = sess->sgwc_ue;
ogs_assert(sgwc_ue);
ogs_assert(message);
ind = &message->bearer_resource_failure_indication;
ogs_assert(ind);
@ -902,17 +851,6 @@ void sgwc_s5c_handle_bearer_resource_failure_indication(
s11_xact = s5c_xact->assoc_xact;
ogs_assert(s11_xact);
/************************
* Check Session Context
************************/
if (!sess) {
ogs_error("No Context in TEID");
cause_value = OGS_GTP2_CAUSE_CONTEXT_NOT_FOUND;
} else {
sgwc_ue = sess->sgwc_ue;
ogs_assert(sgwc_ue);
}
/********************
* Check Cause Value
********************/

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

View File

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

View File

@ -57,7 +57,7 @@ static void timer_send_event(int timer_id, void *data)
rv = ogs_queue_push(ogs_app()->queue, e);
if (rv != OGS_OK) {
ogs_warn("ogs_queue_push() failed [%d] in %s",
ogs_error("ogs_queue_push() failed [%d] in %s",
(int)rv, sgwc_timer_get_name(e->timer_id));
sgwc_event_free(e);
}

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);
if (rv != OGS_OK) {
ogs_warn("ogs_queue_push() failed:%d", (int)rv);
ogs_error("ogs_queue_push() failed:%d", (int)rv);
ogs_pkbuf_free(e->pkbuf);
sgwu_event_free(e);
}

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);
if (rv != OGS_OK) {
ogs_warn("ogs_queue_push() failed:%d", (int)rv);
ogs_error("ogs_queue_push() failed:%d", (int)rv);
sgwu_event_free(e);
}
break;

View File

@ -45,7 +45,7 @@ static void timer_send_event(int timer_id, void *data)
rv = ogs_queue_push(ogs_app()->queue, e);
if (rv != OGS_OK) {
ogs_warn("ogs_queue_push() failed:%d", (int)rv);
ogs_error("ogs_queue_push() failed:%d", (int)rv);
sgwu_event_free(e);
}
}

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);
if (rv != OGS_OK) {
ogs_warn("ogs_queue_push() failed:%d", (int)rv);
ogs_error("ogs_queue_push() failed:%d", (int)rv);
ogs_pkbuf_free(e->pkbuf);
smf_event_free(e);
}

View File

@ -1005,7 +1005,7 @@ out:
e->gtp_xact = xact;
rv = ogs_queue_push(ogs_app()->queue, e);
if (rv != OGS_OK) {
ogs_warn("ogs_queue_push() failed:%d", (int)rv);
ogs_error("ogs_queue_push() failed:%d", (int)rv);
ogs_session_data_free(&gx_message->session_data);
ogs_free(gx_message);
smf_event_free(e);
@ -1248,7 +1248,7 @@ static int smf_gx_rar_cb( struct msg **msg, struct avp *avp,
e->gx_message = gx_message;
rv = ogs_queue_push(ogs_app()->queue, e);
if (rv != OGS_OK) {
ogs_warn("ogs_queue_push() failed:%d", (int)rv);
ogs_error("ogs_queue_push() failed:%d", (int)rv);
ogs_session_data_free(&gx_message->session_data);
ogs_free(gx_message);
smf_event_free(e);

View File

@ -1104,7 +1104,7 @@ out:
}
rv = ogs_queue_push(ogs_app()->queue, e);
if (rv != OGS_OK) {
ogs_warn("ogs_queue_push() failed:%d", (int)rv);
ogs_error("ogs_queue_push() failed:%d", (int)rv);
ogs_free(gy_message);
smf_event_free(e);
} else {
@ -1233,7 +1233,7 @@ static int smf_gy_rar_cb( struct msg **msg, struct avp *avp,
e->gy_message = gy_message;
rv = ogs_queue_push(ogs_app()->queue, e);
if (rv != OGS_OK) {
ogs_warn("ogs_queue_push() failed:%d", (int)rv);
ogs_error("ogs_queue_push() failed:%d", (int)rv);
ogs_free(gy_message);
smf_event_free(e);
} else {

View File

@ -53,7 +53,7 @@ int smf_initialize()
rv = ogs_pfcp_context_parse_config("smf", "upf");
if (rv != OGS_OK) return rv;
rv = ogs_sbi_context_parse_config("smf", "nrf");
rv = ogs_sbi_context_parse_config("smf", "nrf", "scp");
if (rv != OGS_OK) return rv;
rv = ogs_metrics_context_parse_config();

View File

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

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