Merge branch 'main' into gh_upf_metrics_wrong_dnn

This commit is contained in:
gstaa 2023-04-17 06:47:15 +02:00 committed by GitHub
commit 9e0467e534
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
67 changed files with 1510 additions and 1007 deletions

View File

@ -38,9 +38,9 @@ static ogs_core_context_t self = {
void ogs_core_initialize(void)
{
ogs_mem_init();
ogs_log_init();
ogs_pkbuf_init();
ogs_mem_init();
ogs_socket_init();
ogs_tlv_init();
@ -56,9 +56,9 @@ void ogs_core_terminate(void)
{
ogs_tlv_final();
ogs_socket_final();
ogs_mem_final();
ogs_pkbuf_final();
ogs_log_final();
ogs_mem_final();
}
ogs_core_context_t *ogs_core(void)

View File

@ -58,7 +58,7 @@ void *ogs_realloc_debug(
void *ptr, size_t size, const char *file_line);
int ogs_free_debug(void *ptr);
#if OGS_USE_TALLOC
#if OGS_USE_TALLOC == 1
/*****************************************
* Memory Pool - Use talloc library

View File

@ -99,6 +99,7 @@ void ogs_pkbuf_init(void)
{
#if OGS_USE_TALLOC == 0
ogs_pool_init(&pkbuf_pool, ogs_core()->pkbuf.pool);
#endif
}
@ -219,7 +220,7 @@ void ogs_pkbuf_pool_destroy(ogs_pkbuf_pool_t *pool)
ogs_pkbuf_t *ogs_pkbuf_alloc_debug(
ogs_pkbuf_pool_t *pool, unsigned int size, const char *file_line)
{
#if OGS_USE_TALLOC
#if OGS_USE_TALLOC == 1
ogs_pkbuf_t *pkbuf = NULL;
pkbuf = ogs_talloc_zero_size(pool, sizeof(*pkbuf) + size, file_line);
@ -287,7 +288,7 @@ ogs_pkbuf_t *ogs_pkbuf_alloc_debug(
void ogs_pkbuf_free(ogs_pkbuf_t *pkbuf)
{
#if OGS_USE_TALLOC
#if OGS_USE_TALLOC == 1
ogs_talloc_free(pkbuf, OGS_FILE_LINE);
#else
ogs_pkbuf_pool_t *pool = NULL;
@ -315,7 +316,7 @@ void ogs_pkbuf_free(ogs_pkbuf_t *pkbuf)
ogs_pkbuf_t *ogs_pkbuf_copy_debug(ogs_pkbuf_t *pkbuf, const char *file_line)
{
#if OGS_USE_TALLOC
#if OGS_USE_TALLOC == 1
ogs_pkbuf_t *newbuf;
#else
ogs_pkbuf_pool_t *pool = NULL;
@ -331,7 +332,7 @@ ogs_pkbuf_t *ogs_pkbuf_copy_debug(ogs_pkbuf_t *pkbuf, const char *file_line)
return NULL;
}
#if OGS_USE_TALLOC
#if OGS_USE_TALLOC == 1
newbuf = ogs_pkbuf_alloc_debug(NULL, size, file_line);
if (!newbuf) {
ogs_error("ogs_pkbuf_alloc() failed [size=%d]", size);

View File

@ -35,7 +35,7 @@ typedef struct ogs_cluster_s {
unsigned int reference_count;
} ogs_cluster_t;
#if OGS_USE_TALLOC
#if OGS_USE_TALLOC == 1
typedef void ogs_pkbuf_pool_t;
#else
typedef struct ogs_pkbuf_pool_s ogs_pkbuf_pool_t;

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2019 by Sukchan Lee <acetcom@gmail.com>
* Copyright (C) 2019-2023 by Sukchan Lee <acetcom@gmail.com>
*
* This file is part of Open5GS.
*
@ -28,7 +28,15 @@
extern "C" {
#endif
typedef unsigned int ogs_index_t;
#if OGS_USE_TALLOC == 1
#define ogs_pool_create ogs_malloc
#define ogs_pool_destroy ogs_free
#else
#define ogs_pool_create malloc
#define ogs_pool_destroy free
#endif
typedef uint32_t ogs_pool_id_t;
#define OGS_POOL(pool, type) \
struct { \
@ -41,11 +49,11 @@ typedef unsigned int ogs_index_t;
#define ogs_pool_init(pool, _size) do { \
int i; \
(pool)->name = #pool; \
(pool)->free = malloc(sizeof(*(pool)->free) * _size); \
(pool)->free = ogs_pool_create(sizeof(*(pool)->free) * _size); \
ogs_assert((pool)->free); \
(pool)->array = malloc(sizeof(*(pool)->array) * _size); \
(pool)->array = ogs_pool_create(sizeof(*(pool)->array) * _size); \
ogs_assert((pool)->array); \
(pool)->index = malloc(sizeof(*(pool)->index) * _size); \
(pool)->index = ogs_pool_create(sizeof(*(pool)->index) * _size); \
ogs_assert((pool)->index); \
(pool)->size = (pool)->avail = _size; \
(pool)->head = (pool)->tail = 0; \
@ -59,9 +67,9 @@ typedef unsigned int ogs_index_t;
if (((pool)->size != (pool)->avail)) \
ogs_error("%d in '%s[%d]' were not released.", \
(pool)->size - (pool)->avail, (pool)->name, (pool)->size); \
free((pool)->free); \
free((pool)->array); \
free((pool)->index); \
ogs_pool_destroy((pool)->free); \
ogs_pool_destroy((pool)->array); \
ogs_pool_destroy((pool)->index); \
} while (0)
#define ogs_pool_index(pool, node) (((node) - (pool)->array)+1)
@ -93,30 +101,23 @@ typedef unsigned int ogs_index_t;
#define ogs_pool_size(pool) ((pool)->size)
#define ogs_pool_avail(pool) ((pool)->avail)
#define ogs_index_init(pool, _size) do { \
#define ogs_pool_sequence_id_generate(pool) do { \
int i; \
(pool)->name = #pool; \
(pool)->free = ogs_malloc(sizeof(*(pool)->free) * _size); \
ogs_assert((pool)->free); \
(pool)->array = ogs_malloc(sizeof(*(pool)->array) * _size); \
ogs_assert((pool)->array); \
(pool)->index = ogs_malloc(sizeof(*(pool)->index) * _size); \
ogs_assert((pool)->index); \
(pool)->size = (pool)->avail = _size; \
(pool)->head = (pool)->tail = 0; \
for (i = 0; i < _size; i++) { \
(pool)->free[i] = &((pool)->array[i]); \
(pool)->index[i] = NULL; \
} \
for (i = 0; i < (pool)->size; i++) \
(pool)->array[i] = i+1; \
} while (0)
#define ogs_index_final(pool) do { \
if (((pool)->size != (pool)->avail)) \
ogs_error("%d in '%s[%d]' were not released.", \
(pool)->size - (pool)->avail, (pool)->name, (pool)->size); \
ogs_free((pool)->free); \
ogs_free((pool)->array); \
ogs_free((pool)->index); \
#define ogs_pool_random_id_generate(pool) do { \
int i, j; \
ogs_pool_id_t temp; \
for (i = 0; i < (pool)->size; i++) \
(pool)->array[i] = i+1; \
for (i = (pool)->size - 1; i > 0; i--) { \
j = ogs_random32() % (i + 1); \
temp = (pool)->array[i]; \
(pool)->array[i] = (pool)->array[j]; \
(pool)->array[j] = temp; \
} \
} while (0)
#ifdef __cplusplus

View File

@ -110,7 +110,7 @@ char *ogs_mstrcatf_debug(
char *source, const char *file_line, const char *message, ...)
OGS_GNUC_PRINTF(3, 4);
#if OGS_USE_TALLOC
#if OGS_USE_TALLOC == 1
/*****************************************
* Memory Pool - Use talloc library

View File

@ -1,6 +1,7 @@
/*
* Copyright (C) 2019 by Sukchan Lee <acetcom@gmail.com>
* Copyright (C) 2022 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de>
* Copyright (C) 2023 Sukchan Lee <acetcom@gmail.com>
*
* This file is part of Open5GS.
*

View File

@ -1,6 +1,7 @@
/*
* Copyright (C) 2019 by Sukchan Lee <acetcom@gmail.com>
* Copyright (C) 2022 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de>
* Copyright (C) 2023 by Sukchan Lee <acetcom@gmail.com>
*
* This file is part of Open5GS.
*
@ -31,6 +32,7 @@ extern "C" {
ogs_pkbuf_t *ogs_gtp1_build_echo_request(uint8_t type);
ogs_pkbuf_t *ogs_gtp1_build_echo_response(uint8_t type, uint8_t recovery);
#ifdef __cplusplus
}
#endif

View File

@ -1,6 +1,7 @@
/*
* Copyright (C) 2019 by Sukchan Lee <acetcom@gmail.com>
* Copyright (C) 2022 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de>
* Copyright (C) 2023 by Sukchan Lee <acetcom@gmail.com>
*
* This file is part of Open5GS.
*
@ -143,8 +144,7 @@ void ogs_gtp1_send_error_message(
ogs_expect(rv == OGS_OK);
}
void ogs_gtp1_send_echo_request(
ogs_gtp_node_t *gnode)
void ogs_gtp1_send_echo_request(ogs_gtp_node_t *gnode)
{
int rv;
ogs_pkbuf_t *pkbuf = NULL;

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2019 by Sukchan Lee <acetcom@gmail.com>
* Copyright (C) 2019-2023 by Sukchan Lee <acetcom@gmail.com>
*
* This file is part of Open5GS.
*
@ -57,7 +57,7 @@ ogs_pkbuf_t *ogs_gtp2_build_echo_response(
return ogs_gtp2_build_msg(&gtp_message);
}
ogs_pkbuf_t *ogs_gtp2_build_error_indication(
ogs_pkbuf_t *ogs_gtp1_build_error_indication(
uint32_t teid, ogs_sockaddr_t *addr)
{
ogs_pkbuf_t *pkbuf = NULL;
@ -112,3 +112,91 @@ ogs_pkbuf_t *ogs_gtp2_build_error_indication(
return pkbuf;
}
void ogs_gtp2_fill_header(
ogs_gtp2_header_t *gtp_hdesc, ogs_gtp2_extension_header_t *ext_hdesc,
ogs_pkbuf_t *pkbuf)
{
ogs_gtp2_header_t *gtp_h = NULL;
ogs_gtp2_extension_header_t *ext_h = NULL;
uint8_t flags;
uint8_t gtp_hlen = 0;
ogs_assert(gtp_hdesc);
ogs_assert(ext_hdesc);
ogs_assert(pkbuf);
/* Processing GTP Flags */
flags = gtp_hdesc->flags;
flags |= OGS_GTPU_FLAGS_V | OGS_GTPU_FLAGS_PT;
if (ext_hdesc->qos_flow_identifier) flags |= OGS_GTPU_FLAGS_E;
/* Define GTP Header Size */
if (flags & OGS_GTPU_FLAGS_E)
gtp_hlen = OGS_GTPV1U_HEADER_LEN+8;
else if (flags & (OGS_GTPU_FLAGS_S|OGS_GTPU_FLAGS_PN))
gtp_hlen = OGS_GTPV1U_HEADER_LEN+4;
else
gtp_hlen = OGS_GTPV1U_HEADER_LEN;
ogs_pkbuf_push(pkbuf, gtp_hlen);
/* Fill GTP Header */
gtp_h = (ogs_gtp2_header_t *)pkbuf->data;
ogs_assert(gtp_h);
memset(gtp_h, 0, gtp_hlen);
gtp_h->flags = flags;
gtp_h->type = gtp_hdesc->type;
if (gtp_h->type == OGS_GTPU_MSGTYPE_ECHO_REQ ||
gtp_h->type == OGS_GTPU_MSGTYPE_ECHO_RSP ||
gtp_h->type == OGS_GTPU_MSGTYPE_ERR_IND) {
/*
* TS29.281 5.1 General format in GTP-U header
*
* - The Echo Request/Response and Supported Extension Headers
* notification messages, where the Tunnel Endpoint Identifier
* shall be set to all zeroes.
* - The Error Indication message where the Tunnel Endpoint Identifier
* shall be set to all zeros.
*/
ogs_assert(gtp_hdesc->teid == 0);
}
gtp_h->teid = htobe32(gtp_hdesc->teid);
/*
* TS29.281 5.1 General format in GTP-U header
*
* Length: This field indicates the length in octets of the payload,
* i.e. the rest of the packet following the mandatory part of
* the GTP header (that is the first 8 octets). The Sequence Number,
* the N-PDU Number or any Extension headers shall be considered
* to be part of the payload, i.e. included in the length count.
*/
gtp_h->length = htobe16(pkbuf->len - OGS_GTPV1U_HEADER_LEN);
/* Fill Extention Header */
if (gtp_h->flags & OGS_GTPU_FLAGS_E) {
ext_h = (ogs_gtp2_extension_header_t *)
(pkbuf->data + OGS_GTPV1U_HEADER_LEN);
ogs_assert(ext_h);
if (ext_hdesc->qos_flow_identifier) {
/* 5G Core */
ext_h->type = OGS_GTP2_EXTENSION_HEADER_TYPE_PDU_SESSION_CONTAINER;
ext_h->len = 1;
ext_h->pdu_type = ext_hdesc->pdu_type;
ext_h->qos_flow_identifier = ext_hdesc->qos_flow_identifier;
ext_h->next_type =
OGS_GTP2_EXTENSION_HEADER_TYPE_NO_MORE_EXTENSION_HEADERS;
} else {
/* EPC */
ext_h->type = ext_hdesc->type;
ext_h->len = 1;
ext_h->next_type =
OGS_GTP2_EXTENSION_HEADER_TYPE_NO_MORE_EXTENSION_HEADERS;
}
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2019 by Sukchan Lee <acetcom@gmail.com>
* Copyright (C) 2019-2023 by Sukchan Lee <acetcom@gmail.com>
*
* This file is part of Open5GS.
*
@ -33,9 +33,13 @@ ogs_pkbuf_t *ogs_gtp2_build_echo_request(
ogs_pkbuf_t *ogs_gtp2_build_echo_response(
uint8_t type, uint8_t recovery, uint8_t features);
ogs_pkbuf_t *ogs_gtp2_build_error_indication(
ogs_pkbuf_t *ogs_gtp1_build_error_indication(
uint32_t teid, ogs_sockaddr_t *addr);
void ogs_gtp2_fill_header(
ogs_gtp2_header_t *gtp_hdesc, ogs_gtp2_extension_header_t *ext_hdesc,
ogs_pkbuf_t *pkbuf);
#ifdef __cplusplus
}
#endif

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2019 by Sukchan Lee <acetcom@gmail.com>
* Copyright (C) 2019-2023 by Sukchan Lee <acetcom@gmail.com>
*
* This file is part of Open5GS.
*
@ -27,92 +27,11 @@ int ogs_gtp2_send_user_plane(
char buf[OGS_ADDRSTRLEN];
int rv;
ogs_gtp2_header_t *gtp_h = NULL;
ogs_gtp2_extension_header_t *ext_h = NULL;
uint8_t flags;
uint8_t gtp_hlen = 0;
ogs_assert(gnode);
ogs_assert(gtp_hdesc);
ogs_assert(ext_hdesc);
ogs_assert(pkbuf);
/* Processing GTP Flags */
flags = gtp_hdesc->flags;
flags |= OGS_GTPU_FLAGS_V | OGS_GTPU_FLAGS_PT;
if (ext_hdesc->qos_flow_identifier) flags |= OGS_GTPU_FLAGS_E;
/* Define GTP Header Size */
if (flags & OGS_GTPU_FLAGS_E)
gtp_hlen = OGS_GTPV1U_HEADER_LEN+8;
else if (flags & (OGS_GTPU_FLAGS_S|OGS_GTPU_FLAGS_PN))
gtp_hlen = OGS_GTPV1U_HEADER_LEN+4;
else
gtp_hlen = OGS_GTPV1U_HEADER_LEN;
ogs_pkbuf_push(pkbuf, gtp_hlen);
/* Fill GTP Header */
gtp_h = (ogs_gtp2_header_t *)pkbuf->data;
ogs_assert(gtp_h);
memset(gtp_h, 0, gtp_hlen);
gtp_h->flags = flags;
gtp_h->type = gtp_hdesc->type;
if (gtp_h->type == OGS_GTPU_MSGTYPE_ECHO_REQ ||
gtp_h->type == OGS_GTPU_MSGTYPE_ECHO_RSP ||
gtp_h->type == OGS_GTPU_MSGTYPE_ERR_IND) {
/*
* TS29.281 5.1 General format in GTP-U header
*
* - The Echo Request/Response and Supported Extension Headers
* notification messages, where the Tunnel Endpoint Identifier
* shall be set to all zeroes.
* - The Error Indication message where the Tunnel Endpoint Identifier
* shall be set to all zeros.
*/
ogs_assert(gtp_hdesc->teid == 0);
}
gtp_h->teid = htobe32(gtp_hdesc->teid);
/*
* TS29.281 5.1 General format in GTP-U header
*
* Length: This field indicates the length in octets of the payload,
* i.e. the rest of the packet following the mandatory part of
* the GTP header (that is the first 8 octets). The Sequence Number,
* the N-PDU Number or any Extension headers shall be considered
* to be part of the payload, i.e. included in the length count.
*/
gtp_h->length = htobe16(pkbuf->len - OGS_GTPV1U_HEADER_LEN);
/* Fill Extention Header */
if (gtp_h->flags & OGS_GTPU_FLAGS_E) {
ext_h = (ogs_gtp2_extension_header_t *)
(pkbuf->data + OGS_GTPV1U_HEADER_LEN);
ogs_assert(ext_h);
if (ext_hdesc->qos_flow_identifier) {
/* 5G Core */
ext_h->type = OGS_GTP2_EXTENSION_HEADER_TYPE_PDU_SESSION_CONTAINER;
ext_h->len = 1;
ext_h->pdu_type = ext_hdesc->pdu_type;
ext_h->qos_flow_identifier = ext_hdesc->qos_flow_identifier;
ext_h->next_type =
OGS_GTP2_EXTENSION_HEADER_TYPE_NO_MORE_EXTENSION_HEADERS;
} else {
/* EPC */
ext_h->type = ext_hdesc->type;
ext_h->len = 1;
ext_h->next_type =
OGS_GTP2_EXTENSION_HEADER_TYPE_NO_MORE_EXTENSION_HEADERS;
}
}
ogs_gtp2_fill_header(gtp_hdesc, ext_hdesc, pkbuf);
ogs_trace("SEND GTP-U[%d] to Peer[%s] : TEID[0x%x]",
gtp_hdesc->type, OGS_ADDR(&gnode->addr, buf), gtp_hdesc->teid);
rv = ogs_gtp_sendto(gnode, pkbuf);
if (rv != OGS_OK) {
if (ogs_socket_errno != OGS_EAGAIN) {
@ -342,3 +261,39 @@ void ogs_gtp2_send_echo_response(ogs_gtp_xact_t *xact,
rv = ogs_gtp_xact_commit(xact);
ogs_expect(rv == OGS_OK);
}
void ogs_gtp1_send_error_indication(
ogs_sock_t *sock, uint32_t teid, uint8_t qfi, const ogs_sockaddr_t *to)
{
ssize_t sent;
ogs_pkbuf_t *pkbuf = NULL;
ogs_gtp2_header_t gtp_hdesc;
ogs_gtp2_extension_header_t ext_hdesc;
ogs_assert(sock);
ogs_assert(to);
pkbuf = ogs_gtp1_build_error_indication(teid, &sock->local_addr);
if (!pkbuf) {
ogs_error("ogs_gtp1_build_error_indication() failed");
return;
}
memset(&gtp_hdesc, 0, sizeof(gtp_hdesc));
memset(&ext_hdesc, 0, sizeof(ext_hdesc));
gtp_hdesc.type = OGS_GTPU_MSGTYPE_ERR_IND;
gtp_hdesc.flags = OGS_GTPU_FLAGS_S|OGS_GTPU_FLAGS_E;
ext_hdesc.type = OGS_GTP2_EXTENSION_HEADER_TYPE_UDP_PORT;
ext_hdesc.qos_flow_identifier = qfi;
ogs_gtp2_fill_header(&gtp_hdesc, &ext_hdesc, pkbuf);
sent = ogs_sendto(sock->fd, pkbuf->data, pkbuf->len, 0, to);
if (sent < 0 || sent != pkbuf->len) {
ogs_log_message(OGS_LOG_ERROR, ogs_socket_errno,
"ogs_sendto() failed");
}
ogs_pkbuf_free(pkbuf);
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2019 by Sukchan Lee <acetcom@gmail.com>
* Copyright (C) 2019-2023 by Sukchan Lee <acetcom@gmail.com>
*
* This file is part of Open5GS.
*
@ -44,6 +44,9 @@ void ogs_gtp2_send_echo_request(
void ogs_gtp2_send_echo_response(ogs_gtp_xact_t *xact,
uint8_t recovery, uint8_t features);
void ogs_gtp1_send_error_indication(
ogs_sock_t *sock, uint32_t teid, uint8_t qfi, const ogs_sockaddr_t *to);
#ifdef __cplusplus
}
#endif

View File

@ -1,6 +1,7 @@
/*
* Copyright (C) 2019 by Sukchan Lee <acetcom@gmail.com>
* Copyright (C) 2022 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de>
* Copyright (C) 2023 by Sukchan Lee <acetcom@gmail.com>
*
* This file is part of Open5GS.
*
@ -57,7 +58,7 @@ extern "C" {
*/
typedef struct ogs_gtp_xact_s {
ogs_lnode_t node; /**< A node of list */
ogs_index_t index;
ogs_pool_id_t index;
uint8_t gtp_version; /**< 1 or 2 */

View File

@ -446,17 +446,15 @@ bool ogs_pfcp_build_created_pdr(
ogs_assert(pdr);
if (ogs_pfcp_self()->up_function_features.ftup) {
if (pdr->f_teid_len) {
memcpy(&pdrbuf[i].f_teid, &pdr->f_teid, pdr->f_teid_len);
pdrbuf[i].f_teid.teid = htobe32(pdr->f_teid.teid);
if (pdr->f_teid_len) {
memcpy(&pdrbuf[i].f_teid, &pdr->f_teid, pdr->f_teid_len);
pdrbuf[i].f_teid.teid = htobe32(pdr->f_teid.teid);
message->local_f_teid.presence = 1;
message->local_f_teid.data = &pdrbuf[i].f_teid;
message->local_f_teid.len = pdr->f_teid_len;
message->local_f_teid.presence = 1;
message->local_f_teid.data = &pdrbuf[i].f_teid;
message->local_f_teid.len = pdr->f_teid_len;
pdr_presence = true;
}
pdr_presence = true;
}
if (pdr_presence == true) {

View File

@ -27,18 +27,23 @@ static int context_initialized = 0;
static OGS_POOL(ogs_pfcp_node_pool, ogs_pfcp_node_t);
static OGS_POOL(ogs_pfcp_sess_pool, ogs_pfcp_sess_t);
static OGS_POOL(ogs_pfcp_pdr_pool, ogs_pfcp_pdr_t);
static OGS_POOL(ogs_pfcp_far_pool, ogs_pfcp_far_t);
static OGS_POOL(ogs_pfcp_urr_pool, ogs_pfcp_urr_t);
static OGS_POOL(ogs_pfcp_qer_pool, ogs_pfcp_qer_t);
static OGS_POOL(ogs_pfcp_bar_pool, ogs_pfcp_bar_t);
static OGS_POOL(ogs_pfcp_pdr_pool, ogs_pfcp_pdr_t);
static OGS_POOL(ogs_pfcp_pdr_teid_pool, ogs_pool_id_t);
static ogs_pool_id_t *pdr_random_to_index;
static OGS_POOL(ogs_pfcp_rule_pool, ogs_pfcp_rule_t);
static OGS_POOL(ogs_pfcp_dev_pool, ogs_pfcp_dev_t);
static OGS_POOL(ogs_pfcp_subnet_pool, ogs_pfcp_subnet_t);
static OGS_POOL(ogs_pfcp_rule_pool, ogs_pfcp_rule_t);
void ogs_pfcp_context_init(void)
{
int i;
ogs_assert(context_initialized == 0);
/* Initialize SMF context */
@ -52,8 +57,6 @@ void ogs_pfcp_context_init(void)
ogs_pool_init(&ogs_pfcp_sess_pool, ogs_app()->pool.sess);
ogs_pool_init(&ogs_pfcp_pdr_pool,
ogs_app()->pool.sess * OGS_MAX_NUM_OF_PDR);
ogs_pool_init(&ogs_pfcp_far_pool,
ogs_app()->pool.sess * OGS_MAX_NUM_OF_FAR);
ogs_pool_init(&ogs_pfcp_urr_pool,
@ -63,6 +66,17 @@ void ogs_pfcp_context_init(void)
ogs_pool_init(&ogs_pfcp_bar_pool,
ogs_app()->pool.sess * OGS_MAX_NUM_OF_BAR);
ogs_pool_init(&ogs_pfcp_pdr_pool,
ogs_app()->pool.sess * OGS_MAX_NUM_OF_PDR);
ogs_pool_init(&ogs_pfcp_pdr_teid_pool, ogs_pfcp_pdr_pool.size);
ogs_pool_random_id_generate(&ogs_pfcp_pdr_teid_pool);
pdr_random_to_index = ogs_calloc(
sizeof(ogs_pool_id_t), ogs_pfcp_pdr_pool.size);
ogs_assert(pdr_random_to_index);
for (i = 0; i < ogs_pfcp_pdr_pool.size; i++)
pdr_random_to_index[ogs_pfcp_pdr_teid_pool.array[i]] = i;
ogs_pool_init(&ogs_pfcp_rule_pool,
ogs_app()->pool.sess *
OGS_MAX_NUM_OF_PDR * OGS_MAX_NUM_OF_FLOW_IN_PDR);
@ -98,8 +112,11 @@ void ogs_pfcp_context_final(void)
ogs_pool_final(&ogs_pfcp_subnet_pool);
ogs_pool_final(&ogs_pfcp_rule_pool);
ogs_pool_final(&ogs_pfcp_sess_pool);
ogs_pool_final(&ogs_pfcp_pdr_pool);
ogs_pool_final(&ogs_pfcp_pdr_teid_pool);
ogs_free(pdr_random_to_index);
ogs_pool_final(&ogs_pfcp_sess_pool);
ogs_pool_final(&ogs_pfcp_far_pool);
ogs_pool_final(&ogs_pfcp_urr_pool);
ogs_pool_final(&ogs_pfcp_qer_pool);
@ -894,6 +911,16 @@ ogs_pfcp_pdr_t *ogs_pfcp_pdr_add(ogs_pfcp_sess_t *sess)
}
memset(pdr, 0, sizeof *pdr);
pdr->obj.type = OGS_PFCP_OBJ_PDR_TYPE;
pdr->src_if = OGS_PFCP_INTERFACE_UNKNOWN;
/* Set TEID */
ogs_pool_alloc(&ogs_pfcp_pdr_teid_pool, &pdr->teid_node);
ogs_assert(pdr->teid_node);
pdr->teid = *(pdr->teid_node);
/* Set PDR-ID */
ogs_pool_alloc(&sess->pdr_id_pool, &pdr->id_node);
if (pdr->id_node == NULL) {
ogs_error("pdr_id_pool() failed");
@ -901,17 +928,9 @@ ogs_pfcp_pdr_t *ogs_pfcp_pdr_add(ogs_pfcp_sess_t *sess)
return NULL;
}
pdr->obj.type = OGS_PFCP_OBJ_PDR_TYPE;
pdr->index = ogs_pool_index(&ogs_pfcp_pdr_pool, pdr);
ogs_assert(pdr->index > 0 &&
pdr->index <= ogs_app()->pool.sess * OGS_MAX_NUM_OF_PDR);
pdr->id = *(pdr->id_node);
ogs_assert(pdr->id > 0 && pdr->id <= OGS_MAX_NUM_OF_PDR);
pdr->src_if = OGS_PFCP_INTERFACE_UNKNOWN;
pdr->sess = sess;
ogs_list_add(&sess->pdr_list, pdr);
@ -948,12 +967,88 @@ ogs_pfcp_pdr_t *ogs_pfcp_pdr_find_or_add(
return pdr;
}
void ogs_pfcp_pdr_swap_teid(ogs_pfcp_pdr_t *pdr)
{
int i = 0;
ogs_assert(pdr);
ogs_assert(pdr->f_teid.teid > 0 &&
pdr->f_teid.teid <= ogs_pfcp_pdr_teid_pool.size);
/* Find out the Array Index for the restored TEID. */
i = pdr_random_to_index[pdr->f_teid.teid];
ogs_assert(i < ogs_pfcp_pdr_teid_pool.size);
ogs_assert(pdr->teid_node);
/*
* If SWAP has already done this, it will not try this again.
* This situation can occur when multiple PDRs are restored
* with the same TEID.
*/
if (pdr->f_teid.teid == ogs_pfcp_pdr_teid_pool.array[i]) {
ogs_pfcp_pdr_teid_pool.array[i] = *(pdr->teid_node);
*(pdr->teid_node) = pdr->f_teid.teid;
}
}
void ogs_pfcp_object_teid_hash_set(
ogs_pfcp_object_type_e type, ogs_pfcp_pdr_t *pdr)
ogs_pfcp_object_type_e type, ogs_pfcp_pdr_t *pdr,
bool restoration_indication)
{
ogs_assert(type);
ogs_assert(pdr);
if (ogs_pfcp_self()->up_function_features.ftup && pdr->f_teid.ch) {
ogs_pfcp_pdr_t *choosed_pdr = NULL;
if (pdr->f_teid.chid) {
choosed_pdr = ogs_pfcp_pdr_find_by_choose_id(
pdr->sess, pdr->f_teid.choose_id);
if (!choosed_pdr) {
pdr->chid = true;
pdr->choose_id = pdr->f_teid.choose_id;
}
}
if (choosed_pdr) {
pdr->f_teid_len = choosed_pdr->f_teid_len;
memcpy(&pdr->f_teid, &choosed_pdr->f_teid, pdr->f_teid_len);
} else {
ogs_gtpu_resource_t *resource = NULL;
resource = ogs_pfcp_find_gtpu_resource(
&ogs_gtp_self()->gtpu_resource_list,
pdr->dnn, OGS_PFCP_INTERFACE_ACCESS);
if (resource) {
ogs_assert(
(resource->info.v4 && pdr->f_teid.ipv4) ||
(resource->info.v6 && pdr->f_teid.ipv6));
ogs_assert(OGS_OK ==
ogs_pfcp_user_plane_ip_resource_info_to_f_teid(
&resource->info, &pdr->f_teid, &pdr->f_teid_len));
if (resource->info.teidri)
pdr->f_teid.teid = OGS_PFCP_GTPU_INDEX_TO_TEID(
pdr->teid, resource->info.teidri,
resource->info.teid_range);
else
pdr->f_teid.teid = pdr->teid;
} else {
ogs_assert(
(ogs_gtp_self()->gtpu_addr && pdr->f_teid.ipv4) ||
(ogs_gtp_self()->gtpu_addr6 && pdr->f_teid.ipv6));
ogs_assert(OGS_OK ==
ogs_pfcp_sockaddr_to_f_teid(
pdr->f_teid.ipv4 ?
ogs_gtp_self()->gtpu_addr : NULL,
pdr->f_teid.ipv6 ?
ogs_gtp_self()->gtpu_addr6 : NULL,
&pdr->f_teid, &pdr->f_teid_len));
pdr->f_teid.teid = pdr->teid;
}
}
}
if (pdr->hash.teid.len)
ogs_hash_set(self.object_teid_hash,
&pdr->hash.teid.key, pdr->hash.teid.len, NULL);
@ -1107,6 +1202,7 @@ void ogs_pfcp_pdr_remove(ogs_pfcp_pdr_t *pdr)
ogs_free(pdr->ipv6_framed_routes);
}
ogs_pool_free(&ogs_pfcp_pdr_teid_pool, pdr->teid_node);
ogs_pool_free(&ogs_pfcp_pdr_pool, pdr);
}
@ -1220,7 +1316,7 @@ void ogs_pfcp_far_f_teid_hash_set(ogs_pfcp_far_t *far)
&far->hash.f_teid.key, far->hash.f_teid.len, far);
}
ogs_pfcp_far_t *ogs_pfcp_far_find_by_error_indication(ogs_pkbuf_t *pkbuf)
ogs_pfcp_far_t *ogs_pfcp_far_find_by_gtpu_error_indication(ogs_pkbuf_t *pkbuf)
{
ogs_pfcp_far_hash_f_teid_t hashkey;
int hashkey_len;
@ -1282,6 +1378,61 @@ ogs_pfcp_far_t *ogs_pfcp_far_find_by_error_indication(ogs_pkbuf_t *pkbuf)
self.far_f_teid_hash, &hashkey, hashkey_len);
}
ogs_pfcp_far_t *ogs_pfcp_far_find_by_pfcp_session_report(
ogs_pfcp_sess_t *sess,
ogs_pfcp_tlv_error_indication_report_t *error_indication_report)
{
ogs_pfcp_far_t *far = NULL;
ogs_pfcp_f_teid_t *remote_f_teid = NULL;
uint32_t teid;
uint16_t len; /* OGS_IPV4_LEN or OGS_IPV6_LEN */
uint32_t addr[4];
ogs_assert(sess);
ogs_assert(error_indication_report);
if (error_indication_report->presence == 0) {
ogs_error("No Error Indication Report");
return NULL;
}
if (error_indication_report->remote_f_teid.presence == 0) {
ogs_error("No Remote F-TEID");
return NULL;
}
remote_f_teid = error_indication_report->remote_f_teid.data;
ogs_assert(remote_f_teid);
teid = be32toh(remote_f_teid->teid);
if (remote_f_teid->ipv4 && remote_f_teid->ipv6) {
ogs_error("User plane should not set both IPv4 and IPv6");
return NULL;
} else if (remote_f_teid->ipv4) {
len = OGS_IPV4_LEN;
memcpy(addr, &remote_f_teid->addr, len);
} else if (remote_f_teid->ipv6) {
len = OGS_IPV6_LEN;
memcpy(addr, remote_f_teid->addr6, len);
} else {
ogs_error("No IPv4 and IPv6");
return NULL;
}
ogs_list_for_each(&sess->far_list, far) {
if (teid == far->outer_header_creation.teid)
return far;
}
ogs_error("Cannot find the session context "
"[TEID:0x%x,LEN:%d,ADDR:%08x %08x %08x %08x]",
teid, len, be32toh(addr[0]), be32toh(addr[1]),
be32toh(addr[2]), be32toh(addr[3]));
return NULL;
}
void ogs_pfcp_far_teid_hash_set(ogs_pfcp_far_t *far)
{
ogs_assert(far);
@ -1929,41 +2080,29 @@ ogs_pfcp_subnet_t *ogs_pfcp_find_subnet_by_dnn(int family, const char *dnn)
void ogs_pfcp_pool_init(ogs_pfcp_sess_t *sess)
{
int i;
ogs_assert(sess);
sess->obj.type = OGS_PFCP_OBJ_SESS_TYPE;
ogs_index_init(&sess->pdr_id_pool, OGS_MAX_NUM_OF_PDR);
ogs_index_init(&sess->far_id_pool, OGS_MAX_NUM_OF_FAR);
ogs_index_init(&sess->urr_id_pool, OGS_MAX_NUM_OF_URR);
ogs_index_init(&sess->qer_id_pool, OGS_MAX_NUM_OF_QER);
ogs_index_init(&sess->bar_id_pool, OGS_MAX_NUM_OF_BAR);
ogs_pool_init(&sess->pdr_id_pool, OGS_MAX_NUM_OF_PDR);
ogs_pool_init(&sess->far_id_pool, OGS_MAX_NUM_OF_FAR);
ogs_pool_init(&sess->urr_id_pool, OGS_MAX_NUM_OF_URR);
ogs_pool_init(&sess->qer_id_pool, OGS_MAX_NUM_OF_QER);
ogs_pool_init(&sess->bar_id_pool, OGS_MAX_NUM_OF_BAR);
for (i = 1; i <= OGS_MAX_NUM_OF_PDR; i++) {
sess->pdr_id_pool.array[i-1] = i;
}
for (i = 1; i <= OGS_MAX_NUM_OF_FAR; i++) {
sess->far_id_pool.array[i-1] = i;
}
for (i = 1; i <= OGS_MAX_NUM_OF_URR; i++) {
sess->urr_id_pool.array[i-1] = i;
}
for (i = 1; i <= OGS_MAX_NUM_OF_QER; i++) {
sess->qer_id_pool.array[i-1] = i;
}
for (i = 1; i <= OGS_MAX_NUM_OF_BAR; i++) {
sess->bar_id_pool.array[i-1] = i;
}
ogs_pool_sequence_id_generate(&sess->pdr_id_pool);
ogs_pool_sequence_id_generate(&sess->far_id_pool);
ogs_pool_sequence_id_generate(&sess->urr_id_pool);
ogs_pool_sequence_id_generate(&sess->qer_id_pool);
ogs_pool_sequence_id_generate(&sess->bar_id_pool);
}
void ogs_pfcp_pool_final(ogs_pfcp_sess_t *sess)
{
ogs_assert(sess);
ogs_index_final(&sess->pdr_id_pool);
ogs_index_final(&sess->far_id_pool);
ogs_index_final(&sess->urr_id_pool);
ogs_index_final(&sess->qer_id_pool);
ogs_index_final(&sess->bar_id_pool);
ogs_pool_final(&sess->pdr_id_pool);
ogs_pool_final(&sess->far_id_pool);
ogs_pool_final(&sess->urr_id_pool);
ogs_pool_final(&sess->qer_id_pool);
ogs_pool_final(&sess->bar_id_pool);
}

View File

@ -137,7 +137,9 @@ typedef struct ogs_pfcp_bar_s ogs_pfcp_bar_t;
typedef struct ogs_pfcp_pdr_s {
ogs_pfcp_object_t obj;
uint32_t index;
ogs_pool_id_t *teid_node; /* A node of TEID */
ogs_pool_id_t teid;
ogs_lnode_t to_create_node;
ogs_lnode_t to_modify_node;
@ -399,8 +401,11 @@ ogs_pfcp_pdr_t *ogs_pfcp_pdr_find(
ogs_pfcp_pdr_t *ogs_pfcp_pdr_find_or_add(
ogs_pfcp_sess_t *sess, ogs_pfcp_pdr_id_t id);
void ogs_pfcp_pdr_swap_teid(ogs_pfcp_pdr_t *pdr);
void ogs_pfcp_object_teid_hash_set(
ogs_pfcp_object_type_e type, ogs_pfcp_pdr_t *pdr);
ogs_pfcp_object_type_e type, ogs_pfcp_pdr_t *pdr,
bool restoration_indication);
ogs_pfcp_object_t *ogs_pfcp_object_find_by_teid(uint32_t teid);
int ogs_pfcp_object_count_by_teid(ogs_pfcp_sess_t *sess, uint32_t teid);
@ -422,7 +427,11 @@ ogs_pfcp_far_t *ogs_pfcp_far_find_or_add(
ogs_pfcp_sess_t *sess, ogs_pfcp_far_id_t id);
void ogs_pfcp_far_f_teid_hash_set(ogs_pfcp_far_t *far);
ogs_pfcp_far_t *ogs_pfcp_far_find_by_error_indication(ogs_pkbuf_t *pkbuf);
ogs_pfcp_far_t *ogs_pfcp_far_find_by_gtpu_error_indication(
ogs_pkbuf_t *pkbuf);
ogs_pfcp_far_t *ogs_pfcp_far_find_by_pfcp_session_report(
ogs_pfcp_sess_t *sess,
ogs_pfcp_tlv_error_indication_report_t *error_indication_report);
void ogs_pfcp_far_teid_hash_set(ogs_pfcp_far_t *far);
ogs_pfcp_far_t *ogs_pfcp_far_find_by_teid(uint32_t teid);

View File

@ -320,6 +320,7 @@ bool ogs_pfcp_up_handle_error_indication(
ogs_pfcp_pdr_t *ogs_pfcp_handle_create_pdr(ogs_pfcp_sess_t *sess,
ogs_pfcp_tlv_create_pdr_t *message,
ogs_pfcp_sereq_flags_t *sereq_flags,
uint8_t *cause_value, uint8_t *offending_ie_value)
{
ogs_pfcp_pdr_t *pdr = NULL;
@ -376,6 +377,18 @@ ogs_pfcp_pdr_t *ogs_pfcp_handle_create_pdr(ogs_pfcp_sess_t *sess,
*offending_ie_value = OGS_PFCP_F_TEID_TYPE;
return NULL;
}
if (f_teid.ch == 0) {
if (sereq_flags && sereq_flags->restoration_indication == 1) {
f_teid.teid = be32toh(f_teid.teid);
if (ogs_pfcp_object_find_by_teid(f_teid.teid)) {
ogs_error("TEID:%x had already been allocated", f_teid.teid);
*cause_value = OGS_PFCP_CAUSE_INVALID_F_TEID_ALLOCATION_OPTION;
*offending_ie_value = OGS_PFCP_F_TEID_TYPE;
return NULL;
}
}
}
}
pdr->src_if = message->pdi.source_interface.u8;
@ -398,7 +411,6 @@ ogs_pfcp_pdr_t *ogs_pfcp_handle_create_pdr(ogs_pfcp_sess_t *sess,
if (sdf_filter.bid) {
oppsite_direction_rule = ogs_pfcp_rule_find_by_sdf_filter_id(
sess, sdf_filter.sdf_filter_id);
}
if (!oppsite_direction_rule && !sdf_filter.fd) {

View File

@ -53,6 +53,7 @@ bool ogs_pfcp_up_handle_error_indication(
ogs_pfcp_pdr_t *ogs_pfcp_handle_create_pdr(ogs_pfcp_sess_t *sess,
ogs_pfcp_tlv_create_pdr_t *message,
ogs_pfcp_sereq_flags_t *sereq_flags,
uint8_t *cause_value, uint8_t *offending_ie_value);
ogs_pfcp_pdr_t *ogs_pfcp_handle_created_pdr(ogs_pfcp_sess_t *sess,
ogs_pfcp_tlv_created_pdr_t *message,

View File

@ -20,7 +20,7 @@
/*******************************************************************************
* This file had been created by pfcp-tlv.py script v0.1.0
* Please do not modify this file but regenerate it via script.
* Created on: 2023-03-05 22:26:11.716006 by acetcom
* Created on: 2023-04-09 20:37:00.518388 by acetcom
* from 29244-h71-modified.docx
******************************************************************************/
@ -1546,10 +1546,10 @@ ogs_tlv_desc_t ogs_pfcp_tlv_desc_cp_pfcp_entity_ip_address =
ogs_tlv_desc_t ogs_pfcp_tlv_desc_pfcpsereq_flags =
{
OGS_TLV_VAR_STR,
OGS_TLV_UINT8,
"PFCPSEReq-Flags",
OGS_PFCP_PFCPSEREQ_FLAGS_TYPE,
0,
1,
0,
sizeof(ogs_pfcp_tlv_pfcpsereq_flags_t),
{ NULL }

View File

@ -20,7 +20,7 @@
/*******************************************************************************
* This file had been created by pfcp-tlv.py script v0.1.0
* Please do not modify this file but regenerate it via script.
* Created on: 2023-03-05 22:26:11.698310 by acetcom
* Created on: 2023-04-09 20:37:00.506639 by acetcom
* from 29244-h71-modified.docx
******************************************************************************/
@ -903,7 +903,7 @@ typedef ogs_tlv_uint32_t ogs_pfcp_tlv_quota_validity_time_t;
typedef ogs_tlv_octet_t ogs_pfcp_tlv_number_of_reports_t;
typedef ogs_tlv_octet_t ogs_pfcp_tlv_pfcpasrsp_flags_t;
typedef ogs_tlv_octet_t ogs_pfcp_tlv_cp_pfcp_entity_ip_address_t;
typedef ogs_tlv_octet_t ogs_pfcp_tlv_pfcpsereq_flags_t;
typedef ogs_tlv_uint8_t ogs_pfcp_tlv_pfcpsereq_flags_t;
typedef ogs_tlv_octet_t ogs_pfcp_tlv_ip_multicast_address_t;
typedef ogs_tlv_octet_t ogs_pfcp_tlv_source_ip_address_t;
typedef ogs_tlv_octet_t ogs_pfcp_tlv_packet_rate_status_t;

View File

@ -519,6 +519,7 @@ type_list["Paging Policy Indicator"]["size"] = 1 # Type 158
type_list["PFCPSRReq-Flags"]["size"] = 1 # Type 161
type_list["PFCPAUReq-Flags"]["size"] = 1 # Type 162
type_list["Quota Validity Time"]["size"] = 4 # Type 181
type_list["PFCPSEReq-Flags"]["size"] = 1 # Type 186
type_list["Data Status"]["size"] = 1 # Type 260
f = open(outdir + 'message.h', 'w')

View File

@ -1651,6 +1651,28 @@ int16_t ogs_pfcp_build_user_id(
ogs_tlv_octet_t *octet, ogs_pfcp_user_id_t *user_id,
void *data, int data_len);
/*
* 8.2.136 PFCPSEReq-Flags
*
* The following bits within Octet 5 shall indicate:
* - Bit 1 RESTI (Restoration Indication): if this bit is set to "1",
* it indicates to the UP function that the PFCP session to be established is
* to restore an existing PFCP session.
* - Bit 2 SUMPC (Stop of Usage Measurement to Pause Charging):
* if this bit is set to "1", it indicates that the UP function shall
* stop the usage measurement for all URRs with the "ASPOC" flag set to "1".
*/
typedef struct ogs_pfcp_sereq_flags_s {
union {
struct {
ED3(uint8_t spare:6;,
uint8_t stop_of_usage_measurement_to_pause_charging:1;,
uint8_t restoration_indication:1;)
};
uint8_t value;
};
} __attribute__ ((packed)) ogs_pfcp_sereq_flags_t;
#ifdef __cplusplus
}
#endif

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2019 by Sukchan Lee <acetcom@gmail.com>
* Copyright (C) 2019-2023 by Sukchan Lee <acetcom@gmail.com>
*
* This file is part of Open5GS.
*
@ -35,7 +35,7 @@ typedef struct ogs_pfcp_xact_s {
ogs_lnode_t lnode; /**< A node of list */
ogs_lnode_t tmpnode; /**< A node of temp-list */
ogs_index_t index;
ogs_pool_id_t index;
#define OGS_PFCP_LOCAL_ORIGINATOR 0
#define OGS_PFCP_REMOTE_ORIGINATOR 1
@ -78,6 +78,9 @@ typedef struct ogs_pfcp_xact_s {
bool epc; /**< EPC or 5GC */
#define OGS_PFCP_CREATE_RESTORATION_INDICATION ((uint64_t)1<<0)
uint64_t create_flags;
#define OGS_PFCP_MODIFY_SESSION ((uint64_t)1<<0)
#define OGS_PFCP_MODIFY_DL_ONLY ((uint64_t)1<<1)
#define OGS_PFCP_MODIFY_UL_ONLY ((uint64_t)1<<2)
@ -110,7 +113,6 @@ typedef struct ogs_pfcp_xact_s {
#define OGS_PFCP_MODIFY_URR_TIME_QUOTA ((uint64_t)1<<29)
#define OGS_PFCP_MODIFY_URR_VOLUME_THRESH ((uint64_t)1<<30)
#define OGS_PFCP_MODIFY_URR_TIME_THRESH ((uint64_t)1<<31)
uint64_t modify_flags;
#define OGS_PFCP_DELETE_TRIGGER_LOCAL_INITIATED 1

View File

@ -1,6 +1,6 @@
#!/bin/bash
version=0.10.2
version=0.10.3
display_help() {
echo "open5gs-dbctl: Open5GS Database Configuration Tool ($version)"
@ -24,6 +24,7 @@ display_help() {
echo " showall: shows the list of subscriber in the db"
echo " showpretty: shows the list of subscriber in the db in a pretty json tree format"
echo " showfiltered: shows {imsi key opc apn ip} information of subscriber"
echo " ambr_speed {imsi dl_value dl_unit ul_value ul_unit}: Change AMBR speed from a specific user and the unit values are \"[0=bps 1=Kbps 2=Mbps 3=Gbps 4=Tbps ]\""
}
@ -785,4 +786,44 @@ if [ "$1" = "showfiltered" ]; then
exit $?
fi
if [ "$1" = "ambr_speed" ]; then
if [ "$#" -eq 6 ]; then
IMSI=$2
DL_VALUE=$3
DL_UNIT=$4
UL_VALUE=$5
UL_UNIT=$6
mongosh --eval "db.subscribers.updateOne({\"imsi\": \"$IMSI\"},
{\$set: {
\"ambr\" : {
\"downlink\" : {
\"value\" : NumberInt($DL_VALUE),
\"unit\" : NumberInt($DL_UNIT)
},
\"uplink\" :{
\"value\": NumberInt($UL_VALUE),
\"unit\" : NumberInt($UL_UNIT)
}
},
\"slice.0.session.0.ambr\": {
\"downlink\" : {
\"value\" : NumberInt($DL_VALUE),
\"unit\" : NumberInt($DL_UNIT)
},
\"uplink\" :{
\"value\": NumberInt($UL_VALUE),
\"unit\" : NumberInt($UL_UNIT)
}
}
}
});" $DB_URI
exit $?
fi
echo "open5gs-dbctl: incorrect number of args, format is \"open5gs-dbctl ambr_speed imsi dl_value dl_unit ul_value ul_unit dl is for download and ul is for upload and the unit values are[0=bps 1=Kbps 2=Mbps 3=Gbps 4=Tbps ] \""
exit 1
fi
display_help

View File

@ -29,6 +29,8 @@ static OGS_POOL(amf_ue_pool, amf_ue_t);
static OGS_POOL(ran_ue_pool, ran_ue_t);
static OGS_POOL(amf_sess_pool, amf_sess_t);
static OGS_POOL(m_tmsi_pool, amf_m_tmsi_t);
static int context_initialized = 0;
static int num_of_ran_ue = 0;
@ -60,7 +62,8 @@ void amf_context_init(void)
ogs_pool_init(&amf_ue_pool, ogs_app()->max.ue);
ogs_pool_init(&ran_ue_pool, ogs_app()->max.ue);
ogs_pool_init(&amf_sess_pool, ogs_app()->pool.sess);
ogs_pool_init(&self.m_tmsi, ogs_app()->max.ue*2);
ogs_pool_init(&m_tmsi_pool, ogs_app()->max.ue*2);
ogs_pool_random_id_generate(&m_tmsi_pool);
ogs_list_init(&self.gnb_list);
ogs_list_init(&self.amf_ue_list);
@ -98,7 +101,7 @@ void amf_context_final(void)
ogs_assert(self.supi_hash);
ogs_hash_destroy(self.supi_hash);
ogs_pool_final(&self.m_tmsi);
ogs_pool_final(&m_tmsi_pool);
ogs_pool_final(&amf_sess_pool);
ogs_pool_final(&amf_ue_pool);
ogs_pool_final(&ran_ue_pool);
@ -1697,11 +1700,6 @@ amf_ue_t *amf_ue_find_by_guti(ogs_nas_5gs_guti_t *guti)
self.guti_ue_hash, guti, sizeof(ogs_nas_5gs_guti_t));
}
amf_ue_t *amf_ue_find_by_teid(uint32_t teid)
{
return ogs_pool_find(&amf_ue_pool, teid);
}
amf_ue_t *amf_ue_find_by_suci(char *suci)
{
ogs_assert(suci);
@ -2368,6 +2366,7 @@ ogs_s_nssai_t *amf_find_s_nssai(
return NULL;
}
#if 0 /* DEPRECATED */
int amf_m_tmsi_pool_generate(void)
{
int j;
@ -2378,7 +2377,7 @@ int amf_m_tmsi_pool_generate(void)
amf_m_tmsi_t *m_tmsi = NULL;
int conflict = 0;
m_tmsi = &self.m_tmsi.array[index];
m_tmsi = &m_tmsi_pool.array[index];
ogs_assert(m_tmsi);
*m_tmsi = ogs_random32();
@ -2387,10 +2386,10 @@ int amf_m_tmsi_pool_generate(void)
*m_tmsi &= 0xff00ffff;
for (j = 0; j < index; j++) {
if (*m_tmsi == self.m_tmsi.array[j]) {
if (*m_tmsi == m_tmsi_pool.array[j]) {
conflict = 1;
ogs_trace("[M-TMSI CONFLICT] %d:0x%x == %d:0x%x",
index, *m_tmsi, j, self.m_tmsi.array[j]);
index, *m_tmsi, j, m_tmsi_pool.array[j]);
break;
}
}
@ -2400,26 +2399,48 @@ int amf_m_tmsi_pool_generate(void)
index++;
}
self.m_tmsi.size = index;
m_tmsi_pool.size = index;
ogs_trace("M-TMSI Pool generate...done");
return OGS_OK;
}
#endif
amf_m_tmsi_t *amf_m_tmsi_alloc(void)
{
amf_m_tmsi_t *m_tmsi = NULL;
ogs_pool_alloc(&self.m_tmsi, &m_tmsi);
ogs_pool_alloc(&m_tmsi_pool, &m_tmsi);
ogs_assert(m_tmsi);
/* TS23.003
* 2.8.2.1.2 Mapping in the UE
*
* E-UTRAN <M-TMSI> maps as follows:
* - 6 bits of the E-UTRAN <M-TMSI> starting at bit 29 and down to bit 24
* are mapped into bit 29 and down to bit 24 of the GERAN/UTRAN <P-TMSI>;
* - 16 bits of the E-UTRAN <M-TMSI> starting at bit 15 and down to bit 0
* are mapped into bit 15 and down to bit 0 of the GERAN/UTRAN <P-TMSI>;
* - and the remaining 8 bits of the E-UTRAN <M-TMSI> are
* mapped into the 8 Most Significant Bits of the <P-TMSI signature> field.
*
* The UE shall fill the remaining 2 octets of the <P-TMSI signature>
* according to clauses 9.1.1, 9.4.1, 10.2.1, or 10.5.1
* of 3GPP TS.33.401 [89] , as appropriate, for RAU/Attach procedures
*/
ogs_assert(*m_tmsi <= 0x003fffff);
*m_tmsi = ((*m_tmsi & 0xffff) | ((*m_tmsi & 0x003f0000) << 8));
*m_tmsi |= 0xc0000000;
return m_tmsi;
}
int amf_m_tmsi_free(amf_m_tmsi_t *m_tmsi)
{
ogs_assert(m_tmsi);
ogs_pool_free(&self.m_tmsi, m_tmsi);
ogs_pool_free(&m_tmsi_pool, m_tmsi);
return OGS_OK;
}

View File

@ -111,8 +111,6 @@ typedef struct amf_context_s {
ogs_hash_t *suci_hash; /* hash table (SUCI) */
ogs_hash_t *supi_hash; /* hash table (SUPI) */
OGS_POOL(m_tmsi, amf_m_tmsi_t); /* M-TMSI Pool */
uint16_t ngap_port; /* Default NGAP Port */
ogs_list_t ngap_list; /* AMF NGAP IPv4 Server List */
@ -697,7 +695,6 @@ void amf_ue_fsm_init(amf_ue_t *amf_ue);
void amf_ue_fsm_fini(amf_ue_t *amf_ue);
amf_ue_t *amf_ue_find_by_guti(ogs_nas_5gs_guti_t *nas_guti);
amf_ue_t *amf_ue_find_by_teid(uint32_t teid);
amf_ue_t *amf_ue_find_by_suci(char *suci);
amf_ue_t *amf_ue_find_by_supi(char *supi);
@ -823,7 +820,6 @@ int amf_find_served_tai(ogs_5gs_tai_t *nr_tai);
ogs_s_nssai_t *amf_find_s_nssai(
ogs_plmn_id_t *served_plmn_id, ogs_s_nssai_t *s_nssai);
int amf_m_tmsi_pool_generate(void);
amf_m_tmsi_t *amf_m_tmsi_alloc(void);
int amf_m_tmsi_free(amf_m_tmsi_t *tmsi);

View File

@ -46,9 +46,6 @@ int amf_initialize(void)
rv = amf_context_nf_info();
if (rv != OGS_OK) return rv;
rv = amf_m_tmsi_pool_generate();
if (rv != OGS_OK) return rv;
rv = ogs_log_config_domain(
ogs_app()->logger.domain, ogs_app()->logger.level);
if (rv != OGS_OK) return rv;

View File

@ -44,11 +44,14 @@ static OGS_POOL(mme_csmap_pool, mme_csmap_t);
static OGS_POOL(mme_enb_pool, mme_enb_t);
static OGS_POOL(mme_ue_pool, mme_ue_t);
static OGS_POOL(mme_s11_teid_pool, ogs_pool_id_t);
static OGS_POOL(enb_ue_pool, enb_ue_t);
static OGS_POOL(sgw_ue_pool, sgw_ue_t);
static OGS_POOL(mme_sess_pool, mme_sess_t);
static OGS_POOL(mme_bearer_pool, mme_bearer_t);
static OGS_POOL(m_tmsi_pool, mme_m_tmsi_t);
static int context_initialized = 0;
static int num_of_enb_ue = 0;
@ -100,11 +103,15 @@ void mme_context_init(void)
ogs_pool_init(&mme_enb_pool, ogs_app()->max.peer*2);
ogs_pool_init(&mme_ue_pool, ogs_app()->max.ue);
ogs_pool_init(&mme_s11_teid_pool, ogs_app()->max.ue);
ogs_pool_random_id_generate(&mme_s11_teid_pool);
ogs_pool_init(&enb_ue_pool, ogs_app()->max.ue);
ogs_pool_init(&sgw_ue_pool, ogs_app()->max.ue);
ogs_pool_init(&mme_sess_pool, ogs_app()->pool.sess);
ogs_pool_init(&mme_bearer_pool, ogs_app()->pool.bearer);
ogs_pool_init(&self.m_tmsi, ogs_app()->max.ue*2);
ogs_pool_init(&m_tmsi_pool, ogs_app()->max.ue*2);
ogs_pool_random_id_generate(&m_tmsi_pool);
self.enb_addr_hash = ogs_hash_make();
ogs_assert(self.enb_addr_hash);
@ -114,6 +121,8 @@ void mme_context_init(void)
ogs_assert(self.imsi_ue_hash);
self.guti_ue_hash = ogs_hash_make();
ogs_assert(self.guti_ue_hash);
self.mme_s11_teid_hash = ogs_hash_make();
ogs_assert(self.mme_s11_teid_hash);
ogs_list_init(&self.mme_ue_list);
@ -141,11 +150,14 @@ void mme_context_final(void)
ogs_hash_destroy(self.imsi_ue_hash);
ogs_assert(self.guti_ue_hash);
ogs_hash_destroy(self.guti_ue_hash);
ogs_assert(self.mme_s11_teid_hash);
ogs_hash_destroy(self.mme_s11_teid_hash);
ogs_pool_final(&self.m_tmsi);
ogs_pool_final(&m_tmsi_pool);
ogs_pool_final(&mme_bearer_pool);
ogs_pool_final(&mme_sess_pool);
ogs_pool_final(&mme_ue_pool);
ogs_pool_final(&mme_s11_teid_pool);
ogs_pool_final(&enb_ue_pool);
ogs_pool_final(&sgw_ue_pool);
@ -2327,11 +2339,6 @@ void sgw_ue_switch_to_sgw(sgw_ue_t *sgw_ue, mme_sgw_t *new_sgw)
sgw_ue->sgw = new_sgw;
}
sgw_ue_t *sgw_ue_find(uint32_t index)
{
return ogs_pool_find(&sgw_ue_pool, index);
}
sgw_ue_t *sgw_ue_cycle(sgw_ue_t *sgw_ue)
{
return ogs_pool_cycle(&sgw_ue_pool, sgw_ue);
@ -2564,9 +2571,14 @@ mme_ue_t *mme_ue_add(enb_ue_t *enb_ue)
ogs_list_init(&mme_ue->sess_list);
mme_ue->mme_s11_teid = ogs_pool_index(&mme_ue_pool, mme_ue);
ogs_assert(mme_ue->mme_s11_teid > 0 &&
mme_ue->mme_s11_teid <= ogs_app()->max.ue);
/* Set MME-S11_TEID */
ogs_pool_alloc(&mme_s11_teid_pool, &mme_ue->mme_s11_teid_node);
ogs_assert(mme_ue->mme_s11_teid_node);
mme_ue->mme_s11_teid = *(mme_ue->mme_s11_teid_node);
ogs_hash_set(self.mme_s11_teid_hash,
&mme_ue->mme_s11_teid, sizeof(mme_ue->mme_s11_teid), mme_ue);
/*
* When used for the first time, if last node is set,
@ -2609,6 +2621,9 @@ void mme_ue_remove(mme_ue_t *mme_ue)
mme_ue_fsm_fini(mme_ue);
ogs_hash_set(self.mme_s11_teid_hash,
&mme_ue->mme_s11_teid, sizeof(mme_ue->mme_s11_teid), NULL);
ogs_assert(mme_ue->sgw_ue);
sgw_ue_remove(mme_ue->sgw_ue);
@ -2654,6 +2669,7 @@ void mme_ue_remove(mme_ue_t *mme_ue)
mme_ebi_pool_final(mme_ue);
ogs_pool_free(&mme_s11_teid_pool, mme_ue->mme_s11_teid_node);
ogs_pool_free(&mme_ue_pool, mme_ue);
ogs_info("[Removed] Number of MME-UEs is now %d",
@ -2729,7 +2745,7 @@ mme_ue_t *mme_ue_find_by_guti(ogs_nas_eps_guti_t *guti)
mme_ue_t *mme_ue_find_by_teid(uint32_t teid)
{
return ogs_pool_find(&mme_ue_pool, teid);
return ogs_hash_get(self.mme_s11_teid_hash, &teid, sizeof(teid));
}
mme_ue_t *mme_ue_find_by_message(ogs_nas_eps_message_t *message)
@ -3743,6 +3759,7 @@ int mme_find_served_tai(ogs_eps_tai_t *tai)
return -1;
}
#if 0 /* DEPRECATED */
int mme_m_tmsi_pool_generate(void)
{
int j;
@ -3753,7 +3770,7 @@ int mme_m_tmsi_pool_generate(void)
mme_m_tmsi_t *m_tmsi = NULL;
int conflict = 0;
m_tmsi = &self.m_tmsi.array[index];
m_tmsi = &m_tmsi_pool.array[index];
ogs_assert(m_tmsi);
*m_tmsi = ogs_random32();
@ -3762,10 +3779,10 @@ int mme_m_tmsi_pool_generate(void)
*m_tmsi &= 0xff00ffff;
for (j = 0; j < index; j++) {
if (*m_tmsi == self.m_tmsi.array[j]) {
if (*m_tmsi == m_tmsi_pool.array[j]) {
conflict = 1;
ogs_trace("[M-TMSI CONFLICT] %d:0x%x == %d:0x%x",
index, *m_tmsi, j, self.m_tmsi.array[j]);
index, *m_tmsi, j, m_tmsi_pool.array[j]);
break;
}
}
@ -3775,26 +3792,48 @@ int mme_m_tmsi_pool_generate(void)
index++;
}
self.m_tmsi.size = index;
m_tmsi_pool.size = index;
ogs_trace("M-TMSI Pool generate...done");
return OGS_OK;
}
#endif
mme_m_tmsi_t *mme_m_tmsi_alloc(void)
{
mme_m_tmsi_t *m_tmsi = NULL;
ogs_pool_alloc(&self.m_tmsi, &m_tmsi);
ogs_pool_alloc(&m_tmsi_pool, &m_tmsi);
ogs_assert(m_tmsi);
/* TS23.003
* 2.8.2.1.2 Mapping in the UE
*
* E-UTRAN <M-TMSI> maps as follows:
* - 6 bits of the E-UTRAN <M-TMSI> starting at bit 29 and down to bit 24
* are mapped into bit 29 and down to bit 24 of the GERAN/UTRAN <P-TMSI>;
* - 16 bits of the E-UTRAN <M-TMSI> starting at bit 15 and down to bit 0
* are mapped into bit 15 and down to bit 0 of the GERAN/UTRAN <P-TMSI>;
* - and the remaining 8 bits of the E-UTRAN <M-TMSI> are
* mapped into the 8 Most Significant Bits of the <P-TMSI signature> field.
*
* The UE shall fill the remaining 2 octets of the <P-TMSI signature>
* according to clauses 9.1.1, 9.4.1, 10.2.1, or 10.5.1
* of 3GPP TS.33.401 [89] , as appropriate, for RAU/Attach procedures
*/
ogs_assert(*m_tmsi <= 0x003fffff);
*m_tmsi = ((*m_tmsi & 0xffff) | ((*m_tmsi & 0x003f0000) << 8));
*m_tmsi |= 0xc0000000;
return m_tmsi;
}
int mme_m_tmsi_free(mme_m_tmsi_t *m_tmsi)
{
ogs_assert(m_tmsi);
ogs_pool_free(&self.m_tmsi, m_tmsi);
ogs_pool_free(&m_tmsi_pool, m_tmsi);
return OGS_OK;
}
@ -3805,7 +3844,7 @@ void mme_ebi_pool_init(mme_ue_t *mme_ue)
ogs_assert(mme_ue);
ogs_index_init(&mme_ue->ebi_pool, MAX_EPS_BEARER_ID-MIN_EPS_BEARER_ID+1);
ogs_pool_init(&mme_ue->ebi_pool, MAX_EPS_BEARER_ID-MIN_EPS_BEARER_ID+1);
for (i = MIN_EPS_BEARER_ID, index = 0;
i <= MAX_EPS_BEARER_ID; i++, index++) {
@ -3817,17 +3856,17 @@ void mme_ebi_pool_final(mme_ue_t *mme_ue)
{
ogs_assert(mme_ue);
ogs_index_final(&mme_ue->ebi_pool);
ogs_pool_final(&mme_ue->ebi_pool);
}
void mme_ebi_pool_clear(mme_ue_t *mme_ue)
{
ogs_assert(mme_ue);
ogs_free(mme_ue->ebi_pool.free);
ogs_free(mme_ue->ebi_pool.array);
ogs_free(mme_ue->ebi_pool.index);
/* Suppress log message (mme_ue->ebi_pool.avail != mme_ue->ebi_pool.size) */
mme_ue->ebi_pool.avail = mme_ue->ebi_pool.size;
mme_ebi_pool_final(mme_ue);
mme_ebi_pool_init(mme_ue);
}

View File

@ -145,15 +145,14 @@ typedef struct mme_context_s {
/* Generator for unique identification */
uint32_t mme_ue_s1ap_id; /* mme_ue_s1ap_id generator */
/* M-TMSI Pool */
OGS_POOL(m_tmsi, mme_m_tmsi_t);
ogs_list_t mme_ue_list;
ogs_hash_t *enb_addr_hash; /* hash table for ENB Address */
ogs_hash_t *enb_id_hash; /* hash table for ENB-ID */
ogs_hash_t *imsi_ue_hash; /* hash table (IMSI : MME_UE) */
ogs_hash_t *guti_ue_hash; /* hash table (GUTI : MME_UE) */
ogs_hash_t *enb_addr_hash; /* hash table for ENB Address */
ogs_hash_t *enb_id_hash; /* hash table for ENB-ID */
ogs_hash_t *imsi_ue_hash; /* hash table (IMSI : MME_UE) */
ogs_hash_t *guti_ue_hash; /* hash table (GUTI : MME_UE) */
ogs_hash_t *mme_s11_teid_hash; /* hash table (MME-S11-TEID : MME_UE) */
struct {
struct {
@ -286,7 +285,6 @@ struct enb_ue_s {
struct sgw_ue_s {
ogs_lnode_t lnode;
uint32_t index;
sgw_ue_t *source_ue;
sgw_ue_t *target_ue;
@ -371,7 +369,8 @@ struct mme_ue_s {
ogs_nas_eps_guti_t guti;
} current, next;
uint32_t mme_s11_teid; /* MME-S11-TEID is derived from INDEX */
ogs_pool_id_t *mme_s11_teid_node; /* A node of MME-S11-TEID */
uint32_t mme_s11_teid; /* MME-S11-TEID is derived from NODE */
uint16_t vlr_ostream_id; /* SCTP output stream id for VLR */
@ -685,7 +684,6 @@ typedef struct mme_bearer_s {
ogs_lnode_t lnode;
ogs_lnode_t to_modify_node;
uint32_t index;
ogs_fsm_t sm; /* State Machine */
uint8_t *ebi_node; /* Pool-Node for EPS Bearer ID */
@ -794,7 +792,6 @@ enb_ue_t *enb_ue_cycle(enb_ue_t *enb_ue);
sgw_ue_t *sgw_ue_add(mme_sgw_t *sgw);
void sgw_ue_remove(sgw_ue_t *sgw_ue);
void sgw_ue_switch_to_sgw(sgw_ue_t *sgw_ue, mme_sgw_t *new_sgw);
sgw_ue_t *sgw_ue_find(uint32_t index);
sgw_ue_t *sgw_ue_cycle(sgw_ue_t *sgw_ue);
typedef enum {
@ -923,7 +920,6 @@ ogs_session_t *mme_default_session(mme_ue_t *mme_ue);
int mme_find_served_tai(ogs_eps_tai_t *tai);
int mme_m_tmsi_pool_generate(void);
mme_m_tmsi_t *mme_m_tmsi_alloc(void);
int mme_m_tmsi_free(mme_m_tmsi_t *tmsi);

View File

@ -61,9 +61,6 @@ int mme_initialize(void)
ogs_app()->logger.domain, ogs_app()->logger.level);
if (rv != OGS_OK) return rv;
rv = mme_m_tmsi_pool_generate();
if (rv != OGS_OK) return rv;
ogs_metrics_context_open(ogs_metrics_self());
rv = mme_fd_init();

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2019 by Sukchan Lee <acetcom@gmail.com>
* Copyright (C) 2019-2023 by Sukchan Lee <acetcom@gmail.com>
*
* This file is part of Open5GS.
*
@ -25,11 +25,15 @@ static sgwc_context_t self;
int __sgwc_log_domain;
static OGS_POOL(sgwc_ue_pool, sgwc_ue_t);
static OGS_POOL(sgwc_sess_pool, sgwc_sess_t);
static OGS_POOL(sgwc_bearer_pool, sgwc_bearer_t);
static OGS_POOL(sgwc_tunnel_pool, sgwc_tunnel_t);
static OGS_POOL(sgwc_ue_pool, sgwc_ue_t);
static OGS_POOL(sgwc_s11_teid_pool, ogs_pool_id_t);
static OGS_POOL(sgwc_sess_pool, sgwc_sess_t);
static OGS_POOL(sgwc_sxa_seid_pool, ogs_pool_id_t);
static int context_initialized = 0;
static int num_of_sgwc_sess = 0;
@ -45,13 +49,23 @@ void sgwc_context_init(void)
ogs_log_install_domain(&__sgwc_log_domain, "sgwc", ogs_core()->log.level);
ogs_pool_init(&sgwc_ue_pool, ogs_app()->max.ue);
ogs_pool_init(&sgwc_sess_pool, ogs_app()->pool.sess);
ogs_pool_init(&sgwc_bearer_pool, ogs_app()->pool.bearer);
ogs_pool_init(&sgwc_tunnel_pool, ogs_app()->pool.tunnel);
ogs_pool_init(&sgwc_ue_pool, ogs_app()->max.ue);
ogs_pool_init(&sgwc_s11_teid_pool, ogs_app()->max.ue);
ogs_pool_random_id_generate(&sgwc_s11_teid_pool);
ogs_pool_init(&sgwc_sess_pool, ogs_app()->pool.sess);
ogs_pool_init(&sgwc_sxa_seid_pool, ogs_app()->pool.sess);
ogs_pool_random_id_generate(&sgwc_sxa_seid_pool);
self.imsi_ue_hash = ogs_hash_make();
ogs_assert(self.imsi_ue_hash);
self.sgw_s11_teid_hash = ogs_hash_make();
ogs_assert(self.sgw_s11_teid_hash);
self.sgwc_sxa_seid_hash = ogs_hash_make();
ogs_assert(self.sgwc_sxa_seid_hash);
ogs_list_init(&self.sgw_ue_list);
@ -66,11 +80,19 @@ void sgwc_context_final(void)
ogs_assert(self.imsi_ue_hash);
ogs_hash_destroy(self.imsi_ue_hash);
ogs_assert(self.sgw_s11_teid_hash);
ogs_hash_destroy(self.sgw_s11_teid_hash);
ogs_assert(self.sgwc_sxa_seid_hash);
ogs_hash_destroy(self.sgwc_sxa_seid_hash);
ogs_pool_final(&sgwc_tunnel_pool);
ogs_pool_final(&sgwc_bearer_pool);
ogs_pool_final(&sgwc_sess_pool);
ogs_pool_final(&sgwc_ue_pool);
ogs_pool_final(&sgwc_s11_teid_pool);
ogs_pool_final(&sgwc_sess_pool);
ogs_pool_final(&sgwc_sxa_seid_pool);
ogs_gtp_node_remove_all(&self.mme_s11_list);
ogs_gtp_node_remove_all(&self.pgw_s5c_list);
@ -192,9 +214,14 @@ sgwc_ue_t *sgwc_ue_add(uint8_t *imsi, int imsi_len)
ogs_assert(sgwc_ue);
memset(sgwc_ue, 0, sizeof *sgwc_ue);
sgwc_ue->sgw_s11_teid = ogs_pool_index(&sgwc_ue_pool, sgwc_ue);
ogs_assert(sgwc_ue->sgw_s11_teid > 0 &&
sgwc_ue->sgw_s11_teid <= ogs_app()->max.ue);
/* Set SGW-S11-TEID */
ogs_pool_alloc(&sgwc_s11_teid_pool, &sgwc_ue->sgw_s11_teid_node);
ogs_assert(sgwc_ue->sgw_s11_teid_node);
sgwc_ue->sgw_s11_teid = *(sgwc_ue->sgw_s11_teid_node);
ogs_hash_set(self.sgw_s11_teid_hash,
&sgwc_ue->sgw_s11_teid, sizeof(sgwc_ue->sgw_s11_teid), sgwc_ue);
/* Set IMSI */
sgwc_ue->imsi_len = imsi_len;
@ -219,10 +246,13 @@ int sgwc_ue_remove(sgwc_ue_t *sgwc_ue)
ogs_list_remove(&self.sgw_ue_list, sgwc_ue);
ogs_hash_set(self.sgw_s11_teid_hash,
&sgwc_ue->sgw_s11_teid, sizeof(sgwc_ue->sgw_s11_teid), NULL);
ogs_hash_set(self.imsi_ue_hash, sgwc_ue->imsi, sgwc_ue->imsi_len, NULL);
sgwc_sess_remove_all(sgwc_ue);
ogs_pool_free(&sgwc_s11_teid_pool, sgwc_ue->sgw_s11_teid_node);
ogs_pool_free(&sgwc_ue_pool, sgwc_ue);
ogs_info("[Removed] Number of SGWC-UEs is now %d",
@ -255,12 +285,12 @@ sgwc_ue_t *sgwc_ue_find_by_imsi(uint8_t *imsi, int imsi_len)
{
ogs_assert(imsi && imsi_len);
return (sgwc_ue_t *)ogs_hash_get(self.imsi_ue_hash, imsi, imsi_len);
return ogs_hash_get(self.imsi_ue_hash, imsi, imsi_len);
}
sgwc_ue_t *sgwc_ue_find_by_teid(uint32_t teid)
{
return ogs_pool_find(&sgwc_ue_pool, teid);
return ogs_hash_get(self.sgw_s11_teid_hash, &teid, sizeof(teid));
}
sgwc_sess_t *sgwc_sess_add(sgwc_ue_t *sgwc_ue, char *apn)
@ -279,12 +309,15 @@ sgwc_sess_t *sgwc_sess_add(sgwc_ue_t *sgwc_ue, char *apn)
ogs_pfcp_pool_init(&sess->pfcp);
sess->index = ogs_pool_index(&sgwc_sess_pool, sess);
ogs_assert(sess->index > 0 && sess->index <= ogs_app()->pool.sess);
/* Set TEID & SEID */
sess->sgw_s5c_teid = sess->index;
sess->sgwc_sxa_seid = sess->index;
ogs_pool_alloc(&sgwc_sxa_seid_pool, &sess->sgwc_sxa_seid_node);
ogs_assert(sess->sgwc_sxa_seid_node);
sess->sgw_s5c_teid = *(sess->sgwc_sxa_seid_node);
sess->sgwc_sxa_seid = *(sess->sgwc_sxa_seid_node);
ogs_hash_set(self.sgwc_sxa_seid_hash,
&sess->sgwc_sxa_seid, sizeof(sess->sgwc_sxa_seid), sess);
/* Create BAR in PFCP Session */
ogs_pfcp_bar_new(&sess->pfcp);
@ -400,6 +433,9 @@ int sgwc_sess_remove(sgwc_sess_t *sess)
ogs_list_remove(&sgwc_ue->sess_list, sess);
ogs_hash_set(self.sgwc_sxa_seid_hash, &sess->sgwc_sxa_seid,
sizeof(sess->sgwc_sxa_seid), NULL);
sgwc_bearer_remove_all(sess);
ogs_assert(sess->pfcp.bar);
@ -410,6 +446,7 @@ int sgwc_sess_remove(sgwc_sess_t *sess)
ogs_assert(sess->session.name);
ogs_free(sess->session.name);
ogs_pool_free(&sgwc_sxa_seid_pool, sess->sgwc_sxa_seid_node);
ogs_pool_free(&sgwc_sess_pool, sess);
stats_remove_sgwc_session();
@ -426,19 +463,14 @@ void sgwc_sess_remove_all(sgwc_ue_t *sgwc_ue)
sgwc_sess_remove(sess);
}
sgwc_sess_t *sgwc_sess_find(uint32_t index)
{
return ogs_pool_find(&sgwc_sess_pool, index);
}
sgwc_sess_t* sgwc_sess_find_by_teid(uint32_t teid)
{
return ogs_pool_find(&sgwc_sess_pool, teid);
return sgwc_sess_find_by_seid(teid);
}
sgwc_sess_t *sgwc_sess_find_by_seid(uint64_t seid)
{
return sgwc_sess_find(seid);
return ogs_hash_get(self.sgwc_sxa_seid_hash, &seid, sizeof(seid));
}
sgwc_sess_t* sgwc_sess_find_by_apn(sgwc_ue_t *sgwc_ue, char *apn)
@ -578,71 +610,6 @@ sgwc_bearer_t *sgwc_bearer_find_by_ue_ebi(sgwc_ue_t *sgwc_ue, uint8_t ebi)
return NULL;
}
sgwc_bearer_t *sgwc_bearer_find_by_error_indication_report(
sgwc_sess_t *sess,
ogs_pfcp_tlv_error_indication_report_t *error_indication_report)
{
ogs_pfcp_f_teid_t *remote_f_teid = NULL;
sgwc_bearer_t *bearer = NULL;
sgwc_tunnel_t *tunnel = NULL;
uint32_t teid;
uint16_t len; /* OGS_IPV4_LEN or OGS_IPV6_LEN */
uint32_t addr[4];
ogs_assert(sess);
ogs_assert(error_indication_report);
if (error_indication_report->presence == 0) {
ogs_error("No Error Indication Report");
return NULL;
}
if (error_indication_report->remote_f_teid.presence == 0) {
ogs_error("No Remote F-TEID");
return NULL;
}
remote_f_teid = error_indication_report->remote_f_teid.data;
ogs_assert(remote_f_teid);
teid = be32toh(remote_f_teid->teid);
if (remote_f_teid->ipv4 && remote_f_teid->ipv6) {
ogs_error("User plane should not set both IPv4 and IPv6");
return NULL;
} else if (remote_f_teid->ipv4) {
len = OGS_IPV4_LEN;
memcpy(addr, &remote_f_teid->addr, len);
} else if (remote_f_teid->ipv6) {
len = OGS_IPV6_LEN;
memcpy(addr, remote_f_teid->addr6, len);
} else {
ogs_error("No IPv4 and IPv6");
return NULL;
}
ogs_list_for_each(&sess->bearer_list, bearer) {
ogs_list_for_each(&bearer->tunnel_list, tunnel) {
if (teid == tunnel->remote_teid) {
if (len == OGS_IPV4_LEN && tunnel->remote_ip.ipv4 &&
memcmp(addr, &tunnel->remote_ip.addr, len) == 0) {
return bearer;
} else if (len == OGS_IPV6_LEN && tunnel->remote_ip.ipv6 &&
memcmp(addr, tunnel->remote_ip.addr6, len) == 0) {
return bearer;
}
}
}
}
ogs_error("Cannot find the bearer context "
"[TEID:%d,LEN:%d,ADDR:%08x %08x %08x %08x]",
teid, len, be32toh(addr[0]), be32toh(addr[1]),
be32toh(addr[2]), be32toh(addr[3]));
return NULL;
}
sgwc_bearer_t *sgwc_default_bearer_in_sess(sgwc_sess_t *sess)
{
ogs_assert(sess);
@ -690,6 +657,7 @@ sgwc_tunnel_t *sgwc_tunnel_add(
break;
default:
ogs_fatal("Invalid interface type = %d", interface_type);
ogs_assert_if_reached();
}
ogs_pool_alloc(&sgwc_tunnel_pool, &tunnel);
@ -697,8 +665,6 @@ sgwc_tunnel_t *sgwc_tunnel_add(
memset(tunnel, 0, sizeof *tunnel);
tunnel->interface_type = interface_type;
tunnel->index = ogs_pool_index(&sgwc_tunnel_pool, tunnel);
ogs_assert(tunnel->index > 0 && tunnel->index <= ogs_app()->pool.tunnel);
pdr = ogs_pfcp_pdr_add(&sess->pfcp);
ogs_assert(pdr);
@ -753,10 +719,10 @@ sgwc_tunnel_t *sgwc_tunnel_add(
&tunnel->local_addr, &tunnel->local_addr6);
if (resource->info.teidri)
tunnel->local_teid = OGS_PFCP_GTPU_INDEX_TO_TEID(
pdr->index, resource->info.teidri,
pdr->teid, resource->info.teidri,
resource->info.teid_range);
else
tunnel->local_teid = pdr->index;
tunnel->local_teid = pdr->teid;
} else {
if (sess->pfcp_node->addr.ogs_sa_family == AF_INET)
ogs_assert(OGS_OK ==
@ -769,7 +735,7 @@ sgwc_tunnel_t *sgwc_tunnel_add(
else
ogs_assert_if_reached();
tunnel->local_teid = pdr->index;
tunnel->local_teid = pdr->teid;
}
ogs_assert(OGS_OK ==
@ -872,6 +838,28 @@ sgwc_tunnel_t *sgwc_tunnel_find_by_pdr_id(
return NULL;
}
sgwc_tunnel_t *sgwc_tunnel_find_by_far_id(
sgwc_sess_t *sess, ogs_pfcp_far_id_t far_id)
{
sgwc_bearer_t *bearer = NULL;
sgwc_tunnel_t *tunnel = NULL;
ogs_pfcp_far_t *far = NULL;
ogs_assert(sess);
ogs_list_for_each(&sess->bearer_list, bearer) {
ogs_list_for_each(&bearer->tunnel_list, tunnel) {
far = tunnel->far;
ogs_assert(far);
if (far->id == far_id) return tunnel;
}
}
return NULL;
}
sgwc_tunnel_t *sgwc_dl_tunnel_in_bearer(sgwc_bearer_t *bearer)
{
ogs_assert(bearer);

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2019 by Sukchan Lee <acetcom@gmail.com>
* Copyright (C) 2019-2023 by Sukchan Lee <acetcom@gmail.com>
*
* This file is part of Open5GS.
*
@ -39,18 +39,21 @@ extern int __sgwc_log_domain;
typedef struct sgwc_tunnel_s sgwc_tunnel_t;
typedef struct sgwc_context_s {
ogs_list_t mme_s11_list; /* MME GTPC Node List */
ogs_list_t pgw_s5c_list; /* PGW GTPC Node List */
ogs_list_t mme_s11_list; /* MME GTPC Node List */
ogs_list_t pgw_s5c_list; /* PGW GTPC Node List */
ogs_hash_t *imsi_ue_hash; /* hash table (IMSI : SGW_UE) */
ogs_hash_t *imsi_ue_hash; /* hash table (IMSI : SGW_UE) */
ogs_hash_t *sgw_s11_teid_hash; /* hash table (SGW-S11-TEID : SGW_UE) */
ogs_hash_t *sgwc_sxa_seid_hash; /* hash table (SGWC-SXA-SEID : Session) */
ogs_list_t sgw_ue_list; /* SGW_UE List */
ogs_list_t sgw_ue_list; /* SGW_UE List */
} sgwc_context_t;
typedef struct sgwc_ue_s {
ogs_lnode_t lnode;
ogs_pool_id_t *sgw_s11_teid_node; /* A node of SGW-S11-TEID */
uint32_t sgw_s11_teid; /* SGW-S11-TEID is derived from INDEX */
uint32_t sgw_s11_teid; /* SGW-S11-TEID is derived from NODE */
uint32_t mme_s11_teid; /* MME-S11-TEID is received from MME */
/* UE identity */
@ -70,15 +73,15 @@ typedef struct sgwc_ue_s {
#define SGWC_SESS(pfcp_sess) ogs_container_of(pfcp_sess, sgwc_sess_t, pfcp)
typedef struct sgwc_sess_s {
ogs_lnode_t lnode; /* A node of list_t */
uint32_t index; /**< An index of this node */
ogs_lnode_t lnode; /* A node of list_t */
ogs_pool_id_t *sgwc_sxa_seid_node; /* A node of SGWC-SXA-SEID */
ogs_pfcp_sess_t pfcp; /* PFCP session context */
uint32_t sgw_s5c_teid; /* SGW-S5C-TEID is derived from INDEX */
uint32_t sgw_s5c_teid; /* SGW-S5C-TEID is derived from NODE */
uint32_t pgw_s5c_teid; /* PGW-S5C-TEID is received from PGW */
uint64_t sgwc_sxa_seid; /* SGW-C SEID is dervied from INDEX */
uint64_t sgwc_sxa_seid; /* SGW-C SEID is dervied from NODE */
uint64_t sgwu_sxa_seid; /* SGW-U SEID is received from Peer */
/* APN Configuration */
@ -106,7 +109,6 @@ typedef struct sgwc_bearer_s {
typedef struct sgwc_tunnel_s {
ogs_lnode_t lnode;
uint32_t index; /**< An index of this node */
uint8_t interface_type;
@ -147,7 +149,6 @@ void sgwc_sess_select_sgwu(sgwc_sess_t *sess);
int sgwc_sess_remove(sgwc_sess_t *sess);
void sgwc_sess_remove_all(sgwc_ue_t *sgwc_ue);
sgwc_sess_t *sgwc_sess_find(uint32_t index);
sgwc_sess_t *sgwc_sess_find_by_teid(uint32_t teid);
sgwc_sess_t *sgwc_sess_find_by_seid(uint64_t seid);
@ -167,9 +168,6 @@ sgwc_bearer_t *sgwc_bearer_find_by_sess_ebi(
sgwc_sess_t *sess, uint8_t ebi);
sgwc_bearer_t *sgwc_bearer_find_by_ue_ebi(
sgwc_ue_t *sgwc_ue, uint8_t ebi);
sgwc_bearer_t *sgwc_bearer_find_by_error_indication_report(
sgwc_sess_t *sess,
ogs_pfcp_tlv_error_indication_report_t *error_indication_report);
sgwc_bearer_t *sgwc_default_bearer_in_sess(sgwc_sess_t *sess);
sgwc_bearer_t *sgwc_bearer_cycle(sgwc_bearer_t *bearer);
@ -182,6 +180,8 @@ sgwc_tunnel_t *sgwc_tunnel_find_by_interface_type(
sgwc_bearer_t *bearer, uint8_t interface_type);
sgwc_tunnel_t *sgwc_tunnel_find_by_pdr_id(
sgwc_sess_t *sess, ogs_pfcp_pdr_id_t pdr_id);
sgwc_tunnel_t *sgwc_tunnel_find_by_far_id(
sgwc_sess_t *sess, ogs_pfcp_far_id_t far_id);
sgwc_tunnel_t *sgwc_dl_tunnel_in_bearer(sgwc_bearer_t *bearer);
sgwc_tunnel_t *sgwc_ul_tunnel_in_bearer(sgwc_bearer_t *bearer);

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2019 by Sukchan Lee <acetcom@gmail.com>
* Copyright (C) 2019-2023 by Sukchan Lee <acetcom@gmail.com>
*
* This file is part of Open5GS.
*

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2019 by Sukchan Lee <acetcom@gmail.com>
* Copyright (C) 2019-2023 by Sukchan Lee <acetcom@gmail.com>
*
* This file is part of Open5GS.
*
@ -238,7 +238,8 @@ int sgwc_pfcp_send_bearer_to_modify_list(
}
int sgwc_pfcp_send_session_establishment_request(
sgwc_sess_t *sess, ogs_gtp_xact_t *gtp_xact, ogs_pkbuf_t *gtpbuf)
sgwc_sess_t *sess, ogs_gtp_xact_t *gtp_xact, ogs_pkbuf_t *gtpbuf,
uint64_t flags)
{
int rv;
ogs_pkbuf_t *sxabuf = NULL;
@ -262,9 +263,40 @@ int sgwc_pfcp_send_session_establishment_request(
}
}
xact->local_seid = sess->sgwc_sxa_seid;
xact->create_flags = flags;
memset(&h, 0, sizeof(ogs_pfcp_header_t));
h.type = OGS_PFCP_SESSION_ESTABLISHMENT_REQUEST_TYPE;
/*
* 7.2.2.4.2 Conditions for Sending SEID=0 in PFCP Header
*
* If a peer's SEID is not available, the SEID field shall still be present
* in the header and its value shall be set to "0" in the following messages:
*
* - PFCP Session Establishment Request message on Sxa/Sxb/Sxc/N4;
*
* - If a node receives a message for which it has no session, i.e.
* if SEID in the PFCP header is not known, it shall respond
* with "Session context not found" cause in the corresponding
* response message to the sender, the SEID used in the PFCP header
* in the response message shall be then set to "0";
*
* - If a node receives a request message containing protocol error,
* e.g. Mandatory IE missing, which requires the receiver
* to reject the message as specified in clause 7.6, it shall reject
* the request message. For the response message, the node should look up
* the remote peer's SEID and accordingly set SEID in the PFCP header
* and the message cause code. As an implementation option,
* the node may not look up the remote peer's SEID and
* set the PFCP header SEID to "0" in the response message.
* However in this case, the cause value shall not be set
* to "Session not found".
*
* - When the UP function sends PFCP Session Report Request message
* over N4 towards another SMF or another PFCP entity in the SMF
* as specified in clause 5.22.2 and clause 5.22.3.
*/
h.seid = sess->sgwu_sxa_seid;
sxabuf = sgwc_sxa_build_session_establishment_request(h.type, sess);

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2019 by Sukchan Lee <acetcom@gmail.com>
* Copyright (C) 2019-2023 by Sukchan Lee <acetcom@gmail.com>
*
* This file is part of Open5GS.
*
@ -33,7 +33,8 @@ int sgwc_pfcp_send_bearer_to_modify_list(
sgwc_sess_t *sess, ogs_pfcp_xact_t *xact);
int sgwc_pfcp_send_session_establishment_request(
sgwc_sess_t *sess, ogs_gtp_xact_t *gtp_xact, ogs_pkbuf_t *gtpbuf);
sgwc_sess_t *sess, ogs_gtp_xact_t *gtp_xact, ogs_pkbuf_t *gtpbuf,
uint64_t flags);
int sgwc_pfcp_send_session_modification_request(
sgwc_sess_t *sess, ogs_gtp_xact_t *gtp_xact,

View File

@ -20,6 +20,7 @@
#include "pfcp-path.h"
#include "sxa-handler.h"
static void pfcp_restoration(ogs_pfcp_node_t *node);
static void node_timeout(ogs_pfcp_xact_t *xact, void *data);
void sgwc_pfcp_state_initial(ogs_fsm_t *s, sgwc_event_t *e)
@ -188,6 +189,7 @@ void sgwc_pfcp_state_associated(ogs_fsm_t *s, sgwc_event_t *e)
ogs_pfcp_send_heartbeat_request(node, node_timeout));
if (node->restoration_required == true) {
pfcp_restoration(node);
node->restoration_required = false;
ogs_error("PFCP restoration");
}
@ -220,11 +222,56 @@ void sgwc_pfcp_state_associated(ogs_fsm_t *s, sgwc_event_t *e)
ogs_expect(true ==
ogs_pfcp_handle_heartbeat_request(node, xact,
&message->pfcp_heartbeat_request));
if (node->restoration_required == true) {
if (node->t_association) {
/*
* node->t_association that the PFCP entity attempts an association.
*
* In this case, even if Remote PFCP entity is restarted,
* PFCP restoration must be performed after PFCP association.
*
* Otherwise, Session related PFCP cannot be initiated
* because the peer PFCP entity is in a de-associated state.
*/
OGS_FSM_TRAN(s, sgwc_pfcp_state_will_associate);
} else {
/*
* If the peer PFCP entity is performing the association,
* Restoration can be performed immediately.
*/
pfcp_restoration(node);
node->restoration_required = false;
ogs_error("PFCP restoration");
}
}
break;
case OGS_PFCP_HEARTBEAT_RESPONSE_TYPE:
ogs_expect(true ==
ogs_pfcp_handle_heartbeat_response(node, xact,
&message->pfcp_heartbeat_response));
if (node->restoration_required == true) {
/*
* node->t_association that the PFCP entity attempts an association.
*
* In this case, even if Remote PFCP entity is restarted,
* PFCP restoration must be performed after PFCP association.
*
* Otherwise, Session related PFCP cannot be initiated
* because the peer PFCP entity is in a de-associated state.
*/
if (node->t_association) {
OGS_FSM_TRAN(s, sgwc_pfcp_state_will_associate);
} else {
/*
* If the peer PFCP entity is performing the association,
* Restoration can be performed immediately.
*/
pfcp_restoration(node);
node->restoration_required = false;
ogs_error("PFCP restoration");
}
}
break;
case OGS_PFCP_ASSOCIATION_SETUP_REQUEST_TYPE:
ogs_warn("PFCP[REQ] has already been associated [%s]:%d",
@ -243,9 +290,24 @@ void sgwc_pfcp_state_associated(ogs_fsm_t *s, sgwc_event_t *e)
case OGS_PFCP_SESSION_ESTABLISHMENT_RESPONSE_TYPE:
if (!message->h.seid_presence) ogs_error("No SEID");
sgwc_sxa_handle_session_establishment_response(
sess, xact, e->gtp_message,
&message->pfcp_session_establishment_response);
if ((xact->create_flags &
OGS_PFCP_CREATE_RESTORATION_INDICATION)) {
ogs_pfcp_session_establishment_response_t *rsp = NULL;
ogs_pfcp_f_seid_t *up_f_seid = NULL;
rsp = &message->pfcp_session_establishment_response;
if (rsp->up_f_seid.presence == 0) {
ogs_error("No UP F-SEID");
break;
}
up_f_seid = rsp->up_f_seid.data;
ogs_assert(up_f_seid);
sess->sgwu_sxa_seid = be64toh(up_f_seid->seid);
} else {
sgwc_sxa_handle_session_establishment_response(
sess, xact, e->gtp_message,
&message->pfcp_session_establishment_response);
}
break;
case OGS_PFCP_SESSION_MODIFICATION_RESPONSE_TYPE:
@ -326,6 +388,29 @@ void sgwc_pfcp_state_exception(ogs_fsm_t *s, sgwc_event_t *e)
}
}
static void pfcp_restoration(ogs_pfcp_node_t *node)
{
sgwc_ue_t *sgwc_ue = NULL;
ogs_list_for_each(&sgwc_self()->sgw_ue_list, sgwc_ue) {
sgwc_sess_t *sess = NULL;
ogs_assert(sgwc_ue);
ogs_list_for_each(&sgwc_ue->sess_list, sess) {
ogs_assert(sess);
if (node == sess->pfcp_node) {
ogs_info("UE IMSI[%s] APN[%s]",
sgwc_ue->imsi_bcd, sess->session.name);
ogs_assert(OGS_OK ==
sgwc_pfcp_send_session_establishment_request(
sess, NULL, NULL,
OGS_PFCP_CREATE_RESTORATION_INDICATION));
}
}
}
}
static void node_timeout(ogs_pfcp_xact_t *xact, void *data)
{
int rv;

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2019 by Sukchan Lee <acetcom@gmail.com>
* Copyright (C) 2019-2023 by Sukchan Lee <acetcom@gmail.com>
*
* This file is part of Open5GS.
*
@ -234,6 +234,8 @@ void sgwc_s11_handle_create_session_request(
sess = sgwc_sess_add(sgwc_ue, apn);
ogs_assert(sess);
ogs_info("UE IMSI[%s] APN[%s]", sgwc_ue->imsi_bcd, sess->session.name);
/* Set User Location Information */
if (req->user_location_information.presence == 1) {
decoded = ogs_gtp2_parse_uli(&uli, &req->user_location_information);
@ -376,7 +378,8 @@ void sgwc_s11_handle_create_session_request(
sgwc_ue->mme_s11_teid, sgwc_ue->sgw_s11_teid);
ogs_assert(OGS_OK ==
sgwc_pfcp_send_session_establishment_request(sess, s11_xact, gtpbuf));
sgwc_pfcp_send_session_establishment_request(
sess, s11_xact, gtpbuf, 0));
}
void sgwc_s11_handle_modify_bearer_request(

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2019 by Sukchan Lee <acetcom@gmail.com>
* Copyright (C) 2019-2023 by Sukchan Lee <acetcom@gmail.com>
*
* This file is part of Open5GS.
*
@ -1297,10 +1297,7 @@ void sgwc_sxa_handle_session_deletion_response(
ogs_pfcp_xact_commit(pfcp_xact);
if (!gtp_message) {
ogs_error("No GTP Message");
goto cleanup;
}
if (!gtp_message) goto cleanup;
if (gtp_message->h.type == OGS_GTP2_DELETE_SESSION_REQUEST_TYPE) {
/*
@ -1380,7 +1377,10 @@ void sgwc_sxa_handle_session_deletion_response(
}
cleanup:
sgwc_sess_remove(sess);
if (sgwc_sess_cycle(sess))
sgwc_sess_remove(sess);
else
ogs_error("Session has already been removed");
}
void sgwc_sxa_handle_session_report_request(
@ -1390,6 +1390,7 @@ void sgwc_sxa_handle_session_report_request(
sgwc_ue_t *sgwc_ue = NULL;
sgwc_bearer_t *bearer = NULL;
sgwc_tunnel_t *tunnel = NULL;
ogs_pfcp_far_t *far = NULL;
ogs_pfcp_report_type_t report_type;
uint8_t cause_value = 0;
@ -1470,22 +1471,44 @@ void sgwc_sxa_handle_session_report_request(
ogs_error("Cannot find the PDR-ID[%d]", pdr_id);
} else if (report_type.error_indication_report) {
bearer = sgwc_bearer_find_by_error_indication_report(
sess, &pfcp_req->error_indication_report);
if (!bearer) return;
ogs_list_for_each(&sgwc_ue->sess_list, sess) {
ogs_assert(OGS_OK ==
sgwc_pfcp_send_session_modification_request(sess,
/* We only use the `assoc_xact` parameter temporarily here
* to pass the `bearer` context. */
(ogs_gtp_xact_t *)bearer,
NULL,
OGS_PFCP_MODIFY_DL_ONLY|OGS_PFCP_MODIFY_DEACTIVATE|
OGS_PFCP_MODIFY_ERROR_INDICATION));
}
far = ogs_pfcp_far_find_by_pfcp_session_report(
&sess->pfcp, &pfcp_req->error_indication_report);
if (far) {
tunnel = sgwc_tunnel_find_by_far_id(sess, far->id);
ogs_assert(tunnel);
bearer = tunnel->bearer;
ogs_assert(bearer);
if (far->dst_if == OGS_PFCP_INTERFACE_ACCESS) {
ogs_warn("[%s] Error Indication from eNB", sgwc_ue->imsi_bcd);
ogs_list_for_each(&sgwc_ue->sess_list, sess) {
ogs_assert(OGS_OK ==
sgwc_pfcp_send_session_modification_request(sess,
/* We only use the `assoc_xact` parameter temporarily here
* to pass the `bearer` context. */
(ogs_gtp_xact_t *)bearer,
NULL,
OGS_PFCP_MODIFY_DL_ONLY|OGS_PFCP_MODIFY_DEACTIVATE|
OGS_PFCP_MODIFY_ERROR_INDICATION));
}
} else if (far->dst_if == OGS_PFCP_INTERFACE_CORE) {
if (sgwc_default_bearer_in_sess(sess) == bearer) {
ogs_error("[%s] Error Indication(Default Bearer) from SMF",
sgwc_ue->imsi_bcd);
ogs_assert(OGS_OK ==
sgwc_pfcp_send_session_deletion_request(
sess, NULL, NULL));
} else {
ogs_error("[%s] Error Indication(Dedicated Bearer) "
"from SMF", sgwc_ue->imsi_bcd);
ogs_assert(OGS_OK ==
sgwc_pfcp_send_bearer_modification_request(
bearer, NULL, NULL, OGS_PFCP_MODIFY_REMOVE));
}
} else {
ogs_error("Error Indication Ignored for Indirect Tunnel");
}
} else
ogs_error("Cannot find Session in Error Indication");
} else {
ogs_error("Not supported Report Type[%d]", report_type.value);

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2019 by Sukchan Lee <acetcom@gmail.com>
* Copyright (C) 2019-2023 by Sukchan Lee <acetcom@gmail.com>
*
* This file is part of Open5GS.
*
@ -24,6 +24,7 @@ static sgwu_context_t self;
int __sgwu_log_domain;
static OGS_POOL(sgwu_sess_pool, sgwu_sess_t);
static OGS_POOL(sgwu_sxa_seid_pool, ogs_pool_id_t);
static int context_initialized = 0;
@ -43,11 +44,15 @@ void sgwu_context_init(void)
ogs_list_init(&self.sess_list);
ogs_pool_init(&sgwu_sess_pool, ogs_app()->pool.sess);
ogs_pool_init(&sgwu_sxa_seid_pool, ogs_app()->pool.sess);
ogs_pool_random_id_generate(&sgwu_sxa_seid_pool);
self.seid_hash = ogs_hash_make();
ogs_assert(self.seid_hash);
self.f_seid_hash = ogs_hash_make();
ogs_assert(self.f_seid_hash);
self.sgwu_sxa_seid_hash = ogs_hash_make();
ogs_assert(self.sgwu_sxa_seid_hash);
self.sgwc_sxa_seid_hash = ogs_hash_make();
ogs_assert(self.sgwc_sxa_seid_hash);
self.sgwc_sxa_f_seid_hash = ogs_hash_make();
ogs_assert(self.sgwc_sxa_f_seid_hash);
context_initialized = 1;
}
@ -58,12 +63,15 @@ void sgwu_context_final(void)
sgwu_sess_remove_all();
ogs_assert(self.seid_hash);
ogs_hash_destroy(self.seid_hash);
ogs_assert(self.f_seid_hash);
ogs_hash_destroy(self.f_seid_hash);
ogs_assert(self.sgwu_sxa_seid_hash);
ogs_hash_destroy(self.sgwu_sxa_seid_hash);
ogs_assert(self.sgwc_sxa_seid_hash);
ogs_hash_destroy(self.sgwc_sxa_seid_hash);
ogs_assert(self.sgwc_sxa_f_seid_hash);
ogs_hash_destroy(self.sgwc_sxa_f_seid_hash);
ogs_pool_final(&sgwu_sess_pool);
ogs_pool_final(&sgwu_sxa_seid_pool);
context_initialized = 0;
}
@ -137,10 +145,14 @@ sgwu_sess_t *sgwu_sess_add(ogs_pfcp_f_seid_t *cp_f_seid)
ogs_pfcp_pool_init(&sess->pfcp);
sess->index = ogs_pool_index(&sgwu_sess_pool, sess);
ogs_assert(sess->index > 0 && sess->index <= ogs_app()->pool.sess);
/* Set SEID */
ogs_pool_alloc(&sgwu_sxa_seid_pool, &sess->sgwu_sxa_seid_node);
ogs_assert(sess->sgwu_sxa_seid_node);
sess->sgwu_sxa_seid = sess->index;
sess->sgwu_sxa_seid = *(sess->sgwu_sxa_seid_node);
ogs_hash_set(self.sgwu_sxa_seid_hash, &sess->sgwu_sxa_seid,
sizeof(sess->sgwu_sxa_seid), sess);
/* Since F-SEID is composed of ogs_ip_t and uint64-seid,
* all these values must be put into the structure-sgwc_sxa_f_eid
@ -149,9 +161,9 @@ sgwu_sess_t *sgwu_sess_add(ogs_pfcp_f_seid_t *cp_f_seid)
ogs_assert(OGS_OK ==
ogs_pfcp_f_seid_to_ip(cp_f_seid, &sess->sgwc_sxa_f_seid.ip));
ogs_hash_set(self.f_seid_hash, &sess->sgwc_sxa_f_seid,
ogs_hash_set(self.sgwc_sxa_f_seid_hash, &sess->sgwc_sxa_f_seid,
sizeof(sess->sgwc_sxa_f_seid), sess);
ogs_hash_set(self.seid_hash, &sess->sgwc_sxa_f_seid.seid,
ogs_hash_set(self.sgwc_sxa_seid_hash, &sess->sgwc_sxa_f_seid.seid,
sizeof(sess->sgwc_sxa_f_seid.seid), sess);
ogs_info("UE F-SEID[UP:0x%lx CP:0x%lx]",
@ -172,13 +184,17 @@ int sgwu_sess_remove(sgwu_sess_t *sess)
ogs_list_remove(&self.sess_list, sess);
ogs_pfcp_sess_clear(&sess->pfcp);
ogs_hash_set(self.seid_hash, &sess->sgwc_sxa_f_seid.seid,
ogs_hash_set(self.sgwu_sxa_seid_hash, &sess->sgwu_sxa_seid,
sizeof(sess->sgwu_sxa_seid), NULL);
ogs_hash_set(self.sgwc_sxa_seid_hash, &sess->sgwc_sxa_f_seid.seid,
sizeof(sess->sgwc_sxa_f_seid.seid), NULL);
ogs_hash_set(self.f_seid_hash, &sess->sgwc_sxa_f_seid,
ogs_hash_set(self.sgwc_sxa_f_seid_hash, &sess->sgwc_sxa_f_seid,
sizeof(sess->sgwc_sxa_f_seid), NULL);
ogs_pfcp_pool_final(&sess->pfcp);
ogs_pool_free(&sgwu_sxa_seid_pool, sess->sgwu_sxa_seid_node);
ogs_pool_free(&sgwu_sess_pool, sess);
ogs_info("[Removed] Number of SGWU-sessions is now %d",
@ -196,14 +212,9 @@ void sgwu_sess_remove_all(void)
}
}
sgwu_sess_t *sgwu_sess_find(uint32_t index)
{
return ogs_pool_find(&sgwu_sess_pool, index);
}
sgwu_sess_t *sgwu_sess_find_by_sgwc_sxa_seid(uint64_t seid)
{
return (sgwu_sess_t *)ogs_hash_get(self.seid_hash, &seid, sizeof(seid));
return ogs_hash_get(self.sgwc_sxa_seid_hash, &seid, sizeof(seid));
}
sgwu_sess_t *sgwu_sess_find_by_sgwc_sxa_f_seid(ogs_pfcp_f_seid_t *f_seid)
@ -217,12 +228,12 @@ sgwu_sess_t *sgwu_sess_find_by_sgwc_sxa_f_seid(ogs_pfcp_f_seid_t *f_seid)
ogs_assert(OGS_OK == ogs_pfcp_f_seid_to_ip(f_seid, &key.ip));
key.seid = f_seid->seid;
return (sgwu_sess_t *)ogs_hash_get(self.f_seid_hash, &key, sizeof(key));
return ogs_hash_get(self.sgwc_sxa_f_seid_hash, &key, sizeof(key));
}
sgwu_sess_t *sgwu_sess_find_by_sgwu_sxa_seid(uint64_t seid)
{
return sgwu_sess_find(seid);
return ogs_hash_get(self.sgwu_sxa_seid_hash, &seid, sizeof(seid));
}
sgwu_sess_t *sgwu_sess_add_by_message(ogs_pfcp_message_t *message)
@ -244,7 +255,10 @@ sgwu_sess_t *sgwu_sess_add_by_message(ogs_pfcp_message_t *message)
sess = sgwu_sess_find_by_sgwc_sxa_f_seid(f_seid);
if (!sess) {
sess = sgwu_sess_add(f_seid);
if (!sess) return NULL;
if (!sess) {
ogs_error("No Session Context");
return NULL;
}
}
ogs_assert(sess);

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2019 by Sukchan Lee <acetcom@gmail.com>
* Copyright (C) 2019-2023 by Sukchan Lee <acetcom@gmail.com>
*
* This file is part of Open5GS.
*
@ -37,16 +37,17 @@ extern int __sgwu_log_domain;
#define OGS_LOG_DOMAIN __sgwu_log_domain
typedef struct sgwu_context_s {
ogs_hash_t *seid_hash; /* hash table (SEID) */
ogs_hash_t *f_seid_hash; /* hash table (F-SEID) */
ogs_hash_t *sgwu_sxa_seid_hash; /* hash table (SGWU-SXA-SEID) */
ogs_hash_t *sgwc_sxa_seid_hash; /* hash table (SGWC-SXA-SEID) */
ogs_hash_t *sgwc_sxa_f_seid_hash; /* hash table (SGWC-SXA-F-SEID) */
ogs_list_t sess_list;
ogs_list_t sess_list;
} sgwu_context_t;
#define SGWU_SESS(pfcp_sess) ogs_container_of(pfcp_sess, sgwu_sess_t, pfcp)
typedef struct sgwu_sess_s {
ogs_lnode_t lnode;
uint32_t index; /**< An index of this node */
ogs_pool_id_t *sgwu_sxa_seid_node; /* A node of SGWU-SXA-SEID */
ogs_pfcp_sess_t pfcp;
@ -70,7 +71,6 @@ sgwu_sess_t *sgwu_sess_add_by_message(ogs_pfcp_message_t *message);
sgwu_sess_t *sgwu_sess_add(ogs_pfcp_f_seid_t *f_seid);
int sgwu_sess_remove(sgwu_sess_t *sess);
void sgwu_sess_remove_all(void);
sgwu_sess_t *sgwu_sess_find(uint32_t index);
sgwu_sess_t *sgwu_sess_find_by_sgwc_sxa_seid(uint64_t seid);
sgwu_sess_t *sgwu_sess_find_by_sgwc_sxa_f_seid(ogs_pfcp_f_seid_t *f_seid);
sgwu_sess_t *sgwu_sess_find_by_sgwu_sxa_seid(uint64_t seid);

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2019 by Sukchan Lee <acetcom@gmail.com>
* Copyright (C) 2019-2023 by Sukchan Lee <acetcom@gmail.com>
*
* This file is part of Open5GS.
*
@ -28,11 +28,13 @@ static void _gtpv1_u_recv_cb(short when, ogs_socket_t fd, void *data)
{
int len;
ssize_t size;
char buf[OGS_ADDRSTRLEN];
char buf1[OGS_ADDRSTRLEN];
char buf2[OGS_ADDRSTRLEN];
sgwu_sess_t *sess = NULL;
ogs_pkbuf_t *pkbuf = NULL;
ogs_sock_t *sock = NULL;
ogs_sockaddr_t from;
ogs_gtp2_header_t *gtp_h = NULL;
@ -42,6 +44,8 @@ static void _gtpv1_u_recv_cb(short when, ogs_socket_t fd, void *data)
uint8_t qfi;
ogs_assert(fd != INVALID_SOCKET);
sock = data;
ogs_assert(sock);
pkbuf = ogs_pkbuf_alloc(packet_pool, OGS_MAX_PKT_LEN);
ogs_assert(pkbuf);
@ -69,14 +73,14 @@ static void _gtpv1_u_recv_cb(short when, ogs_socket_t fd, void *data)
if (gtp_h->type == OGS_GTPU_MSGTYPE_ECHO_REQ) {
ogs_pkbuf_t *echo_rsp;
ogs_debug("[RECV] Echo Request from [%s]", OGS_ADDR(&from, buf));
ogs_debug("[RECV] Echo Request from [%s]", OGS_ADDR(&from, buf1));
echo_rsp = ogs_gtp2_handle_echo_req(pkbuf);
ogs_expect(echo_rsp);
if (echo_rsp) {
ssize_t sent;
/* Echo reply */
ogs_debug("[SEND] Echo Response to [%s]", OGS_ADDR(&from, buf));
ogs_debug("[SEND] Echo Response to [%s]", OGS_ADDR(&from, buf1));
sent = ogs_sendto(fd, echo_rsp->data, echo_rsp->len, 0, &from);
if (sent < 0 || sent != echo_rsp->len) {
@ -91,7 +95,7 @@ static void _gtpv1_u_recv_cb(short when, ogs_socket_t fd, void *data)
teid = be32toh(gtp_h->teid);
ogs_trace("[RECV] GPU-U Type [%d] from [%s] : TEID[0x%x]",
gtp_h->type, OGS_ADDR(&from, buf), teid);
gtp_h->type, OGS_ADDR(&from, buf1), teid);
qfi = 0;
if (gtp_h->flags & OGS_GTPU_FLAGS_E) {
@ -139,7 +143,27 @@ static void _gtpv1_u_recv_cb(short when, ogs_socket_t fd, void *data)
pfcp_object = ogs_pfcp_object_find_by_teid(teid);
if (!pfcp_object) {
/* TODO : Send Error Indication */
/*
* Refer to the following 5G standard
*
* TS23.527 Restoration procedures
* 4.3 UPF Restoration Procedures
* 4.3.2 Restoration Procedure for PSA UPF Restart
*
* The UPF shall not send GTP-U Error indication message
* for a configurable period after an UPF restart
* when the UPF receives a G-PDU not matching any PDRs.
*/
if (ogs_time_ntp32_now() >
(ogs_pfcp_self()->local_recovery +
ogs_time_sec(
ogs_app()->time.message.pfcp.association_interval))) {
ogs_error("[%s] Send Error Indication [TEID:0x%x] to [%s]",
OGS_ADDR(&sock->local_addr, buf1),
teid,
OGS_ADDR(&from, buf2));
ogs_gtp1_send_error_indication(sock, teid, 0, &from);
}
goto cleanup;
}
@ -164,7 +188,7 @@ static void _gtpv1_u_recv_cb(short when, ogs_socket_t fd, void *data)
} else if (gtp_h->type == OGS_GTPU_MSGTYPE_ERR_IND) {
ogs_pfcp_far_t *far = NULL;
far = ogs_pfcp_far_find_by_error_indication(pkbuf);
far = ogs_pfcp_far_find_by_gtpu_error_indication(pkbuf);
if (far) {
ogs_assert(true ==
ogs_pfcp_up_handle_error_indication(far, &report));
@ -177,7 +201,6 @@ static void _gtpv1_u_recv_cb(short when, ogs_socket_t fd, void *data)
ogs_assert(OGS_OK ==
sgwu_pfcp_send_session_report_request(sess, &report));
}
} else {
ogs_error("[DROP] Cannot find FAR by Error-Indication");
ogs_log_hexdump(OGS_LOG_ERROR, pkbuf->data, pkbuf->len);
@ -193,7 +216,27 @@ static void _gtpv1_u_recv_cb(short when, ogs_socket_t fd, void *data)
pfcp_object = ogs_pfcp_object_find_by_teid(teid);
if (!pfcp_object) {
/* TODO : Send Error Indication */
/*
* Refer to the following 5G standard
*
* TS23.527 Restoration procedures
* 4.3 UPF Restoration Procedures
* 4.3.2 Restoration Procedure for PSA UPF Restart
*
* The UPF shall not send GTP-U Error indication message
* for a configurable period after an UPF restart
* when the UPF receives a G-PDU not matching any PDRs.
*/
if (ogs_time_ntp32_now() >
(ogs_pfcp_self()->local_recovery +
ogs_time_sec(
ogs_app()->time.message.pfcp.association_interval))) {
ogs_error("[%s] Send Error Indication [TEID:0x%x] to [%s]",
OGS_ADDR(&sock->local_addr, buf1),
teid,
OGS_ADDR(&from, buf2));
ogs_gtp1_send_error_indication(sock, teid, 0, &from);
}
goto cleanup;
}
@ -203,6 +246,8 @@ static void _gtpv1_u_recv_cb(short when, ogs_socket_t fd, void *data)
ogs_assert(pdr);
break;
case OGS_PFCP_OBJ_SESS_TYPE:
/* SGWU does not use SESS TYPE */
ogs_assert_if_reached();
pfcp_sess = (ogs_pfcp_sess_t *)pfcp_object;
ogs_assert(pfcp_sess);
@ -266,7 +311,7 @@ int sgwu_gtp_init(void)
config.cluster_2048_pool = ogs_app()->pool.packet;
#if OGS_USE_TALLOC
#if OGS_USE_TALLOC == 1
/* allocate a talloc pool for GTP to ensure it doesn't have to go back
* to the libc malloc all the time */
packet_pool = talloc_pool(__ogs_talloc_core, 1000*1024);

View File

@ -205,7 +205,6 @@ int sgwu_pfcp_send_session_modification_response(
ogs_pfcp_header_t h;
ogs_assert(xact);
ogs_assert(created_pdr);
memset(&h, 0, sizeof(ogs_pfcp_header_t));
h.type = OGS_PFCP_SESSION_MODIFICATION_RESPONSE_TYPE;

View File

@ -277,12 +277,9 @@ void sgwu_pfcp_state_associated(ogs_fsm_t *s, sgwu_event_t *e)
&message->pfcp_association_setup_response);
break;
case OGS_PFCP_SESSION_ESTABLISHMENT_REQUEST_TYPE:
if (message->h.seid_presence && message->h.seid == 0) {
ogs_expect(!sess);
sess = sgwu_sess_add_by_message(message);
if (sess)
OGS_SETUP_PFCP_NODE(sess, node);
}
sess = sgwu_sess_add_by_message(message);
if (sess)
OGS_SETUP_PFCP_NODE(sess, node);
sgwu_sxa_handle_session_establishment_request(
sess, xact, &message->pfcp_session_establishment_request);
break;

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2019 by Sukchan Lee <acetcom@gmail.com>
* Copyright (C) 2019-2023 by Sukchan Lee <acetcom@gmail.com>
*
* This file is part of Open5GS.
*
@ -33,6 +33,9 @@ void sgwu_sxa_handle_session_establishment_request(
uint8_t offending_ie_value = 0;
int i;
ogs_pfcp_sereq_flags_t sereq_flags;
bool restoration_indication = false;
ogs_assert(xact);
ogs_assert(req);
@ -48,9 +51,16 @@ void sgwu_sxa_handle_session_establishment_request(
return;
}
/* PFCPSEReq-Flags */
memset(&sereq_flags, 0, sizeof(sereq_flags));
if (req->pfcpsereq_flags.presence == 1) {
sereq_flags.value = req->pfcpsereq_flags.u8;
}
for (i = 0; i < OGS_MAX_NUM_OF_PDR; i++) {
created_pdr[i] = ogs_pfcp_handle_create_pdr(&sess->pfcp,
&req->create_pdr[i], &cause_value, &offending_ie_value);
&req->create_pdr[i], &sereq_flags,
&cause_value, &offending_ie_value);
if (created_pdr[i] == NULL)
break;
}
@ -79,6 +89,18 @@ void sgwu_sxa_handle_session_establishment_request(
if (cause_value != OGS_PFCP_CAUSE_REQUEST_ACCEPTED)
goto cleanup;
/* PFCPSEReq-Flags */
if (sereq_flags.restoration_indication == 1) {
for (i = 0; i < num_of_created_pdr; i++) {
pdr = created_pdr[i];
ogs_assert(pdr);
if (pdr->f_teid_len)
ogs_pfcp_pdr_swap_teid(pdr);
}
restoration_indication = true;
}
/* Setup GTP Node */
ogs_list_for_each(&sess->pfcp.far_list, far) {
ogs_assert(OGS_ERROR != ogs_pfcp_setup_far_gtpu_node(far));
@ -86,70 +108,14 @@ void sgwu_sxa_handle_session_establishment_request(
ogs_pfcp_far_f_teid_hash_set(far);
}
/* Setup TEID Hash */
for (i = 0; i < num_of_created_pdr; i++) {
pdr = created_pdr[i];
ogs_assert(pdr);
if (pdr->f_teid_len) {
ogs_pfcp_object_type_e type = OGS_PFCP_OBJ_PDR_TYPE;
if (ogs_pfcp_self()->up_function_features.ftup &&
pdr->f_teid.ch) {
ogs_pfcp_pdr_t *choosed_pdr = NULL;
if (pdr->f_teid.chid) {
type = OGS_PFCP_OBJ_SESS_TYPE;
choosed_pdr = ogs_pfcp_pdr_find_by_choose_id(
&sess->pfcp, pdr->f_teid.choose_id);
if (!choosed_pdr) {
pdr->chid = true;
pdr->choose_id = pdr->f_teid.choose_id;
}
}
if (choosed_pdr) {
pdr->f_teid_len = choosed_pdr->f_teid_len;
memcpy(&pdr->f_teid, &choosed_pdr->f_teid, pdr->f_teid_len);
} else {
ogs_gtpu_resource_t *resource = NULL;
resource = ogs_pfcp_find_gtpu_resource(
&ogs_gtp_self()->gtpu_resource_list,
pdr->apn, OGS_PFCP_INTERFACE_ACCESS);
if (resource) {
ogs_assert(
(resource->info.v4 && pdr->f_teid.ipv4) ||
(resource->info.v6 && pdr->f_teid.ipv6));
ogs_assert(OGS_OK ==
ogs_pfcp_user_plane_ip_resource_info_to_f_teid(
&resource->info, &pdr->f_teid, &pdr->f_teid_len));
if (resource->info.teidri)
pdr->f_teid.teid = OGS_PFCP_GTPU_INDEX_TO_TEID(
pdr->index, resource->info.teidri,
resource->info.teid_range);
else
pdr->f_teid.teid = pdr->index;
} else {
ogs_assert(
(ogs_gtp_self()->gtpu_addr && pdr->f_teid.ipv4) ||
(ogs_gtp_self()->gtpu_addr6 && pdr->f_teid.ipv6));
ogs_assert(OGS_OK ==
ogs_pfcp_sockaddr_to_f_teid(
pdr->f_teid.ipv4 ?
ogs_gtp_self()->gtpu_addr : NULL,
pdr->f_teid.ipv6 ?
ogs_gtp_self()->gtpu_addr6 : NULL,
&pdr->f_teid, &pdr->f_teid_len));
pdr->f_teid.teid = pdr->index;
}
}
}
ogs_pfcp_object_teid_hash_set(type, pdr);
}
/* Setup TEID Hash */
if (pdr->f_teid_len)
ogs_pfcp_object_teid_hash_set(
OGS_PFCP_OBJ_PDR_TYPE, pdr, restoration_indication);
}
/* Send Buffered Packet to gNB */
@ -159,9 +125,15 @@ void sgwu_sxa_handle_session_establishment_request(
}
}
ogs_assert(OGS_OK ==
sgwu_pfcp_send_session_establishment_response(
xact, sess, created_pdr, num_of_created_pdr));
if (restoration_indication == true ||
ogs_pfcp_self()->up_function_features.ftup == 0)
ogs_assert(OGS_OK ==
sgwu_pfcp_send_session_establishment_response(
xact, sess, NULL, 0));
else
ogs_assert(OGS_OK ==
sgwu_pfcp_send_session_establishment_response(
xact, sess, created_pdr, num_of_created_pdr));
return;
cleanup:
@ -200,7 +172,7 @@ void sgwu_sxa_handle_session_modification_request(
for (i = 0; i < OGS_MAX_NUM_OF_PDR; i++) {
created_pdr[i] = ogs_pfcp_handle_create_pdr(&sess->pfcp,
&req->create_pdr[i], &cause_value, &offending_ie_value);
&req->create_pdr[i], NULL, &cause_value, &offending_ie_value);
if (created_pdr[i] == NULL)
break;
}
@ -301,70 +273,13 @@ void sgwu_sxa_handle_session_modification_request(
ogs_pfcp_far_f_teid_hash_set(far);
}
/* Setup TEID Hash */
for (i = 0; i < num_of_created_pdr; i++) {
pdr = created_pdr[i];
ogs_assert(pdr);
if (pdr->f_teid_len) {
ogs_pfcp_object_type_e type = OGS_PFCP_OBJ_PDR_TYPE;
if (ogs_pfcp_self()->up_function_features.ftup &&
pdr->f_teid.ch) {
ogs_pfcp_pdr_t *choosed_pdr = NULL;
if (pdr->f_teid.chid) {
type = OGS_PFCP_OBJ_SESS_TYPE;
choosed_pdr = ogs_pfcp_pdr_find_by_choose_id(
&sess->pfcp, pdr->f_teid.choose_id);
if (!choosed_pdr) {
pdr->chid = true;
pdr->choose_id = pdr->f_teid.choose_id;
}
}
if (choosed_pdr) {
pdr->f_teid_len = choosed_pdr->f_teid_len;
memcpy(&pdr->f_teid, &choosed_pdr->f_teid, pdr->f_teid_len);
} else {
ogs_gtpu_resource_t *resource = NULL;
resource = ogs_pfcp_find_gtpu_resource(
&ogs_gtp_self()->gtpu_resource_list,
pdr->apn, OGS_PFCP_INTERFACE_ACCESS);
if (resource) {
ogs_assert(
(resource->info.v4 && pdr->f_teid.ipv4) ||
(resource->info.v6 && pdr->f_teid.ipv6));
ogs_assert(OGS_OK ==
ogs_pfcp_user_plane_ip_resource_info_to_f_teid(
&resource->info, &pdr->f_teid, &pdr->f_teid_len));
if (resource->info.teidri)
pdr->f_teid.teid = OGS_PFCP_GTPU_INDEX_TO_TEID(
pdr->index, resource->info.teidri,
resource->info.teid_range);
else
pdr->f_teid.teid = pdr->index;
} else {
ogs_assert(
(ogs_gtp_self()->gtpu_addr && pdr->f_teid.ipv4) ||
(ogs_gtp_self()->gtpu_addr6 && pdr->f_teid.ipv6));
ogs_assert(OGS_OK ==
ogs_pfcp_sockaddr_to_f_teid(
pdr->f_teid.ipv4 ?
ogs_gtp_self()->gtpu_addr : NULL,
pdr->f_teid.ipv6 ?
ogs_gtp_self()->gtpu_addr6 : NULL,
&pdr->f_teid, &pdr->f_teid_len));
pdr->f_teid.teid = pdr->index;
}
}
}
ogs_pfcp_object_teid_hash_set(type, pdr);
}
/* Setup TEID Hash */
if (pdr->f_teid_len)
ogs_pfcp_object_teid_hash_set(OGS_PFCP_OBJ_PDR_TYPE, pdr, false);
}
/* Send Buffered Packet to gNB */
@ -374,9 +289,14 @@ void sgwu_sxa_handle_session_modification_request(
}
}
ogs_assert(OGS_OK ==
sgwu_pfcp_send_session_modification_response(
xact, sess, created_pdr, num_of_created_pdr));
if (ogs_pfcp_self()->up_function_features.ftup == 0)
ogs_assert(OGS_OK ==
sgwu_pfcp_send_session_modification_response(
xact, sess, NULL, 0));
else
ogs_assert(OGS_OK ==
sgwu_pfcp_send_session_modification_response(
xact, sess, created_pdr, num_of_created_pdr));
return;
cleanup:

View File

@ -197,10 +197,10 @@ void smf_bearer_binding(smf_sess_t *sess)
&bearer->pgw_s5u_addr, &bearer->pgw_s5u_addr6);
if (resource->info.teidri)
bearer->pgw_s5u_teid = OGS_PFCP_GTPU_INDEX_TO_TEID(
ul_pdr->index, resource->info.teidri,
ul_pdr->teid, resource->info.teidri,
resource->info.teid_range);
else
bearer->pgw_s5u_teid = ul_pdr->index;
bearer->pgw_s5u_teid = ul_pdr->teid;
} else {
if (sess->pfcp_node->addr.ogs_sa_family == AF_INET)
ogs_assert(OGS_OK ==
@ -214,7 +214,7 @@ void smf_bearer_binding(smf_sess_t *sess)
else
ogs_assert_if_reached();
bearer->pgw_s5u_teid = ul_pdr->index;
bearer->pgw_s5u_teid = ul_pdr->teid;
}
ogs_assert(OGS_OK ==

View File

@ -29,11 +29,12 @@ int __gsm_log_domain;
static OGS_POOL(smf_gtp_node_pool, smf_gtp_node_t);
static OGS_POOL(smf_ue_pool, smf_ue_t);
static OGS_POOL(smf_sess_pool, smf_sess_t);
static OGS_POOL(smf_bearer_pool, smf_bearer_t);
static OGS_POOL(smf_pf_pool, smf_pf_t);
static OGS_POOL(smf_sess_pool, smf_sess_t);
static OGS_POOL(smf_n4_seid_pool, ogs_pool_id_t);
static int context_initialized = 0;
static int num_of_smf_sess = 0;
@ -82,16 +83,20 @@ void smf_context_init(void)
ogs_pool_init(&smf_gtp_node_pool, ogs_app()->pool.nf);
ogs_pool_init(&smf_ue_pool, ogs_app()->max.ue);
ogs_pool_init(&smf_sess_pool, ogs_app()->pool.sess);
ogs_pool_init(&smf_bearer_pool, ogs_app()->pool.bearer);
ogs_pool_init(&smf_pf_pool,
ogs_app()->pool.bearer * OGS_MAX_NUM_OF_FLOW_IN_BEARER);
ogs_pool_init(&smf_sess_pool, ogs_app()->pool.sess);
ogs_pool_init(&smf_n4_seid_pool, ogs_app()->pool.sess);
ogs_pool_random_id_generate(&smf_n4_seid_pool);
self.supi_hash = ogs_hash_make();
ogs_assert(self.supi_hash);
self.imsi_hash = ogs_hash_make();
ogs_assert(self.imsi_hash);
self.smf_n4_seid_hash = ogs_hash_make();
ogs_assert(self.smf_n4_seid_hash);
self.ipv4_hash = ogs_hash_make();
ogs_assert(self.ipv4_hash);
self.ipv6_hash = ogs_hash_make();
@ -99,7 +104,6 @@ void smf_context_init(void)
self.n1n2message_hash = ogs_hash_make();
ogs_assert(self.n1n2message_hash);
context_initialized = 1;
}
@ -114,6 +118,8 @@ void smf_context_final(void)
ogs_hash_destroy(self.supi_hash);
ogs_assert(self.imsi_hash);
ogs_hash_destroy(self.imsi_hash);
ogs_assert(self.smf_n4_seid_hash);
ogs_hash_destroy(self.smf_n4_seid_hash);
ogs_assert(self.ipv4_hash);
ogs_hash_destroy(self.ipv4_hash);
ogs_assert(self.ipv6_hash);
@ -123,10 +129,11 @@ void smf_context_final(void)
ogs_pool_final(&smf_ue_pool);
ogs_pool_final(&smf_bearer_pool);
ogs_pool_final(&smf_sess_pool);
ogs_pool_final(&smf_pf_pool);
ogs_pool_final(&smf_sess_pool);
ogs_pool_final(&smf_n4_seid_pool);
ogs_list_for_each_entry_safe(&self.sgw_s5c_list, next_gnode, gnode, node) {
smf_gtp_node_t *smf_gnode = gnode->data_ptr;
ogs_assert(smf_gnode);
@ -1198,8 +1205,14 @@ smf_sess_t *smf_sess_add_by_apn(smf_ue_t *smf_ue, char *apn, uint8_t rat_type)
ogs_assert(sess->index > 0 && sess->index <= ogs_app()->pool.sess);
/* Set TEID & SEID */
sess->smf_n4_teid = sess->index;
sess->smf_n4_seid = sess->index;
ogs_pool_alloc(&smf_n4_seid_pool, &sess->smf_n4_seid_node);
ogs_assert(sess->smf_n4_seid_node);
sess->smf_n4_teid = *(sess->smf_n4_seid_node);
sess->smf_n4_seid = *(sess->smf_n4_seid_node);
ogs_hash_set(self.smf_n4_seid_hash, &sess->smf_n4_seid,
sizeof(sess->smf_n4_seid), sess);
/* Set Charging ID */
sess->charging.id = sess->index;
@ -1403,9 +1416,18 @@ smf_sess_t *smf_sess_add_by_psi(smf_ue_t *smf_ue, uint8_t psi)
sess->index = ogs_pool_index(&smf_sess_pool, sess);
ogs_assert(sess->index > 0 && sess->index <= ogs_app()->pool.sess);
/* Set TEID & SEID */
ogs_pool_alloc(&smf_n4_seid_pool, &sess->smf_n4_seid_node);
ogs_assert(sess->smf_n4_seid_node);
sess->smf_n4_teid = *(sess->smf_n4_seid_node);
sess->smf_n4_seid = *(sess->smf_n4_seid_node);
ogs_hash_set(self.smf_n4_seid_hash, &sess->smf_n4_seid,
sizeof(sess->smf_n4_seid), sess);
/* Set SmContextRef in 5GC */
sess->sm_context_ref = ogs_msprintf("%d",
(int)ogs_pool_index(&smf_sess_pool, sess));
sess->sm_context_ref = ogs_msprintf("%d", sess->index);
ogs_assert(sess->sm_context_ref);
/* Create BAR in PFCP Session */
@ -1420,10 +1442,6 @@ smf_sess_t *smf_sess_add_by_psi(smf_ue_t *smf_ue, uint8_t psi)
sess->mapped_hplmn.sst = 0;
sess->mapped_hplmn.sd.v = OGS_S_NSSAI_NO_SD_VALUE;
/* Set TEID & SEID */
sess->smf_n4_teid = sess->index;
sess->smf_n4_seid = sess->index;
/* Set Charging Id */
sess->charging.id = sess->index;
@ -1623,68 +1641,6 @@ void smf_sess_set_paging_n1n2message_location(
sess);
}
smf_sess_t *smf_sess_find_by_error_indication_report(
smf_ue_t *smf_ue,
ogs_pfcp_tlv_error_indication_report_t *error_indication_report)
{
smf_sess_t *sess = NULL;
ogs_pfcp_f_teid_t *remote_f_teid = NULL;
uint32_t teid;
uint16_t len; /* OGS_IPV4_LEN or OGS_IPV6_LEN */
uint32_t addr[4];
ogs_assert(smf_ue);
ogs_assert(error_indication_report);
if (error_indication_report->presence == 0) {
ogs_error("No Error Indication Report");
return NULL;
}
if (error_indication_report->remote_f_teid.presence == 0) {
ogs_error("No Remote F-TEID");
return NULL;
}
remote_f_teid = error_indication_report->remote_f_teid.data;
ogs_assert(remote_f_teid);
teid = be32toh(remote_f_teid->teid);
if (remote_f_teid->ipv4 && remote_f_teid->ipv6) {
ogs_error("User plane should not set both IPv4 and IPv6");
return NULL;
} else if (remote_f_teid->ipv4) {
len = OGS_IPV4_LEN;
memcpy(addr, &remote_f_teid->addr, len);
} else if (remote_f_teid->ipv6) {
len = OGS_IPV6_LEN;
memcpy(addr, remote_f_teid->addr6, len);
} else {
ogs_error("No IPv4 and IPv6");
return NULL;
}
ogs_list_reverse_for_each(&smf_ue->sess_list, sess) {
if (teid == sess->gnb_n3_teid) {
if (len == OGS_IPV4_LEN && sess->gnb_n3_ip.ipv4 &&
memcmp(addr, &sess->gnb_n3_ip.addr, len) == 0) {
return sess;
} else if (len == OGS_IPV6_LEN && sess->gnb_n3_ip.ipv6 &&
memcmp(addr, sess->gnb_n3_ip.addr6, len) == 0) {
return sess;
}
}
}
ogs_error("Cannot find the session context "
"[TEID:%d,LEN:%d,ADDR:%08x %08x %08x %08x]",
teid, len, be32toh(addr[0]), be32toh(addr[1]),
be32toh(addr[2]), be32toh(addr[3]));
return NULL;
}
void smf_sess_remove(smf_sess_t *sess)
{
int i;
@ -1722,6 +1678,9 @@ void smf_sess_remove(smf_sess_t *sess)
OGS_PCC_RULE_FREE(&sess->policy.pcc_rule[i]);
sess->policy.num_of_pcc_rule = 0;
ogs_hash_set(self.smf_n4_seid_hash, &sess->smf_n4_seid,
sizeof(sess->smf_n4_seid), NULL);
if (sess->ipv4) {
ogs_hash_set(self.ipv4_hash, sess->ipv4->addr, OGS_IPV4_LEN, NULL);
ogs_pfcp_ue_ip_free(sess->ipv4);
@ -1809,6 +1768,8 @@ void smf_sess_remove(smf_sess_t *sess)
break;
}
stats_remove_smf_session(sess);
ogs_pool_free(&smf_n4_seid_pool, sess->smf_n4_seid_node);
ogs_pool_free(&smf_sess_pool, sess);
}
@ -1822,19 +1783,14 @@ void smf_sess_remove_all(smf_ue_t *smf_ue)
smf_sess_remove(sess);
}
smf_sess_t *smf_sess_find(uint32_t index)
{
return ogs_pool_find(&smf_sess_pool, index);
}
smf_sess_t *smf_sess_find_by_teid(uint32_t teid)
{
return smf_sess_find(teid);
return smf_sess_find_by_seid(teid);
}
smf_sess_t *smf_sess_find_by_seid(uint64_t seid)
{
return smf_sess_find(seid);
return ogs_hash_get(self.smf_n4_seid_hash, &seid, sizeof(seid));
}
smf_sess_t *smf_sess_find_by_apn(smf_ue_t *smf_ue, char *apn, uint8_t rat_type)
@ -1868,6 +1824,11 @@ smf_sess_t *smf_sess_find_by_psi(smf_ue_t *smf_ue, uint8_t psi)
return NULL;
}
smf_sess_t *smf_sess_find(uint32_t index)
{
return ogs_pool_find(&smf_sess_pool, index);
}
smf_sess_t *smf_sess_find_by_charging_id(uint32_t charging_id)
{
ogs_assert(charging_id);
@ -1939,10 +1900,6 @@ smf_bearer_t *smf_qos_flow_add(smf_sess_t *sess)
smf_pf_identifier_pool_init(qos_flow);
qos_flow->index = ogs_pool_index(&smf_bearer_pool, qos_flow);
ogs_assert(qos_flow->index > 0 && qos_flow->index <=
ogs_app()->pool.bearer);
ogs_list_init(&qos_flow->pf_list);
/* PDR */
@ -2123,37 +2080,51 @@ void smf_sess_create_indirect_data_forwarding(smf_sess_t *sess)
pdr->f_teid.choose_id = OGS_PFCP_INDIRECT_DATA_FORWARDING_CHOOSE_ID;
pdr->f_teid_len = 2;
} else {
ogs_gtpu_resource_t *resource = NULL;
/*
* CHOOSE_ID is set in INDIRECT so that all PDRs must be set
* to the same TEID.
*
* If sess->handover.upf_dl_teid is set in the PDR of
* the first QoS flow, the PDRs of the remaining QoS flows use
* the same TEID.
*/
if (ogs_list_first(&sess->bearer_list) == qos_flow) {
ogs_gtpu_resource_t *resource = NULL;
if (sess->handover.upf_dl_addr)
ogs_freeaddrinfo(sess->handover.upf_dl_addr);
if (sess->handover.upf_dl_addr6)
ogs_freeaddrinfo(sess->handover.upf_dl_addr6);
if (sess->handover.upf_dl_addr)
ogs_freeaddrinfo(sess->handover.upf_dl_addr);
if (sess->handover.upf_dl_addr6)
ogs_freeaddrinfo(sess->handover.upf_dl_addr6);
resource = ogs_pfcp_find_gtpu_resource(
&sess->pfcp_node->gtpu_resource_list,
sess->session.name, OGS_PFCP_INTERFACE_ACCESS);
resource = ogs_pfcp_find_gtpu_resource(
&sess->pfcp_node->gtpu_resource_list,
sess->session.name, OGS_PFCP_INTERFACE_ACCESS);
if (resource) {
ogs_user_plane_ip_resource_info_to_sockaddr(&resource->info,
&sess->handover.upf_dl_addr, &sess->handover.upf_dl_addr6);
if (resource->info.teidri)
sess->handover.upf_dl_teid = OGS_PFCP_GTPU_INDEX_TO_TEID(
pdr->index, resource->info.teidri,
resource->info.teid_range);
else
sess->handover.upf_dl_teid = pdr->index;
} else {
if (sess->pfcp_node->addr.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)
ogs_assert(OGS_OK == ogs_copyaddrinfo(
&sess->handover.upf_dl_addr6, &sess->pfcp_node->addr));
else
ogs_assert_if_reached();
if (resource) {
ogs_user_plane_ip_resource_info_to_sockaddr(&resource->info,
&sess->handover.upf_dl_addr,
&sess->handover.upf_dl_addr6);
if (resource->info.teidri)
sess->handover.upf_dl_teid =
OGS_PFCP_GTPU_INDEX_TO_TEID(
pdr->teid, resource->info.teidri,
resource->info.teid_range);
else
sess->handover.upf_dl_teid = pdr->teid;
} else {
if (sess->pfcp_node->addr.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)
ogs_assert(OGS_OK == ogs_copyaddrinfo(
&sess->handover.upf_dl_addr6,
&sess->pfcp_node->addr));
else
ogs_assert_if_reached();
sess->handover.upf_dl_teid = pdr->index;
sess->handover.upf_dl_teid = pdr->teid;
}
}
ogs_assert(OGS_OK ==
@ -2370,10 +2341,6 @@ smf_bearer_t *smf_bearer_add(smf_sess_t *sess)
smf_pf_identifier_pool_init(bearer);
bearer->index = ogs_pool_index(&smf_bearer_pool, bearer);
ogs_assert(bearer->index > 0 && bearer->index <=
ogs_app()->pool.bearer);
ogs_list_init(&bearer->pf_list);
/* PDR */
@ -3033,64 +3000,48 @@ int smf_pco_build(uint8_t *pco_buf, uint8_t *buffer, int length)
void smf_qfi_pool_init(smf_sess_t *sess)
{
int i;
ogs_assert(sess);
ogs_index_init(&sess->qfi_pool, OGS_MAX_QOS_FLOW_ID);
for (i = 1; i <= OGS_MAX_QOS_FLOW_ID; i++) {
sess->qfi_pool.array[i-1] = i;
}
ogs_pool_init(&sess->qfi_pool, OGS_MAX_QOS_FLOW_ID);
ogs_pool_sequence_id_generate(&sess->qfi_pool);
}
void smf_qfi_pool_final(smf_sess_t *sess)
{
ogs_assert(sess);
ogs_index_final(&sess->qfi_pool);
ogs_pool_final(&sess->qfi_pool);
}
void smf_pf_identifier_pool_init(smf_bearer_t *bearer)
{
int i;
ogs_assert(bearer);
ogs_index_init(&bearer->pf_identifier_pool, OGS_MAX_NUM_OF_FLOW_IN_BEARER);
for (i = 1; i <= OGS_MAX_NUM_OF_FLOW_IN_BEARER; i++) {
bearer->pf_identifier_pool.array[i-1] = i;
}
ogs_pool_init(&bearer->pf_identifier_pool, OGS_MAX_NUM_OF_FLOW_IN_BEARER);
ogs_pool_sequence_id_generate(&bearer->pf_identifier_pool);
}
void smf_pf_identifier_pool_final(smf_bearer_t *bearer)
{
ogs_assert(bearer);
ogs_index_final(&bearer->pf_identifier_pool);
ogs_pool_final(&bearer->pf_identifier_pool);
}
void smf_pf_precedence_pool_init(smf_sess_t *sess)
{
int i;
ogs_assert(sess);
ogs_index_init(&sess->pf_precedence_pool,
ogs_pool_init(&sess->pf_precedence_pool,
OGS_MAX_NUM_OF_BEARER * OGS_MAX_NUM_OF_FLOW_IN_BEARER);
for (i = 1; i <=
OGS_MAX_NUM_OF_BEARER * OGS_MAX_NUM_OF_FLOW_IN_BEARER; i++) {
sess->pf_precedence_pool.array[i-1] = i;
}
ogs_pool_sequence_id_generate(&sess->pf_precedence_pool);
}
void smf_pf_precedence_pool_final(smf_sess_t *sess)
{
ogs_assert(sess);
ogs_index_final(&sess->pf_precedence_pool);
ogs_pool_final(&sess->pf_precedence_pool);
}
static void stats_add_smf_session(void)

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2019-2022 by Sukchan Lee <acetcom@gmail.com>
* Copyright (C) 2019-2023 by Sukchan Lee <acetcom@gmail.com>
*
* This file is part of Open5GS.
*
@ -88,6 +88,7 @@ typedef struct smf_context_s {
ogs_hash_t *imsi_hash; /* hash table (IMSI) */
ogs_hash_t *ipv4_hash; /* hash table (IPv4 Address) */
ogs_hash_t *ipv6_hash; /* hash table (IPv6 Address) */
ogs_hash_t *smf_n4_seid_hash; /* hash table (SMF-N4-SEID) */
ogs_hash_t *n1n2message_hash; /* hash table (N1N2Message Location) */
uint16_t mtu; /* MTU to advertise in PCO */
@ -173,8 +174,6 @@ typedef struct smf_bearer_s {
ogs_lnode_t to_modify_node;
ogs_lnode_t to_delete_node;
uint32_t index;
ogs_pfcp_pdr_t *dl_pdr;
ogs_pfcp_pdr_t *ul_pdr;
ogs_pfcp_far_t *dl_far;
@ -215,7 +214,10 @@ typedef struct smf_bearer_s {
#define SMF_SESS(pfcp_sess) ogs_container_of(pfcp_sess, smf_sess_t, pfcp)
typedef struct smf_sess_s {
ogs_sbi_object_t sbi;
uint32_t index; /**< An index of this node */
uint32_t index; /* An index of this node */
ogs_pool_id_t *smf_n4_seid_node; /* A node of SMF-N4-SEID */
ogs_fsm_t sm; /* A state machine */
struct {
bool gx_ccr_init_in_flight; /* Waiting for Gx CCA */
@ -236,12 +238,12 @@ typedef struct smf_sess_s {
uint64_t smpolicycontrol_features; /* SBI features */
uint32_t smf_n4_teid; /* SMF-N4-TEID is derived from INDEX */
uint32_t smf_n4_teid; /* SMF-N4-TEID is derived from NODE */
uint32_t sgw_s5c_teid; /* SGW-S5C-TEID is received from SGW */
ogs_ip_t sgw_s5c_ip; /* SGW-S5C IPv4/IPv6 */
uint64_t smf_n4_seid; /* SMF SEID is dervied from INDEX */
uint64_t smf_n4_seid; /* SMF SEID is dervied from NODE */
uint64_t upf_n4_seid; /* UPF SEID is received from Peer */
uint32_t upf_n3_teid; /* UPF-N3 TEID */
@ -463,9 +465,6 @@ smf_sess_t *smf_sess_find_by_ipv4(uint32_t addr);
smf_sess_t *smf_sess_find_by_ipv6(uint32_t *addr6);
smf_sess_t *smf_sess_find_by_paging_n1n2message_location(
char *n1n2message_location);
smf_sess_t *smf_sess_find_by_error_indication_report(
smf_ue_t *smf_ue,
ogs_pfcp_tlv_error_indication_report_t *error_indication_report);
void smf_sess_create_indirect_data_forwarding(smf_sess_t *sess);
bool smf_sess_have_indirect_data_forwarding(smf_sess_t *sess);

View File

@ -62,6 +62,7 @@ void smf_fd_final(void)
}
smf_gx_final();
smf_gy_final();
smf_s6b_final();
ogs_diam_final();

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2019-2022 by Sukchan Lee <acetcom@gmail.com>
* Copyright (C) 2019-2023 by Sukchan Lee <acetcom@gmail.com>
*
* This file is part of Open5GS.
*
@ -452,7 +452,7 @@ test_can_proceed:
OGS_FSM_TRAN(s, &smf_gsm_state_wait_pfcp_establishment);
ogs_assert(OGS_OK ==
smf_epc_pfcp_send_session_establishment_request(
sess, e->gtp_xact));
sess, e->gtp_xact, 0));
} else {
/* FIXME: tear down Gx/Gy session
* if its sm_data.*init_err == ER_DIAMETER_SUCCESS */
@ -671,21 +671,28 @@ void smf_gsm_state_wait_pfcp_establishment(ogs_fsm_t *s, smf_event_t *e)
send_gtp_create_err_msg(sess, e->gtp_xact, gtp_cause);
return;
}
switch (gtp_xact->gtp_version) {
case 1:
rv = smf_gtp1_send_create_pdp_context_response(sess, gtp_xact);
break;
case 2:
rv = smf_gtp2_send_create_session_response(sess, gtp_xact);
break;
default:
rv = OGS_ERROR;
break;
}
/* If no CreatePDPCtxResp can be sent, then tear down the session: */
if (rv != OGS_OK) {
OGS_FSM_TRAN(s, &smf_gsm_state_wait_pfcp_deletion);
return;
gtp_xact = pfcp_xact->assoc_xact;
if (gtp_xact) {
switch (gtp_xact->gtp_version) {
case 1:
rv = smf_gtp1_send_create_pdp_context_response(
sess, gtp_xact);
break;
case 2:
rv = smf_gtp2_send_create_session_response(
sess, gtp_xact);
break;
default:
rv = OGS_ERROR;
break;
}
/* If no CreatePDPCtxResp can be sent,
* then tear down the session: */
if (rv != OGS_OK) {
OGS_FSM_TRAN(s, &smf_gsm_state_wait_pfcp_deletion);
return;
}
}
if (sess->gtp_rat_type == OGS_GTP2_RAT_TYPE_WLAN) {
@ -739,6 +746,9 @@ void smf_gsm_state_operational(ogs_fsm_t *s, smf_event_t *e)
smf_sess_t *sess = NULL;
ogs_pkbuf_t *pkbuf = NULL;
ogs_pfcp_xact_t *pfcp_xact = NULL;
ogs_pfcp_message_t *pfcp_message = NULL;
ogs_nas_5gs_message_t *nas_message = NULL;
ogs_sbi_stream_t *stream = NULL;
@ -815,6 +825,43 @@ void smf_gsm_state_operational(ogs_fsm_t *s, smf_event_t *e)
}
break;
case SMF_EVT_N4_MESSAGE:
pfcp_xact = e->pfcp_xact;
ogs_assert(pfcp_xact);
pfcp_message = e->pfcp_message;
ogs_assert(pfcp_message);
switch (pfcp_message->h.type) {
case OGS_PFCP_SESSION_ESTABLISHMENT_RESPONSE_TYPE:
if ((pfcp_xact->create_flags &
OGS_PFCP_CREATE_RESTORATION_INDICATION)) {
ogs_pfcp_session_establishment_response_t *rsp = NULL;
ogs_pfcp_f_seid_t *up_f_seid = NULL;
rsp = &pfcp_message->pfcp_session_establishment_response;
if (rsp->up_f_seid.presence == 0) {
ogs_error("No UP F-SEID");
break;
}
up_f_seid = rsp->up_f_seid.data;
ogs_assert(up_f_seid);
sess->upf_n4_seid = be64toh(up_f_seid->seid);
} else {
ogs_error("cannot handle PFCP Session Establishment Response");
}
break;
case OGS_PFCP_SESSION_DELETION_RESPONSE_TYPE:
ogs_error("Session Released by Error Indication");
OGS_FSM_TRAN(s, smf_gsm_state_session_will_release);
break;
default:
ogs_error("cannot handle PFCP message type[%d]",
pfcp_message->h.type);
}
break;
case OGS_EVENT_SBI_SERVER:
sbi_message = e->h.sbi.message;
ogs_assert(sbi_message);

View File

@ -202,10 +202,10 @@ uint32_t smf_gx_handle_cca_initial_request(
&bearer->pgw_s5u_addr, &bearer->pgw_s5u_addr6);
if (resource->info.teidri)
bearer->pgw_s5u_teid = OGS_PFCP_GTPU_INDEX_TO_TEID(
ul_pdr->index, resource->info.teidri,
ul_pdr->teid, resource->info.teidri,
resource->info.teid_range);
else
bearer->pgw_s5u_teid = ul_pdr->index;
bearer->pgw_s5u_teid = ul_pdr->teid;
} else {
if (sess->pfcp_node->addr.ogs_sa_family == AF_INET)
ogs_assert(OGS_OK ==
@ -218,7 +218,7 @@ uint32_t smf_gx_handle_cca_initial_request(
else
ogs_assert_if_reached();
bearer->pgw_s5u_teid = ul_pdr->index;
bearer->pgw_s5u_teid = ul_pdr->teid;
}
ogs_assert(OGS_OK ==
@ -231,7 +231,7 @@ uint32_t smf_gx_handle_cca_initial_request(
ogs_pfcp_sockaddr_to_f_teid(
bearer->pgw_s5u_addr, bearer->pgw_s5u_addr6,
&cp2up_pdr->f_teid, &cp2up_pdr->f_teid_len));
cp2up_pdr->f_teid.teid = cp2up_pdr->index;
cp2up_pdr->f_teid.teid = cp2up_pdr->teid;
ogs_assert(OGS_OK ==
ogs_pfcp_sockaddr_to_f_teid(

View File

@ -21,7 +21,7 @@
#include "n4-build.h"
ogs_pkbuf_t *smf_n4_build_session_establishment_request(
uint8_t type, smf_sess_t *sess)
uint8_t type, smf_sess_t *sess, ogs_pfcp_xact_t *xact)
{
ogs_pfcp_message_t *pfcp_message = NULL;
ogs_pfcp_session_establishment_request_t *req = NULL;
@ -46,6 +46,7 @@ ogs_pkbuf_t *smf_n4_build_session_establishment_request(
ogs_assert(sess);
smf_ue = sess->smf_ue;
ogs_assert(smf_ue);
ogs_assert(xact);
pfcp_message = ogs_calloc(1, sizeof(*pfcp_message));
if (!pfcp_message) {
@ -159,6 +160,16 @@ ogs_pkbuf_t *smf_n4_build_session_establishment_request(
req->s_nssai.data = &sess->s_nssai;
}
/* Restoration Indication */
if (xact->create_flags & OGS_PFCP_CREATE_RESTORATION_INDICATION) {
ogs_pfcp_sereq_flags_t sereq_flags;
sereq_flags.value = 0;
sereq_flags.restoration_indication = 1;
req->pfcpsereq_flags.presence = 1;
req->pfcpsereq_flags.u8 = sereq_flags.value;
}
pfcp_message->h.type = type;
pkbuf = ogs_pfcp_build_msg(pfcp_message);
ogs_expect(pkbuf);

View File

@ -27,7 +27,7 @@ extern "C" {
#endif
ogs_pkbuf_t *smf_n4_build_session_establishment_request(
uint8_t type, smf_sess_t *sess);
uint8_t type, smf_sess_t *sess, ogs_pfcp_xact_t *xact);
ogs_pkbuf_t *smf_n4_build_pdr_to_modify_list(
uint8_t type, smf_sess_t *sess, ogs_pfcp_xact_t *xact);
ogs_pkbuf_t *smf_n4_build_qos_flow_to_modify_list(

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2019 by Sukchan Lee <acetcom@gmail.com>
* Copyright (C) 2019-2023 by Sukchan Lee <acetcom@gmail.com>
*
* This file is part of Open5GS.
*
@ -148,8 +148,6 @@ uint8_t smf_5gc_n4_handle_session_establishment_response(
{
int i;
ogs_sbi_stream_t *stream = NULL;
uint8_t cause_value = OGS_PFCP_CAUSE_REQUEST_ACCEPTED;
uint8_t offending_ie_value = 0;
@ -164,9 +162,6 @@ uint8_t smf_5gc_n4_handle_session_establishment_response(
ogs_debug("Session Establishment Response [5gc]");
stream = xact->assoc_stream;
ogs_assert(stream);
ogs_pfcp_xact_commit(xact);
if (rsp->up_f_seid.presence == 0) {
@ -732,7 +727,6 @@ uint8_t smf_epc_n4_handle_session_establishment_response(
uint8_t cause_value = OGS_PFCP_CAUSE_REQUEST_ACCEPTED;
smf_bearer_t *bearer = NULL;
ogs_gtp_xact_t *gtp_xact = NULL;
ogs_pfcp_f_seid_t *up_f_seid = NULL;
@ -742,9 +736,6 @@ uint8_t smf_epc_n4_handle_session_establishment_response(
ogs_debug("Session Establishment Response [epc]");
gtp_xact = xact->assoc_xact;
ogs_assert(gtp_xact);
ogs_pfcp_xact_commit(xact);
if (rsp->up_f_seid.presence == 0) {
@ -1157,9 +1148,11 @@ void smf_n4_handle_session_report_request(
smf_sess_t *sess, ogs_pfcp_xact_t *pfcp_xact,
ogs_pfcp_session_report_request_t *pfcp_req)
{
smf_ue_t *smf_ue = NULL;
smf_bearer_t *qos_flow = NULL;
smf_bearer_t *bearer = NULL;
ogs_pfcp_pdr_t *pdr = NULL;
ogs_pfcp_far_t *far = NULL;
ogs_pfcp_report_type_t report_type;
uint8_t cause_value = 0;
@ -1193,6 +1186,9 @@ void smf_n4_handle_session_report_request(
}
ogs_assert(sess);
smf_ue = sess->smf_ue;
ogs_assert(smf_ue);
report_type.value = pfcp_req->report_type.u8;
if (report_type.downlink_data_report) {
@ -1279,21 +1275,10 @@ void smf_n4_handle_session_report_request(
}
if (report_type.error_indication_report) {
smf_ue_t *smf_ue = sess->smf_ue;
smf_sess_t *error_indication_session = NULL;
ogs_assert(smf_ue);
error_indication_session = smf_sess_find_by_error_indication_report(
smf_ue, &pfcp_req->error_indication_report);
if (error_indication_session) {
ogs_assert(OGS_OK ==
smf_5gc_pfcp_send_all_pdr_modification_request(
error_indication_session, NULL,
OGS_PFCP_MODIFY_DL_ONLY|OGS_PFCP_MODIFY_DEACTIVATE|
OGS_PFCP_MODIFY_ERROR_INDICATION,
0));
}
far = ogs_pfcp_far_find_by_pfcp_session_report(
&sess->pfcp, &pfcp_req->error_indication_report);
if (!far)
ogs_error("Cannot find Session in Error Indication");
}
if (report_type.usage_report) {
@ -1350,4 +1335,24 @@ void smf_n4_handle_session_report_request(
smf_pfcp_send_session_report_response(
pfcp_xact, sess, OGS_PFCP_CAUSE_SYSTEM_FAILURE));
}
/* Error Indication is handled last */
if (report_type.error_indication_report && far) {
if (sess->epc == true) {
ogs_error("[%s:%s] Error Indication from SGW-C",
smf_ue->imsi_bcd, sess->session.name);
ogs_assert(OGS_OK ==
smf_epc_pfcp_send_session_deletion_request(
sess, NULL));
} else {
ogs_warn("[%s:%s] Error Indication from gNB",
smf_ue->supi, sess->session.name);
ogs_assert(OGS_OK ==
smf_5gc_pfcp_send_all_pdr_modification_request(
sess, NULL,
OGS_PFCP_MODIFY_DL_ONLY|OGS_PFCP_MODIFY_DEACTIVATE|
OGS_PFCP_MODIFY_ERROR_INDICATION,
0));
}
}
}

View File

@ -585,10 +585,10 @@ bool smf_npcf_smpolicycontrol_handle_create(
&sess->upf_n3_addr, &sess->upf_n3_addr6);
if (resource->info.teidri)
sess->upf_n3_teid = OGS_PFCP_GTPU_INDEX_TO_TEID(
ul_pdr->index, resource->info.teidri,
ul_pdr->teid, resource->info.teidri,
resource->info.teid_range);
else
sess->upf_n3_teid = ul_pdr->index;
sess->upf_n3_teid = ul_pdr->teid;
} else {
if (sess->pfcp_node->addr.ogs_sa_family == AF_INET)
ogs_assert(OGS_OK ==
@ -601,7 +601,7 @@ bool smf_npcf_smpolicycontrol_handle_create(
else
ogs_assert_if_reached();
sess->upf_n3_teid = ul_pdr->index;
sess->upf_n3_teid = ul_pdr->teid;
}
ogs_assert(OGS_OK ==
@ -614,7 +614,7 @@ bool smf_npcf_smpolicycontrol_handle_create(
ogs_pfcp_sockaddr_to_f_teid(
sess->upf_n3_addr, sess->upf_n3_addr6,
&cp2up_pdr->f_teid, &cp2up_pdr->f_teid_len));
cp2up_pdr->f_teid.teid = cp2up_pdr->index;
cp2up_pdr->f_teid.teid = cp2up_pdr->teid;
ogs_assert(OGS_OK ==
ogs_pfcp_sockaddr_to_f_teid(
@ -630,7 +630,7 @@ bool smf_npcf_smpolicycontrol_handle_create(
up2cp_pdr->precedence = OGS_PFCP_UP2CP_PDR_PRECEDENCE;
ogs_assert(OGS_OK ==
smf_5gc_pfcp_send_session_establishment_request(sess, stream));
smf_5gc_pfcp_send_session_establishment_request(sess, 0));
return true;

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2019 by Sukchan Lee <acetcom@gmail.com>
* Copyright (C) 2019-2023 by Sukchan Lee <acetcom@gmail.com>
*
* This file is part of Open5GS.
*
@ -362,7 +362,7 @@ int smf_pfcp_send_modify_list(
}
int smf_5gc_pfcp_send_session_establishment_request(
smf_sess_t *sess, ogs_sbi_stream_t *stream)
smf_sess_t *sess, uint64_t flags)
{
int rv;
ogs_pkbuf_t *n4buf = NULL;
@ -370,7 +370,6 @@ int smf_5gc_pfcp_send_session_establishment_request(
ogs_pfcp_xact_t *xact = NULL;
ogs_assert(sess);
ogs_assert(stream);
xact = ogs_pfcp_xact_local_create(sess->pfcp_node, sess_5gc_timeout, sess);
if (!xact) {
@ -378,14 +377,44 @@ int smf_5gc_pfcp_send_session_establishment_request(
return OGS_ERROR;
}
xact->assoc_stream = stream;
xact->local_seid = sess->smf_n4_seid;
xact->create_flags = flags;
memset(&h, 0, sizeof(ogs_pfcp_header_t));
h.type = OGS_PFCP_SESSION_ESTABLISHMENT_REQUEST_TYPE;
/*
* 7.2.2.4.2 Conditions for Sending SEID=0 in PFCP Header
*
* If a peer's SEID is not available, the SEID field shall still be present
* in the header and its value shall be set to "0" in the following messages:
*
* - PFCP Session Establishment Request message on Sxa/Sxb/Sxc/N4;
*
* - If a node receives a message for which it has no session, i.e.
* if SEID in the PFCP header is not known, it shall respond
* with "Session context not found" cause in the corresponding
* response message to the sender, the SEID used in the PFCP header
* in the response message shall be then set to "0";
*
* - If a node receives a request message containing protocol error,
* e.g. Mandatory IE missing, which requires the receiver
* to reject the message as specified in clause 7.6, it shall reject
* the request message. For the response message, the node should look up
* the remote peer's SEID and accordingly set SEID in the PFCP header
* and the message cause code. As an implementation option,
* the node may not look up the remote peer's SEID and
* set the PFCP header SEID to "0" in the response message.
* However in this case, the cause value shall not be set
* to "Session not found".
*
* - When the UP function sends PFCP Session Report Request message
* over N4 towards another SMF or another PFCP entity in the SMF
* as specified in clause 5.22.2 and clause 5.22.3.
*/
h.seid = sess->upf_n4_seid;
n4buf = smf_n4_build_session_establishment_request(h.type, sess);
n4buf = smf_n4_build_session_establishment_request(h.type, sess, xact);
if (!n4buf) {
ogs_error("smf_n4_build_session_establishment_request() failed");
return OGS_ERROR;
@ -506,7 +535,7 @@ int smf_5gc_pfcp_send_session_deletion_request(
}
int smf_epc_pfcp_send_session_establishment_request(
smf_sess_t *sess, void *gtp_xact)
smf_sess_t *sess, void *gtp_xact, uint64_t flags)
{
int rv;
ogs_pkbuf_t *n4buf = NULL;
@ -524,12 +553,43 @@ int smf_epc_pfcp_send_session_establishment_request(
xact->epc = true; /* EPC PFCP transaction */
xact->assoc_xact = gtp_xact;
xact->local_seid = sess->smf_n4_seid;
xact->create_flags = flags;
memset(&h, 0, sizeof(ogs_pfcp_header_t));
h.type = OGS_PFCP_SESSION_ESTABLISHMENT_REQUEST_TYPE;
/*
* 7.2.2.4.2 Conditions for Sending SEID=0 in PFCP Header
*
* If a peer's SEID is not available, the SEID field shall still be present
* in the header and its value shall be set to "0" in the following messages:
*
* - PFCP Session Establishment Request message on Sxa/Sxb/Sxc/N4;
*
* - If a node receives a message for which it has no session, i.e.
* if SEID in the PFCP header is not known, it shall respond
* with "Session context not found" cause in the corresponding
* response message to the sender, the SEID used in the PFCP header
* in the response message shall be then set to "0";
*
* - If a node receives a request message containing protocol error,
* e.g. Mandatory IE missing, which requires the receiver
* to reject the message as specified in clause 7.6, it shall reject
* the request message. For the response message, the node should look up
* the remote peer's SEID and accordingly set SEID in the PFCP header
* and the message cause code. As an implementation option,
* the node may not look up the remote peer's SEID and
* set the PFCP header SEID to "0" in the response message.
* However in this case, the cause value shall not be set
* to "Session not found".
*
* - When the UP function sends PFCP Session Report Request message
* over N4 towards another SMF or another PFCP entity in the SMF
* as specified in clause 5.22.2 and clause 5.22.3.
*/
h.seid = sess->upf_n4_seid;
n4buf = smf_n4_build_session_establishment_request(h.type, sess);
n4buf = smf_n4_build_session_establishment_request(h.type, sess, xact);
if (!n4buf) {
ogs_error("smf_n4_build_session_establishment_request() failed");
return OGS_ERROR;

View File

@ -36,7 +36,7 @@ int smf_pfcp_send_modify_list(
ogs_pfcp_xact_t *xact, ogs_time_t duration);
int smf_5gc_pfcp_send_session_establishment_request(
smf_sess_t *sess, ogs_sbi_stream_t *stream);
smf_sess_t *sess, uint64_t flags);
int smf_5gc_pfcp_send_all_pdr_modification_request(
smf_sess_t *sess, ogs_sbi_stream_t *stream,
uint64_t flags, ogs_time_t duration);
@ -47,7 +47,7 @@ int smf_5gc_pfcp_send_session_deletion_request(
smf_sess_t *sess, ogs_sbi_stream_t *stream, int trigger);
int smf_epc_pfcp_send_session_establishment_request(
smf_sess_t *sess, void *gtp_xact);
smf_sess_t *sess, void *gtp_xact, uint64_t flags);
int smf_epc_pfcp_send_all_pdr_modification_request(
smf_sess_t *sess, void *gtp_xact, ogs_pkbuf_t *gtpbuf,
uint64_t flags, uint8_t gtp_pti, uint8_t gtp_cause);

View File

@ -22,6 +22,7 @@
#include "n4-handler.h"
static void pfcp_restoration(ogs_pfcp_node_t *node);
static void reselect_upf(ogs_pfcp_node_t *node);
static void node_timeout(ogs_pfcp_xact_t *xact, void *data);
@ -191,7 +192,7 @@ void smf_pfcp_state_associated(ogs_fsm_t *s, smf_event_t *e)
ogs_pfcp_send_heartbeat_request(node, node_timeout));
if (node->restoration_required == true) {
/* PFCP Restoration is being performed after PFCP association */
pfcp_restoration(node);
node->restoration_required = false;
ogs_error("PFCP restoration");
}
@ -244,6 +245,7 @@ void smf_pfcp_state_associated(ogs_fsm_t *s, smf_event_t *e)
* If the peer PFCP entity is performing the association,
* Restoration can be performed immediately.
*/
pfcp_restoration(node);
node->restoration_required = false;
ogs_error("PFCP restoration");
}
@ -270,6 +272,7 @@ void smf_pfcp_state_associated(ogs_fsm_t *s, smf_event_t *e)
* If the peer PFCP entity is performing the association,
* Restoration can be performed immediately.
*/
pfcp_restoration(node);
node->restoration_required = false;
ogs_error("PFCP restoration");
}
@ -409,10 +412,52 @@ void smf_pfcp_state_exception(ogs_fsm_t *s, smf_event_t *e)
}
}
static void pfcp_restoration(ogs_pfcp_node_t *node)
{
smf_ue_t *smf_ue = NULL;
char buf1[OGS_ADDRSTRLEN];
char buf2[OGS_ADDRSTRLEN];
ogs_list_for_each(&smf_self()->smf_ue_list, smf_ue) {
smf_sess_t *sess = NULL;
ogs_assert(smf_ue);
ogs_list_for_each(&smf_ue->sess_list, sess) {
ogs_assert(sess);
if (node == sess->pfcp_node) {
if (sess->epc) {
ogs_info("UE IMSI[%s] APN[%s] IPv4[%s] IPv6[%s]",
smf_ue->imsi_bcd, sess->session.name,
sess->ipv4 ?
OGS_INET_NTOP(&sess->ipv4->addr, buf1) : "",
sess->ipv6 ?
OGS_INET6_NTOP(&sess->ipv6->addr, buf2) : "");
ogs_assert(OGS_OK ==
smf_epc_pfcp_send_session_establishment_request(
sess, NULL,
OGS_PFCP_CREATE_RESTORATION_INDICATION));
} else {
ogs_info("UE SUPI[%s] DNN[%s] IPv4[%s] IPv6[%s]",
smf_ue->supi, sess->session.name,
sess->ipv4 ?
OGS_INET_NTOP(&sess->ipv4->addr, buf1) : "",
sess->ipv6 ?
OGS_INET6_NTOP(&sess->ipv6->addr, buf2) : "");
ogs_assert(OGS_OK ==
smf_5gc_pfcp_send_session_establishment_request(
sess, OGS_PFCP_CREATE_RESTORATION_INDICATION));
}
}
}
}
}
static void reselect_upf(ogs_pfcp_node_t *node)
{
int r;
smf_ue_t *smf_ue = NULL, *next_ue = NULL;;
smf_ue_t *smf_ue = NULL;
ogs_pfcp_node_t *iter = NULL;
ogs_assert(node);
@ -434,19 +479,18 @@ static void reselect_upf(ogs_pfcp_node_t *node)
return;
}
ogs_list_for_each_safe(&smf_self()->smf_ue_list, next_ue, smf_ue) {
smf_sess_t *sess = NULL, *next_sess = NULL;;
ogs_list_for_each(&smf_self()->smf_ue_list, smf_ue) {
smf_sess_t *sess = NULL;
ogs_assert(smf_ue);
ogs_list_for_each_safe(&smf_ue->sess_list, next_sess, sess) {
ogs_list_for_each(&smf_ue->sess_list, sess) {
ogs_assert(sess);
if (sess->epc) {
ogs_error("[%s:%s] EPC restoration is not implemented",
smf_ue->imsi_bcd, sess->session.name);
} else {
ogs_assert(sess->sm_context_ref);
if (node == sess->pfcp_node) {
if (node == sess->pfcp_node) {
if (sess->epc) {
ogs_error("[%s:%s] EPC restoration is not implemented",
smf_ue->imsi_bcd, sess->session.name);
} else {
smf_npcf_smpolicycontrol_param_t param;
ogs_info("[%s:%d] SMF-initiated Deletion",
@ -479,18 +523,6 @@ static void node_timeout(ogs_pfcp_xact_t *xact, void *data)
switch (type) {
case OGS_PFCP_HEARTBEAT_REQUEST_TYPE:
ogs_assert(data);
/*
* The code below is not secure.
* Session does not differentiate between EPC and 5GC.
* And, it does not check whether there are other PFCP Nodes.
*
* So, UPF redundancy will be implemented later.
*
* We plan to do this again after testing with restoration first
* in case peer PFCP restarts.
*/
reselect_upf(data);
e = smf_event_new(SMF_EVT_N4_NO_HEARTBEAT);

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2019 by Sukchan Lee <acetcom@gmail.com>
* Copyright (C) 2019-2023 by Sukchan Lee <acetcom@gmail.com>
*
* This file is part of Open5GS.
*
@ -25,6 +25,7 @@ static upf_context_t self;
int __upf_log_domain;
static OGS_POOL(upf_sess_pool, upf_sess_t);
static OGS_POOL(upf_n4_seid_pool, ogs_pool_id_t);
static int context_initialized = 0;
@ -49,11 +50,15 @@ void upf_context_init(void)
ogs_list_init(&self.sess_list);
ogs_pool_init(&upf_sess_pool, ogs_app()->pool.sess);
ogs_pool_init(&upf_n4_seid_pool, ogs_app()->pool.sess);
ogs_pool_random_id_generate(&upf_n4_seid_pool);
self.seid_hash = ogs_hash_make();
ogs_assert(self.seid_hash);
self.f_seid_hash = ogs_hash_make();
ogs_assert(self.f_seid_hash);
self.upf_n4_seid_hash = ogs_hash_make();
ogs_assert(self.upf_n4_seid_hash);
self.smf_n4_seid_hash = ogs_hash_make();
ogs_assert(self.smf_n4_seid_hash);
self.smf_n4_f_seid_hash = ogs_hash_make();
ogs_assert(self.smf_n4_f_seid_hash);
self.ipv4_hash = ogs_hash_make();
ogs_assert(self.ipv4_hash);
self.ipv6_hash = ogs_hash_make();
@ -77,10 +82,12 @@ void upf_context_final(void)
upf_sess_remove_all();
ogs_assert(self.seid_hash);
ogs_hash_destroy(self.seid_hash);
ogs_assert(self.f_seid_hash);
ogs_hash_destroy(self.f_seid_hash);
ogs_assert(self.upf_n4_seid_hash);
ogs_hash_destroy(self.upf_n4_seid_hash);
ogs_assert(self.smf_n4_seid_hash);
ogs_hash_destroy(self.smf_n4_seid_hash);
ogs_assert(self.smf_n4_f_seid_hash);
ogs_hash_destroy(self.smf_n4_f_seid_hash);
ogs_assert(self.ipv4_hash);
ogs_hash_destroy(self.ipv4_hash);
ogs_assert(self.ipv6_hash);
@ -90,6 +97,7 @@ void upf_context_final(void)
free_upf_route_trie_node(self.ipv6_framed_routes);
ogs_pool_final(&upf_sess_pool);
ogs_pool_final(&upf_n4_seid_pool);
context_initialized = 0;
}
@ -171,10 +179,14 @@ upf_sess_t *upf_sess_add(ogs_pfcp_f_seid_t *cp_f_seid)
ogs_pfcp_pool_init(&sess->pfcp);
sess->index = ogs_pool_index(&upf_sess_pool, sess);
ogs_assert(sess->index > 0 && sess->index <= ogs_app()->pool.sess);
/* Set UPF-N4-SEID */
ogs_pool_alloc(&upf_n4_seid_pool, &sess->upf_n4_seid_node);
ogs_assert(sess->upf_n4_seid_node);
sess->upf_n4_seid = sess->index;
sess->upf_n4_seid = *(sess->upf_n4_seid_node);
ogs_hash_set(self.upf_n4_seid_hash, &sess->upf_n4_seid,
sizeof(sess->upf_n4_seid), sess);
/* Since F-SEID is composed of ogs_ip_t and uint64-seid,
* all these values must be put into the structure-smf_n4_f_seid
@ -183,9 +195,9 @@ upf_sess_t *upf_sess_add(ogs_pfcp_f_seid_t *cp_f_seid)
ogs_assert(OGS_OK ==
ogs_pfcp_f_seid_to_ip(cp_f_seid, &sess->smf_n4_f_seid.ip));
ogs_hash_set(self.f_seid_hash, &sess->smf_n4_f_seid,
ogs_hash_set(self.smf_n4_f_seid_hash, &sess->smf_n4_f_seid,
sizeof(sess->smf_n4_f_seid), sess);
ogs_hash_set(self.seid_hash, &sess->smf_n4_f_seid.seid,
ogs_hash_set(self.smf_n4_seid_hash, &sess->smf_n4_f_seid.seid,
sizeof(sess->smf_n4_f_seid.seid), sess);
ogs_list_add(&self.sess_list, sess);
@ -206,9 +218,12 @@ int upf_sess_remove(upf_sess_t *sess)
ogs_list_remove(&self.sess_list, sess);
ogs_pfcp_sess_clear(&sess->pfcp);
ogs_hash_set(self.seid_hash, &sess->smf_n4_f_seid.seid,
ogs_hash_set(self.upf_n4_seid_hash, &sess->upf_n4_seid,
sizeof(sess->upf_n4_seid), NULL);
ogs_hash_set(self.smf_n4_seid_hash, &sess->smf_n4_f_seid.seid,
sizeof(sess->smf_n4_f_seid.seid), NULL);
ogs_hash_set(self.f_seid_hash, &sess->smf_n4_f_seid,
ogs_hash_set(self.smf_n4_f_seid_hash, &sess->smf_n4_f_seid,
sizeof(sess->smf_n4_f_seid), NULL);
if (sess->ipv4) {
@ -226,6 +241,7 @@ int upf_sess_remove(upf_sess_t *sess)
ogs_pfcp_pool_final(&sess->pfcp);
ogs_pool_free(&upf_n4_seid_pool, sess->upf_n4_seid_node);
ogs_pool_free(&upf_sess_pool, sess);
if (sess->apn_dnn)
ogs_free(sess->apn_dnn);
@ -246,14 +262,9 @@ void upf_sess_remove_all(void)
}
}
upf_sess_t *upf_sess_find(uint32_t index)
{
return ogs_pool_find(&upf_sess_pool, index);
}
upf_sess_t *upf_sess_find_by_smf_n4_seid(uint64_t seid)
{
return (upf_sess_t *)ogs_hash_get(self.seid_hash, &seid, sizeof(seid));
return ogs_hash_get(self.smf_n4_seid_hash, &seid, sizeof(seid));
}
upf_sess_t *upf_sess_find_by_smf_n4_f_seid(ogs_pfcp_f_seid_t *f_seid)
@ -267,12 +278,12 @@ upf_sess_t *upf_sess_find_by_smf_n4_f_seid(ogs_pfcp_f_seid_t *f_seid)
ogs_assert(OGS_OK == ogs_pfcp_f_seid_to_ip(f_seid, &key.ip));
key.seid = f_seid->seid;
return (upf_sess_t *)ogs_hash_get(self.f_seid_hash, &key, sizeof(key));
return ogs_hash_get(self.smf_n4_f_seid_hash, &key, sizeof(key));
}
upf_sess_t *upf_sess_find_by_upf_n4_seid(uint64_t seid)
{
return upf_sess_find(seid);
return ogs_hash_get(self.upf_n4_seid_hash, &seid, sizeof(seid));
}
upf_sess_t *upf_sess_find_by_ipv4(uint32_t addr)
@ -357,7 +368,10 @@ upf_sess_t *upf_sess_add_by_message(ogs_pfcp_message_t *message)
sess = upf_sess_find_by_smf_n4_f_seid(f_seid);
if (!sess) {
sess = upf_sess_add(f_seid);
if (!sess) return NULL;
if (!sess) {
ogs_error("No Session Context");
return NULL;
}
}
ogs_assert(sess);

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2019 by Sukchan Lee <acetcom@gmail.com>
* Copyright (C) 2019-2023 by Sukchan Lee <acetcom@gmail.com>
*
* This file is part of Open5GS.
*
@ -48,14 +48,18 @@ extern int __upf_log_domain;
struct upf_route_trie_node;
typedef struct upf_context_s {
ogs_hash_t *seid_hash; /* hash table (SEID) */
ogs_hash_t *f_seid_hash; /* hash table (F-SEID) */
ogs_hash_t *ipv4_hash; /* hash table (IPv4 Address) */
ogs_hash_t *ipv6_hash; /* hash table (IPv6 Address) */
struct upf_route_trie_node *ipv4_framed_routes; /* IPv4 framed routes trie */
struct upf_route_trie_node *ipv6_framed_routes; /* IPv6 framed routes trie */
ogs_hash_t *upf_n4_seid_hash; /* hash table (UPF-N4-SEID) */
ogs_hash_t *smf_n4_seid_hash; /* hash table (SMF-N4-SEID) */
ogs_hash_t *smf_n4_f_seid_hash; /* hash table (SMF-N4-F-SEID) */
ogs_hash_t *ipv4_hash; /* hash table (IPv4 Address) */
ogs_hash_t *ipv6_hash; /* hash table (IPv6 Address) */
ogs_list_t sess_list;
/* IPv4 framed routes trie */
struct upf_route_trie_node *ipv4_framed_routes;
/* IPv6 framed routes trie */
struct upf_route_trie_node *ipv6_framed_routes;
ogs_list_t sess_list;
} upf_context_t;
/* trie mapping from IP framed routes to session. */
@ -96,11 +100,11 @@ typedef struct upf_sess_urr_acc_s {
#define UPF_SESS(pfcp_sess) ogs_container_of(pfcp_sess, upf_sess_t, pfcp)
typedef struct upf_sess_s {
ogs_lnode_t lnode;
uint32_t index; /**< An index of this node */
ogs_pool_id_t *upf_n4_seid_node; /* A node of UPF-N4-SEID */
ogs_pfcp_sess_t pfcp;
uint64_t upf_n4_seid; /* UPF SEID is dervied from INDEX */
uint64_t upf_n4_seid; /* UPF SEID is dervied from NODE */
struct {
uint64_t seid;
ogs_ip_t ip;
@ -132,7 +136,6 @@ upf_sess_t *upf_sess_add_by_message(ogs_pfcp_message_t *message);
upf_sess_t *upf_sess_add(ogs_pfcp_f_seid_t *f_seid);
int upf_sess_remove(upf_sess_t *sess);
void upf_sess_remove_all(void);
upf_sess_t *upf_sess_find(uint32_t index);
upf_sess_t *upf_sess_find_by_smf_n4_seid(uint64_t seid);
upf_sess_t *upf_sess_find_by_smf_n4_f_seid(ogs_pfcp_f_seid_t *f_seid);
upf_sess_t *upf_sess_find_by_upf_n4_seid(uint64_t seid);

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2019 by Sukchan Lee <acetcom@gmail.com>
* Copyright (C) 2019-2023 by Sukchan Lee <acetcom@gmail.com>
*
* This file is part of Open5GS.
*
@ -258,11 +258,13 @@ static void _gtpv1_u_recv_cb(short when, ogs_socket_t fd, void *data)
{
int len;
ssize_t size;
char buf[OGS_ADDRSTRLEN];
char buf1[OGS_ADDRSTRLEN];
char buf2[OGS_ADDRSTRLEN];
upf_sess_t *sess = NULL;
ogs_pkbuf_t *pkbuf = NULL;
ogs_sock_t *sock = NULL;
ogs_sockaddr_t from;
ogs_gtp2_header_t *gtp_h = NULL;
@ -272,6 +274,8 @@ static void _gtpv1_u_recv_cb(short when, ogs_socket_t fd, void *data)
uint8_t qfi;
ogs_assert(fd != INVALID_SOCKET);
sock = data;
ogs_assert(sock);
pkbuf = ogs_pkbuf_alloc(packet_pool, OGS_MAX_PKT_LEN);
ogs_assert(pkbuf);
@ -300,14 +304,14 @@ static void _gtpv1_u_recv_cb(short when, ogs_socket_t fd, void *data)
if (gtp_h->type == OGS_GTPU_MSGTYPE_ECHO_REQ) {
ogs_pkbuf_t *echo_rsp;
ogs_debug("[RECV] Echo Request from [%s]", OGS_ADDR(&from, buf));
ogs_debug("[RECV] Echo Request from [%s]", OGS_ADDR(&from, buf1));
echo_rsp = ogs_gtp2_handle_echo_req(pkbuf);
ogs_expect(echo_rsp);
if (echo_rsp) {
ssize_t sent;
/* Echo reply */
ogs_debug("[SEND] Echo Response to [%s]", OGS_ADDR(&from, buf));
ogs_debug("[SEND] Echo Response to [%s]", OGS_ADDR(&from, buf1));
sent = ogs_sendto(fd, echo_rsp->data, echo_rsp->len, 0, &from);
if (sent < 0 || sent != echo_rsp->len) {
@ -322,7 +326,7 @@ static void _gtpv1_u_recv_cb(short when, ogs_socket_t fd, void *data)
teid = be32toh(gtp_h->teid);
ogs_trace("[RECV] GPU-U Type [%d] from [%s] : TEID[0x%x]",
gtp_h->type, OGS_ADDR(&from, buf), teid);
gtp_h->type, OGS_ADDR(&from, buf1), teid);
qfi = 0;
if (gtp_h->flags & OGS_GTPU_FLAGS_E) {
@ -369,7 +373,7 @@ static void _gtpv1_u_recv_cb(short when, ogs_socket_t fd, void *data)
} else if (gtp_h->type == OGS_GTPU_MSGTYPE_ERR_IND) {
ogs_pfcp_far_t *far = NULL;
far = ogs_pfcp_far_find_by_error_indication(pkbuf);
far = ogs_pfcp_far_find_by_gtpu_error_indication(pkbuf);
if (far) {
ogs_assert(true ==
ogs_pfcp_up_handle_error_indication(far, &report));
@ -419,12 +423,32 @@ static void _gtpv1_u_recv_cb(short when, ogs_socket_t fd, void *data)
pfcp_object = ogs_pfcp_object_find_by_teid(teid);
if (!pfcp_object) {
/* TODO : Send Error Indication */
/*
* TS23.527 Restoration procedures
* 4.3 UPF Restoration Procedures
* 4.3.2 Restoration Procedure for PSA UPF Restart
*
* The UPF shall not send GTP-U Error indication message
* for a configurable period after an UPF restart
* when the UPF receives a G-PDU not matching any PDRs.
*/
if (ogs_time_ntp32_now() >
(ogs_pfcp_self()->local_recovery +
ogs_time_sec(
ogs_app()->time.message.pfcp.association_interval))) {
ogs_error("[%s] Send Error Indication [TEID:0x%x] to [%s]",
OGS_ADDR(&sock->local_addr, buf1),
teid,
OGS_ADDR(&from, buf2));
ogs_gtp1_send_error_indication(sock, teid, qfi, &from);
}
goto cleanup;
}
switch(pfcp_object->type) {
case OGS_PFCP_OBJ_PDR_TYPE:
/* UPF does not use PDR TYPE */
ogs_assert_if_reached();
pdr = (ogs_pfcp_pdr_t *)pfcp_object;
ogs_assert(pdr);
break;
@ -456,7 +480,26 @@ static void _gtpv1_u_recv_cb(short when, ogs_socket_t fd, void *data)
}
if (!pdr) {
/* TODO : Send Error Indication */
/*
* TS23.527 Restoration procedures
* 4.3 UPF Restoration Procedures
* 4.3.2 Restoration Procedure for PSA UPF Restart
*
* The UPF shall not send GTP-U Error indication message
* for a configurable period after an UPF restart
* when the UPF receives a G-PDU not matching any PDRs.
*/
if (ogs_time_ntp32_now() >
(ogs_pfcp_self()->local_recovery +
ogs_time_sec(
ogs_app()->time.message.pfcp.association_interval))) {
ogs_error(
"[%s] Send Error Indication [TEID:0x%x] to [%s]",
OGS_ADDR(&sock->local_addr, buf1),
teid,
OGS_ADDR(&from, buf2));
ogs_gtp1_send_error_indication(sock, teid, qfi, &from);
}
goto cleanup;
}
@ -684,7 +727,7 @@ int upf_gtp_init(void)
config.cluster_2048_pool = ogs_app()->pool.packet;
#if OGS_USE_TALLOC
#if OGS_USE_TALLOC == 1
/* allocate a talloc pool for GTP to ensure it doesn't have to go back
* to the libc malloc all the time */
packet_pool = talloc_pool(__ogs_talloc_core, 1000*1024);

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2019 by Sukchan Lee <acetcom@gmail.com>
* Copyright (C) 2019-2023 by Sukchan Lee <acetcom@gmail.com>
*
* This file is part of Open5GS.
*
@ -55,6 +55,9 @@ void upf_n4_handle_session_establishment_request(
uint8_t offending_ie_value = 0;
int i;
ogs_pfcp_sereq_flags_t sereq_flags;
bool restoration_indication = false;
upf_metrics_inst_global_inc(UPF_METR_GLOB_CTR_SM_N4SESSIONESTABREQ);
ogs_assert(xact);
@ -74,9 +77,14 @@ void upf_n4_handle_session_establishment_request(
return;
}
memset(&sereq_flags, 0, sizeof(sereq_flags));
if (req->pfcpsereq_flags.presence == 1)
sereq_flags.value = req->pfcpsereq_flags.u8;
for (i = 0; i < OGS_MAX_NUM_OF_PDR; i++) {
created_pdr[i] = ogs_pfcp_handle_create_pdr(&sess->pfcp,
&req->create_pdr[i], &cause_value, &offending_ie_value);
&req->create_pdr[i], &sereq_flags,
&cause_value, &offending_ie_value);
if (created_pdr[i] == NULL)
break;
}
@ -123,6 +131,18 @@ void upf_n4_handle_session_establishment_request(
if (cause_value != OGS_PFCP_CAUSE_REQUEST_ACCEPTED)
goto cleanup;
/* PFCPSEReq-Flags */
if (sereq_flags.restoration_indication == 1) {
for (i = 0; i < num_of_created_pdr; i++) {
pdr = created_pdr[i];
ogs_assert(pdr);
if (pdr->f_teid_len)
ogs_pfcp_pdr_swap_teid(pdr);
}
restoration_indication = true;
}
/* Setup GTP Node */
ogs_list_for_each(&sess->pfcp.far_list, far) {
ogs_assert(OGS_ERROR != ogs_pfcp_setup_far_gtpu_node(far));
@ -162,65 +182,9 @@ void upf_n4_handle_session_establishment_request(
}
/* Setup UPF-N3-TEID & QFI Hash */
if (pdr->f_teid_len) {
ogs_pfcp_object_type_e type = OGS_PFCP_OBJ_SESS_TYPE;
if (ogs_pfcp_self()->up_function_features.ftup &&
pdr->f_teid.ch) {
ogs_pfcp_pdr_t *choosed_pdr = NULL;
if (pdr->f_teid.chid) {
choosed_pdr = ogs_pfcp_pdr_find_by_choose_id(
&sess->pfcp, pdr->f_teid.choose_id);
if (!choosed_pdr) {
pdr->chid = true;
pdr->choose_id = pdr->f_teid.choose_id;
}
} else {
type = OGS_PFCP_OBJ_PDR_TYPE;
}
if (choosed_pdr) {
pdr->f_teid_len = choosed_pdr->f_teid_len;
memcpy(&pdr->f_teid, &choosed_pdr->f_teid, pdr->f_teid_len);
} else {
ogs_gtpu_resource_t *resource = NULL;
resource = ogs_pfcp_find_gtpu_resource(
&ogs_gtp_self()->gtpu_resource_list,
pdr->dnn, OGS_PFCP_INTERFACE_ACCESS);
if (resource) {
ogs_assert(
(resource->info.v4 && pdr->f_teid.ipv4) ||
(resource->info.v6 && pdr->f_teid.ipv6));
ogs_assert(OGS_OK ==
ogs_pfcp_user_plane_ip_resource_info_to_f_teid(
&resource->info, &pdr->f_teid, &pdr->f_teid_len));
if (resource->info.teidri)
pdr->f_teid.teid = OGS_PFCP_GTPU_INDEX_TO_TEID(
pdr->index, resource->info.teidri,
resource->info.teid_range);
else
pdr->f_teid.teid = pdr->index;
} else {
ogs_assert(
(ogs_gtp_self()->gtpu_addr && pdr->f_teid.ipv4) ||
(ogs_gtp_self()->gtpu_addr6 && pdr->f_teid.ipv6));
ogs_assert(OGS_OK ==
ogs_pfcp_sockaddr_to_f_teid(
pdr->f_teid.ipv4 ?
ogs_gtp_self()->gtpu_addr : NULL,
pdr->f_teid.ipv6 ?
ogs_gtp_self()->gtpu_addr6 : NULL,
&pdr->f_teid, &pdr->f_teid_len));
pdr->f_teid.teid = pdr->index;
}
}
}
ogs_pfcp_object_teid_hash_set(type, pdr);
}
if (pdr->f_teid_len)
ogs_pfcp_object_teid_hash_set(
OGS_PFCP_OBJ_SESS_TYPE, pdr, restoration_indication);
}
/* Send Buffered Packet to gNB/SGW */
@ -230,9 +194,16 @@ void upf_n4_handle_session_establishment_request(
}
}
ogs_assert(OGS_OK ==
upf_pfcp_send_session_establishment_response(
xact, sess, created_pdr, num_of_created_pdr));
if (restoration_indication == true ||
ogs_pfcp_self()->up_function_features.ftup == 0)
ogs_assert(OGS_OK ==
upf_pfcp_send_session_establishment_response(
xact, sess, NULL, 0));
else
ogs_assert(OGS_OK ==
upf_pfcp_send_session_establishment_response(
xact, sess, created_pdr, num_of_created_pdr));
return;
cleanup:
@ -273,7 +244,7 @@ void upf_n4_handle_session_modification_request(
for (i = 0; i < OGS_MAX_NUM_OF_PDR; i++) {
created_pdr[i] = ogs_pfcp_handle_create_pdr(&sess->pfcp,
&req->create_pdr[i], &cause_value, &offending_ie_value);
&req->create_pdr[i], NULL, &cause_value, &offending_ie_value);
if (created_pdr[i] == NULL)
break;
}
@ -406,70 +377,13 @@ void upf_n4_handle_session_modification_request(
ogs_pfcp_far_f_teid_hash_set(far);
}
/* Setup UPF-N3-TEID & QFI Hash */
for (i = 0; i < num_of_created_pdr; i++) {
pdr = created_pdr[i];
ogs_assert(pdr);
if (pdr->f_teid_len) {
ogs_pfcp_object_type_e type = OGS_PFCP_OBJ_SESS_TYPE;
if (ogs_pfcp_self()->up_function_features.ftup &&
pdr->f_teid.ch) {
ogs_pfcp_pdr_t *choosed_pdr = NULL;
if (pdr->f_teid.chid) {
choosed_pdr = ogs_pfcp_pdr_find_by_choose_id(
&sess->pfcp, pdr->f_teid.choose_id);
if (!choosed_pdr) {
pdr->chid = true;
pdr->choose_id = pdr->f_teid.choose_id;
}
} else {
type = OGS_PFCP_OBJ_PDR_TYPE;
}
if (choosed_pdr) {
pdr->f_teid_len = choosed_pdr->f_teid_len;
memcpy(&pdr->f_teid, &choosed_pdr->f_teid, pdr->f_teid_len);
} else {
ogs_gtpu_resource_t *resource = NULL;
resource = ogs_pfcp_find_gtpu_resource(
&ogs_gtp_self()->gtpu_resource_list,
pdr->dnn, OGS_PFCP_INTERFACE_ACCESS);
if (resource) {
ogs_assert(
(resource->info.v4 && pdr->f_teid.ipv4) ||
(resource->info.v6 && pdr->f_teid.ipv6));
ogs_assert(OGS_OK ==
ogs_pfcp_user_plane_ip_resource_info_to_f_teid(
&resource->info, &pdr->f_teid, &pdr->f_teid_len));
if (resource->info.teidri)
pdr->f_teid.teid = OGS_PFCP_GTPU_INDEX_TO_TEID(
pdr->index, resource->info.teidri,
resource->info.teid_range);
else
pdr->f_teid.teid = pdr->index;
} else {
ogs_assert(
(ogs_gtp_self()->gtpu_addr && pdr->f_teid.ipv4) ||
(ogs_gtp_self()->gtpu_addr6 && pdr->f_teid.ipv6));
ogs_assert(OGS_OK ==
ogs_pfcp_sockaddr_to_f_teid(
pdr->f_teid.ipv4 ?
ogs_gtp_self()->gtpu_addr : NULL,
pdr->f_teid.ipv6 ?
ogs_gtp_self()->gtpu_addr6 : NULL,
&pdr->f_teid, &pdr->f_teid_len));
pdr->f_teid.teid = pdr->index;
}
}
}
ogs_pfcp_object_teid_hash_set(type, pdr);
}
/* Setup UPF-N3-TEID & QFI Hash */
if (pdr->f_teid_len)
ogs_pfcp_object_teid_hash_set(OGS_PFCP_OBJ_SESS_TYPE, pdr, false);
}
/* Send Buffered Packet to gNB/SGW */
@ -479,9 +393,14 @@ void upf_n4_handle_session_modification_request(
}
}
ogs_assert(OGS_OK ==
upf_pfcp_send_session_modification_response(
xact, sess, created_pdr, num_of_created_pdr));
if (ogs_pfcp_self()->up_function_features.ftup == 0)
ogs_assert(OGS_OK ==
upf_pfcp_send_session_modification_response(
xact, sess, NULL, 0));
else
ogs_assert(OGS_OK ==
upf_pfcp_send_session_modification_response(
xact, sess, created_pdr, num_of_created_pdr));
return;
cleanup:

View File

@ -208,7 +208,6 @@ int upf_pfcp_send_session_modification_response(
ogs_pfcp_header_t h;
ogs_assert(xact);
ogs_assert(created_pdr);
memset(&h, 0, sizeof(ogs_pfcp_header_t));
h.type = OGS_PFCP_SESSION_MODIFICATION_RESPONSE_TYPE;

View File

@ -281,12 +281,9 @@ void upf_pfcp_state_associated(ogs_fsm_t *s, upf_event_t *e)
&message->pfcp_association_setup_response);
break;
case OGS_PFCP_SESSION_ESTABLISHMENT_REQUEST_TYPE:
if (message->h.seid_presence && message->h.seid == 0) {
ogs_expect(!sess);
sess = upf_sess_add_by_message(message);
if (sess)
OGS_SETUP_PFCP_NODE(sess, node);
}
sess = upf_sess_add_by_message(message);
if (sess)
OGS_SETUP_PFCP_NODE(sess, node);
upf_n4_handle_session_establishment_request(
sess, xact, &message->pfcp_session_establishment_request);
break;

View File

@ -499,7 +499,7 @@ int test_gtpu_send_error_indication(
ogs_assert_if_reached();
}
pkbuf = ogs_gtp2_build_error_indication(teid, node->addr);
pkbuf = ogs_gtp1_build_error_indication(teid, node->addr);
ogs_assert(pkbuf);
memset(&gtp_hdesc, 0, sizeof(gtp_hdesc));

View File

@ -41,7 +41,7 @@ static void test2_func(abts_case *tc, void *data)
static void test3_func(abts_case *tc, void *data)
{
#if OGS_USE_TALLOC != 1
#if OGS_USE_TALLOC == 0
char *ptr = ogs_realloc(0, 10);
ABTS_PTR_NOTNULL(tc, ptr);
ogs_free(ptr);
@ -54,7 +54,7 @@ static void test3_func(abts_case *tc, void *data)
static void test4_func(abts_case *tc, void *data)
{
#if OGS_USE_TALLOC != 1
#if OGS_USE_TALLOC == 0
char *p, *q;
p = ogs_malloc(10);

View File

@ -806,9 +806,6 @@ static void direct_complete_func(abts_case *tc, void *data)
rv = testgnb_ngap_send(ngap2, sendbuf);
ABTS_INT_EQUAL(tc, OGS_OK, rv);
/* Waiting for N4 */
ogs_msleep(100);
/* Receive End Mark */
recvbuf = test_gtpu_read(gtpu1);
ABTS_PTR_NOTNULL(tc, recvbuf);
@ -926,9 +923,6 @@ static void direct_complete_func(abts_case *tc, void *data)
rv = testgnb_ngap_send(ngap1, sendbuf);
ABTS_INT_EQUAL(tc, OGS_OK, rv);
/* Waiting for N4 */
ogs_msleep(100);
/* Receive End Mark */
recvbuf = test_gtpu_read(gtpu2);
ABTS_PTR_NOTNULL(tc, recvbuf);
@ -1844,9 +1838,6 @@ static void indirect_complete_func(abts_case *tc, void *data)
rv = testgnb_ngap_send(ngap2, sendbuf);
ABTS_INT_EQUAL(tc, OGS_OK, rv);
/* Waiting for N4 */
ogs_msleep(100);
/* Receive End Mark */
recvbuf = test_gtpu_read(gtpu1);
ABTS_PTR_NOTNULL(tc, recvbuf);
@ -1916,6 +1907,9 @@ static void indirect_complete_func(abts_case *tc, void *data)
ABTS_PTR_NOTNULL(tc, recvbuf);
ogs_pkbuf_free(recvbuf);
/* Waiting for removing Indirect Data Forwarding */
ogs_msleep(100);
/* Send HandoverRequired */
sendbuf = testngap_build_handover_required(
test_ue, NGAP_HandoverType_intra5gs,
@ -1992,9 +1986,6 @@ static void indirect_complete_func(abts_case *tc, void *data)
rv = testgnb_ngap_send(ngap1, sendbuf);
ABTS_INT_EQUAL(tc, OGS_OK, rv);
/* Waiting for N4 */
ogs_msleep(100);
/* Receive End Mark */
recvbuf = test_gtpu_read(gtpu2);
ABTS_PTR_NOTNULL(tc, recvbuf);
@ -2500,9 +2491,6 @@ static void indirect_cancel_func(abts_case *tc, void *data)
rv = testgnb_ngap_send(ngap2, sendbuf);
ABTS_INT_EQUAL(tc, OGS_OK, rv);
/* Waiting for N4 */
ogs_msleep(100);
/* Receive End Mark */
recvbuf = test_gtpu_read(gtpu1);
ABTS_PTR_NOTNULL(tc, recvbuf);