2020-04-26 19:36:05 +00:00
|
|
|
/*
|
|
|
|
* Copyright (C) 2019 by Sukchan Lee <acetcom@gmail.com>
|
|
|
|
*
|
|
|
|
* 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 "pfcp-path.h"
|
2020-06-18 01:43:16 +00:00
|
|
|
#include "gtp-path.h"
|
2020-04-26 19:36:05 +00:00
|
|
|
#include "n4-handler.h"
|
|
|
|
|
2022-04-08 14:10:42 +00:00
|
|
|
static void upf_n4_handle_create_urr(upf_sess_t *sess, ogs_pfcp_tlv_create_urr_t *create_urr_arr,
|
|
|
|
uint8_t *cause_value, uint8_t *offending_ie_value)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
ogs_pfcp_urr_t *urr;
|
|
|
|
|
|
|
|
*cause_value = OGS_PFCP_CAUSE_REQUEST_ACCEPTED;
|
|
|
|
|
|
|
|
for (i = 0; i < OGS_MAX_NUM_OF_URR; i++) {
|
|
|
|
urr = ogs_pfcp_handle_create_urr(&sess->pfcp, &create_urr_arr[i],
|
|
|
|
cause_value, offending_ie_value);
|
|
|
|
if (!urr)
|
|
|
|
return;
|
|
|
|
|
2022-05-24 13:54:30 +00:00
|
|
|
/* TODO: enable counters somewhere else if ISTM not set, upon first pkt received */
|
|
|
|
if (urr->meas_info.istm) {
|
|
|
|
upf_sess_urr_acc_timers_setup(sess, urr);
|
2022-04-08 14:10:42 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-04-26 19:36:05 +00:00
|
|
|
void upf_n4_handle_session_establishment_request(
|
2022-03-15 04:34:32 +00:00
|
|
|
upf_sess_t *sess, ogs_pfcp_xact_t *xact,
|
2020-04-26 19:36:05 +00:00
|
|
|
ogs_pfcp_session_establishment_request_t *req)
|
|
|
|
{
|
2020-07-20 01:42:58 +00:00
|
|
|
ogs_pfcp_pdr_t *pdr = NULL;
|
2020-08-13 00:31:22 +00:00
|
|
|
ogs_pfcp_far_t *far = NULL;
|
2020-04-26 19:36:05 +00:00
|
|
|
ogs_pfcp_pdr_t *created_pdr[OGS_MAX_NUM_OF_PDR];
|
|
|
|
int num_of_created_pdr = 0;
|
|
|
|
uint8_t cause_value = 0;
|
|
|
|
uint8_t offending_ie_value = 0;
|
|
|
|
int i;
|
|
|
|
|
2022-08-19 12:08:27 +00:00
|
|
|
upf_metrics_inst_global_inc(UPF_METR_GLOB_CTR_SM_N4SESSIONESTABREQ);
|
|
|
|
|
2020-04-26 19:36:05 +00:00
|
|
|
ogs_assert(xact);
|
|
|
|
ogs_assert(req);
|
|
|
|
|
2020-07-09 05:38:09 +00:00
|
|
|
ogs_debug("Session Establishment Request");
|
2020-04-26 19:36:05 +00:00
|
|
|
|
|
|
|
cause_value = OGS_PFCP_CAUSE_REQUEST_ACCEPTED;
|
|
|
|
|
|
|
|
if (!sess) {
|
2020-12-03 06:16:57 +00:00
|
|
|
ogs_error("No Context");
|
2020-04-26 19:36:05 +00:00
|
|
|
ogs_pfcp_send_error_message(xact, 0,
|
|
|
|
OGS_PFCP_SESSION_ESTABLISHMENT_RESPONSE_TYPE,
|
2020-12-03 06:16:57 +00:00
|
|
|
OGS_PFCP_CAUSE_MANDATORY_IE_MISSING, 0);
|
2022-08-19 12:08:27 +00:00
|
|
|
upf_metrics_inst_by_cause_add(OGS_PFCP_CAUSE_MANDATORY_IE_MISSING,
|
|
|
|
UPF_METR_CTR_SM_N4SESSIONESTABFAIL, 1);
|
2020-04-26 19:36:05 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0; i < OGS_MAX_NUM_OF_PDR; i++) {
|
2020-08-13 00:31:22 +00:00
|
|
|
created_pdr[i] = ogs_pfcp_handle_create_pdr(&sess->pfcp,
|
2020-04-26 19:36:05 +00:00
|
|
|
&req->create_pdr[i], &cause_value, &offending_ie_value);
|
|
|
|
if (created_pdr[i] == NULL)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
num_of_created_pdr = i;
|
|
|
|
if (cause_value != OGS_PFCP_CAUSE_REQUEST_ACCEPTED)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
for (i = 0; i < OGS_MAX_NUM_OF_FAR; i++) {
|
2020-08-13 00:31:22 +00:00
|
|
|
if (ogs_pfcp_handle_create_far(&sess->pfcp, &req->create_far[i],
|
2020-04-26 19:36:05 +00:00
|
|
|
&cause_value, &offending_ie_value) == NULL)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (cause_value != OGS_PFCP_CAUSE_REQUEST_ACCEPTED)
|
|
|
|
goto cleanup;
|
|
|
|
|
2022-04-08 14:10:42 +00:00
|
|
|
upf_n4_handle_create_urr(sess, &req->create_urr[0], &cause_value, &offending_ie_value);
|
2021-10-04 13:28:32 +00:00
|
|
|
if (cause_value != OGS_PFCP_CAUSE_REQUEST_ACCEPTED)
|
|
|
|
goto cleanup;
|
|
|
|
|
2020-04-26 19:36:05 +00:00
|
|
|
for (i = 0; i < OGS_MAX_NUM_OF_QER; i++) {
|
2020-08-13 00:31:22 +00:00
|
|
|
if (ogs_pfcp_handle_create_qer(&sess->pfcp, &req->create_qer[i],
|
2020-04-26 19:36:05 +00:00
|
|
|
&cause_value, &offending_ie_value) == NULL)
|
|
|
|
break;
|
2022-08-19 12:08:27 +00:00
|
|
|
if (req->apn_dnn.presence == 1) {
|
|
|
|
upf_metrics_inst_by_dnn_add(req->apn_dnn.data,
|
|
|
|
UPF_METR_GAUGE_UPF_QOSFLOWS, 1);
|
|
|
|
} else {
|
|
|
|
upf_metrics_inst_by_dnn_add(NULL,
|
|
|
|
UPF_METR_GAUGE_UPF_QOSFLOWS, 1);
|
|
|
|
}
|
2020-04-26 19:36:05 +00:00
|
|
|
}
|
|
|
|
if (cause_value != OGS_PFCP_CAUSE_REQUEST_ACCEPTED)
|
|
|
|
goto cleanup;
|
|
|
|
|
2020-12-03 06:16:57 +00:00
|
|
|
ogs_pfcp_handle_create_bar(&sess->pfcp, &req->create_bar,
|
|
|
|
&cause_value, &offending_ie_value);
|
|
|
|
if (cause_value != OGS_PFCP_CAUSE_REQUEST_ACCEPTED)
|
|
|
|
goto cleanup;
|
|
|
|
|
2020-08-13 00:31:22 +00:00
|
|
|
/* Setup GTP Node */
|
2021-03-15 01:01:55 +00:00
|
|
|
ogs_list_for_each(&sess->pfcp.far_list, far) {
|
2021-06-06 13:35:46 +00:00
|
|
|
ogs_assert(OGS_ERROR != ogs_pfcp_setup_far_gtpu_node(far));
|
2021-03-15 01:01:55 +00:00
|
|
|
if (far->gnode)
|
|
|
|
ogs_pfcp_far_f_teid_hash_set(far);
|
|
|
|
}
|
2020-08-13 00:31:22 +00:00
|
|
|
|
2020-07-20 01:42:58 +00:00
|
|
|
for (i = 0; i < num_of_created_pdr; i++) {
|
|
|
|
pdr = created_pdr[i];
|
|
|
|
ogs_assert(pdr);
|
|
|
|
|
2020-12-03 06:16:57 +00:00
|
|
|
/* Setup UE IP address */
|
2022-04-14 08:34:55 +00:00
|
|
|
if (pdr->ue_ip_addr_len) {
|
|
|
|
if (req->pdn_type.presence == 1) {
|
2022-06-23 13:04:01 +00:00
|
|
|
cause_value = upf_sess_set_ue_ip(sess, req->pdn_type.u8, pdr);
|
|
|
|
if (cause_value != OGS_PFCP_CAUSE_REQUEST_ACCEPTED)
|
|
|
|
goto cleanup;
|
2022-04-14 08:34:55 +00:00
|
|
|
} else {
|
|
|
|
ogs_error("No PDN Type");
|
|
|
|
}
|
2020-12-03 06:16:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Setup UPF-N3-TEID & QFI Hash */
|
|
|
|
if (pdr->f_teid_len) {
|
2022-04-16 05:08:56 +00:00
|
|
|
ogs_pfcp_object_type_e type = OGS_PFCP_OBJ_SESS_TYPE;
|
2021-03-15 01:01:55 +00:00
|
|
|
|
2020-12-03 06:16:57 +00:00
|
|
|
if (ogs_pfcp_self()->up_function_features.ftup &&
|
|
|
|
pdr->f_teid.ch) {
|
|
|
|
|
|
|
|
ogs_pfcp_pdr_t *choosed_pdr = NULL;
|
|
|
|
|
|
|
|
if (pdr->f_teid.chid) {
|
|
|
|
choosed_pdr = ogs_pfcp_pdr_find_by_choose_id(
|
|
|
|
&sess->pfcp, pdr->f_teid.choose_id);
|
|
|
|
if (!choosed_pdr) {
|
|
|
|
pdr->chid = true;
|
|
|
|
pdr->choose_id = pdr->f_teid.choose_id;
|
|
|
|
}
|
2022-04-16 05:08:56 +00:00
|
|
|
} else {
|
|
|
|
type = OGS_PFCP_OBJ_PDR_TYPE;
|
2020-12-03 06:16:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (choosed_pdr) {
|
|
|
|
pdr->f_teid_len = choosed_pdr->f_teid_len;
|
|
|
|
memcpy(&pdr->f_teid, &choosed_pdr->f_teid, pdr->f_teid_len);
|
2022-04-16 05:08:56 +00:00
|
|
|
|
2020-12-03 06:16:57 +00:00
|
|
|
} else {
|
2021-03-15 01:01:55 +00:00
|
|
|
ogs_gtpu_resource_t *resource = NULL;
|
|
|
|
resource = ogs_pfcp_find_gtpu_resource(
|
|
|
|
&ogs_gtp_self()->gtpu_resource_list,
|
2020-12-03 06:16:57 +00:00
|
|
|
pdr->dnn, OGS_PFCP_INTERFACE_ACCESS);
|
2020-10-26 02:43:53 +00:00
|
|
|
if (resource) {
|
2022-06-24 06:16:54 +00:00
|
|
|
ogs_assert(
|
|
|
|
(resource->info.v4 && pdr->f_teid.ipv4) ||
|
|
|
|
(resource->info.v6 && pdr->f_teid.ipv6));
|
2021-06-06 13:35:46 +00:00
|
|
|
ogs_assert(OGS_OK ==
|
|
|
|
ogs_pfcp_user_plane_ip_resource_info_to_f_teid(
|
|
|
|
&resource->info, &pdr->f_teid, &pdr->f_teid_len));
|
2020-10-26 02:43:53 +00:00
|
|
|
if (resource->info.teidri)
|
|
|
|
pdr->f_teid.teid = OGS_PFCP_GTPU_INDEX_TO_TEID(
|
|
|
|
pdr->index, resource->info.teidri,
|
|
|
|
resource->info.teid_range);
|
|
|
|
else
|
|
|
|
pdr->f_teid.teid = pdr->index;
|
|
|
|
} else {
|
2022-06-24 06:16:54 +00:00
|
|
|
ogs_assert(
|
|
|
|
(ogs_gtp_self()->gtpu_addr && pdr->f_teid.ipv4) ||
|
|
|
|
(ogs_gtp_self()->gtpu_addr6 && pdr->f_teid.ipv6));
|
2021-05-30 11:35:30 +00:00
|
|
|
ogs_assert(OGS_OK ==
|
|
|
|
ogs_pfcp_sockaddr_to_f_teid(
|
2022-06-24 06:16:54 +00:00
|
|
|
pdr->f_teid.ipv4 ?
|
|
|
|
ogs_gtp_self()->gtpu_addr : NULL,
|
|
|
|
pdr->f_teid.ipv6 ?
|
|
|
|
ogs_gtp_self()->gtpu_addr6 : NULL,
|
2021-05-30 11:35:30 +00:00
|
|
|
&pdr->f_teid, &pdr->f_teid_len));
|
2020-10-26 02:43:53 +00:00
|
|
|
pdr->f_teid.teid = pdr->index;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2020-12-03 06:16:57 +00:00
|
|
|
|
2021-03-15 01:01:55 +00:00
|
|
|
ogs_pfcp_object_teid_hash_set(type, pdr);
|
2020-07-20 01:42:58 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Send Buffered Packet to gNB/SGW */
|
|
|
|
ogs_list_for_each(&sess->pfcp.pdr_list, pdr) {
|
|
|
|
if (pdr->src_if == OGS_PFCP_INTERFACE_CORE) { /* Downlink */
|
2020-08-13 00:31:22 +00:00
|
|
|
ogs_pfcp_send_buffered_packet(pdr);
|
2020-07-20 01:42:58 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-05-16 03:22:10 +00:00
|
|
|
ogs_assert(OGS_OK ==
|
|
|
|
upf_pfcp_send_session_establishment_response(
|
|
|
|
xact, sess, created_pdr, num_of_created_pdr));
|
2020-04-26 19:36:05 +00:00
|
|
|
return;
|
|
|
|
|
|
|
|
cleanup:
|
2022-08-19 12:08:27 +00:00
|
|
|
upf_metrics_inst_by_cause_add(cause_value,
|
|
|
|
UPF_METR_CTR_SM_N4SESSIONESTABFAIL, 1);
|
2020-04-26 19:36:05 +00:00
|
|
|
ogs_pfcp_sess_clear(&sess->pfcp);
|
2022-05-18 01:29:58 +00:00
|
|
|
ogs_pfcp_send_error_message(xact, sess ? sess->smf_n4_f_seid.seid : 0,
|
2020-04-26 19:36:05 +00:00
|
|
|
OGS_PFCP_SESSION_ESTABLISHMENT_RESPONSE_TYPE,
|
|
|
|
cause_value, offending_ie_value);
|
|
|
|
}
|
|
|
|
|
|
|
|
void upf_n4_handle_session_modification_request(
|
2022-03-15 04:34:32 +00:00
|
|
|
upf_sess_t *sess, ogs_pfcp_xact_t *xact,
|
2020-04-26 19:36:05 +00:00
|
|
|
ogs_pfcp_session_modification_request_t *req)
|
|
|
|
{
|
2020-07-20 01:42:58 +00:00
|
|
|
ogs_pfcp_pdr_t *pdr = NULL;
|
2020-08-13 00:31:22 +00:00
|
|
|
ogs_pfcp_far_t *far = NULL;
|
2020-04-26 19:36:05 +00:00
|
|
|
ogs_pfcp_pdr_t *created_pdr[OGS_MAX_NUM_OF_PDR];
|
|
|
|
int num_of_created_pdr = 0;
|
|
|
|
uint8_t cause_value = 0;
|
|
|
|
uint8_t offending_ie_value = 0;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
ogs_assert(xact);
|
|
|
|
ogs_assert(req);
|
|
|
|
|
2020-07-09 05:38:09 +00:00
|
|
|
ogs_debug("Session Modification Request");
|
2020-04-26 19:36:05 +00:00
|
|
|
|
|
|
|
cause_value = OGS_PFCP_CAUSE_REQUEST_ACCEPTED;
|
|
|
|
|
|
|
|
if (!sess) {
|
2020-08-13 00:31:22 +00:00
|
|
|
ogs_error("No Context");
|
2020-04-26 19:36:05 +00:00
|
|
|
ogs_pfcp_send_error_message(xact, 0,
|
|
|
|
OGS_PFCP_SESSION_MODIFICATION_RESPONSE_TYPE,
|
|
|
|
OGS_PFCP_CAUSE_SESSION_CONTEXT_NOT_FOUND, 0);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0; i < OGS_MAX_NUM_OF_PDR; i++) {
|
2020-08-13 00:31:22 +00:00
|
|
|
created_pdr[i] = ogs_pfcp_handle_create_pdr(&sess->pfcp,
|
2020-04-26 19:36:05 +00:00
|
|
|
&req->create_pdr[i], &cause_value, &offending_ie_value);
|
|
|
|
if (created_pdr[i] == NULL)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
num_of_created_pdr = i;
|
|
|
|
if (cause_value != OGS_PFCP_CAUSE_REQUEST_ACCEPTED)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
for (i = 0; i < OGS_MAX_NUM_OF_PDR; i++) {
|
2020-08-13 00:31:22 +00:00
|
|
|
if (ogs_pfcp_handle_update_pdr(&sess->pfcp, &req->update_pdr[i],
|
|
|
|
&cause_value, &offending_ie_value) == NULL)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (cause_value != OGS_PFCP_CAUSE_REQUEST_ACCEPTED)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
for (i = 0; i < OGS_MAX_NUM_OF_PDR; i++) {
|
|
|
|
if (ogs_pfcp_handle_remove_pdr(&sess->pfcp, &req->remove_pdr[i],
|
2020-04-26 19:36:05 +00:00
|
|
|
&cause_value, &offending_ie_value) == false)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (cause_value != OGS_PFCP_CAUSE_REQUEST_ACCEPTED)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
for (i = 0; i < OGS_MAX_NUM_OF_FAR; i++) {
|
2020-08-13 00:31:22 +00:00
|
|
|
if (ogs_pfcp_handle_create_far(&sess->pfcp, &req->create_far[i],
|
2020-04-26 19:36:05 +00:00
|
|
|
&cause_value, &offending_ie_value) == NULL)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (cause_value != OGS_PFCP_CAUSE_REQUEST_ACCEPTED)
|
|
|
|
goto cleanup;
|
|
|
|
|
2020-06-17 05:22:28 +00:00
|
|
|
for (i = 0; i < OGS_MAX_NUM_OF_FAR; i++) {
|
2020-08-13 00:31:22 +00:00
|
|
|
if (ogs_pfcp_handle_update_far_flags(&sess->pfcp, &req->update_far[i],
|
2020-06-17 05:22:28 +00:00
|
|
|
&cause_value, &offending_ie_value) == NULL)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (cause_value != OGS_PFCP_CAUSE_REQUEST_ACCEPTED)
|
|
|
|
goto cleanup;
|
|
|
|
|
2020-08-13 00:31:22 +00:00
|
|
|
/* Send End Marker to gNB */
|
|
|
|
ogs_list_for_each(&sess->pfcp.pdr_list, pdr) {
|
2022-04-30 01:23:12 +00:00
|
|
|
if (pdr->src_if == OGS_PFCP_INTERFACE_CORE) { /* Downlink */
|
|
|
|
far = pdr->far;
|
|
|
|
if (far && far->smreq_flags.send_end_marker_packets)
|
|
|
|
ogs_assert(OGS_ERROR != ogs_pfcp_send_end_marker(pdr));
|
|
|
|
}
|
2020-08-13 00:31:22 +00:00
|
|
|
}
|
|
|
|
/* Clear PFCPSMReq-Flags */
|
|
|
|
ogs_list_for_each(&sess->pfcp.far_list, far)
|
|
|
|
far->smreq_flags.value = 0;
|
|
|
|
|
2020-06-17 05:22:28 +00:00
|
|
|
for (i = 0; i < OGS_MAX_NUM_OF_FAR; i++) {
|
2020-08-13 00:31:22 +00:00
|
|
|
if (ogs_pfcp_handle_update_far(&sess->pfcp, &req->update_far[i],
|
|
|
|
&cause_value, &offending_ie_value) == NULL)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (cause_value != OGS_PFCP_CAUSE_REQUEST_ACCEPTED)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
for (i = 0; i < OGS_MAX_NUM_OF_FAR; i++) {
|
|
|
|
if (ogs_pfcp_handle_remove_far(&sess->pfcp, &req->remove_far[i],
|
2020-04-26 19:36:05 +00:00
|
|
|
&cause_value, &offending_ie_value) == false)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (cause_value != OGS_PFCP_CAUSE_REQUEST_ACCEPTED)
|
|
|
|
goto cleanup;
|
|
|
|
|
2022-04-08 14:10:42 +00:00
|
|
|
upf_n4_handle_create_urr(sess, &req->create_urr[0], &cause_value, &offending_ie_value);
|
2021-10-04 13:28:32 +00:00
|
|
|
if (cause_value != OGS_PFCP_CAUSE_REQUEST_ACCEPTED)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
for (i = 0; i < OGS_MAX_NUM_OF_URR; i++) {
|
|
|
|
if (ogs_pfcp_handle_update_urr(&sess->pfcp, &req->update_urr[i],
|
|
|
|
&cause_value, &offending_ie_value) == NULL)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (cause_value != OGS_PFCP_CAUSE_REQUEST_ACCEPTED)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
for (i = 0; i < OGS_MAX_NUM_OF_URR; i++) {
|
|
|
|
if (ogs_pfcp_handle_remove_urr(&sess->pfcp, &req->remove_urr[i],
|
|
|
|
&cause_value, &offending_ie_value) == false)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (cause_value != OGS_PFCP_CAUSE_REQUEST_ACCEPTED)
|
|
|
|
goto cleanup;
|
|
|
|
|
2020-04-26 19:36:05 +00:00
|
|
|
for (i = 0; i < OGS_MAX_NUM_OF_QER; i++) {
|
2020-08-13 00:31:22 +00:00
|
|
|
if (ogs_pfcp_handle_create_qer(&sess->pfcp, &req->create_qer[i],
|
2020-04-26 19:36:05 +00:00
|
|
|
&cause_value, &offending_ie_value) == NULL)
|
|
|
|
break;
|
2022-08-19 12:08:27 +00:00
|
|
|
upf_metrics_inst_by_dnn_add(NULL,
|
|
|
|
UPF_METR_GAUGE_UPF_QOSFLOWS, 1);
|
2020-04-26 19:36:05 +00:00
|
|
|
}
|
|
|
|
if (cause_value != OGS_PFCP_CAUSE_REQUEST_ACCEPTED)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
for (i = 0; i < OGS_MAX_NUM_OF_QER; i++) {
|
2020-08-13 00:31:22 +00:00
|
|
|
if (ogs_pfcp_handle_update_qer(&sess->pfcp, &req->update_qer[i],
|
2020-04-26 19:36:05 +00:00
|
|
|
&cause_value, &offending_ie_value) == NULL)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (cause_value != OGS_PFCP_CAUSE_REQUEST_ACCEPTED)
|
|
|
|
goto cleanup;
|
|
|
|
|
2020-06-17 05:22:28 +00:00
|
|
|
for (i = 0; i < OGS_MAX_NUM_OF_QER; i++) {
|
2020-08-13 00:31:22 +00:00
|
|
|
if (ogs_pfcp_handle_remove_qer(&sess->pfcp, &req->remove_qer[i],
|
2020-04-26 19:36:05 +00:00
|
|
|
&cause_value, &offending_ie_value) == false)
|
|
|
|
break;
|
2022-08-19 12:08:27 +00:00
|
|
|
upf_metrics_inst_by_dnn_add(NULL,
|
|
|
|
UPF_METR_GAUGE_UPF_QOSFLOWS, -1);
|
2020-04-26 19:36:05 +00:00
|
|
|
}
|
|
|
|
if (cause_value != OGS_PFCP_CAUSE_REQUEST_ACCEPTED)
|
|
|
|
goto cleanup;
|
|
|
|
|
2020-12-03 06:16:57 +00:00
|
|
|
ogs_pfcp_handle_create_bar(&sess->pfcp, &req->create_bar,
|
|
|
|
&cause_value, &offending_ie_value);
|
|
|
|
if (cause_value != OGS_PFCP_CAUSE_REQUEST_ACCEPTED)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
ogs_pfcp_handle_remove_bar(&sess->pfcp, &req->remove_bar,
|
|
|
|
&cause_value, &offending_ie_value);
|
|
|
|
if (cause_value != OGS_PFCP_CAUSE_REQUEST_ACCEPTED)
|
|
|
|
goto cleanup;
|
|
|
|
|
2020-08-13 00:31:22 +00:00
|
|
|
/* Setup GTP Node */
|
2021-03-15 01:01:55 +00:00
|
|
|
ogs_list_for_each(&sess->pfcp.far_list, far) {
|
2021-06-06 13:35:46 +00:00
|
|
|
ogs_assert(OGS_ERROR != ogs_pfcp_setup_far_gtpu_node(far));
|
2021-03-15 01:01:55 +00:00
|
|
|
if (far->gnode)
|
|
|
|
ogs_pfcp_far_f_teid_hash_set(far);
|
|
|
|
}
|
2020-08-13 00:31:22 +00:00
|
|
|
|
2020-07-20 01:42:58 +00:00
|
|
|
/* Setup UPF-N3-TEID & QFI Hash */
|
|
|
|
for (i = 0; i < num_of_created_pdr; i++) {
|
|
|
|
pdr = created_pdr[i];
|
|
|
|
ogs_assert(pdr);
|
|
|
|
|
2020-12-03 06:16:57 +00:00
|
|
|
if (pdr->f_teid_len) {
|
2022-04-16 05:08:56 +00:00
|
|
|
ogs_pfcp_object_type_e type = OGS_PFCP_OBJ_SESS_TYPE;
|
2021-03-15 01:01:55 +00:00
|
|
|
|
2020-12-03 06:16:57 +00:00
|
|
|
if (ogs_pfcp_self()->up_function_features.ftup &&
|
|
|
|
pdr->f_teid.ch) {
|
|
|
|
|
|
|
|
ogs_pfcp_pdr_t *choosed_pdr = NULL;
|
|
|
|
|
|
|
|
if (pdr->f_teid.chid) {
|
|
|
|
choosed_pdr = ogs_pfcp_pdr_find_by_choose_id(
|
|
|
|
&sess->pfcp, pdr->f_teid.choose_id);
|
|
|
|
if (!choosed_pdr) {
|
|
|
|
pdr->chid = true;
|
|
|
|
pdr->choose_id = pdr->f_teid.choose_id;
|
|
|
|
}
|
2022-04-16 05:08:56 +00:00
|
|
|
} else {
|
|
|
|
type = OGS_PFCP_OBJ_PDR_TYPE;
|
2020-12-03 06:16:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (choosed_pdr) {
|
|
|
|
pdr->f_teid_len = choosed_pdr->f_teid_len;
|
|
|
|
memcpy(&pdr->f_teid, &choosed_pdr->f_teid, pdr->f_teid_len);
|
|
|
|
|
|
|
|
} else {
|
2021-03-15 01:01:55 +00:00
|
|
|
ogs_gtpu_resource_t *resource = NULL;
|
|
|
|
resource = ogs_pfcp_find_gtpu_resource(
|
|
|
|
&ogs_gtp_self()->gtpu_resource_list,
|
2020-12-03 06:16:57 +00:00
|
|
|
pdr->dnn, OGS_PFCP_INTERFACE_ACCESS);
|
2020-10-26 02:43:53 +00:00
|
|
|
if (resource) {
|
2022-06-24 06:16:54 +00:00
|
|
|
ogs_assert(
|
|
|
|
(resource->info.v4 && pdr->f_teid.ipv4) ||
|
|
|
|
(resource->info.v6 && pdr->f_teid.ipv6));
|
2021-06-06 13:35:46 +00:00
|
|
|
ogs_assert(OGS_OK ==
|
|
|
|
ogs_pfcp_user_plane_ip_resource_info_to_f_teid(
|
|
|
|
&resource->info, &pdr->f_teid, &pdr->f_teid_len));
|
2020-10-26 02:43:53 +00:00
|
|
|
if (resource->info.teidri)
|
|
|
|
pdr->f_teid.teid = OGS_PFCP_GTPU_INDEX_TO_TEID(
|
|
|
|
pdr->index, resource->info.teidri,
|
|
|
|
resource->info.teid_range);
|
|
|
|
else
|
|
|
|
pdr->f_teid.teid = pdr->index;
|
|
|
|
} else {
|
2022-06-24 06:16:54 +00:00
|
|
|
ogs_assert(
|
|
|
|
(ogs_gtp_self()->gtpu_addr && pdr->f_teid.ipv4) ||
|
|
|
|
(ogs_gtp_self()->gtpu_addr6 && pdr->f_teid.ipv6));
|
2021-05-30 11:35:30 +00:00
|
|
|
ogs_assert(OGS_OK ==
|
|
|
|
ogs_pfcp_sockaddr_to_f_teid(
|
2022-06-24 06:16:54 +00:00
|
|
|
pdr->f_teid.ipv4 ?
|
|
|
|
ogs_gtp_self()->gtpu_addr : NULL,
|
|
|
|
pdr->f_teid.ipv6 ?
|
|
|
|
ogs_gtp_self()->gtpu_addr6 : NULL,
|
2021-05-30 11:35:30 +00:00
|
|
|
&pdr->f_teid, &pdr->f_teid_len));
|
2020-10-26 02:43:53 +00:00
|
|
|
pdr->f_teid.teid = pdr->index;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2020-12-03 06:16:57 +00:00
|
|
|
|
2021-03-15 01:01:55 +00:00
|
|
|
ogs_pfcp_object_teid_hash_set(type, pdr);
|
2020-07-20 01:42:58 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Send Buffered Packet to gNB/SGW */
|
|
|
|
ogs_list_for_each(&sess->pfcp.pdr_list, pdr) {
|
|
|
|
if (pdr->src_if == OGS_PFCP_INTERFACE_CORE) { /* Downlink */
|
2020-08-13 00:31:22 +00:00
|
|
|
ogs_pfcp_send_buffered_packet(pdr);
|
2020-07-20 01:42:58 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-05-16 03:22:10 +00:00
|
|
|
ogs_assert(OGS_OK ==
|
|
|
|
upf_pfcp_send_session_modification_response(
|
|
|
|
xact, sess, created_pdr, num_of_created_pdr));
|
2020-04-26 19:36:05 +00:00
|
|
|
return;
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
ogs_pfcp_sess_clear(&sess->pfcp);
|
2022-05-18 01:29:58 +00:00
|
|
|
ogs_pfcp_send_error_message(xact, sess ? sess->smf_n4_f_seid.seid : 0,
|
2020-04-26 19:36:05 +00:00
|
|
|
OGS_PFCP_SESSION_MODIFICATION_RESPONSE_TYPE,
|
|
|
|
cause_value, offending_ie_value);
|
|
|
|
}
|
|
|
|
|
|
|
|
void upf_n4_handle_session_deletion_request(
|
|
|
|
upf_sess_t *sess, ogs_pfcp_xact_t *xact,
|
|
|
|
ogs_pfcp_session_deletion_request_t *req)
|
|
|
|
{
|
2022-08-19 12:08:27 +00:00
|
|
|
ogs_pfcp_pdr_t *pdr = NULL;
|
|
|
|
ogs_pfcp_qer_t *qer = NULL;
|
|
|
|
|
2020-04-26 19:36:05 +00:00
|
|
|
ogs_assert(xact);
|
|
|
|
ogs_assert(req);
|
|
|
|
|
2020-07-09 05:38:09 +00:00
|
|
|
ogs_debug("Session Deletion Request");
|
2020-04-26 19:36:05 +00:00
|
|
|
|
|
|
|
if (!sess) {
|
2020-08-13 00:31:22 +00:00
|
|
|
ogs_error("No Context");
|
2020-04-26 19:36:05 +00:00
|
|
|
ogs_pfcp_send_error_message(xact, 0,
|
2020-07-04 03:14:48 +00:00
|
|
|
OGS_PFCP_SESSION_DELETION_RESPONSE_TYPE,
|
2020-04-26 19:36:05 +00:00
|
|
|
OGS_PFCP_CAUSE_SESSION_CONTEXT_NOT_FOUND, 0);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
upf_pfcp_send_session_deletion_response(xact, sess);
|
2022-08-19 12:08:27 +00:00
|
|
|
|
|
|
|
ogs_list_for_each(&sess->pfcp.pdr_list, pdr) {
|
|
|
|
ogs_list_for_each(&sess->pfcp.qer_list, qer) {
|
|
|
|
upf_metrics_inst_by_dnn_add(NULL,
|
|
|
|
UPF_METR_GAUGE_UPF_QOSFLOWS, -1);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
2020-04-26 19:36:05 +00:00
|
|
|
upf_sess_remove(sess);
|
|
|
|
}
|
2021-01-18 16:48:35 +00:00
|
|
|
|
|
|
|
void upf_n4_handle_session_report_response(
|
|
|
|
upf_sess_t *sess, ogs_pfcp_xact_t *xact,
|
|
|
|
ogs_pfcp_session_report_response_t *rsp)
|
|
|
|
{
|
|
|
|
uint8_t cause_value = 0;
|
|
|
|
|
|
|
|
ogs_assert(xact);
|
|
|
|
ogs_assert(rsp);
|
|
|
|
|
|
|
|
ogs_pfcp_xact_commit(xact);
|
|
|
|
|
2022-03-15 04:34:32 +00:00
|
|
|
ogs_debug("Session Report Response");
|
2021-01-18 16:48:35 +00:00
|
|
|
|
|
|
|
cause_value = OGS_PFCP_CAUSE_REQUEST_ACCEPTED;
|
|
|
|
|
|
|
|
if (!sess) {
|
|
|
|
ogs_warn("No Context");
|
|
|
|
cause_value = OGS_PFCP_CAUSE_SESSION_CONTEXT_NOT_FOUND;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (rsp->cause.presence) {
|
|
|
|
if (rsp->cause.u8 != OGS_PFCP_CAUSE_REQUEST_ACCEPTED) {
|
|
|
|
ogs_error("PFCP Cause[%d] : Not Accepted", rsp->cause.u8);
|
|
|
|
cause_value = rsp->cause.u8;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
ogs_error("No Cause");
|
|
|
|
cause_value = OGS_PFCP_CAUSE_MANDATORY_IE_MISSING;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (cause_value != OGS_PFCP_CAUSE_REQUEST_ACCEPTED) {
|
|
|
|
ogs_error("Cause request not accepted[%d]", cause_value);
|
|
|
|
return;
|
2022-08-19 12:08:27 +00:00
|
|
|
} else {
|
|
|
|
upf_metrics_inst_global_inc(UPF_METR_GLOB_CTR_SM_N4SESSIONREPORTSUCC);
|
2021-01-18 16:48:35 +00:00
|
|
|
}
|
2022-08-19 12:08:27 +00:00
|
|
|
|
2021-01-18 16:48:35 +00:00
|
|
|
}
|