2020-04-26 19:36:05 +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-04-26 19:36:05 +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 "event.h"
|
|
|
|
#include "context.h"
|
|
|
|
#include "gtp-path.h"
|
|
|
|
#include "fd-path.h"
|
|
|
|
#include "s5c-build.h"
|
|
|
|
#include "s5c-handler.h"
|
|
|
|
#include "pfcp-path.h"
|
|
|
|
|
|
|
|
#include "ipfw/ipfw2.h"
|
|
|
|
|
2022-05-15 14:35:41 +00:00
|
|
|
static void pfcp_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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-04-26 19:36:05 +00:00
|
|
|
void smf_s5c_handle_echo_request(
|
2022-04-12 22:07:39 +00:00
|
|
|
ogs_gtp_xact_t *xact, ogs_gtp2_echo_request_t *req)
|
2020-04-26 19:36:05 +00:00
|
|
|
{
|
|
|
|
ogs_assert(xact);
|
|
|
|
ogs_assert(req);
|
|
|
|
|
|
|
|
ogs_debug("[PGW] Receiving Echo Request");
|
|
|
|
/* FIXME : Before implementing recovery counter correctly,
|
|
|
|
* I'll re-use the recovery value in request message */
|
2022-04-12 22:07:39 +00:00
|
|
|
ogs_gtp2_send_echo_response(xact, req->recovery.u8, 0);
|
2020-04-26 19:36:05 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void smf_s5c_handle_echo_response(
|
2022-04-12 22:07:39 +00:00
|
|
|
ogs_gtp_xact_t *xact, ogs_gtp2_echo_response_t *req)
|
2020-04-26 19:36:05 +00:00
|
|
|
{
|
|
|
|
/* Not Implemented */
|
|
|
|
}
|
|
|
|
|
2022-04-14 01:30:58 +00:00
|
|
|
uint8_t smf_s5c_handle_create_session_request(
|
2020-04-26 19:36:05 +00:00
|
|
|
smf_sess_t *sess, ogs_gtp_xact_t *xact,
|
2022-04-12 22:07:39 +00:00
|
|
|
ogs_gtp2_create_session_request_t *req)
|
2020-04-26 19:36:05 +00:00
|
|
|
{
|
2020-07-20 01:42:58 +00:00
|
|
|
char buf1[OGS_ADDRSTRLEN];
|
|
|
|
char buf2[OGS_ADDRSTRLEN];
|
|
|
|
|
2022-05-12 13:52:36 +00:00
|
|
|
int i, rv;
|
2020-04-26 19:36:05 +00:00
|
|
|
uint8_t cause_value = 0;
|
2020-07-20 01:42:58 +00:00
|
|
|
|
2022-04-12 22:07:39 +00:00
|
|
|
ogs_gtp2_uli_t uli;
|
2020-07-20 01:42:58 +00:00
|
|
|
|
|
|
|
smf_ue_t *smf_ue = NULL;
|
|
|
|
|
2022-04-12 22:07:39 +00:00
|
|
|
ogs_gtp2_f_teid_t *sgw_s5c_teid, *sgw_s5u_teid;
|
2021-06-21 13:36:38 +00:00
|
|
|
ogs_paa_t *paa = NULL;
|
2020-04-26 19:36:05 +00:00
|
|
|
smf_bearer_t *bearer = NULL;
|
2022-04-12 22:07:39 +00:00
|
|
|
ogs_gtp2_bearer_qos_t bearer_qos;
|
|
|
|
ogs_gtp2_ambr_t *ambr = NULL;
|
2020-04-26 19:36:05 +00:00
|
|
|
uint16_t decoded = 0;
|
|
|
|
|
2022-04-14 01:30:58 +00:00
|
|
|
ogs_assert(sess);
|
2020-04-26 19:36:05 +00:00
|
|
|
ogs_assert(xact);
|
|
|
|
ogs_assert(req);
|
|
|
|
|
2022-02-02 14:23:12 +00:00
|
|
|
ogs_debug("Create Session Request");
|
2020-04-26 19:36:05 +00:00
|
|
|
|
2022-04-12 22:07:39 +00:00
|
|
|
cause_value = OGS_GTP2_CAUSE_REQUEST_ACCEPTED;
|
2020-04-26 19:36:05 +00:00
|
|
|
|
|
|
|
if (req->imsi.presence == 0) {
|
|
|
|
ogs_error("No IMSI");
|
2022-04-14 08:34:55 +00:00
|
|
|
cause_value = OGS_GTP2_CAUSE_CONDITIONAL_IE_MISSING;
|
2020-04-26 19:36:05 +00:00
|
|
|
}
|
|
|
|
if (req->sender_f_teid_for_control_plane.presence == 0) {
|
|
|
|
ogs_error("No TEID");
|
2022-04-12 22:07:39 +00:00
|
|
|
cause_value = OGS_GTP2_CAUSE_MANDATORY_IE_MISSING;
|
2020-04-26 19:36:05 +00:00
|
|
|
}
|
2022-05-12 13:52:36 +00:00
|
|
|
if (req->bearer_contexts_to_be_created[0].presence == 0) {
|
2020-04-26 19:36:05 +00:00
|
|
|
ogs_error("No Bearer");
|
2022-04-12 22:07:39 +00:00
|
|
|
cause_value = OGS_GTP2_CAUSE_MANDATORY_IE_MISSING;
|
2020-04-26 19:36:05 +00:00
|
|
|
}
|
2022-05-12 13:52:36 +00:00
|
|
|
if (req->bearer_contexts_to_be_created[0].eps_bearer_id.presence == 0) {
|
2020-07-20 01:42:58 +00:00
|
|
|
ogs_error("No EPS Bearer ID");
|
2022-04-12 22:07:39 +00:00
|
|
|
cause_value = OGS_GTP2_CAUSE_MANDATORY_IE_MISSING;
|
2020-07-20 01:42:58 +00:00
|
|
|
}
|
2022-05-12 13:52:36 +00:00
|
|
|
if (req->bearer_contexts_to_be_created[0].bearer_level_qos.presence == 0) {
|
2020-04-26 19:36:05 +00:00
|
|
|
ogs_error("No EPS Bearer QoS");
|
2022-04-12 22:07:39 +00:00
|
|
|
cause_value = OGS_GTP2_CAUSE_MANDATORY_IE_MISSING;
|
2020-04-26 19:36:05 +00:00
|
|
|
}
|
2020-07-20 01:42:58 +00:00
|
|
|
if (req->pdn_address_allocation.presence == 0) {
|
|
|
|
ogs_error("No PAA");
|
2022-04-14 08:34:55 +00:00
|
|
|
cause_value = OGS_GTP2_CAUSE_CONDITIONAL_IE_MISSING;
|
2020-07-20 01:42:58 +00:00
|
|
|
}
|
2021-06-21 13:36:38 +00:00
|
|
|
if (req->serving_network.presence == 0) {
|
|
|
|
ogs_error("No Serving Network");
|
2022-04-14 08:34:55 +00:00
|
|
|
cause_value = OGS_GTP2_CAUSE_CONDITIONAL_IE_MISSING;
|
2021-06-21 13:36:38 +00:00
|
|
|
}
|
|
|
|
if (req->serving_network.data == NULL) {
|
|
|
|
ogs_error("No Data in Serving Network");
|
2022-04-14 08:34:55 +00:00
|
|
|
cause_value = OGS_GTP2_CAUSE_CONDITIONAL_IE_MISSING;
|
2021-06-21 13:36:38 +00:00
|
|
|
}
|
|
|
|
if (req->serving_network.len != OGS_PLMN_ID_LEN) {
|
|
|
|
ogs_error("Invalid Len[%d] in Serving Network",
|
|
|
|
req->serving_network.len);
|
2022-04-14 08:34:55 +00:00
|
|
|
cause_value = OGS_GTP2_CAUSE_CONDITIONAL_IE_MISSING;
|
2021-06-21 13:36:38 +00:00
|
|
|
}
|
|
|
|
|
2022-04-14 01:30:58 +00:00
|
|
|
if (!ogs_diam_app_connected(OGS_DIAM_GX_APPLICATION_ID)) {
|
|
|
|
ogs_error("No Gx Diameter Peer");
|
|
|
|
cause_value = OGS_GTP2_CAUSE_REMOTE_PEER_NOT_RESPONDING;
|
|
|
|
}
|
|
|
|
switch (sess->gtp_rat_type) {
|
|
|
|
case OGS_GTP2_RAT_TYPE_EUTRAN:
|
2022-05-12 13:52:36 +00:00
|
|
|
if (req->bearer_contexts_to_be_created[0].
|
2022-04-14 01:30:58 +00:00
|
|
|
s5_s8_u_sgw_f_teid.presence == 0) {
|
|
|
|
ogs_error("No S5/S8 SGW GTP-U TEID");
|
|
|
|
cause_value = OGS_GTP2_CAUSE_MANDATORY_IE_MISSING;
|
|
|
|
}
|
|
|
|
if (req->user_location_information.presence == 0) {
|
|
|
|
ogs_error("No UE Location Information");
|
|
|
|
cause_value = OGS_GTP2_CAUSE_MANDATORY_IE_MISSING;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case OGS_GTP2_RAT_TYPE_WLAN:
|
|
|
|
if (!ogs_diam_app_connected(OGS_DIAM_S6B_APPLICATION_ID)) {
|
|
|
|
ogs_error("No S6b Diameter Peer");
|
2022-04-12 22:07:39 +00:00
|
|
|
cause_value = OGS_GTP2_CAUSE_REMOTE_PEER_NOT_RESPONDING;
|
2021-06-21 13:36:38 +00:00
|
|
|
}
|
2022-05-12 13:52:36 +00:00
|
|
|
if (req->bearer_contexts_to_be_created[0].
|
2022-04-14 01:30:58 +00:00
|
|
|
s2b_u_epdg_f_teid_5.presence == 0) {
|
|
|
|
ogs_error("No S2b ePDG GTP-U TEID");
|
2022-04-12 22:07:39 +00:00
|
|
|
cause_value = OGS_GTP2_CAUSE_MANDATORY_IE_MISSING;
|
2021-06-21 13:36:38 +00:00
|
|
|
}
|
2022-04-14 01:30:58 +00:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
ogs_error("Unknown RAT Type [%d]", req->rat_type.u8);
|
|
|
|
cause_value = OGS_GTP2_CAUSE_MANDATORY_IE_MISSING;
|
2020-04-26 19:36:05 +00:00
|
|
|
}
|
|
|
|
|
2022-04-14 01:30:58 +00:00
|
|
|
if (cause_value != OGS_GTP2_CAUSE_REQUEST_ACCEPTED)
|
|
|
|
return cause_value;
|
2020-07-20 01:42:58 +00:00
|
|
|
|
|
|
|
smf_ue = sess->smf_ue;
|
|
|
|
ogs_assert(smf_ue);
|
|
|
|
|
2022-05-03 20:37:44 +00:00
|
|
|
/* Set MSISDN: */
|
|
|
|
/* TS 29.274 sec 8.11, TS 29.002 ISDN-AddressString */
|
2022-05-10 12:23:03 +00:00
|
|
|
if (req->msisdn.presence == 1) {
|
|
|
|
if (req->msisdn.len > sizeof(smf_ue->msisdn)) {
|
|
|
|
ogs_error("MSISDN wrong size %u > %zu",
|
|
|
|
req->msisdn.len, sizeof(smf_ue->msisdn));
|
|
|
|
return OGS_GTP2_CAUSE_MANDATORY_IE_INCORRECT;
|
|
|
|
}
|
|
|
|
smf_ue->msisdn_len = req->msisdn.len;
|
|
|
|
if (smf_ue->msisdn_len > 0) {
|
|
|
|
memcpy(smf_ue->msisdn, req->msisdn.data, smf_ue->msisdn_len);
|
|
|
|
ogs_buffer_to_bcd(
|
|
|
|
smf_ue->msisdn, smf_ue->msisdn_len, smf_ue->msisdn_bcd);
|
|
|
|
}
|
2022-05-03 20:37:44 +00:00
|
|
|
}
|
|
|
|
|
2022-05-12 13:43:12 +00:00
|
|
|
/* Set Selection Mode, TS 29.274 8.58 */
|
|
|
|
if (req->selection_mode.presence == 1) {
|
|
|
|
sess->gtp.selection_mode = req->selection_mode.u8 & 0x03;
|
|
|
|
if (sess->gtp.selection_mode > 2)
|
|
|
|
sess->gtp.selection_mode = 2;
|
|
|
|
}
|
|
|
|
|
2022-04-12 22:07:39 +00:00
|
|
|
if (sess->gtp_rat_type == OGS_GTP2_RAT_TYPE_EUTRAN) {
|
2021-08-27 02:40:58 +00:00
|
|
|
/* User Location Inforation is mandatory only for E-UTRAN */
|
|
|
|
ogs_assert(req->user_location_information.presence);
|
2022-04-12 22:07:39 +00:00
|
|
|
ogs_gtp2_parse_uli(&uli, &req->user_location_information);
|
2021-08-27 02:40:58 +00:00
|
|
|
memcpy(&sess->e_tai, &uli.tai, sizeof(sess->e_tai));
|
|
|
|
memcpy(&sess->e_cgi, &uli.e_cgi, sizeof(sess->e_cgi));
|
|
|
|
|
2022-04-12 22:07:39 +00:00
|
|
|
} else if (sess->gtp_rat_type == OGS_GTP2_RAT_TYPE_WLAN) {
|
2021-08-27 02:40:58 +00:00
|
|
|
/* Even after handover to WLAN,
|
|
|
|
* there must be at least one EUTRAN session */
|
2021-06-21 13:36:38 +00:00
|
|
|
smf_sess_t *eutran_sess = smf_sess_find_by_apn(
|
2022-04-12 22:07:39 +00:00
|
|
|
smf_ue, sess->session.name, OGS_GTP2_RAT_TYPE_EUTRAN);
|
2021-06-21 13:36:38 +00:00
|
|
|
if (eutran_sess) {
|
|
|
|
/* Need to check handover is possible */
|
|
|
|
int eutran_session_count = 0;
|
2022-05-17 12:44:52 +00:00
|
|
|
ogs_list_reverse_for_each(&smf_ue->sess_list, eutran_sess) {
|
2022-04-12 22:07:39 +00:00
|
|
|
if (eutran_sess->gtp_rat_type != OGS_GTP2_RAT_TYPE_EUTRAN)
|
2021-06-21 13:36:38 +00:00
|
|
|
continue;
|
|
|
|
if (strcmp(eutran_sess->session.name, sess->session.name) == 0)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
eutran_session_count++;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (eutran_session_count < 1) {
|
|
|
|
ogs_error("Cannot handover to WLAN");
|
2022-04-14 01:30:58 +00:00
|
|
|
return OGS_GTP2_CAUSE_MULTIPLE_ACCESSES_TO_A_PDN_CONNECTION_NOT_ALLOWED;
|
2021-06-21 13:36:38 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Serving Network */
|
2023-11-19 10:34:51 +00:00
|
|
|
ogs_nas_to_plmn_id(&sess->serving_plmn_id, req->serving_network.data);
|
2021-06-21 13:36:38 +00:00
|
|
|
|
2020-08-29 14:53:02 +00:00
|
|
|
/* Select PGW based on UE Location Information */
|
2020-07-20 01:42:58 +00:00
|
|
|
smf_sess_select_upf(sess);
|
|
|
|
|
2020-08-29 14:53:02 +00:00
|
|
|
/* Check if selected PGW is associated with SMF */
|
2020-07-20 01:42:58 +00:00
|
|
|
ogs_assert(sess->pfcp_node);
|
2022-04-14 01:30:58 +00:00
|
|
|
if (!OGS_FSM_CHECK(&sess->pfcp_node->sm, smf_pfcp_state_associated))
|
|
|
|
return OGS_GTP2_CAUSE_REMOTE_PEER_NOT_RESPONDING;
|
2020-07-20 01:42:58 +00:00
|
|
|
|
|
|
|
/* UE IP Address */
|
2021-06-21 13:36:38 +00:00
|
|
|
paa = req->pdn_address_allocation.data;
|
|
|
|
ogs_assert(paa);
|
2022-02-23 11:16:04 +00:00
|
|
|
|
|
|
|
/* Store UE Session Type (IPv4, IPv6, IPv4v6) */
|
|
|
|
sess->ue_session_type = paa->session_type;
|
|
|
|
|
|
|
|
/* Initially Set Session Type from UE */
|
|
|
|
sess->session.session_type = sess->ue_session_type;
|
2024-01-05 19:16:29 +00:00
|
|
|
rv = ogs_paa_to_ip(paa, &sess->session.ue_ip);
|
2021-06-06 13:35:46 +00:00
|
|
|
ogs_assert(rv == OGS_OK);
|
2020-07-20 01:42:58 +00:00
|
|
|
|
2023-10-05 09:28:40 +00:00
|
|
|
/* Set UE IP Address */
|
|
|
|
rv = smf_sess_set_ue_ip(sess);
|
|
|
|
if (rv != OGS_PFCP_CAUSE_REQUEST_ACCEPTED) {
|
|
|
|
/* only two possibilities are:
|
|
|
|
* OGS_PFCP_CAUSE_ALL_DYNAMIC_ADDRESS_ARE_OCCUPIED
|
|
|
|
* OGS_PFCP_CAUSE_NO_RESOURCES_AVAILABLE
|
|
|
|
*/
|
|
|
|
ogs_error("Failed to set UE IP Address");
|
|
|
|
switch(rv) {
|
|
|
|
case OGS_PFCP_CAUSE_ALL_DYNAMIC_ADDRESS_ARE_OCCUPIED:
|
|
|
|
cause_value = OGS_GTP2_CAUSE_ALL_DYNAMIC_ADDRESSES_ARE_OCCUPIED;
|
|
|
|
break;
|
|
|
|
case OGS_PFCP_CAUSE_NO_RESOURCES_AVAILABLE:
|
|
|
|
cause_value = OGS_GTP2_CAUSE_NO_RESOURCES_AVAILABLE;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
cause_value = OGS_GTP2_CAUSE_REQUEST_REJECTED_REASON_NOT_SPECIFIED;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return cause_value;
|
|
|
|
}
|
2020-07-20 01:42:58 +00:00
|
|
|
|
2021-01-23 03:17:01 +00:00
|
|
|
ogs_info("UE IMSI[%s] APN[%s] IPv4[%s] IPv6[%s]",
|
2022-09-02 14:38:39 +00:00
|
|
|
smf_ue->imsi_bcd,
|
|
|
|
sess->session.name,
|
2020-07-20 01:42:58 +00:00
|
|
|
sess->ipv4 ? OGS_INET_NTOP(&sess->ipv4->addr, buf1) : "",
|
|
|
|
sess->ipv6 ? OGS_INET6_NTOP(&sess->ipv6->addr, buf2) : "");
|
|
|
|
|
2020-04-26 19:36:05 +00:00
|
|
|
/* Control Plane(DL) : SGW-S5C */
|
|
|
|
sgw_s5c_teid = req->sender_f_teid_for_control_plane.data;
|
|
|
|
ogs_assert(sgw_s5c_teid);
|
|
|
|
sess->sgw_s5c_teid = be32toh(sgw_s5c_teid->teid);
|
2022-04-12 22:07:39 +00:00
|
|
|
rv = ogs_gtp2_f_teid_to_ip(sgw_s5c_teid, &sess->sgw_s5c_ip);
|
2020-04-26 19:36:05 +00:00
|
|
|
ogs_assert(rv == OGS_OK);
|
|
|
|
|
|
|
|
ogs_debug(" SGW_S5C_TEID[0x%x] SMF_N4_TEID[0x%x]",
|
|
|
|
sess->sgw_s5c_teid, sess->smf_n4_teid);
|
2021-06-21 13:36:38 +00:00
|
|
|
|
2022-04-29 12:28:16 +00:00
|
|
|
/* Remove all previous bearer */
|
|
|
|
smf_bearer_remove_all(sess);
|
|
|
|
|
2022-05-12 13:52:36 +00:00
|
|
|
/* Setup Bearer */
|
|
|
|
for (i = 0; i < OGS_BEARER_PER_UE; i++) {
|
|
|
|
if (req->bearer_contexts_to_be_created[i].presence == 0)
|
|
|
|
break;
|
|
|
|
if (req->bearer_contexts_to_be_created[i].eps_bearer_id.presence == 0) {
|
|
|
|
ogs_error("No EPS Bearer ID");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (req->bearer_contexts_to_be_created[i].
|
|
|
|
bearer_level_qos.presence == 0) {
|
|
|
|
ogs_error("No Bearer QoS");
|
|
|
|
break;
|
|
|
|
}
|
2022-04-29 12:28:16 +00:00
|
|
|
|
2022-05-12 13:52:36 +00:00
|
|
|
decoded = ogs_gtp2_parse_bearer_qos(&bearer_qos,
|
|
|
|
&req->bearer_contexts_to_be_created[i].bearer_level_qos);
|
|
|
|
ogs_assert(decoded ==
|
|
|
|
req->bearer_contexts_to_be_created[i].bearer_level_qos.len);
|
|
|
|
|
|
|
|
bearer = smf_bearer_add(sess);
|
|
|
|
ogs_assert(bearer);
|
|
|
|
|
|
|
|
/* Set Bearer EBI */
|
|
|
|
bearer->ebi = req->bearer_contexts_to_be_created[i].eps_bearer_id.u8;
|
|
|
|
|
|
|
|
switch (sess->gtp_rat_type) {
|
|
|
|
case OGS_GTP2_RAT_TYPE_EUTRAN:
|
|
|
|
sgw_s5u_teid = req->bearer_contexts_to_be_created[i].
|
|
|
|
s5_s8_u_sgw_f_teid.data;
|
|
|
|
ogs_assert(sgw_s5u_teid);
|
|
|
|
bearer->sgw_s5u_teid = be32toh(sgw_s5u_teid->teid);
|
|
|
|
rv = ogs_gtp2_f_teid_to_ip(sgw_s5u_teid, &bearer->sgw_s5u_ip);
|
|
|
|
ogs_assert(rv == OGS_OK);
|
|
|
|
|
|
|
|
break;
|
|
|
|
case OGS_GTP2_RAT_TYPE_WLAN:
|
|
|
|
sgw_s5u_teid = req->bearer_contexts_to_be_created[i].
|
|
|
|
s2b_u_epdg_f_teid_5.data;
|
|
|
|
ogs_assert(sgw_s5u_teid);
|
|
|
|
bearer->sgw_s5u_teid = be32toh(sgw_s5u_teid->teid);
|
|
|
|
rv = ogs_gtp2_f_teid_to_ip(sgw_s5u_teid, &bearer->sgw_s5u_ip);
|
|
|
|
ogs_assert(rv == OGS_OK);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
ogs_error("Unknown RAT Type [%d]", sess->gtp_rat_type);
|
|
|
|
ogs_assert_if_reached();
|
|
|
|
}
|
2021-08-27 02:40:58 +00:00
|
|
|
|
2022-05-12 13:52:36 +00:00
|
|
|
ogs_debug(" SGW_S5U_TEID[0x%x] PGW_S5U_TEID[0x%x]",
|
|
|
|
bearer->sgw_s5u_teid, bearer->pgw_s5u_teid);
|
|
|
|
|
|
|
|
/* Set Session QoS from Default Bearer Level QoS */
|
|
|
|
if (i == 0) {
|
|
|
|
sess->session.qos.index = bearer_qos.qci;
|
|
|
|
sess->session.qos.arp.priority_level = bearer_qos.priority_level;
|
|
|
|
sess->session.qos.arp.pre_emption_capability =
|
|
|
|
bearer_qos.pre_emption_capability;
|
|
|
|
sess->session.qos.arp.pre_emption_vulnerability =
|
|
|
|
bearer_qos.pre_emption_vulnerability;
|
|
|
|
}
|
2021-06-21 13:36:38 +00:00
|
|
|
}
|
|
|
|
|
2020-04-26 19:36:05 +00:00
|
|
|
/* Set AMBR if available */
|
|
|
|
if (req->aggregate_maximum_bit_rate.presence) {
|
|
|
|
/*
|
|
|
|
* Ch 8.7. Aggregate Maximum Bit Rate(AMBR) in TS 29.274 V15.9.0
|
|
|
|
*
|
|
|
|
* AMBR is defined in clause 9.9.4.2 of 3GPP TS 24.301 [23],
|
|
|
|
* but it shall be encoded as shown in Figure 8.7-1 as
|
|
|
|
* Unsigned32 binary integer values in kbps (1000 bits per second).
|
|
|
|
*/
|
|
|
|
ambr = req->aggregate_maximum_bit_rate.data;
|
2021-03-08 12:25:09 +00:00
|
|
|
sess->session.ambr.downlink = be32toh(ambr->downlink) * 1000;
|
|
|
|
sess->session.ambr.uplink = be32toh(ambr->uplink) * 1000;
|
2020-04-26 19:36:05 +00:00
|
|
|
}
|
|
|
|
|
2023-04-21 15:04:11 +00:00
|
|
|
/* ePCO */
|
|
|
|
if (req->extended_protocol_configuration_options.presence) {
|
|
|
|
OGS_TLV_STORE_DATA(&sess->gtp.ue_epco,
|
|
|
|
&req->extended_protocol_configuration_options);
|
|
|
|
|
2020-04-26 19:36:05 +00:00
|
|
|
/* PCO */
|
2023-04-21 15:04:11 +00:00
|
|
|
} else if (req->protocol_configuration_options.presence) {
|
2020-06-23 04:35:41 +00:00
|
|
|
OGS_TLV_STORE_DATA(&sess->gtp.ue_pco,
|
|
|
|
&req->protocol_configuration_options);
|
2020-04-26 19:36:05 +00:00
|
|
|
}
|
|
|
|
|
2024-02-26 14:49:54 +00:00
|
|
|
/* APCO */
|
|
|
|
if (req->additional_protocol_configuration_options.presence) {
|
|
|
|
OGS_TLV_STORE_DATA(&sess->gtp.ue_apco,
|
|
|
|
&req->additional_protocol_configuration_options);
|
|
|
|
}
|
|
|
|
|
2020-04-26 19:36:05 +00:00
|
|
|
/* Set User Location Information */
|
|
|
|
if (req->user_location_information.presence) {
|
2020-06-23 04:35:41 +00:00
|
|
|
OGS_TLV_STORE_DATA(&sess->gtp.user_location_information,
|
2020-04-26 19:36:05 +00:00
|
|
|
&req->user_location_information);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Set UE Timezone */
|
|
|
|
if (req->ue_time_zone.presence) {
|
2020-06-23 04:35:41 +00:00
|
|
|
OGS_TLV_STORE_DATA(&sess->gtp.ue_timezone, &req->ue_time_zone);
|
2020-04-26 19:36:05 +00:00
|
|
|
}
|
2020-07-20 01:42:58 +00:00
|
|
|
|
2022-05-12 21:32:20 +00:00
|
|
|
if (req->charging_characteristics.presence) {
|
|
|
|
OGS_TLV_STORE_DATA(&sess->gtp.charging_characteristics, &req->charging_characteristics);
|
|
|
|
}
|
|
|
|
|
2022-05-12 13:52:36 +00:00
|
|
|
/* Set MSISDN */
|
|
|
|
if (req->msisdn.presence && req->msisdn.len && req->msisdn.data) {
|
|
|
|
smf_ue->msisdn_len = req->msisdn.len;
|
|
|
|
memcpy(smf_ue->msisdn, req->msisdn.data,
|
|
|
|
ogs_min(smf_ue->msisdn_len, OGS_MAX_MSISDN_LEN));
|
|
|
|
ogs_buffer_to_bcd(smf_ue->msisdn,
|
|
|
|
smf_ue->msisdn_len, smf_ue->msisdn_bcd);
|
|
|
|
}
|
|
|
|
|
2022-05-14 12:32:32 +00:00
|
|
|
/* Set IMEI(SV) */
|
|
|
|
if (req->me_identity.presence && req->me_identity.len > 0) {
|
|
|
|
smf_ue->imeisv_len = req->me_identity.len;
|
|
|
|
memcpy(smf_ue->imeisv,
|
|
|
|
(uint8_t*)req->me_identity.data, smf_ue->imeisv_len);
|
|
|
|
ogs_buffer_to_bcd(
|
|
|
|
smf_ue->imeisv, smf_ue->imeisv_len, smf_ue->imeisv_bcd);
|
|
|
|
}
|
|
|
|
|
2022-04-14 01:30:58 +00:00
|
|
|
return OGS_GTP2_CAUSE_REQUEST_ACCEPTED;
|
2020-04-26 19:36:05 +00:00
|
|
|
}
|
|
|
|
|
2022-04-20 12:42:18 +00:00
|
|
|
uint8_t smf_s5c_handle_delete_session_request(
|
2020-04-26 19:36:05 +00:00
|
|
|
smf_sess_t *sess, ogs_gtp_xact_t *xact,
|
2022-04-12 22:07:39 +00:00
|
|
|
ogs_gtp2_delete_session_request_t *req)
|
2020-04-26 19:36:05 +00:00
|
|
|
{
|
2020-11-07 22:27:12 +00:00
|
|
|
ogs_debug("Delete Session Request");
|
2020-04-26 19:36:05 +00:00
|
|
|
|
|
|
|
ogs_assert(xact);
|
|
|
|
ogs_assert(req);
|
|
|
|
|
2022-04-20 12:42:18 +00:00
|
|
|
if (!ogs_diam_app_connected(OGS_DIAM_GX_APPLICATION_ID)) {
|
|
|
|
ogs_error("No Gx Diameter Peer");
|
|
|
|
return OGS_GTP2_CAUSE_REMOTE_PEER_NOT_RESPONDING;
|
2020-04-26 19:36:05 +00:00
|
|
|
}
|
|
|
|
|
2022-04-20 12:42:18 +00:00
|
|
|
if (sess->gtp_rat_type == OGS_GTP2_RAT_TYPE_WLAN) {
|
|
|
|
if (!ogs_diam_app_connected(OGS_DIAM_S6B_APPLICATION_ID)) {
|
|
|
|
ogs_error("No S6b Diameter Peer");
|
|
|
|
return OGS_GTP2_CAUSE_REMOTE_PEER_NOT_RESPONDING;
|
|
|
|
}
|
2020-04-26 19:36:05 +00:00
|
|
|
}
|
|
|
|
|
2022-08-12 11:48:54 +00:00
|
|
|
/* PCO
|
|
|
|
* 3GPP TS 29.274 version 10.5.0, Table 7.2.9.1-1
|
|
|
|
* If the UE includes the PCO IE, then the MME/SGSN shall copy
|
|
|
|
* the content of this IE transparently from the PCO IE included by the UE.
|
|
|
|
* If SGW receives the PCO IE, SGW shall forward it to PGW.
|
|
|
|
*/
|
|
|
|
if (req->protocol_configuration_options.presence) {
|
|
|
|
OGS_TLV_STORE_DATA(&sess->gtp.ue_pco,
|
|
|
|
&req->protocol_configuration_options);
|
|
|
|
} else {
|
2023-04-21 15:04:11 +00:00
|
|
|
/*
|
2022-08-12 11:48:54 +00:00
|
|
|
* Clear contents to reflect whether PCO IE was included or not as part
|
|
|
|
* of session deletion procedure
|
|
|
|
*/
|
|
|
|
OGS_TLV_CLEAR_DATA(&sess->gtp.ue_pco);
|
|
|
|
}
|
|
|
|
|
2024-02-26 14:49:54 +00:00
|
|
|
/* APCO not present in Session deletion procedure, hence no need to clear it here. */
|
|
|
|
|
2023-04-21 15:04:11 +00:00
|
|
|
if (req->extended_protocol_configuration_options.presence) {
|
|
|
|
OGS_TLV_STORE_DATA(&sess->gtp.ue_epco,
|
|
|
|
&req->extended_protocol_configuration_options);
|
|
|
|
} else {
|
|
|
|
/*
|
|
|
|
* Clear contents to reflect whether PCO IE was included or not as part
|
|
|
|
* of session deletion procedure
|
|
|
|
*/
|
|
|
|
OGS_TLV_CLEAR_DATA(&sess->gtp.ue_epco);
|
|
|
|
}
|
|
|
|
|
2020-04-26 19:36:05 +00:00
|
|
|
ogs_debug(" SGW_S5C_TEID[0x%x] SMF_N4_TEID[0x%x]",
|
|
|
|
sess->sgw_s5c_teid, sess->smf_n4_teid);
|
|
|
|
|
2022-04-20 12:42:18 +00:00
|
|
|
return OGS_GTP2_CAUSE_REQUEST_ACCEPTED;
|
2021-06-21 13:36:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void smf_s5c_handle_modify_bearer_request(
|
2022-05-15 14:35:41 +00:00
|
|
|
smf_sess_t *sess, ogs_gtp_xact_t *gtp_xact,
|
2022-05-12 13:52:36 +00:00
|
|
|
ogs_pkbuf_t *gtpbuf, ogs_gtp2_modify_bearer_request_t *req)
|
2021-06-21 13:36:38 +00:00
|
|
|
{
|
2022-05-12 13:52:36 +00:00
|
|
|
int rv, i;
|
2021-06-21 13:36:38 +00:00
|
|
|
uint8_t cause_value = 0;
|
2022-05-12 13:52:36 +00:00
|
|
|
uint64_t flags = 0;
|
2021-06-21 13:36:38 +00:00
|
|
|
|
|
|
|
smf_ue_t *smf_ue = NULL;
|
2022-05-12 13:52:36 +00:00
|
|
|
smf_bearer_t *bearer = NULL;
|
2021-06-21 13:36:38 +00:00
|
|
|
|
|
|
|
ogs_debug("Modify Bearer Request");
|
|
|
|
|
2022-05-15 14:35:41 +00:00
|
|
|
ogs_assert(gtp_xact);
|
2021-06-21 13:36:38 +00:00
|
|
|
ogs_assert(req);
|
|
|
|
|
2022-04-29 12:28:16 +00:00
|
|
|
/************************
|
|
|
|
* Check Session Context
|
|
|
|
************************/
|
2022-04-12 22:07:39 +00:00
|
|
|
cause_value = OGS_GTP2_CAUSE_REQUEST_ACCEPTED;
|
2021-06-21 13:36:38 +00:00
|
|
|
|
|
|
|
if (!sess) {
|
2022-04-29 12:28:16 +00:00
|
|
|
ogs_error("No Context");
|
2022-04-12 22:07:39 +00:00
|
|
|
cause_value = OGS_GTP2_CAUSE_CONTEXT_NOT_FOUND;
|
2021-06-21 13:36:38 +00:00
|
|
|
}
|
|
|
|
|
2022-04-12 22:07:39 +00:00
|
|
|
if (cause_value != OGS_GTP2_CAUSE_REQUEST_ACCEPTED) {
|
[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
|
|
|
ogs_gtp2_send_error_message(gtp_xact,
|
|
|
|
sess ? OGS_GTP2_TEID_PRESENCE : OGS_GTP2_TEID_NO_PRESENCE,
|
|
|
|
sess ? sess->sgw_s5c_teid : 0,
|
2022-04-12 22:07:39 +00:00
|
|
|
OGS_GTP2_MODIFY_BEARER_RESPONSE_TYPE, cause_value);
|
2021-06-21 13:36:38 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2022-04-29 12:28:16 +00:00
|
|
|
/********************
|
|
|
|
* Check ALL Context
|
|
|
|
********************/
|
2021-06-21 13:36:38 +00:00
|
|
|
ogs_assert(sess);
|
|
|
|
smf_ue = sess->smf_ue;
|
|
|
|
ogs_assert(smf_ue);
|
|
|
|
|
2022-04-29 12:28:16 +00:00
|
|
|
/* Control Plane(DL) : SGW-S5C */
|
|
|
|
if (req->sender_f_teid_for_control_plane.presence == 1) {
|
|
|
|
ogs_gtp2_f_teid_t *sgw_s5c_teid =
|
|
|
|
req->sender_f_teid_for_control_plane.data;
|
|
|
|
ogs_assert(sgw_s5c_teid);
|
|
|
|
sess->sgw_s5c_teid = be32toh(sgw_s5c_teid->teid);
|
|
|
|
rv = ogs_gtp2_f_teid_to_ip(sgw_s5c_teid, &sess->sgw_s5c_ip);
|
|
|
|
ogs_assert(rv == OGS_OK);
|
2021-06-21 13:36:38 +00:00
|
|
|
|
2022-05-15 14:35:41 +00:00
|
|
|
OGS_SETUP_GTP_NODE(sess, gtp_xact->gnode);
|
2022-05-12 13:52:36 +00:00
|
|
|
|
2022-04-29 12:28:16 +00:00
|
|
|
ogs_debug(" SGW_S5C_TEID[0x%x] SMF_N4_TEID[0x%x]",
|
|
|
|
sess->sgw_s5c_teid, sess->smf_n4_teid);
|
|
|
|
}
|
|
|
|
|
2022-05-12 13:52:36 +00:00
|
|
|
/* Check Modify Bearer */
|
|
|
|
ogs_list_init(&sess->qos_flow_to_modify_list);
|
2022-04-29 12:28:16 +00:00
|
|
|
|
2022-05-12 13:52:36 +00:00
|
|
|
for (i = 0; i < OGS_BEARER_PER_UE; i++) {
|
|
|
|
if (req->bearer_contexts_to_be_modified[i].presence == 0)
|
|
|
|
break;
|
|
|
|
if (req->bearer_contexts_to_be_modified[i].
|
|
|
|
eps_bearer_id.presence == 0) {
|
|
|
|
ogs_error("No EPS Bearer ID");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
/* EPS Bearer ID */
|
|
|
|
bearer = smf_bearer_find_by_ebi(sess,
|
|
|
|
req->bearer_contexts_to_be_modified[i].eps_bearer_id.u8);
|
|
|
|
if (!bearer) {
|
|
|
|
ogs_error("No Bearer Context");
|
|
|
|
break;
|
|
|
|
}
|
2022-04-29 12:28:16 +00:00
|
|
|
|
2022-05-12 13:52:36 +00:00
|
|
|
if (req->bearer_contexts_to_be_modified[i].s4_u_sgsn_f_teid.presence) {
|
|
|
|
ogs_pfcp_far_t *far = NULL;
|
|
|
|
ogs_gtp2_f_teid_t *sgw_s5u_teid = NULL;
|
|
|
|
|
|
|
|
ogs_ip_t remote_ip;
|
|
|
|
ogs_ip_t zero_ip;
|
|
|
|
|
|
|
|
/* Data Plane(DL) : SGW-S5U */
|
|
|
|
sgw_s5u_teid = req->bearer_contexts_to_be_modified[i].
|
|
|
|
s4_u_sgsn_f_teid.data;
|
|
|
|
ogs_assert(sgw_s5u_teid);
|
|
|
|
bearer->sgw_s5u_teid = be32toh(sgw_s5u_teid->teid);
|
|
|
|
ogs_assert(OGS_OK ==
|
|
|
|
ogs_gtp2_f_teid_to_ip(sgw_s5u_teid, &remote_ip));
|
|
|
|
|
|
|
|
memset(&zero_ip, 0, sizeof(ogs_ip_t));
|
|
|
|
if (memcmp(&bearer->sgw_s5u_ip, &zero_ip, sizeof(ogs_ip_t)) != 0 &&
|
|
|
|
memcmp(&bearer->sgw_s5u_ip,
|
|
|
|
&remote_ip, sizeof(ogs_ip_t)) != 0) {
|
|
|
|
|
|
|
|
ogs_assert(sess->pfcp_node);
|
|
|
|
|
|
|
|
/* eNB IP is changed during handover */
|
|
|
|
if (sess->pfcp_node->up_function_features.empu) {
|
|
|
|
flags |= OGS_PFCP_MODIFY_END_MARKER;
|
|
|
|
} else {
|
|
|
|
ogs_error("UPF does not support End Marker");
|
|
|
|
}
|
|
|
|
}
|
2022-02-23 11:21:33 +00:00
|
|
|
|
2022-05-12 13:52:36 +00:00
|
|
|
memcpy(&bearer->sgw_s5u_ip, &remote_ip, sizeof(ogs_ip_t));
|
2021-06-21 13:36:38 +00:00
|
|
|
|
2022-05-12 13:52:36 +00:00
|
|
|
far = bearer->dl_far;
|
|
|
|
ogs_assert(far);
|
2021-06-21 13:36:38 +00:00
|
|
|
|
2022-05-12 13:52:36 +00:00
|
|
|
far->apply_action = OGS_PFCP_APPLY_ACTION_FORW;
|
2021-06-21 13:36:38 +00:00
|
|
|
|
2022-05-12 13:52:36 +00:00
|
|
|
ogs_assert(OGS_OK ==
|
|
|
|
ogs_pfcp_ip_to_outer_header_creation(
|
|
|
|
&bearer->sgw_s5u_ip,
|
|
|
|
&far->outer_header_creation,
|
|
|
|
&far->outer_header_creation_len));
|
|
|
|
far->outer_header_creation.teid = bearer->sgw_s5u_teid;
|
2021-06-21 13:36:38 +00:00
|
|
|
|
2022-05-12 13:52:36 +00:00
|
|
|
ogs_list_add(&sess->qos_flow_to_modify_list,
|
|
|
|
&bearer->to_modify_node);
|
|
|
|
|
|
|
|
ogs_debug(" SGW_S5U_TEID[0x%x] PGW_S5U_TEID[0x%x]",
|
|
|
|
bearer->sgw_s5u_teid, bearer->pgw_s5u_teid);
|
|
|
|
}
|
2021-06-21 13:36:38 +00:00
|
|
|
}
|
|
|
|
|
2022-05-12 13:52:36 +00:00
|
|
|
if (ogs_list_count(&sess->qos_flow_to_modify_list)) {
|
2022-05-15 14:35:41 +00:00
|
|
|
ogs_pfcp_xact_t *pfcp_xact = NULL;
|
2021-06-21 13:36:38 +00:00
|
|
|
|
2022-05-12 13:52:36 +00:00
|
|
|
/* Need to modify SGW-S5U */
|
2022-05-15 14:35:41 +00:00
|
|
|
pfcp_xact = ogs_pfcp_xact_local_create(
|
|
|
|
sess->pfcp_node, pfcp_sess_timeout, sess);
|
|
|
|
ogs_assert(pfcp_xact);
|
|
|
|
|
|
|
|
pfcp_xact->epc = true; /* EPC PFCP transaction */
|
|
|
|
pfcp_xact->assoc_xact = gtp_xact;
|
|
|
|
pfcp_xact->modify_flags =
|
|
|
|
flags|OGS_PFCP_MODIFY_DL_ONLY|OGS_PFCP_MODIFY_ACTIVATE;
|
|
|
|
|
|
|
|
pfcp_xact->gtp_pti = OGS_NAS_PROCEDURE_TRANSACTION_IDENTITY_UNASSIGNED;
|
|
|
|
pfcp_xact->gtp_cause = OGS_GTP2_CAUSE_UNDEFINED_VALUE;
|
2022-06-30 01:35:03 +00:00
|
|
|
pfcp_xact->local_seid = sess->smf_n4_seid;
|
2022-05-15 14:35:41 +00:00
|
|
|
|
|
|
|
ogs_assert(gtpbuf);
|
|
|
|
pfcp_xact->gtpbuf = ogs_pkbuf_copy(gtpbuf);
|
|
|
|
ogs_assert(pfcp_xact->gtpbuf);
|
|
|
|
|
|
|
|
ogs_assert(OGS_OK == smf_pfcp_send_modify_list(
|
|
|
|
sess, smf_n4_build_qos_flow_to_modify_list, pfcp_xact, 0));
|
2022-05-12 13:52:36 +00:00
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
/* Check if Handover from Non-3GPP to 3GPP */
|
|
|
|
ogs_gtp2_indication_t *indication = NULL;
|
|
|
|
|
|
|
|
ogs_assert(OGS_OK ==
|
2022-05-15 14:35:41 +00:00
|
|
|
smf_gtp2_send_modify_bearer_response(sess, gtp_xact, req, false));
|
2022-05-12 13:52:36 +00:00
|
|
|
|
|
|
|
if (req->indication_flags.presence &&
|
|
|
|
req->indication_flags.data && req->indication_flags.len) {
|
|
|
|
indication = req->indication_flags.data;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (indication && indication->handover_indication) {
|
|
|
|
ogs_assert(OGS_OK == smf_epc_pfcp_send_deactivation(sess,
|
|
|
|
OGS_GTP2_CAUSE_ACCESS_CHANGED_FROM_NON_3GPP_TO_3GPP));
|
|
|
|
}
|
2021-06-21 13:36:38 +00:00
|
|
|
}
|
2020-04-26 19:36:05 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void smf_s5c_handle_create_bearer_response(
|
|
|
|
smf_sess_t *sess, ogs_gtp_xact_t *xact,
|
2022-04-12 22:07:39 +00:00
|
|
|
ogs_gtp2_create_bearer_response_t *rsp)
|
2020-04-26 19:36:05 +00:00
|
|
|
{
|
|
|
|
int rv;
|
2020-11-07 22:27:12 +00:00
|
|
|
uint8_t cause_value;
|
2022-04-29 12:28:16 +00:00
|
|
|
ogs_gtp2_cause_t *cause = NULL;
|
2022-06-20 13:36:51 +00:00
|
|
|
ogs_gtp2_f_teid_t *sgw_s5u_teid = NULL, *pgw_s5u_teid = NULL;
|
2020-04-26 19:36:05 +00:00
|
|
|
smf_bearer_t *bearer = NULL;
|
2020-08-29 14:53:02 +00:00
|
|
|
ogs_pfcp_far_t *dl_far = NULL;
|
2020-04-26 19:36:05 +00:00
|
|
|
|
2022-07-16 04:27:18 +00:00
|
|
|
ogs_assert(sess);
|
2020-04-26 19:36:05 +00:00
|
|
|
ogs_assert(rsp);
|
|
|
|
|
2022-04-29 12:28:16 +00:00
|
|
|
ogs_debug("Create Bearer Response");
|
|
|
|
|
|
|
|
/********************
|
|
|
|
* Check Transaction
|
|
|
|
********************/
|
|
|
|
ogs_assert(xact);
|
2021-11-23 05:19:30 +00:00
|
|
|
bearer = xact->data;
|
|
|
|
ogs_assert(bearer);
|
|
|
|
|
2022-04-29 12:28:16 +00:00
|
|
|
rv = ogs_gtp_xact_commit(xact);
|
|
|
|
ogs_expect(rv == OGS_OK);
|
2020-11-07 22:27:12 +00:00
|
|
|
|
2022-04-29 12:28:16 +00:00
|
|
|
/************************
|
|
|
|
* Check Session Context
|
|
|
|
************************/
|
2022-04-12 22:07:39 +00:00
|
|
|
cause_value = OGS_GTP2_CAUSE_REQUEST_ACCEPTED;
|
2020-04-26 19:36:05 +00:00
|
|
|
|
2022-04-29 12:28:16 +00:00
|
|
|
if (cause_value != OGS_GTP2_CAUSE_REQUEST_ACCEPTED) {
|
|
|
|
ogs_assert(OGS_OK ==
|
2022-05-18 01:29:58 +00:00
|
|
|
smf_epc_pfcp_send_one_bearer_modification_request(
|
2022-04-29 12:28:16 +00:00
|
|
|
bearer, NULL, OGS_PFCP_MODIFY_REMOVE,
|
|
|
|
OGS_NAS_PROCEDURE_TRANSACTION_IDENTITY_UNASSIGNED,
|
|
|
|
OGS_GTP2_CAUSE_UNDEFINED_VALUE));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*****************************************
|
|
|
|
* Check Mandatory/Conditional IE Missing
|
|
|
|
*****************************************/
|
|
|
|
ogs_assert(cause_value == OGS_GTP2_CAUSE_REQUEST_ACCEPTED);
|
2020-04-26 19:36:05 +00:00
|
|
|
|
|
|
|
if (rsp->bearer_contexts.presence == 0) {
|
|
|
|
ogs_error("No Bearer");
|
2022-04-12 22:07:39 +00:00
|
|
|
cause_value = OGS_GTP2_CAUSE_MANDATORY_IE_MISSING;
|
2020-04-26 19:36:05 +00:00
|
|
|
}
|
|
|
|
if (rsp->bearer_contexts.eps_bearer_id.presence == 0) {
|
|
|
|
ogs_error("No EPS Bearer ID");
|
2022-04-12 22:07:39 +00:00
|
|
|
cause_value = OGS_GTP2_CAUSE_MANDATORY_IE_MISSING;
|
2020-04-26 19:36:05 +00:00
|
|
|
}
|
2021-06-21 13:36:38 +00:00
|
|
|
|
|
|
|
if (rsp->bearer_contexts.s5_s8_u_pgw_f_teid.presence &&
|
|
|
|
rsp->bearer_contexts.s5_s8_u_sgw_f_teid.presence) {
|
|
|
|
if (rsp->bearer_contexts.s5_s8_u_pgw_f_teid.presence)
|
|
|
|
pgw_s5u_teid = rsp->bearer_contexts.s5_s8_u_pgw_f_teid.data;
|
|
|
|
if (rsp->bearer_contexts.s5_s8_u_sgw_f_teid.presence)
|
|
|
|
sgw_s5u_teid = rsp->bearer_contexts.s5_s8_u_sgw_f_teid.data;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (rsp->bearer_contexts.s2b_u_pgw_f_teid.presence &&
|
|
|
|
rsp->bearer_contexts.s2b_u_epdg_f_teid_8.presence) {
|
|
|
|
if (rsp->bearer_contexts.s2b_u_pgw_f_teid.presence)
|
|
|
|
pgw_s5u_teid = rsp->bearer_contexts.s2b_u_pgw_f_teid.data;
|
|
|
|
if (rsp->bearer_contexts.s2b_u_epdg_f_teid_8.presence)
|
|
|
|
sgw_s5u_teid = rsp->bearer_contexts.s2b_u_epdg_f_teid_8.data;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!pgw_s5u_teid) {
|
|
|
|
ogs_error("No PGW TEID");
|
2022-04-29 12:28:16 +00:00
|
|
|
cause_value = OGS_GTP2_CAUSE_CONDITIONAL_IE_MISSING;
|
2020-04-26 19:36:05 +00:00
|
|
|
}
|
2021-06-21 13:36:38 +00:00
|
|
|
if (!sgw_s5u_teid) {
|
2020-04-26 19:36:05 +00:00
|
|
|
ogs_error("No SGW TEID");
|
2022-04-29 12:28:16 +00:00
|
|
|
cause_value = OGS_GTP2_CAUSE_CONDITIONAL_IE_MISSING;
|
2020-11-07 22:27:12 +00:00
|
|
|
}
|
|
|
|
|
2022-04-29 12:28:16 +00:00
|
|
|
if (rsp->cause.presence == 0) {
|
|
|
|
ogs_error("No Cause");
|
|
|
|
cause_value = OGS_GTP2_CAUSE_MANDATORY_IE_MISSING;
|
|
|
|
}
|
|
|
|
if (rsp->bearer_contexts.cause.presence == 0) {
|
|
|
|
ogs_error("No Bearer Cause");
|
|
|
|
cause_value = OGS_GTP2_CAUSE_MANDATORY_IE_MISSING;
|
2020-11-07 22:27:12 +00:00
|
|
|
}
|
|
|
|
|
2022-04-29 12:28:16 +00:00
|
|
|
if (cause_value != OGS_GTP2_CAUSE_REQUEST_ACCEPTED) {
|
|
|
|
ogs_assert(OGS_OK ==
|
2022-05-18 01:29:58 +00:00
|
|
|
smf_epc_pfcp_send_one_bearer_modification_request(
|
2022-04-29 12:28:16 +00:00
|
|
|
bearer, NULL, OGS_PFCP_MODIFY_REMOVE,
|
|
|
|
OGS_NAS_PROCEDURE_TRANSACTION_IDENTITY_UNASSIGNED,
|
|
|
|
OGS_GTP2_CAUSE_UNDEFINED_VALUE));
|
|
|
|
return;
|
|
|
|
}
|
2020-11-07 22:27:12 +00:00
|
|
|
|
2022-04-29 12:28:16 +00:00
|
|
|
/********************
|
|
|
|
* Check Cause Value
|
|
|
|
********************/
|
|
|
|
ogs_assert(cause_value == OGS_GTP2_CAUSE_REQUEST_ACCEPTED);
|
2020-11-07 22:27:12 +00:00
|
|
|
|
2022-04-29 12:28:16 +00:00
|
|
|
cause = rsp->bearer_contexts.cause.data;
|
|
|
|
ogs_assert(cause);
|
|
|
|
cause_value = cause->value;
|
|
|
|
if (cause_value != OGS_GTP2_CAUSE_REQUEST_ACCEPTED) {
|
2022-09-25 10:16:32 +00:00
|
|
|
ogs_error("GTP Bearer Cause [VALUE:%d]", cause_value);
|
2022-04-29 12:28:16 +00:00
|
|
|
ogs_assert(OGS_OK ==
|
2022-05-18 01:29:58 +00:00
|
|
|
smf_epc_pfcp_send_one_bearer_modification_request(
|
2022-04-29 12:28:16 +00:00
|
|
|
bearer, NULL, OGS_PFCP_MODIFY_REMOVE,
|
|
|
|
OGS_NAS_PROCEDURE_TRANSACTION_IDENTITY_UNASSIGNED,
|
|
|
|
OGS_GTP2_CAUSE_UNDEFINED_VALUE));
|
|
|
|
return;
|
2020-11-07 22:27:12 +00:00
|
|
|
}
|
|
|
|
|
2022-04-29 12:28:16 +00:00
|
|
|
cause = rsp->cause.data;
|
|
|
|
ogs_assert(cause);
|
|
|
|
cause_value = cause->value;
|
2022-04-12 22:07:39 +00:00
|
|
|
if (cause_value != OGS_GTP2_CAUSE_REQUEST_ACCEPTED) {
|
2022-09-25 10:16:32 +00:00
|
|
|
ogs_error("GTP Cause [Value:%d]", cause_value);
|
2021-05-16 03:22:10 +00:00
|
|
|
ogs_assert(OGS_OK ==
|
2022-05-18 01:29:58 +00:00
|
|
|
smf_epc_pfcp_send_one_bearer_modification_request(
|
2021-11-23 05:19:30 +00:00
|
|
|
bearer, NULL, OGS_PFCP_MODIFY_REMOVE,
|
|
|
|
OGS_NAS_PROCEDURE_TRANSACTION_IDENTITY_UNASSIGNED,
|
2022-04-12 22:07:39 +00:00
|
|
|
OGS_GTP2_CAUSE_UNDEFINED_VALUE));
|
2020-04-26 19:36:05 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2022-04-29 12:28:16 +00:00
|
|
|
/********************
|
|
|
|
* Check ALL Context
|
|
|
|
********************/
|
|
|
|
ogs_assert(bearer);
|
|
|
|
ogs_assert(sess);
|
|
|
|
|
2020-08-29 14:53:02 +00:00
|
|
|
/* Find the Bearer by PGW-S5U-TEID */
|
2021-06-21 13:36:38 +00:00
|
|
|
ogs_assert(pgw_s5u_teid);
|
2020-10-26 02:43:53 +00:00
|
|
|
bearer = smf_bearer_find_by_pgw_s5u_teid(sess, be32toh(pgw_s5u_teid->teid));
|
2023-01-23 15:01:36 +00:00
|
|
|
if (!bearer) {
|
|
|
|
ogs_error("smf_bearer_find_by_pgw_s5u_teid() failed");
|
|
|
|
return;
|
|
|
|
}
|
2020-04-26 19:36:05 +00:00
|
|
|
|
|
|
|
/* Set EBI */
|
|
|
|
bearer->ebi = rsp->bearer_contexts.eps_bearer_id.u8;
|
|
|
|
|
2020-07-20 01:42:58 +00:00
|
|
|
/* Data Plane(DL) : SGW-S5U */
|
|
|
|
ogs_assert(sgw_s5u_teid);
|
|
|
|
bearer->sgw_s5u_teid = be32toh(sgw_s5u_teid->teid);
|
2022-04-12 22:07:39 +00:00
|
|
|
rv = ogs_gtp2_f_teid_to_ip(sgw_s5u_teid, &bearer->sgw_s5u_ip);
|
2020-04-26 19:36:05 +00:00
|
|
|
ogs_assert(rv == OGS_OK);
|
|
|
|
|
2020-11-07 22:27:12 +00:00
|
|
|
ogs_debug("Create Bearer Response : SGW[0x%x] --> SMF[0x%x]",
|
2020-04-26 19:36:05 +00:00
|
|
|
sess->sgw_s5c_teid, sess->smf_n4_teid);
|
|
|
|
|
2020-07-20 01:42:58 +00:00
|
|
|
/* Setup FAR */
|
2020-08-29 14:53:02 +00:00
|
|
|
dl_far = bearer->dl_far;
|
|
|
|
ogs_assert(dl_far);
|
|
|
|
|
2020-12-03 06:16:57 +00:00
|
|
|
dl_far->apply_action = OGS_PFCP_APPLY_ACTION_FORW;
|
|
|
|
|
2021-06-06 13:35:46 +00:00
|
|
|
ogs_assert(OGS_OK ==
|
|
|
|
ogs_pfcp_ip_to_outer_header_creation(
|
|
|
|
&bearer->sgw_s5u_ip,
|
|
|
|
&dl_far->outer_header_creation,
|
|
|
|
&dl_far->outer_header_creation_len));
|
2020-08-29 14:53:02 +00:00
|
|
|
dl_far->outer_header_creation.teid = bearer->sgw_s5u_teid;
|
2020-07-20 01:42:58 +00:00
|
|
|
|
2021-05-16 03:22:10 +00:00
|
|
|
ogs_assert(OGS_OK ==
|
2022-05-18 01:29:58 +00:00
|
|
|
smf_epc_pfcp_send_one_bearer_modification_request(
|
2021-11-23 05:19:30 +00:00
|
|
|
bearer, NULL, OGS_PFCP_MODIFY_ACTIVATE,
|
|
|
|
OGS_NAS_PROCEDURE_TRANSACTION_IDENTITY_UNASSIGNED,
|
2022-04-12 22:07:39 +00:00
|
|
|
OGS_GTP2_CAUSE_UNDEFINED_VALUE));
|
2020-04-26 19:36:05 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void smf_s5c_handle_update_bearer_response(
|
|
|
|
smf_sess_t *sess, ogs_gtp_xact_t *xact,
|
2022-04-12 22:07:39 +00:00
|
|
|
ogs_gtp2_update_bearer_response_t *rsp)
|
2020-04-26 19:36:05 +00:00
|
|
|
{
|
|
|
|
int rv;
|
2020-11-07 22:27:12 +00:00
|
|
|
uint8_t cause_value;
|
2022-04-29 12:28:16 +00:00
|
|
|
ogs_gtp2_cause_t *cause = NULL;
|
2020-08-13 00:31:22 +00:00
|
|
|
uint64_t gtp_flags = 0;
|
|
|
|
uint64_t pfcp_flags = 0;
|
2020-04-26 19:36:05 +00:00
|
|
|
smf_bearer_t *bearer = NULL;
|
|
|
|
|
2022-07-16 04:27:18 +00:00
|
|
|
ogs_assert(sess);
|
2020-04-26 19:36:05 +00:00
|
|
|
ogs_assert(rsp);
|
2022-04-29 12:28:16 +00:00
|
|
|
|
|
|
|
ogs_debug("Update Bearer Response");
|
|
|
|
|
|
|
|
/********************
|
|
|
|
* Check Transaction
|
|
|
|
********************/
|
|
|
|
ogs_assert(xact);
|
2020-08-13 00:31:22 +00:00
|
|
|
gtp_flags = xact->update_flags;
|
|
|
|
ogs_assert(gtp_flags);
|
2021-11-23 05:19:30 +00:00
|
|
|
bearer = xact->data;
|
|
|
|
ogs_assert(bearer);
|
|
|
|
|
2022-04-29 12:28:16 +00:00
|
|
|
rv = ogs_gtp_xact_commit(xact);
|
|
|
|
ogs_expect(rv == OGS_OK);
|
2020-11-07 22:27:12 +00:00
|
|
|
|
2022-04-29 12:28:16 +00:00
|
|
|
/*****************************************
|
|
|
|
* Check Mandatory/Conditional IE Missing
|
|
|
|
*****************************************/
|
2022-07-16 04:27:18 +00:00
|
|
|
cause_value = OGS_GTP2_CAUSE_REQUEST_ACCEPTED;
|
2020-04-26 19:36:05 +00:00
|
|
|
|
2020-11-07 22:27:12 +00:00
|
|
|
if (rsp->bearer_contexts.presence == 0) {
|
|
|
|
ogs_error("No Bearer");
|
2022-04-12 22:07:39 +00:00
|
|
|
cause_value = OGS_GTP2_CAUSE_MANDATORY_IE_MISSING;
|
2020-11-07 22:27:12 +00:00
|
|
|
}
|
|
|
|
if (rsp->bearer_contexts.eps_bearer_id.presence == 0) {
|
|
|
|
ogs_error("No EPS Bearer ID");
|
2022-04-12 22:07:39 +00:00
|
|
|
cause_value = OGS_GTP2_CAUSE_MANDATORY_IE_MISSING;
|
2020-11-07 22:27:12 +00:00
|
|
|
}
|
|
|
|
|
2022-04-29 12:28:16 +00:00
|
|
|
if (rsp->cause.presence == 0) {
|
|
|
|
ogs_error("No Cause");
|
|
|
|
cause_value = OGS_GTP2_CAUSE_MANDATORY_IE_MISSING;
|
|
|
|
}
|
|
|
|
if (rsp->bearer_contexts.cause.presence == 0) {
|
|
|
|
ogs_error("No Bearer Cause");
|
|
|
|
cause_value = OGS_GTP2_CAUSE_MANDATORY_IE_MISSING;
|
2020-11-07 22:27:12 +00:00
|
|
|
}
|
2020-04-26 19:36:05 +00:00
|
|
|
|
2022-04-29 12:28:16 +00:00
|
|
|
if (cause_value != OGS_GTP2_CAUSE_REQUEST_ACCEPTED) {
|
|
|
|
return;
|
|
|
|
}
|
2020-04-26 19:36:05 +00:00
|
|
|
|
2022-04-29 12:28:16 +00:00
|
|
|
/********************
|
|
|
|
* Check Cause Value
|
|
|
|
********************/
|
|
|
|
ogs_assert(cause_value == OGS_GTP2_CAUSE_REQUEST_ACCEPTED);
|
2020-11-07 22:27:12 +00:00
|
|
|
|
2022-04-29 12:28:16 +00:00
|
|
|
cause = rsp->bearer_contexts.cause.data;
|
|
|
|
ogs_assert(cause);
|
|
|
|
cause_value = cause->value;
|
|
|
|
if (cause_value != OGS_GTP2_CAUSE_REQUEST_ACCEPTED) {
|
2022-09-25 10:16:32 +00:00
|
|
|
ogs_error("GTP Bearer Cause [VALUE:%d]", cause_value);
|
2022-04-29 12:28:16 +00:00
|
|
|
return;
|
2020-04-26 19:36:05 +00:00
|
|
|
}
|
|
|
|
|
2022-04-29 12:28:16 +00:00
|
|
|
cause = rsp->cause.data;
|
|
|
|
ogs_assert(cause);
|
|
|
|
cause_value = cause->value;
|
2022-04-12 22:07:39 +00:00
|
|
|
if (cause_value != OGS_GTP2_CAUSE_REQUEST_ACCEPTED) {
|
2022-09-25 10:16:32 +00:00
|
|
|
ogs_error("GTP Cause [Value:%d]", cause_value);
|
2020-04-26 19:36:05 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2022-04-29 12:28:16 +00:00
|
|
|
/********************
|
|
|
|
* Check ALL Context
|
|
|
|
********************/
|
|
|
|
ogs_assert(sess);
|
|
|
|
ogs_assert(bearer);
|
|
|
|
|
|
|
|
ogs_debug(" SGW_S5C_TEID[0x%x] SMF_N4_TEID[0x%x]",
|
|
|
|
sess->sgw_s5c_teid, sess->smf_n4_teid);
|
|
|
|
|
2020-11-07 22:27:12 +00:00
|
|
|
ogs_debug("Update Bearer Response : SGW[0x%x] --> SMF[0x%x]",
|
2020-04-26 19:36:05 +00:00
|
|
|
sess->sgw_s5c_teid, sess->smf_n4_teid);
|
|
|
|
|
2020-08-13 00:31:22 +00:00
|
|
|
if (gtp_flags & OGS_GTP_MODIFY_TFT_UPDATE) {
|
2021-11-14 12:07:56 +00:00
|
|
|
pfcp_flags |= OGS_PFCP_MODIFY_EPC_TFT_UPDATE;
|
|
|
|
smf_bearer_tft_update(bearer);
|
2020-08-13 00:31:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (gtp_flags & OGS_GTP_MODIFY_QOS_UPDATE) {
|
2021-11-14 12:07:56 +00:00
|
|
|
pfcp_flags |= OGS_PFCP_MODIFY_EPC_QOS_UPDATE;
|
|
|
|
smf_bearer_qos_update(bearer);
|
2020-04-26 19:36:05 +00:00
|
|
|
}
|
2020-08-13 00:31:22 +00:00
|
|
|
|
|
|
|
if (pfcp_flags)
|
2021-05-16 03:22:10 +00:00
|
|
|
ogs_assert(OGS_OK ==
|
2022-05-18 01:29:58 +00:00
|
|
|
smf_epc_pfcp_send_one_bearer_modification_request(
|
2021-11-23 05:19:30 +00:00
|
|
|
bearer, NULL, pfcp_flags,
|
|
|
|
OGS_NAS_PROCEDURE_TRANSACTION_IDENTITY_UNASSIGNED,
|
2022-04-12 22:07:39 +00:00
|
|
|
OGS_GTP2_CAUSE_UNDEFINED_VALUE));
|
2020-04-26 19:36:05 +00:00
|
|
|
}
|
|
|
|
|
2022-04-20 12:42:18 +00:00
|
|
|
/* return true if entire session must be released */
|
|
|
|
bool smf_s5c_handle_delete_bearer_response(
|
2020-04-26 19:36:05 +00:00
|
|
|
smf_sess_t *sess, ogs_gtp_xact_t *xact,
|
2022-04-12 22:07:39 +00:00
|
|
|
ogs_gtp2_delete_bearer_response_t *rsp)
|
2020-04-26 19:36:05 +00:00
|
|
|
{
|
|
|
|
int rv;
|
2020-11-07 22:27:12 +00:00
|
|
|
uint8_t cause_value;
|
2020-04-26 19:36:05 +00:00
|
|
|
smf_bearer_t *bearer = NULL;
|
|
|
|
|
2022-07-16 04:27:18 +00:00
|
|
|
ogs_assert(sess);
|
2020-04-26 19:36:05 +00:00
|
|
|
ogs_assert(rsp);
|
|
|
|
|
2020-11-07 22:27:12 +00:00
|
|
|
ogs_debug("Delete Bearer Response");
|
|
|
|
|
2022-04-29 12:28:16 +00:00
|
|
|
/********************
|
|
|
|
* Check Transaction
|
|
|
|
********************/
|
|
|
|
ogs_assert(xact);
|
2020-11-07 22:27:12 +00:00
|
|
|
bearer = xact->data;
|
|
|
|
ogs_assert(bearer);
|
|
|
|
|
2021-06-21 13:36:38 +00:00
|
|
|
rv = ogs_gtp_xact_commit(xact);
|
|
|
|
ogs_expect(rv == OGS_OK);
|
|
|
|
|
2022-04-29 12:28:16 +00:00
|
|
|
/********************
|
|
|
|
* Check ALL Context
|
|
|
|
********************/
|
|
|
|
ogs_assert(bearer);
|
2020-04-26 19:36:05 +00:00
|
|
|
|
2021-06-21 13:36:38 +00:00
|
|
|
if (rsp->linked_eps_bearer_id.presence) {
|
|
|
|
/*
|
|
|
|
* 1. SMF sends Delete Bearer Request(DEFAULT BEARER) to SGW/MME.
|
|
|
|
* 2. MME sends Delete Bearer Response to SGW/SMF.
|
|
|
|
*
|
|
|
|
* OR
|
|
|
|
*
|
|
|
|
* 1. SMF sends Delete Bearer Request(DEFAULT BEARER) to ePDG.
|
|
|
|
* 2. ePDG sends Delete Bearer Response(DEFAULT BEARER) to SMF.
|
|
|
|
*/
|
|
|
|
if (rsp->cause.presence) {
|
2022-04-12 22:07:39 +00:00
|
|
|
ogs_gtp2_cause_t *cause = rsp->cause.data;
|
2021-06-21 13:36:38 +00:00
|
|
|
ogs_assert(cause);
|
2020-04-26 19:36:05 +00:00
|
|
|
|
2021-06-21 13:36:38 +00:00
|
|
|
cause_value = cause->value;
|
2022-04-12 22:07:39 +00:00
|
|
|
if (cause->value == OGS_GTP2_CAUSE_REQUEST_ACCEPTED) {
|
2020-11-07 22:27:12 +00:00
|
|
|
} else {
|
2022-09-25 10:16:32 +00:00
|
|
|
ogs_error("GTP Cause [Value:%d]", cause_value);
|
2020-11-07 22:27:12 +00:00
|
|
|
}
|
|
|
|
} else {
|
2021-06-21 13:36:38 +00:00
|
|
|
ogs_error("No Cause");
|
2020-11-07 22:27:12 +00:00
|
|
|
}
|
2022-04-20 12:42:18 +00:00
|
|
|
/* Release entire session: */
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* 1. MME sends Bearer Resource Command to SGW/SMF.
|
|
|
|
* 2. SMF sends Delete Bearer Request(DEDICATED BEARER) to SGW/MME
|
|
|
|
* 3. MME sends Delete Bearer Response(DEDICATED BEARER) to SGW/SMF
|
|
|
|
*
|
|
|
|
* OR
|
|
|
|
*
|
|
|
|
* 1. SMF sends Delete Bearer Request(DEDICATED BEARER) to SGW/MME
|
|
|
|
* 2. MME sends Delete Bearer Response(DEDICATED BEARER) to SGW/SMF
|
|
|
|
*/
|
|
|
|
if (rsp->bearer_contexts.presence == 0) {
|
|
|
|
ogs_error("No Bearer");
|
|
|
|
cause_value = OGS_GTP2_CAUSE_MANDATORY_IE_MISSING;
|
|
|
|
}
|
|
|
|
if (rsp->bearer_contexts.eps_bearer_id.presence == 0) {
|
|
|
|
ogs_error("No EPS Bearer ID");
|
|
|
|
cause_value = OGS_GTP2_CAUSE_MANDATORY_IE_MISSING;
|
|
|
|
}
|
2021-06-21 13:36:38 +00:00
|
|
|
|
2022-04-20 12:42:18 +00:00
|
|
|
if (rsp->cause.presence) {
|
|
|
|
ogs_gtp2_cause_t *cause = rsp->cause.data;
|
|
|
|
ogs_assert(cause);
|
2020-04-26 19:36:05 +00:00
|
|
|
|
2022-04-20 12:42:18 +00:00
|
|
|
cause_value = cause->value;
|
|
|
|
if (cause_value == OGS_GTP2_CAUSE_REQUEST_ACCEPTED) {
|
|
|
|
if (rsp->bearer_contexts.cause.presence) {
|
|
|
|
cause = rsp->bearer_contexts.cause.data;
|
|
|
|
ogs_assert(cause);
|
2020-04-26 19:36:05 +00:00
|
|
|
|
2022-04-29 12:28:16 +00:00
|
|
|
if (cause_value == OGS_GTP2_CAUSE_REQUEST_ACCEPTED) {
|
|
|
|
} else {
|
2022-09-25 10:16:32 +00:00
|
|
|
ogs_error("GTP Cause [Value:%d]", cause_value);
|
2022-04-29 12:28:16 +00:00
|
|
|
}
|
2021-06-21 13:36:38 +00:00
|
|
|
} else {
|
2022-04-20 12:42:18 +00:00
|
|
|
ogs_error("No Cause");
|
2021-06-21 13:36:38 +00:00
|
|
|
}
|
|
|
|
} else {
|
2022-09-25 10:16:32 +00:00
|
|
|
ogs_error("GTP Cause [Value:%d]", cause_value);
|
2021-06-21 13:36:38 +00:00
|
|
|
}
|
2022-04-20 12:42:18 +00:00
|
|
|
} else {
|
|
|
|
ogs_error("No Cause");
|
|
|
|
}
|
2021-06-21 13:36:38 +00:00
|
|
|
|
2022-04-20 12:42:18 +00:00
|
|
|
ogs_debug(" SGW_S5C_TEID[0x%x] SMF_N4_TEID[0x%x]",
|
|
|
|
sess->sgw_s5c_teid, sess->smf_n4_teid);
|
2021-06-21 13:36:38 +00:00
|
|
|
|
2022-04-20 12:42:18 +00:00
|
|
|
ogs_debug("Delete Bearer Response : SGW[0x%x] --> SMF[0x%x]",
|
|
|
|
sess->sgw_s5c_teid, sess->smf_n4_teid);
|
2021-06-21 13:36:38 +00:00
|
|
|
|
2022-04-20 12:42:18 +00:00
|
|
|
ogs_assert(OGS_OK ==
|
2022-05-18 01:29:58 +00:00
|
|
|
smf_epc_pfcp_send_one_bearer_modification_request(
|
2022-04-20 12:42:18 +00:00
|
|
|
bearer, NULL, OGS_PFCP_MODIFY_REMOVE,
|
|
|
|
OGS_NAS_PROCEDURE_TRANSACTION_IDENTITY_UNASSIGNED,
|
|
|
|
OGS_GTP2_CAUSE_UNDEFINED_VALUE));
|
|
|
|
return false;
|
2020-04-26 19:36:05 +00:00
|
|
|
}
|
|
|
|
|
2022-04-12 22:07:39 +00:00
|
|
|
static int reconfigure_packet_filter(smf_pf_t *pf, ogs_gtp2_tft_t *tft, int i)
|
2020-04-26 19:36:05 +00:00
|
|
|
{
|
|
|
|
int j;
|
|
|
|
|
2020-09-21 03:35:10 +00:00
|
|
|
ogs_assert(pf);
|
|
|
|
ogs_assert(tft);
|
|
|
|
|
2020-08-13 00:31:22 +00:00
|
|
|
memset(&pf->ipfw_rule, 0, sizeof(ogs_ipfw_rule_t));
|
2020-09-21 03:35:10 +00:00
|
|
|
pf->direction = tft->pf[i].direction;
|
2021-01-01 02:07:08 +00:00
|
|
|
for (j = 0; j < tft->pf[i].content.num_of_component; j++) {
|
|
|
|
switch(tft->pf[i].content.component[j].type) {
|
|
|
|
case OGS_PACKET_FILTER_PROTOCOL_IDENTIFIER_NEXT_HEADER_TYPE:
|
|
|
|
pf->ipfw_rule.proto = tft->pf[i].content.component[j].proto;
|
2020-04-26 19:36:05 +00:00
|
|
|
break;
|
2021-01-01 02:07:08 +00:00
|
|
|
case OGS_PACKET_FILTER_IPV4_REMOTE_ADDRESS_TYPE:
|
2020-09-21 03:35:10 +00:00
|
|
|
pf->ipfw_rule.ipv4_dst = 1;
|
2021-01-01 02:07:08 +00:00
|
|
|
pf->ipfw_rule.ip.dst.addr[0] =
|
|
|
|
tft->pf[i].content.component[j].ipv4.addr;
|
|
|
|
pf->ipfw_rule.ip.dst.mask[0] =
|
|
|
|
tft->pf[i].content.component[j].ipv4.mask;
|
2020-04-26 19:36:05 +00:00
|
|
|
break;
|
2021-01-01 02:07:08 +00:00
|
|
|
case OGS_PACKET_FILTER_IPV4_LOCAL_ADDRESS_TYPE:
|
2020-09-21 03:35:10 +00:00
|
|
|
pf->ipfw_rule.ipv4_src = 1;
|
2021-01-01 02:07:08 +00:00
|
|
|
pf->ipfw_rule.ip.src.addr[0] =
|
|
|
|
tft->pf[i].content.component[j].ipv4.addr;
|
|
|
|
pf->ipfw_rule.ip.src.mask[0] =
|
|
|
|
tft->pf[i].content.component[j].ipv4.mask;
|
2020-04-26 19:36:05 +00:00
|
|
|
break;
|
2021-01-01 02:07:08 +00:00
|
|
|
case OGS_PACKET_FILTER_IPV6_REMOTE_ADDRESS_TYPE:
|
2020-09-21 03:35:10 +00:00
|
|
|
pf->ipfw_rule.ipv6_dst = 1;
|
|
|
|
memcpy(pf->ipfw_rule.ip.dst.addr,
|
2021-01-01 02:07:08 +00:00
|
|
|
tft->pf[i].content.component[j].ipv6_mask.addr,
|
2020-09-21 03:35:10 +00:00
|
|
|
sizeof(pf->ipfw_rule.ip.dst.addr));
|
|
|
|
memcpy(pf->ipfw_rule.ip.dst.mask,
|
2021-01-01 02:07:08 +00:00
|
|
|
tft->pf[i].content.component[j].ipv6_mask.mask,
|
2020-09-21 03:35:10 +00:00
|
|
|
sizeof(pf->ipfw_rule.ip.dst.mask));
|
2020-04-26 19:36:05 +00:00
|
|
|
break;
|
2021-01-01 02:07:08 +00:00
|
|
|
case OGS_PACKET_FILTER_IPV6_REMOTE_ADDRESS_PREFIX_LENGTH_TYPE:
|
2020-09-21 03:35:10 +00:00
|
|
|
pf->ipfw_rule.ipv6_dst = 1;
|
|
|
|
memcpy(pf->ipfw_rule.ip.dst.addr,
|
2021-01-01 02:07:08 +00:00
|
|
|
tft->pf[i].content.component[j].ipv6_mask.addr,
|
2020-09-21 03:35:10 +00:00
|
|
|
sizeof(pf->ipfw_rule.ip.dst.addr));
|
|
|
|
n2mask((struct in6_addr *)pf->ipfw_rule.ip.dst.mask,
|
2021-01-01 02:07:08 +00:00
|
|
|
tft->pf[i].content.component[j].ipv6.prefixlen);
|
2020-04-26 19:36:05 +00:00
|
|
|
break;
|
2021-01-01 02:07:08 +00:00
|
|
|
case OGS_PACKET_FILTER_IPV6_LOCAL_ADDRESS_TYPE:
|
2020-09-21 03:35:10 +00:00
|
|
|
pf->ipfw_rule.ipv6_src = 1;
|
|
|
|
memcpy(pf->ipfw_rule.ip.src.addr,
|
2021-01-01 02:07:08 +00:00
|
|
|
tft->pf[i].content.component[j].ipv6_mask.addr,
|
2020-09-21 03:35:10 +00:00
|
|
|
sizeof(pf->ipfw_rule.ip.src.addr));
|
|
|
|
memcpy(pf->ipfw_rule.ip.src.mask,
|
2021-01-01 02:07:08 +00:00
|
|
|
tft->pf[i].content.component[j].ipv6_mask.mask,
|
2020-09-21 03:35:10 +00:00
|
|
|
sizeof(pf->ipfw_rule.ip.src.mask));
|
2020-04-26 19:36:05 +00:00
|
|
|
break;
|
2021-01-01 02:07:08 +00:00
|
|
|
case OGS_PACKET_FILTER_IPV6_LOCAL_ADDRESS_PREFIX_LENGTH_TYPE:
|
2020-09-21 03:35:10 +00:00
|
|
|
pf->ipfw_rule.ipv6_src = 1;
|
|
|
|
memcpy(pf->ipfw_rule.ip.src.addr,
|
2021-01-01 02:07:08 +00:00
|
|
|
tft->pf[i].content.component[j].ipv6_mask.addr,
|
2020-09-21 03:35:10 +00:00
|
|
|
sizeof(pf->ipfw_rule.ip.src.addr));
|
|
|
|
n2mask((struct in6_addr *)pf->ipfw_rule.ip.src.mask,
|
2021-01-01 02:07:08 +00:00
|
|
|
tft->pf[i].content.component[j].ipv6.prefixlen);
|
2020-04-26 19:36:05 +00:00
|
|
|
break;
|
2021-01-01 02:07:08 +00:00
|
|
|
case OGS_PACKET_FILTER_SINGLE_LOCAL_PORT_TYPE:
|
2020-09-21 03:35:10 +00:00
|
|
|
pf->ipfw_rule.port.src.low = pf->ipfw_rule.port.src.high =
|
2021-01-01 02:07:08 +00:00
|
|
|
tft->pf[i].content.component[j].port.low;
|
2020-04-26 19:36:05 +00:00
|
|
|
break;
|
2021-01-01 02:07:08 +00:00
|
|
|
case OGS_PACKET_FILTER_SINGLE_REMOTE_PORT_TYPE:
|
2020-09-21 03:35:10 +00:00
|
|
|
pf->ipfw_rule.port.dst.low = pf->ipfw_rule.port.dst.high =
|
2021-01-01 02:07:08 +00:00
|
|
|
tft->pf[i].content.component[j].port.low;
|
2020-04-26 19:36:05 +00:00
|
|
|
break;
|
2021-01-01 02:07:08 +00:00
|
|
|
case OGS_PACKET_FILTER_LOCAL_PORT_RANGE_TYPE:
|
|
|
|
pf->ipfw_rule.port.src.low =
|
|
|
|
tft->pf[i].content.component[j].port.low;
|
|
|
|
pf->ipfw_rule.port.src.high =
|
|
|
|
tft->pf[i].content.component[j].port.high;
|
2020-04-26 19:36:05 +00:00
|
|
|
break;
|
2021-01-01 02:07:08 +00:00
|
|
|
case OGS_PACKET_FILTER_REMOTE_PORT_RANGE_TYPE:
|
|
|
|
pf->ipfw_rule.port.dst.low =
|
|
|
|
tft->pf[i].content.component[j].port.low;
|
|
|
|
pf->ipfw_rule.port.dst.high =
|
|
|
|
tft->pf[i].content.component[j].port.high;
|
2020-04-26 19:36:05 +00:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
ogs_error("Unknown Packet Filter Type(%d)",
|
2021-01-01 02:07:08 +00:00
|
|
|
tft->pf[i].content.component[j].type);
|
2020-04-26 19:36:05 +00:00
|
|
|
return OGS_ERROR;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return j;
|
|
|
|
}
|
|
|
|
|
|
|
|
void smf_s5c_handle_bearer_resource_command(
|
|
|
|
smf_sess_t *sess, ogs_gtp_xact_t *xact,
|
2022-04-12 22:07:39 +00:00
|
|
|
ogs_gtp2_bearer_resource_command_t *cmd)
|
2020-04-26 19:36:05 +00:00
|
|
|
{
|
|
|
|
int rv;
|
|
|
|
uint8_t cause_value = 0;
|
|
|
|
int i;
|
|
|
|
|
2022-04-12 22:07:39 +00:00
|
|
|
ogs_gtp2_header_t h;
|
2020-04-26 19:36:05 +00:00
|
|
|
ogs_pkbuf_t *pkbuf = NULL;
|
|
|
|
|
|
|
|
smf_bearer_t *bearer = NULL;
|
|
|
|
smf_pf_t *pf = NULL;
|
|
|
|
|
|
|
|
int16_t decoded;
|
2022-04-12 22:07:39 +00:00
|
|
|
ogs_gtp2_tft_t tft;
|
2020-04-26 19:36:05 +00:00
|
|
|
|
|
|
|
int tft_update = 0;
|
|
|
|
int qos_update = 0;
|
|
|
|
int tft_delete = 0;
|
|
|
|
|
|
|
|
ogs_assert(xact);
|
|
|
|
ogs_assert(cmd);
|
|
|
|
|
2022-04-29 12:28:16 +00:00
|
|
|
ogs_debug("Bearer Resource Command");
|
2020-04-26 19:36:05 +00:00
|
|
|
|
2022-04-29 12:28:16 +00:00
|
|
|
/************************
|
|
|
|
* Check Session Context
|
|
|
|
************************/
|
2022-04-12 22:07:39 +00:00
|
|
|
cause_value = OGS_GTP2_CAUSE_REQUEST_ACCEPTED;
|
2020-04-26 19:36:05 +00:00
|
|
|
|
2022-04-29 12:28:16 +00:00
|
|
|
if (!sess) {
|
|
|
|
ogs_error("No Context");
|
|
|
|
cause_value = OGS_GTP2_CAUSE_CONTEXT_NOT_FOUND;
|
|
|
|
} else {
|
|
|
|
if (cmd->linked_eps_bearer_id.presence == 0) {
|
|
|
|
ogs_error("No EPS Bearer ID");
|
|
|
|
cause_value = OGS_GTP2_CAUSE_MANDATORY_IE_MISSING;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (cause_value == OGS_GTP2_CAUSE_REQUEST_ACCEPTED) {
|
|
|
|
uint8_t ebi = cmd->linked_eps_bearer_id.u8;
|
|
|
|
|
|
|
|
if (cmd->eps_bearer_id.presence)
|
|
|
|
ebi = cmd->eps_bearer_id.u8;
|
|
|
|
|
|
|
|
bearer = smf_bearer_find_by_ebi(sess, ebi);
|
|
|
|
if (!bearer) {
|
|
|
|
ogs_error("No Context for Linked EPS Bearer ID[%d:%d]",
|
|
|
|
cmd->linked_eps_bearer_id.u8, ebi);
|
|
|
|
cause_value = OGS_GTP2_CAUSE_CONTEXT_NOT_FOUND;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (cause_value != OGS_GTP2_CAUSE_REQUEST_ACCEPTED) {
|
[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
|
|
|
ogs_gtp2_send_error_message(xact,
|
|
|
|
sess ? OGS_GTP2_TEID_PRESENCE : OGS_GTP2_TEID_NO_PRESENCE,
|
|
|
|
sess ? sess->sgw_s5c_teid : 0,
|
2022-04-29 12:28:16 +00:00
|
|
|
OGS_GTP2_BEARER_RESOURCE_FAILURE_INDICATION_TYPE, cause_value);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*****************************************
|
|
|
|
* Check Mandatory/Conditional IE Missing
|
|
|
|
*****************************************/
|
|
|
|
ogs_assert(cause_value == OGS_GTP2_CAUSE_REQUEST_ACCEPTED);
|
|
|
|
|
2020-04-26 19:36:05 +00:00
|
|
|
if (cmd->procedure_transaction_id.presence == 0) {
|
|
|
|
ogs_error("No PTI");
|
2022-04-12 22:07:39 +00:00
|
|
|
cause_value = OGS_GTP2_CAUSE_MANDATORY_IE_MISSING;
|
2020-04-26 19:36:05 +00:00
|
|
|
}
|
|
|
|
if (cmd->traffic_aggregate_description.presence == 0) {
|
|
|
|
ogs_error("No Traffic aggregate description(TAD)");
|
2022-04-12 22:07:39 +00:00
|
|
|
cause_value = OGS_GTP2_CAUSE_MANDATORY_IE_MISSING;
|
2020-04-26 19:36:05 +00:00
|
|
|
}
|
|
|
|
|
2020-11-07 22:27:12 +00:00
|
|
|
if (cmd->linked_eps_bearer_id.presence == 0) {
|
|
|
|
ogs_error("No Linked EPS Bearer ID");
|
2022-04-12 22:07:39 +00:00
|
|
|
cause_value = OGS_GTP2_CAUSE_MANDATORY_IE_MISSING;
|
2020-11-07 22:27:12 +00:00
|
|
|
}
|
|
|
|
|
2022-04-12 22:07:39 +00:00
|
|
|
if (cause_value != OGS_GTP2_CAUSE_REQUEST_ACCEPTED) {
|
[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
|
|
|
ogs_gtp2_send_error_message(xact,
|
|
|
|
sess ? OGS_GTP2_TEID_PRESENCE : OGS_GTP2_TEID_NO_PRESENCE,
|
|
|
|
sess ? sess->sgw_s5c_teid : 0,
|
2022-04-12 22:07:39 +00:00
|
|
|
OGS_GTP2_BEARER_RESOURCE_FAILURE_INDICATION_TYPE, cause_value);
|
2020-04-26 19:36:05 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2022-04-29 12:28:16 +00:00
|
|
|
/********************
|
|
|
|
* Check ALL Context
|
|
|
|
********************/
|
2020-04-26 19:36:05 +00:00
|
|
|
ogs_assert(bearer);
|
2022-04-29 12:28:16 +00:00
|
|
|
ogs_assert(sess);
|
|
|
|
|
|
|
|
ogs_debug(" SGW_S5C_TEID[0x%x] PGW_S5C_TEID[0x%x]",
|
|
|
|
sess->sgw_s5c_teid, sess->smf_n4_teid);
|
2020-04-26 19:36:05 +00:00
|
|
|
|
2022-04-12 22:07:39 +00:00
|
|
|
decoded = ogs_gtp2_parse_tft(&tft, &cmd->traffic_aggregate_description);
|
2020-04-26 19:36:05 +00:00
|
|
|
ogs_assert(cmd->traffic_aggregate_description.len == decoded);
|
|
|
|
|
2022-04-12 22:07:39 +00:00
|
|
|
if (tft.code == OGS_GTP2_TFT_CODE_NO_TFT_OPERATION) {
|
2020-04-26 19:36:05 +00:00
|
|
|
/* No operation */
|
2022-04-12 22:07:39 +00:00
|
|
|
} else if (tft.code == OGS_GTP2_TFT_CODE_DELETE_EXISTING_TFT) {
|
2020-04-26 19:36:05 +00:00
|
|
|
smf_pf_remove_all(bearer);
|
|
|
|
tft_delete = 1;
|
|
|
|
} else if (tft.code ==
|
2022-04-12 22:07:39 +00:00
|
|
|
OGS_GTP2_TFT_CODE_REPLACE_PACKET_FILTERS_IN_EXISTING) {
|
2021-08-07 05:23:20 +00:00
|
|
|
for (i = 0; i < tft.num_of_packet_filter &&
|
|
|
|
i < OGS_MAX_NUM_OF_FLOW_IN_GTP; i++) {
|
2020-04-26 19:36:05 +00:00
|
|
|
pf = smf_pf_find_by_id(bearer, tft.pf[i].identifier+1);
|
|
|
|
if (pf) {
|
|
|
|
if (reconfigure_packet_filter(pf, &tft, i) < 0) {
|
[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
|
|
|
ogs_gtp2_send_error_message(xact,
|
|
|
|
sess ? OGS_GTP2_TEID_PRESENCE :
|
|
|
|
OGS_GTP2_TEID_NO_PRESENCE,
|
|
|
|
sess ? sess->sgw_s5c_teid : 0,
|
2022-04-12 22:07:39 +00:00
|
|
|
OGS_GTP2_BEARER_RESOURCE_FAILURE_INDICATION_TYPE,
|
|
|
|
OGS_GTP2_CAUSE_SEMANTIC_ERRORS_IN_PACKET_FILTER);
|
2020-04-26 19:36:05 +00:00
|
|
|
return;
|
|
|
|
}
|
2020-09-21 03:35:10 +00:00
|
|
|
/*
|
|
|
|
* Refer to lib/ipfw/ogs-ipfw.h
|
|
|
|
* Issue #338
|
|
|
|
*
|
2024-02-17 19:40:08 +00:00
|
|
|
* <DOWNLINK/BI-DIRECTIONAL>
|
2020-09-21 03:35:10 +00:00
|
|
|
* TFT : Local <UE_IP> <UE_PORT> REMOTE <P-CSCF_RTP_IP> <P-CSCF_RTP_PORT>
|
|
|
|
* -->
|
|
|
|
* RULE : Source <P-CSCF_RTP_IP> <P-CSCF_RTP_PORT> Destination <UE_IP> <UE_PORT>
|
|
|
|
*
|
|
|
|
* <UPLINK>
|
|
|
|
* TFT : Local <UE_IP> <UE_PORT> REMOTE <P-CSCF_RTP_IP> <P-CSCF_RTP_PORT>
|
|
|
|
* -->
|
|
|
|
* RULE : Source <UE_IP> <UE_PORT> Destination <P-CSCF_RTP_IP> <P-CSCF_RTP_PORT>
|
|
|
|
*/
|
|
|
|
if (pf->direction == OGS_FLOW_DOWNLINK_ONLY)
|
|
|
|
ogs_ipfw_rule_swap(&pf->ipfw_rule);
|
2020-08-13 00:31:22 +00:00
|
|
|
|
|
|
|
if (pf->flow_description)
|
|
|
|
ogs_free(pf->flow_description);
|
2020-09-21 04:33:36 +00:00
|
|
|
/*
|
|
|
|
* Issue #338
|
|
|
|
*
|
2024-02-17 19:40:08 +00:00
|
|
|
* <DOWNLINK/BI-DIRECTIONAL>
|
2020-09-21 04:33:36 +00:00
|
|
|
* RULE : Source <P-CSCF_RTP_IP> <P-CSCF_RTP_PORT> Destination <UE_IP> <UE_PORT>
|
|
|
|
* -->
|
|
|
|
* GX : permit out from <P-CSCF_RTP_IP> <P-CSCF_RTP_PORT> to <UE_IP> <UE_PORT>
|
|
|
|
* PFCP : permit out from <P-CSCF_RTP_IP> <P-CSCF_RTP_PORT> to <UE_IP> <UE_PORT>
|
|
|
|
*
|
|
|
|
* <UPLINK>
|
|
|
|
* RULE : Source <UE_IP> <UE_PORT> Destination <P-CSCF_RTP_IP> <P-CSCF_RTP_PORT>
|
|
|
|
* -->
|
|
|
|
* GX : permit out from <P-CSCF_RTP_IP> <P-CSCF_RTP_PORT> to <UE_IP> <UE_PORT>
|
|
|
|
* PFCP : permit out from <P-CSCF_RTP_IP> <P-CSCF_RTP_PORT> to <UE_IP> <UE_PORT>
|
|
|
|
*/
|
|
|
|
if (pf->direction == OGS_FLOW_UPLINK_ONLY) {
|
|
|
|
ogs_ipfw_rule_t tmp;
|
|
|
|
ogs_ipfw_copy_and_swap(&tmp, &pf->ipfw_rule);
|
|
|
|
pf->flow_description =
|
|
|
|
ogs_ipfw_encode_flow_description(&tmp);
|
2021-06-06 13:35:46 +00:00
|
|
|
ogs_assert(pf->flow_description);
|
2020-09-21 04:33:36 +00:00
|
|
|
} else {
|
|
|
|
pf->flow_description =
|
|
|
|
ogs_ipfw_encode_flow_description(&pf->ipfw_rule);
|
2021-06-06 13:35:46 +00:00
|
|
|
ogs_assert(pf->flow_description);
|
2020-09-21 04:33:36 +00:00
|
|
|
}
|
2020-04-26 19:36:05 +00:00
|
|
|
|
2021-11-14 12:07:56 +00:00
|
|
|
tft_update = 1;
|
|
|
|
}
|
2020-04-26 19:36:05 +00:00
|
|
|
}
|
|
|
|
} else if (tft.code ==
|
2022-04-12 22:07:39 +00:00
|
|
|
OGS_GTP2_TFT_CODE_ADD_PACKET_FILTERS_TO_EXISTING_TFT ||
|
|
|
|
tft.code == OGS_GTP2_TFT_CODE_CREATE_NEW_TFT) {
|
|
|
|
if (tft.code == OGS_GTP2_TFT_CODE_CREATE_NEW_TFT)
|
2020-04-26 19:36:05 +00:00
|
|
|
smf_pf_remove_all(bearer);
|
|
|
|
|
2021-08-07 05:23:20 +00:00
|
|
|
for (i = 0; i < tft.num_of_packet_filter &&
|
|
|
|
i < OGS_MAX_NUM_OF_FLOW_IN_GTP; i++) {
|
2020-04-26 19:36:05 +00:00
|
|
|
pf = smf_pf_find_by_id(bearer, tft.pf[i].identifier+1);
|
|
|
|
if (!pf)
|
2021-01-01 02:07:08 +00:00
|
|
|
pf = smf_pf_add(bearer);
|
2020-04-26 19:36:05 +00:00
|
|
|
ogs_assert(pf);
|
|
|
|
|
|
|
|
if (reconfigure_packet_filter(pf, &tft, i) < 0) {
|
[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
|
|
|
ogs_gtp2_send_error_message(xact,
|
|
|
|
sess ? OGS_GTP2_TEID_PRESENCE : OGS_GTP2_TEID_NO_PRESENCE,
|
|
|
|
sess ? sess->sgw_s5c_teid : 0,
|
2022-04-12 22:07:39 +00:00
|
|
|
OGS_GTP2_BEARER_RESOURCE_FAILURE_INDICATION_TYPE,
|
|
|
|
OGS_GTP2_CAUSE_SEMANTIC_ERRORS_IN_PACKET_FILTER);
|
2020-04-26 19:36:05 +00:00
|
|
|
return;
|
|
|
|
}
|
2020-09-21 03:35:10 +00:00
|
|
|
/*
|
|
|
|
* Refer to lib/ipfw/ogs-ipfw.h
|
|
|
|
* Issue #338
|
|
|
|
*
|
2024-02-17 19:40:08 +00:00
|
|
|
* <DOWNLINK/BI-DIRECTIONAL>
|
2020-09-21 03:35:10 +00:00
|
|
|
* TFT : Local <UE_IP> <UE_PORT> REMOTE <P-CSCF_RTP_IP> <P-CSCF_RTP_PORT>
|
|
|
|
* -->
|
|
|
|
* RULE : Source <P-CSCF_RTP_IP> <P-CSCF_RTP_PORT> Destination <UE_IP> <UE_PORT>
|
|
|
|
*
|
|
|
|
* <UPLINK>
|
|
|
|
* TFT : Local <UE_IP> <UE_PORT> REMOTE <P-CSCF_RTP_IP> <P-CSCF_RTP_PORT>
|
|
|
|
* -->
|
|
|
|
* RULE : Source <UE_IP> <UE_PORT> Destination <P-CSCF_RTP_IP> <P-CSCF_RTP_PORT>
|
|
|
|
*/
|
|
|
|
if (pf->direction == OGS_FLOW_DOWNLINK_ONLY)
|
|
|
|
ogs_ipfw_rule_swap(&pf->ipfw_rule);
|
2020-04-26 19:36:05 +00:00
|
|
|
|
2020-08-13 00:31:22 +00:00
|
|
|
if (pf->flow_description)
|
|
|
|
ogs_free(pf->flow_description);
|
2020-09-21 04:33:36 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Issue #338
|
|
|
|
*
|
2024-02-17 19:40:08 +00:00
|
|
|
* <DOWNLINK/BI-DIRECTIONAL>
|
2020-09-21 04:33:36 +00:00
|
|
|
* RULE : Source <P-CSCF_RTP_IP> <P-CSCF_RTP_PORT> Destination <UE_IP> <UE_PORT>
|
|
|
|
* -->
|
|
|
|
* GX : permit out from <P-CSCF_RTP_IP> <P-CSCF_RTP_PORT> to <UE_IP> <UE_PORT>
|
|
|
|
* PFCP : permit out from <P-CSCF_RTP_IP> <P-CSCF_RTP_PORT> to <UE_IP> <UE_PORT>
|
|
|
|
*
|
|
|
|
* <UPLINK>
|
|
|
|
* RULE : Source <UE_IP> <UE_PORT> Destination <P-CSCF_RTP_IP> <P-CSCF_RTP_PORT>
|
|
|
|
* -->
|
|
|
|
* GX : permit out from <P-CSCF_RTP_IP> <P-CSCF_RTP_PORT> to <UE_IP> <UE_PORT>
|
|
|
|
* PFCP : permit out from <P-CSCF_RTP_IP> <P-CSCF_RTP_PORT> to <UE_IP> <UE_PORT>
|
|
|
|
*/
|
|
|
|
if (pf->direction == OGS_FLOW_UPLINK_ONLY) {
|
|
|
|
ogs_ipfw_rule_t tmp;
|
|
|
|
ogs_ipfw_copy_and_swap(&tmp, &pf->ipfw_rule);
|
|
|
|
pf->flow_description =
|
|
|
|
ogs_ipfw_encode_flow_description(&tmp);
|
2021-06-06 13:35:46 +00:00
|
|
|
ogs_assert(pf->flow_description);
|
2020-09-21 04:33:36 +00:00
|
|
|
} else {
|
|
|
|
pf->flow_description =
|
|
|
|
ogs_ipfw_encode_flow_description(&pf->ipfw_rule);
|
2021-06-06 13:35:46 +00:00
|
|
|
ogs_assert(pf->flow_description);
|
2020-09-21 04:33:36 +00:00
|
|
|
}
|
2020-08-13 00:31:22 +00:00
|
|
|
|
2020-04-26 19:36:05 +00:00
|
|
|
tft_update = 1;
|
|
|
|
}
|
|
|
|
} else if (tft.code ==
|
2022-04-12 22:07:39 +00:00
|
|
|
OGS_GTP2_TFT_CODE_DELETE_PACKET_FILTERS_FROM_EXISTING) {
|
2021-08-07 05:23:20 +00:00
|
|
|
for (i = 0; i < tft.num_of_packet_filter &&
|
|
|
|
i <= OGS_MAX_NUM_OF_FLOW_IN_GTP; i++) {
|
2020-04-26 19:36:05 +00:00
|
|
|
pf = smf_pf_find_by_id(bearer, tft.pf[i].identifier+1);
|
|
|
|
if (pf)
|
|
|
|
smf_pf_remove(pf);
|
|
|
|
}
|
2021-11-14 12:07:56 +00:00
|
|
|
|
|
|
|
if (ogs_list_count(&bearer->pf_list))
|
|
|
|
tft_update = 1;
|
|
|
|
else
|
|
|
|
tft_delete = 1;
|
2020-04-26 19:36:05 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (cmd->flow_quality_of_service.presence) {
|
2022-04-12 22:07:39 +00:00
|
|
|
ogs_gtp2_flow_qos_t flow_qos;
|
2020-04-26 19:36:05 +00:00
|
|
|
|
2022-04-12 22:07:39 +00:00
|
|
|
decoded = ogs_gtp2_parse_flow_qos(
|
2020-04-26 19:36:05 +00:00
|
|
|
&flow_qos, &cmd->flow_quality_of_service);
|
|
|
|
ogs_assert(cmd->flow_quality_of_service.len == decoded);
|
|
|
|
|
|
|
|
bearer->qos.mbr.uplink = flow_qos.ul_mbr;
|
|
|
|
bearer->qos.mbr.downlink = flow_qos.dl_mbr;
|
|
|
|
bearer->qos.gbr.uplink = flow_qos.ul_gbr;
|
|
|
|
bearer->qos.gbr.downlink = flow_qos.dl_gbr;
|
|
|
|
|
|
|
|
qos_update = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (tft_update == 0 && tft_delete == 0 && qos_update == 0) {
|
|
|
|
/* No modification */
|
[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
|
|
|
ogs_gtp2_send_error_message(xact,
|
|
|
|
sess ? OGS_GTP2_TEID_PRESENCE : OGS_GTP2_TEID_NO_PRESENCE,
|
|
|
|
sess ? sess->sgw_s5c_teid : 0,
|
2022-04-12 22:07:39 +00:00
|
|
|
OGS_GTP2_BEARER_RESOURCE_FAILURE_INDICATION_TYPE,
|
|
|
|
OGS_GTP2_CAUSE_SERVICE_NOT_SUPPORTED);
|
2020-04-26 19:36:05 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (tft_delete) {
|
2021-11-23 05:19:30 +00:00
|
|
|
/*
|
|
|
|
* TS23.214
|
|
|
|
* 6.3.1.7 Procedures with modification of bearer
|
|
|
|
* p50
|
|
|
|
* 2. ...
|
|
|
|
* For "PGW/MME initiated bearer deactivation procedure",
|
|
|
|
* PGW-C shall indicate PGW-U to stop counting and stop
|
|
|
|
* forwarding downlink packets for the affected bearer(s).
|
|
|
|
*/
|
|
|
|
ogs_assert(OGS_OK ==
|
2022-05-18 01:29:58 +00:00
|
|
|
smf_epc_pfcp_send_one_bearer_modification_request(
|
2021-11-23 05:19:30 +00:00
|
|
|
bearer, xact,
|
|
|
|
OGS_PFCP_MODIFY_DL_ONLY|OGS_PFCP_MODIFY_DEACTIVATE,
|
|
|
|
cmd->procedure_transaction_id.u8,
|
2022-04-12 22:07:39 +00:00
|
|
|
OGS_GTP2_CAUSE_UNDEFINED_VALUE));
|
2020-08-13 00:31:22 +00:00
|
|
|
|
|
|
|
} else {
|
2022-04-12 22:07:39 +00:00
|
|
|
memset(&h, 0, sizeof(ogs_gtp2_header_t));
|
2021-11-23 05:19:30 +00:00
|
|
|
h.teid = sess->sgw_s5c_teid;
|
[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.teid_presence = OGS_GTP2_TEID_PRESENCE;
|
2022-04-12 22:07:39 +00:00
|
|
|
h.type = OGS_GTP2_UPDATE_BEARER_REQUEST_TYPE;
|
2021-11-23 05:19:30 +00:00
|
|
|
|
2020-04-26 19:36:05 +00:00
|
|
|
pkbuf = smf_s5c_build_update_bearer_request(
|
|
|
|
h.type, bearer, cmd->procedure_transaction_id.u8,
|
|
|
|
tft_update ? &tft : NULL, qos_update);
|
2023-01-23 15:01:36 +00:00
|
|
|
if (!pkbuf) {
|
|
|
|
ogs_error("smf_s5c_build_update_bearer_request() failed");
|
|
|
|
return;
|
|
|
|
}
|
2020-04-26 19:36:05 +00:00
|
|
|
|
2020-08-13 00:31:22 +00:00
|
|
|
rv = ogs_gtp_xact_update_tx(xact, &h, pkbuf);
|
2023-01-23 15:01:36 +00:00
|
|
|
if (rv != OGS_OK) {
|
|
|
|
ogs_error("ogs_gtp_xact_update_tx() failed");
|
|
|
|
return;
|
|
|
|
}
|
2020-04-26 19:36:05 +00:00
|
|
|
|
2020-08-13 00:31:22 +00:00
|
|
|
if (tft_update)
|
|
|
|
xact->update_flags |= OGS_GTP_MODIFY_TFT_UPDATE;
|
|
|
|
if (qos_update)
|
|
|
|
xact->update_flags |= OGS_GTP_MODIFY_QOS_UPDATE;
|
2020-04-26 19:36:05 +00:00
|
|
|
|
2021-11-23 05:19:30 +00:00
|
|
|
/* IMPORTANT:
|
|
|
|
*
|
|
|
|
* When initiaited by Bearer Resource Command, there must be bearer context
|
|
|
|
* in the Transaction. Otherwise, the bearer context cannot be found
|
|
|
|
* in GTP response message.
|
|
|
|
*
|
|
|
|
* For example,
|
|
|
|
* 1. MME sends Bearer Resource Command to SGW-C, SMF.
|
|
|
|
* 2. SMF sends Update/Delete Bearer Request to the SGW-C, MME.
|
|
|
|
* 3. MME sends Update/Delete Bearer Response to thw SGW-C, SMF.
|
|
|
|
*
|
|
|
|
* On number 3 step, if MME sends Response without Bearer Context,
|
|
|
|
* we need a way to find Bearer context.
|
|
|
|
*
|
|
|
|
* To do this, I saved Bearer Context in Transaction Context.
|
|
|
|
*/
|
|
|
|
xact->data = bearer;
|
2020-11-07 22:27:12 +00:00
|
|
|
|
2021-11-23 05:19:30 +00:00
|
|
|
rv = ogs_gtp_xact_commit(xact);
|
|
|
|
ogs_expect(rv == OGS_OK);
|
|
|
|
}
|
2020-04-26 19:36:05 +00:00
|
|
|
}
|