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) 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.
|
||||
*
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
/*
|
||||
* Copyright (C) 2019 by Sukchan Lee <acetcom@gmail.com>
|
||||
* Copyright (C) 2022 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de>
|
||||
* Copyright (C) 2023 by Sukchan Lee <acetcom@gmail.com>
|
||||
*
|
||||
* This file is part of Open5GS.
|
||||
*
|
||||
|
@ -31,6 +32,7 @@ extern "C" {
|
|||
|
||||
ogs_pkbuf_t *ogs_gtp1_build_echo_request(uint8_t type);
|
||||
ogs_pkbuf_t *ogs_gtp1_build_echo_response(uint8_t type, uint8_t recovery);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
/*
|
||||
* Copyright (C) 2019 by Sukchan Lee <acetcom@gmail.com>
|
||||
* Copyright (C) 2022 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de>
|
||||
* Copyright (C) 2023 by Sukchan Lee <acetcom@gmail.com>
|
||||
*
|
||||
* This file is part of Open5GS.
|
||||
*
|
||||
|
@ -143,8 +144,7 @@ void ogs_gtp1_send_error_message(
|
|||
ogs_expect(rv == OGS_OK);
|
||||
}
|
||||
|
||||
void ogs_gtp1_send_echo_request(
|
||||
ogs_gtp_node_t *gnode)
|
||||
void ogs_gtp1_send_echo_request(ogs_gtp_node_t *gnode)
|
||||
{
|
||||
int rv;
|
||||
ogs_pkbuf_t *pkbuf = NULL;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (C) 2019 by Sukchan Lee <acetcom@gmail.com>
|
||||
* Copyright (C) 2019-2023 by Sukchan Lee <acetcom@gmail.com>
|
||||
*
|
||||
* This file is part of Open5GS.
|
||||
*
|
||||
|
@ -57,7 +57,7 @@ ogs_pkbuf_t *ogs_gtp2_build_echo_response(
|
|||
return ogs_gtp2_build_msg(>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)
|
||||
{
|
||||
ogs_pkbuf_t *pkbuf = NULL;
|
||||
|
@ -112,3 +112,91 @@ ogs_pkbuf_t *ogs_gtp2_build_error_indication(
|
|||
|
||||
return pkbuf;
|
||||
}
|
||||
|
||||
void ogs_gtp2_fill_header(
|
||||
ogs_gtp2_header_t *gtp_hdesc, ogs_gtp2_extension_header_t *ext_hdesc,
|
||||
ogs_pkbuf_t *pkbuf)
|
||||
{
|
||||
ogs_gtp2_header_t *gtp_h = NULL;
|
||||
ogs_gtp2_extension_header_t *ext_h = NULL;
|
||||
uint8_t flags;
|
||||
uint8_t gtp_hlen = 0;
|
||||
|
||||
ogs_assert(gtp_hdesc);
|
||||
ogs_assert(ext_hdesc);
|
||||
ogs_assert(pkbuf);
|
||||
|
||||
/* Processing GTP Flags */
|
||||
flags = gtp_hdesc->flags;
|
||||
flags |= OGS_GTPU_FLAGS_V | OGS_GTPU_FLAGS_PT;
|
||||
if (ext_hdesc->qos_flow_identifier) flags |= OGS_GTPU_FLAGS_E;
|
||||
|
||||
/* Define GTP Header Size */
|
||||
if (flags & OGS_GTPU_FLAGS_E)
|
||||
gtp_hlen = OGS_GTPV1U_HEADER_LEN+8;
|
||||
else if (flags & (OGS_GTPU_FLAGS_S|OGS_GTPU_FLAGS_PN))
|
||||
gtp_hlen = OGS_GTPV1U_HEADER_LEN+4;
|
||||
else
|
||||
gtp_hlen = OGS_GTPV1U_HEADER_LEN;
|
||||
|
||||
ogs_pkbuf_push(pkbuf, gtp_hlen);
|
||||
|
||||
/* Fill GTP Header */
|
||||
gtp_h = (ogs_gtp2_header_t *)pkbuf->data;
|
||||
ogs_assert(gtp_h);
|
||||
memset(gtp_h, 0, gtp_hlen);
|
||||
|
||||
gtp_h->flags = flags;
|
||||
gtp_h->type = gtp_hdesc->type;
|
||||
|
||||
if (gtp_h->type == OGS_GTPU_MSGTYPE_ECHO_REQ ||
|
||||
gtp_h->type == OGS_GTPU_MSGTYPE_ECHO_RSP ||
|
||||
gtp_h->type == OGS_GTPU_MSGTYPE_ERR_IND) {
|
||||
/*
|
||||
* TS29.281 5.1 General format in GTP-U header
|
||||
*
|
||||
* - The Echo Request/Response and Supported Extension Headers
|
||||
* notification messages, where the Tunnel Endpoint Identifier
|
||||
* shall be set to all zeroes.
|
||||
* - The Error Indication message where the Tunnel Endpoint Identifier
|
||||
* shall be set to all zeros.
|
||||
*/
|
||||
ogs_assert(gtp_hdesc->teid == 0);
|
||||
}
|
||||
|
||||
gtp_h->teid = htobe32(gtp_hdesc->teid);
|
||||
|
||||
/*
|
||||
* TS29.281 5.1 General format in GTP-U header
|
||||
*
|
||||
* Length: This field indicates the length in octets of the payload,
|
||||
* i.e. the rest of the packet following the mandatory part of
|
||||
* the GTP header (that is the first 8 octets). The Sequence Number,
|
||||
* the N-PDU Number or any Extension headers shall be considered
|
||||
* to be part of the payload, i.e. included in the length count.
|
||||
*/
|
||||
gtp_h->length = htobe16(pkbuf->len - OGS_GTPV1U_HEADER_LEN);
|
||||
|
||||
/* Fill Extention Header */
|
||||
if (gtp_h->flags & OGS_GTPU_FLAGS_E) {
|
||||
ext_h = (ogs_gtp2_extension_header_t *)
|
||||
(pkbuf->data + OGS_GTPV1U_HEADER_LEN);
|
||||
ogs_assert(ext_h);
|
||||
|
||||
if (ext_hdesc->qos_flow_identifier) {
|
||||
/* 5G Core */
|
||||
ext_h->type = OGS_GTP2_EXTENSION_HEADER_TYPE_PDU_SESSION_CONTAINER;
|
||||
ext_h->len = 1;
|
||||
ext_h->pdu_type = ext_hdesc->pdu_type;
|
||||
ext_h->qos_flow_identifier = ext_hdesc->qos_flow_identifier;
|
||||
ext_h->next_type =
|
||||
OGS_GTP2_EXTENSION_HEADER_TYPE_NO_MORE_EXTENSION_HEADERS;
|
||||
} else {
|
||||
/* EPC */
|
||||
ext_h->type = ext_hdesc->type;
|
||||
ext_h->len = 1;
|
||||
ext_h->next_type =
|
||||
OGS_GTP2_EXTENSION_HEADER_TYPE_NO_MORE_EXTENSION_HEADERS;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (C) 2019 by Sukchan Lee <acetcom@gmail.com>
|
||||
* Copyright (C) 2019-2023 by Sukchan Lee <acetcom@gmail.com>
|
||||
*
|
||||
* This file is part of Open5GS.
|
||||
*
|
||||
|
@ -33,9 +33,13 @@ ogs_pkbuf_t *ogs_gtp2_build_echo_request(
|
|||
ogs_pkbuf_t *ogs_gtp2_build_echo_response(
|
||||
uint8_t type, uint8_t recovery, uint8_t features);
|
||||
|
||||
ogs_pkbuf_t *ogs_gtp2_build_error_indication(
|
||||
ogs_pkbuf_t *ogs_gtp1_build_error_indication(
|
||||
uint32_t teid, ogs_sockaddr_t *addr);
|
||||
|
||||
void ogs_gtp2_fill_header(
|
||||
ogs_gtp2_header_t *gtp_hdesc, ogs_gtp2_extension_header_t *ext_hdesc,
|
||||
ogs_pkbuf_t *pkbuf);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (C) 2019 by Sukchan Lee <acetcom@gmail.com>
|
||||
* Copyright (C) 2019-2023 by Sukchan Lee <acetcom@gmail.com>
|
||||
*
|
||||
* This file is part of Open5GS.
|
||||
*
|
||||
|
@ -27,92 +27,11 @@ int ogs_gtp2_send_user_plane(
|
|||
char buf[OGS_ADDRSTRLEN];
|
||||
int rv;
|
||||
|
||||
ogs_gtp2_header_t *gtp_h = NULL;
|
||||
ogs_gtp2_extension_header_t *ext_h = NULL;
|
||||
uint8_t flags;
|
||||
uint8_t gtp_hlen = 0;
|
||||
|
||||
ogs_assert(gnode);
|
||||
ogs_assert(gtp_hdesc);
|
||||
ogs_assert(ext_hdesc);
|
||||
ogs_assert(pkbuf);
|
||||
|
||||
/* Processing GTP Flags */
|
||||
flags = gtp_hdesc->flags;
|
||||
flags |= OGS_GTPU_FLAGS_V | OGS_GTPU_FLAGS_PT;
|
||||
if (ext_hdesc->qos_flow_identifier) flags |= OGS_GTPU_FLAGS_E;
|
||||
|
||||
/* Define GTP Header Size */
|
||||
if (flags & OGS_GTPU_FLAGS_E)
|
||||
gtp_hlen = OGS_GTPV1U_HEADER_LEN+8;
|
||||
else if (flags & (OGS_GTPU_FLAGS_S|OGS_GTPU_FLAGS_PN))
|
||||
gtp_hlen = OGS_GTPV1U_HEADER_LEN+4;
|
||||
else
|
||||
gtp_hlen = OGS_GTPV1U_HEADER_LEN;
|
||||
|
||||
ogs_pkbuf_push(pkbuf, gtp_hlen);
|
||||
|
||||
/* Fill GTP Header */
|
||||
gtp_h = (ogs_gtp2_header_t *)pkbuf->data;
|
||||
ogs_assert(gtp_h);
|
||||
memset(gtp_h, 0, gtp_hlen);
|
||||
|
||||
gtp_h->flags = flags;
|
||||
gtp_h->type = gtp_hdesc->type;
|
||||
|
||||
if (gtp_h->type == OGS_GTPU_MSGTYPE_ECHO_REQ ||
|
||||
gtp_h->type == OGS_GTPU_MSGTYPE_ECHO_RSP ||
|
||||
gtp_h->type == OGS_GTPU_MSGTYPE_ERR_IND) {
|
||||
/*
|
||||
* TS29.281 5.1 General format in GTP-U header
|
||||
*
|
||||
* - The Echo Request/Response and Supported Extension Headers
|
||||
* notification messages, where the Tunnel Endpoint Identifier
|
||||
* shall be set to all zeroes.
|
||||
* - The Error Indication message where the Tunnel Endpoint Identifier
|
||||
* shall be set to all zeros.
|
||||
*/
|
||||
ogs_assert(gtp_hdesc->teid == 0);
|
||||
}
|
||||
|
||||
gtp_h->teid = htobe32(gtp_hdesc->teid);
|
||||
|
||||
/*
|
||||
* TS29.281 5.1 General format in GTP-U header
|
||||
*
|
||||
* Length: This field indicates the length in octets of the payload,
|
||||
* i.e. the rest of the packet following the mandatory part of
|
||||
* the GTP header (that is the first 8 octets). The Sequence Number,
|
||||
* the N-PDU Number or any Extension headers shall be considered
|
||||
* to be part of the payload, i.e. included in the length count.
|
||||
*/
|
||||
gtp_h->length = htobe16(pkbuf->len - OGS_GTPV1U_HEADER_LEN);
|
||||
|
||||
/* Fill Extention Header */
|
||||
if (gtp_h->flags & OGS_GTPU_FLAGS_E) {
|
||||
ext_h = (ogs_gtp2_extension_header_t *)
|
||||
(pkbuf->data + OGS_GTPV1U_HEADER_LEN);
|
||||
ogs_assert(ext_h);
|
||||
|
||||
if (ext_hdesc->qos_flow_identifier) {
|
||||
/* 5G Core */
|
||||
ext_h->type = OGS_GTP2_EXTENSION_HEADER_TYPE_PDU_SESSION_CONTAINER;
|
||||
ext_h->len = 1;
|
||||
ext_h->pdu_type = ext_hdesc->pdu_type;
|
||||
ext_h->qos_flow_identifier = ext_hdesc->qos_flow_identifier;
|
||||
ext_h->next_type =
|
||||
OGS_GTP2_EXTENSION_HEADER_TYPE_NO_MORE_EXTENSION_HEADERS;
|
||||
} else {
|
||||
/* EPC */
|
||||
ext_h->type = ext_hdesc->type;
|
||||
ext_h->len = 1;
|
||||
ext_h->next_type =
|
||||
OGS_GTP2_EXTENSION_HEADER_TYPE_NO_MORE_EXTENSION_HEADERS;
|
||||
}
|
||||
}
|
||||
ogs_gtp2_fill_header(gtp_hdesc, ext_hdesc, pkbuf);
|
||||
|
||||
ogs_trace("SEND GTP-U[%d] to Peer[%s] : TEID[0x%x]",
|
||||
gtp_hdesc->type, OGS_ADDR(&gnode->addr, buf), gtp_hdesc->teid);
|
||||
|
||||
rv = ogs_gtp_sendto(gnode, pkbuf);
|
||||
if (rv != OGS_OK) {
|
||||
if (ogs_socket_errno != OGS_EAGAIN) {
|
||||
|
@ -342,3 +261,39 @@ void ogs_gtp2_send_echo_response(ogs_gtp_xact_t *xact,
|
|||
rv = ogs_gtp_xact_commit(xact);
|
||||
ogs_expect(rv == OGS_OK);
|
||||
}
|
||||
|
||||
void ogs_gtp1_send_error_indication(
|
||||
ogs_sock_t *sock, uint32_t teid, uint8_t qfi, const ogs_sockaddr_t *to)
|
||||
{
|
||||
ssize_t sent;
|
||||
ogs_pkbuf_t *pkbuf = NULL;
|
||||
|
||||
ogs_gtp2_header_t gtp_hdesc;
|
||||
ogs_gtp2_extension_header_t ext_hdesc;
|
||||
|
||||
ogs_assert(sock);
|
||||
ogs_assert(to);
|
||||
|
||||
pkbuf = ogs_gtp1_build_error_indication(teid, &sock->local_addr);
|
||||
if (!pkbuf) {
|
||||
ogs_error("ogs_gtp1_build_error_indication() failed");
|
||||
return;
|
||||
}
|
||||
|
||||
memset(>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.
|
||||
*
|
||||
|
@ -44,6 +44,9 @@ void ogs_gtp2_send_echo_request(
|
|||
void ogs_gtp2_send_echo_response(ogs_gtp_xact_t *xact,
|
||||
uint8_t recovery, uint8_t features);
|
||||
|
||||
void ogs_gtp1_send_error_indication(
|
||||
ogs_sock_t *sock, uint32_t teid, uint8_t qfi, const ogs_sockaddr_t *to);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
ogs_pfcp_far_t *ogs_pfcp_far_find_by_error_indication(ogs_pkbuf_t *pkbuf)
|
||||
ogs_pfcp_far_t *ogs_pfcp_far_find_by_gtpu_error_indication(ogs_pkbuf_t *pkbuf)
|
||||
{
|
||||
ogs_pfcp_far_hash_f_teid_t hashkey;
|
||||
int hashkey_len;
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
ogs_pfcp_far_t *ogs_pfcp_far_find_by_pfcp_session_report(
|
||||
ogs_pfcp_sess_t *sess,
|
||||
ogs_pfcp_tlv_error_indication_report_t *error_indication_report)
|
||||
{
|
||||
ogs_pfcp_far_t *far = NULL;
|
||||
ogs_pfcp_f_teid_t *remote_f_teid = NULL;
|
||||
|
||||
uint32_t teid;
|
||||
uint16_t len; /* OGS_IPV4_LEN or OGS_IPV6_LEN */
|
||||
uint32_t addr[4];
|
||||
|
||||
ogs_assert(sess);
|
||||
ogs_assert(error_indication_report);
|
||||
|
||||
if (error_indication_report->presence == 0) {
|
||||
ogs_error("No Error Indication Report");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (error_indication_report->remote_f_teid.presence == 0) {
|
||||
ogs_error("No Remote F-TEID");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
remote_f_teid = error_indication_report->remote_f_teid.data;
|
||||
ogs_assert(remote_f_teid);
|
||||
|
||||
teid = be32toh(remote_f_teid->teid);
|
||||
if (remote_f_teid->ipv4 && remote_f_teid->ipv6) {
|
||||
ogs_error("User plane should not set both IPv4 and IPv6");
|
||||
return NULL;
|
||||
} else if (remote_f_teid->ipv4) {
|
||||
len = OGS_IPV4_LEN;
|
||||
memcpy(addr, &remote_f_teid->addr, len);
|
||||
} else if (remote_f_teid->ipv6) {
|
||||
len = OGS_IPV6_LEN;
|
||||
memcpy(addr, remote_f_teid->addr6, len);
|
||||
} else {
|
||||
ogs_error("No IPv4 and IPv6");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ogs_list_for_each(&sess->far_list, far) {
|
||||
if (teid == far->outer_header_creation.teid)
|
||||
return far;
|
||||
}
|
||||
|
||||
ogs_error("Cannot find the session context "
|
||||
"[TEID:0x%x,LEN:%d,ADDR:%08x %08x %08x %08x]",
|
||||
teid, len, be32toh(addr[0]), be32toh(addr[1]),
|
||||
be32toh(addr[2]), be32toh(addr[3]));
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void ogs_pfcp_far_teid_hash_set(ogs_pfcp_far_t *far)
|
||||
{
|
||||
ogs_assert(far);
|
||||
|
|
|
@ -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);
|
||||
|
||||
void ogs_pfcp_far_f_teid_hash_set(ogs_pfcp_far_t *far);
|
||||
ogs_pfcp_far_t *ogs_pfcp_far_find_by_error_indication(ogs_pkbuf_t *pkbuf);
|
||||
ogs_pfcp_far_t *ogs_pfcp_far_find_by_gtpu_error_indication(
|
||||
ogs_pkbuf_t *pkbuf);
|
||||
ogs_pfcp_far_t *ogs_pfcp_far_find_by_pfcp_session_report(
|
||||
ogs_pfcp_sess_t *sess,
|
||||
ogs_pfcp_tlv_error_indication_report_t *error_indication_report);
|
||||
|
||||
void ogs_pfcp_far_teid_hash_set(ogs_pfcp_far_t *far);
|
||||
ogs_pfcp_far_t *ogs_pfcp_far_find_by_teid(uint32_t teid);
|
||||
|
|
|
@ -610,71 +610,6 @@ sgwc_bearer_t *sgwc_bearer_find_by_ue_ebi(sgwc_ue_t *sgwc_ue, uint8_t ebi)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
sgwc_bearer_t *sgwc_bearer_find_by_error_indication_report(
|
||||
sgwc_sess_t *sess,
|
||||
ogs_pfcp_tlv_error_indication_report_t *error_indication_report)
|
||||
{
|
||||
ogs_pfcp_f_teid_t *remote_f_teid = NULL;
|
||||
sgwc_bearer_t *bearer = NULL;
|
||||
sgwc_tunnel_t *tunnel = NULL;
|
||||
|
||||
uint32_t teid;
|
||||
uint16_t len; /* OGS_IPV4_LEN or OGS_IPV6_LEN */
|
||||
uint32_t addr[4];
|
||||
|
||||
ogs_assert(sess);
|
||||
ogs_assert(error_indication_report);
|
||||
|
||||
if (error_indication_report->presence == 0) {
|
||||
ogs_error("No Error Indication Report");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (error_indication_report->remote_f_teid.presence == 0) {
|
||||
ogs_error("No Remote F-TEID");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
remote_f_teid = error_indication_report->remote_f_teid.data;
|
||||
ogs_assert(remote_f_teid);
|
||||
|
||||
teid = be32toh(remote_f_teid->teid);
|
||||
if (remote_f_teid->ipv4 && remote_f_teid->ipv6) {
|
||||
ogs_error("User plane should not set both IPv4 and IPv6");
|
||||
return NULL;
|
||||
} else if (remote_f_teid->ipv4) {
|
||||
len = OGS_IPV4_LEN;
|
||||
memcpy(addr, &remote_f_teid->addr, len);
|
||||
} else if (remote_f_teid->ipv6) {
|
||||
len = OGS_IPV6_LEN;
|
||||
memcpy(addr, remote_f_teid->addr6, len);
|
||||
} else {
|
||||
ogs_error("No IPv4 and IPv6");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ogs_list_for_each(&sess->bearer_list, bearer) {
|
||||
ogs_list_for_each(&bearer->tunnel_list, tunnel) {
|
||||
if (teid == tunnel->remote_teid) {
|
||||
if (len == OGS_IPV4_LEN && tunnel->remote_ip.ipv4 &&
|
||||
memcmp(addr, &tunnel->remote_ip.addr, len) == 0) {
|
||||
return bearer;
|
||||
} else if (len == OGS_IPV6_LEN && tunnel->remote_ip.ipv6 &&
|
||||
memcmp(addr, tunnel->remote_ip.addr6, len) == 0) {
|
||||
return bearer;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ogs_error("Cannot find the bearer context "
|
||||
"[TEID:%d,LEN:%d,ADDR:%08x %08x %08x %08x]",
|
||||
teid, len, be32toh(addr[0]), be32toh(addr[1]),
|
||||
be32toh(addr[2]), be32toh(addr[3]));
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
sgwc_bearer_t *sgwc_default_bearer_in_sess(sgwc_sess_t *sess)
|
||||
{
|
||||
ogs_assert(sess);
|
||||
|
@ -722,6 +657,7 @@ sgwc_tunnel_t *sgwc_tunnel_add(
|
|||
break;
|
||||
default:
|
||||
ogs_fatal("Invalid interface type = %d", interface_type);
|
||||
ogs_assert_if_reached();
|
||||
}
|
||||
|
||||
ogs_pool_alloc(&sgwc_tunnel_pool, &tunnel);
|
||||
|
@ -902,6 +838,28 @@ sgwc_tunnel_t *sgwc_tunnel_find_by_pdr_id(
|
|||
return NULL;
|
||||
}
|
||||
|
||||
sgwc_tunnel_t *sgwc_tunnel_find_by_far_id(
|
||||
sgwc_sess_t *sess, ogs_pfcp_far_id_t far_id)
|
||||
{
|
||||
sgwc_bearer_t *bearer = NULL;
|
||||
sgwc_tunnel_t *tunnel = NULL;
|
||||
|
||||
ogs_pfcp_far_t *far = NULL;
|
||||
|
||||
ogs_assert(sess);
|
||||
|
||||
ogs_list_for_each(&sess->bearer_list, bearer) {
|
||||
ogs_list_for_each(&bearer->tunnel_list, tunnel) {
|
||||
far = tunnel->far;
|
||||
ogs_assert(far);
|
||||
|
||||
if (far->id == far_id) return tunnel;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
sgwc_tunnel_t *sgwc_dl_tunnel_in_bearer(sgwc_bearer_t *bearer)
|
||||
{
|
||||
ogs_assert(bearer);
|
||||
|
|
|
@ -168,9 +168,6 @@ sgwc_bearer_t *sgwc_bearer_find_by_sess_ebi(
|
|||
sgwc_sess_t *sess, uint8_t ebi);
|
||||
sgwc_bearer_t *sgwc_bearer_find_by_ue_ebi(
|
||||
sgwc_ue_t *sgwc_ue, uint8_t ebi);
|
||||
sgwc_bearer_t *sgwc_bearer_find_by_error_indication_report(
|
||||
sgwc_sess_t *sess,
|
||||
ogs_pfcp_tlv_error_indication_report_t *error_indication_report);
|
||||
sgwc_bearer_t *sgwc_default_bearer_in_sess(sgwc_sess_t *sess);
|
||||
sgwc_bearer_t *sgwc_bearer_cycle(sgwc_bearer_t *bearer);
|
||||
|
||||
|
@ -183,6 +180,8 @@ sgwc_tunnel_t *sgwc_tunnel_find_by_interface_type(
|
|||
sgwc_bearer_t *bearer, uint8_t interface_type);
|
||||
sgwc_tunnel_t *sgwc_tunnel_find_by_pdr_id(
|
||||
sgwc_sess_t *sess, ogs_pfcp_pdr_id_t pdr_id);
|
||||
sgwc_tunnel_t *sgwc_tunnel_find_by_far_id(
|
||||
sgwc_sess_t *sess, ogs_pfcp_far_id_t far_id);
|
||||
sgwc_tunnel_t *sgwc_dl_tunnel_in_bearer(sgwc_bearer_t *bearer);
|
||||
sgwc_tunnel_t *sgwc_ul_tunnel_in_bearer(sgwc_bearer_t *bearer);
|
||||
|
||||
|
|
|
@ -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.
|
||||
*
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (C) 2019 by Sukchan Lee <acetcom@gmail.com>
|
||||
* Copyright (C) 2019-2023 by Sukchan Lee <acetcom@gmail.com>
|
||||
*
|
||||
* This file is part of Open5GS.
|
||||
*
|
||||
|
@ -1297,10 +1297,7 @@ void sgwc_sxa_handle_session_deletion_response(
|
|||
|
||||
ogs_pfcp_xact_commit(pfcp_xact);
|
||||
|
||||
if (!gtp_message) {
|
||||
ogs_error("No GTP Message");
|
||||
goto cleanup;
|
||||
}
|
||||
if (!gtp_message) goto cleanup;
|
||||
|
||||
if (gtp_message->h.type == OGS_GTP2_DELETE_SESSION_REQUEST_TYPE) {
|
||||
/*
|
||||
|
@ -1380,7 +1377,10 @@ void sgwc_sxa_handle_session_deletion_response(
|
|||
}
|
||||
|
||||
cleanup:
|
||||
sgwc_sess_remove(sess);
|
||||
if (sgwc_sess_cycle(sess))
|
||||
sgwc_sess_remove(sess);
|
||||
else
|
||||
ogs_error("Session has already been removed");
|
||||
}
|
||||
|
||||
void sgwc_sxa_handle_session_report_request(
|
||||
|
@ -1390,6 +1390,7 @@ void sgwc_sxa_handle_session_report_request(
|
|||
sgwc_ue_t *sgwc_ue = NULL;
|
||||
sgwc_bearer_t *bearer = NULL;
|
||||
sgwc_tunnel_t *tunnel = NULL;
|
||||
ogs_pfcp_far_t *far = NULL;
|
||||
|
||||
ogs_pfcp_report_type_t report_type;
|
||||
uint8_t cause_value = 0;
|
||||
|
@ -1470,22 +1471,44 @@ void sgwc_sxa_handle_session_report_request(
|
|||
ogs_error("Cannot find the PDR-ID[%d]", pdr_id);
|
||||
|
||||
} else if (report_type.error_indication_report) {
|
||||
bearer = sgwc_bearer_find_by_error_indication_report(
|
||||
sess, &pfcp_req->error_indication_report);
|
||||
|
||||
if (!bearer) return;
|
||||
|
||||
ogs_list_for_each(&sgwc_ue->sess_list, sess) {
|
||||
|
||||
ogs_assert(OGS_OK ==
|
||||
sgwc_pfcp_send_session_modification_request(sess,
|
||||
/* We only use the `assoc_xact` parameter temporarily here
|
||||
* to pass the `bearer` context. */
|
||||
(ogs_gtp_xact_t *)bearer,
|
||||
NULL,
|
||||
OGS_PFCP_MODIFY_DL_ONLY|OGS_PFCP_MODIFY_DEACTIVATE|
|
||||
OGS_PFCP_MODIFY_ERROR_INDICATION));
|
||||
}
|
||||
far = ogs_pfcp_far_find_by_pfcp_session_report(
|
||||
&sess->pfcp, &pfcp_req->error_indication_report);
|
||||
if (far) {
|
||||
tunnel = sgwc_tunnel_find_by_far_id(sess, far->id);
|
||||
ogs_assert(tunnel);
|
||||
bearer = tunnel->bearer;
|
||||
ogs_assert(bearer);
|
||||
if (far->dst_if == OGS_PFCP_INTERFACE_ACCESS) {
|
||||
ogs_warn("[%s] Error Indication from eNB", sgwc_ue->imsi_bcd);
|
||||
ogs_list_for_each(&sgwc_ue->sess_list, sess) {
|
||||
ogs_assert(OGS_OK ==
|
||||
sgwc_pfcp_send_session_modification_request(sess,
|
||||
/* We only use the `assoc_xact` parameter temporarily here
|
||||
* to pass the `bearer` context. */
|
||||
(ogs_gtp_xact_t *)bearer,
|
||||
NULL,
|
||||
OGS_PFCP_MODIFY_DL_ONLY|OGS_PFCP_MODIFY_DEACTIVATE|
|
||||
OGS_PFCP_MODIFY_ERROR_INDICATION));
|
||||
}
|
||||
} else if (far->dst_if == OGS_PFCP_INTERFACE_CORE) {
|
||||
if (sgwc_default_bearer_in_sess(sess) == bearer) {
|
||||
ogs_error("[%s] Error Indication(Default Bearer) from SMF",
|
||||
sgwc_ue->imsi_bcd);
|
||||
ogs_assert(OGS_OK ==
|
||||
sgwc_pfcp_send_session_deletion_request(
|
||||
sess, NULL, NULL));
|
||||
} else {
|
||||
ogs_error("[%s] Error Indication(Dedicated Bearer) "
|
||||
"from SMF", sgwc_ue->imsi_bcd);
|
||||
ogs_assert(OGS_OK ==
|
||||
sgwc_pfcp_send_bearer_modification_request(
|
||||
bearer, NULL, NULL, OGS_PFCP_MODIFY_REMOVE));
|
||||
}
|
||||
} else {
|
||||
ogs_error("Error Indication Ignored for Indirect Tunnel");
|
||||
}
|
||||
} else
|
||||
ogs_error("Cannot find Session in Error Indication");
|
||||
|
||||
} else {
|
||||
ogs_error("Not supported Report Type[%d]", report_type.value);
|
||||
|
|
|
@ -28,11 +28,13 @@ static void _gtpv1_u_recv_cb(short when, ogs_socket_t fd, void *data)
|
|||
{
|
||||
int len;
|
||||
ssize_t size;
|
||||
char buf[OGS_ADDRSTRLEN];
|
||||
char buf1[OGS_ADDRSTRLEN];
|
||||
char buf2[OGS_ADDRSTRLEN];
|
||||
|
||||
sgwu_sess_t *sess = NULL;
|
||||
|
||||
ogs_pkbuf_t *pkbuf = NULL;
|
||||
ogs_sock_t *sock = NULL;
|
||||
ogs_sockaddr_t from;
|
||||
|
||||
ogs_gtp2_header_t *gtp_h = NULL;
|
||||
|
@ -42,6 +44,8 @@ static void _gtpv1_u_recv_cb(short when, ogs_socket_t fd, void *data)
|
|||
uint8_t qfi;
|
||||
|
||||
ogs_assert(fd != INVALID_SOCKET);
|
||||
sock = data;
|
||||
ogs_assert(sock);
|
||||
|
||||
pkbuf = ogs_pkbuf_alloc(packet_pool, OGS_MAX_PKT_LEN);
|
||||
ogs_assert(pkbuf);
|
||||
|
@ -69,14 +73,14 @@ static void _gtpv1_u_recv_cb(short when, ogs_socket_t fd, void *data)
|
|||
if (gtp_h->type == OGS_GTPU_MSGTYPE_ECHO_REQ) {
|
||||
ogs_pkbuf_t *echo_rsp;
|
||||
|
||||
ogs_debug("[RECV] Echo Request from [%s]", OGS_ADDR(&from, buf));
|
||||
ogs_debug("[RECV] Echo Request from [%s]", OGS_ADDR(&from, buf1));
|
||||
echo_rsp = ogs_gtp2_handle_echo_req(pkbuf);
|
||||
ogs_expect(echo_rsp);
|
||||
if (echo_rsp) {
|
||||
ssize_t sent;
|
||||
|
||||
/* Echo reply */
|
||||
ogs_debug("[SEND] Echo Response to [%s]", OGS_ADDR(&from, buf));
|
||||
ogs_debug("[SEND] Echo Response to [%s]", OGS_ADDR(&from, buf1));
|
||||
|
||||
sent = ogs_sendto(fd, echo_rsp->data, echo_rsp->len, 0, &from);
|
||||
if (sent < 0 || sent != echo_rsp->len) {
|
||||
|
@ -91,7 +95,7 @@ static void _gtpv1_u_recv_cb(short when, ogs_socket_t fd, void *data)
|
|||
teid = be32toh(gtp_h->teid);
|
||||
|
||||
ogs_trace("[RECV] GPU-U Type [%d] from [%s] : TEID[0x%x]",
|
||||
gtp_h->type, OGS_ADDR(&from, buf), teid);
|
||||
gtp_h->type, OGS_ADDR(&from, buf1), teid);
|
||||
|
||||
qfi = 0;
|
||||
if (gtp_h->flags & OGS_GTPU_FLAGS_E) {
|
||||
|
@ -139,7 +143,27 @@ static void _gtpv1_u_recv_cb(short when, ogs_socket_t fd, void *data)
|
|||
|
||||
pfcp_object = ogs_pfcp_object_find_by_teid(teid);
|
||||
if (!pfcp_object) {
|
||||
/* TODO : Send Error Indication */
|
||||
/*
|
||||
* Refer to the following 5G standard
|
||||
*
|
||||
* TS23.527 Restoration procedures
|
||||
* 4.3 UPF Restoration Procedures
|
||||
* 4.3.2 Restoration Procedure for PSA UPF Restart
|
||||
*
|
||||
* The UPF shall not send GTP-U Error indication message
|
||||
* for a configurable period after an UPF restart
|
||||
* when the UPF receives a G-PDU not matching any PDRs.
|
||||
*/
|
||||
if (ogs_time_ntp32_now() >
|
||||
(ogs_pfcp_self()->local_recovery +
|
||||
ogs_time_sec(
|
||||
ogs_app()->time.message.pfcp.association_interval))) {
|
||||
ogs_error("[%s] Send Error Indication [TEID:0x%x] to [%s]",
|
||||
OGS_ADDR(&sock->local_addr, buf1),
|
||||
teid,
|
||||
OGS_ADDR(&from, buf2));
|
||||
ogs_gtp1_send_error_indication(sock, teid, 0, &from);
|
||||
}
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
|
@ -164,7 +188,7 @@ static void _gtpv1_u_recv_cb(short when, ogs_socket_t fd, void *data)
|
|||
} else if (gtp_h->type == OGS_GTPU_MSGTYPE_ERR_IND) {
|
||||
ogs_pfcp_far_t *far = NULL;
|
||||
|
||||
far = ogs_pfcp_far_find_by_error_indication(pkbuf);
|
||||
far = ogs_pfcp_far_find_by_gtpu_error_indication(pkbuf);
|
||||
if (far) {
|
||||
ogs_assert(true ==
|
||||
ogs_pfcp_up_handle_error_indication(far, &report));
|
||||
|
@ -177,7 +201,6 @@ static void _gtpv1_u_recv_cb(short when, ogs_socket_t fd, void *data)
|
|||
ogs_assert(OGS_OK ==
|
||||
sgwu_pfcp_send_session_report_request(sess, &report));
|
||||
}
|
||||
|
||||
} else {
|
||||
ogs_error("[DROP] Cannot find FAR by Error-Indication");
|
||||
ogs_log_hexdump(OGS_LOG_ERROR, pkbuf->data, pkbuf->len);
|
||||
|
@ -193,7 +216,27 @@ static void _gtpv1_u_recv_cb(short when, ogs_socket_t fd, void *data)
|
|||
|
||||
pfcp_object = ogs_pfcp_object_find_by_teid(teid);
|
||||
if (!pfcp_object) {
|
||||
/* TODO : Send Error Indication */
|
||||
/*
|
||||
* Refer to the following 5G standard
|
||||
*
|
||||
* TS23.527 Restoration procedures
|
||||
* 4.3 UPF Restoration Procedures
|
||||
* 4.3.2 Restoration Procedure for PSA UPF Restart
|
||||
*
|
||||
* The UPF shall not send GTP-U Error indication message
|
||||
* for a configurable period after an UPF restart
|
||||
* when the UPF receives a G-PDU not matching any PDRs.
|
||||
*/
|
||||
if (ogs_time_ntp32_now() >
|
||||
(ogs_pfcp_self()->local_recovery +
|
||||
ogs_time_sec(
|
||||
ogs_app()->time.message.pfcp.association_interval))) {
|
||||
ogs_error("[%s] Send Error Indication [TEID:0x%x] to [%s]",
|
||||
OGS_ADDR(&sock->local_addr, buf1),
|
||||
teid,
|
||||
OGS_ADDR(&from, buf2));
|
||||
ogs_gtp1_send_error_indication(sock, teid, 0, &from);
|
||||
}
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
|
|
|
@ -1641,68 +1641,6 @@ void smf_sess_set_paging_n1n2message_location(
|
|||
sess);
|
||||
}
|
||||
|
||||
smf_sess_t *smf_sess_find_by_error_indication_report(
|
||||
smf_ue_t *smf_ue,
|
||||
ogs_pfcp_tlv_error_indication_report_t *error_indication_report)
|
||||
{
|
||||
smf_sess_t *sess = NULL;
|
||||
ogs_pfcp_f_teid_t *remote_f_teid = NULL;
|
||||
|
||||
uint32_t teid;
|
||||
uint16_t len; /* OGS_IPV4_LEN or OGS_IPV6_LEN */
|
||||
uint32_t addr[4];
|
||||
|
||||
ogs_assert(smf_ue);
|
||||
ogs_assert(error_indication_report);
|
||||
|
||||
if (error_indication_report->presence == 0) {
|
||||
ogs_error("No Error Indication Report");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (error_indication_report->remote_f_teid.presence == 0) {
|
||||
ogs_error("No Remote F-TEID");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
remote_f_teid = error_indication_report->remote_f_teid.data;
|
||||
ogs_assert(remote_f_teid);
|
||||
|
||||
teid = be32toh(remote_f_teid->teid);
|
||||
if (remote_f_teid->ipv4 && remote_f_teid->ipv6) {
|
||||
ogs_error("User plane should not set both IPv4 and IPv6");
|
||||
return NULL;
|
||||
} else if (remote_f_teid->ipv4) {
|
||||
len = OGS_IPV4_LEN;
|
||||
memcpy(addr, &remote_f_teid->addr, len);
|
||||
} else if (remote_f_teid->ipv6) {
|
||||
len = OGS_IPV6_LEN;
|
||||
memcpy(addr, remote_f_teid->addr6, len);
|
||||
} else {
|
||||
ogs_error("No IPv4 and IPv6");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ogs_list_reverse_for_each(&smf_ue->sess_list, sess) {
|
||||
if (teid == sess->gnb_n3_teid) {
|
||||
if (len == OGS_IPV4_LEN && sess->gnb_n3_ip.ipv4 &&
|
||||
memcmp(addr, &sess->gnb_n3_ip.addr, len) == 0) {
|
||||
return sess;
|
||||
} else if (len == OGS_IPV6_LEN && sess->gnb_n3_ip.ipv6 &&
|
||||
memcmp(addr, sess->gnb_n3_ip.addr6, len) == 0) {
|
||||
return sess;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ogs_error("Cannot find the session context "
|
||||
"[TEID:%d,LEN:%d,ADDR:%08x %08x %08x %08x]",
|
||||
teid, len, be32toh(addr[0]), be32toh(addr[1]),
|
||||
be32toh(addr[2]), be32toh(addr[3]));
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void smf_sess_remove(smf_sess_t *sess)
|
||||
{
|
||||
int i;
|
||||
|
|
|
@ -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_paging_n1n2message_location(
|
||||
char *n1n2message_location);
|
||||
smf_sess_t *smf_sess_find_by_error_indication_report(
|
||||
smf_ue_t *smf_ue,
|
||||
ogs_pfcp_tlv_error_indication_report_t *error_indication_report);
|
||||
|
||||
void smf_sess_create_indirect_data_forwarding(smf_sess_t *sess);
|
||||
bool smf_sess_have_indirect_data_forwarding(smf_sess_t *sess);
|
||||
|
|
|
@ -851,6 +851,11 @@ void smf_gsm_state_operational(ogs_fsm_t *s, smf_event_t *e)
|
|||
}
|
||||
break;
|
||||
|
||||
case OGS_PFCP_SESSION_DELETION_RESPONSE_TYPE:
|
||||
ogs_error("Session Released by Error Indication");
|
||||
OGS_FSM_TRAN(s, smf_gsm_state_session_will_release);
|
||||
break;
|
||||
|
||||
default:
|
||||
ogs_error("cannot handle PFCP message type[%d]",
|
||||
pfcp_message->h.type);
|
||||
|
|
|
@ -1148,9 +1148,11 @@ void smf_n4_handle_session_report_request(
|
|||
smf_sess_t *sess, ogs_pfcp_xact_t *pfcp_xact,
|
||||
ogs_pfcp_session_report_request_t *pfcp_req)
|
||||
{
|
||||
smf_ue_t *smf_ue = NULL;
|
||||
smf_bearer_t *qos_flow = NULL;
|
||||
smf_bearer_t *bearer = NULL;
|
||||
ogs_pfcp_pdr_t *pdr = NULL;
|
||||
ogs_pfcp_far_t *far = NULL;
|
||||
|
||||
ogs_pfcp_report_type_t report_type;
|
||||
uint8_t cause_value = 0;
|
||||
|
@ -1184,6 +1186,9 @@ void smf_n4_handle_session_report_request(
|
|||
}
|
||||
|
||||
ogs_assert(sess);
|
||||
smf_ue = sess->smf_ue;
|
||||
ogs_assert(smf_ue);
|
||||
|
||||
report_type.value = pfcp_req->report_type.u8;
|
||||
|
||||
if (report_type.downlink_data_report) {
|
||||
|
@ -1270,21 +1275,10 @@ void smf_n4_handle_session_report_request(
|
|||
}
|
||||
|
||||
if (report_type.error_indication_report) {
|
||||
smf_ue_t *smf_ue = sess->smf_ue;
|
||||
smf_sess_t *error_indication_session = NULL;
|
||||
ogs_assert(smf_ue);
|
||||
|
||||
error_indication_session = smf_sess_find_by_error_indication_report(
|
||||
smf_ue, &pfcp_req->error_indication_report);
|
||||
|
||||
if (error_indication_session) {
|
||||
ogs_assert(OGS_OK ==
|
||||
smf_5gc_pfcp_send_all_pdr_modification_request(
|
||||
error_indication_session, NULL,
|
||||
OGS_PFCP_MODIFY_DL_ONLY|OGS_PFCP_MODIFY_DEACTIVATE|
|
||||
OGS_PFCP_MODIFY_ERROR_INDICATION,
|
||||
0));
|
||||
}
|
||||
far = ogs_pfcp_far_find_by_pfcp_session_report(
|
||||
&sess->pfcp, &pfcp_req->error_indication_report);
|
||||
if (!far)
|
||||
ogs_error("Cannot find Session in Error Indication");
|
||||
}
|
||||
|
||||
if (report_type.usage_report) {
|
||||
|
@ -1341,4 +1335,24 @@ void smf_n4_handle_session_report_request(
|
|||
smf_pfcp_send_session_report_response(
|
||||
pfcp_xact, sess, OGS_PFCP_CAUSE_SYSTEM_FAILURE));
|
||||
}
|
||||
|
||||
/* Error Indication is handled last */
|
||||
if (report_type.error_indication_report && far) {
|
||||
if (sess->epc == true) {
|
||||
ogs_error("[%s:%s] Error Indication from SGW-C",
|
||||
smf_ue->imsi_bcd, sess->session.name);
|
||||
ogs_assert(OGS_OK ==
|
||||
smf_epc_pfcp_send_session_deletion_request(
|
||||
sess, NULL));
|
||||
} else {
|
||||
ogs_warn("[%s:%s] Error Indication from gNB",
|
||||
smf_ue->supi, sess->session.name);
|
||||
ogs_assert(OGS_OK ==
|
||||
smf_5gc_pfcp_send_all_pdr_modification_request(
|
||||
sess, NULL,
|
||||
OGS_PFCP_MODIFY_DL_ONLY|OGS_PFCP_MODIFY_DEACTIVATE|
|
||||
OGS_PFCP_MODIFY_ERROR_INDICATION,
|
||||
0));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -258,11 +258,13 @@ static void _gtpv1_u_recv_cb(short when, ogs_socket_t fd, void *data)
|
|||
{
|
||||
int len;
|
||||
ssize_t size;
|
||||
char buf[OGS_ADDRSTRLEN];
|
||||
char buf1[OGS_ADDRSTRLEN];
|
||||
char buf2[OGS_ADDRSTRLEN];
|
||||
|
||||
upf_sess_t *sess = NULL;
|
||||
|
||||
ogs_pkbuf_t *pkbuf = NULL;
|
||||
ogs_sock_t *sock = NULL;
|
||||
ogs_sockaddr_t from;
|
||||
|
||||
ogs_gtp2_header_t *gtp_h = NULL;
|
||||
|
@ -272,6 +274,8 @@ static void _gtpv1_u_recv_cb(short when, ogs_socket_t fd, void *data)
|
|||
uint8_t qfi;
|
||||
|
||||
ogs_assert(fd != INVALID_SOCKET);
|
||||
sock = data;
|
||||
ogs_assert(sock);
|
||||
|
||||
pkbuf = ogs_pkbuf_alloc(packet_pool, OGS_MAX_PKT_LEN);
|
||||
ogs_assert(pkbuf);
|
||||
|
@ -300,14 +304,14 @@ static void _gtpv1_u_recv_cb(short when, ogs_socket_t fd, void *data)
|
|||
if (gtp_h->type == OGS_GTPU_MSGTYPE_ECHO_REQ) {
|
||||
ogs_pkbuf_t *echo_rsp;
|
||||
|
||||
ogs_debug("[RECV] Echo Request from [%s]", OGS_ADDR(&from, buf));
|
||||
ogs_debug("[RECV] Echo Request from [%s]", OGS_ADDR(&from, buf1));
|
||||
echo_rsp = ogs_gtp2_handle_echo_req(pkbuf);
|
||||
ogs_expect(echo_rsp);
|
||||
if (echo_rsp) {
|
||||
ssize_t sent;
|
||||
|
||||
/* Echo reply */
|
||||
ogs_debug("[SEND] Echo Response to [%s]", OGS_ADDR(&from, buf));
|
||||
ogs_debug("[SEND] Echo Response to [%s]", OGS_ADDR(&from, buf1));
|
||||
|
||||
sent = ogs_sendto(fd, echo_rsp->data, echo_rsp->len, 0, &from);
|
||||
if (sent < 0 || sent != echo_rsp->len) {
|
||||
|
@ -322,7 +326,7 @@ static void _gtpv1_u_recv_cb(short when, ogs_socket_t fd, void *data)
|
|||
teid = be32toh(gtp_h->teid);
|
||||
|
||||
ogs_trace("[RECV] GPU-U Type [%d] from [%s] : TEID[0x%x]",
|
||||
gtp_h->type, OGS_ADDR(&from, buf), teid);
|
||||
gtp_h->type, OGS_ADDR(&from, buf1), teid);
|
||||
|
||||
qfi = 0;
|
||||
if (gtp_h->flags & OGS_GTPU_FLAGS_E) {
|
||||
|
@ -369,7 +373,7 @@ static void _gtpv1_u_recv_cb(short when, ogs_socket_t fd, void *data)
|
|||
} else if (gtp_h->type == OGS_GTPU_MSGTYPE_ERR_IND) {
|
||||
ogs_pfcp_far_t *far = NULL;
|
||||
|
||||
far = ogs_pfcp_far_find_by_error_indication(pkbuf);
|
||||
far = ogs_pfcp_far_find_by_gtpu_error_indication(pkbuf);
|
||||
if (far) {
|
||||
ogs_assert(true ==
|
||||
ogs_pfcp_up_handle_error_indication(far, &report));
|
||||
|
@ -419,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);
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -458,7 +480,26 @@ static void _gtpv1_u_recv_cb(short when, ogs_socket_t fd, void *data)
|
|||
}
|
||||
|
||||
if (!pdr) {
|
||||
/* TODO : Send Error Indication */
|
||||
/*
|
||||
* TS23.527 Restoration procedures
|
||||
* 4.3 UPF Restoration Procedures
|
||||
* 4.3.2 Restoration Procedure for PSA UPF Restart
|
||||
*
|
||||
* The UPF shall not send GTP-U Error indication message
|
||||
* for a configurable period after an UPF restart
|
||||
* when the UPF receives a G-PDU not matching any PDRs.
|
||||
*/
|
||||
if (ogs_time_ntp32_now() >
|
||||
(ogs_pfcp_self()->local_recovery +
|
||||
ogs_time_sec(
|
||||
ogs_app()->time.message.pfcp.association_interval))) {
|
||||
ogs_error(
|
||||
"[%s] Send Error Indication [TEID:0x%x] to [%s]",
|
||||
OGS_ADDR(&sock->local_addr, buf1),
|
||||
teid,
|
||||
OGS_ADDR(&from, buf2));
|
||||
ogs_gtp1_send_error_indication(sock, teid, qfi, &from);
|
||||
}
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
|
|
|
@ -499,7 +499,7 @@ int test_gtpu_send_error_indication(
|
|||
ogs_assert_if_reached();
|
||||
}
|
||||
|
||||
pkbuf = ogs_gtp2_build_error_indication(teid, node->addr);
|
||||
pkbuf = ogs_gtp1_build_error_indication(teid, node->addr);
|
||||
ogs_assert(pkbuf);
|
||||
|
||||
memset(>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);
|
||||
ABTS_INT_EQUAL(tc, OGS_OK, rv);
|
||||
|
||||
/* Waiting for N4 */
|
||||
ogs_msleep(100);
|
||||
|
||||
/* Receive End Mark */
|
||||
recvbuf = test_gtpu_read(gtpu1);
|
||||
ABTS_PTR_NOTNULL(tc, recvbuf);
|
||||
|
@ -926,9 +923,6 @@ static void direct_complete_func(abts_case *tc, void *data)
|
|||
rv = testgnb_ngap_send(ngap1, sendbuf);
|
||||
ABTS_INT_EQUAL(tc, OGS_OK, rv);
|
||||
|
||||
/* Waiting for N4 */
|
||||
ogs_msleep(100);
|
||||
|
||||
/* Receive End Mark */
|
||||
recvbuf = test_gtpu_read(gtpu2);
|
||||
ABTS_PTR_NOTNULL(tc, recvbuf);
|
||||
|
@ -1844,9 +1838,6 @@ static void indirect_complete_func(abts_case *tc, void *data)
|
|||
rv = testgnb_ngap_send(ngap2, sendbuf);
|
||||
ABTS_INT_EQUAL(tc, OGS_OK, rv);
|
||||
|
||||
/* Waiting for N4 */
|
||||
ogs_msleep(100);
|
||||
|
||||
/* Receive End Mark */
|
||||
recvbuf = test_gtpu_read(gtpu1);
|
||||
ABTS_PTR_NOTNULL(tc, recvbuf);
|
||||
|
@ -1916,6 +1907,9 @@ static void indirect_complete_func(abts_case *tc, void *data)
|
|||
ABTS_PTR_NOTNULL(tc, recvbuf);
|
||||
ogs_pkbuf_free(recvbuf);
|
||||
|
||||
/* Waiting for removing Indirect Data Forwarding */
|
||||
ogs_msleep(100);
|
||||
|
||||
/* Send HandoverRequired */
|
||||
sendbuf = testngap_build_handover_required(
|
||||
test_ue, NGAP_HandoverType_intra5gs,
|
||||
|
@ -1992,9 +1986,6 @@ static void indirect_complete_func(abts_case *tc, void *data)
|
|||
rv = testgnb_ngap_send(ngap1, sendbuf);
|
||||
ABTS_INT_EQUAL(tc, OGS_OK, rv);
|
||||
|
||||
/* Waiting for N4 */
|
||||
ogs_msleep(100);
|
||||
|
||||
/* Receive End Mark */
|
||||
recvbuf = test_gtpu_read(gtpu2);
|
||||
ABTS_PTR_NOTNULL(tc, recvbuf);
|
||||
|
@ -2500,9 +2491,6 @@ static void indirect_cancel_func(abts_case *tc, void *data)
|
|||
rv = testgnb_ngap_send(ngap2, sendbuf);
|
||||
ABTS_INT_EQUAL(tc, OGS_OK, rv);
|
||||
|
||||
/* Waiting for N4 */
|
||||
ogs_msleep(100);
|
||||
|
||||
/* Receive End Mark */
|
||||
recvbuf = test_gtpu_read(gtpu1);
|
||||
ABTS_PTR_NOTNULL(tc, recvbuf);
|
||||
|
|
Loading…
Reference in New Issue