forked from acouzens/open5gs
[GTP-U] Send Error Indication for unknown PDR
This commit is contained in:
parent
d2e2a58232
commit
aed52a9ad8
|
@ -1,6 +1,7 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (C) 2019 by Sukchan Lee <acetcom@gmail.com>
|
* Copyright (C) 2019 by Sukchan Lee <acetcom@gmail.com>
|
||||||
* Copyright (C) 2022 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de>
|
* 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.
|
* This file is part of Open5GS.
|
||||||
*
|
*
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (C) 2019 by Sukchan Lee <acetcom@gmail.com>
|
* Copyright (C) 2019 by Sukchan Lee <acetcom@gmail.com>
|
||||||
* Copyright (C) 2022 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de>
|
* 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.
|
* 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_request(uint8_t type);
|
||||||
ogs_pkbuf_t *ogs_gtp1_build_echo_response(uint8_t type, uint8_t recovery);
|
ogs_pkbuf_t *ogs_gtp1_build_echo_response(uint8_t type, uint8_t recovery);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (C) 2019 by Sukchan Lee <acetcom@gmail.com>
|
* Copyright (C) 2019 by Sukchan Lee <acetcom@gmail.com>
|
||||||
* Copyright (C) 2022 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de>
|
* 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.
|
* This file is part of Open5GS.
|
||||||
*
|
*
|
||||||
|
@ -143,8 +144,7 @@ void ogs_gtp1_send_error_message(
|
||||||
ogs_expect(rv == OGS_OK);
|
ogs_expect(rv == OGS_OK);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ogs_gtp1_send_echo_request(
|
void ogs_gtp1_send_echo_request(ogs_gtp_node_t *gnode)
|
||||||
ogs_gtp_node_t *gnode)
|
|
||||||
{
|
{
|
||||||
int rv;
|
int rv;
|
||||||
ogs_pkbuf_t *pkbuf = NULL;
|
ogs_pkbuf_t *pkbuf = NULL;
|
||||||
|
|
|
@ -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.
|
* This file is part of Open5GS.
|
||||||
*
|
*
|
||||||
|
@ -57,7 +57,7 @@ ogs_pkbuf_t *ogs_gtp2_build_echo_response(
|
||||||
return ogs_gtp2_build_msg(>p_message);
|
return ogs_gtp2_build_msg(>p_message);
|
||||||
}
|
}
|
||||||
|
|
||||||
ogs_pkbuf_t *ogs_gtp2_build_error_indication(
|
ogs_pkbuf_t *ogs_gtp1_build_error_indication(
|
||||||
uint32_t teid, ogs_sockaddr_t *addr)
|
uint32_t teid, ogs_sockaddr_t *addr)
|
||||||
{
|
{
|
||||||
ogs_pkbuf_t *pkbuf = NULL;
|
ogs_pkbuf_t *pkbuf = NULL;
|
||||||
|
@ -112,3 +112,91 @@ ogs_pkbuf_t *ogs_gtp2_build_error_indication(
|
||||||
|
|
||||||
return pkbuf;
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -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.
|
* 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(
|
ogs_pkbuf_t *ogs_gtp2_build_echo_response(
|
||||||
uint8_t type, uint8_t recovery, uint8_t features);
|
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);
|
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
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -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.
|
* This file is part of Open5GS.
|
||||||
*
|
*
|
||||||
|
@ -27,92 +27,11 @@ int ogs_gtp2_send_user_plane(
|
||||||
char buf[OGS_ADDRSTRLEN];
|
char buf[OGS_ADDRSTRLEN];
|
||||||
int rv;
|
int rv;
|
||||||
|
|
||||||
ogs_gtp2_header_t *gtp_h = NULL;
|
ogs_gtp2_fill_header(gtp_hdesc, ext_hdesc, pkbuf);
|
||||||
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_trace("SEND GTP-U[%d] to Peer[%s] : TEID[0x%x]",
|
ogs_trace("SEND GTP-U[%d] to Peer[%s] : TEID[0x%x]",
|
||||||
gtp_hdesc->type, OGS_ADDR(&gnode->addr, buf), gtp_hdesc->teid);
|
gtp_hdesc->type, OGS_ADDR(&gnode->addr, buf), gtp_hdesc->teid);
|
||||||
|
|
||||||
rv = ogs_gtp_sendto(gnode, pkbuf);
|
rv = ogs_gtp_sendto(gnode, pkbuf);
|
||||||
if (rv != OGS_OK) {
|
if (rv != OGS_OK) {
|
||||||
if (ogs_socket_errno != OGS_EAGAIN) {
|
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);
|
rv = ogs_gtp_xact_commit(xact);
|
||||||
ogs_expect(rv == OGS_OK);
|
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(>p_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(>p_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);
|
||||||
|
}
|
||||||
|
|
|
@ -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.
|
* 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,
|
void ogs_gtp2_send_echo_response(ogs_gtp_xact_t *xact,
|
||||||
uint8_t recovery, uint8_t features);
|
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
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1316,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);
|
&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;
|
ogs_pfcp_far_hash_f_teid_t hashkey;
|
||||||
int hashkey_len;
|
int hashkey_len;
|
||||||
|
@ -1378,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);
|
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)
|
void ogs_pfcp_far_teid_hash_set(ogs_pfcp_far_t *far)
|
||||||
{
|
{
|
||||||
ogs_assert(far);
|
ogs_assert(far);
|
||||||
|
|
|
@ -427,7 +427,11 @@ ogs_pfcp_far_t *ogs_pfcp_far_find_or_add(
|
||||||
ogs_pfcp_sess_t *sess, ogs_pfcp_far_id_t id);
|
ogs_pfcp_sess_t *sess, ogs_pfcp_far_id_t id);
|
||||||
|
|
||||||
void ogs_pfcp_far_f_teid_hash_set(ogs_pfcp_far_t *far);
|
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);
|
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);
|
ogs_pfcp_far_t *ogs_pfcp_far_find_by_teid(uint32_t teid);
|
||||||
|
|
|
@ -610,71 +610,6 @@ sgwc_bearer_t *sgwc_bearer_find_by_ue_ebi(sgwc_ue_t *sgwc_ue, uint8_t ebi)
|
||||||
return NULL;
|
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)
|
sgwc_bearer_t *sgwc_default_bearer_in_sess(sgwc_sess_t *sess)
|
||||||
{
|
{
|
||||||
ogs_assert(sess);
|
ogs_assert(sess);
|
||||||
|
@ -722,6 +657,7 @@ sgwc_tunnel_t *sgwc_tunnel_add(
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
ogs_fatal("Invalid interface type = %d", interface_type);
|
ogs_fatal("Invalid interface type = %d", interface_type);
|
||||||
|
ogs_assert_if_reached();
|
||||||
}
|
}
|
||||||
|
|
||||||
ogs_pool_alloc(&sgwc_tunnel_pool, &tunnel);
|
ogs_pool_alloc(&sgwc_tunnel_pool, &tunnel);
|
||||||
|
@ -902,6 +838,28 @@ sgwc_tunnel_t *sgwc_tunnel_find_by_pdr_id(
|
||||||
return NULL;
|
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)
|
sgwc_tunnel_t *sgwc_dl_tunnel_in_bearer(sgwc_bearer_t *bearer)
|
||||||
{
|
{
|
||||||
ogs_assert(bearer);
|
ogs_assert(bearer);
|
||||||
|
|
|
@ -168,9 +168,6 @@ sgwc_bearer_t *sgwc_bearer_find_by_sess_ebi(
|
||||||
sgwc_sess_t *sess, uint8_t ebi);
|
sgwc_sess_t *sess, uint8_t ebi);
|
||||||
sgwc_bearer_t *sgwc_bearer_find_by_ue_ebi(
|
sgwc_bearer_t *sgwc_bearer_find_by_ue_ebi(
|
||||||
sgwc_ue_t *sgwc_ue, uint8_t 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_default_bearer_in_sess(sgwc_sess_t *sess);
|
||||||
sgwc_bearer_t *sgwc_bearer_cycle(sgwc_bearer_t *bearer);
|
sgwc_bearer_t *sgwc_bearer_cycle(sgwc_bearer_t *bearer);
|
||||||
|
|
||||||
|
@ -183,6 +180,8 @@ sgwc_tunnel_t *sgwc_tunnel_find_by_interface_type(
|
||||||
sgwc_bearer_t *bearer, uint8_t interface_type);
|
sgwc_bearer_t *bearer, uint8_t interface_type);
|
||||||
sgwc_tunnel_t *sgwc_tunnel_find_by_pdr_id(
|
sgwc_tunnel_t *sgwc_tunnel_find_by_pdr_id(
|
||||||
sgwc_sess_t *sess, ogs_pfcp_pdr_id_t 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_dl_tunnel_in_bearer(sgwc_bearer_t *bearer);
|
||||||
sgwc_tunnel_t *sgwc_ul_tunnel_in_bearer(sgwc_bearer_t *bearer);
|
sgwc_tunnel_t *sgwc_ul_tunnel_in_bearer(sgwc_bearer_t *bearer);
|
||||||
|
|
||||||
|
|
|
@ -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.
|
* This file is part of Open5GS.
|
||||||
*
|
*
|
||||||
|
|
|
@ -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.
|
* This file is part of Open5GS.
|
||||||
*
|
*
|
||||||
|
@ -1297,10 +1297,7 @@ void sgwc_sxa_handle_session_deletion_response(
|
||||||
|
|
||||||
ogs_pfcp_xact_commit(pfcp_xact);
|
ogs_pfcp_xact_commit(pfcp_xact);
|
||||||
|
|
||||||
if (!gtp_message) {
|
if (!gtp_message) goto cleanup;
|
||||||
ogs_error("No GTP Message");
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (gtp_message->h.type == OGS_GTP2_DELETE_SESSION_REQUEST_TYPE) {
|
if (gtp_message->h.type == OGS_GTP2_DELETE_SESSION_REQUEST_TYPE) {
|
||||||
/*
|
/*
|
||||||
|
@ -1380,7 +1377,10 @@ void sgwc_sxa_handle_session_deletion_response(
|
||||||
}
|
}
|
||||||
|
|
||||||
cleanup:
|
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(
|
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_ue_t *sgwc_ue = NULL;
|
||||||
sgwc_bearer_t *bearer = NULL;
|
sgwc_bearer_t *bearer = NULL;
|
||||||
sgwc_tunnel_t *tunnel = NULL;
|
sgwc_tunnel_t *tunnel = NULL;
|
||||||
|
ogs_pfcp_far_t *far = NULL;
|
||||||
|
|
||||||
ogs_pfcp_report_type_t report_type;
|
ogs_pfcp_report_type_t report_type;
|
||||||
uint8_t cause_value = 0;
|
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);
|
ogs_error("Cannot find the PDR-ID[%d]", pdr_id);
|
||||||
|
|
||||||
} else if (report_type.error_indication_report) {
|
} else if (report_type.error_indication_report) {
|
||||||
bearer = sgwc_bearer_find_by_error_indication_report(
|
far = ogs_pfcp_far_find_by_pfcp_session_report(
|
||||||
sess, &pfcp_req->error_indication_report);
|
&sess->pfcp, &pfcp_req->error_indication_report);
|
||||||
|
if (far) {
|
||||||
if (!bearer) return;
|
tunnel = sgwc_tunnel_find_by_far_id(sess, far->id);
|
||||||
|
ogs_assert(tunnel);
|
||||||
ogs_list_for_each(&sgwc_ue->sess_list, sess) {
|
bearer = tunnel->bearer;
|
||||||
|
ogs_assert(bearer);
|
||||||
ogs_assert(OGS_OK ==
|
if (far->dst_if == OGS_PFCP_INTERFACE_ACCESS) {
|
||||||
sgwc_pfcp_send_session_modification_request(sess,
|
ogs_warn("[%s] Error Indication from eNB", sgwc_ue->imsi_bcd);
|
||||||
/* We only use the `assoc_xact` parameter temporarily here
|
ogs_list_for_each(&sgwc_ue->sess_list, sess) {
|
||||||
* to pass the `bearer` context. */
|
ogs_assert(OGS_OK ==
|
||||||
(ogs_gtp_xact_t *)bearer,
|
sgwc_pfcp_send_session_modification_request(sess,
|
||||||
NULL,
|
/* We only use the `assoc_xact` parameter temporarily here
|
||||||
OGS_PFCP_MODIFY_DL_ONLY|OGS_PFCP_MODIFY_DEACTIVATE|
|
* to pass the `bearer` context. */
|
||||||
OGS_PFCP_MODIFY_ERROR_INDICATION));
|
(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 {
|
} else {
|
||||||
ogs_error("Not supported Report Type[%d]", report_type.value);
|
ogs_error("Not supported Report Type[%d]", report_type.value);
|
||||||
|
|
|
@ -28,11 +28,13 @@ static void _gtpv1_u_recv_cb(short when, ogs_socket_t fd, void *data)
|
||||||
{
|
{
|
||||||
int len;
|
int len;
|
||||||
ssize_t size;
|
ssize_t size;
|
||||||
char buf[OGS_ADDRSTRLEN];
|
char buf1[OGS_ADDRSTRLEN];
|
||||||
|
char buf2[OGS_ADDRSTRLEN];
|
||||||
|
|
||||||
sgwu_sess_t *sess = NULL;
|
sgwu_sess_t *sess = NULL;
|
||||||
|
|
||||||
ogs_pkbuf_t *pkbuf = NULL;
|
ogs_pkbuf_t *pkbuf = NULL;
|
||||||
|
ogs_sock_t *sock = NULL;
|
||||||
ogs_sockaddr_t from;
|
ogs_sockaddr_t from;
|
||||||
|
|
||||||
ogs_gtp2_header_t *gtp_h = NULL;
|
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;
|
uint8_t qfi;
|
||||||
|
|
||||||
ogs_assert(fd != INVALID_SOCKET);
|
ogs_assert(fd != INVALID_SOCKET);
|
||||||
|
sock = data;
|
||||||
|
ogs_assert(sock);
|
||||||
|
|
||||||
pkbuf = ogs_pkbuf_alloc(packet_pool, OGS_MAX_PKT_LEN);
|
pkbuf = ogs_pkbuf_alloc(packet_pool, OGS_MAX_PKT_LEN);
|
||||||
ogs_assert(pkbuf);
|
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) {
|
if (gtp_h->type == OGS_GTPU_MSGTYPE_ECHO_REQ) {
|
||||||
ogs_pkbuf_t *echo_rsp;
|
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);
|
echo_rsp = ogs_gtp2_handle_echo_req(pkbuf);
|
||||||
ogs_expect(echo_rsp);
|
ogs_expect(echo_rsp);
|
||||||
if (echo_rsp) {
|
if (echo_rsp) {
|
||||||
ssize_t sent;
|
ssize_t sent;
|
||||||
|
|
||||||
/* Echo reply */
|
/* 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);
|
sent = ogs_sendto(fd, echo_rsp->data, echo_rsp->len, 0, &from);
|
||||||
if (sent < 0 || sent != echo_rsp->len) {
|
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);
|
teid = be32toh(gtp_h->teid);
|
||||||
|
|
||||||
ogs_trace("[RECV] GPU-U Type [%d] from [%s] : TEID[0x%x]",
|
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;
|
qfi = 0;
|
||||||
if (gtp_h->flags & OGS_GTPU_FLAGS_E) {
|
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);
|
pfcp_object = ogs_pfcp_object_find_by_teid(teid);
|
||||||
if (!pfcp_object) {
|
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;
|
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) {
|
} else if (gtp_h->type == OGS_GTPU_MSGTYPE_ERR_IND) {
|
||||||
ogs_pfcp_far_t *far = NULL;
|
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) {
|
if (far) {
|
||||||
ogs_assert(true ==
|
ogs_assert(true ==
|
||||||
ogs_pfcp_up_handle_error_indication(far, &report));
|
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 ==
|
ogs_assert(OGS_OK ==
|
||||||
sgwu_pfcp_send_session_report_request(sess, &report));
|
sgwu_pfcp_send_session_report_request(sess, &report));
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
ogs_error("[DROP] Cannot find FAR by Error-Indication");
|
ogs_error("[DROP] Cannot find FAR by Error-Indication");
|
||||||
ogs_log_hexdump(OGS_LOG_ERROR, pkbuf->data, pkbuf->len);
|
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);
|
pfcp_object = ogs_pfcp_object_find_by_teid(teid);
|
||||||
if (!pfcp_object) {
|
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;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1641,68 +1641,6 @@ void smf_sess_set_paging_n1n2message_location(
|
||||||
sess);
|
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)
|
void smf_sess_remove(smf_sess_t *sess)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
|
@ -465,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_ipv6(uint32_t *addr6);
|
||||||
smf_sess_t *smf_sess_find_by_paging_n1n2message_location(
|
smf_sess_t *smf_sess_find_by_paging_n1n2message_location(
|
||||||
char *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);
|
void smf_sess_create_indirect_data_forwarding(smf_sess_t *sess);
|
||||||
bool smf_sess_have_indirect_data_forwarding(smf_sess_t *sess);
|
bool smf_sess_have_indirect_data_forwarding(smf_sess_t *sess);
|
||||||
|
|
|
@ -851,6 +851,11 @@ void smf_gsm_state_operational(ogs_fsm_t *s, smf_event_t *e)
|
||||||
}
|
}
|
||||||
break;
|
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:
|
default:
|
||||||
ogs_error("cannot handle PFCP message type[%d]",
|
ogs_error("cannot handle PFCP message type[%d]",
|
||||||
pfcp_message->h.type);
|
pfcp_message->h.type);
|
||||||
|
|
|
@ -1148,9 +1148,11 @@ void smf_n4_handle_session_report_request(
|
||||||
smf_sess_t *sess, ogs_pfcp_xact_t *pfcp_xact,
|
smf_sess_t *sess, ogs_pfcp_xact_t *pfcp_xact,
|
||||||
ogs_pfcp_session_report_request_t *pfcp_req)
|
ogs_pfcp_session_report_request_t *pfcp_req)
|
||||||
{
|
{
|
||||||
|
smf_ue_t *smf_ue = NULL;
|
||||||
smf_bearer_t *qos_flow = NULL;
|
smf_bearer_t *qos_flow = NULL;
|
||||||
smf_bearer_t *bearer = NULL;
|
smf_bearer_t *bearer = NULL;
|
||||||
ogs_pfcp_pdr_t *pdr = NULL;
|
ogs_pfcp_pdr_t *pdr = NULL;
|
||||||
|
ogs_pfcp_far_t *far = NULL;
|
||||||
|
|
||||||
ogs_pfcp_report_type_t report_type;
|
ogs_pfcp_report_type_t report_type;
|
||||||
uint8_t cause_value = 0;
|
uint8_t cause_value = 0;
|
||||||
|
@ -1184,6 +1186,9 @@ void smf_n4_handle_session_report_request(
|
||||||
}
|
}
|
||||||
|
|
||||||
ogs_assert(sess);
|
ogs_assert(sess);
|
||||||
|
smf_ue = sess->smf_ue;
|
||||||
|
ogs_assert(smf_ue);
|
||||||
|
|
||||||
report_type.value = pfcp_req->report_type.u8;
|
report_type.value = pfcp_req->report_type.u8;
|
||||||
|
|
||||||
if (report_type.downlink_data_report) {
|
if (report_type.downlink_data_report) {
|
||||||
|
@ -1270,21 +1275,10 @@ void smf_n4_handle_session_report_request(
|
||||||
}
|
}
|
||||||
|
|
||||||
if (report_type.error_indication_report) {
|
if (report_type.error_indication_report) {
|
||||||
smf_ue_t *smf_ue = sess->smf_ue;
|
far = ogs_pfcp_far_find_by_pfcp_session_report(
|
||||||
smf_sess_t *error_indication_session = NULL;
|
&sess->pfcp, &pfcp_req->error_indication_report);
|
||||||
ogs_assert(smf_ue);
|
if (!far)
|
||||||
|
ogs_error("Cannot find Session in Error Indication");
|
||||||
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));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (report_type.usage_report) {
|
if (report_type.usage_report) {
|
||||||
|
@ -1341,4 +1335,24 @@ void smf_n4_handle_session_report_request(
|
||||||
smf_pfcp_send_session_report_response(
|
smf_pfcp_send_session_report_response(
|
||||||
pfcp_xact, sess, OGS_PFCP_CAUSE_SYSTEM_FAILURE));
|
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));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -258,11 +258,13 @@ static void _gtpv1_u_recv_cb(short when, ogs_socket_t fd, void *data)
|
||||||
{
|
{
|
||||||
int len;
|
int len;
|
||||||
ssize_t size;
|
ssize_t size;
|
||||||
char buf[OGS_ADDRSTRLEN];
|
char buf1[OGS_ADDRSTRLEN];
|
||||||
|
char buf2[OGS_ADDRSTRLEN];
|
||||||
|
|
||||||
upf_sess_t *sess = NULL;
|
upf_sess_t *sess = NULL;
|
||||||
|
|
||||||
ogs_pkbuf_t *pkbuf = NULL;
|
ogs_pkbuf_t *pkbuf = NULL;
|
||||||
|
ogs_sock_t *sock = NULL;
|
||||||
ogs_sockaddr_t from;
|
ogs_sockaddr_t from;
|
||||||
|
|
||||||
ogs_gtp2_header_t *gtp_h = NULL;
|
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;
|
uint8_t qfi;
|
||||||
|
|
||||||
ogs_assert(fd != INVALID_SOCKET);
|
ogs_assert(fd != INVALID_SOCKET);
|
||||||
|
sock = data;
|
||||||
|
ogs_assert(sock);
|
||||||
|
|
||||||
pkbuf = ogs_pkbuf_alloc(packet_pool, OGS_MAX_PKT_LEN);
|
pkbuf = ogs_pkbuf_alloc(packet_pool, OGS_MAX_PKT_LEN);
|
||||||
ogs_assert(pkbuf);
|
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) {
|
if (gtp_h->type == OGS_GTPU_MSGTYPE_ECHO_REQ) {
|
||||||
ogs_pkbuf_t *echo_rsp;
|
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);
|
echo_rsp = ogs_gtp2_handle_echo_req(pkbuf);
|
||||||
ogs_expect(echo_rsp);
|
ogs_expect(echo_rsp);
|
||||||
if (echo_rsp) {
|
if (echo_rsp) {
|
||||||
ssize_t sent;
|
ssize_t sent;
|
||||||
|
|
||||||
/* Echo reply */
|
/* 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);
|
sent = ogs_sendto(fd, echo_rsp->data, echo_rsp->len, 0, &from);
|
||||||
if (sent < 0 || sent != echo_rsp->len) {
|
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);
|
teid = be32toh(gtp_h->teid);
|
||||||
|
|
||||||
ogs_trace("[RECV] GPU-U Type [%d] from [%s] : TEID[0x%x]",
|
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;
|
qfi = 0;
|
||||||
if (gtp_h->flags & OGS_GTPU_FLAGS_E) {
|
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) {
|
} else if (gtp_h->type == OGS_GTPU_MSGTYPE_ERR_IND) {
|
||||||
ogs_pfcp_far_t *far = NULL;
|
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) {
|
if (far) {
|
||||||
ogs_assert(true ==
|
ogs_assert(true ==
|
||||||
ogs_pfcp_up_handle_error_indication(far, &report));
|
ogs_pfcp_up_handle_error_indication(far, &report));
|
||||||
|
@ -419,7 +423,25 @@ static void _gtpv1_u_recv_cb(short when, ogs_socket_t fd, void *data)
|
||||||
|
|
||||||
pfcp_object = ogs_pfcp_object_find_by_teid(teid);
|
pfcp_object = ogs_pfcp_object_find_by_teid(teid);
|
||||||
if (!pfcp_object) {
|
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;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -458,7 +480,26 @@ static void _gtpv1_u_recv_cb(short when, ogs_socket_t fd, void *data)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!pdr) {
|
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;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -499,7 +499,7 @@ int test_gtpu_send_error_indication(
|
||||||
ogs_assert_if_reached();
|
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);
|
ogs_assert(pkbuf);
|
||||||
|
|
||||||
memset(>p_hdesc, 0, sizeof(gtp_hdesc));
|
memset(>p_hdesc, 0, sizeof(gtp_hdesc));
|
||||||
|
|
|
@ -806,9 +806,6 @@ static void direct_complete_func(abts_case *tc, void *data)
|
||||||
rv = testgnb_ngap_send(ngap2, sendbuf);
|
rv = testgnb_ngap_send(ngap2, sendbuf);
|
||||||
ABTS_INT_EQUAL(tc, OGS_OK, rv);
|
ABTS_INT_EQUAL(tc, OGS_OK, rv);
|
||||||
|
|
||||||
/* Waiting for N4 */
|
|
||||||
ogs_msleep(100);
|
|
||||||
|
|
||||||
/* Receive End Mark */
|
/* Receive End Mark */
|
||||||
recvbuf = test_gtpu_read(gtpu1);
|
recvbuf = test_gtpu_read(gtpu1);
|
||||||
ABTS_PTR_NOTNULL(tc, recvbuf);
|
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);
|
rv = testgnb_ngap_send(ngap1, sendbuf);
|
||||||
ABTS_INT_EQUAL(tc, OGS_OK, rv);
|
ABTS_INT_EQUAL(tc, OGS_OK, rv);
|
||||||
|
|
||||||
/* Waiting for N4 */
|
|
||||||
ogs_msleep(100);
|
|
||||||
|
|
||||||
/* Receive End Mark */
|
/* Receive End Mark */
|
||||||
recvbuf = test_gtpu_read(gtpu2);
|
recvbuf = test_gtpu_read(gtpu2);
|
||||||
ABTS_PTR_NOTNULL(tc, recvbuf);
|
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);
|
rv = testgnb_ngap_send(ngap2, sendbuf);
|
||||||
ABTS_INT_EQUAL(tc, OGS_OK, rv);
|
ABTS_INT_EQUAL(tc, OGS_OK, rv);
|
||||||
|
|
||||||
/* Waiting for N4 */
|
|
||||||
ogs_msleep(100);
|
|
||||||
|
|
||||||
/* Receive End Mark */
|
/* Receive End Mark */
|
||||||
recvbuf = test_gtpu_read(gtpu1);
|
recvbuf = test_gtpu_read(gtpu1);
|
||||||
ABTS_PTR_NOTNULL(tc, recvbuf);
|
ABTS_PTR_NOTNULL(tc, recvbuf);
|
||||||
|
@ -1916,6 +1907,9 @@ static void indirect_complete_func(abts_case *tc, void *data)
|
||||||
ABTS_PTR_NOTNULL(tc, recvbuf);
|
ABTS_PTR_NOTNULL(tc, recvbuf);
|
||||||
ogs_pkbuf_free(recvbuf);
|
ogs_pkbuf_free(recvbuf);
|
||||||
|
|
||||||
|
/* Waiting for removing Indirect Data Forwarding */
|
||||||
|
ogs_msleep(100);
|
||||||
|
|
||||||
/* Send HandoverRequired */
|
/* Send HandoverRequired */
|
||||||
sendbuf = testngap_build_handover_required(
|
sendbuf = testngap_build_handover_required(
|
||||||
test_ue, NGAP_HandoverType_intra5gs,
|
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);
|
rv = testgnb_ngap_send(ngap1, sendbuf);
|
||||||
ABTS_INT_EQUAL(tc, OGS_OK, rv);
|
ABTS_INT_EQUAL(tc, OGS_OK, rv);
|
||||||
|
|
||||||
/* Waiting for N4 */
|
|
||||||
ogs_msleep(100);
|
|
||||||
|
|
||||||
/* Receive End Mark */
|
/* Receive End Mark */
|
||||||
recvbuf = test_gtpu_read(gtpu2);
|
recvbuf = test_gtpu_read(gtpu2);
|
||||||
ABTS_PTR_NOTNULL(tc, recvbuf);
|
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);
|
rv = testgnb_ngap_send(ngap2, sendbuf);
|
||||||
ABTS_INT_EQUAL(tc, OGS_OK, rv);
|
ABTS_INT_EQUAL(tc, OGS_OK, rv);
|
||||||
|
|
||||||
/* Waiting for N4 */
|
|
||||||
ogs_msleep(100);
|
|
||||||
|
|
||||||
/* Receive End Mark */
|
/* Receive End Mark */
|
||||||
recvbuf = test_gtpu_read(gtpu1);
|
recvbuf = test_gtpu_read(gtpu1);
|
||||||
ABTS_PTR_NOTNULL(tc, recvbuf);
|
ABTS_PTR_NOTNULL(tc, recvbuf);
|
||||||
|
|
Loading…
Reference in New Issue