mirror of
https://github.com/open5gs/open5gs.git
synced 2025-10-23 07:41:57 +00:00
[PFCP] Refactor PFCP address handling (#3431)
- Replace direct usage of OGS_ADDR/OGS_PORT macros with ogs_sockaddr_to_string_static() for consistent IPv4/IPv6 logging. - Remove redundant stack buffer allocations for address printing. - Update PFCP node address handling to use addr_list and related merges, avoiding obsolete sa_list references. - Use ogs_pfcp_extract_node_id() and related APIs to safely extract PFCP Node ID, improving error handling and reducing stack usage.
This commit is contained in:
@@ -55,6 +55,10 @@
|
||||
#undef OGS_LOG_DOMAIN
|
||||
#define OGS_LOG_DOMAIN __ogs_sock_domain
|
||||
|
||||
static bool ogs_sockaddr_compare(const ogs_sockaddr_t *a,
|
||||
const ogs_sockaddr_t *b,
|
||||
bool compare_port);
|
||||
|
||||
/* If you want to use getnameinfo,
|
||||
* you need to consider DNS query delay (about 10 seconds) */
|
||||
#if 0
|
||||
@@ -264,6 +268,60 @@ int ogs_sortaddrinfo(ogs_sockaddr_t **sa_list, int family)
|
||||
return OGS_OK;
|
||||
}
|
||||
|
||||
/*--------------------------------------------------------------------------
|
||||
* Merge a single node if not already in "dest" list
|
||||
*--------------------------------------------------------------------------
|
||||
*/
|
||||
void ogs_merge_single_addrinfo(
|
||||
ogs_sockaddr_t **dest, const ogs_sockaddr_t *item)
|
||||
{
|
||||
ogs_sockaddr_t *p;
|
||||
ogs_sockaddr_t *new_sa;
|
||||
|
||||
ogs_assert(dest);
|
||||
ogs_assert(item);
|
||||
|
||||
p = *dest;
|
||||
|
||||
while (p) {
|
||||
if (ogs_sockaddr_is_equal(p, item)) {
|
||||
/* Already exists */
|
||||
return;
|
||||
}
|
||||
p = p->next;
|
||||
}
|
||||
new_sa = (ogs_sockaddr_t *)ogs_malloc(sizeof(*new_sa));
|
||||
ogs_assert(new_sa);
|
||||
memcpy(new_sa, item, sizeof(*new_sa));
|
||||
if (item->hostname) {
|
||||
new_sa->hostname = ogs_strdup(item->hostname);
|
||||
ogs_assert(new_sa->hostname);
|
||||
}
|
||||
new_sa->next = NULL;
|
||||
if (!(*dest)) {
|
||||
*dest = new_sa;
|
||||
} else {
|
||||
p = *dest;
|
||||
while (p->next)
|
||||
p = p->next;
|
||||
p->next = new_sa;
|
||||
}
|
||||
}
|
||||
|
||||
/*--------------------------------------------------------------------------
|
||||
* Merge an entire src list into dest
|
||||
*--------------------------------------------------------------------------
|
||||
*/
|
||||
void ogs_merge_addrinfo(ogs_sockaddr_t **dest, const ogs_sockaddr_t *src)
|
||||
{
|
||||
const ogs_sockaddr_t *cur;
|
||||
cur = src;
|
||||
while (cur) {
|
||||
ogs_merge_single_addrinfo(dest, cur);
|
||||
cur = cur->next;
|
||||
}
|
||||
}
|
||||
|
||||
ogs_sockaddr_t *ogs_link_local_addr(const char *dev, const ogs_sockaddr_t *sa)
|
||||
{
|
||||
#if defined(HAVE_GETIFADDRS)
|
||||
@@ -419,13 +477,16 @@ socklen_t ogs_sockaddr_len(const void *sa)
|
||||
}
|
||||
}
|
||||
|
||||
bool ogs_sockaddr_is_equal(const void *p, const void *q)
|
||||
/*
|
||||
* Helper function to compare two addresses.
|
||||
* If compare_port is true, compare both port and address.
|
||||
* Otherwise, compare address only.
|
||||
*/
|
||||
static bool ogs_sockaddr_compare(const ogs_sockaddr_t *a,
|
||||
const ogs_sockaddr_t *b,
|
||||
bool compare_port)
|
||||
{
|
||||
const ogs_sockaddr_t *a, *b;
|
||||
|
||||
a = p;
|
||||
ogs_assert(a);
|
||||
b = q;
|
||||
ogs_assert(b);
|
||||
|
||||
if (a->ogs_sa_family != b->ogs_sa_family)
|
||||
@@ -433,23 +494,42 @@ bool ogs_sockaddr_is_equal(const void *p, const void *q)
|
||||
|
||||
switch (a->ogs_sa_family) {
|
||||
case AF_INET:
|
||||
if (a->sin.sin_port != b->sin.sin_port)
|
||||
if (compare_port && (a->sin.sin_port != b->sin.sin_port))
|
||||
return false;
|
||||
if (memcmp(&a->sin.sin_addr, &b->sin.sin_addr, sizeof(struct in_addr)) != 0)
|
||||
if (memcmp(&a->sin.sin_addr, &b->sin.sin_addr,
|
||||
sizeof(struct in_addr)) != 0)
|
||||
return false;
|
||||
return true;
|
||||
case AF_INET6:
|
||||
if (a->sin6.sin6_port != b->sin6.sin6_port)
|
||||
if (compare_port && (a->sin6.sin6_port != b->sin6.sin6_port))
|
||||
return false;
|
||||
if (memcmp(&a->sin6.sin6_addr, &b->sin6.sin6_addr, sizeof(struct in6_addr)) != 0)
|
||||
if (memcmp(&a->sin6.sin6_addr, &b->sin6.sin6_addr,
|
||||
sizeof(struct in6_addr)) != 0)
|
||||
return false;
|
||||
return true;
|
||||
default:
|
||||
ogs_error("Unexpected address faimily %u", a->ogs_sa_family);
|
||||
ogs_error("Unexpected address family %u", a->ogs_sa_family);
|
||||
ogs_abort();
|
||||
return false; /* Defensive return */
|
||||
}
|
||||
}
|
||||
|
||||
/* Compare addresses including port */
|
||||
bool ogs_sockaddr_is_equal(const void *p, const void *q)
|
||||
{
|
||||
const ogs_sockaddr_t *a = (const ogs_sockaddr_t *)p;
|
||||
const ogs_sockaddr_t *b = (const ogs_sockaddr_t *)q;
|
||||
return ogs_sockaddr_compare(a, b, true);
|
||||
}
|
||||
|
||||
/* Compare addresses without considering port */
|
||||
bool ogs_sockaddr_is_equal_addr(const void *p, const void *q)
|
||||
{
|
||||
const ogs_sockaddr_t *a = (const ogs_sockaddr_t *)p;
|
||||
const ogs_sockaddr_t *b = (const ogs_sockaddr_t *)q;
|
||||
return ogs_sockaddr_compare(a, b, false);
|
||||
}
|
||||
|
||||
static int parse_network(ogs_ipsubnet_t *ipsub, const char *network)
|
||||
{
|
||||
/* legacy syntax for ip addrs: a.b.c. ==> a.b.c.0/24 for example */
|
||||
@@ -669,7 +749,7 @@ char *ogs_ipstrdup(ogs_sockaddr_t *addr)
|
||||
|
||||
char *ogs_sockaddr_to_string_static(ogs_sockaddr_t *sa_list)
|
||||
{
|
||||
static char dumpstr[OGS_HUGE_LEN];
|
||||
static char dumpstr[OGS_HUGE_LEN] = { 0, };
|
||||
char *p, *last;
|
||||
ogs_sockaddr_t *addr = NULL;
|
||||
|
||||
|
@@ -67,20 +67,8 @@ struct ogs_sockaddr_s {
|
||||
* If there is a name in the configuration file,
|
||||
* it is set in the 'hostname' of ogs_sockaddr_t.
|
||||
* Then, it immediately call getaddrinfo() to fill addr in ogs_sockaddr_t.
|
||||
*
|
||||
* When it was always possible to convert DNS to addr, that was no problem.
|
||||
* However, in some environments, such as Roaming, there are situations
|
||||
* where it is difficult to always change the DNS to addr.
|
||||
*
|
||||
* So, 'fqdn' was created for the purpose of first use in ogs_sbi_client_t.
|
||||
* 'fqdn' always do not change with addr.
|
||||
* This value is used as it is in the actual client connection.
|
||||
*
|
||||
* Note that 'hostname' is still in use for server or other client
|
||||
* except for ogs_sbi_client_t.
|
||||
*/
|
||||
char *hostname;
|
||||
char *fqdn;
|
||||
|
||||
ogs_sockaddr_t *next;
|
||||
};
|
||||
@@ -103,6 +91,10 @@ int ogs_copyaddrinfo(
|
||||
int ogs_filteraddrinfo(ogs_sockaddr_t **sa_list, int family);
|
||||
int ogs_sortaddrinfo(ogs_sockaddr_t **sa_list, int family);
|
||||
|
||||
void ogs_merge_single_addrinfo(
|
||||
ogs_sockaddr_t **dest, const ogs_sockaddr_t *item);
|
||||
void ogs_merge_addrinfo(ogs_sockaddr_t **dest, const ogs_sockaddr_t *src);
|
||||
|
||||
ogs_sockaddr_t *ogs_link_local_addr(const char *dev, const ogs_sockaddr_t *sa);
|
||||
ogs_sockaddr_t *ogs_link_local_addr_by_dev(const char *dev);
|
||||
ogs_sockaddr_t *ogs_link_local_addr_by_sa(const ogs_sockaddr_t *sa);
|
||||
@@ -119,6 +111,7 @@ int ogs_inet_pton(int family, const char *src, void *sa);
|
||||
|
||||
socklen_t ogs_sockaddr_len(const void *sa);
|
||||
bool ogs_sockaddr_is_equal(const void *p, const void *q);
|
||||
bool ogs_sockaddr_is_equal_addr(const void *p, const void *q);
|
||||
|
||||
int ogs_ipsubnet(ogs_ipsubnet_t *ipsub,
|
||||
const char *ipstr, const char *mask_or_numbits);
|
||||
|
@@ -868,20 +868,67 @@ int ogs_pfcp_context_parse_config(const char *local, const char *remote)
|
||||
return OGS_OK;
|
||||
}
|
||||
|
||||
ogs_pfcp_node_t *ogs_pfcp_node_new(ogs_sockaddr_t *sa_list)
|
||||
/*--------------------------------------------------------------------------
|
||||
* check_any_match():
|
||||
* If any node in "list" or the single "single" matches base, return 1
|
||||
*--------------------------------------------------------------------------
|
||||
*/
|
||||
static bool check_any_match(ogs_sockaddr_t *base,
|
||||
ogs_sockaddr_t *list,
|
||||
const ogs_sockaddr_t *single)
|
||||
{
|
||||
ogs_pfcp_node_t *node = NULL;
|
||||
ogs_sockaddr_t *p = NULL;
|
||||
|
||||
ogs_assert(sa_list);
|
||||
while (list) {
|
||||
p = base;
|
||||
while (p) {
|
||||
if (ogs_sockaddr_is_equal_addr(p, list))
|
||||
return true;
|
||||
p = p->next;
|
||||
}
|
||||
list = list->next;
|
||||
}
|
||||
if (single) {
|
||||
p = base;
|
||||
while (p) {
|
||||
if (ogs_sockaddr_is_equal_addr(p, single))
|
||||
return true;
|
||||
p = p->next;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/*--------------------------------------------------------------------------
|
||||
* ogs_pfcp_node_new():
|
||||
* Create node with config_addr, copy config_addr into node->addr_list
|
||||
*--------------------------------------------------------------------------
|
||||
*/
|
||||
ogs_pfcp_node_t *ogs_pfcp_node_new(ogs_sockaddr_t *config_addr)
|
||||
{
|
||||
int rv;
|
||||
ogs_pfcp_node_t *node = NULL;
|
||||
|
||||
ogs_pool_alloc(&ogs_pfcp_node_pool, &node);
|
||||
if (!node) {
|
||||
ogs_error("No memory: ogs_pool_alloc() failed");
|
||||
ogs_error("No memory: ogs_pool_alloc() failed [%s]",
|
||||
ogs_sockaddr_to_string_static(config_addr));
|
||||
return NULL;
|
||||
}
|
||||
memset(node, 0, sizeof(ogs_pfcp_node_t));
|
||||
|
||||
node->sa_list = sa_list;
|
||||
/* Store config_addr, if any */
|
||||
node->config_addr = config_addr;
|
||||
|
||||
/* If config_addr is given, copy it immediately into addr_list */
|
||||
if (config_addr) {
|
||||
rv = ogs_copyaddrinfo(&node->addr_list, config_addr);
|
||||
if (rv != OGS_OK) {
|
||||
ogs_error("ogs_copyaddrinfo() failed");
|
||||
ogs_pool_free(&ogs_pfcp_node_pool, node);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
ogs_list_init(&node->local_list);
|
||||
ogs_list_init(&node->remote_list);
|
||||
@@ -899,49 +946,125 @@ void ogs_pfcp_node_free(ogs_pfcp_node_t *node)
|
||||
|
||||
ogs_pfcp_xact_delete_all(node);
|
||||
|
||||
ogs_freeaddrinfo(node->sa_list);
|
||||
ogs_freeaddrinfo(node->config_addr);
|
||||
ogs_freeaddrinfo(node->addr_list);
|
||||
|
||||
ogs_pool_free(&ogs_pfcp_node_pool, node);
|
||||
}
|
||||
|
||||
ogs_pfcp_node_t *ogs_pfcp_node_add(
|
||||
ogs_list_t *list, ogs_sockaddr_t *addr)
|
||||
/*--------------------------------------------------------------------------
|
||||
* ogs_pfcp_node_add():
|
||||
* Create a new node (with config_addr=NULL), set node_id/from,
|
||||
* then merge => finally add to list
|
||||
*--------------------------------------------------------------------------
|
||||
*/
|
||||
ogs_pfcp_node_t *ogs_pfcp_node_add(ogs_list_t *list,
|
||||
ogs_pfcp_node_id_t *node_id, ogs_sockaddr_t *from)
|
||||
{
|
||||
ogs_pfcp_node_t *node = NULL;
|
||||
ogs_sockaddr_t *new = NULL;
|
||||
|
||||
ogs_assert(list);
|
||||
ogs_assert(addr);
|
||||
ogs_assert(node_id && from);
|
||||
|
||||
ogs_assert(OGS_OK == ogs_copyaddrinfo(&new, addr));
|
||||
node = ogs_pfcp_node_new(new);
|
||||
/* Create node with no config_addr initially */
|
||||
node = ogs_pfcp_node_new(NULL);
|
||||
if (!node) {
|
||||
ogs_error("No memory : ogs_pfcp_node_new() failed");
|
||||
ogs_freeaddrinfo(new);
|
||||
ogs_error("No memory: ogs_pfcp_node_add() failed node_id:%s from:%s",
|
||||
ogs_pfcp_node_id_to_string_static(node_id),
|
||||
ogs_sockaddr_to_string_static(from));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ogs_assert(node);
|
||||
memcpy(&node->addr, new, sizeof node->addr);
|
||||
/* Store node_id and from_addr */
|
||||
memcpy(&node->node_id, node_id, sizeof(node->node_id));
|
||||
|
||||
/* Merge them => fill node->addr_list if conditions are met */
|
||||
if (ogs_pfcp_node_merge(node, node_id, from) != OGS_OK) {
|
||||
ogs_error("ogs_pfcp_node_merge() failed node_id [%s] from [%s]",
|
||||
ogs_pfcp_node_id_to_string_static(node_id),
|
||||
ogs_sockaddr_to_string_static(from));
|
||||
ogs_pool_free(&ogs_pfcp_node_pool, node);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ogs_list_add(list, node);
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
ogs_pfcp_node_t *ogs_pfcp_node_find(
|
||||
ogs_list_t *list, ogs_sockaddr_t *addr)
|
||||
/*--------------------------------------------------------------------------
|
||||
* ogs_pfcp_node_find():
|
||||
* Find a node in the list whose "addr_list" matches node_id or from_addr
|
||||
*--------------------------------------------------------------------------
|
||||
*/
|
||||
ogs_pfcp_node_t *ogs_pfcp_node_find(ogs_list_t *list,
|
||||
ogs_pfcp_node_id_t *node_id, ogs_sockaddr_t *from)
|
||||
{
|
||||
ogs_pfcp_node_t *node = NULL;
|
||||
ogs_pfcp_node_t *cur;
|
||||
ogs_sockaddr_t *nid_list = NULL;
|
||||
int found = 0;
|
||||
|
||||
ogs_assert(list);
|
||||
ogs_assert(addr);
|
||||
ogs_assert(node_id || from);
|
||||
|
||||
ogs_list_for_each(list, node) {
|
||||
if (ogs_sockaddr_is_equal(&node->addr, addr) == true)
|
||||
if (node_id)
|
||||
nid_list = ogs_pfcp_node_id_to_addrinfo(node_id);
|
||||
|
||||
ogs_list_for_each(list, cur) {
|
||||
if (check_any_match(cur->addr_list, nid_list, from)) {
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (nid_list)
|
||||
ogs_freeaddrinfo(nid_list);
|
||||
|
||||
if (found)
|
||||
return cur;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*--------------------------------------------------------------------------
|
||||
* ogs_pfcp_node_merge():
|
||||
* Merge logic: addr_list + node_id + from_addr
|
||||
*--------------------------------------------------------------------------
|
||||
* - If node->addr_list is empty, copy node->config_addr into addr_list first
|
||||
* - Convert node_id to addresses, then check from_addr
|
||||
* - If addr_list is empty => merge everything
|
||||
* - If addr_list not empty => merge only if there's a matching IP
|
||||
*/
|
||||
int ogs_pfcp_node_merge(ogs_pfcp_node_t *node,
|
||||
ogs_pfcp_node_id_t *node_id, ogs_sockaddr_t *from)
|
||||
{
|
||||
ogs_sockaddr_t *nid_list = NULL;
|
||||
ogs_sockaddr_t single;
|
||||
|
||||
ogs_assert(node);
|
||||
ogs_assert(node_id || from);
|
||||
|
||||
/* Convert node_id to a list of addresses */
|
||||
if (node_id) {
|
||||
nid_list = ogs_pfcp_node_id_to_addrinfo(node_id);
|
||||
if (!nid_list) {
|
||||
ogs_error("ogs_pfcp_node_id_to_addrinfo() failed [%d]",
|
||||
node_id->type);
|
||||
return OGS_ERROR;
|
||||
}
|
||||
|
||||
ogs_merge_addrinfo(&node->addr_list, nid_list);
|
||||
ogs_freeaddrinfo(nid_list);
|
||||
}
|
||||
|
||||
return node;
|
||||
/* "from" as single item */
|
||||
if (from) {
|
||||
memcpy(&single, from, sizeof(single));
|
||||
single.next = NULL;
|
||||
|
||||
ogs_merge_addrinfo(&node->addr_list, &single);
|
||||
}
|
||||
|
||||
return OGS_OK;
|
||||
}
|
||||
|
||||
void ogs_pfcp_node_remove(ogs_list_t *list, ogs_pfcp_node_t *node)
|
||||
@@ -963,6 +1086,26 @@ void ogs_pfcp_node_remove_all(ogs_list_t *list)
|
||||
ogs_pfcp_node_remove(list, node);
|
||||
}
|
||||
|
||||
/* Function to compare two node IDs */
|
||||
int ogs_pfcp_node_id_compare(
|
||||
const ogs_pfcp_node_id_t *id1, const ogs_pfcp_node_id_t *id2)
|
||||
{
|
||||
if (id1->type != id2->type) {
|
||||
return false; /* Types do not match */
|
||||
}
|
||||
|
||||
switch (id1->type) {
|
||||
case OGS_PFCP_NODE_ID_IPV4:
|
||||
return (id1->addr == id2->addr);
|
||||
case OGS_PFCP_NODE_ID_IPV6:
|
||||
return (memcmp(id1->addr6, id2->addr6, OGS_IPV6_LEN) == 0);
|
||||
case OGS_PFCP_NODE_ID_FQDN:
|
||||
return (strcmp(id1->fqdn, id2->fqdn) == 0);
|
||||
default:
|
||||
return false; /* Unknown types do not match */
|
||||
}
|
||||
}
|
||||
|
||||
ogs_gtpu_resource_t *ogs_pfcp_find_gtpu_resource(ogs_list_t *list,
|
||||
char *dnn, ogs_pfcp_interface_t source_interface)
|
||||
{
|
||||
|
@@ -84,10 +84,17 @@ typedef struct ogs_pfcp_context_s {
|
||||
typedef struct ogs_pfcp_node_s {
|
||||
ogs_lnode_t lnode; /* A node of list_t */
|
||||
|
||||
ogs_sockaddr_t *sa_list; /* Socket Address List Candidate */
|
||||
ogs_sockaddr_t *config_addr; /* Configured addresses */
|
||||
ogs_pfcp_node_id_t node_id; /* PFCP node ID */
|
||||
|
||||
ogs_sock_t *sock; /* Socket Instance */
|
||||
ogs_sockaddr_t addr; /* Remote Address */
|
||||
/* List of addresses:: final merged address list */
|
||||
ogs_sockaddr_t *addr_list;
|
||||
|
||||
/*
|
||||
* Iterator for round-robin sendto operations.
|
||||
* Points to the current address in the round-robin sequence.
|
||||
*/
|
||||
ogs_sockaddr_t *current_addr;
|
||||
|
||||
ogs_list_t local_list;
|
||||
ogs_list_t remote_list;
|
||||
@@ -399,15 +406,19 @@ void ogs_pfcp_context_final(void);
|
||||
ogs_pfcp_context_t *ogs_pfcp_self(void);
|
||||
int ogs_pfcp_context_parse_config(const char *local, const char *remote);
|
||||
|
||||
ogs_pfcp_node_t *ogs_pfcp_node_new(ogs_sockaddr_t *sa_list);
|
||||
ogs_pfcp_node_t *ogs_pfcp_node_new(ogs_sockaddr_t *config_addr);
|
||||
void ogs_pfcp_node_free(ogs_pfcp_node_t *node);
|
||||
|
||||
ogs_pfcp_node_t *ogs_pfcp_node_add(
|
||||
ogs_list_t *list, ogs_sockaddr_t *addr);
|
||||
ogs_pfcp_node_t *ogs_pfcp_node_find(
|
||||
ogs_list_t *list, ogs_sockaddr_t *addr);
|
||||
ogs_pfcp_node_t *ogs_pfcp_node_add(ogs_list_t *list,
|
||||
ogs_pfcp_node_id_t *node_id, ogs_sockaddr_t *from);
|
||||
ogs_pfcp_node_t *ogs_pfcp_node_find(ogs_list_t *list,
|
||||
ogs_pfcp_node_id_t *node_id, ogs_sockaddr_t *from);
|
||||
int ogs_pfcp_node_merge(ogs_pfcp_node_t *node,
|
||||
ogs_pfcp_node_id_t *node_id, ogs_sockaddr_t *from);
|
||||
void ogs_pfcp_node_remove(ogs_list_t *list, ogs_pfcp_node_t *node);
|
||||
void ogs_pfcp_node_remove_all(ogs_list_t *list);
|
||||
int ogs_pfcp_node_id_compare(
|
||||
const ogs_pfcp_node_id_t *id1, const ogs_pfcp_node_id_t *id2);
|
||||
|
||||
ogs_gtpu_resource_t *ogs_pfcp_find_gtpu_resource(ogs_list_t *list,
|
||||
char *dnn, ogs_pfcp_interface_t source_interface);
|
||||
|
@@ -130,14 +130,9 @@ bool ogs_pfcp_cp_handle_association_setup_request(
|
||||
}
|
||||
}
|
||||
|
||||
if (node->up_function_features.ftup == 0) {
|
||||
char buf[OGS_ADDRSTRLEN];
|
||||
ogs_sockaddr_t *addr = node->sa_list;
|
||||
ogs_assert(addr);
|
||||
|
||||
ogs_warn("F-TEID allocation/release not supported with peer [%s]:%d",
|
||||
OGS_ADDR(addr, buf), OGS_PORT(addr));
|
||||
}
|
||||
if (node->up_function_features.ftup == 0)
|
||||
ogs_warn("F-TEID allocation/release not supported with peer %s",
|
||||
ogs_sockaddr_to_string_static(node->addr_list));
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -182,14 +177,9 @@ bool ogs_pfcp_cp_handle_association_setup_response(
|
||||
}
|
||||
}
|
||||
|
||||
if (node->up_function_features.ftup == 0) {
|
||||
char buf[OGS_ADDRSTRLEN];
|
||||
ogs_sockaddr_t *addr = node->sa_list;
|
||||
ogs_assert(addr);
|
||||
|
||||
ogs_warn("F-TEID allocation/release not supported with peer [%s]:%d",
|
||||
OGS_ADDR(addr, buf), OGS_PORT(addr));
|
||||
}
|
||||
if (node->up_function_features.ftup == 0)
|
||||
ogs_warn("F-TEID allocation/release not supported with peer %s",
|
||||
ogs_sockaddr_to_string_static(node->addr_list));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@@ -36,69 +36,6 @@ ogs_sock_t *ogs_pfcp_server(ogs_socknode_t *node)
|
||||
return pfcp;
|
||||
}
|
||||
|
||||
int ogs_pfcp_connect(
|
||||
ogs_sock_t *ipv4, ogs_sock_t *ipv6, ogs_pfcp_node_t *node)
|
||||
{
|
||||
ogs_sockaddr_t *addr;
|
||||
char buf[OGS_ADDRSTRLEN];
|
||||
|
||||
ogs_assert(ipv4 || ipv6);
|
||||
ogs_assert(node);
|
||||
ogs_assert(node->sa_list);
|
||||
|
||||
addr = node->sa_list;
|
||||
while (addr) {
|
||||
ogs_sock_t *sock = NULL;
|
||||
|
||||
if (addr->ogs_sa_family == AF_INET)
|
||||
sock = ipv4;
|
||||
else if (addr->ogs_sa_family == AF_INET6)
|
||||
sock = ipv6;
|
||||
else
|
||||
ogs_assert_if_reached();
|
||||
|
||||
if (sock) {
|
||||
ogs_info("ogs_pfcp_connect() [%s]:%d",
|
||||
OGS_ADDR(addr, buf), OGS_PORT(addr));
|
||||
|
||||
node->sock = sock;
|
||||
memcpy(&node->addr, addr, sizeof node->addr);
|
||||
break;
|
||||
}
|
||||
|
||||
addr = addr->next;
|
||||
}
|
||||
|
||||
if (addr == NULL) {
|
||||
ogs_error("ogs_pfcp_connect() [%s]:%d failed",
|
||||
OGS_ADDR(node->sa_list, buf), OGS_PORT(node->sa_list));
|
||||
ogs_error("Please check the IP version between SMF and UPF nodes.");
|
||||
return OGS_ERROR;
|
||||
}
|
||||
|
||||
return OGS_OK;
|
||||
}
|
||||
|
||||
int ogs_pfcp_send(ogs_pfcp_node_t *node, ogs_pkbuf_t *pkbuf)
|
||||
{
|
||||
ssize_t sent;
|
||||
ogs_sock_t *sock = NULL;
|
||||
|
||||
ogs_assert(node);
|
||||
ogs_assert(pkbuf);
|
||||
sock = node->sock;
|
||||
ogs_assert(sock);
|
||||
|
||||
sent = ogs_send(sock->fd, pkbuf->data, pkbuf->len, 0);
|
||||
if (sent < 0 || sent != pkbuf->len) {
|
||||
ogs_log_message(OGS_LOG_ERROR, ogs_socket_errno,
|
||||
"ogs_pfcp_send() failed");
|
||||
return OGS_ERROR;
|
||||
}
|
||||
|
||||
return OGS_OK;
|
||||
}
|
||||
|
||||
int ogs_pfcp_sendto(ogs_pfcp_node_t *node, ogs_pkbuf_t *pkbuf)
|
||||
{
|
||||
ssize_t sent;
|
||||
@@ -107,11 +44,34 @@ int ogs_pfcp_sendto(ogs_pfcp_node_t *node, ogs_pkbuf_t *pkbuf)
|
||||
|
||||
ogs_assert(node);
|
||||
ogs_assert(pkbuf);
|
||||
sock = node->sock;
|
||||
ogs_assert(sock);
|
||||
addr = &node->addr;
|
||||
ogs_assert(node->addr_list);
|
||||
|
||||
/* Initialize round-robin iterator if needed */
|
||||
if (node->current_addr == NULL) {
|
||||
node->current_addr = node->addr_list;
|
||||
}
|
||||
addr = node->current_addr;
|
||||
ogs_assert(addr);
|
||||
|
||||
if (addr->ogs_sa_family == AF_INET) {
|
||||
sock = ogs_pfcp_self()->pfcp_sock;
|
||||
if (!sock) {
|
||||
ogs_error("IPv4 socket (pfcp_sock) is not available. "
|
||||
"Ensure that 'pfcp.server.address: 127.0.0.1' "
|
||||
"is set in the YAML configuration file.");
|
||||
return OGS_ERROR;
|
||||
}
|
||||
} else if (addr->ogs_sa_family == AF_INET6) {
|
||||
sock = ogs_pfcp_self()->pfcp_sock6;
|
||||
if (!sock) {
|
||||
ogs_error("IPv6 socket (pfcp_sock) is not available. "
|
||||
"Ensure that 'pfcp.server.address: [::1]' "
|
||||
"is set in the YAML configuration file.");
|
||||
return OGS_ERROR;
|
||||
}
|
||||
} else
|
||||
ogs_assert_if_reached();
|
||||
|
||||
sent = ogs_sendto(sock->fd, pkbuf->data, pkbuf->len, 0, addr);
|
||||
if (sent < 0 || sent != pkbuf->len) {
|
||||
if (ogs_socket_errno != OGS_EAGAIN) {
|
||||
@@ -125,6 +85,13 @@ int ogs_pfcp_sendto(ogs_pfcp_node_t *node, ogs_pkbuf_t *pkbuf)
|
||||
return OGS_ERROR;
|
||||
}
|
||||
|
||||
/* Move to next address in round-robin sequence */
|
||||
if (node->current_addr->next)
|
||||
node->current_addr = node->current_addr->next;
|
||||
else
|
||||
/* If end of list reached, wrap around to the start */
|
||||
node->current_addr = node->addr_list;
|
||||
|
||||
return OGS_OK;
|
||||
}
|
||||
|
||||
|
@@ -56,10 +56,6 @@ extern "C" {
|
||||
typedef struct ogs_pfcp_xact_s ogs_pfcp_xact_t;
|
||||
|
||||
ogs_sock_t *ogs_pfcp_server(ogs_socknode_t *node);
|
||||
int ogs_pfcp_connect(
|
||||
ogs_sock_t *ipv4, ogs_sock_t *ipv6, ogs_pfcp_node_t *node);
|
||||
|
||||
int ogs_pfcp_send(ogs_pfcp_node_t *node, ogs_pkbuf_t *pkbuf);
|
||||
int ogs_pfcp_sendto(ogs_pfcp_node_t *node, ogs_pkbuf_t *pkbuf);
|
||||
|
||||
ogs_pkbuf_t *ogs_pfcp_handle_echo_req(ogs_pkbuf_t *pkt);
|
||||
|
336
lib/pfcp/util.c
336
lib/pfcp/util.c
@@ -19,116 +19,180 @@
|
||||
|
||||
#include "ogs-pfcp.h"
|
||||
|
||||
/**
|
||||
* Extracts the `node_id` from a PFCP message.
|
||||
*
|
||||
* @param node_id Pointer to store the extracted node_id.
|
||||
* @param msg Pointer to the parsed PFCP message.
|
||||
* @return ogs_pfcp_status_e Status of the operation.
|
||||
/*
|
||||
* Requirements of Node ID:
|
||||
* NONE : Node ID must not be present
|
||||
* OPTIONAL : Node ID may or may not be present
|
||||
* MANDATORY : Node ID must be present
|
||||
*/
|
||||
ogs_pfcp_status_e ogs_pfcp_get_node_id(
|
||||
ogs_pfcp_node_id_t *node_id, ogs_pfcp_message_t *message)
|
||||
#define OGS_PFCP_NODE_ID_NONE 0
|
||||
#define OGS_PFCP_NODE_ID_OPTIONAL 1
|
||||
#define OGS_PFCP_NODE_ID_MANDATORY 2
|
||||
|
||||
/*
|
||||
* This function extracts the PFCP Node ID from the given PFCP message.
|
||||
* It determines the Node ID field location and requirement based on
|
||||
* the message type. Then it validates presence and copies data into
|
||||
* 'node_id'. If Node ID is not consistent with the requirement, an
|
||||
* error status is returned.
|
||||
*/
|
||||
ogs_pfcp_status_e
|
||||
ogs_pfcp_extract_node_id(ogs_pfcp_message_t *message,
|
||||
ogs_pfcp_node_id_t *node_id)
|
||||
{
|
||||
|
||||
/* For C89 compliance, all variables are declared upfront. */
|
||||
ogs_pfcp_tlv_node_id_t *tlv_node_id = NULL;
|
||||
int requirement = OGS_PFCP_NODE_ID_NONE;
|
||||
ogs_pfcp_status_e status = OGS_PFCP_STATUS_SUCCESS;
|
||||
|
||||
ogs_assert(node_id);
|
||||
/* Validate input pointers */
|
||||
ogs_assert(message);
|
||||
ogs_assert(node_id);
|
||||
|
||||
/* Initialize the output structure */
|
||||
memset(node_id, 0, sizeof(*node_id));
|
||||
|
||||
/* Determine the location of node_id TLV and requirement */
|
||||
switch (message->h.type) {
|
||||
/* Message Types with node_id */
|
||||
case OGS_PFCP_PFD_MANAGEMENT_REQUEST_TYPE:
|
||||
tlv_node_id = &message->pfcp_pfd_management_request.node_id;
|
||||
break;
|
||||
case OGS_PFCP_PFD_MANAGEMENT_REQUEST_TYPE:
|
||||
tlv_node_id = &message->pfcp_pfd_management_request.node_id;
|
||||
requirement = OGS_PFCP_NODE_ID_OPTIONAL;
|
||||
break;
|
||||
|
||||
case OGS_PFCP_PFD_MANAGEMENT_RESPONSE_TYPE:
|
||||
tlv_node_id = &message->pfcp_pfd_management_response.node_id;
|
||||
break;
|
||||
case OGS_PFCP_PFD_MANAGEMENT_RESPONSE_TYPE:
|
||||
tlv_node_id = &message->pfcp_pfd_management_response.node_id;
|
||||
requirement = OGS_PFCP_NODE_ID_OPTIONAL;
|
||||
break;
|
||||
|
||||
case OGS_PFCP_ASSOCIATION_SETUP_REQUEST_TYPE:
|
||||
tlv_node_id = &message->pfcp_association_setup_request.node_id;
|
||||
break;
|
||||
case OGS_PFCP_ASSOCIATION_SETUP_REQUEST_TYPE:
|
||||
tlv_node_id = &message->pfcp_association_setup_request.node_id;
|
||||
requirement = OGS_PFCP_NODE_ID_MANDATORY;
|
||||
break;
|
||||
|
||||
case OGS_PFCP_ASSOCIATION_SETUP_RESPONSE_TYPE:
|
||||
tlv_node_id = &message->pfcp_association_setup_response.node_id;
|
||||
break;
|
||||
case OGS_PFCP_ASSOCIATION_SETUP_RESPONSE_TYPE:
|
||||
tlv_node_id = &message->pfcp_association_setup_response.node_id;
|
||||
requirement = OGS_PFCP_NODE_ID_MANDATORY;
|
||||
break;
|
||||
|
||||
case OGS_PFCP_ASSOCIATION_UPDATE_REQUEST_TYPE:
|
||||
tlv_node_id = &message->pfcp_association_update_request.node_id;
|
||||
break;
|
||||
case OGS_PFCP_ASSOCIATION_UPDATE_REQUEST_TYPE:
|
||||
tlv_node_id = &message->pfcp_association_update_request.node_id;
|
||||
requirement = OGS_PFCP_NODE_ID_MANDATORY;
|
||||
break;
|
||||
|
||||
case OGS_PFCP_ASSOCIATION_UPDATE_RESPONSE_TYPE:
|
||||
tlv_node_id = &message->pfcp_association_update_response.node_id;
|
||||
break;
|
||||
case OGS_PFCP_ASSOCIATION_UPDATE_RESPONSE_TYPE:
|
||||
tlv_node_id = &message->pfcp_association_update_response.node_id;
|
||||
requirement = OGS_PFCP_NODE_ID_MANDATORY;
|
||||
break;
|
||||
|
||||
case OGS_PFCP_ASSOCIATION_RELEASE_REQUEST_TYPE:
|
||||
tlv_node_id = &message->pfcp_association_release_request.node_id;
|
||||
break;
|
||||
case OGS_PFCP_ASSOCIATION_RELEASE_REQUEST_TYPE:
|
||||
tlv_node_id = &message->pfcp_association_release_request.node_id;
|
||||
requirement = OGS_PFCP_NODE_ID_MANDATORY;
|
||||
break;
|
||||
|
||||
case OGS_PFCP_ASSOCIATION_RELEASE_RESPONSE_TYPE:
|
||||
tlv_node_id = &message->pfcp_association_release_response.node_id;
|
||||
break;
|
||||
case OGS_PFCP_ASSOCIATION_RELEASE_RESPONSE_TYPE:
|
||||
tlv_node_id = &message->pfcp_association_release_response.node_id;
|
||||
requirement = OGS_PFCP_NODE_ID_MANDATORY;
|
||||
break;
|
||||
|
||||
case OGS_PFCP_NODE_REPORT_REQUEST_TYPE:
|
||||
tlv_node_id = &message->pfcp_node_report_request.node_id;
|
||||
break;
|
||||
case OGS_PFCP_NODE_REPORT_REQUEST_TYPE:
|
||||
tlv_node_id = &message->pfcp_node_report_request.node_id;
|
||||
requirement = OGS_PFCP_NODE_ID_MANDATORY;
|
||||
break;
|
||||
|
||||
case OGS_PFCP_NODE_REPORT_RESPONSE_TYPE:
|
||||
tlv_node_id = &message->pfcp_node_report_response.node_id;
|
||||
break;
|
||||
case OGS_PFCP_NODE_REPORT_RESPONSE_TYPE:
|
||||
tlv_node_id = &message->pfcp_node_report_response.node_id;
|
||||
requirement = OGS_PFCP_NODE_ID_MANDATORY;
|
||||
break;
|
||||
|
||||
case OGS_PFCP_SESSION_SET_DELETION_REQUEST_TYPE:
|
||||
tlv_node_id = &message->pfcp_session_set_deletion_request.node_id;
|
||||
break;
|
||||
case OGS_PFCP_SESSION_SET_DELETION_REQUEST_TYPE:
|
||||
tlv_node_id = &message->pfcp_session_set_deletion_request.node_id;
|
||||
requirement = OGS_PFCP_NODE_ID_MANDATORY;
|
||||
break;
|
||||
|
||||
case OGS_PFCP_SESSION_SET_DELETION_RESPONSE_TYPE:
|
||||
tlv_node_id = &message->pfcp_session_set_deletion_response.node_id;
|
||||
break;
|
||||
case OGS_PFCP_SESSION_SET_DELETION_RESPONSE_TYPE:
|
||||
tlv_node_id = &message->pfcp_session_set_deletion_response.node_id;
|
||||
requirement = OGS_PFCP_NODE_ID_MANDATORY;
|
||||
break;
|
||||
|
||||
case OGS_PFCP_SESSION_SET_MODIFICATION_REQUEST_TYPE:
|
||||
tlv_node_id =
|
||||
&message->pfcp_session_set_modification_request.node_id;
|
||||
break;
|
||||
case OGS_PFCP_SESSION_SET_MODIFICATION_REQUEST_TYPE:
|
||||
tlv_node_id = &message->pfcp_session_set_modification_request.node_id;
|
||||
requirement = OGS_PFCP_NODE_ID_MANDATORY;
|
||||
break;
|
||||
|
||||
case OGS_PFCP_SESSION_SET_MODIFICATION_RESPONSE_TYPE:
|
||||
tlv_node_id =
|
||||
&message->pfcp_session_set_modification_response.node_id;
|
||||
break;
|
||||
case OGS_PFCP_SESSION_SET_MODIFICATION_RESPONSE_TYPE:
|
||||
tlv_node_id = &message->pfcp_session_set_modification_response.node_id;
|
||||
requirement = OGS_PFCP_NODE_ID_MANDATORY;
|
||||
break;
|
||||
|
||||
case OGS_PFCP_SESSION_ESTABLISHMENT_REQUEST_TYPE:
|
||||
tlv_node_id = &message->pfcp_session_establishment_request.node_id;
|
||||
break;
|
||||
case OGS_PFCP_SESSION_ESTABLISHMENT_REQUEST_TYPE:
|
||||
tlv_node_id = &message->pfcp_session_establishment_request.node_id;
|
||||
requirement = OGS_PFCP_NODE_ID_MANDATORY;
|
||||
break;
|
||||
|
||||
case OGS_PFCP_SESSION_ESTABLISHMENT_RESPONSE_TYPE:
|
||||
tlv_node_id = &message->pfcp_session_establishment_response.node_id;
|
||||
break;
|
||||
case OGS_PFCP_SESSION_ESTABLISHMENT_RESPONSE_TYPE:
|
||||
tlv_node_id = &message->pfcp_session_establishment_response.node_id;
|
||||
requirement = OGS_PFCP_NODE_ID_MANDATORY;
|
||||
break;
|
||||
|
||||
case OGS_PFCP_SESSION_MODIFICATION_REQUEST_TYPE:
|
||||
tlv_node_id = &message->pfcp_session_modification_request.node_id;
|
||||
break;
|
||||
case OGS_PFCP_SESSION_MODIFICATION_REQUEST_TYPE:
|
||||
tlv_node_id = &message->pfcp_session_modification_request.node_id;
|
||||
requirement = OGS_PFCP_NODE_ID_OPTIONAL;
|
||||
break;
|
||||
|
||||
/* Add other message types with node_id here as needed */
|
||||
/* Add other message types with node_id here as needed */
|
||||
|
||||
/* Message Types without node_id */
|
||||
case OGS_PFCP_HEARTBEAT_REQUEST_TYPE:
|
||||
case OGS_PFCP_HEARTBEAT_RESPONSE_TYPE:
|
||||
case OGS_PFCP_VERSION_NOT_SUPPORTED_RESPONSE_TYPE:
|
||||
case OGS_PFCP_SESSION_MODIFICATION_RESPONSE_TYPE:
|
||||
case OGS_PFCP_SESSION_DELETION_REQUEST_TYPE:
|
||||
case OGS_PFCP_SESSION_DELETION_RESPONSE_TYPE:
|
||||
case OGS_PFCP_SESSION_REPORT_REQUEST_TYPE:
|
||||
case OGS_PFCP_SESSION_REPORT_RESPONSE_TYPE:
|
||||
break;
|
||||
case OGS_PFCP_HEARTBEAT_REQUEST_TYPE:
|
||||
case OGS_PFCP_HEARTBEAT_RESPONSE_TYPE:
|
||||
case OGS_PFCP_VERSION_NOT_SUPPORTED_RESPONSE_TYPE:
|
||||
case OGS_PFCP_SESSION_MODIFICATION_RESPONSE_TYPE:
|
||||
case OGS_PFCP_SESSION_DELETION_REQUEST_TYPE:
|
||||
case OGS_PFCP_SESSION_DELETION_RESPONSE_TYPE:
|
||||
case OGS_PFCP_SESSION_REPORT_REQUEST_TYPE:
|
||||
case OGS_PFCP_SESSION_REPORT_RESPONSE_TYPE:
|
||||
/* Node ID must not be present for these messages */
|
||||
requirement = OGS_PFCP_NODE_ID_NONE;
|
||||
break;
|
||||
|
||||
default:
|
||||
ogs_error("Unknown message type %d", message->h.type);
|
||||
return OGS_PFCP_ERROR_UNKNOWN_MESSAGE;
|
||||
default:
|
||||
/* Unknown message type */
|
||||
ogs_error("Unknown message type %d", message->h.type);
|
||||
return OGS_PFCP_ERROR_UNKNOWN_MESSAGE;
|
||||
}
|
||||
|
||||
if (!tlv_node_id)
|
||||
return OGS_PFCP_ERROR_NODE_ID_NOT_FOUND;
|
||||
/* Check requirement vs. tlv_node_id existence */
|
||||
switch (requirement) {
|
||||
case OGS_PFCP_NODE_ID_MANDATORY:
|
||||
/* Must have tlv_node_id. presence must be 1. */
|
||||
ogs_assert(tlv_node_id);
|
||||
if (!tlv_node_id->presence) {
|
||||
status = OGS_PFCP_ERROR_NODE_ID_NOT_PRESENT;
|
||||
goto done;
|
||||
}
|
||||
break;
|
||||
|
||||
if (!tlv_node_id->presence)
|
||||
return OGS_PFCP_ERROR_NODE_ID_NOT_PRESENT;
|
||||
case OGS_PFCP_NODE_ID_OPTIONAL:
|
||||
/*
|
||||
* Must have tlv_node_id. presence=1 => real Node ID
|
||||
* presence=0 => no Node ID
|
||||
*/
|
||||
ogs_assert(tlv_node_id);
|
||||
if (!tlv_node_id->presence) {
|
||||
status = OGS_PFCP_STATUS_NODE_ID_OPTIONAL_ABSENT;
|
||||
goto done;
|
||||
}
|
||||
break;
|
||||
|
||||
case OGS_PFCP_NODE_ID_NONE:
|
||||
/* Must be NULL => no Node ID field */
|
||||
ogs_assert(tlv_node_id == NULL);
|
||||
status = OGS_PFCP_STATUS_NODE_ID_NONE;
|
||||
goto done;
|
||||
|
||||
default:
|
||||
status = OGS_PFCP_ERROR_UNKNOWN_MESSAGE;
|
||||
goto done;
|
||||
}
|
||||
|
||||
memcpy(node_id, tlv_node_id->data, tlv_node_id->len);
|
||||
|
||||
@@ -140,5 +204,113 @@ ogs_pfcp_status_e ogs_pfcp_get_node_id(
|
||||
return OGS_PFCP_ERROR_SEMANTIC_INCORRECT_MESSAGE;
|
||||
}
|
||||
|
||||
return OGS_PFCP_STATUS_SUCCESS;
|
||||
/* Node ID is valid */
|
||||
status = OGS_PFCP_STATUS_SUCCESS;
|
||||
|
||||
done:
|
||||
return status;
|
||||
}
|
||||
|
||||
ogs_sockaddr_t *ogs_pfcp_node_id_to_addrinfo(const ogs_pfcp_node_id_t *node_id)
|
||||
{
|
||||
ogs_sockaddr_t *p;
|
||||
int ret;
|
||||
uint16_t port = ogs_pfcp_self()->pfcp_port;
|
||||
char fqdn[OGS_MAX_FQDN_LEN+1];
|
||||
|
||||
ogs_assert(node_id);
|
||||
switch (node_id->type) {
|
||||
|
||||
/*------------------------------------------------
|
||||
* 1) IPv4
|
||||
*-----------------------------------------------*/
|
||||
case OGS_PFCP_NODE_ID_IPV4:
|
||||
p = (ogs_sockaddr_t *)ogs_calloc(1, sizeof(*p));
|
||||
if (!p) {
|
||||
ogs_error("ogs_calloc() failed");
|
||||
return NULL;
|
||||
}
|
||||
p->sa.sa_family = AF_INET;
|
||||
p->sin.sin_port = htobe16(port);
|
||||
p->sin.sin_addr.s_addr = node_id->addr;
|
||||
p->next = NULL;
|
||||
return p;
|
||||
|
||||
/*------------------------------------------------
|
||||
* 2) IPv6
|
||||
*-----------------------------------------------*/
|
||||
case OGS_PFCP_NODE_ID_IPV6:
|
||||
p = (ogs_sockaddr_t *)ogs_calloc(1, sizeof(*p));
|
||||
if (!p) {
|
||||
ogs_error("ogs_calloc() failed");
|
||||
return NULL;
|
||||
}
|
||||
p->sa.sa_family = AF_INET6;
|
||||
p->sin6.sin6_port = htobe16(port);
|
||||
/* Copy 16 bytes of IPv6 address */
|
||||
memcpy(&p->sin6.sin6_addr, node_id->addr6, 16);
|
||||
p->next = NULL;
|
||||
return OGS_OK;
|
||||
|
||||
/*------------------------------------------------
|
||||
* 3) FQDN
|
||||
*-----------------------------------------------*/
|
||||
case OGS_PFCP_NODE_ID_FQDN:
|
||||
/* If the FQDN is not empty, we attempt DNS resolution.
|
||||
* ogs_addaddrinfo() is a placeholder for your actual
|
||||
* DNS -> ogs_sockaddr_t function (often wraps getaddrinfo).
|
||||
*/
|
||||
/* Port=0 or set as needed, family=AF_UNSPEC, flags=0. */
|
||||
if (ogs_fqdn_parse(fqdn, node_id->fqdn, strlen(node_id->fqdn)) <= 0) {
|
||||
ogs_error("ogs_fqdn_parse() error [%s]", node_id->fqdn);
|
||||
return NULL;
|
||||
}
|
||||
ret = ogs_getaddrinfo(&p, AF_UNSPEC, fqdn, port, 0);
|
||||
if (ret != 0) {
|
||||
/* DNS resolution failed => *out remains NULL */
|
||||
ogs_error("ogs_addaddrinfo() failed");
|
||||
return NULL;
|
||||
}
|
||||
/* If FQDN is empty, just return with no addresses. */
|
||||
return p;
|
||||
|
||||
/*------------------------------------------------
|
||||
* 4) Unsupported type or default
|
||||
*-----------------------------------------------*/
|
||||
default:
|
||||
/* Optionally handle an error or just return success
|
||||
* with no addresses.
|
||||
*/
|
||||
ogs_error("Unknown type [%d]", node_id->type);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* Utility function to convert node_id to string for logging */
|
||||
const char *ogs_pfcp_node_id_to_string_static(
|
||||
const ogs_pfcp_node_id_t *node_id)
|
||||
{
|
||||
static char buffer[OGS_MAX_FQDN_LEN+1] = { 0, };
|
||||
|
||||
if (node_id) {
|
||||
switch (node_id->type) {
|
||||
case OGS_PFCP_NODE_ID_IPV4:
|
||||
inet_ntop(AF_INET, &node_id->addr, buffer, sizeof(buffer));
|
||||
break;
|
||||
case OGS_PFCP_NODE_ID_IPV6:
|
||||
inet_ntop(AF_INET6, node_id->addr6, buffer, sizeof(buffer));
|
||||
break;
|
||||
case OGS_PFCP_NODE_ID_FQDN:
|
||||
if (ogs_fqdn_parse(buffer,
|
||||
node_id->fqdn,
|
||||
strlen(node_id->fqdn)) <= 0)
|
||||
snprintf(buffer, sizeof(buffer), "%s", node_id->fqdn);
|
||||
break;
|
||||
default:
|
||||
snprintf(buffer, sizeof(buffer), "Unknown");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
@@ -29,26 +29,30 @@ extern "C" {
|
||||
#endif
|
||||
|
||||
typedef enum {
|
||||
/* Operation was successful */
|
||||
/* Success with actual Node ID */
|
||||
OGS_PFCP_STATUS_SUCCESS = 0,
|
||||
|
||||
/* The message type is unknown */
|
||||
OGS_PFCP_ERROR_UNKNOWN_MESSAGE,
|
||||
/* Success with no Node ID (NONE type) */
|
||||
OGS_PFCP_STATUS_NODE_ID_NONE,
|
||||
|
||||
/* The message is semantically incorrect */
|
||||
/* Success with OPTIONAL node_id_tlv, but presence=0 */
|
||||
OGS_PFCP_STATUS_NODE_ID_OPTIONAL_ABSENT,
|
||||
|
||||
/* Error codes */
|
||||
OGS_PFCP_ERROR_SEMANTIC_INCORRECT_MESSAGE,
|
||||
|
||||
/* The node ID is not present in the message */
|
||||
OGS_PFCP_ERROR_NODE_ID_NOT_PRESENT,
|
||||
|
||||
/* The node ID was not found in the expected location */
|
||||
OGS_PFCP_ERROR_NODE_ID_NOT_FOUND,
|
||||
OGS_PFCP_ERROR_UNKNOWN_MESSAGE
|
||||
|
||||
/* Add additional error codes as needed */
|
||||
} ogs_pfcp_status_e;
|
||||
|
||||
ogs_pfcp_status_e ogs_pfcp_get_node_id(
|
||||
ogs_pfcp_node_id_t *node_id, ogs_pfcp_message_t *message);
|
||||
ogs_pfcp_status_e
|
||||
ogs_pfcp_extract_node_id(ogs_pfcp_message_t *message,
|
||||
ogs_pfcp_node_id_t *node_id);
|
||||
|
||||
ogs_sockaddr_t *ogs_pfcp_node_id_to_addrinfo(const ogs_pfcp_node_id_t *node_id);
|
||||
const char *ogs_pfcp_node_id_to_string_static(
|
||||
const ogs_pfcp_node_id_t *node_id);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
113
lib/pfcp/xact.c
113
lib/pfcp/xact.c
@@ -70,7 +70,6 @@ void ogs_pfcp_xact_final(void)
|
||||
ogs_pfcp_xact_t *ogs_pfcp_xact_local_create(ogs_pfcp_node_t *node,
|
||||
void (*cb)(ogs_pfcp_xact_t *xact, void *data), void *data)
|
||||
{
|
||||
char buf[OGS_ADDRSTRLEN];
|
||||
ogs_pfcp_xact_t *xact = NULL;
|
||||
|
||||
ogs_assert(node);
|
||||
@@ -109,11 +108,10 @@ ogs_pfcp_xact_t *ogs_pfcp_xact_local_create(ogs_pfcp_node_t *node,
|
||||
|
||||
ogs_list_init(&xact->pdr_to_create_list);
|
||||
|
||||
ogs_debug("[%d] %s Create peer [%s]:%d",
|
||||
ogs_debug("[%d] %s Create peer %s",
|
||||
xact->xid,
|
||||
xact->org == OGS_PFCP_LOCAL_ORIGINATOR ? "LOCAL " : "REMOTE",
|
||||
OGS_ADDR(&node->addr, buf),
|
||||
OGS_PORT(&node->addr));
|
||||
ogs_sockaddr_to_string_static(node->addr_list));
|
||||
|
||||
return xact;
|
||||
}
|
||||
@@ -121,7 +119,6 @@ ogs_pfcp_xact_t *ogs_pfcp_xact_local_create(ogs_pfcp_node_t *node,
|
||||
static ogs_pfcp_xact_t *ogs_pfcp_xact_remote_create(
|
||||
ogs_pfcp_node_t *node, uint32_t sqn)
|
||||
{
|
||||
char buf[OGS_ADDRSTRLEN];
|
||||
ogs_pfcp_xact_t *xact = NULL;
|
||||
|
||||
ogs_assert(node);
|
||||
@@ -156,11 +153,10 @@ static ogs_pfcp_xact_t *ogs_pfcp_xact_remote_create(
|
||||
ogs_list_add(xact->org == OGS_PFCP_LOCAL_ORIGINATOR ?
|
||||
&xact->node->local_list : &xact->node->remote_list, xact);
|
||||
|
||||
ogs_debug("[%d] %s Create peer [%s]:%d",
|
||||
ogs_debug("[%d] %s Create peer %s",
|
||||
xact->xid,
|
||||
xact->org == OGS_PFCP_LOCAL_ORIGINATOR ? "LOCAL " : "REMOTE",
|
||||
OGS_ADDR(&node->addr, buf),
|
||||
OGS_PORT(&node->addr));
|
||||
ogs_sockaddr_to_string_static(node->addr_list));
|
||||
|
||||
return xact;
|
||||
}
|
||||
@@ -183,7 +179,6 @@ ogs_pfcp_xact_t *ogs_pfcp_xact_find_by_id(ogs_pool_id_t id)
|
||||
int ogs_pfcp_xact_update_tx(ogs_pfcp_xact_t *xact,
|
||||
ogs_pfcp_header_t *hdesc, ogs_pkbuf_t *pkbuf)
|
||||
{
|
||||
char buf[OGS_ADDRSTRLEN];
|
||||
ogs_pfcp_xact_stage_t stage;
|
||||
ogs_pfcp_header_t *h = NULL;
|
||||
int pfcp_hlen = 0;
|
||||
@@ -193,12 +188,11 @@ int ogs_pfcp_xact_update_tx(ogs_pfcp_xact_t *xact,
|
||||
ogs_assert(hdesc);
|
||||
ogs_assert(pkbuf);
|
||||
|
||||
ogs_debug("[%d] %s UPD TX-%d peer [%s]:%d",
|
||||
ogs_debug("[%d] %s UPD TX-%d peer %s",
|
||||
xact->xid,
|
||||
xact->org == OGS_PFCP_LOCAL_ORIGINATOR ? "LOCAL " : "REMOTE",
|
||||
hdesc->type,
|
||||
OGS_ADDR(&xact->node->addr, buf),
|
||||
OGS_PORT(&xact->node->addr));
|
||||
ogs_sockaddr_to_string_static(xact->node->addr_list));
|
||||
|
||||
stage = ogs_pfcp_xact_get_stage(hdesc->type, xact->xid);
|
||||
if (xact->org == OGS_PFCP_LOCAL_ORIGINATOR) {
|
||||
@@ -290,15 +284,13 @@ int ogs_pfcp_xact_update_tx(ogs_pfcp_xact_t *xact,
|
||||
|
||||
static int ogs_pfcp_xact_update_rx(ogs_pfcp_xact_t *xact, uint8_t type)
|
||||
{
|
||||
char buf[OGS_ADDRSTRLEN];
|
||||
ogs_pfcp_xact_stage_t stage;
|
||||
|
||||
ogs_debug("[%d] %s UPD RX-%d peer [%s]:%d",
|
||||
ogs_debug("[%d] %s UPD RX-%d peer %s",
|
||||
xact->xid,
|
||||
xact->org == OGS_PFCP_LOCAL_ORIGINATOR ? "LOCAL " : "REMOTE",
|
||||
type,
|
||||
OGS_ADDR(&xact->node->addr, buf),
|
||||
OGS_PORT(&xact->node->addr));
|
||||
ogs_sockaddr_to_string_static(xact->node->addr_list));
|
||||
|
||||
stage = ogs_pfcp_xact_get_stage(type, xact->xid);
|
||||
if (xact->org == OGS_PFCP_LOCAL_ORIGINATOR) {
|
||||
@@ -325,25 +317,23 @@ static int ogs_pfcp_xact_update_rx(ogs_pfcp_xact_t *xact, uint8_t type)
|
||||
pfcp.t1_holding_duration);
|
||||
|
||||
ogs_warn("[%d] %s Request Duplicated. Retransmit!"
|
||||
" for step %d type %d peer [%s]:%d",
|
||||
" for step %d type %d peer %s",
|
||||
xact->xid,
|
||||
xact->org == OGS_PFCP_LOCAL_ORIGINATOR ?
|
||||
"LOCAL " : "REMOTE",
|
||||
xact->step, type,
|
||||
OGS_ADDR(&xact->node->addr,
|
||||
buf),
|
||||
OGS_PORT(&xact->node->addr));
|
||||
ogs_sockaddr_to_string_static(
|
||||
xact->node->addr_list));
|
||||
ogs_expect(OGS_OK == ogs_pfcp_sendto(xact->node, pkbuf));
|
||||
} else {
|
||||
ogs_warn("[%d] %s Request Duplicated. Discard!"
|
||||
" for step %d type %d peer [%s]:%d",
|
||||
" for step %d type %d peer %s",
|
||||
xact->xid,
|
||||
xact->org == OGS_PFCP_LOCAL_ORIGINATOR ?
|
||||
"LOCAL " : "REMOTE",
|
||||
xact->step, type,
|
||||
OGS_ADDR(&xact->node->addr,
|
||||
buf),
|
||||
OGS_PORT(&xact->node->addr));
|
||||
ogs_sockaddr_to_string_static(
|
||||
xact->node->addr_list));
|
||||
}
|
||||
|
||||
return OGS_RETRY;
|
||||
@@ -391,25 +381,23 @@ static int ogs_pfcp_xact_update_rx(ogs_pfcp_xact_t *xact, uint8_t type)
|
||||
pfcp.t1_holding_duration);
|
||||
|
||||
ogs_warn("[%d] %s Request Duplicated. Retransmit!"
|
||||
" for step %d type %d peer [%s]:%d",
|
||||
" for step %d type %d peer %s",
|
||||
xact->xid,
|
||||
xact->org == OGS_PFCP_LOCAL_ORIGINATOR ?
|
||||
"LOCAL " : "REMOTE",
|
||||
xact->step, type,
|
||||
OGS_ADDR(&xact->node->addr,
|
||||
buf),
|
||||
OGS_PORT(&xact->node->addr));
|
||||
ogs_sockaddr_to_string_static(
|
||||
xact->node->addr_list));
|
||||
ogs_expect(OGS_OK == ogs_pfcp_sendto(xact->node, pkbuf));
|
||||
} else {
|
||||
ogs_warn("[%d] %s Request Duplicated. Discard!"
|
||||
" for step %d type %d peer [%s]:%d",
|
||||
" for step %d type %d peer %s",
|
||||
xact->xid,
|
||||
xact->org == OGS_PFCP_LOCAL_ORIGINATOR ?
|
||||
"LOCAL " : "REMOTE",
|
||||
xact->step, type,
|
||||
OGS_ADDR(&xact->node->addr,
|
||||
buf),
|
||||
OGS_PORT(&xact->node->addr));
|
||||
ogs_sockaddr_to_string_static(
|
||||
xact->node->addr_list));
|
||||
}
|
||||
|
||||
return OGS_RETRY;
|
||||
@@ -462,8 +450,6 @@ static int ogs_pfcp_xact_update_rx(ogs_pfcp_xact_t *xact, uint8_t type)
|
||||
|
||||
int ogs_pfcp_xact_commit(ogs_pfcp_xact_t *xact)
|
||||
{
|
||||
char buf[OGS_ADDRSTRLEN];
|
||||
|
||||
uint8_t type;
|
||||
ogs_pkbuf_t *pkbuf = NULL;
|
||||
ogs_pfcp_xact_stage_t stage;
|
||||
@@ -471,11 +457,10 @@ int ogs_pfcp_xact_commit(ogs_pfcp_xact_t *xact)
|
||||
ogs_assert(xact);
|
||||
ogs_assert(xact->node);
|
||||
|
||||
ogs_debug("[%d] %s Commit peer [%s]:%d",
|
||||
ogs_debug("[%d] %s Commit peer %s",
|
||||
xact->xid,
|
||||
xact->org == OGS_PFCP_LOCAL_ORIGINATOR ? "LOCAL " : "REMOTE",
|
||||
OGS_ADDR(&xact->node->addr, buf),
|
||||
OGS_PORT(&xact->node->addr));
|
||||
ogs_sockaddr_to_string_static(xact->node->addr_list));
|
||||
|
||||
type = xact->seq[xact->step-1].type;
|
||||
stage = ogs_pfcp_xact_get_stage(type, xact->xid);
|
||||
@@ -581,7 +566,6 @@ void ogs_pfcp_xact_delayed_commit(ogs_pfcp_xact_t *xact, ogs_time_t duration)
|
||||
|
||||
static void response_timeout(void *data)
|
||||
{
|
||||
char buf[OGS_ADDRSTRLEN];
|
||||
ogs_pool_id_t xact_id = OGS_INVALID_POOL_ID;
|
||||
ogs_pfcp_xact_t *xact = NULL;
|
||||
|
||||
@@ -597,12 +581,11 @@ static void response_timeout(void *data)
|
||||
ogs_assert(xact->node);
|
||||
|
||||
ogs_debug("[%d] %s Response Timeout "
|
||||
"for step %d type %d peer [%s]:%d",
|
||||
"for step %d type %d peer %s",
|
||||
xact->xid,
|
||||
xact->org == OGS_PFCP_LOCAL_ORIGINATOR ? "LOCAL " : "REMOTE",
|
||||
xact->step, xact->seq[xact->step-1].type,
|
||||
OGS_ADDR(&xact->node->addr, buf),
|
||||
OGS_PORT(&xact->node->addr));
|
||||
ogs_sockaddr_to_string_static(xact->node->addr_list));
|
||||
|
||||
if (--xact->response_rcount > 0) {
|
||||
ogs_pkbuf_t *pkbuf = NULL;
|
||||
@@ -617,12 +600,11 @@ static void response_timeout(void *data)
|
||||
ogs_expect(OGS_OK == ogs_pfcp_sendto(xact->node, pkbuf));
|
||||
} else {
|
||||
ogs_warn("[%d] %s No Reponse. Give up! "
|
||||
"for step %d type %d peer [%s]:%d",
|
||||
"for step %d type %d peer %s",
|
||||
xact->xid,
|
||||
xact->org == OGS_PFCP_LOCAL_ORIGINATOR ? "LOCAL " : "REMOTE",
|
||||
xact->step, xact->seq[xact->step-1].type,
|
||||
OGS_ADDR(&xact->node->addr, buf),
|
||||
OGS_PORT(&xact->node->addr));
|
||||
ogs_sockaddr_to_string_static(xact->node->addr_list));
|
||||
|
||||
if (xact->cb)
|
||||
xact->cb(xact, xact->data);
|
||||
@@ -633,7 +615,6 @@ static void response_timeout(void *data)
|
||||
|
||||
static void holding_timeout(void *data)
|
||||
{
|
||||
char buf[OGS_ADDRSTRLEN];
|
||||
ogs_pool_id_t xact_id = OGS_INVALID_POOL_ID;
|
||||
ogs_pfcp_xact_t *xact = NULL;
|
||||
|
||||
@@ -649,12 +630,11 @@ static void holding_timeout(void *data)
|
||||
ogs_assert(xact->node);
|
||||
|
||||
ogs_debug("[%d] %s Holding Timeout "
|
||||
"for step %d type %d peer [%s]:%d",
|
||||
"for step %d type %d peer %s",
|
||||
xact->xid,
|
||||
xact->org == OGS_PFCP_LOCAL_ORIGINATOR ? "LOCAL " : "REMOTE",
|
||||
xact->step, xact->seq[xact->step-1].type,
|
||||
OGS_ADDR(&xact->node->addr, buf),
|
||||
OGS_PORT(&xact->node->addr));
|
||||
ogs_sockaddr_to_string_static(xact->node->addr_list));
|
||||
|
||||
if (--xact->holding_rcount > 0) {
|
||||
if (xact->tm_holding)
|
||||
@@ -662,19 +642,17 @@ static void holding_timeout(void *data)
|
||||
ogs_local_conf()->time.message.pfcp.t1_holding_duration);
|
||||
} else {
|
||||
ogs_debug("[%d] %s Delete Transaction "
|
||||
"for step %d type %d peer [%s]:%d",
|
||||
"for step %d type %d peer %s",
|
||||
xact->xid,
|
||||
xact->org == OGS_PFCP_LOCAL_ORIGINATOR ? "LOCAL " : "REMOTE",
|
||||
xact->step, xact->seq[xact->step-1].type,
|
||||
OGS_ADDR(&xact->node->addr, buf),
|
||||
OGS_PORT(&xact->node->addr));
|
||||
ogs_sockaddr_to_string_static(xact->node->addr_list));
|
||||
ogs_pfcp_xact_delete(xact);
|
||||
}
|
||||
}
|
||||
|
||||
static void delayed_commit_timeout(void *data)
|
||||
{
|
||||
char buf[OGS_ADDRSTRLEN];
|
||||
ogs_pool_id_t xact_id = OGS_INVALID_POOL_ID;
|
||||
ogs_pfcp_xact_t *xact = NULL;
|
||||
|
||||
@@ -690,12 +668,11 @@ static void delayed_commit_timeout(void *data)
|
||||
ogs_assert(xact->node);
|
||||
|
||||
ogs_debug("[%d] %s Delayed Send Timeout "
|
||||
"for step %d type %d peer [%s]:%d",
|
||||
"for step %d type %d peer %s",
|
||||
xact->xid,
|
||||
xact->org == OGS_PFCP_LOCAL_ORIGINATOR ? "LOCAL " : "REMOTE",
|
||||
xact->step, xact->seq[xact->step-1].type,
|
||||
OGS_ADDR(&xact->node->addr, buf),
|
||||
OGS_PORT(&xact->node->addr));
|
||||
ogs_sockaddr_to_string_static(xact->node->addr_list));
|
||||
|
||||
ogs_pfcp_xact_commit(xact);
|
||||
}
|
||||
@@ -704,7 +681,6 @@ int ogs_pfcp_xact_receive(
|
||||
ogs_pfcp_node_t *node, ogs_pfcp_header_t *h, ogs_pfcp_xact_t **xact)
|
||||
{
|
||||
int rv;
|
||||
char buf[OGS_ADDRSTRLEN];
|
||||
|
||||
uint8_t type;
|
||||
uint32_t sqn, xid;
|
||||
@@ -731,35 +707,33 @@ int ogs_pfcp_xact_receive(
|
||||
list = &node->local_list;
|
||||
break;
|
||||
default:
|
||||
ogs_error("[%d] Unexpected type %u from PFCP peer [%s]:%d",
|
||||
xid, type, OGS_ADDR(&node->addr, buf), OGS_PORT(&node->addr));
|
||||
ogs_error("[%d] Unexpected type %u from PFCP peer %s",
|
||||
xid, type, ogs_sockaddr_to_string_static(node->addr_list));
|
||||
return OGS_ERROR;
|
||||
}
|
||||
|
||||
ogs_assert(list);
|
||||
ogs_list_for_each(list, new) {
|
||||
if (new->xid == xid) {
|
||||
ogs_debug("[%d] %s Find peer [%s]:%d",
|
||||
ogs_debug("[%d] %s Find peer %s",
|
||||
new->xid,
|
||||
new->org == OGS_PFCP_LOCAL_ORIGINATOR ? "LOCAL " : "REMOTE",
|
||||
OGS_ADDR(&node->addr, buf),
|
||||
OGS_PORT(&node->addr));
|
||||
ogs_sockaddr_to_string_static(node->addr_list));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!new) {
|
||||
ogs_debug("[%d] Cannot find new type %u from PFCP peer [%s]:%d",
|
||||
xid, type, OGS_ADDR(&node->addr, buf), OGS_PORT(&node->addr));
|
||||
ogs_debug("[%d] Cannot find new type %u from PFCP peer %s",
|
||||
xid, type, ogs_sockaddr_to_string_static(node->addr_list));
|
||||
new = ogs_pfcp_xact_remote_create(node, sqn);
|
||||
}
|
||||
ogs_assert(new);
|
||||
|
||||
ogs_debug("[%d] %s Receive peer [%s]:%d",
|
||||
ogs_debug("[%d] %s Receive peer %s",
|
||||
new->xid,
|
||||
new->org == OGS_PFCP_LOCAL_ORIGINATOR ? "LOCAL " : "REMOTE",
|
||||
OGS_ADDR(&node->addr, buf),
|
||||
OGS_PORT(&node->addr));
|
||||
ogs_sockaddr_to_string_static(node->addr_list));
|
||||
|
||||
rv = ogs_pfcp_xact_update_rx(new, type);
|
||||
if (rv == OGS_ERROR) {
|
||||
@@ -811,16 +785,13 @@ static ogs_pfcp_xact_stage_t ogs_pfcp_xact_get_stage(uint8_t type, uint32_t xid)
|
||||
|
||||
int ogs_pfcp_xact_delete(ogs_pfcp_xact_t *xact)
|
||||
{
|
||||
char buf[OGS_ADDRSTRLEN];
|
||||
|
||||
ogs_assert(xact);
|
||||
ogs_assert(xact->node);
|
||||
|
||||
ogs_debug("[%d] %s Delete peer [%s]:%d",
|
||||
ogs_debug("[%d] %s Delete peer %s",
|
||||
xact->xid,
|
||||
xact->org == OGS_PFCP_LOCAL_ORIGINATOR ? "LOCAL " : "REMOTE",
|
||||
OGS_ADDR(&xact->node->addr, buf),
|
||||
OGS_PORT(&xact->node->addr));
|
||||
ogs_sockaddr_to_string_static(xact->node->addr_list));
|
||||
|
||||
if (xact->seq[0].pkbuf)
|
||||
ogs_pkbuf_free(xact->seq[0].pkbuf);
|
||||
|
@@ -93,7 +93,6 @@ ogs_sock_t *ogs_sctp_server(
|
||||
int type, ogs_sockaddr_t *sa_list, ogs_sockopt_t *socket_option)
|
||||
{
|
||||
int rv;
|
||||
char *sa_list_str = NULL;
|
||||
char buf[OGS_ADDRSTRLEN];
|
||||
|
||||
ogs_sock_t *new = NULL;
|
||||
@@ -143,10 +142,8 @@ ogs_sock_t *ogs_sctp_server(
|
||||
}
|
||||
|
||||
if (addr == NULL) {
|
||||
sa_list_str = ogs_sockaddr_strdup(sa_list);
|
||||
ogs_error("sctp_server %s failed", sa_list_str);
|
||||
ogs_free(sa_list_str);
|
||||
|
||||
ogs_error("sctp_server %s failed",
|
||||
ogs_sockaddr_to_string_static(sa_list));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -164,7 +161,6 @@ ogs_sock_t *ogs_sctp_client(
|
||||
ogs_sockopt_t *socket_option)
|
||||
{
|
||||
int rv;
|
||||
char *sa_list_str = NULL;
|
||||
char buf[OGS_ADDRSTRLEN];
|
||||
|
||||
ogs_sock_t *new = NULL;
|
||||
@@ -214,10 +210,8 @@ ogs_sock_t *ogs_sctp_client(
|
||||
}
|
||||
|
||||
if (addr == NULL) {
|
||||
sa_list_str = ogs_sockaddr_strdup(sa_list);
|
||||
ogs_error("sctp_client %s failed", sa_list_str);
|
||||
ogs_free(sa_list_str);
|
||||
|
||||
ogs_error("sctp_client %s failed",
|
||||
ogs_sockaddr_to_string_static(sa_list));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -227,7 +221,6 @@ ogs_sock_t *ogs_sctp_client(
|
||||
int ogs_sctp_bind(ogs_sock_t *sock, ogs_sockaddr_t *sa_list)
|
||||
{
|
||||
struct socket *socket = (struct socket *)sock;
|
||||
char *sa_list_str = NULL;
|
||||
socklen_t addrlen;
|
||||
|
||||
ogs_assert(socket);
|
||||
@@ -237,16 +230,13 @@ int ogs_sctp_bind(ogs_sock_t *sock, ogs_sockaddr_t *sa_list)
|
||||
ogs_assert(addrlen);
|
||||
|
||||
if (usrsctp_bind(socket, &sa_list->sa, addrlen) != 0) {
|
||||
sa_list_str = ogs_sockaddr_strdup(sa_list);
|
||||
ogs_error("sctp_bind() %s failed", sa_list_str);
|
||||
ogs_free(sa_list_str);
|
||||
ogs_error("sctp_bind() %s failed",
|
||||
ogs_sockaddr_to_string_static(sa_list));
|
||||
|
||||
return OGS_ERROR;
|
||||
}
|
||||
|
||||
sa_list_str = ogs_sockaddr_strdup(sa_list);
|
||||
ogs_debug("sctp_bind() %s", sa_list_str);
|
||||
ogs_free(sa_list_str);
|
||||
ogs_debug("sctp_bind() %s", ogs_sockaddr_to_string_static(sa_list));
|
||||
|
||||
return OGS_OK;
|
||||
}
|
||||
@@ -254,7 +244,6 @@ int ogs_sctp_bind(ogs_sock_t *sock, ogs_sockaddr_t *sa_list)
|
||||
int ogs_sctp_connect(ogs_sock_t *sock, ogs_sockaddr_t *sa_list)
|
||||
{
|
||||
struct socket *socket = (struct socket *)sock;
|
||||
char *sa_list_str = NULL;
|
||||
socklen_t addrlen;
|
||||
|
||||
ogs_assert(socket);
|
||||
@@ -264,16 +253,11 @@ int ogs_sctp_connect(ogs_sock_t *sock, ogs_sockaddr_t *sa_list)
|
||||
ogs_assert(addrlen);
|
||||
|
||||
if (usrsctp_connect(socket, &sa_list->sa, addrlen) != 0) {
|
||||
sa_list_str = ogs_sockaddr_strdup(sa_list);
|
||||
ogs_error("sctp_connect() %s", sa_list_str);
|
||||
ogs_free(sa_list_str);
|
||||
|
||||
ogs_error("sctp_connect() %s", ogs_sockaddr_to_string_static(sa_list));
|
||||
return OGS_ERROR;
|
||||
}
|
||||
|
||||
sa_list_str = ogs_sockaddr_strdup(sa_list);
|
||||
ogs_debug("sctp_connect() %s", sa_list_str);
|
||||
ogs_free(sa_list_str);
|
||||
ogs_debug("sctp_connect() %s", ogs_sockaddr_to_string_static(sa_list));
|
||||
|
||||
return OGS_OK;
|
||||
}
|
||||
|
@@ -408,8 +408,6 @@ static ogs_pfcp_node_t *selected_sgwu_node(
|
||||
|
||||
void sgwc_sess_select_sgwu(sgwc_sess_t *sess)
|
||||
{
|
||||
char buf[OGS_ADDRSTRLEN];
|
||||
|
||||
ogs_assert(sess);
|
||||
|
||||
/*
|
||||
@@ -425,8 +423,9 @@ void sgwc_sess_select_sgwu(sgwc_sess_t *sess)
|
||||
selected_sgwu_node(ogs_pfcp_self()->pfcp_node, sess);
|
||||
ogs_assert(ogs_pfcp_self()->pfcp_node);
|
||||
OGS_SETUP_PFCP_NODE(sess, ogs_pfcp_self()->pfcp_node);
|
||||
ogs_debug("UE using SGW-U on IP[%s]",
|
||||
OGS_ADDR(&ogs_pfcp_self()->pfcp_node->addr, buf));
|
||||
ogs_debug("UE using SGW-U on IP %s",
|
||||
ogs_sockaddr_to_string_static(
|
||||
ogs_pfcp_self()->pfcp_node->addr_list));
|
||||
}
|
||||
|
||||
int sgwc_sess_remove(sgwc_sess_t *sess)
|
||||
@@ -761,14 +760,15 @@ sgwc_tunnel_t *sgwc_tunnel_add(
|
||||
else
|
||||
tunnel->local_teid = pdr->teid;
|
||||
} else {
|
||||
if (sess->pfcp_node->addr.ogs_sa_family == AF_INET)
|
||||
ogs_assert(sess->pfcp_node->addr_list);
|
||||
if (sess->pfcp_node->addr_list->ogs_sa_family == AF_INET)
|
||||
ogs_assert(OGS_OK ==
|
||||
ogs_copyaddrinfo(
|
||||
&tunnel->local_addr, &sess->pfcp_node->addr));
|
||||
else if (sess->pfcp_node->addr.ogs_sa_family == AF_INET6)
|
||||
&tunnel->local_addr, sess->pfcp_node->addr_list));
|
||||
else if (sess->pfcp_node->addr_list->ogs_sa_family == AF_INET6)
|
||||
ogs_assert(OGS_OK ==
|
||||
ogs_copyaddrinfo(
|
||||
&tunnel->local_addr6, &sess->pfcp_node->addr));
|
||||
&tunnel->local_addr6, sess->pfcp_node->addr_list));
|
||||
else
|
||||
ogs_assert_if_reached();
|
||||
|
||||
|
@@ -61,8 +61,12 @@ static void pfcp_recv_cb(short when, ogs_socket_t fd, void *data)
|
||||
ogs_pkbuf_t *pkbuf = NULL;
|
||||
ogs_sockaddr_t from;
|
||||
ogs_pfcp_node_t *node = NULL;
|
||||
ogs_pfcp_message_t *message = NULL;
|
||||
ogs_pfcp_header_t *h = NULL;
|
||||
|
||||
ogs_pfcp_status_e pfcp_status;;
|
||||
ogs_pfcp_node_id_t node_id;
|
||||
|
||||
ogs_assert(fd != INVALID_SOCKET);
|
||||
|
||||
pkbuf = ogs_pkbuf_alloc(NULL, OGS_MAX_SDU_LEN);
|
||||
@@ -102,28 +106,105 @@ static void pfcp_recv_cb(short when, ogs_socket_t fd, void *data)
|
||||
e = sgwc_event_new(SGWC_EVT_SXA_MESSAGE);
|
||||
ogs_assert(e);
|
||||
|
||||
node = ogs_pfcp_node_find(&ogs_pfcp_self()->pfcp_peer_list, &from);
|
||||
if (!node) {
|
||||
node = ogs_pfcp_node_add(&ogs_pfcp_self()->pfcp_peer_list, &from);
|
||||
if (!node) {
|
||||
ogs_error("No memory: ogs_pfcp_node_add() failed");
|
||||
ogs_pkbuf_free(e->pkbuf);
|
||||
sgwc_event_free(e);
|
||||
return;
|
||||
}
|
||||
|
||||
node->sock = data;
|
||||
pfcp_node_fsm_init(node, false);
|
||||
/*
|
||||
* Issue #1911
|
||||
*
|
||||
* Because ogs_pfcp_message_t is over 80kb in size,
|
||||
* it can cause stack overflow.
|
||||
* To avoid this, the pfcp_message structure uses heap memory.
|
||||
*/
|
||||
if ((message = ogs_pfcp_parse_msg(pkbuf)) == NULL) {
|
||||
ogs_error("ogs_pfcp_parse_msg() failed");
|
||||
ogs_pkbuf_free(pkbuf);
|
||||
sgwc_event_free(e);
|
||||
return;
|
||||
}
|
||||
|
||||
pfcp_status = ogs_pfcp_extract_node_id(message, &node_id);
|
||||
switch (pfcp_status) {
|
||||
case OGS_PFCP_STATUS_SUCCESS:
|
||||
case OGS_PFCP_STATUS_NODE_ID_NONE:
|
||||
case OGS_PFCP_STATUS_NODE_ID_OPTIONAL_ABSENT:
|
||||
ogs_debug("ogs_pfcp_extract_node_id() "
|
||||
"type [%d] pfcp_status [%d] node_id [%s] from %s",
|
||||
message->h.type, pfcp_status,
|
||||
pfcp_status == OGS_PFCP_STATUS_SUCCESS ?
|
||||
ogs_pfcp_node_id_to_string_static(&node_id) :
|
||||
"NULL",
|
||||
ogs_sockaddr_to_string_static(&from));
|
||||
break;
|
||||
|
||||
case OGS_PFCP_ERROR_SEMANTIC_INCORRECT_MESSAGE:
|
||||
case OGS_PFCP_ERROR_NODE_ID_NOT_PRESENT:
|
||||
case OGS_PFCP_ERROR_NODE_ID_NOT_FOUND:
|
||||
case OGS_PFCP_ERROR_UNKNOWN_MESSAGE:
|
||||
ogs_error("ogs_pfcp_extract_node_id() failed "
|
||||
"type [%d] pfcp_status [%d] from %s",
|
||||
message->h.type, pfcp_status,
|
||||
ogs_sockaddr_to_string_static(&from));
|
||||
goto cleanup;
|
||||
|
||||
default:
|
||||
ogs_error("Unexpected pfcp_status "
|
||||
"type [%d] pfcp_status [%d] from %s",
|
||||
message->h.type, pfcp_status,
|
||||
ogs_sockaddr_to_string_static(&from));
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
node = ogs_pfcp_node_find(&ogs_pfcp_self()->pfcp_peer_list,
|
||||
pfcp_status == OGS_PFCP_STATUS_SUCCESS ? &node_id : NULL, &from);
|
||||
if (!node) {
|
||||
if (message->h.type == OGS_PFCP_ASSOCIATION_SETUP_REQUEST_TYPE ||
|
||||
message->h.type == OGS_PFCP_ASSOCIATION_SETUP_RESPONSE_TYPE) {
|
||||
ogs_assert(pfcp_status == OGS_PFCP_STATUS_SUCCESS);
|
||||
node = ogs_pfcp_node_add(&ogs_pfcp_self()->pfcp_peer_list,
|
||||
&node_id, &from);
|
||||
if (!node) {
|
||||
ogs_error("No memory: ogs_pfcp_node_add() failed");
|
||||
goto cleanup;
|
||||
}
|
||||
ogs_debug("Added PFCP-Node: addr_list %s",
|
||||
ogs_sockaddr_to_string_static(node->addr_list));
|
||||
|
||||
pfcp_node_fsm_init(node, false);
|
||||
|
||||
} else {
|
||||
ogs_error("Cannot find PFCP-Node: type [%d] node_id %s from %s",
|
||||
message->h.type,
|
||||
pfcp_status == OGS_PFCP_STATUS_SUCCESS ?
|
||||
ogs_pfcp_node_id_to_string_static(&node_id) :
|
||||
"NULL",
|
||||
ogs_sockaddr_to_string_static(&from));
|
||||
goto cleanup;
|
||||
}
|
||||
} else {
|
||||
ogs_debug("Found PFCP-Node: addr_list %s",
|
||||
ogs_sockaddr_to_string_static(node->addr_list));
|
||||
ogs_expect(OGS_OK == ogs_pfcp_node_merge(
|
||||
node,
|
||||
pfcp_status == OGS_PFCP_STATUS_SUCCESS ? &node_id : NULL,
|
||||
&from));
|
||||
ogs_debug("Merged PFCP-Node: addr_list %s",
|
||||
ogs_sockaddr_to_string_static(node->addr_list));
|
||||
}
|
||||
|
||||
e->pfcp_node = node;
|
||||
e->pkbuf = pkbuf;
|
||||
e->pfcp_message = message;
|
||||
|
||||
rv = ogs_queue_push(ogs_app()->queue, e);
|
||||
if (rv != OGS_OK) {
|
||||
ogs_error("ogs_queue_push() failed:%d", (int)rv);
|
||||
ogs_pkbuf_free(e->pkbuf);
|
||||
sgwc_event_free(e);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
cleanup:
|
||||
ogs_pkbuf_free(pkbuf);
|
||||
ogs_pfcp_message_free(message);
|
||||
sgwc_event_free(e);
|
||||
}
|
||||
|
||||
int sgwc_pfcp_open(void)
|
||||
|
@@ -25,7 +25,6 @@ static void node_timeout(ogs_pfcp_xact_t *xact, void *data);
|
||||
|
||||
void sgwc_pfcp_state_initial(ogs_fsm_t *s, sgwc_event_t *e)
|
||||
{
|
||||
int rv;
|
||||
ogs_pfcp_node_t *node = NULL;
|
||||
|
||||
ogs_assert(s);
|
||||
@@ -36,10 +35,6 @@ void sgwc_pfcp_state_initial(ogs_fsm_t *s, sgwc_event_t *e)
|
||||
node = e->pfcp_node;
|
||||
ogs_assert(node);
|
||||
|
||||
rv = ogs_pfcp_connect(
|
||||
ogs_pfcp_self()->pfcp_sock, ogs_pfcp_self()->pfcp_sock6, node);
|
||||
ogs_assert(rv == OGS_OK);
|
||||
|
||||
node->t_no_heartbeat = ogs_timer_add(ogs_app()->timer_mgr,
|
||||
sgwc_timer_pfcp_no_heartbeat, node);
|
||||
ogs_assert(node->t_no_heartbeat);
|
||||
@@ -63,14 +58,10 @@ void sgwc_pfcp_state_final(ogs_fsm_t *s, sgwc_event_t *e)
|
||||
|
||||
void sgwc_pfcp_state_will_associate(ogs_fsm_t *s, sgwc_event_t *e)
|
||||
{
|
||||
char buf[OGS_ADDRSTRLEN];
|
||||
|
||||
ogs_pfcp_node_t *node = NULL;
|
||||
ogs_pfcp_xact_t *xact = NULL;
|
||||
ogs_pfcp_message_t *message = NULL;
|
||||
|
||||
ogs_sockaddr_t *addr = NULL;
|
||||
|
||||
ogs_assert(s);
|
||||
ogs_assert(e);
|
||||
|
||||
@@ -78,8 +69,6 @@ void sgwc_pfcp_state_will_associate(ogs_fsm_t *s, sgwc_event_t *e)
|
||||
|
||||
node = e->pfcp_node;
|
||||
ogs_assert(node);
|
||||
addr = node->sa_list;
|
||||
ogs_assert(addr);
|
||||
|
||||
switch (e->id) {
|
||||
case OGS_FSM_ENTRY_SIG:
|
||||
@@ -103,8 +92,8 @@ void sgwc_pfcp_state_will_associate(ogs_fsm_t *s, sgwc_event_t *e)
|
||||
node = e->pfcp_node;
|
||||
ogs_assert(node);
|
||||
|
||||
ogs_warn("Retry association with peer [%s]:%d failed",
|
||||
OGS_ADDR(addr, buf), OGS_PORT(addr));
|
||||
ogs_warn("Retry association with peer failed %s",
|
||||
ogs_sockaddr_to_string_static(node->addr_list));
|
||||
|
||||
ogs_assert(node->t_association);
|
||||
ogs_timer_start(node->t_association,
|
||||
@@ -159,13 +148,10 @@ void sgwc_pfcp_state_will_associate(ogs_fsm_t *s, sgwc_event_t *e)
|
||||
|
||||
void sgwc_pfcp_state_associated(ogs_fsm_t *s, sgwc_event_t *e)
|
||||
{
|
||||
char buf[OGS_ADDRSTRLEN];
|
||||
|
||||
ogs_pfcp_node_t *node = NULL;
|
||||
ogs_pfcp_xact_t *xact = NULL;
|
||||
ogs_pfcp_message_t *message = NULL;
|
||||
|
||||
ogs_sockaddr_t *addr = NULL;
|
||||
sgwc_sess_t *sess = NULL;
|
||||
|
||||
ogs_assert(s);
|
||||
@@ -175,14 +161,11 @@ void sgwc_pfcp_state_associated(ogs_fsm_t *s, sgwc_event_t *e)
|
||||
|
||||
node = e->pfcp_node;
|
||||
ogs_assert(node);
|
||||
addr = node->sa_list;
|
||||
ogs_assert(addr);
|
||||
|
||||
switch (e->id) {
|
||||
case OGS_FSM_ENTRY_SIG:
|
||||
ogs_info("PFCP associated [%s]:%d",
|
||||
OGS_ADDR(&node->addr, buf),
|
||||
OGS_PORT(&node->addr));
|
||||
ogs_info("PFCP associated %s",
|
||||
ogs_sockaddr_to_string_static(node->addr_list));
|
||||
ogs_timer_start(node->t_no_heartbeat,
|
||||
ogs_local_conf()->time.message.pfcp.no_heartbeat_duration);
|
||||
ogs_assert(OGS_OK ==
|
||||
@@ -195,9 +178,8 @@ void sgwc_pfcp_state_associated(ogs_fsm_t *s, sgwc_event_t *e)
|
||||
}
|
||||
break;
|
||||
case OGS_FSM_EXIT_SIG:
|
||||
ogs_info("PFCP de-associated [%s]:%d",
|
||||
OGS_ADDR(&node->addr, buf),
|
||||
OGS_PORT(&node->addr));
|
||||
ogs_info("PFCP de-associated %s",
|
||||
ogs_sockaddr_to_string_static(node->addr_list));
|
||||
ogs_timer_stop(node->t_no_heartbeat);
|
||||
break;
|
||||
case SGWC_EVT_SXA_MESSAGE:
|
||||
@@ -274,16 +256,14 @@ void sgwc_pfcp_state_associated(ogs_fsm_t *s, sgwc_event_t *e)
|
||||
}
|
||||
break;
|
||||
case OGS_PFCP_ASSOCIATION_SETUP_REQUEST_TYPE:
|
||||
ogs_warn("PFCP[REQ] has already been associated [%s]:%d",
|
||||
OGS_ADDR(&node->addr, buf),
|
||||
OGS_PORT(&node->addr));
|
||||
ogs_warn("PFCP[REQ] has already been associated %s",
|
||||
ogs_sockaddr_to_string_static(node->addr_list));
|
||||
ogs_pfcp_cp_handle_association_setup_request(node, xact,
|
||||
&message->pfcp_association_setup_request);
|
||||
break;
|
||||
case OGS_PFCP_ASSOCIATION_SETUP_RESPONSE_TYPE:
|
||||
ogs_warn("PFCP[RSP] has already been associated [%s]:%d",
|
||||
OGS_ADDR(&node->addr, buf),
|
||||
OGS_PORT(&node->addr));
|
||||
ogs_warn("PFCP[RSP] has already been associated %s",
|
||||
ogs_sockaddr_to_string_static(node->addr_list));
|
||||
ogs_pfcp_cp_handle_association_setup_response(node, xact,
|
||||
&message->pfcp_association_setup_response);
|
||||
break;
|
||||
@@ -359,8 +339,8 @@ void sgwc_pfcp_state_associated(ogs_fsm_t *s, sgwc_event_t *e)
|
||||
}
|
||||
break;
|
||||
case SGWC_EVT_SXA_NO_HEARTBEAT:
|
||||
ogs_warn("No Heartbeat from SGW-U [%s]:%d",
|
||||
OGS_ADDR(addr, buf), OGS_PORT(addr));
|
||||
ogs_warn("No Heartbeat from SGW-U %s",
|
||||
ogs_sockaddr_to_string_static(node->addr_list));
|
||||
OGS_FSM_TRAN(s, sgwc_pfcp_state_will_associate);
|
||||
break;
|
||||
default:
|
||||
|
@@ -89,23 +89,12 @@ void sgwc_state_operational(ogs_fsm_t *s, sgwc_event_t *e)
|
||||
ogs_assert(e);
|
||||
recvbuf = e->pkbuf;
|
||||
ogs_assert(recvbuf);
|
||||
pfcp_message = e->pfcp_message;
|
||||
ogs_assert(pfcp_message);
|
||||
pfcp_node = e->pfcp_node;
|
||||
ogs_assert(pfcp_node);
|
||||
ogs_assert(OGS_FSM_STATE(&pfcp_node->sm));
|
||||
|
||||
/*
|
||||
* Issue #1911
|
||||
*
|
||||
* Because ogs_pfcp_message_t is over 80kb in size,
|
||||
* it can cause stack overflow.
|
||||
* To avoid this, the pfcp_message structure uses heap memory.
|
||||
*/
|
||||
if ((pfcp_message = ogs_pfcp_parse_msg(recvbuf)) == NULL) {
|
||||
ogs_error("ogs_pfcp_parse_msg() failed");
|
||||
ogs_pkbuf_free(recvbuf);
|
||||
break;
|
||||
}
|
||||
|
||||
rv = ogs_pfcp_xact_receive(pfcp_node, &pfcp_message->h, &pfcp_xact);
|
||||
if (rv != OGS_OK) {
|
||||
ogs_pkbuf_free(recvbuf);
|
||||
@@ -113,7 +102,6 @@ void sgwc_state_operational(ogs_fsm_t *s, sgwc_event_t *e)
|
||||
break;
|
||||
}
|
||||
|
||||
e->pfcp_message = pfcp_message;
|
||||
e->pfcp_xact_id = pfcp_xact ? pfcp_xact->id : OGS_INVALID_POOL_ID;
|
||||
|
||||
e->gtp_message = NULL;
|
||||
|
@@ -61,8 +61,12 @@ static void pfcp_recv_cb(short when, ogs_socket_t fd, void *data)
|
||||
ogs_pkbuf_t *pkbuf = NULL;
|
||||
ogs_sockaddr_t from;
|
||||
ogs_pfcp_node_t *node = NULL;
|
||||
ogs_pfcp_message_t *message = NULL;
|
||||
ogs_pfcp_header_t *h = NULL;
|
||||
|
||||
ogs_pfcp_status_e pfcp_status;;
|
||||
ogs_pfcp_node_id_t node_id;
|
||||
|
||||
ogs_assert(fd != INVALID_SOCKET);
|
||||
|
||||
pkbuf = ogs_pkbuf_alloc(NULL, OGS_MAX_SDU_LEN);
|
||||
@@ -102,28 +106,105 @@ static void pfcp_recv_cb(short when, ogs_socket_t fd, void *data)
|
||||
e = sgwu_event_new(SGWU_EVT_SXA_MESSAGE);
|
||||
ogs_assert(e);
|
||||
|
||||
node = ogs_pfcp_node_find(&ogs_pfcp_self()->pfcp_peer_list, &from);
|
||||
if (!node) {
|
||||
node = ogs_pfcp_node_add(&ogs_pfcp_self()->pfcp_peer_list, &from);
|
||||
if (!node) {
|
||||
ogs_error("No memory: ogs_pfcp_node_add() failed");
|
||||
ogs_pkbuf_free(e->pkbuf);
|
||||
sgwu_event_free(e);
|
||||
return;
|
||||
}
|
||||
|
||||
node->sock = data;
|
||||
pfcp_node_fsm_init(node, false);
|
||||
/*
|
||||
* Issue #1911
|
||||
*
|
||||
* Because ogs_pfcp_message_t is over 80kb in size,
|
||||
* it can cause stack overflow.
|
||||
* To avoid this, the pfcp_message structure uses heap memory.
|
||||
*/
|
||||
if ((message = ogs_pfcp_parse_msg(pkbuf)) == NULL) {
|
||||
ogs_error("ogs_pfcp_parse_msg() failed");
|
||||
ogs_pkbuf_free(pkbuf);
|
||||
sgwu_event_free(e);
|
||||
return;
|
||||
}
|
||||
|
||||
pfcp_status = ogs_pfcp_extract_node_id(message, &node_id);
|
||||
switch (pfcp_status) {
|
||||
case OGS_PFCP_STATUS_SUCCESS:
|
||||
case OGS_PFCP_STATUS_NODE_ID_NONE:
|
||||
case OGS_PFCP_STATUS_NODE_ID_OPTIONAL_ABSENT:
|
||||
ogs_debug("ogs_pfcp_extract_node_id() "
|
||||
"type [%d] pfcp_status [%d] node_id [%s] from %s",
|
||||
message->h.type, pfcp_status,
|
||||
pfcp_status == OGS_PFCP_STATUS_SUCCESS ?
|
||||
ogs_pfcp_node_id_to_string_static(&node_id) :
|
||||
"NULL",
|
||||
ogs_sockaddr_to_string_static(&from));
|
||||
break;
|
||||
|
||||
case OGS_PFCP_ERROR_SEMANTIC_INCORRECT_MESSAGE:
|
||||
case OGS_PFCP_ERROR_NODE_ID_NOT_PRESENT:
|
||||
case OGS_PFCP_ERROR_NODE_ID_NOT_FOUND:
|
||||
case OGS_PFCP_ERROR_UNKNOWN_MESSAGE:
|
||||
ogs_error("ogs_pfcp_extract_node_id() failed "
|
||||
"type [%d] pfcp_status [%d] from %s",
|
||||
message->h.type, pfcp_status,
|
||||
ogs_sockaddr_to_string_static(&from));
|
||||
goto cleanup;
|
||||
|
||||
default:
|
||||
ogs_error("Unexpected pfcp_status "
|
||||
"type [%d] pfcp_status [%d] from %s",
|
||||
message->h.type, pfcp_status,
|
||||
ogs_sockaddr_to_string_static(&from));
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
node = ogs_pfcp_node_find(&ogs_pfcp_self()->pfcp_peer_list,
|
||||
pfcp_status == OGS_PFCP_STATUS_SUCCESS ? &node_id : NULL, &from);
|
||||
if (!node) {
|
||||
if (message->h.type == OGS_PFCP_ASSOCIATION_SETUP_REQUEST_TYPE ||
|
||||
message->h.type == OGS_PFCP_ASSOCIATION_SETUP_RESPONSE_TYPE) {
|
||||
ogs_assert(pfcp_status == OGS_PFCP_STATUS_SUCCESS);
|
||||
node = ogs_pfcp_node_add(&ogs_pfcp_self()->pfcp_peer_list,
|
||||
&node_id, &from);
|
||||
if (!node) {
|
||||
ogs_error("No memory: ogs_pfcp_node_add() failed");
|
||||
goto cleanup;
|
||||
}
|
||||
ogs_debug("Added PFCP-Node: addr_list %s",
|
||||
ogs_sockaddr_to_string_static(node->addr_list));
|
||||
|
||||
pfcp_node_fsm_init(node, false);
|
||||
|
||||
} else {
|
||||
ogs_error("Cannot find PFCP-Node: type [%d] node_id %s from %s",
|
||||
message->h.type,
|
||||
pfcp_status == OGS_PFCP_STATUS_SUCCESS ?
|
||||
ogs_pfcp_node_id_to_string_static(&node_id) :
|
||||
"NULL",
|
||||
ogs_sockaddr_to_string_static(&from));
|
||||
goto cleanup;
|
||||
}
|
||||
} else {
|
||||
ogs_debug("Found PFCP-Node: addr_list %s",
|
||||
ogs_sockaddr_to_string_static(node->addr_list));
|
||||
ogs_expect(OGS_OK == ogs_pfcp_node_merge(
|
||||
node,
|
||||
pfcp_status == OGS_PFCP_STATUS_SUCCESS ? &node_id : NULL,
|
||||
&from));
|
||||
ogs_debug("Merged PFCP-Node: addr_list %s",
|
||||
ogs_sockaddr_to_string_static(node->addr_list));
|
||||
}
|
||||
|
||||
e->pfcp_node = node;
|
||||
e->pkbuf = pkbuf;
|
||||
e->pfcp_message = message;
|
||||
|
||||
rv = ogs_queue_push(ogs_app()->queue, e);
|
||||
if (rv != OGS_OK) {
|
||||
ogs_error("ogs_queue_push() failed:%d", (int)rv);
|
||||
ogs_pkbuf_free(e->pkbuf);
|
||||
sgwu_event_free(e);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
cleanup:
|
||||
ogs_pkbuf_free(pkbuf);
|
||||
ogs_pfcp_message_free(message);
|
||||
sgwu_event_free(e);
|
||||
}
|
||||
|
||||
int sgwu_pfcp_open(void)
|
||||
|
@@ -25,7 +25,6 @@ static void node_timeout(ogs_pfcp_xact_t *xact, void *data);
|
||||
|
||||
void sgwu_pfcp_state_initial(ogs_fsm_t *s, sgwu_event_t *e)
|
||||
{
|
||||
int rv;
|
||||
ogs_pfcp_node_t *node = NULL;
|
||||
|
||||
ogs_assert(s);
|
||||
@@ -36,10 +35,6 @@ void sgwu_pfcp_state_initial(ogs_fsm_t *s, sgwu_event_t *e)
|
||||
node = e->pfcp_node;
|
||||
ogs_assert(node);
|
||||
|
||||
rv = ogs_pfcp_connect(
|
||||
ogs_pfcp_self()->pfcp_sock, ogs_pfcp_self()->pfcp_sock6, node);
|
||||
ogs_assert(rv == OGS_OK);
|
||||
|
||||
node->t_no_heartbeat = ogs_timer_add(ogs_app()->timer_mgr,
|
||||
sgwu_timer_no_heartbeat, node);
|
||||
ogs_assert(node->t_no_heartbeat);
|
||||
@@ -63,12 +58,9 @@ void sgwu_pfcp_state_final(ogs_fsm_t *s, sgwu_event_t *e)
|
||||
|
||||
void sgwu_pfcp_state_will_associate(ogs_fsm_t *s, sgwu_event_t *e)
|
||||
{
|
||||
char buf[OGS_ADDRSTRLEN];
|
||||
|
||||
ogs_pfcp_node_t *node = NULL;
|
||||
ogs_pfcp_xact_t *xact = NULL;
|
||||
ogs_pfcp_message_t *message = NULL;
|
||||
ogs_sockaddr_t *addr = NULL;
|
||||
ogs_assert(s);
|
||||
ogs_assert(e);
|
||||
|
||||
@@ -96,11 +88,8 @@ void sgwu_pfcp_state_will_associate(ogs_fsm_t *s, sgwu_event_t *e)
|
||||
case SGWU_EVT_SXA_TIMER:
|
||||
switch(e->timer_id) {
|
||||
case SGWU_TIMER_ASSOCIATION:
|
||||
addr = node->sa_list;
|
||||
ogs_assert(addr);
|
||||
|
||||
ogs_warn("Retry association with peer [%s]:%d failed",
|
||||
OGS_ADDR(addr, buf), OGS_PORT(addr));
|
||||
ogs_warn("Retry association with peer failed %s",
|
||||
ogs_sockaddr_to_string_static(node->addr_list));
|
||||
|
||||
ogs_assert(node->t_association);
|
||||
ogs_timer_start(node->t_association,
|
||||
@@ -155,13 +144,10 @@ void sgwu_pfcp_state_will_associate(ogs_fsm_t *s, sgwu_event_t *e)
|
||||
|
||||
void sgwu_pfcp_state_associated(ogs_fsm_t *s, sgwu_event_t *e)
|
||||
{
|
||||
char buf[OGS_ADDRSTRLEN];
|
||||
|
||||
ogs_pfcp_node_t *node = NULL;
|
||||
ogs_pfcp_xact_t *xact = NULL;
|
||||
ogs_pfcp_message_t *message = NULL;
|
||||
|
||||
ogs_sockaddr_t *addr = NULL;
|
||||
sgwu_sess_t *sess = NULL;
|
||||
|
||||
ogs_assert(s);
|
||||
@@ -171,14 +157,11 @@ void sgwu_pfcp_state_associated(ogs_fsm_t *s, sgwu_event_t *e)
|
||||
|
||||
node = e->pfcp_node;
|
||||
ogs_assert(node);
|
||||
addr = node->sa_list;
|
||||
ogs_assert(addr);
|
||||
|
||||
switch (e->id) {
|
||||
case OGS_FSM_ENTRY_SIG:
|
||||
ogs_info("PFCP associated [%s]:%d",
|
||||
OGS_ADDR(&node->addr, buf),
|
||||
OGS_PORT(&node->addr));
|
||||
ogs_info("PFCP associated %s",
|
||||
ogs_sockaddr_to_string_static(node->addr_list));
|
||||
ogs_timer_start(node->t_no_heartbeat,
|
||||
ogs_local_conf()->time.message.pfcp.no_heartbeat_duration);
|
||||
ogs_assert(OGS_OK ==
|
||||
@@ -191,9 +174,8 @@ void sgwu_pfcp_state_associated(ogs_fsm_t *s, sgwu_event_t *e)
|
||||
}
|
||||
break;
|
||||
case OGS_FSM_EXIT_SIG:
|
||||
ogs_info("PFCP de-associated [%s]:%d",
|
||||
OGS_ADDR(&node->addr, buf),
|
||||
OGS_PORT(&node->addr));
|
||||
ogs_info("PFCP de-associated %s",
|
||||
ogs_sockaddr_to_string_static(node->addr_list));
|
||||
ogs_timer_stop(node->t_no_heartbeat);
|
||||
break;
|
||||
case SGWU_EVT_SXA_MESSAGE:
|
||||
@@ -263,16 +245,14 @@ void sgwu_pfcp_state_associated(ogs_fsm_t *s, sgwu_event_t *e)
|
||||
}
|
||||
break;
|
||||
case OGS_PFCP_ASSOCIATION_SETUP_REQUEST_TYPE:
|
||||
ogs_warn("PFCP[REQ] has already been associated [%s]:%d",
|
||||
OGS_ADDR(&node->addr, buf),
|
||||
OGS_PORT(&node->addr));
|
||||
ogs_warn("PFCP[REQ] has already been associated %s",
|
||||
ogs_sockaddr_to_string_static(node->addr_list));
|
||||
ogs_pfcp_up_handle_association_setup_request(node, xact,
|
||||
&message->pfcp_association_setup_request);
|
||||
break;
|
||||
case OGS_PFCP_ASSOCIATION_SETUP_RESPONSE_TYPE:
|
||||
ogs_warn("PFCP[RSP] has already been associated [%s]:%d",
|
||||
OGS_ADDR(&node->addr, buf),
|
||||
OGS_PORT(&node->addr));
|
||||
ogs_warn("PFCP[RSP] has already been associated %s",
|
||||
ogs_sockaddr_to_string_static(node->addr_list));
|
||||
ogs_pfcp_up_handle_association_setup_response(node, xact,
|
||||
&message->pfcp_association_setup_response);
|
||||
break;
|
||||
@@ -318,8 +298,8 @@ void sgwu_pfcp_state_associated(ogs_fsm_t *s, sgwu_event_t *e)
|
||||
}
|
||||
break;
|
||||
case SGWU_EVT_SXA_NO_HEARTBEAT:
|
||||
ogs_warn("No Heartbeat from SGW-C [%s]:%d",
|
||||
OGS_ADDR(addr, buf), OGS_PORT(addr));
|
||||
ogs_warn("No Heartbeat from SGW-C %s",
|
||||
ogs_sockaddr_to_string_static(node->addr_list));
|
||||
OGS_FSM_TRAN(s, sgwu_pfcp_state_will_associate);
|
||||
break;
|
||||
default:
|
||||
|
@@ -58,21 +58,11 @@ void sgwu_state_operational(ogs_fsm_t *s, sgwu_event_t *e)
|
||||
ogs_assert(e);
|
||||
recvbuf = e->pkbuf;
|
||||
ogs_assert(recvbuf);
|
||||
pfcp_message = e->pfcp_message;
|
||||
ogs_assert(pfcp_message);
|
||||
node = e->pfcp_node;
|
||||
ogs_assert(node);
|
||||
|
||||
/*
|
||||
* Issue #1911
|
||||
*
|
||||
* Because ogs_pfcp_message_t is over 80kb in size,
|
||||
* it can cause stack overflow.
|
||||
* To avoid this, the pfcp_message structure uses heap memory.
|
||||
*/
|
||||
if ((pfcp_message = ogs_pfcp_parse_msg(recvbuf)) == NULL) {
|
||||
ogs_error("ogs_pfcp_parse_msg() failed");
|
||||
ogs_pkbuf_free(recvbuf);
|
||||
break;
|
||||
}
|
||||
ogs_assert(OGS_FSM_STATE(&node->sm));
|
||||
|
||||
rv = ogs_pfcp_xact_receive(node, &pfcp_message->h, &xact);
|
||||
if (rv != OGS_OK) {
|
||||
@@ -81,7 +71,6 @@ void sgwu_state_operational(ogs_fsm_t *s, sgwu_event_t *e)
|
||||
break;
|
||||
}
|
||||
|
||||
e->pfcp_message = pfcp_message;
|
||||
e->pfcp_xact_id = xact ? xact->id : OGS_INVALID_POOL_ID;
|
||||
ogs_fsm_dispatch(&node->sm, e);
|
||||
if (OGS_FSM_CHECK(&node->sm, sgwu_pfcp_state_exception)) {
|
||||
|
@@ -206,15 +206,17 @@ void smf_bearer_binding(smf_sess_t *sess)
|
||||
else
|
||||
bearer->pgw_s5u_teid = ul_pdr->teid;
|
||||
} else {
|
||||
if (sess->pfcp_node->addr.ogs_sa_family == AF_INET)
|
||||
ogs_assert(sess->pfcp_node->addr_list);
|
||||
if (sess->pfcp_node->addr_list->ogs_sa_family ==
|
||||
AF_INET)
|
||||
ogs_assert(OGS_OK ==
|
||||
ogs_copyaddrinfo(&bearer->pgw_s5u_addr,
|
||||
&sess->pfcp_node->addr));
|
||||
else if (sess->pfcp_node->addr.ogs_sa_family ==
|
||||
sess->pfcp_node->addr_list));
|
||||
else if (sess->pfcp_node->addr_list->ogs_sa_family ==
|
||||
AF_INET6)
|
||||
ogs_assert(OGS_OK ==
|
||||
ogs_copyaddrinfo(&bearer->pgw_s5u_addr6,
|
||||
&sess->pfcp_node->addr));
|
||||
sess->pfcp_node->addr_list));
|
||||
else
|
||||
ogs_assert_if_reached();
|
||||
|
||||
|
@@ -1184,8 +1184,6 @@ static ogs_pfcp_node_t *selected_upf_node(
|
||||
|
||||
void smf_sess_select_upf(smf_sess_t *sess)
|
||||
{
|
||||
char buf[OGS_ADDRSTRLEN];
|
||||
|
||||
ogs_assert(sess);
|
||||
|
||||
/*
|
||||
@@ -1201,8 +1199,9 @@ void smf_sess_select_upf(smf_sess_t *sess)
|
||||
selected_upf_node(ogs_pfcp_self()->pfcp_node, sess);
|
||||
ogs_assert(ogs_pfcp_self()->pfcp_node);
|
||||
OGS_SETUP_PFCP_NODE(sess, ogs_pfcp_self()->pfcp_node);
|
||||
ogs_debug("UE using UPF on IP[%s]",
|
||||
OGS_ADDR(&ogs_pfcp_self()->pfcp_node->addr, buf));
|
||||
ogs_debug("UE using UPF on IP %s",
|
||||
ogs_sockaddr_to_string_static(
|
||||
ogs_pfcp_self()->pfcp_node->addr_list));
|
||||
}
|
||||
|
||||
smf_sess_t *smf_sess_add_by_apn(smf_ue_t *smf_ue, char *apn, uint8_t rat_type)
|
||||
@@ -2186,14 +2185,16 @@ void smf_sess_create_indirect_data_forwarding(smf_sess_t *sess)
|
||||
else
|
||||
sess->handover.upf_dl_teid = pdr->teid;
|
||||
} else {
|
||||
if (sess->pfcp_node->addr.ogs_sa_family == AF_INET)
|
||||
ogs_assert(sess->pfcp_node->addr_list);
|
||||
if (sess->pfcp_node->addr_list->ogs_sa_family == AF_INET)
|
||||
ogs_assert(OGS_OK == ogs_copyaddrinfo(
|
||||
&sess->handover.upf_dl_addr,
|
||||
&sess->pfcp_node->addr));
|
||||
else if (sess->pfcp_node->addr.ogs_sa_family == AF_INET6)
|
||||
sess->pfcp_node->addr_list));
|
||||
else if (sess->pfcp_node->addr_list->ogs_sa_family ==
|
||||
AF_INET6)
|
||||
ogs_assert(OGS_OK == ogs_copyaddrinfo(
|
||||
&sess->handover.upf_dl_addr6,
|
||||
&sess->pfcp_node->addr));
|
||||
sess->pfcp_node->addr_list));
|
||||
else
|
||||
ogs_assert_if_reached();
|
||||
|
||||
|
@@ -210,14 +210,15 @@ uint32_t smf_gx_handle_cca_initial_request(
|
||||
else
|
||||
bearer->pgw_s5u_teid = ul_pdr->teid;
|
||||
} else {
|
||||
if (sess->pfcp_node->addr.ogs_sa_family == AF_INET)
|
||||
ogs_assert(sess->pfcp_node->addr_list);
|
||||
if (sess->pfcp_node->addr_list->ogs_sa_family == AF_INET)
|
||||
ogs_assert(OGS_OK ==
|
||||
ogs_copyaddrinfo(
|
||||
&bearer->pgw_s5u_addr, &sess->pfcp_node->addr));
|
||||
else if (sess->pfcp_node->addr.ogs_sa_family == AF_INET6)
|
||||
&bearer->pgw_s5u_addr, sess->pfcp_node->addr_list));
|
||||
else if (sess->pfcp_node->addr_list->ogs_sa_family == AF_INET6)
|
||||
ogs_assert(OGS_OK ==
|
||||
ogs_copyaddrinfo(
|
||||
&bearer->pgw_s5u_addr6, &sess->pfcp_node->addr));
|
||||
&bearer->pgw_s5u_addr6, sess->pfcp_node->addr_list));
|
||||
else
|
||||
ogs_assert_if_reached();
|
||||
|
||||
|
@@ -645,14 +645,15 @@ bool smf_npcf_smpolicycontrol_handle_create(
|
||||
else
|
||||
sess->upf_n3_teid = ul_pdr->teid;
|
||||
} else {
|
||||
if (sess->pfcp_node->addr.ogs_sa_family == AF_INET)
|
||||
ogs_assert(sess->pfcp_node->addr_list);
|
||||
if (sess->pfcp_node->addr_list->ogs_sa_family == AF_INET)
|
||||
ogs_assert(OGS_OK ==
|
||||
ogs_copyaddrinfo(
|
||||
&sess->upf_n3_addr, &sess->pfcp_node->addr));
|
||||
else if (sess->pfcp_node->addr.ogs_sa_family == AF_INET6)
|
||||
&sess->upf_n3_addr, sess->pfcp_node->addr_list));
|
||||
else if (sess->pfcp_node->addr_list->ogs_sa_family == AF_INET6)
|
||||
ogs_assert(OGS_OK ==
|
||||
ogs_copyaddrinfo(
|
||||
&sess->upf_n3_addr6, &sess->pfcp_node->addr));
|
||||
&sess->upf_n3_addr6, sess->pfcp_node->addr_list));
|
||||
else
|
||||
ogs_assert_if_reached();
|
||||
|
||||
|
@@ -101,8 +101,12 @@ static void pfcp_recv_cb(short when, ogs_socket_t fd, void *data)
|
||||
ogs_pkbuf_t *pkbuf = NULL;
|
||||
ogs_sockaddr_t from;
|
||||
ogs_pfcp_node_t *node = NULL;
|
||||
ogs_pfcp_message_t *message = NULL;
|
||||
ogs_pfcp_header_t *h = NULL;
|
||||
|
||||
ogs_pfcp_status_e pfcp_status;;
|
||||
ogs_pfcp_node_id_t node_id;
|
||||
|
||||
ogs_assert(fd != INVALID_SOCKET);
|
||||
|
||||
pkbuf = ogs_pkbuf_alloc(NULL, OGS_MAX_SDU_LEN);
|
||||
@@ -142,28 +146,105 @@ static void pfcp_recv_cb(short when, ogs_socket_t fd, void *data)
|
||||
e = smf_event_new(SMF_EVT_N4_MESSAGE);
|
||||
ogs_assert(e);
|
||||
|
||||
node = ogs_pfcp_node_find(&ogs_pfcp_self()->pfcp_peer_list, &from);
|
||||
if (!node) {
|
||||
node = ogs_pfcp_node_add(&ogs_pfcp_self()->pfcp_peer_list, &from);
|
||||
if (!node) {
|
||||
ogs_error("No memory: ogs_pfcp_node_add() failed");
|
||||
ogs_pkbuf_free(e->pkbuf);
|
||||
ogs_event_free(e);
|
||||
return;
|
||||
}
|
||||
|
||||
node->sock = data;
|
||||
pfcp_node_fsm_init(node, false);
|
||||
/*
|
||||
* Issue #1911
|
||||
*
|
||||
* Because ogs_pfcp_message_t is over 80kb in size,
|
||||
* it can cause stack overflow.
|
||||
* To avoid this, the pfcp_message structure uses heap memory.
|
||||
*/
|
||||
if ((message = ogs_pfcp_parse_msg(pkbuf)) == NULL) {
|
||||
ogs_error("ogs_pfcp_parse_msg() failed");
|
||||
ogs_pkbuf_free(pkbuf);
|
||||
ogs_event_free(e);
|
||||
return;
|
||||
}
|
||||
|
||||
pfcp_status = ogs_pfcp_extract_node_id(message, &node_id);
|
||||
switch (pfcp_status) {
|
||||
case OGS_PFCP_STATUS_SUCCESS:
|
||||
case OGS_PFCP_STATUS_NODE_ID_NONE:
|
||||
case OGS_PFCP_STATUS_NODE_ID_OPTIONAL_ABSENT:
|
||||
ogs_debug("ogs_pfcp_extract_node_id() "
|
||||
"type [%d] pfcp_status [%d] node_id [%s] from %s",
|
||||
message->h.type, pfcp_status,
|
||||
pfcp_status == OGS_PFCP_STATUS_SUCCESS ?
|
||||
ogs_pfcp_node_id_to_string_static(&node_id) :
|
||||
"NULL",
|
||||
ogs_sockaddr_to_string_static(&from));
|
||||
break;
|
||||
|
||||
case OGS_PFCP_ERROR_SEMANTIC_INCORRECT_MESSAGE:
|
||||
case OGS_PFCP_ERROR_NODE_ID_NOT_PRESENT:
|
||||
case OGS_PFCP_ERROR_NODE_ID_NOT_FOUND:
|
||||
case OGS_PFCP_ERROR_UNKNOWN_MESSAGE:
|
||||
ogs_error("ogs_pfcp_extract_node_id() failed "
|
||||
"type [%d] pfcp_status [%d] from %s",
|
||||
message->h.type, pfcp_status,
|
||||
ogs_sockaddr_to_string_static(&from));
|
||||
goto cleanup;
|
||||
|
||||
default:
|
||||
ogs_error("Unexpected pfcp_status "
|
||||
"type [%d] pfcp_status [%d] from %s",
|
||||
message->h.type, pfcp_status,
|
||||
ogs_sockaddr_to_string_static(&from));
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
node = ogs_pfcp_node_find(&ogs_pfcp_self()->pfcp_peer_list,
|
||||
pfcp_status == OGS_PFCP_STATUS_SUCCESS ? &node_id : NULL, &from);
|
||||
if (!node) {
|
||||
if (message->h.type == OGS_PFCP_ASSOCIATION_SETUP_REQUEST_TYPE ||
|
||||
message->h.type == OGS_PFCP_ASSOCIATION_SETUP_RESPONSE_TYPE) {
|
||||
ogs_assert(pfcp_status == OGS_PFCP_STATUS_SUCCESS);
|
||||
node = ogs_pfcp_node_add(&ogs_pfcp_self()->pfcp_peer_list,
|
||||
&node_id, &from);
|
||||
if (!node) {
|
||||
ogs_error("No memory: ogs_pfcp_node_add() failed");
|
||||
goto cleanup;
|
||||
}
|
||||
ogs_debug("Added PFCP-Node: addr_list %s",
|
||||
ogs_sockaddr_to_string_static(node->addr_list));
|
||||
|
||||
pfcp_node_fsm_init(node, false);
|
||||
|
||||
} else {
|
||||
ogs_error("Cannot find PFCP-Node: type [%d] node_id %s from %s",
|
||||
message->h.type,
|
||||
pfcp_status == OGS_PFCP_STATUS_SUCCESS ?
|
||||
ogs_pfcp_node_id_to_string_static(&node_id) :
|
||||
"NULL",
|
||||
ogs_sockaddr_to_string_static(&from));
|
||||
goto cleanup;
|
||||
}
|
||||
} else {
|
||||
ogs_debug("Found PFCP-Node: addr_list %s",
|
||||
ogs_sockaddr_to_string_static(node->addr_list));
|
||||
ogs_expect(OGS_OK == ogs_pfcp_node_merge(
|
||||
node,
|
||||
pfcp_status == OGS_PFCP_STATUS_SUCCESS ? &node_id : NULL,
|
||||
&from));
|
||||
ogs_debug("Merged PFCP-Node: addr_list %s",
|
||||
ogs_sockaddr_to_string_static(node->addr_list));
|
||||
}
|
||||
|
||||
e->pfcp_node = node;
|
||||
e->pkbuf = pkbuf;
|
||||
e->pfcp_message = message;
|
||||
|
||||
rv = ogs_queue_push(ogs_app()->queue, e);
|
||||
if (rv != OGS_OK) {
|
||||
ogs_error("ogs_queue_push() failed:%d", (int)rv);
|
||||
ogs_pkbuf_free(e->pkbuf);
|
||||
ogs_event_free(e);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
cleanup:
|
||||
ogs_pkbuf_free(pkbuf);
|
||||
ogs_pfcp_message_free(message);
|
||||
ogs_event_free(e);
|
||||
}
|
||||
|
||||
int smf_pfcp_open(void)
|
||||
|
@@ -28,7 +28,6 @@ static void node_timeout(ogs_pfcp_xact_t *xact, void *data);
|
||||
|
||||
void smf_pfcp_state_initial(ogs_fsm_t *s, smf_event_t *e)
|
||||
{
|
||||
int rv;
|
||||
ogs_pfcp_node_t *node = NULL;
|
||||
|
||||
ogs_assert(s);
|
||||
@@ -39,10 +38,6 @@ void smf_pfcp_state_initial(ogs_fsm_t *s, smf_event_t *e)
|
||||
node = e->pfcp_node;
|
||||
ogs_assert(node);
|
||||
|
||||
rv = ogs_pfcp_connect(
|
||||
ogs_pfcp_self()->pfcp_sock, ogs_pfcp_self()->pfcp_sock6, node);
|
||||
ogs_assert(rv == OGS_OK);
|
||||
|
||||
node->t_no_heartbeat = ogs_timer_add(ogs_app()->timer_mgr,
|
||||
smf_timer_pfcp_no_heartbeat, node);
|
||||
ogs_assert(node->t_no_heartbeat);
|
||||
@@ -66,13 +61,10 @@ void smf_pfcp_state_final(ogs_fsm_t *s, smf_event_t *e)
|
||||
|
||||
void smf_pfcp_state_will_associate(ogs_fsm_t *s, smf_event_t *e)
|
||||
{
|
||||
char buf[OGS_ADDRSTRLEN];
|
||||
|
||||
ogs_pfcp_node_t *node = NULL;
|
||||
ogs_pfcp_xact_t *xact = NULL;
|
||||
ogs_pfcp_message_t *message = NULL;
|
||||
|
||||
ogs_sockaddr_t *addr = NULL;
|
||||
smf_sess_t *sess;
|
||||
|
||||
ogs_assert(s);
|
||||
@@ -82,8 +74,6 @@ void smf_pfcp_state_will_associate(ogs_fsm_t *s, smf_event_t *e)
|
||||
|
||||
node = e->pfcp_node;
|
||||
ogs_assert(node);
|
||||
addr = node->sa_list;
|
||||
ogs_assert(addr);
|
||||
|
||||
switch (e->h.id) {
|
||||
case OGS_FSM_ENTRY_SIG:
|
||||
@@ -107,8 +97,8 @@ void smf_pfcp_state_will_associate(ogs_fsm_t *s, smf_event_t *e)
|
||||
node = e->pfcp_node;
|
||||
ogs_assert(node);
|
||||
|
||||
ogs_warn("Retry association with peer [%s]:%d failed",
|
||||
OGS_ADDR(addr, buf), OGS_PORT(addr));
|
||||
ogs_warn("Retry association with peer failed %s",
|
||||
ogs_sockaddr_to_string_static(node->addr_list));
|
||||
|
||||
ogs_assert(node->t_association);
|
||||
ogs_timer_start(node->t_association,
|
||||
@@ -179,13 +169,10 @@ void smf_pfcp_state_will_associate(ogs_fsm_t *s, smf_event_t *e)
|
||||
|
||||
void smf_pfcp_state_associated(ogs_fsm_t *s, smf_event_t *e)
|
||||
{
|
||||
char buf[OGS_ADDRSTRLEN];
|
||||
|
||||
ogs_pfcp_node_t *node = NULL;
|
||||
ogs_pfcp_xact_t *xact = NULL;
|
||||
ogs_pfcp_message_t *message = NULL;
|
||||
|
||||
ogs_sockaddr_t *addr = NULL;
|
||||
smf_sess_t *sess = NULL;
|
||||
|
||||
ogs_assert(s);
|
||||
@@ -195,14 +182,11 @@ void smf_pfcp_state_associated(ogs_fsm_t *s, smf_event_t *e)
|
||||
|
||||
node = e->pfcp_node;
|
||||
ogs_assert(node);
|
||||
addr = node->sa_list;
|
||||
ogs_assert(addr);
|
||||
|
||||
switch (e->h.id) {
|
||||
case OGS_FSM_ENTRY_SIG:
|
||||
ogs_info("PFCP associated [%s]:%d",
|
||||
OGS_ADDR(&node->addr, buf),
|
||||
OGS_PORT(&node->addr));
|
||||
ogs_info("PFCP associated %s",
|
||||
ogs_sockaddr_to_string_static(node->addr_list));
|
||||
ogs_timer_start(node->t_no_heartbeat,
|
||||
ogs_local_conf()->time.message.pfcp.no_heartbeat_duration);
|
||||
ogs_assert(OGS_OK ==
|
||||
@@ -215,9 +199,8 @@ void smf_pfcp_state_associated(ogs_fsm_t *s, smf_event_t *e)
|
||||
}
|
||||
break;
|
||||
case OGS_FSM_EXIT_SIG:
|
||||
ogs_info("PFCP de-associated [%s]:%d",
|
||||
OGS_ADDR(&node->addr, buf),
|
||||
OGS_PORT(&node->addr));
|
||||
ogs_info("PFCP de-associated %s",
|
||||
ogs_sockaddr_to_string_static(node->addr_list));
|
||||
ogs_timer_stop(node->t_no_heartbeat);
|
||||
break;
|
||||
case SMF_EVT_N4_MESSAGE:
|
||||
@@ -296,16 +279,14 @@ void smf_pfcp_state_associated(ogs_fsm_t *s, smf_event_t *e)
|
||||
}
|
||||
break;
|
||||
case OGS_PFCP_ASSOCIATION_SETUP_REQUEST_TYPE:
|
||||
ogs_warn("PFCP[REQ] has already been associated [%s]:%d",
|
||||
OGS_ADDR(&node->addr, buf),
|
||||
OGS_PORT(&node->addr));
|
||||
ogs_warn("PFCP[REQ] has already been associated %s",
|
||||
ogs_sockaddr_to_string_static(node->addr_list));
|
||||
ogs_pfcp_cp_handle_association_setup_request(node, xact,
|
||||
&message->pfcp_association_setup_request);
|
||||
break;
|
||||
case OGS_PFCP_ASSOCIATION_SETUP_RESPONSE_TYPE:
|
||||
ogs_warn("PFCP[RSP] has already been associated [%s]:%d",
|
||||
OGS_ADDR(&node->addr, buf),
|
||||
OGS_PORT(&node->addr));
|
||||
ogs_warn("PFCP[RSP] has already been associated %s",
|
||||
ogs_sockaddr_to_string_static(node->addr_list));
|
||||
ogs_pfcp_cp_handle_association_setup_response(node, xact,
|
||||
&message->pfcp_association_setup_response);
|
||||
break;
|
||||
@@ -421,8 +402,8 @@ void smf_pfcp_state_associated(ogs_fsm_t *s, smf_event_t *e)
|
||||
}
|
||||
break;
|
||||
case SMF_EVT_N4_NO_HEARTBEAT:
|
||||
ogs_warn("No Heartbeat from UPF [%s]:%d",
|
||||
OGS_ADDR(addr, buf), OGS_PORT(addr));
|
||||
ogs_warn("No Heartbeat from UPF %s",
|
||||
ogs_sockaddr_to_string_static(node->addr_list));
|
||||
|
||||
/*
|
||||
* reselect_upf() should not be executed on node_timeout
|
||||
|
@@ -405,23 +405,12 @@ void smf_state_operational(ogs_fsm_t *s, smf_event_t *e)
|
||||
ogs_assert(e);
|
||||
recvbuf = e->pkbuf;
|
||||
ogs_assert(recvbuf);
|
||||
pfcp_message = e->pfcp_message;
|
||||
ogs_assert(pfcp_message);
|
||||
pfcp_node = e->pfcp_node;
|
||||
ogs_assert(pfcp_node);
|
||||
ogs_assert(OGS_FSM_STATE(&pfcp_node->sm));
|
||||
|
||||
/*
|
||||
* Issue #1911
|
||||
*
|
||||
* Because ogs_pfcp_message_t is over 80kb in size,
|
||||
* it can cause stack overflow.
|
||||
* To avoid this, the pfcp_message structure uses heap memory.
|
||||
*/
|
||||
if ((pfcp_message = ogs_pfcp_parse_msg(recvbuf)) == NULL) {
|
||||
ogs_error("ogs_pfcp_parse_msg() failed");
|
||||
ogs_pkbuf_free(recvbuf);
|
||||
break;
|
||||
}
|
||||
|
||||
rv = ogs_pfcp_xact_receive(pfcp_node, &pfcp_message->h, &pfcp_xact);
|
||||
if (rv != OGS_OK) {
|
||||
ogs_pkbuf_free(recvbuf);
|
||||
@@ -429,7 +418,6 @@ void smf_state_operational(ogs_fsm_t *s, smf_event_t *e)
|
||||
break;
|
||||
}
|
||||
|
||||
e->pfcp_message = pfcp_message;
|
||||
e->pfcp_xact_id = pfcp_xact ? pfcp_xact->id : OGS_INVALID_POOL_ID;
|
||||
|
||||
e->gtp2_message = NULL;
|
||||
|
@@ -64,8 +64,12 @@ static void pfcp_recv_cb(short when, ogs_socket_t fd, void *data)
|
||||
ogs_pkbuf_t *pkbuf = NULL;
|
||||
ogs_sockaddr_t from;
|
||||
ogs_pfcp_node_t *node = NULL;
|
||||
ogs_pfcp_message_t *message = NULL;
|
||||
ogs_pfcp_header_t *h = NULL;
|
||||
|
||||
ogs_pfcp_status_e pfcp_status;;
|
||||
ogs_pfcp_node_id_t node_id;
|
||||
|
||||
ogs_assert(fd != INVALID_SOCKET);
|
||||
|
||||
pkbuf = ogs_pkbuf_alloc(NULL, OGS_MAX_SDU_LEN);
|
||||
@@ -105,28 +109,105 @@ static void pfcp_recv_cb(short when, ogs_socket_t fd, void *data)
|
||||
e = upf_event_new(UPF_EVT_N4_MESSAGE);
|
||||
ogs_assert(e);
|
||||
|
||||
node = ogs_pfcp_node_find(&ogs_pfcp_self()->pfcp_peer_list, &from);
|
||||
if (!node) {
|
||||
node = ogs_pfcp_node_add(&ogs_pfcp_self()->pfcp_peer_list, &from);
|
||||
if (!node) {
|
||||
ogs_error("No memory: ogs_pfcp_node_add() failed");
|
||||
ogs_pkbuf_free(e->pkbuf);
|
||||
upf_event_free(e);
|
||||
return;
|
||||
}
|
||||
|
||||
node->sock = data;
|
||||
pfcp_node_fsm_init(node, false);
|
||||
/*
|
||||
* Issue #1911
|
||||
*
|
||||
* Because ogs_pfcp_message_t is over 80kb in size,
|
||||
* it can cause stack overflow.
|
||||
* To avoid this, the pfcp_message structure uses heap memory.
|
||||
*/
|
||||
if ((message = ogs_pfcp_parse_msg(pkbuf)) == NULL) {
|
||||
ogs_error("ogs_pfcp_parse_msg() failed");
|
||||
ogs_pkbuf_free(pkbuf);
|
||||
upf_event_free(e);
|
||||
return;
|
||||
}
|
||||
|
||||
pfcp_status = ogs_pfcp_extract_node_id(message, &node_id);
|
||||
switch (pfcp_status) {
|
||||
case OGS_PFCP_STATUS_SUCCESS:
|
||||
case OGS_PFCP_STATUS_NODE_ID_NONE:
|
||||
case OGS_PFCP_STATUS_NODE_ID_OPTIONAL_ABSENT:
|
||||
ogs_debug("ogs_pfcp_extract_node_id() "
|
||||
"type [%d] pfcp_status [%d] node_id [%s] from %s",
|
||||
message->h.type, pfcp_status,
|
||||
pfcp_status == OGS_PFCP_STATUS_SUCCESS ?
|
||||
ogs_pfcp_node_id_to_string_static(&node_id) :
|
||||
"NULL",
|
||||
ogs_sockaddr_to_string_static(&from));
|
||||
break;
|
||||
|
||||
case OGS_PFCP_ERROR_SEMANTIC_INCORRECT_MESSAGE:
|
||||
case OGS_PFCP_ERROR_NODE_ID_NOT_PRESENT:
|
||||
case OGS_PFCP_ERROR_NODE_ID_NOT_FOUND:
|
||||
case OGS_PFCP_ERROR_UNKNOWN_MESSAGE:
|
||||
ogs_error("ogs_pfcp_extract_node_id() failed "
|
||||
"type [%d] pfcp_status [%d] from %s",
|
||||
message->h.type, pfcp_status,
|
||||
ogs_sockaddr_to_string_static(&from));
|
||||
goto cleanup;
|
||||
|
||||
default:
|
||||
ogs_error("Unexpected pfcp_status "
|
||||
"type [%d] pfcp_status [%d] from %s",
|
||||
message->h.type, pfcp_status,
|
||||
ogs_sockaddr_to_string_static(&from));
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
node = ogs_pfcp_node_find(&ogs_pfcp_self()->pfcp_peer_list,
|
||||
pfcp_status == OGS_PFCP_STATUS_SUCCESS ? &node_id : NULL, &from);
|
||||
if (!node) {
|
||||
if (message->h.type == OGS_PFCP_ASSOCIATION_SETUP_REQUEST_TYPE ||
|
||||
message->h.type == OGS_PFCP_ASSOCIATION_SETUP_RESPONSE_TYPE) {
|
||||
ogs_assert(pfcp_status == OGS_PFCP_STATUS_SUCCESS);
|
||||
node = ogs_pfcp_node_add(&ogs_pfcp_self()->pfcp_peer_list,
|
||||
&node_id, &from);
|
||||
if (!node) {
|
||||
ogs_error("No memory: ogs_pfcp_node_add() failed");
|
||||
goto cleanup;
|
||||
}
|
||||
ogs_debug("Added PFCP-Node: addr_list %s",
|
||||
ogs_sockaddr_to_string_static(node->addr_list));
|
||||
|
||||
pfcp_node_fsm_init(node, false);
|
||||
|
||||
} else {
|
||||
ogs_error("Cannot find PFCP-Node: type [%d] node_id %s from %s",
|
||||
message->h.type,
|
||||
pfcp_status == OGS_PFCP_STATUS_SUCCESS ?
|
||||
ogs_pfcp_node_id_to_string_static(&node_id) :
|
||||
"NULL",
|
||||
ogs_sockaddr_to_string_static(&from));
|
||||
goto cleanup;
|
||||
}
|
||||
} else {
|
||||
ogs_debug("Found PFCP-Node: addr_list %s",
|
||||
ogs_sockaddr_to_string_static(node->addr_list));
|
||||
ogs_expect(OGS_OK == ogs_pfcp_node_merge(
|
||||
node,
|
||||
pfcp_status == OGS_PFCP_STATUS_SUCCESS ? &node_id : NULL,
|
||||
&from));
|
||||
ogs_debug("Merged PFCP-Node: addr_list %s",
|
||||
ogs_sockaddr_to_string_static(node->addr_list));
|
||||
}
|
||||
|
||||
e->pfcp_node = node;
|
||||
e->pkbuf = pkbuf;
|
||||
e->pfcp_message = message;
|
||||
|
||||
rv = ogs_queue_push(ogs_app()->queue, e);
|
||||
if (rv != OGS_OK) {
|
||||
ogs_error("ogs_queue_push() failed:%d", (int)rv);
|
||||
ogs_pkbuf_free(e->pkbuf);
|
||||
upf_event_free(e);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
cleanup:
|
||||
ogs_pkbuf_free(pkbuf);
|
||||
ogs_pfcp_message_free(message);
|
||||
upf_event_free(e);
|
||||
}
|
||||
|
||||
int upf_pfcp_open(void)
|
||||
|
@@ -30,7 +30,6 @@ static void node_timeout(ogs_pfcp_xact_t *xact, void *data);
|
||||
|
||||
void upf_pfcp_state_initial(ogs_fsm_t *s, upf_event_t *e)
|
||||
{
|
||||
int rv;
|
||||
ogs_pfcp_node_t *node = NULL;
|
||||
|
||||
ogs_assert(s);
|
||||
@@ -41,10 +40,6 @@ void upf_pfcp_state_initial(ogs_fsm_t *s, upf_event_t *e)
|
||||
node = e->pfcp_node;
|
||||
ogs_assert(node);
|
||||
|
||||
rv = ogs_pfcp_connect(
|
||||
ogs_pfcp_self()->pfcp_sock, ogs_pfcp_self()->pfcp_sock6, node);
|
||||
ogs_assert(rv == OGS_OK);
|
||||
|
||||
node->t_no_heartbeat = ogs_timer_add(ogs_app()->timer_mgr,
|
||||
upf_timer_no_heartbeat, node);
|
||||
ogs_assert(node->t_no_heartbeat);
|
||||
@@ -68,12 +63,9 @@ void upf_pfcp_state_final(ogs_fsm_t *s, upf_event_t *e)
|
||||
|
||||
void upf_pfcp_state_will_associate(ogs_fsm_t *s, upf_event_t *e)
|
||||
{
|
||||
char buf[OGS_ADDRSTRLEN];
|
||||
|
||||
ogs_pfcp_node_t *node = NULL;
|
||||
ogs_pfcp_xact_t *xact = NULL;
|
||||
ogs_pfcp_message_t *message = NULL;
|
||||
ogs_sockaddr_t *addr = NULL;
|
||||
ogs_assert(s);
|
||||
ogs_assert(e);
|
||||
|
||||
@@ -101,11 +93,8 @@ void upf_pfcp_state_will_associate(ogs_fsm_t *s, upf_event_t *e)
|
||||
case UPF_EVT_N4_TIMER:
|
||||
switch(e->timer_id) {
|
||||
case UPF_TIMER_ASSOCIATION:
|
||||
addr = node->sa_list;
|
||||
ogs_assert(addr);
|
||||
|
||||
ogs_warn("Retry association with peer [%s]:%d failed",
|
||||
OGS_ADDR(addr, buf), OGS_PORT(addr));
|
||||
ogs_warn("Retry association with peer failed %s",
|
||||
ogs_sockaddr_to_string_static(node->addr_list));
|
||||
|
||||
ogs_assert(node->t_association);
|
||||
ogs_timer_start(node->t_association,
|
||||
@@ -160,13 +149,10 @@ void upf_pfcp_state_will_associate(ogs_fsm_t *s, upf_event_t *e)
|
||||
|
||||
void upf_pfcp_state_associated(ogs_fsm_t *s, upf_event_t *e)
|
||||
{
|
||||
char buf[OGS_ADDRSTRLEN];
|
||||
|
||||
ogs_pfcp_node_t *node = NULL;
|
||||
ogs_pfcp_xact_t *xact = NULL;
|
||||
ogs_pfcp_message_t *message = NULL;
|
||||
|
||||
ogs_sockaddr_t *addr = NULL;
|
||||
upf_sess_t *sess = NULL;
|
||||
|
||||
ogs_assert(s);
|
||||
@@ -176,14 +162,11 @@ void upf_pfcp_state_associated(ogs_fsm_t *s, upf_event_t *e)
|
||||
|
||||
node = e->pfcp_node;
|
||||
ogs_assert(node);
|
||||
addr = node->sa_list;
|
||||
ogs_assert(addr);
|
||||
|
||||
switch (e->id) {
|
||||
case OGS_FSM_ENTRY_SIG:
|
||||
ogs_info("PFCP associated [%s]:%d",
|
||||
OGS_ADDR(&node->addr, buf),
|
||||
OGS_PORT(&node->addr));
|
||||
ogs_info("PFCP associated %s",
|
||||
ogs_sockaddr_to_string_static(node->addr_list));
|
||||
ogs_timer_start(node->t_no_heartbeat,
|
||||
ogs_local_conf()->time.message.pfcp.no_heartbeat_duration);
|
||||
ogs_assert(OGS_OK ==
|
||||
@@ -196,9 +179,8 @@ void upf_pfcp_state_associated(ogs_fsm_t *s, upf_event_t *e)
|
||||
}
|
||||
break;
|
||||
case OGS_FSM_EXIT_SIG:
|
||||
ogs_info("PFCP de-associated [%s]:%d",
|
||||
OGS_ADDR(&node->addr, buf),
|
||||
OGS_PORT(&node->addr));
|
||||
ogs_info("PFCP de-associated %s",
|
||||
ogs_sockaddr_to_string_static(node->addr_list));
|
||||
ogs_timer_stop(node->t_no_heartbeat);
|
||||
break;
|
||||
case UPF_EVT_N4_MESSAGE:
|
||||
@@ -267,16 +249,14 @@ void upf_pfcp_state_associated(ogs_fsm_t *s, upf_event_t *e)
|
||||
}
|
||||
break;
|
||||
case OGS_PFCP_ASSOCIATION_SETUP_REQUEST_TYPE:
|
||||
ogs_warn("PFCP[REQ] has already been associated [%s]:%d",
|
||||
OGS_ADDR(&node->addr, buf),
|
||||
OGS_PORT(&node->addr));
|
||||
ogs_warn("PFCP[REQ] has already been associated %s",
|
||||
ogs_sockaddr_to_string_static(node->addr_list));
|
||||
ogs_pfcp_up_handle_association_setup_request(node, xact,
|
||||
&message->pfcp_association_setup_request);
|
||||
break;
|
||||
case OGS_PFCP_ASSOCIATION_SETUP_RESPONSE_TYPE:
|
||||
ogs_warn("PFCP[RSP] has already been associated [%s]:%d",
|
||||
OGS_ADDR(&node->addr, buf),
|
||||
OGS_PORT(&node->addr));
|
||||
ogs_warn("PFCP[RSP] has already been associated %s",
|
||||
ogs_sockaddr_to_string_static(node->addr_list));
|
||||
ogs_pfcp_up_handle_association_setup_response(node, xact,
|
||||
&message->pfcp_association_setup_response);
|
||||
break;
|
||||
@@ -322,8 +302,8 @@ void upf_pfcp_state_associated(ogs_fsm_t *s, upf_event_t *e)
|
||||
}
|
||||
break;
|
||||
case UPF_EVT_N4_NO_HEARTBEAT:
|
||||
ogs_warn("No Heartbeat from SMF [%s]:%d",
|
||||
OGS_ADDR(addr, buf), OGS_PORT(addr));
|
||||
ogs_warn("No Heartbeat from SMF %s",
|
||||
ogs_sockaddr_to_string_static(node->addr_list));
|
||||
OGS_FSM_TRAN(s, upf_pfcp_state_will_associate);
|
||||
break;
|
||||
default:
|
||||
|
@@ -63,21 +63,11 @@ void upf_state_operational(ogs_fsm_t *s, upf_event_t *e)
|
||||
ogs_assert(e);
|
||||
recvbuf = e->pkbuf;
|
||||
ogs_assert(recvbuf);
|
||||
pfcp_message = e->pfcp_message;
|
||||
ogs_assert(pfcp_message);
|
||||
node = e->pfcp_node;
|
||||
ogs_assert(node);
|
||||
|
||||
/*
|
||||
* Issue #1911
|
||||
*
|
||||
* Because ogs_pfcp_message_t is over 80kb in size,
|
||||
* it can cause stack overflow.
|
||||
* To avoid this, the pfcp_message structure uses heap memory.
|
||||
*/
|
||||
if ((pfcp_message = ogs_pfcp_parse_msg(recvbuf)) == NULL) {
|
||||
ogs_error("ogs_pfcp_parse_msg() failed");
|
||||
ogs_pkbuf_free(recvbuf);
|
||||
break;
|
||||
}
|
||||
ogs_assert(OGS_FSM_STATE(&node->sm));
|
||||
|
||||
rv = ogs_pfcp_xact_receive(node, &pfcp_message->h, &xact);
|
||||
if (rv != OGS_OK) {
|
||||
@@ -86,7 +76,6 @@ void upf_state_operational(ogs_fsm_t *s, upf_event_t *e)
|
||||
break;
|
||||
}
|
||||
|
||||
e->pfcp_message = pfcp_message;
|
||||
e->pfcp_xact_id = xact ? xact->id : OGS_INVALID_POOL_ID;
|
||||
ogs_fsm_dispatch(&node->sm, e);
|
||||
if (OGS_FSM_CHECK(&node->sm, upf_pfcp_state_exception)) {
|
||||
|
Reference in New Issue
Block a user