2024-01-24 14:50:32 +00:00
|
|
|
/* Gx Interface, 3GPP TS 29.212 section 4
|
2024-02-17 19:40:08 +00:00
|
|
|
* Copyright (C) 2019-2024 by Sukchan Lee <acetcom@gmail.com>
|
2022-04-08 23:26:28 +00:00
|
|
|
* Copyright (C) 2022 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de>
|
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 "context.h"
|
|
|
|
#include "gtp-path.h"
|
|
|
|
#include "pfcp-path.h"
|
2022-04-08 23:26:28 +00:00
|
|
|
#include "fd-path.h"
|
2020-04-26 19:36:05 +00:00
|
|
|
#include "gx-handler.h"
|
2021-01-01 02:07:08 +00:00
|
|
|
#include "binding.h"
|
2020-04-26 19:36:05 +00:00
|
|
|
|
2022-04-14 01:30:58 +00:00
|
|
|
/* Returns ER_DIAMETER_SUCCESS on success, Diameter error code on failue. */
|
|
|
|
uint32_t smf_gx_handle_cca_initial_request(
|
2020-04-26 19:36:05 +00:00
|
|
|
smf_sess_t *sess, ogs_diam_gx_message_t *gx_message,
|
|
|
|
ogs_gtp_xact_t *gtp_xact)
|
|
|
|
{
|
|
|
|
int i;
|
2020-07-20 01:42:58 +00:00
|
|
|
|
|
|
|
smf_bearer_t *bearer = NULL;
|
2021-03-15 01:01:55 +00:00
|
|
|
|
2020-08-29 14:53:02 +00:00
|
|
|
ogs_pfcp_pdr_t *dl_pdr = NULL;
|
|
|
|
ogs_pfcp_pdr_t *ul_pdr = NULL;
|
|
|
|
ogs_pfcp_far_t *dl_far = NULL;
|
2020-07-20 01:42:58 +00:00
|
|
|
ogs_pfcp_qer_t *qer = NULL;
|
|
|
|
|
2021-03-15 01:01:55 +00:00
|
|
|
ogs_pfcp_pdr_t *cp2up_pdr = NULL;
|
|
|
|
ogs_pfcp_pdr_t *up2cp_pdr = NULL;
|
|
|
|
ogs_pfcp_far_t *up2cp_far = NULL;
|
|
|
|
|
2020-04-26 19:36:05 +00:00
|
|
|
ogs_assert(sess);
|
|
|
|
ogs_assert(gx_message);
|
|
|
|
ogs_assert(gtp_xact);
|
|
|
|
|
|
|
|
ogs_debug("[PGW] Create Session Response");
|
|
|
|
ogs_debug(" SGW_S5C_TEID[0x%x] PGW_S5C_TEID[0x%x]",
|
|
|
|
sess->sgw_s5c_teid, sess->smf_n4_teid);
|
|
|
|
|
2022-04-14 01:30:58 +00:00
|
|
|
if (gx_message->result_code != ER_DIAMETER_SUCCESS)
|
|
|
|
return gx_message->err ? *gx_message->err :
|
|
|
|
ER_DIAMETER_AUTHENTICATION_REJECTED;
|
|
|
|
|
2022-04-06 14:57:55 +00:00
|
|
|
|
2021-11-14 12:07:56 +00:00
|
|
|
sess->policy.num_of_pcc_rule = gx_message->session_data.num_of_pcc_rule;
|
2021-01-01 02:07:08 +00:00
|
|
|
for (i = 0; i < gx_message->session_data.num_of_pcc_rule; i++)
|
2021-11-14 12:07:56 +00:00
|
|
|
OGS_STORE_PCC_RULE(&sess->policy.pcc_rule[i],
|
2021-01-01 02:07:08 +00:00
|
|
|
&gx_message->session_data.pcc_rule[i]);
|
2020-07-20 01:42:58 +00:00
|
|
|
|
|
|
|
/* APN-AMBR
|
|
|
|
* if PCRF changes APN-AMBR, this should be included. */
|
2021-01-18 16:48:35 +00:00
|
|
|
sess->gtp.create_session_response_apn_ambr = false;
|
2021-03-08 12:25:09 +00:00
|
|
|
if ((gx_message->session_data.session.ambr.uplink &&
|
|
|
|
(sess->session.ambr.uplink / 1000) !=
|
|
|
|
(gx_message->session_data.session.ambr.uplink / 1000)) ||
|
|
|
|
(gx_message->session_data.session.ambr.downlink &&
|
|
|
|
(sess->session.ambr.downlink / 1000) !=
|
|
|
|
(gx_message->session_data.session.ambr.downlink / 1000))) {
|
|
|
|
|
|
|
|
sess->session.ambr.downlink =
|
|
|
|
gx_message->session_data.session.ambr.downlink;
|
|
|
|
sess->session.ambr.uplink =
|
|
|
|
gx_message->session_data.session.ambr.uplink;
|
2020-07-20 01:42:58 +00:00
|
|
|
|
2021-01-18 16:48:35 +00:00
|
|
|
sess->gtp.create_session_response_apn_ambr = true;
|
2020-07-20 01:42:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Bearer QoS
|
|
|
|
* if PCRF changes Bearer QoS, this should be included. */
|
2021-01-18 16:48:35 +00:00
|
|
|
sess->gtp.create_session_response_bearer_qos = false;
|
2021-03-08 12:25:09 +00:00
|
|
|
if ((gx_message->session_data.session.qos.index &&
|
|
|
|
sess->session.qos.index !=
|
|
|
|
gx_message->session_data.session.qos.index) ||
|
|
|
|
(gx_message->session_data.session.qos.arp.priority_level &&
|
|
|
|
sess->session.qos.arp.priority_level !=
|
|
|
|
gx_message->session_data.session.qos.arp.priority_level) ||
|
|
|
|
sess->session.qos.arp.pre_emption_capability !=
|
|
|
|
gx_message->session_data.session.qos.arp.pre_emption_capability ||
|
|
|
|
sess->session.qos.arp.pre_emption_vulnerability !=
|
|
|
|
gx_message->session_data.
|
|
|
|
session.qos.arp.pre_emption_vulnerability) {
|
|
|
|
|
|
|
|
sess->session.qos.index = gx_message->session_data.session.qos.index;
|
|
|
|
sess->session.qos.arp.priority_level =
|
|
|
|
gx_message->session_data.session.qos.arp.priority_level;
|
|
|
|
sess->session.qos.arp.pre_emption_capability =
|
|
|
|
gx_message->session_data.session.qos.arp.pre_emption_capability;
|
|
|
|
sess->session.qos.arp.pre_emption_vulnerability =
|
|
|
|
gx_message->session_data.session.qos.arp.pre_emption_vulnerability;
|
2020-07-20 01:42:58 +00:00
|
|
|
|
2021-01-18 16:48:35 +00:00
|
|
|
sess->gtp.create_session_response_bearer_qos = true;
|
2020-07-20 01:42:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bearer = smf_default_bearer_in_sess(sess);
|
|
|
|
ogs_assert(bearer);
|
|
|
|
|
2021-03-15 01:01:55 +00:00
|
|
|
/* Setup CP/UP Data Forwarding PDR/FAR */
|
|
|
|
smf_sess_create_cp_up_data_forwarding(sess);
|
|
|
|
|
2020-07-20 01:42:58 +00:00
|
|
|
/* Setup QER */
|
2021-03-08 12:25:09 +00:00
|
|
|
if (sess->session.ambr.downlink || sess->session.ambr.uplink) {
|
2020-04-26 19:36:05 +00:00
|
|
|
/* Only 1 QER is used per bearer */
|
2020-08-29 14:53:02 +00:00
|
|
|
qer = bearer->qer;
|
2020-04-26 19:36:05 +00:00
|
|
|
if (!qer) {
|
2020-08-29 14:53:02 +00:00
|
|
|
qer = ogs_pfcp_qer_add(&sess->pfcp);
|
2020-04-26 19:36:05 +00:00
|
|
|
ogs_assert(qer);
|
2020-08-29 14:53:02 +00:00
|
|
|
bearer->qer = qer;
|
2020-04-26 19:36:05 +00:00
|
|
|
}
|
|
|
|
|
2021-03-08 12:25:09 +00:00
|
|
|
qer->mbr.uplink = sess->session.ambr.uplink;
|
|
|
|
qer->mbr.downlink = sess->session.ambr.downlink;
|
2020-07-20 01:42:58 +00:00
|
|
|
}
|
2020-04-26 19:36:05 +00:00
|
|
|
|
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);
|
2021-03-15 01:01:55 +00:00
|
|
|
up2cp_far = sess->up2cp_far;
|
|
|
|
ogs_assert(up2cp_far);
|
2020-07-20 01:42:58 +00:00
|
|
|
|
2020-12-03 06:16:57 +00:00
|
|
|
dl_far->apply_action = OGS_PFCP_APPLY_ACTION_FORW;
|
|
|
|
|
2020-08-29 14:53:02 +00:00
|
|
|
/* Set Outer Header Creation to the Default DL FAR */
|
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-04-26 19:36:05 +00:00
|
|
|
|
2020-07-20 01:42:58 +00:00
|
|
|
/* Setup PDR */
|
2020-08-29 14:53:02 +00:00
|
|
|
dl_pdr = bearer->dl_pdr;
|
|
|
|
ogs_assert(dl_pdr);
|
|
|
|
ul_pdr = bearer->ul_pdr;
|
|
|
|
ogs_assert(ul_pdr);
|
2021-03-15 01:01:55 +00:00
|
|
|
cp2up_pdr = sess->cp2up_pdr;
|
|
|
|
ogs_assert(cp2up_pdr);
|
|
|
|
up2cp_pdr = sess->up2cp_pdr;
|
|
|
|
ogs_assert(up2cp_pdr);
|
2020-08-29 14:53:02 +00:00
|
|
|
|
|
|
|
/* Set UE IP Address to the Default DL PDR */
|
2021-06-06 13:35:46 +00:00
|
|
|
ogs_assert(OGS_OK ==
|
|
|
|
ogs_pfcp_paa_to_ue_ip_addr(&sess->session.paa,
|
|
|
|
&dl_pdr->ue_ip_addr, &dl_pdr->ue_ip_addr_len));
|
2020-08-29 14:53:02 +00:00
|
|
|
dl_pdr->ue_ip_addr.sd = OGS_PFCP_UE_IP_DST;
|
|
|
|
|
2022-07-04 08:37:00 +00:00
|
|
|
ogs_assert(OGS_OK ==
|
|
|
|
ogs_pfcp_paa_to_ue_ip_addr(&sess->session.paa,
|
|
|
|
&ul_pdr->ue_ip_addr, &ul_pdr->ue_ip_addr_len));
|
|
|
|
|
2021-03-15 01:01:55 +00:00
|
|
|
/* Set UE-to-CP Flow-Description and Outer-Header-Creation */
|
2024-02-17 19:40:08 +00:00
|
|
|
up2cp_pdr->flow[up2cp_pdr->num_of_flow].fd = 1;
|
|
|
|
up2cp_pdr->flow[up2cp_pdr->num_of_flow].description =
|
2021-03-15 01:01:55 +00:00
|
|
|
(char *)"permit out 58 from ff02::2/128 to assigned";
|
2024-02-17 19:40:08 +00:00
|
|
|
up2cp_pdr->num_of_flow++;
|
|
|
|
|
2021-06-06 13:35:46 +00:00
|
|
|
ogs_assert(OGS_OK ==
|
|
|
|
ogs_pfcp_ip_to_outer_header_creation(
|
2021-03-15 01:01:55 +00:00
|
|
|
&ogs_gtp_self()->gtpu_ip,
|
|
|
|
&up2cp_far->outer_header_creation,
|
2021-06-06 13:35:46 +00:00
|
|
|
&up2cp_far->outer_header_creation_len));
|
2021-03-15 01:01:55 +00:00
|
|
|
up2cp_far->outer_header_creation.teid = sess->index;
|
|
|
|
|
|
|
|
/* Set F-TEID */
|
|
|
|
ogs_assert(sess->pfcp_node);
|
|
|
|
if (sess->pfcp_node->up_function_features.ftup) {
|
2022-06-24 06:16:54 +00:00
|
|
|
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.chid = 1;
|
|
|
|
ul_pdr->f_teid.choose_id = OGS_PFCP_DEFAULT_CHOOSE_ID;
|
|
|
|
ul_pdr->f_teid_len = 2;
|
|
|
|
|
2022-06-24 06:16:54 +00:00
|
|
|
cp2up_pdr->f_teid.ipv4 = 1;
|
|
|
|
cp2up_pdr->f_teid.ipv6 = 1;
|
2021-03-15 01:01:55 +00:00
|
|
|
cp2up_pdr->f_teid.ch = 1;
|
|
|
|
cp2up_pdr->f_teid_len = 1;
|
|
|
|
|
2022-06-24 06:16:54 +00:00
|
|
|
up2cp_pdr->f_teid.ipv4 = 1;
|
|
|
|
up2cp_pdr->f_teid.ipv6 = 1;
|
2021-03-15 01:01:55 +00:00
|
|
|
up2cp_pdr->f_teid.ch = 1;
|
|
|
|
up2cp_pdr->f_teid.chid = 1;
|
|
|
|
up2cp_pdr->f_teid.choose_id = OGS_PFCP_DEFAULT_CHOOSE_ID;
|
|
|
|
up2cp_pdr->f_teid_len = 2;
|
|
|
|
} 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;
|
|
|
|
|
2021-05-30 11:35:30 +00:00
|
|
|
ogs_assert(OGS_OK ==
|
|
|
|
ogs_pfcp_sockaddr_to_f_teid(
|
2022-04-16 05:08:56 +00:00
|
|
|
bearer->pgw_s5u_addr, bearer->pgw_s5u_addr6,
|
2021-05-30 11:35:30 +00:00
|
|
|
&cp2up_pdr->f_teid, &cp2up_pdr->f_teid_len));
|
2023-04-09 01:34:19 +00:00
|
|
|
cp2up_pdr->f_teid.teid = cp2up_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,
|
|
|
|
&up2cp_pdr->f_teid, &up2cp_pdr->f_teid_len));
|
2021-03-15 01:01:55 +00:00
|
|
|
up2cp_pdr->f_teid.teid = bearer->pgw_s5u_teid;
|
|
|
|
}
|
|
|
|
|
|
|
|
dl_pdr->precedence = OGS_PFCP_DEFAULT_PDR_PRECEDENCE;
|
|
|
|
ul_pdr->precedence = OGS_PFCP_DEFAULT_PDR_PRECEDENCE;
|
|
|
|
|
|
|
|
cp2up_pdr->precedence = OGS_PFCP_CP2UP_PDR_PRECEDENCE;
|
|
|
|
up2cp_pdr->precedence = OGS_PFCP_UP2CP_PDR_PRECEDENCE;
|
2020-08-29 14:53:02 +00:00
|
|
|
|
|
|
|
if (qer) {
|
|
|
|
ogs_pfcp_pdr_associate_qer(dl_pdr, qer);
|
|
|
|
ogs_pfcp_pdr_associate_qer(ul_pdr, qer);
|
2020-07-20 01:42:58 +00:00
|
|
|
}
|
2022-04-14 01:30:58 +00:00
|
|
|
return ER_DIAMETER_SUCCESS;
|
2020-04-26 19:36:05 +00:00
|
|
|
}
|
|
|
|
|
2022-04-20 12:42:18 +00:00
|
|
|
uint32_t smf_gx_handle_cca_termination_request(
|
2020-04-26 19:36:05 +00:00
|
|
|
smf_sess_t *sess, ogs_diam_gx_message_t *gx_message,
|
|
|
|
ogs_gtp_xact_t *gtp_xact)
|
|
|
|
{
|
|
|
|
ogs_assert(sess);
|
|
|
|
ogs_assert(gx_message);
|
|
|
|
|
|
|
|
ogs_debug("[SMF] Delete Session Response");
|
|
|
|
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 ER_DIAMETER_SUCCESS;
|
2020-04-26 19:36:05 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void smf_gx_handle_re_auth_request(
|
|
|
|
smf_sess_t *sess, ogs_diam_gx_message_t *gx_message)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
2021-11-14 12:07:56 +00:00
|
|
|
sess->policy.num_of_pcc_rule = gx_message->session_data.num_of_pcc_rule;
|
2021-01-01 02:07:08 +00:00
|
|
|
for (i = 0; i < gx_message->session_data.num_of_pcc_rule; i++)
|
2021-11-14 12:07:56 +00:00
|
|
|
OGS_STORE_PCC_RULE(&sess->policy.pcc_rule[i],
|
2021-01-01 02:07:08 +00:00
|
|
|
&gx_message->session_data.pcc_rule[i]);
|
2020-04-26 19:36:05 +00:00
|
|
|
|
|
|
|
smf_bearer_binding(sess);
|
|
|
|
}
|