2019-12-07 04:17:00 +00:00
|
|
|
/*
|
[GTP/PFCP]] incorrect dst TEI=0/SEID=0 (#3043)
If eg. PCRF or AAA diameter link is not yet ready (eg. PCRF crashed), and
a client sends a CreateSessionRequest announcing its ow F-TEID,
then open5gs-smfd answers with Create Session Response Cause=
"Remote peer not responding", but it is not setting the received F-TEID
in the header of the response, instead it sends with TEI=0.
As a result, the peer cannot match the CreateSessionResponse, and needs
to rely on its own timeout timer to figure out that specific request failed.
This also happens in PFCP, so to solve this problem, I added teid/seid_presence
to the interface that sends the error message as shown below.
void ogs_gtp2_send_error_message(ogs_gtp_xact_t *xact,
int teid_presence, uint32_t teid, uint8_t type, uint8_t cause_value);
void ogs_pfcp_send_error_message(
ogs_pfcp_xact_t *xact, int seid_presence, uint64_t seid, uint8_t type,
uint8_t cause_value, uint16_t offending_ie_value);
2024-03-23 01:00:08 +00:00
|
|
|
* Copyright (C) 2019-2024 by Sukchan Lee <acetcom@gmail.com>
|
2019-12-07 04:17:00 +00:00
|
|
|
*
|
|
|
|
* This file is part of Open5GS.
|
|
|
|
*
|
|
|
|
* This program is free software: you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU Affero General Public License as published by
|
|
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
|
|
* (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "ogs-pfcp.h"
|
2020-07-27 01:02:40 +00:00
|
|
|
#include "ogs-app.h"
|
2019-12-07 04:17:00 +00:00
|
|
|
|
|
|
|
#define PFCP_MIN_XACT_ID 1
|
|
|
|
#define PFCP_MAX_XACT_ID 0x800000
|
|
|
|
|
|
|
|
typedef enum {
|
|
|
|
PFCP_XACT_UNKNOWN_STAGE,
|
|
|
|
PFCP_XACT_INITIAL_STAGE,
|
|
|
|
PFCP_XACT_INTERMEDIATE_STAGE,
|
|
|
|
PFCP_XACT_FINAL_STAGE,
|
|
|
|
} ogs_pfcp_xact_stage_t;
|
|
|
|
|
|
|
|
static int ogs_pfcp_xact_initialized = 0;
|
|
|
|
static uint32_t g_xact_id = 0;
|
|
|
|
|
|
|
|
static OGS_POOL(pool, ogs_pfcp_xact_t);
|
|
|
|
|
2022-01-19 11:03:28 +00:00
|
|
|
static ogs_pfcp_xact_t *ogs_pfcp_xact_remote_create(
|
|
|
|
ogs_pfcp_node_t *node, uint32_t sqn);
|
2020-08-26 03:05:01 +00:00
|
|
|
static ogs_pfcp_xact_stage_t ogs_pfcp_xact_get_stage(
|
2022-06-29 12:15:51 +00:00
|
|
|
uint8_t type, uint32_t xid);
|
2022-01-19 11:03:28 +00:00
|
|
|
static int ogs_pfcp_xact_update_rx(ogs_pfcp_xact_t *xact, uint8_t type);
|
2019-12-07 04:17:00 +00:00
|
|
|
|
|
|
|
static void response_timeout(void *data);
|
|
|
|
static void holding_timeout(void *data);
|
2021-02-01 04:01:15 +00:00
|
|
|
static void delayed_commit_timeout(void *data);
|
2019-12-07 04:17:00 +00:00
|
|
|
|
2020-08-26 03:05:01 +00:00
|
|
|
int ogs_pfcp_xact_init(void)
|
2019-12-07 04:17:00 +00:00
|
|
|
{
|
|
|
|
ogs_assert(ogs_pfcp_xact_initialized == 0);
|
|
|
|
|
2022-07-24 06:10:09 +00:00
|
|
|
ogs_pool_init(&pool, ogs_app()->pool.xact);
|
2019-12-07 04:17:00 +00:00
|
|
|
|
|
|
|
g_xact_id = 0;
|
|
|
|
|
|
|
|
ogs_pfcp_xact_initialized = 1;
|
|
|
|
|
|
|
|
return OGS_OK;
|
|
|
|
}
|
|
|
|
|
2020-08-26 03:05:01 +00:00
|
|
|
void ogs_pfcp_xact_final(void)
|
2019-12-07 04:17:00 +00:00
|
|
|
{
|
|
|
|
ogs_assert(ogs_pfcp_xact_initialized == 1);
|
|
|
|
|
|
|
|
ogs_pool_final(&pool);
|
|
|
|
|
|
|
|
ogs_pfcp_xact_initialized = 0;
|
|
|
|
}
|
|
|
|
|
2020-04-26 19:36:05 +00:00
|
|
|
ogs_pfcp_xact_t *ogs_pfcp_xact_local_create(ogs_pfcp_node_t *node,
|
2019-12-07 04:17:00 +00:00
|
|
|
void (*cb)(ogs_pfcp_xact_t *xact, void *data), void *data)
|
|
|
|
{
|
|
|
|
char buf[OGS_ADDRSTRLEN];
|
|
|
|
ogs_pfcp_xact_t *xact = NULL;
|
|
|
|
|
2020-04-26 19:36:05 +00:00
|
|
|
ogs_assert(node);
|
2019-12-07 04:17:00 +00:00
|
|
|
|
|
|
|
ogs_pool_alloc(&pool, &xact);
|
|
|
|
ogs_assert(xact);
|
|
|
|
memset(xact, 0, sizeof *xact);
|
|
|
|
xact->index = ogs_pool_index(&pool, xact);
|
|
|
|
|
|
|
|
xact->org = OGS_PFCP_LOCAL_ORIGINATOR;
|
|
|
|
xact->xid = OGS_NEXT_ID(g_xact_id, PFCP_MIN_XACT_ID, PFCP_MAX_XACT_ID);
|
2020-04-26 19:36:05 +00:00
|
|
|
xact->node = node;
|
2019-12-07 04:17:00 +00:00
|
|
|
xact->cb = cb;
|
|
|
|
xact->data = data;
|
|
|
|
|
2020-08-26 03:05:01 +00:00
|
|
|
xact->tm_response = ogs_timer_add(
|
|
|
|
ogs_app()->timer_mgr, response_timeout, xact);
|
2019-12-07 04:17:00 +00:00
|
|
|
ogs_assert(xact->tm_response);
|
2023-11-19 10:34:51 +00:00
|
|
|
xact->response_rcount =
|
|
|
|
ogs_local_conf()->time.message.pfcp.n1_response_rcount;
|
2019-12-07 04:17:00 +00:00
|
|
|
|
2020-08-26 03:05:01 +00:00
|
|
|
xact->tm_holding = ogs_timer_add(
|
|
|
|
ogs_app()->timer_mgr, holding_timeout, xact);
|
2019-12-07 04:17:00 +00:00
|
|
|
ogs_assert(xact->tm_holding);
|
2023-11-19 10:34:51 +00:00
|
|
|
xact->holding_rcount =
|
|
|
|
ogs_local_conf()->time.message.pfcp.n1_holding_rcount;
|
2019-12-07 04:17:00 +00:00
|
|
|
|
2021-02-01 04:01:15 +00:00
|
|
|
xact->tm_delayed_commit = ogs_timer_add(
|
|
|
|
ogs_app()->timer_mgr, delayed_commit_timeout, xact);
|
|
|
|
ogs_assert(xact->tm_delayed_commit);
|
|
|
|
|
2022-01-19 11:03:28 +00:00
|
|
|
ogs_list_add(xact->org == OGS_PFCP_LOCAL_ORIGINATOR ?
|
2020-04-26 19:36:05 +00:00
|
|
|
&xact->node->local_list : &xact->node->remote_list, xact);
|
2019-12-07 04:17:00 +00:00
|
|
|
|
2022-04-29 12:28:16 +00:00
|
|
|
ogs_list_init(&xact->pdr_to_create_list);
|
2019-12-07 04:17:00 +00:00
|
|
|
|
|
|
|
ogs_debug("[%d] %s Create peer [%s]:%d",
|
|
|
|
xact->xid,
|
|
|
|
xact->org == OGS_PFCP_LOCAL_ORIGINATOR ? "LOCAL " : "REMOTE",
|
2020-04-26 19:36:05 +00:00
|
|
|
OGS_ADDR(&node->addr, buf),
|
|
|
|
OGS_PORT(&node->addr));
|
2019-12-07 04:17:00 +00:00
|
|
|
|
|
|
|
return xact;
|
|
|
|
}
|
|
|
|
|
2022-01-19 11:03:28 +00:00
|
|
|
static ogs_pfcp_xact_t *ogs_pfcp_xact_remote_create(
|
2020-04-26 19:36:05 +00:00
|
|
|
ogs_pfcp_node_t *node, uint32_t sqn)
|
2019-12-07 04:17:00 +00:00
|
|
|
{
|
|
|
|
char buf[OGS_ADDRSTRLEN];
|
|
|
|
ogs_pfcp_xact_t *xact = NULL;
|
|
|
|
|
2020-04-26 19:36:05 +00:00
|
|
|
ogs_assert(node);
|
2019-12-07 04:17:00 +00:00
|
|
|
|
|
|
|
ogs_pool_alloc(&pool, &xact);
|
|
|
|
ogs_assert(xact);
|
|
|
|
memset(xact, 0, sizeof *xact);
|
|
|
|
xact->index = ogs_pool_index(&pool, xact);
|
|
|
|
|
|
|
|
xact->org = OGS_PFCP_REMOTE_ORIGINATOR;
|
|
|
|
xact->xid = OGS_PFCP_SQN_TO_XID(sqn);
|
2020-04-26 19:36:05 +00:00
|
|
|
xact->node = node;
|
2019-12-07 04:17:00 +00:00
|
|
|
|
2020-08-26 03:05:01 +00:00
|
|
|
xact->tm_response = ogs_timer_add(
|
|
|
|
ogs_app()->timer_mgr, response_timeout, xact);
|
2019-12-07 04:17:00 +00:00
|
|
|
ogs_assert(xact->tm_response);
|
2023-11-19 10:34:51 +00:00
|
|
|
xact->response_rcount =
|
|
|
|
ogs_local_conf()->time.message.pfcp.n1_response_rcount;
|
2019-12-07 04:17:00 +00:00
|
|
|
|
2020-08-26 03:05:01 +00:00
|
|
|
xact->tm_holding = ogs_timer_add(
|
|
|
|
ogs_app()->timer_mgr, holding_timeout, xact);
|
2019-12-07 04:17:00 +00:00
|
|
|
ogs_assert(xact->tm_holding);
|
2023-11-19 10:34:51 +00:00
|
|
|
xact->holding_rcount =
|
|
|
|
ogs_local_conf()->time.message.pfcp.n1_holding_rcount;
|
2019-12-07 04:17:00 +00:00
|
|
|
|
2021-02-01 04:01:15 +00:00
|
|
|
xact->tm_delayed_commit = ogs_timer_add(
|
|
|
|
ogs_app()->timer_mgr, delayed_commit_timeout, xact);
|
|
|
|
ogs_assert(xact->tm_delayed_commit);
|
|
|
|
|
2022-01-19 11:03:28 +00:00
|
|
|
ogs_list_add(xact->org == OGS_PFCP_LOCAL_ORIGINATOR ?
|
2020-04-26 19:36:05 +00:00
|
|
|
&xact->node->local_list : &xact->node->remote_list, xact);
|
2019-12-07 04:17:00 +00:00
|
|
|
|
|
|
|
ogs_debug("[%d] %s Create peer [%s]:%d",
|
|
|
|
xact->xid,
|
|
|
|
xact->org == OGS_PFCP_LOCAL_ORIGINATOR ? "LOCAL " : "REMOTE",
|
2020-04-26 19:36:05 +00:00
|
|
|
OGS_ADDR(&node->addr, buf),
|
|
|
|
OGS_PORT(&node->addr));
|
2019-12-07 04:17:00 +00:00
|
|
|
|
|
|
|
return xact;
|
|
|
|
}
|
|
|
|
|
2020-11-07 22:27:12 +00:00
|
|
|
ogs_pfcp_xact_t *ogs_pfcp_xact_cycle(ogs_pfcp_xact_t *xact)
|
|
|
|
{
|
|
|
|
return ogs_pool_cycle(&pool, xact);
|
|
|
|
}
|
|
|
|
|
2020-04-26 19:36:05 +00:00
|
|
|
void ogs_pfcp_xact_delete_all(ogs_pfcp_node_t *node)
|
2019-12-07 04:17:00 +00:00
|
|
|
{
|
|
|
|
ogs_pfcp_xact_t *xact = NULL, *next_xact = NULL;
|
|
|
|
|
2020-04-26 19:36:05 +00:00
|
|
|
ogs_list_for_each_safe(&node->local_list, next_xact, xact)
|
2019-12-07 04:17:00 +00:00
|
|
|
ogs_pfcp_xact_delete(xact);
|
2020-04-26 19:36:05 +00:00
|
|
|
ogs_list_for_each_safe(&node->remote_list, next_xact, xact)
|
2019-12-07 04:17:00 +00:00
|
|
|
ogs_pfcp_xact_delete(xact);
|
|
|
|
}
|
|
|
|
|
|
|
|
int ogs_pfcp_xact_update_tx(ogs_pfcp_xact_t *xact,
|
|
|
|
ogs_pfcp_header_t *hdesc, ogs_pkbuf_t *pkbuf)
|
|
|
|
{
|
|
|
|
char buf[OGS_ADDRSTRLEN];
|
|
|
|
ogs_pfcp_xact_stage_t stage;
|
|
|
|
ogs_pfcp_header_t *h = NULL;
|
2020-04-26 19:36:05 +00:00
|
|
|
int pfcp_hlen = 0;
|
2022-01-19 11:03:28 +00:00
|
|
|
|
2019-12-07 04:17:00 +00:00
|
|
|
ogs_assert(xact);
|
2020-04-26 19:36:05 +00:00
|
|
|
ogs_assert(xact->node);
|
2019-12-07 04:17:00 +00:00
|
|
|
ogs_assert(hdesc);
|
|
|
|
ogs_assert(pkbuf);
|
|
|
|
|
|
|
|
ogs_debug("[%d] %s UPD TX-%d peer [%s]:%d",
|
|
|
|
xact->xid,
|
|
|
|
xact->org == OGS_PFCP_LOCAL_ORIGINATOR ? "LOCAL " : "REMOTE",
|
|
|
|
hdesc->type,
|
2020-04-26 19:36:05 +00:00
|
|
|
OGS_ADDR(&xact->node->addr, buf),
|
|
|
|
OGS_PORT(&xact->node->addr));
|
2019-12-07 04:17:00 +00:00
|
|
|
|
|
|
|
stage = ogs_pfcp_xact_get_stage(hdesc->type, xact->xid);
|
|
|
|
if (xact->org == OGS_PFCP_LOCAL_ORIGINATOR) {
|
|
|
|
switch (stage) {
|
|
|
|
case PFCP_XACT_INITIAL_STAGE:
|
|
|
|
if (xact->step != 0) {
|
2020-09-14 02:04:43 +00:00
|
|
|
ogs_error("invalid step[%d] type[%d]", xact->step, hdesc->type);
|
2019-12-07 04:17:00 +00:00
|
|
|
ogs_pkbuf_free(pkbuf);
|
|
|
|
return OGS_ERROR;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case PFCP_XACT_INTERMEDIATE_STAGE:
|
|
|
|
ogs_expect(0);
|
|
|
|
ogs_pkbuf_free(pkbuf);
|
|
|
|
return OGS_ERROR;
|
|
|
|
|
|
|
|
case PFCP_XACT_FINAL_STAGE:
|
|
|
|
if (xact->step != 2) {
|
2020-09-14 02:04:43 +00:00
|
|
|
ogs_error("invalid step[%d] type[%d]", xact->step, hdesc->type);
|
2019-12-07 04:17:00 +00:00
|
|
|
ogs_pkbuf_free(pkbuf);
|
|
|
|
return OGS_ERROR;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
ogs_assert_if_reached();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
} else if (xact->org == OGS_PFCP_REMOTE_ORIGINATOR) {
|
|
|
|
switch (stage) {
|
|
|
|
case PFCP_XACT_INITIAL_STAGE:
|
|
|
|
ogs_expect(0);
|
|
|
|
ogs_pkbuf_free(pkbuf);
|
|
|
|
return OGS_ERROR;
|
|
|
|
|
|
|
|
case PFCP_XACT_INTERMEDIATE_STAGE:
|
|
|
|
case PFCP_XACT_FINAL_STAGE:
|
|
|
|
if (xact->step != 1) {
|
2020-09-14 02:04:43 +00:00
|
|
|
ogs_error("invalid step[%d] type[%d]", xact->step, hdesc->type);
|
2019-12-07 04:17:00 +00:00
|
|
|
ogs_pkbuf_free(pkbuf);
|
|
|
|
return OGS_ERROR;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
2020-09-14 02:04:43 +00:00
|
|
|
ogs_error("invalid stage[%d] type[%d]", stage, hdesc->type);
|
2019-12-07 04:17:00 +00:00
|
|
|
ogs_pkbuf_free(pkbuf);
|
|
|
|
return OGS_ERROR;
|
|
|
|
}
|
|
|
|
} else {
|
2020-09-14 02:04:43 +00:00
|
|
|
ogs_error("invalid org[%d] type[%d]", xact->org, hdesc->type);
|
2019-12-07 04:17:00 +00:00
|
|
|
ogs_pkbuf_free(pkbuf);
|
|
|
|
return OGS_ERROR;
|
|
|
|
}
|
|
|
|
|
[GTP/PFCP]] incorrect dst TEI=0/SEID=0 (#3043)
If eg. PCRF or AAA diameter link is not yet ready (eg. PCRF crashed), and
a client sends a CreateSessionRequest announcing its ow F-TEID,
then open5gs-smfd answers with Create Session Response Cause=
"Remote peer not responding", but it is not setting the received F-TEID
in the header of the response, instead it sends with TEI=0.
As a result, the peer cannot match the CreateSessionResponse, and needs
to rely on its own timeout timer to figure out that specific request failed.
This also happens in PFCP, so to solve this problem, I added teid/seid_presence
to the interface that sends the error message as shown below.
void ogs_gtp2_send_error_message(ogs_gtp_xact_t *xact,
int teid_presence, uint32_t teid, uint8_t type, uint8_t cause_value);
void ogs_pfcp_send_error_message(
ogs_pfcp_xact_t *xact, int seid_presence, uint64_t seid, uint8_t type,
uint8_t cause_value, uint16_t offending_ie_value);
2024-03-23 01:00:08 +00:00
|
|
|
if (hdesc->seid_presence) {
|
2020-04-26 19:36:05 +00:00
|
|
|
pfcp_hlen = OGS_PFCP_HEADER_LEN;
|
|
|
|
} else {
|
|
|
|
pfcp_hlen = OGS_PFCP_HEADER_LEN - OGS_PFCP_SEID_LEN;
|
|
|
|
}
|
2019-12-07 04:17:00 +00:00
|
|
|
|
2020-04-26 19:36:05 +00:00
|
|
|
ogs_pkbuf_push(pkbuf, pfcp_hlen);
|
2019-12-07 04:17:00 +00:00
|
|
|
h = (ogs_pfcp_header_t *)pkbuf->data;
|
2020-04-26 19:36:05 +00:00
|
|
|
memset(h, 0, pfcp_hlen);
|
2019-12-07 04:17:00 +00:00
|
|
|
|
2020-04-26 19:36:05 +00:00
|
|
|
h->version = OGS_PFCP_VERSION;
|
2019-12-07 04:17:00 +00:00
|
|
|
h->type = hdesc->type;
|
|
|
|
|
[GTP/PFCP]] incorrect dst TEI=0/SEID=0 (#3043)
If eg. PCRF or AAA diameter link is not yet ready (eg. PCRF crashed), and
a client sends a CreateSessionRequest announcing its ow F-TEID,
then open5gs-smfd answers with Create Session Response Cause=
"Remote peer not responding", but it is not setting the received F-TEID
in the header of the response, instead it sends with TEI=0.
As a result, the peer cannot match the CreateSessionResponse, and needs
to rely on its own timeout timer to figure out that specific request failed.
This also happens in PFCP, so to solve this problem, I added teid/seid_presence
to the interface that sends the error message as shown below.
void ogs_gtp2_send_error_message(ogs_gtp_xact_t *xact,
int teid_presence, uint32_t teid, uint8_t type, uint8_t cause_value);
void ogs_pfcp_send_error_message(
ogs_pfcp_xact_t *xact, int seid_presence, uint64_t seid, uint8_t type,
uint8_t cause_value, uint16_t offending_ie_value);
2024-03-23 01:00:08 +00:00
|
|
|
if (hdesc->seid_presence) {
|
2020-04-26 19:36:05 +00:00
|
|
|
h->seid_presence = 1;
|
2019-12-07 04:17:00 +00:00
|
|
|
h->seid = htobe64(hdesc->seid);
|
|
|
|
h->sqn = OGS_PFCP_XID_TO_SQN(xact->xid);
|
|
|
|
} else {
|
2020-04-26 19:36:05 +00:00
|
|
|
h->seid_presence = 0;
|
2019-12-07 04:17:00 +00:00
|
|
|
h->sqn_only = OGS_PFCP_XID_TO_SQN(xact->xid);
|
|
|
|
}
|
2020-04-26 19:36:05 +00:00
|
|
|
h->length = htobe16(pkbuf->len - 4);
|
2019-12-07 04:17:00 +00:00
|
|
|
|
|
|
|
/* Save Message type and packet of this step */
|
|
|
|
xact->seq[xact->step].type = h->type;
|
|
|
|
xact->seq[xact->step].pkbuf = pkbuf;
|
|
|
|
|
|
|
|
/* Step */
|
|
|
|
xact->step++;
|
|
|
|
|
|
|
|
return OGS_OK;
|
|
|
|
}
|
|
|
|
|
2022-01-19 11:03:28 +00:00
|
|
|
static int ogs_pfcp_xact_update_rx(ogs_pfcp_xact_t *xact, uint8_t type)
|
2019-12-07 04:17:00 +00:00
|
|
|
{
|
|
|
|
char buf[OGS_ADDRSTRLEN];
|
|
|
|
ogs_pfcp_xact_stage_t stage;
|
|
|
|
|
|
|
|
ogs_debug("[%d] %s UPD RX-%d peer [%s]:%d",
|
|
|
|
xact->xid,
|
|
|
|
xact->org == OGS_PFCP_LOCAL_ORIGINATOR ? "LOCAL " : "REMOTE",
|
|
|
|
type,
|
2020-04-26 19:36:05 +00:00
|
|
|
OGS_ADDR(&xact->node->addr, buf),
|
|
|
|
OGS_PORT(&xact->node->addr));
|
2019-12-07 04:17:00 +00:00
|
|
|
|
|
|
|
stage = ogs_pfcp_xact_get_stage(type, xact->xid);
|
|
|
|
if (xact->org == OGS_PFCP_LOCAL_ORIGINATOR) {
|
|
|
|
switch (stage) {
|
|
|
|
case PFCP_XACT_INITIAL_STAGE:
|
|
|
|
ogs_expect(0);
|
|
|
|
return OGS_ERROR;
|
|
|
|
|
|
|
|
case PFCP_XACT_INTERMEDIATE_STAGE:
|
|
|
|
if (xact->seq[1].type == type) {
|
|
|
|
ogs_pkbuf_t *pkbuf = NULL;
|
|
|
|
|
|
|
|
if (xact->step != 2 && xact->step != 3) {
|
2020-09-14 02:04:43 +00:00
|
|
|
ogs_error("invalid step[%d] type[%d]", xact->step, type);
|
2019-12-07 04:17:00 +00:00
|
|
|
ogs_pkbuf_free(pkbuf);
|
|
|
|
return OGS_ERROR;
|
|
|
|
}
|
|
|
|
|
|
|
|
pkbuf = xact->seq[2].pkbuf;
|
|
|
|
if (pkbuf) {
|
|
|
|
if (xact->tm_holding)
|
2020-07-27 01:02:40 +00:00
|
|
|
ogs_timer_start(xact->tm_holding,
|
2023-11-19 10:34:51 +00:00
|
|
|
ogs_local_conf()->time.message.
|
2020-07-27 01:02:40 +00:00
|
|
|
pfcp.t1_holding_duration);
|
2019-12-07 04:17:00 +00:00
|
|
|
|
|
|
|
ogs_warn("[%d] %s Request Duplicated. Retransmit!"
|
|
|
|
" for step %d type %d peer [%s]:%d",
|
|
|
|
xact->xid,
|
|
|
|
xact->org == OGS_PFCP_LOCAL_ORIGINATOR ?
|
|
|
|
"LOCAL " : "REMOTE",
|
|
|
|
xact->step, type,
|
2020-04-26 19:36:05 +00:00
|
|
|
OGS_ADDR(&xact->node->addr,
|
2019-12-07 04:17:00 +00:00
|
|
|
buf),
|
2020-04-26 19:36:05 +00:00
|
|
|
OGS_PORT(&xact->node->addr));
|
2023-02-16 21:55:22 +00:00
|
|
|
ogs_expect(OGS_OK == ogs_pfcp_sendto(xact->node, pkbuf));
|
2019-12-07 04:17:00 +00:00
|
|
|
} else {
|
|
|
|
ogs_warn("[%d] %s Request Duplicated. Discard!"
|
|
|
|
" for step %d type %d peer [%s]:%d",
|
|
|
|
xact->xid,
|
|
|
|
xact->org == OGS_PFCP_LOCAL_ORIGINATOR ?
|
|
|
|
"LOCAL " : "REMOTE",
|
|
|
|
xact->step, type,
|
2020-04-26 19:36:05 +00:00
|
|
|
OGS_ADDR(&xact->node->addr,
|
2019-12-07 04:17:00 +00:00
|
|
|
buf),
|
2020-04-26 19:36:05 +00:00
|
|
|
OGS_PORT(&xact->node->addr));
|
2019-12-07 04:17:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return OGS_RETRY;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (xact->step != 1) {
|
2020-09-14 02:04:43 +00:00
|
|
|
ogs_error("invalid step[%d] type[%d]", xact->step, type);
|
2019-12-07 04:17:00 +00:00
|
|
|
return OGS_ERROR;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (xact->tm_holding)
|
2020-07-27 01:02:40 +00:00
|
|
|
ogs_timer_start(xact->tm_holding,
|
2023-11-19 10:34:51 +00:00
|
|
|
ogs_local_conf()->time.message.pfcp.
|
|
|
|
t1_holding_duration);
|
2019-12-07 04:17:00 +00:00
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
case PFCP_XACT_FINAL_STAGE:
|
|
|
|
if (xact->step != 1) {
|
2020-09-14 02:04:43 +00:00
|
|
|
ogs_error("invalid step[%d] type[%d]", xact->step, type);
|
2019-12-07 04:17:00 +00:00
|
|
|
return OGS_ERROR;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
ogs_error("invalid stage[%d]", stage);
|
|
|
|
return OGS_ERROR;
|
|
|
|
}
|
|
|
|
} else if (xact->org == OGS_PFCP_REMOTE_ORIGINATOR) {
|
|
|
|
switch (stage) {
|
|
|
|
case PFCP_XACT_INITIAL_STAGE:
|
|
|
|
if (xact->seq[0].type == type) {
|
|
|
|
ogs_pkbuf_t *pkbuf = NULL;
|
|
|
|
|
|
|
|
if (xact->step != 1 && xact->step != 2) {
|
2020-09-14 02:04:43 +00:00
|
|
|
ogs_error("invalid step[%d] type[%d]", xact->step, type);
|
2019-12-07 04:17:00 +00:00
|
|
|
return OGS_ERROR;
|
|
|
|
}
|
|
|
|
|
|
|
|
pkbuf = xact->seq[1].pkbuf;
|
|
|
|
if (pkbuf) {
|
|
|
|
if (xact->tm_holding)
|
2020-07-27 01:02:40 +00:00
|
|
|
ogs_timer_start(xact->tm_holding,
|
2023-11-19 10:34:51 +00:00
|
|
|
ogs_local_conf()->time.message.
|
2020-07-27 01:02:40 +00:00
|
|
|
pfcp.t1_holding_duration);
|
2019-12-07 04:17:00 +00:00
|
|
|
|
|
|
|
ogs_warn("[%d] %s Request Duplicated. Retransmit!"
|
|
|
|
" for step %d type %d peer [%s]:%d",
|
|
|
|
xact->xid,
|
|
|
|
xact->org == OGS_PFCP_LOCAL_ORIGINATOR ?
|
|
|
|
"LOCAL " : "REMOTE",
|
|
|
|
xact->step, type,
|
2020-04-26 19:36:05 +00:00
|
|
|
OGS_ADDR(&xact->node->addr,
|
2019-12-07 04:17:00 +00:00
|
|
|
buf),
|
2020-04-26 19:36:05 +00:00
|
|
|
OGS_PORT(&xact->node->addr));
|
2023-02-16 21:55:22 +00:00
|
|
|
ogs_expect(OGS_OK == ogs_pfcp_sendto(xact->node, pkbuf));
|
2019-12-07 04:17:00 +00:00
|
|
|
} else {
|
|
|
|
ogs_warn("[%d] %s Request Duplicated. Discard!"
|
|
|
|
" for step %d type %d peer [%s]:%d",
|
|
|
|
xact->xid,
|
|
|
|
xact->org == OGS_PFCP_LOCAL_ORIGINATOR ?
|
|
|
|
"LOCAL " : "REMOTE",
|
|
|
|
xact->step, type,
|
2020-04-26 19:36:05 +00:00
|
|
|
OGS_ADDR(&xact->node->addr,
|
2019-12-07 04:17:00 +00:00
|
|
|
buf),
|
2020-04-26 19:36:05 +00:00
|
|
|
OGS_PORT(&xact->node->addr));
|
2019-12-07 04:17:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return OGS_RETRY;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (xact->step != 0) {
|
2020-09-14 02:04:43 +00:00
|
|
|
ogs_error("invalid step[%d] type[%d]", xact->step, type);
|
2019-12-07 04:17:00 +00:00
|
|
|
return OGS_ERROR;
|
|
|
|
}
|
|
|
|
if (xact->tm_holding)
|
2020-07-27 01:02:40 +00:00
|
|
|
ogs_timer_start(xact->tm_holding,
|
2023-11-19 10:34:51 +00:00
|
|
|
ogs_local_conf()->time.message.pfcp.
|
|
|
|
t1_holding_duration);
|
2019-12-07 04:17:00 +00:00
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
case PFCP_XACT_INTERMEDIATE_STAGE:
|
|
|
|
ogs_expect(0);
|
|
|
|
return OGS_ERROR;
|
|
|
|
|
|
|
|
case PFCP_XACT_FINAL_STAGE:
|
|
|
|
if (xact->step != 2) {
|
2020-09-14 02:04:43 +00:00
|
|
|
ogs_error("invalid step[%d] type[%d]", xact->step, type);
|
2019-12-07 04:17:00 +00:00
|
|
|
return OGS_ERROR;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* continue */
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
ogs_error("invalid stage[%d]", stage);
|
|
|
|
return OGS_ERROR;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
ogs_error("invalid org[%d]", xact->org);
|
|
|
|
return OGS_ERROR;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (xact->tm_response)
|
|
|
|
ogs_timer_stop(xact->tm_response);
|
|
|
|
|
|
|
|
/* Save Message type of this step */
|
|
|
|
xact->seq[xact->step].type = type;
|
|
|
|
|
|
|
|
/* Step */
|
|
|
|
xact->step++;
|
|
|
|
|
|
|
|
return OGS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
int ogs_pfcp_xact_commit(ogs_pfcp_xact_t *xact)
|
|
|
|
{
|
|
|
|
char buf[OGS_ADDRSTRLEN];
|
|
|
|
|
|
|
|
uint8_t type;
|
|
|
|
ogs_pkbuf_t *pkbuf = NULL;
|
|
|
|
ogs_pfcp_xact_stage_t stage;
|
2022-01-19 11:03:28 +00:00
|
|
|
|
2019-12-07 04:17:00 +00:00
|
|
|
ogs_assert(xact);
|
2020-04-26 19:36:05 +00:00
|
|
|
ogs_assert(xact->node);
|
2019-12-07 04:17:00 +00:00
|
|
|
|
|
|
|
ogs_debug("[%d] %s Commit peer [%s]:%d",
|
|
|
|
xact->xid,
|
|
|
|
xact->org == OGS_PFCP_LOCAL_ORIGINATOR ? "LOCAL " : "REMOTE",
|
2020-04-26 19:36:05 +00:00
|
|
|
OGS_ADDR(&xact->node->addr, buf),
|
|
|
|
OGS_PORT(&xact->node->addr));
|
2019-12-07 04:17:00 +00:00
|
|
|
|
|
|
|
type = xact->seq[xact->step-1].type;
|
|
|
|
stage = ogs_pfcp_xact_get_stage(type, xact->xid);
|
|
|
|
|
|
|
|
if (xact->org == OGS_PFCP_LOCAL_ORIGINATOR) {
|
|
|
|
switch (stage) {
|
|
|
|
case PFCP_XACT_INITIAL_STAGE:
|
|
|
|
if (xact->step != 1) {
|
2020-09-14 02:04:43 +00:00
|
|
|
ogs_error("invalid step[%d] type[%d]", xact->step, type);
|
2019-12-07 04:17:00 +00:00
|
|
|
ogs_pfcp_xact_delete(xact);
|
|
|
|
return OGS_ERROR;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (xact->tm_response)
|
2020-07-27 01:02:40 +00:00
|
|
|
ogs_timer_start(xact->tm_response,
|
2023-11-19 10:34:51 +00:00
|
|
|
ogs_local_conf()->time.message.pfcp.t1_response_duration);
|
2019-12-07 04:17:00 +00:00
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
case PFCP_XACT_INTERMEDIATE_STAGE:
|
|
|
|
ogs_expect(0);
|
|
|
|
ogs_pfcp_xact_delete(xact);
|
|
|
|
return OGS_ERROR;
|
|
|
|
|
|
|
|
case PFCP_XACT_FINAL_STAGE:
|
|
|
|
if (xact->step != 2 && xact->step != 3) {
|
2020-09-14 02:04:43 +00:00
|
|
|
ogs_error("invalid step[%d] type[%d]", xact->step, type);
|
2019-12-07 04:17:00 +00:00
|
|
|
ogs_pfcp_xact_delete(xact);
|
|
|
|
return OGS_ERROR;
|
|
|
|
}
|
|
|
|
if (xact->step == 2) {
|
|
|
|
ogs_pfcp_xact_delete(xact);
|
|
|
|
return OGS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
2020-09-14 02:04:43 +00:00
|
|
|
ogs_error("invalid stage[%d] type[%d]", stage, type);
|
2019-12-07 04:17:00 +00:00
|
|
|
ogs_pfcp_xact_delete(xact);
|
|
|
|
return OGS_ERROR;
|
|
|
|
}
|
|
|
|
} else if (xact->org == OGS_PFCP_REMOTE_ORIGINATOR) {
|
|
|
|
switch (stage) {
|
|
|
|
case PFCP_XACT_INITIAL_STAGE:
|
|
|
|
ogs_expect(0);
|
|
|
|
ogs_pfcp_xact_delete(xact);
|
|
|
|
return OGS_ERROR;
|
|
|
|
|
|
|
|
case PFCP_XACT_INTERMEDIATE_STAGE:
|
|
|
|
if (xact->step != 2) {
|
2020-09-14 02:04:43 +00:00
|
|
|
ogs_error("invalid step[%d] type[%d]", xact->step, type);
|
2019-12-07 04:17:00 +00:00
|
|
|
ogs_pfcp_xact_delete(xact);
|
|
|
|
return OGS_ERROR;
|
|
|
|
}
|
|
|
|
if (xact->tm_response)
|
2020-07-27 01:02:40 +00:00
|
|
|
ogs_timer_start(xact->tm_response,
|
2023-11-19 10:34:51 +00:00
|
|
|
ogs_local_conf()->time.message.pfcp.
|
|
|
|
t1_response_duration);
|
2019-12-07 04:17:00 +00:00
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
case PFCP_XACT_FINAL_STAGE:
|
|
|
|
if (xact->step != 2 && xact->step != 3) {
|
2020-09-14 02:04:43 +00:00
|
|
|
ogs_error("invalid step[%d] type[%d]", xact->step, type);
|
2019-12-07 04:17:00 +00:00
|
|
|
ogs_pfcp_xact_delete(xact);
|
|
|
|
return OGS_ERROR;
|
|
|
|
}
|
|
|
|
if (xact->step == 3) {
|
|
|
|
ogs_pfcp_xact_delete(xact);
|
|
|
|
return OGS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
2020-09-14 02:04:43 +00:00
|
|
|
ogs_error("invalid stage[%d] type[%d]", stage, type);
|
2019-12-07 04:17:00 +00:00
|
|
|
ogs_pfcp_xact_delete(xact);
|
|
|
|
return OGS_ERROR;
|
|
|
|
}
|
|
|
|
} else {
|
2020-09-14 02:04:43 +00:00
|
|
|
ogs_error("invalid org[%d] type[%d]", xact->org, type);
|
2019-12-07 04:17:00 +00:00
|
|
|
ogs_pfcp_xact_delete(xact);
|
|
|
|
return OGS_ERROR;
|
|
|
|
}
|
|
|
|
|
|
|
|
pkbuf = xact->seq[xact->step-1].pkbuf;
|
|
|
|
ogs_assert(pkbuf);
|
|
|
|
|
2023-02-16 21:55:22 +00:00
|
|
|
ogs_expect(OGS_OK == ogs_pfcp_sendto(xact->node, pkbuf));
|
2019-12-07 04:17:00 +00:00
|
|
|
|
|
|
|
return OGS_OK;
|
|
|
|
}
|
|
|
|
|
2021-02-01 04:01:15 +00:00
|
|
|
void ogs_pfcp_xact_delayed_commit(ogs_pfcp_xact_t *xact, ogs_time_t duration)
|
|
|
|
{
|
|
|
|
ogs_assert(xact);
|
|
|
|
ogs_assert(duration);
|
|
|
|
ogs_assert(xact->tm_delayed_commit);
|
|
|
|
|
|
|
|
ogs_timer_start(xact->tm_delayed_commit, duration);
|
|
|
|
}
|
|
|
|
|
2019-12-07 04:17:00 +00:00
|
|
|
static void response_timeout(void *data)
|
|
|
|
{
|
|
|
|
char buf[OGS_ADDRSTRLEN];
|
|
|
|
ogs_pfcp_xact_t *xact = data;
|
2021-02-01 04:01:15 +00:00
|
|
|
|
2019-12-07 04:17:00 +00:00
|
|
|
ogs_assert(xact);
|
2020-04-26 19:36:05 +00:00
|
|
|
ogs_assert(xact->node);
|
2019-12-07 04:17:00 +00:00
|
|
|
|
|
|
|
ogs_debug("[%d] %s Response Timeout "
|
|
|
|
"for step %d type %d peer [%s]:%d",
|
|
|
|
xact->xid,
|
|
|
|
xact->org == OGS_PFCP_LOCAL_ORIGINATOR ? "LOCAL " : "REMOTE",
|
|
|
|
xact->step, xact->seq[xact->step-1].type,
|
2020-04-26 19:36:05 +00:00
|
|
|
OGS_ADDR(&xact->node->addr, buf),
|
|
|
|
OGS_PORT(&xact->node->addr));
|
2019-12-07 04:17:00 +00:00
|
|
|
|
|
|
|
if (--xact->response_rcount > 0) {
|
|
|
|
ogs_pkbuf_t *pkbuf = NULL;
|
|
|
|
|
|
|
|
if (xact->tm_response)
|
2020-07-27 01:02:40 +00:00
|
|
|
ogs_timer_start(xact->tm_response,
|
2023-11-19 10:34:51 +00:00
|
|
|
ogs_local_conf()->time.message.pfcp.t1_response_duration);
|
2019-12-07 04:17:00 +00:00
|
|
|
|
|
|
|
pkbuf = xact->seq[xact->step-1].pkbuf;
|
|
|
|
ogs_assert(pkbuf);
|
|
|
|
|
2023-02-16 21:55:22 +00:00
|
|
|
ogs_expect(OGS_OK == ogs_pfcp_sendto(xact->node, pkbuf));
|
2019-12-07 04:17:00 +00:00
|
|
|
} else {
|
|
|
|
ogs_warn("[%d] %s No Reponse. Give up! "
|
|
|
|
"for step %d type %d peer [%s]:%d",
|
|
|
|
xact->xid,
|
|
|
|
xact->org == OGS_PFCP_LOCAL_ORIGINATOR ? "LOCAL " : "REMOTE",
|
|
|
|
xact->step, xact->seq[xact->step-1].type,
|
2020-04-26 19:36:05 +00:00
|
|
|
OGS_ADDR(&xact->node->addr, buf),
|
|
|
|
OGS_PORT(&xact->node->addr));
|
2019-12-07 04:17:00 +00:00
|
|
|
|
|
|
|
if (xact->cb)
|
|
|
|
xact->cb(xact, xact->data);
|
|
|
|
|
|
|
|
ogs_pfcp_xact_delete(xact);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void holding_timeout(void *data)
|
|
|
|
{
|
|
|
|
char buf[OGS_ADDRSTRLEN];
|
|
|
|
ogs_pfcp_xact_t *xact = data;
|
2021-02-01 04:01:15 +00:00
|
|
|
|
2019-12-07 04:17:00 +00:00
|
|
|
ogs_assert(xact);
|
2020-04-26 19:36:05 +00:00
|
|
|
ogs_assert(xact->node);
|
2019-12-07 04:17:00 +00:00
|
|
|
|
|
|
|
ogs_debug("[%d] %s Holding Timeout "
|
|
|
|
"for step %d type %d peer [%s]:%d",
|
|
|
|
xact->xid,
|
|
|
|
xact->org == OGS_PFCP_LOCAL_ORIGINATOR ? "LOCAL " : "REMOTE",
|
|
|
|
xact->step, xact->seq[xact->step-1].type,
|
2020-04-26 19:36:05 +00:00
|
|
|
OGS_ADDR(&xact->node->addr, buf),
|
|
|
|
OGS_PORT(&xact->node->addr));
|
2019-12-07 04:17:00 +00:00
|
|
|
|
|
|
|
if (--xact->holding_rcount > 0) {
|
|
|
|
if (xact->tm_holding)
|
2020-07-27 01:02:40 +00:00
|
|
|
ogs_timer_start(xact->tm_holding,
|
2023-11-19 10:34:51 +00:00
|
|
|
ogs_local_conf()->time.message.pfcp.t1_holding_duration);
|
2019-12-07 04:17:00 +00:00
|
|
|
} else {
|
|
|
|
ogs_debug("[%d] %s Delete Transaction "
|
|
|
|
"for step %d type %d peer [%s]:%d",
|
|
|
|
xact->xid,
|
|
|
|
xact->org == OGS_PFCP_LOCAL_ORIGINATOR ? "LOCAL " : "REMOTE",
|
|
|
|
xact->step, xact->seq[xact->step-1].type,
|
2020-04-26 19:36:05 +00:00
|
|
|
OGS_ADDR(&xact->node->addr, buf),
|
|
|
|
OGS_PORT(&xact->node->addr));
|
2019-12-07 04:17:00 +00:00
|
|
|
ogs_pfcp_xact_delete(xact);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-02-01 04:01:15 +00:00
|
|
|
static void delayed_commit_timeout(void *data)
|
|
|
|
{
|
|
|
|
char buf[OGS_ADDRSTRLEN];
|
|
|
|
ogs_pfcp_xact_t *xact = data;
|
|
|
|
|
|
|
|
ogs_assert(xact);
|
|
|
|
ogs_assert(xact->node);
|
|
|
|
|
|
|
|
ogs_debug("[%d] %s Delayed Send Timeout "
|
|
|
|
"for step %d type %d peer [%s]:%d",
|
|
|
|
xact->xid,
|
|
|
|
xact->org == OGS_PFCP_LOCAL_ORIGINATOR ? "LOCAL " : "REMOTE",
|
|
|
|
xact->step, xact->seq[xact->step-1].type,
|
|
|
|
OGS_ADDR(&xact->node->addr, buf),
|
|
|
|
OGS_PORT(&xact->node->addr));
|
|
|
|
|
|
|
|
ogs_pfcp_xact_commit(xact);
|
|
|
|
}
|
2019-12-07 04:17:00 +00:00
|
|
|
|
|
|
|
int ogs_pfcp_xact_receive(
|
2020-04-26 19:36:05 +00:00
|
|
|
ogs_pfcp_node_t *node, ogs_pfcp_header_t *h, ogs_pfcp_xact_t **xact)
|
2019-12-07 04:17:00 +00:00
|
|
|
{
|
|
|
|
int rv;
|
2023-03-04 23:35:30 +00:00
|
|
|
char buf[OGS_ADDRSTRLEN];
|
|
|
|
|
|
|
|
uint8_t type;
|
|
|
|
uint32_t sqn, xid;
|
|
|
|
ogs_pfcp_xact_stage_t stage;
|
|
|
|
ogs_list_t *list = NULL;
|
2019-12-07 04:17:00 +00:00
|
|
|
ogs_pfcp_xact_t *new = NULL;
|
|
|
|
|
2020-04-26 19:36:05 +00:00
|
|
|
ogs_assert(node);
|
2019-12-07 04:17:00 +00:00
|
|
|
ogs_assert(h);
|
|
|
|
|
2023-03-04 23:35:30 +00:00
|
|
|
type = h->type;
|
|
|
|
sqn = h->sqn;
|
|
|
|
xid = OGS_PFCP_SQN_TO_XID(sqn);
|
|
|
|
stage = ogs_pfcp_xact_get_stage(type, xid);
|
|
|
|
|
|
|
|
switch (stage) {
|
|
|
|
case PFCP_XACT_INITIAL_STAGE:
|
|
|
|
list = &node->remote_list;
|
|
|
|
break;
|
|
|
|
case PFCP_XACT_INTERMEDIATE_STAGE:
|
|
|
|
list = &node->local_list;
|
|
|
|
break;
|
|
|
|
case PFCP_XACT_FINAL_STAGE:
|
|
|
|
list = &node->local_list;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
ogs_error("[%d] Unexpected type %u from PFCP peer [%s]:%d",
|
|
|
|
xid, type, OGS_ADDR(&node->addr, buf), OGS_PORT(&node->addr));
|
|
|
|
return OGS_ERROR;
|
|
|
|
}
|
|
|
|
|
|
|
|
ogs_assert(list);
|
|
|
|
ogs_list_for_each(list, new) {
|
|
|
|
if (new->xid == xid) {
|
|
|
|
ogs_debug("[%d] %s Find peer [%s]:%d",
|
|
|
|
new->xid,
|
|
|
|
new->org == OGS_PFCP_LOCAL_ORIGINATOR ? "LOCAL " : "REMOTE",
|
|
|
|
OGS_ADDR(&node->addr, buf),
|
|
|
|
OGS_PORT(&node->addr));
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-12-20 19:20:21 +00:00
|
|
|
if (!new) {
|
|
|
|
ogs_debug("[%d] Cannot find new type %u from PFCP peer [%s]:%d",
|
|
|
|
xid, type, OGS_ADDR(&node->addr, buf), OGS_PORT(&node->addr));
|
2023-03-04 23:35:30 +00:00
|
|
|
new = ogs_pfcp_xact_remote_create(node, sqn);
|
2023-12-20 19:20:21 +00:00
|
|
|
}
|
2019-12-07 04:17:00 +00:00
|
|
|
ogs_assert(new);
|
|
|
|
|
|
|
|
ogs_debug("[%d] %s Receive peer [%s]:%d",
|
|
|
|
new->xid,
|
|
|
|
new->org == OGS_PFCP_LOCAL_ORIGINATOR ? "LOCAL " : "REMOTE",
|
2020-04-26 19:36:05 +00:00
|
|
|
OGS_ADDR(&node->addr, buf),
|
|
|
|
OGS_PORT(&node->addr));
|
2019-12-07 04:17:00 +00:00
|
|
|
|
2023-03-04 23:35:30 +00:00
|
|
|
rv = ogs_pfcp_xact_update_rx(new, type);
|
2020-04-26 19:36:05 +00:00
|
|
|
if (rv == OGS_ERROR) {
|
2019-12-07 04:17:00 +00:00
|
|
|
ogs_error("ogs_pfcp_xact_update_rx() failed");
|
|
|
|
ogs_pfcp_xact_delete(new);
|
|
|
|
return rv;
|
2020-04-26 19:36:05 +00:00
|
|
|
} else if (rv == OGS_RETRY) {
|
|
|
|
return rv;
|
2019-12-07 04:17:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
*xact = new;
|
2020-04-26 19:36:05 +00:00
|
|
|
return rv;
|
2019-12-07 04:17:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static ogs_pfcp_xact_stage_t ogs_pfcp_xact_get_stage(uint8_t type, uint32_t xid)
|
|
|
|
{
|
|
|
|
ogs_pfcp_xact_stage_t stage = PFCP_XACT_UNKNOWN_STAGE;
|
|
|
|
|
|
|
|
switch (type) {
|
|
|
|
case OGS_PFCP_HEARTBEAT_REQUEST_TYPE:
|
|
|
|
case OGS_PFCP_ASSOCIATION_SETUP_REQUEST_TYPE:
|
|
|
|
case OGS_PFCP_ASSOCIATION_UPDATE_REQUEST_TYPE:
|
|
|
|
case OGS_PFCP_ASSOCIATION_RELEASE_REQUEST_TYPE:
|
|
|
|
case OGS_PFCP_SESSION_ESTABLISHMENT_REQUEST_TYPE:
|
|
|
|
case OGS_PFCP_SESSION_MODIFICATION_REQUEST_TYPE:
|
|
|
|
case OGS_PFCP_SESSION_DELETION_REQUEST_TYPE:
|
2020-08-13 00:31:22 +00:00
|
|
|
case OGS_PFCP_SESSION_REPORT_REQUEST_TYPE:
|
2019-12-07 04:17:00 +00:00
|
|
|
stage = PFCP_XACT_INITIAL_STAGE;
|
|
|
|
break;
|
|
|
|
case OGS_PFCP_HEARTBEAT_RESPONSE_TYPE:
|
|
|
|
case OGS_PFCP_ASSOCIATION_SETUP_RESPONSE_TYPE:
|
|
|
|
case OGS_PFCP_ASSOCIATION_UPDATE_RESPONSE_TYPE:
|
|
|
|
case OGS_PFCP_ASSOCIATION_RELEASE_RESPONSE_TYPE:
|
|
|
|
case OGS_PFCP_VERSION_NOT_SUPPORTED_RESPONSE_TYPE:
|
|
|
|
case OGS_PFCP_SESSION_ESTABLISHMENT_RESPONSE_TYPE:
|
|
|
|
case OGS_PFCP_SESSION_MODIFICATION_RESPONSE_TYPE:
|
|
|
|
case OGS_PFCP_SESSION_DELETION_RESPONSE_TYPE:
|
2020-08-13 00:31:22 +00:00
|
|
|
case OGS_PFCP_SESSION_REPORT_RESPONSE_TYPE:
|
2019-12-07 04:17:00 +00:00
|
|
|
stage = PFCP_XACT_FINAL_STAGE;
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
ogs_error("Not implemented PFCPv2 Message Type(%d)", type);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return stage;
|
|
|
|
}
|
|
|
|
|
2023-04-04 12:22:03 +00:00
|
|
|
int ogs_pfcp_xact_delete(ogs_pfcp_xact_t *xact)
|
2019-12-07 04:17:00 +00:00
|
|
|
{
|
|
|
|
char buf[OGS_ADDRSTRLEN];
|
|
|
|
|
|
|
|
ogs_assert(xact);
|
2020-04-26 19:36:05 +00:00
|
|
|
ogs_assert(xact->node);
|
2019-12-07 04:17:00 +00:00
|
|
|
|
|
|
|
ogs_debug("[%d] %s Delete peer [%s]:%d",
|
|
|
|
xact->xid,
|
|
|
|
xact->org == OGS_PFCP_LOCAL_ORIGINATOR ? "LOCAL " : "REMOTE",
|
2020-04-26 19:36:05 +00:00
|
|
|
OGS_ADDR(&xact->node->addr, buf),
|
|
|
|
OGS_PORT(&xact->node->addr));
|
2019-12-07 04:17:00 +00:00
|
|
|
|
|
|
|
if (xact->seq[0].pkbuf)
|
|
|
|
ogs_pkbuf_free(xact->seq[0].pkbuf);
|
|
|
|
if (xact->seq[1].pkbuf)
|
|
|
|
ogs_pkbuf_free(xact->seq[1].pkbuf);
|
|
|
|
if (xact->seq[2].pkbuf)
|
|
|
|
ogs_pkbuf_free(xact->seq[2].pkbuf);
|
|
|
|
|
|
|
|
if (xact->tm_response)
|
|
|
|
ogs_timer_delete(xact->tm_response);
|
|
|
|
if (xact->tm_holding)
|
|
|
|
ogs_timer_delete(xact->tm_holding);
|
2021-02-01 04:01:15 +00:00
|
|
|
if (xact->tm_delayed_commit)
|
|
|
|
ogs_timer_delete(xact->tm_delayed_commit);
|
2019-12-07 04:17:00 +00:00
|
|
|
|
|
|
|
ogs_list_remove(xact->org == OGS_PFCP_LOCAL_ORIGINATOR ?
|
2020-04-26 19:36:05 +00:00
|
|
|
&xact->node->local_list : &xact->node->remote_list, xact);
|
2019-12-07 04:17:00 +00:00
|
|
|
ogs_pool_free(&pool, xact);
|
|
|
|
|
|
|
|
return OGS_OK;
|
|
|
|
}
|