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/>.
|
|
|
|
*/
|
|
|
|
|
2021-01-01 02:07:08 +00:00
|
|
|
#include "binding.h"
|
2020-04-26 19:36:05 +00:00
|
|
|
#include "s5c-build.h"
|
2020-10-26 02:43:53 +00:00
|
|
|
#include "pfcp-path.h"
|
2021-06-21 13:36:38 +00:00
|
|
|
#include "gtp-path.h"
|
2020-04-26 19:36:05 +00:00
|
|
|
|
|
|
|
#include "ipfw/ipfw2.h"
|
|
|
|
|
2022-05-15 14:35:41 +00:00
|
|
|
static void gtp_bearer_timeout(ogs_gtp_xact_t *xact, void *data)
|
2020-04-26 19:36:05 +00:00
|
|
|
{
|
2020-11-07 22:27:12 +00:00
|
|
|
smf_bearer_t *bearer = data;
|
|
|
|
smf_sess_t *sess = NULL;
|
|
|
|
smf_ue_t *smf_ue = NULL;
|
2020-04-26 19:36:05 +00:00
|
|
|
uint8_t type = 0;
|
|
|
|
|
2020-11-07 22:27:12 +00:00
|
|
|
ogs_assert(bearer);
|
|
|
|
sess = bearer->sess;
|
2020-04-26 19:36:05 +00:00
|
|
|
ogs_assert(sess);
|
2020-11-07 22:27:12 +00:00
|
|
|
smf_ue = sess->smf_ue;
|
|
|
|
ogs_assert(smf_ue);
|
2020-04-26 19:36:05 +00:00
|
|
|
|
|
|
|
type = xact->seq[0].type;
|
|
|
|
|
2020-11-07 22:27:12 +00:00
|
|
|
switch (type) {
|
2022-04-12 22:07:39 +00:00
|
|
|
case OGS_GTP2_CREATE_BEARER_REQUEST_TYPE:
|
2020-11-07 22:27:12 +00:00
|
|
|
ogs_error("[%s] No Create Bearer Response", smf_ue->imsi_bcd);
|
2021-01-08 20:09:02 +00:00
|
|
|
if (!smf_bearer_cycle(bearer)) {
|
|
|
|
ogs_warn("[%s] Bearer has already been removed", smf_ue->imsi_bcd);
|
|
|
|
break;
|
|
|
|
}
|
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-11-07 22:27:12 +00:00
|
|
|
break;
|
2022-04-12 22:07:39 +00:00
|
|
|
case OGS_GTP2_UPDATE_BEARER_REQUEST_TYPE:
|
2020-11-07 22:27:12 +00:00
|
|
|
ogs_error("[%s] No Update Bearer Response", smf_ue->imsi_bcd);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
ogs_error("GTP Timeout : IMSI[%s] Message-Type[%d]",
|
|
|
|
smf_ue->imsi_bcd, type);
|
|
|
|
break;
|
|
|
|
}
|
2020-04-26 19:36:05 +00:00
|
|
|
}
|
|
|
|
|
2020-09-21 03:35:10 +00:00
|
|
|
/*
|
|
|
|
* Issue #338
|
|
|
|
*
|
2024-02-17 19:40:08 +00:00
|
|
|
* <DOWNLINK/BI-DIRECTIONAL>
|
2020-09-21 03:35:10 +00:00
|
|
|
* RULE : Source <P-CSCF_RTP_IP> <P-CSCF_RTP_PORT> Destination <UE_IP> <UE_PORT>
|
|
|
|
* TFT : Local <UE_IP> <UE_PORT> REMOTE <P-CSCF_RTP_IP> <P-CSCF_RTP_PORT>
|
|
|
|
*
|
|
|
|
* <UPLINK>
|
|
|
|
* RULE : Source <UE_IP> <UE_PORT> Destination <P-CSCF_RTP_IP> <P-CSCF_RTP_PORT>
|
|
|
|
* TFT : Local <UE_IP> <UE_PORT> REMOTE <P-CSCF_RTP_IP> <P-CSCF_RTP_PORT>
|
|
|
|
*/
|
2020-04-26 19:36:05 +00:00
|
|
|
static void encode_traffic_flow_template(
|
2022-04-12 22:07:39 +00:00
|
|
|
ogs_gtp2_tft_t *tft, smf_bearer_t *bearer, uint8_t tft_operation_code)
|
2020-04-26 19:36:05 +00:00
|
|
|
{
|
2021-01-01 02:07:08 +00:00
|
|
|
int i;
|
2020-04-26 19:36:05 +00:00
|
|
|
smf_pf_t *pf = NULL;
|
|
|
|
|
|
|
|
ogs_assert(tft);
|
2021-05-28 14:46:48 +00:00
|
|
|
ogs_assert(bearer);
|
2020-04-26 19:36:05 +00:00
|
|
|
|
|
|
|
memset(tft, 0, sizeof(*tft));
|
2021-05-26 19:29:32 +00:00
|
|
|
tft->code = tft_operation_code;
|
2020-04-26 19:36:05 +00:00
|
|
|
|
|
|
|
i = 0;
|
2022-04-12 22:07:39 +00:00
|
|
|
if (tft_operation_code != OGS_GTP2_TFT_CODE_DELETE_EXISTING_TFT &&
|
|
|
|
tft_operation_code != OGS_GTP2_TFT_CODE_NO_TFT_OPERATION) {
|
2021-05-28 14:46:48 +00:00
|
|
|
ogs_list_for_each_entry(&bearer->pf_to_add_list, pf, to_add_node) {
|
2021-08-07 05:23:20 +00:00
|
|
|
ogs_assert(i < OGS_MAX_NUM_OF_FLOW_IN_GTP);
|
2021-05-26 19:29:32 +00:00
|
|
|
tft->pf[i].identifier = pf->identifier - 1;
|
|
|
|
|
2021-05-28 14:46:48 +00:00
|
|
|
/* Deletion of packet filters
|
|
|
|
* from existing requires only the identifier */
|
2021-05-26 19:29:32 +00:00
|
|
|
if (tft_operation_code !=
|
2022-04-12 22:07:39 +00:00
|
|
|
OGS_GTP2_TFT_CODE_DELETE_PACKET_FILTERS_FROM_EXISTING) {
|
2021-05-26 19:29:32 +00:00
|
|
|
|
|
|
|
tft->pf[i].direction = pf->direction;
|
|
|
|
tft->pf[i].precedence = pf->precedence - 1;
|
2020-04-26 19:36:05 +00:00
|
|
|
|
2021-05-26 19:29:32 +00:00
|
|
|
ogs_pf_content_from_ipfw_rule(
|
2022-02-25 13:11:51 +00:00
|
|
|
pf->direction, &tft->pf[i].content, &pf->ipfw_rule,
|
2023-11-19 10:34:51 +00:00
|
|
|
ogs_global_conf()->parameter.
|
|
|
|
no_ipv4v6_local_addr_in_packet_filter);
|
2021-05-26 19:29:32 +00:00
|
|
|
}
|
2020-04-26 19:36:05 +00:00
|
|
|
|
2021-05-26 19:29:32 +00:00
|
|
|
i++;
|
|
|
|
}
|
2020-04-26 19:36:05 +00:00
|
|
|
}
|
|
|
|
tft->num_of_packet_filter = i;
|
|
|
|
}
|
|
|
|
|
|
|
|
void smf_bearer_binding(smf_sess_t *sess)
|
|
|
|
{
|
|
|
|
int rv;
|
|
|
|
int i, j;
|
|
|
|
|
|
|
|
ogs_assert(sess);
|
|
|
|
|
2021-11-14 12:07:56 +00:00
|
|
|
for (i = 0; i < sess->policy.num_of_pcc_rule; i++) {
|
2020-04-26 19:36:05 +00:00
|
|
|
ogs_gtp_xact_t *xact = NULL;
|
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;
|
2021-11-14 12:07:56 +00:00
|
|
|
ogs_pcc_rule_t *pcc_rule = &sess->policy.pcc_rule[i];
|
2020-04-26 19:36:05 +00:00
|
|
|
|
|
|
|
ogs_assert(pcc_rule);
|
|
|
|
if (pcc_rule->name == NULL) {
|
|
|
|
ogs_error("No PCC Rule Name");
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (pcc_rule->type == OGS_PCC_RULE_TYPE_INSTALL) {
|
2021-11-14 12:07:56 +00:00
|
|
|
bool bearer_created = false;
|
|
|
|
bool qos_presence = false;
|
2020-04-26 19:36:05 +00:00
|
|
|
|
2021-03-29 01:28:08 +00:00
|
|
|
bearer = smf_bearer_find_by_pcc_rule_name(sess, pcc_rule->name);
|
2020-04-26 19:36:05 +00:00
|
|
|
if (!bearer) {
|
2021-11-14 12:07:56 +00:00
|
|
|
ogs_pfcp_pdr_t *dl_pdr = NULL, *ul_pdr = NULL;
|
|
|
|
|
2020-04-26 19:36:05 +00:00
|
|
|
if (pcc_rule->num_of_flow == 0) {
|
|
|
|
/* TFT is mandatory in
|
|
|
|
* activate dedicated EPS bearer context request */
|
|
|
|
ogs_error("No flow in PCC Rule");
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2021-11-23 05:19:30 +00:00
|
|
|
if (ogs_list_count(&sess->bearer_list) >=
|
|
|
|
OGS_MAX_NUM_OF_BEARER) {
|
|
|
|
ogs_error("Bearer Overflow[%d]",
|
|
|
|
ogs_list_count(&sess->bearer_list));
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2020-04-26 19:36:05 +00:00
|
|
|
bearer = smf_bearer_add(sess);
|
|
|
|
ogs_assert(bearer);
|
|
|
|
|
2021-03-15 01:01:55 +00:00
|
|
|
dl_pdr = bearer->dl_pdr;
|
|
|
|
ogs_assert(dl_pdr);
|
|
|
|
ul_pdr = bearer->ul_pdr;
|
|
|
|
ogs_assert(ul_pdr);
|
|
|
|
|
2020-04-26 19:36:05 +00:00
|
|
|
/* Precedence is set to the order in which it was created */
|
2021-03-15 01:01:55 +00:00
|
|
|
dl_pdr->precedence = dl_pdr->id;
|
|
|
|
ul_pdr->precedence = ul_pdr->id;
|
|
|
|
|
|
|
|
ogs_assert(sess->pfcp_node);
|
|
|
|
if (sess->pfcp_node->up_function_features.ftup) {
|
2022-06-24 06:16:54 +00:00
|
|
|
|
|
|
|
/* TS 129 244 V16.5.0 8.2.3
|
|
|
|
*
|
|
|
|
* At least one of the V4 and V6 flags shall be set to "1",
|
|
|
|
* and both may be set to "1" for both scenarios:
|
|
|
|
*
|
|
|
|
* - when the CP function is providing F-TEID, i.e.
|
|
|
|
* both IPv4 address field and IPv6 address field may be present;
|
|
|
|
* or
|
|
|
|
* - when the UP function is requested to allocate the F-TEID,
|
|
|
|
* i.e. when CHOOSE bit is set to "1",
|
|
|
|
* and the IPv4 address and IPv6 address fields are not present.
|
|
|
|
*/
|
|
|
|
|
|
|
|
ul_pdr->f_teid.ipv4 = 1;
|
|
|
|
ul_pdr->f_teid.ipv6 = 1;
|
2021-03-15 01:01:55 +00:00
|
|
|
ul_pdr->f_teid.ch = 1;
|
|
|
|
ul_pdr->f_teid_len = 1;
|
|
|
|
} else {
|
2021-05-30 11:35:30 +00:00
|
|
|
ogs_gtpu_resource_t *resource = NULL;
|
|
|
|
resource = ogs_pfcp_find_gtpu_resource(
|
2021-03-15 01:01:55 +00:00
|
|
|
&sess->pfcp_node->gtpu_resource_list,
|
[GTP-U] Fixed ogs_pfcp_find_gtpu_resource()(#2923)
As mentioned in the sgwu.yaml configuration file, it is possible to configure multiple addresses with different source_interface values for the gtpu interface.
Following the this section, I defined two addresses, one with source_interface set to 0 and another with source_interface set to 1. My expectation was to see different addresses for the two PDRs in the Session Establishment Response message during session establishment. However, both addresses were the same, and it was the address I had set for source_interface = 0.
When I looked into the code, I found the reason for the issue. In the lib/pfcp/context.c file, on line 1185, the function that determines the address is called as follows:
...
} else {
ogs_gtpu_resource_t *resource = NULL;
resource = ogs_pfcp_find_gtpu_resource(
&ogs_gtp_self()->gtpu_resource_list,
pdr->dnn, OGS_PFCP_INTERFACE_ACCESS);
if (resource) {
...
In the last parameter of this function, a constant value, OGS_PFCP_INTERFACE_ACCESS, is used. This causes every PDR with any source_interface to be considered as "access," and the value 0 is used for its interface.
I replaced the value with pdr->src_if, and the bug was resolved.
2024-01-30 13:37:48 +00:00
|
|
|
sess->session.name, ul_pdr->src_if);
|
2021-03-15 01:01:55 +00:00
|
|
|
if (resource) {
|
|
|
|
ogs_user_plane_ip_resource_info_to_sockaddr(
|
|
|
|
&resource->info,
|
|
|
|
&bearer->pgw_s5u_addr, &bearer->pgw_s5u_addr6);
|
|
|
|
if (resource->info.teidri)
|
|
|
|
bearer->pgw_s5u_teid = OGS_PFCP_GTPU_INDEX_TO_TEID(
|
2023-04-09 01:34:19 +00:00
|
|
|
ul_pdr->teid, resource->info.teidri,
|
2021-03-15 01:01:55 +00:00
|
|
|
resource->info.teid_range);
|
|
|
|
else
|
2023-04-09 01:34:19 +00:00
|
|
|
bearer->pgw_s5u_teid = ul_pdr->teid;
|
2021-03-15 01:01:55 +00:00
|
|
|
} else {
|
|
|
|
if (sess->pfcp_node->addr.ogs_sa_family == AF_INET)
|
2021-06-06 13:35:46 +00:00
|
|
|
ogs_assert(OGS_OK ==
|
|
|
|
ogs_copyaddrinfo(&bearer->pgw_s5u_addr,
|
|
|
|
&sess->pfcp_node->addr));
|
2021-03-15 01:01:55 +00:00
|
|
|
else if (sess->pfcp_node->addr.ogs_sa_family ==
|
|
|
|
AF_INET6)
|
2021-06-06 13:35:46 +00:00
|
|
|
ogs_assert(OGS_OK ==
|
|
|
|
ogs_copyaddrinfo(&bearer->pgw_s5u_addr6,
|
|
|
|
&sess->pfcp_node->addr));
|
2021-03-15 01:01:55 +00:00
|
|
|
else
|
|
|
|
ogs_assert_if_reached();
|
|
|
|
|
2023-04-09 01:34:19 +00:00
|
|
|
bearer->pgw_s5u_teid = ul_pdr->teid;
|
2021-03-15 01:01:55 +00:00
|
|
|
}
|
|
|
|
|
2021-05-30 11:35:30 +00:00
|
|
|
ogs_assert(OGS_OK ==
|
|
|
|
ogs_pfcp_sockaddr_to_f_teid(
|
|
|
|
bearer->pgw_s5u_addr, bearer->pgw_s5u_addr6,
|
|
|
|
&ul_pdr->f_teid, &ul_pdr->f_teid_len));
|
2021-03-15 01:01:55 +00:00
|
|
|
ul_pdr->f_teid.teid = bearer->pgw_s5u_teid;
|
|
|
|
}
|
2020-04-26 19:36:05 +00:00
|
|
|
|
2021-01-01 02:07:08 +00:00
|
|
|
bearer->pcc_rule.name = ogs_strdup(pcc_rule->name);
|
|
|
|
ogs_assert(bearer->pcc_rule.name);
|
2020-04-26 19:36:05 +00:00
|
|
|
|
|
|
|
memcpy(&bearer->qos, &pcc_rule->qos, sizeof(ogs_qos_t));
|
|
|
|
|
2021-11-14 12:07:56 +00:00
|
|
|
bearer_created = true;
|
2020-08-13 00:31:22 +00:00
|
|
|
|
2020-04-26 19:36:05 +00:00
|
|
|
} else {
|
2021-01-01 02:07:08 +00:00
|
|
|
ogs_assert(strcmp(bearer->pcc_rule.name, pcc_rule->name) == 0);
|
2020-04-26 19:36:05 +00:00
|
|
|
|
|
|
|
if ((pcc_rule->qos.mbr.downlink &&
|
|
|
|
bearer->qos.mbr.downlink != pcc_rule->qos.mbr.downlink) ||
|
|
|
|
(pcc_rule->qos.mbr.uplink &&
|
|
|
|
bearer->qos.mbr.uplink != pcc_rule->qos.mbr.uplink) ||
|
|
|
|
(pcc_rule->qos.gbr.downlink &&
|
|
|
|
bearer->qos.gbr.downlink != pcc_rule->qos.gbr.downlink) ||
|
|
|
|
(pcc_rule->qos.gbr.uplink &&
|
|
|
|
bearer->qos.gbr.uplink != pcc_rule->qos.gbr.uplink)) {
|
|
|
|
/* Update QoS parameter */
|
|
|
|
memcpy(&bearer->qos, &pcc_rule->qos, sizeof(ogs_qos_t));
|
|
|
|
|
|
|
|
/* Update Bearer Request encodes updated QoS parameter */
|
2021-11-14 12:07:56 +00:00
|
|
|
qos_presence = true;
|
2020-04-26 19:36:05 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-05-15 14:35:41 +00:00
|
|
|
/*
|
|
|
|
* We only use the method of adding a flow to an existing tft.
|
|
|
|
*
|
|
|
|
* EPC: OGS_GTP2_TFT_CODE_ADD_PACKET_FILTERS_TO_EXISTING_TFT
|
|
|
|
* 5GC: OGS_NAS_QOS_CODE_MODIFY_EXISTING_QOS_RULE_AND_ADD_PACKET_FILTERS
|
|
|
|
*/
|
2021-05-28 14:46:48 +00:00
|
|
|
ogs_list_init(&bearer->pf_to_add_list);
|
|
|
|
|
2020-04-26 19:36:05 +00:00
|
|
|
for (j = 0; j < pcc_rule->num_of_flow; j++) {
|
|
|
|
smf_pf_t *pf = NULL;
|
2021-11-14 12:07:56 +00:00
|
|
|
ogs_flow_t *flow = &pcc_rule->flow[j];
|
2020-04-26 19:36:05 +00:00
|
|
|
|
2023-01-23 15:01:36 +00:00
|
|
|
if (!flow) {
|
|
|
|
ogs_error("No Flow");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (!flow->description) {
|
|
|
|
ogs_error("No Flow-Description");
|
|
|
|
return;
|
|
|
|
}
|
2020-04-26 19:36:05 +00:00
|
|
|
|
2021-11-14 12:07:56 +00:00
|
|
|
/*
|
|
|
|
* To add a flow to an existing tft.
|
|
|
|
* duplicated flows are not added
|
|
|
|
*/
|
2021-05-28 14:46:48 +00:00
|
|
|
if (smf_pf_find_by_flow(
|
|
|
|
bearer, flow->direction, flow->description) != NULL) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2021-11-14 12:07:56 +00:00
|
|
|
/*
|
|
|
|
* To add a flow to an existing tft.
|
|
|
|
*
|
|
|
|
* Only new flows are added to the PF list.
|
|
|
|
* Then, in the PF list, there are all flows
|
|
|
|
* from the beginning to the present.
|
|
|
|
*/
|
2021-01-01 02:07:08 +00:00
|
|
|
pf = smf_pf_add(bearer);
|
2021-08-07 05:23:20 +00:00
|
|
|
if (!pf) {
|
|
|
|
ogs_error("Overflow: PacketFilter in Bearer");
|
|
|
|
break;
|
|
|
|
}
|
2020-04-26 19:36:05 +00:00
|
|
|
|
|
|
|
pf->direction = flow->direction;
|
2020-08-13 00:31:22 +00:00
|
|
|
pf->flow_description = ogs_strdup(flow->description);
|
2021-06-06 13:35:46 +00:00
|
|
|
ogs_assert(pf->flow_description);
|
2020-09-21 03:35:10 +00:00
|
|
|
|
2020-08-13 00:31:22 +00:00
|
|
|
rv = ogs_ipfw_compile_rule(
|
|
|
|
&pf->ipfw_rule, pf->flow_description);
|
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
|
|
|
* GX : permit out from <P-CSCF_RTP_IP> <P-CSCF_RTP_PORT> to <UE_IP> <UE_PORT>
|
|
|
|
* -->
|
|
|
|
* RULE : Source <P-CSCF_RTP_IP> <P-CSCF_RTP_PORT> Destination <UE_IP> <UE_PORT>
|
|
|
|
*
|
|
|
|
* <UPLINK>
|
|
|
|
* GX : permit out from <P-CSCF_RTP_IP> <P-CSCF_RTP_PORT> to <UE_IP> <UE_PORT>
|
|
|
|
* -->
|
|
|
|
* RULE : Source <UE_IP> <UE_PORT> Destination <P-CSCF_RTP_IP> <P-CSCF_RTP_PORT>
|
|
|
|
*/
|
|
|
|
if (flow->direction == OGS_FLOW_UPLINK_ONLY)
|
|
|
|
ogs_ipfw_rule_swap(&pf->ipfw_rule);
|
|
|
|
|
2020-08-13 00:31:22 +00:00
|
|
|
if (rv != OGS_OK) {
|
|
|
|
ogs_error("Invalid Flow-Description[%s]",
|
|
|
|
pf->flow_description);
|
|
|
|
smf_pf_remove(pf);
|
|
|
|
break;
|
|
|
|
}
|
2021-05-26 19:29:32 +00:00
|
|
|
|
2021-11-14 12:07:56 +00:00
|
|
|
/*
|
|
|
|
* To add a flow to an existing tft.
|
|
|
|
*
|
|
|
|
* 'pf_to_add_list' now has the added flow.
|
|
|
|
*/
|
2021-05-28 14:46:48 +00:00
|
|
|
ogs_list_add(&bearer->pf_to_add_list, &pf->to_add_node);
|
2020-04-26 19:36:05 +00:00
|
|
|
}
|
|
|
|
|
2021-11-14 12:07:56 +00:00
|
|
|
if (bearer_created == false &&
|
|
|
|
qos_presence == false &&
|
|
|
|
ogs_list_count(&bearer->pf_to_add_list) == 0) {
|
2022-01-12 11:06:26 +00:00
|
|
|
ogs_warn("No need to send 'Update Bearer Request'");
|
|
|
|
ogs_warn("bearer_created:%d, qos_presence:%d, rule_count:%d",
|
2021-11-14 12:07:56 +00:00
|
|
|
bearer_created, qos_presence,
|
|
|
|
ogs_list_count(&bearer->pf_to_add_list));
|
|
|
|
continue;
|
|
|
|
}
|
2020-10-26 02:43:53 +00:00
|
|
|
|
2021-11-14 12:07:56 +00:00
|
|
|
if (bearer_created == true) {
|
2020-10-26 02:43:53 +00:00
|
|
|
|
2021-11-14 12:07:56 +00:00
|
|
|
smf_bearer_tft_update(bearer);
|
|
|
|
smf_bearer_qos_update(bearer);
|
2020-04-26 19:36:05 +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_CREATE,
|
|
|
|
OGS_NAS_PROCEDURE_TRANSACTION_IDENTITY_UNASSIGNED,
|
2022-04-12 22:07:39 +00:00
|
|
|
OGS_GTP2_CAUSE_UNDEFINED_VALUE));
|
2020-10-26 02:43:53 +00:00
|
|
|
} else {
|
2022-04-12 22:07:39 +00:00
|
|
|
ogs_gtp2_tft_t tft;
|
2020-04-26 19:36:05 +00:00
|
|
|
|
2020-10-26 02:43:53 +00:00
|
|
|
memset(&tft, 0, sizeof tft);
|
2021-11-14 12:07:56 +00:00
|
|
|
if (ogs_list_count(&bearer->pf_to_add_list) > 0) {
|
2021-05-26 19:29:32 +00:00
|
|
|
encode_traffic_flow_template(
|
2021-05-28 14:46:48 +00:00
|
|
|
&tft, bearer,
|
2022-04-12 22:07:39 +00:00
|
|
|
OGS_GTP2_TFT_CODE_ADD_PACKET_FILTERS_TO_EXISTING_TFT);
|
2021-08-07 05:23:20 +00:00
|
|
|
}
|
2021-05-26 19:29:32 +00:00
|
|
|
|
2022-04-12 22:07:39 +00:00
|
|
|
memset(&h, 0, sizeof(ogs_gtp2_header_t));
|
|
|
|
h.type = OGS_GTP2_UPDATE_BEARER_REQUEST_TYPE;
|
[GTP/PFCP]] incorrect dst TEI=0/SEID=0 (#3043)
If eg. PCRF or AAA diameter link is not yet ready (eg. PCRF crashed), and
a client sends a CreateSessionRequest announcing its ow F-TEID,
then open5gs-smfd answers with Create Session Response Cause=
"Remote peer not responding", but it is not setting the received F-TEID
in the header of the response, instead it sends with TEI=0.
As a result, the peer cannot match the CreateSessionResponse, and needs
to rely on its own timeout timer to figure out that specific request failed.
This also happens in PFCP, so to solve this problem, I added teid/seid_presence
to the interface that sends the error message as shown below.
void ogs_gtp2_send_error_message(ogs_gtp_xact_t *xact,
int teid_presence, uint32_t teid, uint8_t type, uint8_t cause_value);
void ogs_pfcp_send_error_message(
ogs_pfcp_xact_t *xact, int seid_presence, uint64_t seid, uint8_t type,
uint8_t cause_value, uint16_t offending_ie_value);
2024-03-23 01:00:08 +00:00
|
|
|
h.teid_presence = OGS_GTP2_TEID_PRESENCE;
|
2020-04-26 19:36:05 +00:00
|
|
|
h.teid = sess->sgw_s5c_teid;
|
|
|
|
|
|
|
|
pkbuf = smf_s5c_build_update_bearer_request(
|
|
|
|
h.type, bearer,
|
|
|
|
OGS_NAS_PROCEDURE_TRANSACTION_IDENTITY_UNASSIGNED,
|
2021-11-14 12:07:56 +00:00
|
|
|
(ogs_list_count(&bearer->pf_to_add_list) > 0) ?
|
|
|
|
&tft : NULL, qos_presence);
|
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
|
|
|
xact = ogs_gtp_xact_local_create(
|
2022-05-15 14:35:41 +00:00
|
|
|
sess->gnode, &h, pkbuf, gtp_bearer_timeout, bearer);
|
2023-01-23 15:01:36 +00:00
|
|
|
if (!xact) {
|
|
|
|
ogs_error("ogs_gtp_xact_local_create() failed");
|
|
|
|
return;
|
|
|
|
}
|
2022-06-30 01:53:19 +00:00
|
|
|
xact->local_teid = sess->smf_n4_teid;
|
2020-08-13 00:31:22 +00:00
|
|
|
|
2021-11-14 12:07:56 +00:00
|
|
|
if (ogs_list_count(&bearer->pf_to_add_list) > 0)
|
2020-08-13 00:31:22 +00:00
|
|
|
xact->update_flags |= OGS_GTP_MODIFY_TFT_UPDATE;
|
2021-11-14 12:07:56 +00:00
|
|
|
if (qos_presence == true)
|
2020-08-13 00:31:22 +00:00
|
|
|
xact->update_flags |= OGS_GTP_MODIFY_QOS_UPDATE;
|
2020-04-26 19:36:05 +00:00
|
|
|
|
2020-10-26 02:43:53 +00:00
|
|
|
rv = ogs_gtp_xact_commit(xact);
|
|
|
|
ogs_expect(rv == OGS_OK);
|
|
|
|
}
|
2020-08-13 00:31:22 +00:00
|
|
|
|
2020-04-26 19:36:05 +00:00
|
|
|
} else if (pcc_rule->type == OGS_PCC_RULE_TYPE_REMOVE) {
|
2021-01-01 02:07:08 +00:00
|
|
|
bearer = smf_bearer_find_by_pcc_rule_name(sess, pcc_rule->name);
|
2020-04-26 19:36:05 +00:00
|
|
|
|
|
|
|
if (!bearer) {
|
|
|
|
ogs_warn("No need to send 'Delete Bearer Request'");
|
|
|
|
ogs_warn(" - Bearer[Name:%s] has already been removed.",
|
|
|
|
pcc_rule->name);
|
2020-08-29 14:53:02 +00:00
|
|
|
continue;
|
2020-04-26 19:36:05 +00:00
|
|
|
}
|
|
|
|
|
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).
|
|
|
|
*/
|
2021-06-21 13:36:38 +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_DL_ONLY|OGS_PFCP_MODIFY_DEACTIVATE,
|
|
|
|
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
|
|
|
} else {
|
|
|
|
ogs_error("Invalid Type[%d]", pcc_rule->type);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2020-10-26 02:43:53 +00:00
|
|
|
|
2022-05-12 13:52:36 +00:00
|
|
|
int smf_gtp2_send_create_bearer_request(smf_bearer_t *bearer)
|
2020-10-26 02:43:53 +00:00
|
|
|
{
|
|
|
|
int rv;
|
|
|
|
|
|
|
|
smf_sess_t *sess = NULL;
|
|
|
|
ogs_gtp_xact_t *xact = NULL;
|
|
|
|
|
2022-04-12 22:07:39 +00:00
|
|
|
ogs_gtp2_header_t h;
|
2020-10-26 02:43:53 +00:00
|
|
|
ogs_pkbuf_t *pkbuf = NULL;
|
2022-04-12 22:07:39 +00:00
|
|
|
ogs_gtp2_tft_t tft;
|
2020-10-26 02:43:53 +00:00
|
|
|
|
|
|
|
ogs_assert(bearer);
|
|
|
|
sess = bearer->sess;
|
|
|
|
ogs_assert(sess);
|
|
|
|
|
2022-04-12 22:07:39 +00:00
|
|
|
h.type = OGS_GTP2_CREATE_BEARER_REQUEST_TYPE;
|
[GTP/PFCP]] incorrect dst TEI=0/SEID=0 (#3043)
If eg. PCRF or AAA diameter link is not yet ready (eg. PCRF crashed), and
a client sends a CreateSessionRequest announcing its ow F-TEID,
then open5gs-smfd answers with Create Session Response Cause=
"Remote peer not responding", but it is not setting the received F-TEID
in the header of the response, instead it sends with TEI=0.
As a result, the peer cannot match the CreateSessionResponse, and needs
to rely on its own timeout timer to figure out that specific request failed.
This also happens in PFCP, so to solve this problem, I added teid/seid_presence
to the interface that sends the error message as shown below.
void ogs_gtp2_send_error_message(ogs_gtp_xact_t *xact,
int teid_presence, uint32_t teid, uint8_t type, uint8_t cause_value);
void ogs_pfcp_send_error_message(
ogs_pfcp_xact_t *xact, int seid_presence, uint64_t seid, uint8_t type,
uint8_t cause_value, uint16_t offending_ie_value);
2024-03-23 01:00:08 +00:00
|
|
|
h.teid_presence = OGS_GTP2_TEID_PRESENCE;
|
2020-10-26 02:43:53 +00:00
|
|
|
h.teid = sess->sgw_s5c_teid;
|
|
|
|
|
|
|
|
memset(&tft, 0, sizeof tft);
|
2022-05-15 14:35:41 +00:00
|
|
|
encode_traffic_flow_template(
|
|
|
|
&tft, bearer, OGS_GTP2_TFT_CODE_CREATE_NEW_TFT);
|
2020-10-26 02:43:53 +00:00
|
|
|
|
|
|
|
pkbuf = smf_s5c_build_create_bearer_request(h.type, bearer, &tft);
|
2023-01-23 15:01:36 +00:00
|
|
|
if (!pkbuf) {
|
|
|
|
ogs_error("smf_s5c_build_create_bearer_request() failed");
|
|
|
|
return OGS_ERROR;
|
|
|
|
}
|
2020-10-26 02:43:53 +00:00
|
|
|
|
2020-11-07 22:27:12 +00:00
|
|
|
xact = ogs_gtp_xact_local_create(
|
2022-05-15 14:35:41 +00:00
|
|
|
sess->gnode, &h, pkbuf, gtp_bearer_timeout, bearer);
|
2023-01-23 15:01:36 +00:00
|
|
|
if (!xact) {
|
|
|
|
ogs_error("ogs_gtp_xact_local_create() failed");
|
|
|
|
return OGS_ERROR;
|
|
|
|
}
|
2022-06-30 01:53:19 +00:00
|
|
|
xact->local_teid = sess->smf_n4_teid;
|
2020-10-26 02:43:53 +00:00
|
|
|
|
|
|
|
rv = ogs_gtp_xact_commit(xact);
|
|
|
|
ogs_expect(rv == OGS_OK);
|
2021-06-06 13:35:46 +00:00
|
|
|
|
|
|
|
return rv;
|
2020-10-26 02:43:53 +00:00
|
|
|
}
|
2021-01-01 02:07:08 +00:00
|
|
|
|
2021-11-14 12:07:56 +00:00
|
|
|
void smf_qos_flow_binding(smf_sess_t *sess)
|
2021-01-01 02:07:08 +00:00
|
|
|
{
|
|
|
|
int rv;
|
|
|
|
int i, j;
|
|
|
|
|
2022-05-15 14:35:41 +00:00
|
|
|
uint64_t pfcp_flags, check;
|
|
|
|
|
2021-01-01 02:07:08 +00:00
|
|
|
ogs_assert(sess);
|
|
|
|
|
2022-05-15 14:35:41 +00:00
|
|
|
pfcp_flags = OGS_PFCP_MODIFY_NETWORK_REQUESTED;
|
|
|
|
|
|
|
|
ogs_list_init(&sess->qos_flow_to_modify_list);
|
|
|
|
|
2021-11-14 12:07:56 +00:00
|
|
|
for (i = 0; i < sess->policy.num_of_pcc_rule; i++) {
|
2021-01-01 02:07:08 +00:00
|
|
|
smf_bearer_t *qos_flow = NULL;
|
2021-11-14 12:07:56 +00:00
|
|
|
ogs_pcc_rule_t *pcc_rule = &sess->policy.pcc_rule[i];
|
2021-01-01 02:07:08 +00:00
|
|
|
|
|
|
|
ogs_assert(pcc_rule);
|
|
|
|
if (pcc_rule->id == NULL) {
|
|
|
|
ogs_error("No PCC Rule Id");
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (pcc_rule->type == OGS_PCC_RULE_TYPE_INSTALL) {
|
2021-11-14 12:07:56 +00:00
|
|
|
smf_pf_t *pf = NULL;
|
2021-01-01 02:07:08 +00:00
|
|
|
ogs_pfcp_pdr_t *dl_pdr = NULL, *ul_pdr = NULL;
|
|
|
|
|
2021-11-14 12:07:56 +00:00
|
|
|
bool qos_flow_created = false;
|
|
|
|
bool qos_presence = false;
|
|
|
|
|
2021-03-29 01:28:08 +00:00
|
|
|
qos_flow = smf_qos_flow_find_by_pcc_rule_id(sess, pcc_rule->id);
|
2021-01-01 02:07:08 +00:00
|
|
|
if (!qos_flow) {
|
|
|
|
if (pcc_rule->num_of_flow == 0) {
|
|
|
|
/* TFT is mandatory in
|
|
|
|
* activate dedicated EPS bearer context request */
|
|
|
|
ogs_error("No flow in PCC Rule");
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2021-11-23 05:19:30 +00:00
|
|
|
if (ogs_list_count(&sess->bearer_list) >=
|
|
|
|
OGS_MAX_NUM_OF_BEARER) {
|
|
|
|
ogs_error("QosFlow Overflow[%d]",
|
|
|
|
ogs_list_count(&sess->bearer_list));
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2021-01-01 02:07:08 +00:00
|
|
|
qos_flow = smf_qos_flow_add(sess);
|
|
|
|
ogs_assert(qos_flow);
|
|
|
|
|
|
|
|
dl_pdr = qos_flow->dl_pdr;
|
|
|
|
ogs_assert(dl_pdr);
|
|
|
|
ul_pdr = qos_flow->ul_pdr;
|
|
|
|
ogs_assert(ul_pdr);
|
|
|
|
|
|
|
|
/* Precedence is derived from PCC Rule Precedence */
|
|
|
|
dl_pdr->precedence = pcc_rule->precedence;
|
|
|
|
ul_pdr->precedence = pcc_rule->precedence;
|
|
|
|
|
|
|
|
/* Set UPF-N3 TEID & ADDR to the UL PDR */
|
|
|
|
ogs_assert(sess->pfcp_node);
|
|
|
|
if (sess->pfcp_node->up_function_features.ftup) {
|
2022-06-24 06:16:54 +00:00
|
|
|
|
|
|
|
/* TS 129 244 V16.5.0 8.2.3
|
|
|
|
*
|
|
|
|
* At least one of the V4 and V6 flags shall be set to "1",
|
|
|
|
* and both may be set to "1" for both scenarios:
|
|
|
|
*
|
|
|
|
* - when the CP function is providing F-TEID, i.e.
|
|
|
|
* both IPv4 address field and IPv6 address field may be present;
|
|
|
|
* or
|
|
|
|
* - when the UP function is requested to allocate the F-TEID,
|
|
|
|
* i.e. when CHOOSE bit is set to "1",
|
|
|
|
* and the IPv4 address and IPv6 address fields are not present.
|
|
|
|
*/
|
|
|
|
|
|
|
|
ul_pdr->f_teid.ipv4 = 1;
|
|
|
|
ul_pdr->f_teid.ipv6 = 1;
|
2021-01-01 02:07:08 +00:00
|
|
|
ul_pdr->f_teid.ch = 1;
|
|
|
|
ul_pdr->f_teid.chid = 1;
|
|
|
|
ul_pdr->f_teid.choose_id = OGS_PFCP_DEFAULT_CHOOSE_ID;
|
|
|
|
ul_pdr->f_teid_len = 2;
|
|
|
|
} else {
|
2021-05-30 11:35:30 +00:00
|
|
|
ogs_assert(OGS_OK ==
|
|
|
|
ogs_pfcp_sockaddr_to_f_teid(
|
2021-01-01 02:07:08 +00:00
|
|
|
sess->upf_n3_addr, sess->upf_n3_addr6,
|
2021-05-30 11:35:30 +00:00
|
|
|
&ul_pdr->f_teid, &ul_pdr->f_teid_len));
|
2021-01-01 02:07:08 +00:00
|
|
|
ul_pdr->f_teid.teid = sess->upf_n3_teid;
|
|
|
|
}
|
|
|
|
|
|
|
|
qos_flow->pcc_rule.id = ogs_strdup(pcc_rule->id);
|
|
|
|
ogs_assert(qos_flow->pcc_rule.id);
|
|
|
|
|
|
|
|
memcpy(&qos_flow->qos, &pcc_rule->qos, sizeof(ogs_qos_t));
|
|
|
|
|
2021-11-14 12:07:56 +00:00
|
|
|
qos_flow_created = true;
|
2021-01-01 02:07:08 +00:00
|
|
|
|
|
|
|
} else {
|
|
|
|
ogs_assert(strcmp(qos_flow->pcc_rule.id, pcc_rule->id) == 0);
|
|
|
|
|
|
|
|
if ((pcc_rule->qos.mbr.downlink &&
|
|
|
|
qos_flow->qos.mbr.downlink != pcc_rule->qos.mbr.downlink) ||
|
|
|
|
(pcc_rule->qos.mbr.uplink &&
|
|
|
|
qos_flow->qos.mbr.uplink != pcc_rule->qos.mbr.uplink) ||
|
|
|
|
(pcc_rule->qos.gbr.downlink &&
|
|
|
|
qos_flow->qos.gbr.downlink != pcc_rule->qos.gbr.downlink) ||
|
|
|
|
(pcc_rule->qos.gbr.uplink &&
|
|
|
|
qos_flow->qos.gbr.uplink != pcc_rule->qos.gbr.uplink)) {
|
|
|
|
/* Update QoS parameter */
|
|
|
|
memcpy(&qos_flow->qos, &pcc_rule->qos, sizeof(ogs_qos_t));
|
|
|
|
|
|
|
|
/* Update Bearer Request encodes updated QoS parameter */
|
2021-11-14 12:07:56 +00:00
|
|
|
qos_presence = true;
|
2021-01-01 02:07:08 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-05-15 14:35:41 +00:00
|
|
|
/*
|
|
|
|
* We only use the method of adding a flow to an existing tft.
|
|
|
|
*
|
|
|
|
* EPC: OGS_GTP2_TFT_CODE_ADD_PACKET_FILTERS_TO_EXISTING_TFT
|
|
|
|
* 5GC: OGS_NAS_QOS_CODE_MODIFY_EXISTING_QOS_RULE_AND_ADD_PACKET_FILTERS
|
|
|
|
*/
|
2021-05-28 14:46:48 +00:00
|
|
|
ogs_list_init(&qos_flow->pf_to_add_list);
|
|
|
|
|
2021-01-01 02:07:08 +00:00
|
|
|
for (j = 0; j < pcc_rule->num_of_flow; j++) {
|
|
|
|
ogs_flow_t *flow = &pcc_rule->flow[j];
|
|
|
|
|
2023-01-23 15:01:36 +00:00
|
|
|
if (!flow) {
|
|
|
|
ogs_error("No Flow");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (!flow->description) {
|
|
|
|
ogs_error("No Flow-Description");
|
|
|
|
return;
|
|
|
|
}
|
2021-01-01 02:07:08 +00:00
|
|
|
|
2021-11-14 12:07:56 +00:00
|
|
|
/*
|
|
|
|
* To add a flow to an existing tft.
|
|
|
|
* duplicated flows are not added
|
|
|
|
*/
|
2021-05-28 14:46:48 +00:00
|
|
|
if (smf_pf_find_by_flow(
|
|
|
|
qos_flow, flow->direction, flow->description) != NULL) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2021-11-14 12:07:56 +00:00
|
|
|
/*
|
|
|
|
* To add a flow to an existing tft.
|
|
|
|
*
|
|
|
|
* Only new flows are added to the PF list.
|
|
|
|
* Then, in the PF list, there are all flows
|
|
|
|
* from the beginning to the present.
|
|
|
|
*/
|
2021-01-01 02:07:08 +00:00
|
|
|
pf = smf_pf_add(qos_flow);
|
2021-11-14 12:07:56 +00:00
|
|
|
if (!pf) {
|
|
|
|
ogs_error("Overflow: PacketFilter in Bearer");
|
|
|
|
break;
|
|
|
|
}
|
2021-01-01 02:07:08 +00:00
|
|
|
|
|
|
|
pf->direction = flow->direction;
|
|
|
|
pf->flow_description = ogs_strdup(flow->description);
|
2021-06-06 13:35:46 +00:00
|
|
|
ogs_assert(pf->flow_description);
|
2021-01-01 02:07:08 +00:00
|
|
|
|
|
|
|
rv = ogs_ipfw_compile_rule(
|
|
|
|
&pf->ipfw_rule, pf->flow_description);
|
|
|
|
/*
|
|
|
|
* Refer to lib/ipfw/ogs-ipfw.h
|
|
|
|
* Issue #338
|
|
|
|
*
|
2024-02-17 19:40:08 +00:00
|
|
|
* <DOWNLINK/BI-DIRECTIONAL>
|
2021-01-01 02:07:08 +00:00
|
|
|
* GX : permit out from <P-CSCF_RTP_IP> <P-CSCF_RTP_PORT> to <UE_IP> <UE_PORT>
|
|
|
|
* -->
|
|
|
|
* RULE : Source <P-CSCF_RTP_IP> <P-CSCF_RTP_PORT> Destination <UE_IP> <UE_PORT>
|
|
|
|
*
|
|
|
|
* <UPLINK>
|
|
|
|
* GX : permit out from <P-CSCF_RTP_IP> <P-CSCF_RTP_PORT> to <UE_IP> <UE_PORT>
|
|
|
|
* -->
|
|
|
|
* RULE : Source <UE_IP> <UE_PORT> Destination <P-CSCF_RTP_IP> <P-CSCF_RTP_PORT>
|
|
|
|
*/
|
|
|
|
if (flow->direction == OGS_FLOW_UPLINK_ONLY)
|
|
|
|
ogs_ipfw_rule_swap(&pf->ipfw_rule);
|
|
|
|
|
|
|
|
if (rv != OGS_OK) {
|
|
|
|
ogs_error("Invalid Flow-Description[%s]",
|
|
|
|
pf->flow_description);
|
|
|
|
smf_pf_remove(pf);
|
|
|
|
break;
|
|
|
|
}
|
2021-05-26 19:29:32 +00:00
|
|
|
|
2021-11-14 12:07:56 +00:00
|
|
|
/*
|
|
|
|
* To add a flow to an existing tft.
|
|
|
|
*
|
|
|
|
* 'pf_to_add_list' now has the added flow.
|
|
|
|
*/
|
2021-05-28 14:46:48 +00:00
|
|
|
ogs_list_add(&qos_flow->pf_to_add_list, &pf->to_add_node);
|
2021-01-01 02:07:08 +00:00
|
|
|
}
|
|
|
|
|
2021-11-14 12:07:56 +00:00
|
|
|
if (qos_flow_created == false &&
|
|
|
|
qos_presence == false &&
|
|
|
|
ogs_list_count(&qos_flow->pf_to_add_list) == 0) {
|
2022-01-12 11:06:26 +00:00
|
|
|
ogs_warn("No need to send 'Session Modification Request'");
|
|
|
|
ogs_warn("qos_flow_created:%d, qos_presence:%d, rule_count:%d",
|
2021-11-14 12:07:56 +00:00
|
|
|
qos_flow_created, qos_presence,
|
|
|
|
ogs_list_count(&qos_flow->pf_to_add_list));
|
|
|
|
continue;
|
|
|
|
}
|
2021-01-01 02:07:08 +00:00
|
|
|
|
2021-11-14 12:07:56 +00:00
|
|
|
if (qos_flow_created == true) {
|
|
|
|
smf_bearer_tft_update(qos_flow);
|
|
|
|
smf_bearer_qos_update(qos_flow);
|
2021-01-01 02:07:08 +00:00
|
|
|
|
2022-05-15 14:35:41 +00:00
|
|
|
pfcp_flags |= OGS_PFCP_MODIFY_CREATE;
|
2021-01-01 02:07:08 +00:00
|
|
|
|
2022-05-15 14:35:41 +00:00
|
|
|
ogs_list_add(&sess->qos_flow_to_modify_list,
|
|
|
|
&qos_flow->to_modify_node);
|
2021-01-01 02:07:08 +00:00
|
|
|
} else {
|
2021-11-14 12:07:56 +00:00
|
|
|
pfcp_flags |= OGS_PFCP_MODIFY_NETWORK_REQUESTED;
|
2021-01-01 02:07:08 +00:00
|
|
|
|
2021-11-14 12:07:56 +00:00
|
|
|
if (ogs_list_count(&qos_flow->pf_to_add_list) > 0) {
|
|
|
|
pfcp_flags |= OGS_PFCP_MODIFY_TFT_ADD;
|
|
|
|
smf_bearer_tft_update(qos_flow);
|
|
|
|
}
|
|
|
|
if (qos_presence == true) {
|
|
|
|
pfcp_flags |= OGS_PFCP_MODIFY_QOS_MODIFY;
|
|
|
|
smf_bearer_qos_update(qos_flow);
|
|
|
|
}
|
2021-01-01 02:07:08 +00:00
|
|
|
|
2022-05-15 14:35:41 +00:00
|
|
|
ogs_list_add(&sess->qos_flow_to_modify_list,
|
|
|
|
&qos_flow->to_modify_node);
|
2021-01-01 02:07:08 +00:00
|
|
|
}
|
|
|
|
} else if (pcc_rule->type == OGS_PCC_RULE_TYPE_REMOVE) {
|
2021-11-14 12:07:56 +00:00
|
|
|
qos_flow = smf_qos_flow_find_by_pcc_rule_id(sess, pcc_rule->id);
|
2021-01-01 02:07:08 +00:00
|
|
|
|
|
|
|
if (!qos_flow) {
|
2021-11-14 12:07:56 +00:00
|
|
|
ogs_warn("No need to send 'Session Modification Request'");
|
|
|
|
ogs_warn(" - QosFlow[Id:%s] has already been removed.",
|
|
|
|
pcc_rule->id);
|
2021-01-01 02:07:08 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2022-05-15 14:35:41 +00:00
|
|
|
pfcp_flags |= OGS_PFCP_MODIFY_REMOVE;
|
|
|
|
|
|
|
|
ogs_list_add(&sess->qos_flow_to_modify_list,
|
|
|
|
&qos_flow->to_modify_node);
|
2021-01-01 02:07:08 +00:00
|
|
|
|
|
|
|
} else {
|
|
|
|
ogs_error("Invalid Type[%d]", pcc_rule->type);
|
|
|
|
ogs_assert_if_reached();
|
|
|
|
}
|
|
|
|
}
|
2022-05-15 14:35:41 +00:00
|
|
|
|
|
|
|
check = pfcp_flags & (OGS_PFCP_MODIFY_CREATE|OGS_PFCP_MODIFY_REMOVE);
|
|
|
|
if (check != 0 &&
|
|
|
|
check != OGS_PFCP_MODIFY_CREATE && check != OGS_PFCP_MODIFY_REMOVE) {
|
2022-05-15 14:40:51 +00:00
|
|
|
ogs_fatal("Invalid flags[%d]", (int)pfcp_flags);
|
2022-05-15 14:35:41 +00:00
|
|
|
ogs_assert_if_reached();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ogs_list_count(&sess->qos_flow_to_modify_list)) {
|
|
|
|
ogs_assert(OGS_OK ==
|
2022-05-18 01:29:58 +00:00
|
|
|
smf_5gc_pfcp_send_qos_flow_list_modification_request(
|
2022-05-15 14:35:41 +00:00
|
|
|
sess, NULL, pfcp_flags, 0));
|
|
|
|
}
|
2021-01-01 02:07:08 +00:00
|
|
|
}
|