2020-08-13 00:31:22 +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>
|
2020-08-13 00:31:22 +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 "pfcp-path.h"
|
|
|
|
|
|
|
|
static void pfcp_node_fsm_init(ogs_pfcp_node_t *node, bool try_to_assoicate)
|
|
|
|
{
|
|
|
|
sgwc_event_t e;
|
|
|
|
|
|
|
|
ogs_assert(node);
|
|
|
|
|
|
|
|
memset(&e, 0, sizeof(e));
|
|
|
|
e.pfcp_node = node;
|
|
|
|
|
|
|
|
if (try_to_assoicate == true) {
|
2020-08-26 03:05:01 +00:00
|
|
|
node->t_association = ogs_timer_add(ogs_app()->timer_mgr,
|
2020-08-13 00:31:22 +00:00
|
|
|
sgwc_timer_pfcp_association, node);
|
|
|
|
ogs_assert(node->t_association);
|
|
|
|
}
|
|
|
|
|
2022-08-12 05:03:53 +00:00
|
|
|
ogs_fsm_init(&node->sm, sgwc_pfcp_state_initial, sgwc_pfcp_state_final, &e);
|
2020-08-13 00:31:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void pfcp_node_fsm_fini(ogs_pfcp_node_t *node)
|
|
|
|
{
|
|
|
|
sgwc_event_t e;
|
|
|
|
|
|
|
|
ogs_assert(node);
|
|
|
|
|
|
|
|
memset(&e, 0, sizeof(e));
|
|
|
|
e.pfcp_node = node;
|
|
|
|
|
|
|
|
ogs_fsm_fini(&node->sm, &e);
|
|
|
|
|
|
|
|
if (node->t_association)
|
|
|
|
ogs_timer_delete(node->t_association);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void pfcp_recv_cb(short when, ogs_socket_t fd, void *data)
|
|
|
|
{
|
|
|
|
int rv;
|
|
|
|
|
|
|
|
ssize_t size;
|
|
|
|
sgwc_event_t *e = NULL;
|
|
|
|
ogs_pkbuf_t *pkbuf = NULL;
|
|
|
|
ogs_sockaddr_t from;
|
|
|
|
ogs_pfcp_node_t *node = NULL;
|
|
|
|
ogs_pfcp_header_t *h = NULL;
|
|
|
|
|
|
|
|
ogs_assert(fd != INVALID_SOCKET);
|
|
|
|
|
|
|
|
pkbuf = ogs_pkbuf_alloc(NULL, OGS_MAX_SDU_LEN);
|
2020-09-07 03:53:38 +00:00
|
|
|
ogs_assert(pkbuf);
|
2020-08-13 00:31:22 +00:00
|
|
|
ogs_pkbuf_put(pkbuf, OGS_MAX_SDU_LEN);
|
|
|
|
|
|
|
|
size = ogs_recvfrom(fd, pkbuf->data, pkbuf->len, 0, &from);
|
|
|
|
if (size <= 0) {
|
|
|
|
ogs_log_message(OGS_LOG_ERROR, ogs_socket_errno,
|
|
|
|
"ogs_recvfrom() failed");
|
|
|
|
ogs_pkbuf_free(pkbuf);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
ogs_pkbuf_trim(pkbuf, size);
|
|
|
|
|
|
|
|
h = (ogs_pfcp_header_t *)pkbuf->data;
|
2022-10-01 04:28:41 +00:00
|
|
|
if (h->version != OGS_PFCP_VERSION) {
|
2020-08-13 00:31:22 +00:00
|
|
|
ogs_pfcp_header_t rsp;
|
|
|
|
|
|
|
|
ogs_error("Not supported version[%d]", h->version);
|
|
|
|
|
|
|
|
memset(&rsp, 0, sizeof rsp);
|
|
|
|
rsp.flags = (OGS_PFCP_VERSION << 5);
|
|
|
|
rsp.type = OGS_PFCP_VERSION_NOT_SUPPORTED_RESPONSE_TYPE;
|
|
|
|
rsp.length = htobe16(4);
|
|
|
|
rsp.sqn_only = h->sqn_only;
|
2020-09-19 01:46:49 +00:00
|
|
|
if (ogs_sendto(fd, &rsp, 8, 0, &from) < 0) {
|
|
|
|
ogs_log_message(OGS_LOG_ERROR, ogs_socket_errno,
|
|
|
|
"ogs_sendto() failed");
|
|
|
|
}
|
2020-08-13 00:31:22 +00:00
|
|
|
ogs_pkbuf_free(pkbuf);
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
e = sgwc_event_new(SGWC_EVT_SXA_MESSAGE);
|
|
|
|
ogs_assert(e);
|
|
|
|
|
2021-03-15 01:01:55 +00:00
|
|
|
node = ogs_pfcp_node_find(&ogs_pfcp_self()->pfcp_peer_list, &from);
|
2020-08-13 00:31:22 +00:00
|
|
|
if (!node) {
|
2021-03-15 01:01:55 +00:00
|
|
|
node = ogs_pfcp_node_add(&ogs_pfcp_self()->pfcp_peer_list, &from);
|
2023-08-18 13:19:46 +00:00
|
|
|
if (!node) {
|
|
|
|
ogs_error("No memory: ogs_pfcp_node_add() failed");
|
|
|
|
ogs_pkbuf_free(e->pkbuf);
|
|
|
|
ogs_event_free(e);
|
|
|
|
return;
|
|
|
|
}
|
2020-08-13 00:31:22 +00:00
|
|
|
|
|
|
|
node->sock = data;
|
|
|
|
pfcp_node_fsm_init(node, false);
|
|
|
|
}
|
|
|
|
e->pfcp_node = node;
|
|
|
|
e->pkbuf = pkbuf;
|
|
|
|
|
2020-08-26 03:05:01 +00:00
|
|
|
rv = ogs_queue_push(ogs_app()->queue, e);
|
2020-08-13 00:31:22 +00:00
|
|
|
if (rv != OGS_OK) {
|
2022-07-16 04:27:18 +00:00
|
|
|
ogs_error("ogs_queue_push() failed:%d", (int)rv);
|
2020-08-13 00:31:22 +00:00
|
|
|
ogs_pkbuf_free(e->pkbuf);
|
|
|
|
sgwc_event_free(e);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int sgwc_pfcp_open(void)
|
|
|
|
{
|
|
|
|
ogs_socknode_t *node = NULL;
|
|
|
|
ogs_sock_t *sock = NULL;
|
|
|
|
|
|
|
|
/* PFCP Server */
|
|
|
|
ogs_list_for_each(&ogs_pfcp_self()->pfcp_list, node) {
|
|
|
|
sock = ogs_pfcp_server(node);
|
2021-04-21 08:24:17 +00:00
|
|
|
if (!sock) return OGS_ERROR;
|
2022-04-29 12:28:16 +00:00
|
|
|
|
2020-08-26 03:05:01 +00:00
|
|
|
node->poll = ogs_pollset_add(ogs_app()->pollset,
|
2020-08-13 00:31:22 +00:00
|
|
|
OGS_POLLIN, sock->fd, pfcp_recv_cb, sock);
|
2021-04-21 08:24:17 +00:00
|
|
|
ogs_assert(node->poll);
|
2020-08-13 00:31:22 +00:00
|
|
|
}
|
|
|
|
ogs_list_for_each(&ogs_pfcp_self()->pfcp_list6, node) {
|
|
|
|
sock = ogs_pfcp_server(node);
|
2021-04-21 08:24:17 +00:00
|
|
|
if (!sock) return OGS_ERROR;
|
2020-08-13 00:31:22 +00:00
|
|
|
|
2020-08-26 03:05:01 +00:00
|
|
|
node->poll = ogs_pollset_add(ogs_app()->pollset,
|
2020-08-13 00:31:22 +00:00
|
|
|
OGS_POLLIN, sock->fd, pfcp_recv_cb, sock);
|
2021-04-21 08:24:17 +00:00
|
|
|
ogs_assert(node->poll);
|
2020-08-13 00:31:22 +00:00
|
|
|
}
|
|
|
|
|
2021-03-15 01:01:55 +00:00
|
|
|
OGS_SETUP_PFCP_SERVER;
|
2020-08-13 00:31:22 +00:00
|
|
|
|
|
|
|
return OGS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
void sgwc_pfcp_close(void)
|
|
|
|
{
|
|
|
|
ogs_pfcp_node_t *pfcp_node = NULL;
|
|
|
|
|
2021-03-15 01:01:55 +00:00
|
|
|
ogs_list_for_each(&ogs_pfcp_self()->pfcp_peer_list, pfcp_node)
|
2020-08-13 00:31:22 +00:00
|
|
|
pfcp_node_fsm_fini(pfcp_node);
|
|
|
|
|
2023-02-23 07:59:59 +00:00
|
|
|
ogs_freeaddrinfo(ogs_pfcp_self()->pfcp_advertise);
|
|
|
|
ogs_freeaddrinfo(ogs_pfcp_self()->pfcp_advertise6);
|
|
|
|
|
2020-08-13 00:31:22 +00:00
|
|
|
ogs_socknode_remove_all(&ogs_pfcp_self()->pfcp_list);
|
|
|
|
ogs_socknode_remove_all(&ogs_pfcp_self()->pfcp_list6);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void sess_timeout(ogs_pfcp_xact_t *xact, void *data)
|
|
|
|
{
|
|
|
|
uint8_t type;
|
|
|
|
|
|
|
|
ogs_assert(xact);
|
|
|
|
type = xact->seq[0].type;
|
|
|
|
|
|
|
|
switch (type) {
|
|
|
|
case OGS_PFCP_SESSION_ESTABLISHMENT_REQUEST_TYPE:
|
|
|
|
ogs_error("No PFCP session establishment response");
|
|
|
|
break;
|
|
|
|
case OGS_PFCP_SESSION_MODIFICATION_REQUEST_TYPE:
|
|
|
|
ogs_error("No PFCP session modification response");
|
|
|
|
break;
|
|
|
|
case OGS_PFCP_SESSION_DELETION_REQUEST_TYPE:
|
|
|
|
ogs_error("No PFCP session deletion response");
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
ogs_error("Not implemented [type:%d]", type);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-01-23 03:17:01 +00:00
|
|
|
static void bearer_timeout(ogs_pfcp_xact_t *xact, void *data)
|
|
|
|
{
|
|
|
|
uint8_t type;
|
|
|
|
|
|
|
|
ogs_assert(xact);
|
|
|
|
type = xact->seq[0].type;
|
|
|
|
|
|
|
|
switch (type) {
|
|
|
|
case OGS_PFCP_SESSION_MODIFICATION_REQUEST_TYPE:
|
|
|
|
ogs_error("No PFCP session modification response");
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
ogs_error("Not implemented [type:%d]", type);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-05-12 13:52:36 +00:00
|
|
|
int sgwc_pfcp_send_bearer_to_modify_list(
|
|
|
|
sgwc_sess_t *sess, ogs_pfcp_xact_t *xact)
|
2020-08-13 00:31:22 +00:00
|
|
|
{
|
|
|
|
int rv;
|
|
|
|
ogs_pkbuf_t *sxabuf = NULL;
|
|
|
|
ogs_pfcp_header_t h;
|
|
|
|
|
|
|
|
ogs_assert(sess);
|
2022-05-12 13:52:36 +00:00
|
|
|
ogs_assert(xact);
|
2020-08-13 00:31:22 +00:00
|
|
|
|
2022-07-16 04:27:18 +00:00
|
|
|
xact->local_seid = sess->sgwc_sxa_seid;
|
|
|
|
|
2020-08-13 00:31:22 +00:00
|
|
|
memset(&h, 0, sizeof(ogs_pfcp_header_t));
|
2022-05-12 13:52:36 +00:00
|
|
|
h.type = OGS_PFCP_SESSION_MODIFICATION_REQUEST_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
|
|
|
h.seid_presence = OGS_PFCP_SEID_PRESENCE;
|
2020-08-13 00:31:22 +00:00
|
|
|
h.seid = sess->sgwu_sxa_seid;
|
|
|
|
|
2022-05-12 13:52:36 +00:00
|
|
|
sxabuf = sgwc_sxa_build_bearer_to_modify_list(h.type, sess, xact);
|
2023-01-23 15:01:36 +00:00
|
|
|
if (!sxabuf) {
|
|
|
|
ogs_error("sgwc_sxa_build_bearer_to_modify_list() failed");
|
|
|
|
return OGS_ERROR;
|
|
|
|
}
|
2022-04-29 12:28:16 +00:00
|
|
|
|
|
|
|
rv = ogs_pfcp_xact_update_tx(xact, &h, sxabuf);
|
2023-01-23 15:01:36 +00:00
|
|
|
if (rv != OGS_OK) {
|
|
|
|
ogs_error("ogs_pfcp_xact_update_tx() failed");
|
|
|
|
return OGS_ERROR;
|
|
|
|
}
|
2022-04-29 12:28:16 +00:00
|
|
|
|
2020-08-13 00:31:22 +00:00
|
|
|
rv = ogs_pfcp_xact_commit(xact);
|
|
|
|
ogs_expect(rv == OGS_OK);
|
2021-05-16 03:22:10 +00:00
|
|
|
|
|
|
|
return rv;
|
2020-08-13 00:31:22 +00:00
|
|
|
}
|
|
|
|
|
2022-05-12 13:52:36 +00:00
|
|
|
int sgwc_pfcp_send_session_establishment_request(
|
2023-04-15 09:54:03 +00:00
|
|
|
sgwc_sess_t *sess, ogs_gtp_xact_t *gtp_xact, ogs_pkbuf_t *gtpbuf,
|
|
|
|
uint64_t flags)
|
2022-04-29 12:28:16 +00:00
|
|
|
{
|
2022-05-12 13:52:36 +00:00
|
|
|
int rv;
|
|
|
|
ogs_pkbuf_t *sxabuf = NULL;
|
|
|
|
ogs_pfcp_header_t h;
|
2022-04-29 12:28:16 +00:00
|
|
|
ogs_pfcp_xact_t *xact = NULL;
|
|
|
|
|
|
|
|
ogs_assert(sess);
|
|
|
|
|
|
|
|
xact = ogs_pfcp_xact_local_create(sess->pfcp_node, sess_timeout, sess);
|
2023-01-23 15:01:36 +00:00
|
|
|
if (!xact) {
|
|
|
|
ogs_error("ogs_pfcp_xact_local_create() failed");
|
|
|
|
return OGS_ERROR;
|
|
|
|
}
|
2022-04-29 12:28:16 +00:00
|
|
|
|
|
|
|
xact->assoc_xact = gtp_xact;
|
|
|
|
if (gtpbuf) {
|
|
|
|
xact->gtpbuf = ogs_pkbuf_copy(gtpbuf);
|
2023-01-23 15:01:36 +00:00
|
|
|
if (!xact->gtpbuf) {
|
|
|
|
ogs_error("ogs_pkbuf_copy() failed");
|
|
|
|
return OGS_ERROR;
|
|
|
|
}
|
2022-04-29 12:28:16 +00:00
|
|
|
}
|
2022-06-30 01:35:03 +00:00
|
|
|
xact->local_seid = sess->sgwc_sxa_seid;
|
2023-04-15 09:54:03 +00:00
|
|
|
xact->create_flags = flags;
|
2022-04-29 12:28:16 +00:00
|
|
|
|
2020-08-13 00:31:22 +00:00
|
|
|
memset(&h, 0, sizeof(ogs_pfcp_header_t));
|
2022-05-12 13:52:36 +00:00
|
|
|
h.type = OGS_PFCP_SESSION_ESTABLISHMENT_REQUEST_TYPE;
|
2023-04-15 09:54:03 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* 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.
|
|
|
|
*/
|
[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
|
|
|
h.seid_presence = OGS_PFCP_SEID_PRESENCE;
|
2020-08-13 00:31:22 +00:00
|
|
|
h.seid = sess->sgwu_sxa_seid;
|
|
|
|
|
2022-05-12 13:52:36 +00:00
|
|
|
sxabuf = sgwc_sxa_build_session_establishment_request(h.type, sess);
|
2023-01-23 15:01:36 +00:00
|
|
|
if (!sxabuf) {
|
|
|
|
ogs_error("sgwc_sxa_build_session_establishment_request() failed");
|
|
|
|
return OGS_ERROR;
|
|
|
|
}
|
2020-08-13 00:31:22 +00:00
|
|
|
|
2022-04-29 12:28:16 +00:00
|
|
|
rv = ogs_pfcp_xact_update_tx(xact, &h, sxabuf);
|
2023-01-23 15:01:36 +00:00
|
|
|
if (rv != OGS_OK) {
|
|
|
|
ogs_error("ogs_pfcp_xact_update_tx() failed");
|
|
|
|
return OGS_ERROR;
|
|
|
|
}
|
2022-04-16 05:08:56 +00:00
|
|
|
|
2020-08-13 00:31:22 +00:00
|
|
|
rv = ogs_pfcp_xact_commit(xact);
|
|
|
|
ogs_expect(rv == OGS_OK);
|
2021-05-16 03:22:10 +00:00
|
|
|
|
|
|
|
return rv;
|
2020-08-13 00:31:22 +00:00
|
|
|
}
|
|
|
|
|
2022-05-12 13:52:36 +00:00
|
|
|
int sgwc_pfcp_send_session_modification_request(
|
2022-04-29 12:28:16 +00:00
|
|
|
sgwc_sess_t *sess, ogs_gtp_xact_t *gtp_xact,
|
|
|
|
ogs_pkbuf_t *gtpbuf, uint64_t flags)
|
|
|
|
{
|
|
|
|
ogs_pfcp_xact_t *xact = NULL;
|
|
|
|
sgwc_bearer_t *bearer = NULL;
|
|
|
|
|
|
|
|
ogs_assert(sess);
|
|
|
|
|
2022-05-12 13:52:36 +00:00
|
|
|
xact = ogs_pfcp_xact_local_create(sess->pfcp_node, sess_timeout, sess);
|
2023-01-23 15:01:36 +00:00
|
|
|
if (!xact) {
|
|
|
|
ogs_error("ogs_pfcp_xact_local_create() failed");
|
|
|
|
return OGS_ERROR;
|
|
|
|
}
|
2022-04-29 12:28:16 +00:00
|
|
|
|
2022-05-12 13:52:36 +00:00
|
|
|
xact->assoc_xact = gtp_xact;
|
|
|
|
xact->modify_flags = flags | OGS_PFCP_MODIFY_SESSION;
|
|
|
|
if (gtpbuf) {
|
|
|
|
xact->gtpbuf = ogs_pkbuf_copy(gtpbuf);
|
2023-01-23 15:01:36 +00:00
|
|
|
if (!xact->gtpbuf) {
|
|
|
|
ogs_error("ogs_pkbuf_copy() failed");
|
|
|
|
return OGS_ERROR;
|
|
|
|
}
|
2022-05-12 13:52:36 +00:00
|
|
|
}
|
2022-06-30 01:35:03 +00:00
|
|
|
xact->local_seid = sess->sgwc_sxa_seid;
|
2022-05-12 13:52:36 +00:00
|
|
|
|
2022-04-29 12:28:16 +00:00
|
|
|
ogs_list_for_each(&sess->bearer_list, bearer)
|
|
|
|
ogs_list_add(&xact->bearer_to_modify_list, &bearer->to_modify_node);
|
|
|
|
|
2022-05-12 13:52:36 +00:00
|
|
|
return sgwc_pfcp_send_bearer_to_modify_list(sess, xact);
|
2022-04-29 12:28:16 +00:00
|
|
|
}
|
|
|
|
|
2021-05-16 03:22:10 +00:00
|
|
|
int sgwc_pfcp_send_bearer_modification_request(
|
2020-08-13 00:31:22 +00:00
|
|
|
sgwc_bearer_t *bearer, ogs_gtp_xact_t *gtp_xact,
|
|
|
|
ogs_pkbuf_t *gtpbuf, uint64_t flags)
|
|
|
|
{
|
|
|
|
int rv;
|
|
|
|
ogs_pkbuf_t *sxabuf = NULL;
|
|
|
|
ogs_pfcp_header_t h;
|
|
|
|
ogs_pfcp_xact_t *xact = NULL;
|
|
|
|
sgwc_sess_t *sess = NULL;
|
|
|
|
|
|
|
|
ogs_assert(bearer);
|
|
|
|
sess = bearer->sess;
|
|
|
|
ogs_assert(sess);
|
|
|
|
|
2022-04-29 12:28:16 +00:00
|
|
|
xact = ogs_pfcp_xact_local_create(sess->pfcp_node, bearer_timeout, bearer);
|
2023-01-23 15:01:36 +00:00
|
|
|
if (!xact) {
|
|
|
|
ogs_error("ogs_pfcp_xact_local_create() failed");
|
|
|
|
return OGS_ERROR;
|
|
|
|
}
|
2022-04-29 12:28:16 +00:00
|
|
|
|
2020-08-13 00:31:22 +00:00
|
|
|
xact->assoc_xact = gtp_xact;
|
|
|
|
xact->modify_flags = flags;
|
2020-09-18 18:53:23 +00:00
|
|
|
if (gtpbuf) {
|
2020-08-13 00:31:22 +00:00
|
|
|
xact->gtpbuf = ogs_pkbuf_copy(gtpbuf);
|
2023-01-23 15:01:36 +00:00
|
|
|
if (!xact->gtpbuf) {
|
|
|
|
ogs_error("ogs_pkbuf_copy() failed");
|
|
|
|
return OGS_ERROR;
|
|
|
|
}
|
2020-09-18 18:53:23 +00:00
|
|
|
}
|
2022-06-30 01:35:03 +00:00
|
|
|
xact->local_seid = sess->sgwc_sxa_seid;
|
2020-08-13 00:31:22 +00:00
|
|
|
|
2022-04-29 12:28:16 +00:00
|
|
|
ogs_list_add(&xact->bearer_to_modify_list, &bearer->to_modify_node);
|
|
|
|
|
|
|
|
memset(&h, 0, sizeof(ogs_pfcp_header_t));
|
|
|
|
h.type = OGS_PFCP_SESSION_MODIFICATION_REQUEST_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
|
|
|
h.seid_presence = OGS_PFCP_SEID_PRESENCE;
|
2022-04-29 12:28:16 +00:00
|
|
|
h.seid = sess->sgwu_sxa_seid;
|
|
|
|
|
2022-05-12 13:52:36 +00:00
|
|
|
sxabuf = sgwc_sxa_build_bearer_to_modify_list(h.type, sess, xact);
|
2023-01-23 15:01:36 +00:00
|
|
|
if (!sxabuf) {
|
|
|
|
ogs_error("sgwc_sxa_build_bearer_to_modify_list() failed");
|
|
|
|
return OGS_ERROR;
|
|
|
|
}
|
2022-04-29 12:28:16 +00:00
|
|
|
|
|
|
|
rv = ogs_pfcp_xact_update_tx(xact, &h, sxabuf);
|
2023-01-23 15:01:36 +00:00
|
|
|
if (rv != OGS_OK) {
|
|
|
|
ogs_error("ogs_pfcp_xact_update_tx() failed");
|
|
|
|
return OGS_ERROR;
|
|
|
|
}
|
2022-04-16 05:08:56 +00:00
|
|
|
|
2020-08-13 00:31:22 +00:00
|
|
|
rv = ogs_pfcp_xact_commit(xact);
|
|
|
|
ogs_expect(rv == OGS_OK);
|
2021-05-16 03:22:10 +00:00
|
|
|
|
|
|
|
return rv;
|
2020-08-13 00:31:22 +00:00
|
|
|
}
|
|
|
|
|
2021-05-16 03:22:10 +00:00
|
|
|
int sgwc_pfcp_send_session_deletion_request(
|
2020-08-13 00:31:22 +00:00
|
|
|
sgwc_sess_t *sess, ogs_gtp_xact_t *gtp_xact, ogs_pkbuf_t *gtpbuf)
|
|
|
|
{
|
|
|
|
int rv;
|
|
|
|
ogs_pkbuf_t *sxabuf = NULL;
|
|
|
|
ogs_pfcp_header_t h;
|
|
|
|
ogs_pfcp_xact_t *xact = NULL;
|
|
|
|
|
|
|
|
ogs_assert(sess);
|
|
|
|
|
2022-04-29 12:28:16 +00:00
|
|
|
xact = ogs_pfcp_xact_local_create(sess->pfcp_node, sess_timeout, sess);
|
2023-01-23 15:01:36 +00:00
|
|
|
if (!xact) {
|
|
|
|
ogs_error("ogs_pfcp_xact_local_create() failed");
|
|
|
|
return OGS_ERROR;
|
|
|
|
}
|
2022-04-29 12:28:16 +00:00
|
|
|
|
2020-08-13 00:31:22 +00:00
|
|
|
xact->assoc_xact = gtp_xact;
|
2020-09-18 18:53:23 +00:00
|
|
|
if (gtpbuf) {
|
2020-08-13 00:31:22 +00:00
|
|
|
xact->gtpbuf = ogs_pkbuf_copy(gtpbuf);
|
2023-01-23 15:01:36 +00:00
|
|
|
if (!xact->gtpbuf) {
|
|
|
|
ogs_error("ogs_pkbuf_copy() failed");
|
|
|
|
return OGS_ERROR;
|
|
|
|
}
|
2020-09-18 18:53:23 +00:00
|
|
|
}
|
2022-06-30 01:35:03 +00:00
|
|
|
xact->local_seid = sess->sgwc_sxa_seid;
|
2020-08-13 00:31:22 +00:00
|
|
|
|
2022-05-12 13:52:36 +00:00
|
|
|
memset(&h, 0, sizeof(ogs_pfcp_header_t));
|
|
|
|
h.type = OGS_PFCP_SESSION_DELETION_REQUEST_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
|
|
|
h.seid_presence = OGS_PFCP_SEID_PRESENCE;
|
2022-05-12 13:52:36 +00:00
|
|
|
h.seid = sess->sgwu_sxa_seid;
|
|
|
|
|
2022-04-29 12:28:16 +00:00
|
|
|
sxabuf = sgwc_sxa_build_session_deletion_request(h.type, sess);
|
2023-01-23 15:01:36 +00:00
|
|
|
if (!sxabuf) {
|
|
|
|
ogs_error("sgwc_sxa_build_session_deletion_request() failed");
|
|
|
|
return OGS_ERROR;
|
|
|
|
}
|
2022-04-29 12:28:16 +00:00
|
|
|
|
|
|
|
rv = ogs_pfcp_xact_update_tx(xact, &h, sxabuf);
|
2023-01-23 15:01:36 +00:00
|
|
|
if (rv != OGS_OK) {
|
|
|
|
ogs_error("ogs_pfcp_xact_update_tx() failed");
|
|
|
|
return OGS_ERROR;
|
|
|
|
}
|
2022-04-29 12:28:16 +00:00
|
|
|
|
2020-08-13 00:31:22 +00:00
|
|
|
rv = ogs_pfcp_xact_commit(xact);
|
|
|
|
ogs_expect(rv == OGS_OK);
|
2021-05-16 03:22:10 +00:00
|
|
|
|
|
|
|
return rv;
|
2020-08-13 00:31:22 +00:00
|
|
|
}
|
|
|
|
|
2021-05-16 03:22:10 +00:00
|
|
|
int sgwc_pfcp_send_session_report_response(
|
2020-08-13 00:31:22 +00:00
|
|
|
ogs_pfcp_xact_t *xact, sgwc_sess_t *sess, uint8_t cause)
|
|
|
|
{
|
|
|
|
int rv;
|
|
|
|
ogs_pkbuf_t *sxabuf = NULL;
|
|
|
|
ogs_pfcp_header_t h;
|
|
|
|
|
|
|
|
memset(&h, 0, sizeof(ogs_pfcp_header_t));
|
|
|
|
h.type = OGS_PFCP_SESSION_REPORT_RESPONSE_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
|
|
|
h.seid_presence = OGS_PFCP_SEID_PRESENCE;
|
2020-08-13 00:31:22 +00:00
|
|
|
h.seid = sess->sgwu_sxa_seid;
|
|
|
|
|
|
|
|
sxabuf = ogs_pfcp_build_session_report_response(h.type, cause);
|
2023-01-23 15:01:36 +00:00
|
|
|
if (!sxabuf) {
|
|
|
|
ogs_error("ogs_pfcp_build_session_report_response() failed");
|
|
|
|
return OGS_ERROR;
|
|
|
|
}
|
2020-08-13 00:31:22 +00:00
|
|
|
|
|
|
|
rv = ogs_pfcp_xact_update_tx(xact, &h, sxabuf);
|
2023-01-23 15:01:36 +00:00
|
|
|
if (rv != OGS_OK) {
|
|
|
|
ogs_error("ogs_pfcp_xact_update_tx() failed");
|
|
|
|
return OGS_ERROR;
|
|
|
|
}
|
2020-08-13 00:31:22 +00:00
|
|
|
|
|
|
|
rv = ogs_pfcp_xact_commit(xact);
|
|
|
|
ogs_expect(rv == OGS_OK);
|
2021-05-16 03:22:10 +00:00
|
|
|
|
|
|
|
return rv;
|
2021-06-06 13:35:46 +00:00
|
|
|
}
|