diff --git a/lib/pfcp/build.c b/lib/pfcp/build.c index 521941249..d6470aa9a 100644 --- a/lib/pfcp/build.c +++ b/lib/pfcp/build.c @@ -637,51 +637,6 @@ void ogs_pfcp_build_create_urr( } } -void ogs_pfcp_build_update_urr( - ogs_pfcp_tlv_update_urr_t *message, int i, ogs_pfcp_urr_t *urr, uint64_t modify_flags) -{ - ogs_assert(message); - ogs_assert(urr); - - /* No change requested, skip. */ - if (!(modify_flags & (OGS_PFCP_MODIFY_URR_MEAS_METHOD| - OGS_PFCP_MODIFY_URR_REPORT_TRIGGER| - OGS_PFCP_MODIFY_URR_VOLUME_THRESH| - OGS_PFCP_MODIFY_URR_TIME_THRESH))) - return; - - /* Change request: Send only changed IEs */ - message->presence = 1; - message->urr_id.presence = 1; - message->urr_id.u32 = urr->id; - if (modify_flags & OGS_PFCP_MODIFY_URR_MEAS_METHOD) { - message->measurement_method.presence = 1; - message->measurement_method.u8 = urr->meas_method; - } - if (modify_flags & OGS_PFCP_MODIFY_URR_REPORT_TRIGGER) { - message->reporting_triggers.presence = 1; - message->reporting_triggers.u24 = (urr->rep_triggers.reptri_5 << 16) - | (urr->rep_triggers.reptri_6 << 8) - | (urr->rep_triggers.reptri_7); - } - - if (modify_flags & OGS_PFCP_MODIFY_URR_VOLUME_THRESH) { - if (urr->vol_threshold.flags) { - message->volume_threshold.presence = 1; - ogs_pfcp_build_volume( - &message->volume_threshold, &urr->vol_threshold, - &urrbuf[i].vol_threshold, sizeof(urrbuf[i].vol_threshold)); - } - } - - if (modify_flags & OGS_PFCP_MODIFY_URR_TIME_THRESH) { - if (urr->time_threshold) { - message->time_threshold.presence = 1; - message->time_threshold.u32 = urr->time_threshold; - } - } -} - static struct { char mbr[OGS_PFCP_BITRATE_LEN]; char gbr[OGS_PFCP_BITRATE_LEN]; diff --git a/lib/pfcp/build.h b/lib/pfcp/build.h index c2065cae9..4eda0f8ee 100644 --- a/lib/pfcp/build.h +++ b/lib/pfcp/build.h @@ -59,8 +59,6 @@ void ogs_pfcp_build_update_qer( void ogs_pfcp_build_create_urr( ogs_pfcp_tlv_create_urr_t *message, int i, ogs_pfcp_urr_t *urr); -void ogs_pfcp_build_update_urr( - ogs_pfcp_tlv_update_urr_t *message, int i, ogs_pfcp_urr_t *urr, uint64_t modify_flags); void ogs_pfcp_build_create_bar( ogs_pfcp_tlv_create_bar_t *message, ogs_pfcp_bar_t *bar); diff --git a/lib/pfcp/xact.h b/lib/pfcp/xact.h index 4ba968f02..6d7904496 100644 --- a/lib/pfcp/xact.h +++ b/lib/pfcp/xact.h @@ -97,11 +97,6 @@ typedef struct ogs_pfcp_xact_s { #define OGS_PFCP_MODIFY_XN_HANDOVER ((uint64_t)1<<21) #define OGS_PFCP_MODIFY_N2_HANDOVER ((uint64_t)1<<22) #define OGS_PFCP_MODIFY_HANDOVER_CANCEL ((uint64_t)1<<23) -#define OGS_PFCP_MODIFY_URR ((uint64_t)1<<24) /* type of trigger */ -#define OGS_PFCP_MODIFY_URR_MEAS_METHOD ((uint64_t)1<<25) -#define OGS_PFCP_MODIFY_URR_REPORT_TRIGGER ((uint64_t)1<<26) -#define OGS_PFCP_MODIFY_URR_VOLUME_THRESH ((uint64_t)1<<27) -#define OGS_PFCP_MODIFY_URR_TIME_THRESH ((uint64_t)1<<28) uint64_t modify_flags; diff --git a/src/smf/context.h b/src/smf/context.h index 40e5bb40d..3ce15b93a 100644 --- a/src/smf/context.h +++ b/src/smf/context.h @@ -24,7 +24,6 @@ #include "ogs-gtp.h" #include "ogs-diameter-gx.h" -#include "ogs-diameter-gy.h" #include "ogs-diameter-rx.h" #include "ogs-diameter-s6b.h" #include "ogs-pfcp.h" @@ -218,7 +217,6 @@ typedef struct smf_sess_s { ogs_ip_t gnb_n3_ip; /* gNB-N3 IPv4/IPv6 */ char *gx_sid; /* Gx Session ID */ - char *gy_sid; /* Gx Session ID */ char *s6b_sid; /* S6b Session ID */ OGS_POOL(pf_precedence_pool, uint8_t); @@ -293,18 +291,6 @@ typedef struct smf_sess_s { uint8_t nsapi; } gtp1; /* GTPv1C specific fields */ - struct { - uint64_t ul_octets; - uint64_t dl_octets; - ogs_time_t duration; - /* Snapshot of measurement when last report was sent: */ - struct { - uint64_t ul_octets; - uint64_t dl_octets; - ogs_time_t duration; - } last_report; - } gy; - struct { ogs_nas_extended_protocol_configuration_options_t ue_pco; } nas; /* Saved from NAS-5GS */ diff --git a/src/smf/event.c b/src/smf/event.c index 181aa0cc3..7453c8e16 100644 --- a/src/smf/event.c +++ b/src/smf/event.c @@ -68,8 +68,6 @@ const char *smf_event_get_name(smf_event_t *e) return "SMF_EVT_GN_MESSAGE"; case SMF_EVT_GX_MESSAGE: return "SMF_EVT_GX_MESSAGE"; - case SMF_EVT_GY_MESSAGE: - return "SMF_EVT_GY_MESSAGE"; case SMF_EVT_N4_MESSAGE: return "SMF_EVT_N4_MESSAGE"; case SMF_EVT_N4_TIMER: diff --git a/src/smf/event.h b/src/smf/event.h index 8b6cfca30..625e0ced9 100644 --- a/src/smf/event.h +++ b/src/smf/event.h @@ -32,7 +32,6 @@ typedef struct ogs_pfcp_node_s ogs_pfcp_node_t; typedef struct ogs_pfcp_xact_s ogs_pfcp_xact_t; typedef struct ogs_pfcp_message_s ogs_pfcp_message_t; typedef struct ogs_diam_gx_message_s ogs_diam_gx_message_t; -typedef struct ogs_diam_gy_message_s ogs_diam_gy_message_t; typedef struct smf_sess_s smf_sess_t; typedef struct smf_upf_s smf_upf_t; typedef struct ogs_sbi_request_s ogs_sbi_request_t; @@ -49,7 +48,6 @@ typedef enum { SMF_EVT_S5C_MESSAGE, SMF_EVT_GN_MESSAGE, SMF_EVT_GX_MESSAGE, - SMF_EVT_GY_MESSAGE, SMF_EVT_N4_MESSAGE, SMF_EVT_N4_TIMER, @@ -81,10 +79,7 @@ typedef struct smf_event_s { ogs_pfcp_xact_t *pfcp_xact; ogs_pfcp_message_t *pfcp_message; - union { - ogs_diam_gx_message_t *gx_message; - ogs_diam_gy_message_t *gy_message; - }; + ogs_diam_gx_message_t *gx_message; struct { ogs_sbi_request_t *request; diff --git a/src/smf/fd-path.c b/src/smf/fd-path.c index 622181278..9e073a94b 100644 --- a/src/smf/fd-path.c +++ b/src/smf/fd-path.c @@ -36,9 +36,6 @@ int smf_fd_init(void) ogs_assert(rv == 0); rv = smf_gx_init(); - ogs_assert(rv == OGS_OK); - - rv = smf_gy_init(); ogs_assert(rv == OGS_OK); rv = ogs_diam_rx_init(); diff --git a/src/smf/fd-path.h b/src/smf/fd-path.h index 571057ce8..77c810458 100644 --- a/src/smf/fd-path.h +++ b/src/smf/fd-path.h @@ -33,15 +33,11 @@ void smf_fd_final(void); int smf_gx_init(void); void smf_gx_final(void); -int smf_gy_init(void); -void smf_gy_final(void); int smf_s6b_init(void); void smf_s6b_final(void); void smf_gx_send_ccr(smf_sess_t *sess, ogs_gtp_xact_t *xact, uint32_t cc_request_type); -void smf_gy_send_ccr(smf_sess_t *sess, void *xact, - uint32_t cc_request_type); void smf_s6b_send_aar(smf_sess_t *sess, ogs_gtp_xact_t *xact); void smf_s6b_send_str(smf_sess_t *sess, ogs_gtp_xact_t *xact, uint32_t cause); @@ -51,3 +47,4 @@ void smf_s6b_send_str(smf_sess_t *sess, ogs_gtp_xact_t *xact, uint32_t cause); #endif #endif /* SMF_FD_PATH_H */ + diff --git a/src/smf/gx-handler.c b/src/smf/gx-handler.c index cff35b728..395158a98 100644 --- a/src/smf/gx-handler.c +++ b/src/smf/gx-handler.c @@ -1,6 +1,5 @@ /* * Copyright (C) 2019 by Sukchan Lee - * Copyright (C) 2022 by sysmocom - s.f.m.c. GmbH * * This file is part of Open5GS. * @@ -21,7 +20,6 @@ #include "context.h" #include "gtp-path.h" #include "pfcp-path.h" -#include "fd-path.h" #include "gx-handler.h" #include "binding.h" @@ -273,21 +271,8 @@ void smf_gx_handle_cca_initial_request( ogs_pfcp_pdr_associate_qer(ul_pdr, qer); } - /* if !Gy */ - if (!ogs_diam_app_connected(OGS_DIAM_GY_APPLICATION_ID)) { - ogs_error("No Gy Diameter Peer"); - //cause_value = OGS_GTP1_CAUSE_NO_RESOURCES_AVAILABLE; - /* FIXME: let's continue on now without Gy (charging features). Ideally - * it should be specified in the config the policy to use if Gy not - * present: either reject the context or continue nevertheless (default) */ - ogs_assert(OGS_OK == - smf_epc_pfcp_send_session_establishment_request(sess, gtp_xact)); - return; - } - - /* Gy is available, set up session for the bearer before accepting it towards the UE */ - smf_gy_send_ccr(sess, gtp_xact, - OGS_DIAM_GY_CC_REQUEST_TYPE_INITIAL_REQUEST); + ogs_assert(OGS_OK == + smf_epc_pfcp_send_session_establishment_request(sess, gtp_xact)); } void smf_gx_handle_cca_termination_request( diff --git a/src/smf/gy-handler.c b/src/smf/gy-handler.c deleted file mode 100644 index 7890edef7..000000000 --- a/src/smf/gy-handler.c +++ /dev/null @@ -1,260 +0,0 @@ -/* - * Copyright (C) 2019 by Sukchan Lee - * Copyright (C) 2022 by sysmocom - s.f.m.c. GmbH - * - * 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 . - */ - -#include "context.h" -#include "gtp-path.h" -#include "pfcp-path.h" -#include "gy-handler.h" -#include "binding.h" - -static uint8_t gtp_cause_from_diameter( - const uint32_t *dia_err, const uint32_t *dia_exp_err) -{ - if (dia_exp_err) { - } - if (dia_err) { - switch (*dia_err) { - case OGS_DIAM_UNKNOWN_SESSION_ID: - return OGS_GTP_CAUSE_APN_ACCESS_DENIED_NO_SUBSCRIPTION; - } - } - - ogs_error("Unexpected Diameter Result Code %d/%d, defaulting to severe " - "network failure", - dia_err ? *dia_err : -1, dia_exp_err ? *dia_exp_err : -1); - return OGS_GTP_CAUSE_UE_NOT_AUTHORISED_BY_OCS_OR_EXTERNAL_AAA_SERVER; -} - -static void urr_enable_total_volume_threshold(smf_sess_t *sess, ogs_pfcp_urr_t *urr, - uint64_t total_volume_threshold) -{ - ogs_debug("Adding CC Grant total_octets=%" PRIu64, total_volume_threshold); - urr->meas_method |= OGS_PFCP_MEASUREMENT_METHOD_VOLUME; - urr->rep_triggers.volume_threshold = 1; - urr->vol_threshold.tovol = 1; - urr->vol_threshold.total_volume = total_volume_threshold; - if (sess->pfcp_node->up_function_features.mnop) - urr->meas_info.mnop = 1; -} - -static void urr_disable_total_volume_threshold(ogs_pfcp_urr_t *urr) -{ - urr->meas_method &= ~OGS_PFCP_MEASUREMENT_METHOD_VOLUME; - urr->rep_triggers.volume_threshold = 0; - urr->vol_threshold.tovol = 0; - urr->vol_threshold.total_volume = 0; -} - -static void urr_update_total_volume_threshold(smf_sess_t *sess, ogs_pfcp_urr_t *urr, ogs_diam_gy_message_t *gy_message) -{ - if (gy_message->cca.granted.cc_total_octets_present) - urr_enable_total_volume_threshold(sess, urr, gy_message->cca.granted.cc_total_octets); - else - urr_disable_total_volume_threshold(urr); -} - -static void urr_update_time_threshold(ogs_pfcp_urr_t *urr, ogs_diam_gy_message_t *gy_message) -{ - uint32_t time_threshold; - if (gy_message->cca.validity_time && (gy_message->cca.granted.cc_time_present && gy_message->cca.granted.cc_time > 0)) - time_threshold = (gy_message->cca.validity_time <= gy_message->cca.granted.cc_time) ? - gy_message->cca.validity_time : gy_message->cca.granted.cc_time; - else if (gy_message->cca.validity_time) - time_threshold = gy_message->cca.validity_time; - else if (gy_message->cca.granted.cc_time_present && gy_message->cca.granted.cc_time > 0) - time_threshold = gy_message->cca.granted.cc_time; - else - time_threshold = 0; - if (time_threshold) { - ogs_debug("Adding CC Grant time=%" PRIu32, time_threshold); - urr->meas_method |= OGS_PFCP_MEASUREMENT_METHOD_DURATION; - urr->rep_triggers.time_threshold = 1; - urr->time_threshold = time_threshold; - urr->meas_info.istm = 1; - } else { - urr->meas_method &= ~OGS_PFCP_MEASUREMENT_METHOD_DURATION; - urr->rep_triggers.time_threshold = 0; - urr->time_threshold = 0; - } -} - -void smf_gy_handle_cca_initial_request( - smf_sess_t *sess, ogs_diam_gy_message_t *gy_message, - ogs_gtp_xact_t *gtp_xact) -{ - smf_bearer_t *bearer; - - ogs_assert(sess); - ogs_assert(gy_message); - ogs_assert(gtp_xact); - - ogs_debug("[Gy CCA Initial]"); - ogs_debug(" SGW_S5C_TEID[0x%x] PGW_S5C_TEID[0x%x]", - sess->sgw_s5c_teid, sess->smf_n4_teid); - - if (gy_message->result_code != ER_DIAMETER_SUCCESS) { - uint8_t cause_value = gtp_cause_from_diameter( - gy_message->err, gy_message->exp_err); - - if (gtp_xact->gtp_version == 1) - ogs_gtp1_send_error_message(gtp_xact, sess ? sess->sgw_s5c_teid : 0, - OGS_GTP1_CREATE_PDP_CONTEXT_RESPONSE_TYPE, cause_value); - else - ogs_gtp_send_error_message(gtp_xact, sess ? sess->sgw_s5c_teid : 0, - OGS_GTP_CREATE_SESSION_RESPONSE_TYPE, cause_value); - return; - } - - bearer = smf_default_bearer_in_sess(sess); - ogs_assert(bearer); - - if (!bearer->urr) - bearer->urr = ogs_pfcp_urr_add(&sess->pfcp); - ogs_assert(bearer->urr); - - /* Configure based on what we received from OCS: */ - urr_update_time_threshold(bearer->urr, gy_message); - urr_update_total_volume_threshold(sess, bearer->urr, gy_message); - - /* Associate acconting URR each direction PDR: */ - ogs_pfcp_pdr_associate_urr(bearer->ul_pdr, bearer->urr); - ogs_pfcp_pdr_associate_urr(bearer->dl_pdr, bearer->urr); - - ogs_assert(OGS_OK == - smf_epc_pfcp_send_session_establishment_request(sess, gtp_xact)); -} - -void smf_gy_handle_cca_update_request( - smf_sess_t *sess, ogs_diam_gy_message_t *gy_message, - ogs_pfcp_xact_t *pfcp_xact) -{ - ogs_pfcp_urr_t *urr = NULL; - smf_bearer_t *bearer; - int rv; - uint64_t modify_flags = 0; - ogs_pfcp_measurement_method_t prev_meas_method; - ogs_pfcp_reporting_triggers_t prev_rep_triggers; - ogs_pfcp_volume_threshold_t prev_vol_threshold; - ogs_pfcp_time_threshold_t prev_time_threshold; - - ogs_assert(sess); - ogs_assert(gy_message); - ogs_assert(pfcp_xact); - - ogs_debug("[Gy CCA Update]"); - ogs_debug(" SGW_S5C_TEID[0x%x] PGW_S5C_TEID[0x%x]", - sess->sgw_s5c_teid, sess->smf_n4_teid); - - if (gy_message->result_code != ER_DIAMETER_SUCCESS) { - ogs_warn("Gy CCA Update Diameter failure: res=%u err=%u", - gy_message->result_code, *gy_message->err); - // TODO: generate new gtp_xact from sess here? */ - //ogs_assert(OGS_OK == - // smf_epc_pfcp_send_session_deletion_request(sess, gtp_xact)); - return; - } - - bearer = smf_default_bearer_in_sess(sess); - ogs_assert(bearer); - - urr = bearer->urr; - ogs_assert(urr); - prev_meas_method = urr->meas_method; - prev_rep_triggers = urr->rep_triggers; - prev_vol_threshold = urr->vol_threshold; - prev_time_threshold = urr->time_threshold; - - urr_update_time_threshold(urr, gy_message); - urr_update_total_volume_threshold(sess, urr, gy_message); - ogs_pfcp_pdr_associate_urr(bearer->ul_pdr, urr); - - if (urr->meas_method != prev_meas_method) - modify_flags |= OGS_PFCP_MODIFY_URR_MEAS_METHOD; - if (urr->rep_triggers.time_threshold != prev_rep_triggers.time_threshold || - urr->rep_triggers.volume_threshold != prev_rep_triggers.volume_threshold) - modify_flags |= OGS_PFCP_MODIFY_URR_REPORT_TRIGGER; - - if (urr->time_threshold != prev_time_threshold) - modify_flags |= OGS_PFCP_MODIFY_URR_TIME_THRESH; - - if (urr->vol_threshold.tovol != prev_vol_threshold.tovol || - urr->vol_threshold.total_volume != prev_vol_threshold.total_volume) - modify_flags |= OGS_PFCP_MODIFY_URR_VOLUME_THRESH; - - /* Send PFCP Session Modification Request if we need to update the params. */ - if (modify_flags) { - modify_flags |= OGS_PFCP_MODIFY_URR|OGS_PFCP_MODIFY_UL_ONLY; - rv = smf_epc_pfcp_send_session_modification_request(sess, pfcp_xact, - modify_flags, - OGS_NAS_PROCEDURE_TRANSACTION_IDENTITY_UNASSIGNED, - OGS_GTP1_CAUSE_REACTIACTION_REQUESTED); - ogs_assert(rv == OGS_OK); - } -} - -void smf_gy_handle_cca_termination_request( - smf_sess_t *sess, ogs_diam_gy_message_t *gy_message, - ogs_gtp_xact_t *gtp_xact) -{ - ogs_assert(sess); - ogs_assert(gy_message); - ogs_assert(gtp_xact); - - 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); - - if (gtp_xact) { - /* - * 1. MME sends Delete Session Request to SGW/SMF. - * 2. SMF sends Delete Session Response to SGW/MME. - */ - switch (gtp_xact->gtp_version) { - case 1: - ogs_assert(OGS_OK == smf_gtp1_send_delete_pdp_context_response(sess, gtp_xact)); - break; - case 2: - ogs_assert(OGS_OK == smf_gtp_send_delete_session_response(sess, gtp_xact)); - break; - } - } else { - /* - * 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. - * - * Note that the following messages are not processed here. - * - Bearer Resource Command - * - Delete Bearer Request/Response with DEDICATED BEARER. - */ - } - SMF_SESS_CLEAR(sess); - return; -} - -void smf_gy_handle_re_auth_request( - smf_sess_t *sess, ogs_diam_gy_message_t *gy_message) -{ - /* TODO: find out what to do here */ -} diff --git a/src/smf/gy-handler.h b/src/smf/gy-handler.h deleted file mode 100644 index 6dde724eb..000000000 --- a/src/smf/gy-handler.h +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (C) 2019 by Sukchan Lee - * Copyright (C) 2022 by sysmocom - s.f.m.c. GmbH - * - * 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 . - */ - -#ifndef SMF_GY_HANDLER_H -#define SMF_GY_HANDLER_H - -#include "context.h" - -#ifdef __cplusplus -extern "C" { -#endif - -void smf_gy_handle_cca_initial_request( - smf_sess_t *sess, ogs_diam_gy_message_t *gy_message, - ogs_gtp_xact_t *gtp_xact); -void smf_gy_handle_cca_update_request( - smf_sess_t *sess, ogs_diam_gy_message_t *gy_message, - ogs_pfcp_xact_t *gtp_xact); -void smf_gy_handle_cca_termination_request( - smf_sess_t *sess, ogs_diam_gy_message_t *gy_message, - ogs_gtp_xact_t *gtp_xact); -void smf_gy_handle_re_auth_request( - smf_sess_t *sess, ogs_diam_gy_message_t *gy_message); - -#ifdef __cplusplus -} -#endif - -#endif /* SMF_GY_HANDLER_H */ diff --git a/src/smf/gy-path.c b/src/smf/gy-path.c deleted file mode 100644 index 19f99da07..000000000 --- a/src/smf/gy-path.c +++ /dev/null @@ -1,1137 +0,0 @@ -/* - * Copyright (C) 2019 by Sukchan Lee - * Copyright (C) 2022 by sysmocom - s.f.m.c. GmbH - * - * 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 . - */ - -#include "fd-path.h" - -static struct session_handler *smf_gy_reg = NULL; -static struct disp_hdl *hdl_gy_fb = NULL; -static struct disp_hdl *hdl_gy_rar = NULL; - -struct sess_state { - os0_t gy_sid; /* Gy Session-Id */ - - os0_t peer_host; /* Peer Host */ - -#define MAX_CC_REQUEST_NUMBER 32 - smf_sess_t *sess; - struct { - bool pfcp; - void *ptr; /* INITIAL: ogs_gtp_xact_t, UPDATE: ogs_pfcp_xact_t */ - } xact_data[MAX_CC_REQUEST_NUMBER]; - uint32_t cc_request_type; - uint32_t cc_request_number; - - struct timespec ts; /* Time of sending the message */ -}; - -static OGS_POOL(sess_state_pool, struct sess_state); -static ogs_thread_mutex_t sess_state_mutex; - -static int decode_granted_service_unit( - ogs_diam_gy_service_unit_t *su, struct avp *avpch1, int *perror); -static void smf_gy_cca_cb(void *data, struct msg **msg); - -static __inline__ struct sess_state *new_state(os0_t sid) -{ - struct sess_state *new = NULL; - - ogs_thread_mutex_lock(&sess_state_mutex); - ogs_pool_alloc(&sess_state_pool, &new); - ogs_expect_or_return_val(new, NULL); - memset(new, 0, sizeof(*new)); - ogs_thread_mutex_unlock(&sess_state_mutex); - - new->gy_sid = (os0_t)ogs_strdup((char *)sid); - ogs_expect_or_return_val(new->gy_sid, NULL); - - return new; -} - -static void state_cleanup(struct sess_state *sess_data, os0_t sid, void *opaque) -{ - if (sess_data->gy_sid) - ogs_free(sess_data->gy_sid); - - if (sess_data->peer_host) - ogs_free(sess_data->peer_host); - - ogs_thread_mutex_lock(&sess_state_mutex); - ogs_pool_free(&sess_state_pool, sess_data); - ogs_thread_mutex_unlock(&sess_state_mutex); -} - -/* TS 32.299 7.1.9 Multiple-Services-Credit-Control AVP for CCR */ -static void fill_multiple_services_credit_control_ccr(smf_sess_t *sess, - uint32_t cc_request_type, struct msg *req) -{ - int ret; - union avp_value val; - struct avp *avp; - struct avp *avpch1, *avpch2, *avpch3; - - /* Multiple-Services-Credit-Control */ - ret = fd_msg_avp_new(ogs_diam_gy_multiple_services_cc, 0, &avp); - ogs_assert(ret == 0); - - /* Requested-Service-Unit, RFC4006 8.18 */ - if (cc_request_type == OGS_DIAM_GY_CC_REQUEST_TYPE_INITIAL_REQUEST || - cc_request_type == OGS_DIAM_GY_CC_REQUEST_TYPE_UPDATE_REQUEST) { - ret = fd_msg_avp_new(ogs_diam_gy_requested_service_unit, 0, &avpch1); - ogs_assert(ret == 0); - - /* CC-Time, RFC4006 8.21 */ - /* CC-Money, RFC4006 8.22. Not used in 3GPP. */ - /* CC-Total-Octets, RFC4006 8.23 */ - /* CC-Input-Octets, RFC4006 8.24 */ - /* CC-Output-Octets, RFC4006 8.25 */ - /* CC-Service-Specific-Units, RFC4006 8.26 */ - - ret = fd_msg_avp_add (avp, MSG_BRW_LAST_CHILD, avpch1); - ogs_assert(ret == 0); - } - - /* Used-Service-Unit, RFC4006 8.18 */ - ret = fd_msg_avp_new(ogs_diam_gy_used_service_unit, 0, &avpch1); - ogs_assert(ret == 0); - - /* Reporting-Reason, TS 32.299 7.2.175 */ - /* Tariff-Change-Usage */ - - /* CC-Time, RFC4006 8.21 */ - ret = fd_msg_avp_new(ogs_diam_gy_cc_time, 0, &avpch2); - ogs_assert(ret == 0); - val.u32 = sess->gy.duration - sess->gy.last_report.duration; - sess->gy.last_report.duration = sess->gy.duration; - ret = fd_msg_avp_setvalue (avpch2, &val); - ogs_assert(ret == 0); - ret = fd_msg_avp_add (avpch1, MSG_BRW_LAST_CHILD, avpch2); - ogs_assert(ret == 0); - - /* CC-Total-Octets, RFC4006 8.23 */ - - /* CC-Input-Octets, RFC4006 8.24 */ - ret = fd_msg_avp_new(ogs_diam_gy_cc_input_octets, 0, &avpch2); - ogs_assert(ret == 0); - val.u64 = sess->gy.ul_octets - sess->gy.last_report.ul_octets; - sess->gy.last_report.ul_octets = sess->gy.ul_octets; - ret = fd_msg_avp_setvalue (avpch2, &val); - ogs_assert(ret == 0); - ret = fd_msg_avp_add (avpch1, MSG_BRW_LAST_CHILD, avpch2); - ogs_assert(ret == 0); - - /* CC-Output-Octets, RFC4006 8.25 */ - ret = fd_msg_avp_new(ogs_diam_gy_cc_output_octets, 0, &avpch2); - ogs_assert(ret == 0); - val.u64 = sess->gy.dl_octets - sess->gy.last_report.dl_octets; - sess->gy.last_report.dl_octets = sess->gy.dl_octets; - ret = fd_msg_avp_setvalue (avpch2, &val); - ogs_assert(ret == 0); - ret = fd_msg_avp_add (avpch1, MSG_BRW_LAST_CHILD, avpch2); - ogs_assert(ret == 0); - - /* CC-Service-Specific-Units, RFC4006 8.26 */ - - ret = fd_msg_avp_add (avp, MSG_BRW_LAST_CHILD, avpch1); - ogs_assert(ret == 0); - - /* Service-Identifier, RFC4006 8.28 */ - ret = fd_msg_avp_new(ogs_diam_gy_service_id, 0, &avpch1); - ogs_assert(ret == 0); - val.u32 = 123; // TODO: set value - ret = fd_msg_avp_setvalue (avpch1, &val); - ogs_assert(ret == 0); - ret = fd_msg_avp_add (avp, MSG_BRW_LAST_CHILD, avpch1); - ogs_assert(ret == 0); - - /* Rating-Group */ - - /* Reporting-Reason, TS 32.299 7.2.175 */ - if (cc_request_type == OGS_DIAM_GY_CC_REQUEST_TYPE_UPDATE_REQUEST || - cc_request_type == OGS_DIAM_GY_CC_REQUEST_TYPE_TERMINATION_REQUEST) { - ret = fd_msg_avp_new(ogs_diam_gy_reporting_reason, 0, &avpch1); - ogs_assert(ret == 0); - val.u32 = OGS_DIAM_GY_REPORTING_REASON_VALIDITY_TIME; // TODO: set value - ret = fd_msg_avp_setvalue (avpch1, &val); - ogs_assert(ret == 0); - ret = fd_msg_avp_add (avp, MSG_BRW_LAST_CHILD, avpch1); - ogs_assert(ret == 0); - } - - /* ... lots of AVPs ... */ - - /* QoS-Information */ - ret = fd_msg_avp_new(ogs_diam_gx_qos_information, 0, &avpch1); - ogs_assert(ret == 0); - - /* QoS-Class-Identifier */ - ret = fd_msg_avp_new(ogs_diam_gy_qos_class_identifier, 0, &avpch2); - ogs_assert(ret == 0); - val.u32 = sess->session.qos.index; - ret = fd_msg_avp_setvalue (avpch2, &val); - ogs_assert(ret == 0); - ret = fd_msg_avp_add (avpch1, MSG_BRW_LAST_CHILD, avpch2); - ogs_assert(ret == 0); - - /* Allocation-Retention-Priority */ - ret = fd_msg_avp_new( - ogs_diam_gy_allocation_retention_priority, 0, &avpch2); - ogs_assert(ret == 0); - - /* Priority-Level */ - ret = fd_msg_avp_new(ogs_diam_gy_priority_level, 0, &avpch3); - ogs_assert(ret == 0); - val.u32 = sess->session.qos.arp.priority_level; - ret = fd_msg_avp_setvalue (avpch3, &val); - ogs_assert(ret == 0); - ret = fd_msg_avp_add (avpch2, MSG_BRW_LAST_CHILD, avpch3); - ogs_assert(ret == 0); - - /* Pre-emption-Capability */ - ret = fd_msg_avp_new(ogs_diam_gy_pre_emption_capability, 0, &avpch3); - ogs_assert(ret == 0); - val.u32 = sess->session.qos.arp.pre_emption_capability; - ret = fd_msg_avp_setvalue (avpch3, &val); - ogs_assert(ret == 0); - ret = fd_msg_avp_add (avpch2, MSG_BRW_LAST_CHILD, avpch3); - ogs_assert(ret == 0); - - /* Pre-emption-Vulnerability */ - ret = fd_msg_avp_new(ogs_diam_gy_pre_emption_vulnerability, 0, &avpch3); - ogs_assert(ret == 0); - val.u32 = sess->session.qos.arp.pre_emption_vulnerability; - ret = fd_msg_avp_setvalue (avpch3, &val); - ogs_assert(ret == 0); - ret = fd_msg_avp_add (avpch2, MSG_BRW_LAST_CHILD, avpch3); - ogs_assert(ret == 0); - - ret = fd_msg_avp_add (avpch1, MSG_BRW_LAST_CHILD, avpch2); - ogs_assert(ret == 0); - - if (sess->session.ambr.uplink) { - ret = fd_msg_avp_new(ogs_diam_gy_apn_aggregate_max_bitrate_ul, - 0, &avpch2); - ogs_assert(ret == 0); - val.u32 = sess->session.ambr.uplink; - ret = fd_msg_avp_setvalue (avpch2, &val); - ogs_assert(ret == 0); - ret = fd_msg_avp_add (avpch1, MSG_BRW_LAST_CHILD, avpch2); - ogs_assert(ret == 0); - } - if (sess->session.ambr.downlink) { - ret = fd_msg_avp_new( - ogs_diam_gy_apn_aggregate_max_bitrate_dl, 0, &avpch2); - ogs_assert(ret == 0); - val.u32 = sess->session.ambr.downlink; - ret = fd_msg_avp_setvalue (avpch2, &val); - ogs_assert(ret == 0); - ret = fd_msg_avp_add (avpch1, MSG_BRW_LAST_CHILD, avpch2); - ogs_assert(ret == 0); - } - ret = fd_msg_avp_add (avp, MSG_BRW_LAST_CHILD, avpch1); - ogs_assert(ret == 0); - - /* Multiple Services AVP add to req: */ - ret = fd_msg_avp_add(req, MSG_BRW_LAST_CHILD, avp); - ogs_assert(ret == 0); -} - -/* 3GPP TS 32.299 6.4.2 Credit-Control-Request message */ -void smf_gy_send_ccr(smf_sess_t *sess, void *xact, - uint32_t cc_request_type) -{ - int ret; - smf_ue_t *smf_ue = NULL; - - struct msg *req = NULL; - struct avp *avp; - struct avp *avpch1; - union avp_value val; - struct sess_state *sess_data = NULL, *svg; - struct session *session = NULL; - int new; - char buf[OGS_PLMNIDSTRLEN]; - const char *service_context_id = "open5gs-smfd@open5gs.org"; - uint32_t timestamp; - - ogs_assert(xact); - ogs_assert(sess); - - ogs_assert(sess->ipv4 || sess->ipv6); - smf_ue = sess->smf_ue; - ogs_assert(smf_ue); - - ogs_debug("[Gy][Credit-Control-Request]"); - - /* Create the request */ - ret = fd_msg_new(ogs_diam_gy_cmd_ccr, MSGFL_ALLOC_ETEID, &req); - ogs_assert(ret == 0); - { - struct msg_hdr *h; - ret = fd_msg_hdr(req, &h); - ogs_assert(ret == 0); - h->msg_appl = OGS_DIAM_GY_APPLICATION_ID; - } - - /* Find Diameter Gy Session */ - if (sess->gy_sid) { - /* Retrieve session by Session-Id */ - size_t sidlen = strlen(sess->gy_sid); - ret = fd_sess_fromsid_msg((os0_t)sess->gy_sid, sidlen, &session, &new); - ogs_assert(ret == 0); - ogs_assert(new == 0); - - ogs_debug(" Found Gy Session-Id: [%s]", sess->gy_sid); - - /* Add Session-Id to the message */ - ret = ogs_diam_message_session_id_set(req, (os0_t)sess->gy_sid, sidlen); - ogs_assert(ret == 0); - /* Save the session associated with the message */ - ret = fd_msg_sess_set(req, session); - } else { - /* Create a new session */ - #define OGS_DIAM_GY_APP_SID_OPT "app_gy" - ret = fd_msg_new_session(req, (os0_t)OGS_DIAM_GY_APP_SID_OPT, - CONSTSTRLEN(OGS_DIAM_GY_APP_SID_OPT)); - ogs_assert(ret == 0); - ret = fd_msg_sess_get(fd_g_config->cnf_dict, req, &session, NULL); - ogs_assert(ret == 0); - ogs_debug(" Create a New Gy Session"); - } - - /* Retrieve session state in this session */ - ret = fd_sess_state_retrieve(smf_gy_reg, session, &sess_data); - if (!sess_data) { - os0_t sid; - size_t sidlen; - - ret = fd_sess_getsid(session, &sid, &sidlen); - ogs_assert(ret == 0); - - /* Allocate new session state memory */ - sess_data = new_state(sid); - ogs_assert(sess_data); - - ogs_debug(" Allocate new Gy session: [%s]", sess_data->gy_sid); - - /* Save Session-Id to SMF Session Context */ - sess->gy_sid = (char *)sess_data->gy_sid; - } else - ogs_debug(" Retrieve Gy session: [%s]", sess_data->gy_sid); - - /* - * 8.2. CC-Request-Number AVP - * - * The CC-Request-Number AVP (AVP Code 415) is of type Unsigned32 and - * identifies this request within one session. As Session-Id AVPs are - * globally unique, the combination of Session-Id and CC-Request-Number - * AVPs is also globally unique and can be used in matching credit- - * control messages with confirmations. An easy way to produce unique - * numbers is to set the value to 0 for a credit-control request of type - * INITIAL_REQUEST and EVENT_REQUEST and to set the value to 1 for the - * first UPDATE_REQUEST, to 2 for the second, and so on until the value - * for TERMINATION_REQUEST is one more than for the last UPDATE_REQUEST. - */ - - sess_data->cc_request_type = cc_request_type; - if (cc_request_type == OGS_DIAM_GY_CC_REQUEST_TYPE_INITIAL_REQUEST || - cc_request_type == OGS_DIAM_GY_CC_REQUEST_TYPE_EVENT_REQUEST) - sess_data->cc_request_number = 0; - else - sess_data->cc_request_number++; - - ogs_debug(" CC Request Type[%d] Number[%d]", - sess_data->cc_request_type, sess_data->cc_request_number); - ogs_assert(sess_data->cc_request_number <= MAX_CC_REQUEST_NUMBER); - - /* Update session state */ - sess_data->sess = sess; - if (cc_request_type == OGS_DIAM_GY_CC_REQUEST_TYPE_UPDATE_REQUEST) - sess_data->xact_data[sess_data->cc_request_number].pfcp = true; - else - sess_data->xact_data[sess_data->cc_request_number].pfcp = false; - sess_data->xact_data[sess_data->cc_request_number].ptr = xact; - - /* Origin-Host & Origin-Realm */ - ret = fd_msg_add_origin(req, 0); - ogs_assert(ret == 0); - - /* the Destination-Realm AVP */ - ret = fd_msg_avp_new(ogs_diam_destination_realm, 0, &avp); - ogs_assert(ret == 0); - val.os.data = (unsigned char *)(fd_g_config->cnf_diamrlm); - val.os.len = strlen(fd_g_config->cnf_diamrlm); - ret = fd_msg_avp_setvalue(avp, &val); - ogs_assert(ret == 0); - ret = fd_msg_avp_add(req, MSG_BRW_LAST_CHILD, avp); - ogs_assert(ret == 0); - - /* the Auth-Application-Id AVP */ - ret = fd_msg_avp_new(ogs_diam_auth_application_id, 0, &avp); - ogs_assert(ret == 0); - val.i32 = OGS_DIAM_GY_APPLICATION_ID; - ret = fd_msg_avp_setvalue(avp, &val); - ogs_assert(ret == 0); - ret = fd_msg_avp_add(req, MSG_BRW_LAST_CHILD, avp); - ogs_assert(ret == 0); - - /* Service-Context-Id */ - ret = fd_msg_avp_new(ogs_diam_service_context_id, 0, &avp); - ogs_assert(ret == 0); - val.os.data = (unsigned char *)service_context_id; - val.os.len = strlen(service_context_id); - ret = fd_msg_avp_setvalue(avp, &val); - ogs_assert(ret == 0); - ret = fd_msg_avp_add(req, MSG_BRW_LAST_CHILD, avp); - ogs_assert(ret == 0); - - /* CC-Request-Type, CC-Request-Number */ - ret = fd_msg_avp_new(ogs_diam_gy_cc_request_type, 0, &avp); - ogs_assert(ret == 0); - val.i32 = sess_data->cc_request_type; - ret = fd_msg_avp_setvalue(avp, &val); - ogs_assert(ret == 0); - ret = fd_msg_avp_add(req, MSG_BRW_LAST_CHILD, avp); - ogs_assert(ret == 0); - - ret = fd_msg_avp_new(ogs_diam_gy_cc_request_number, 0, &avp); - ogs_assert(ret == 0); - val.i32 = sess_data->cc_request_number; - ret = fd_msg_avp_setvalue(avp, &val); - ogs_assert(ret == 0); - ret = fd_msg_avp_add(req, MSG_BRW_LAST_CHILD, avp); - ogs_assert(ret == 0); - - /* Set the Destination-Host AVP */ - if (sess_data->peer_host) { - ret = fd_msg_avp_new(ogs_diam_destination_host, 0, &avp); - ogs_assert(ret == 0); - val.os.data = sess_data->peer_host; - val.os.len = strlen((char *)sess_data->peer_host); - ret = fd_msg_avp_setvalue(avp, &val); - ogs_assert(ret == 0); - ret = fd_msg_avp_add(req, MSG_BRW_LAST_CHILD, avp); - ogs_assert(ret == 0); - } - - /* User-Name */ -#if 0 - ret = fd_msg_avp_new(ogs_diam_user_name, 0, &avp); - ogs_assert(ret == 0); - val.os.data = ?; - val.os.len = strlen(?); - ret = fd_msg_avp_setvalue(avp, &val); - ogs_assert(ret == 0); - ret = fd_msg_avp_add(req, MSG_BRW_LAST_CHILD, avp); - ogs_assert(ret == 0); -#endif - - /* Origin-State-Id */ -#if 0 - /* TODO: implement restart counter */ - ret = fd_msg_avp_new(ogs_diam_gy_origin_state_id, 0, &avp); - ogs_assert(ret == 0); - val.i32 = ?; - ret = fd_msg_avp_setvalue(avp, &val); - ogs_assert(ret == 0); - ret = fd_msg_avp_add(req, MSG_BRW_LAST_CHILD, avp); - ogs_assert(ret == 0); -#endif - - /* Event-Timestamp (rfc6733 8.21, type in 4.3.1) */ - ret = fd_msg_avp_new(ogs_diam_event_timestamp, 0, &avp); - ogs_assert(ret == 0); - timestamp = htobe32(ogs_time_ntp32_now()); - val.os.data = (unsigned char *)×tamp; - val.os.len = 4; - ret = fd_msg_avp_setvalue(avp, &val); - ogs_assert(ret == 0); - ret = fd_msg_avp_add(req, MSG_BRW_LAST_CHILD, avp); - ogs_assert(ret == 0); - - /* Subscription-Id */ - ret = fd_msg_avp_new(ogs_diam_subscription_id, 0, &avp); - ogs_assert(ret == 0); - - ret = fd_msg_avp_new(ogs_diam_subscription_id_type, 0, &avpch1); - ogs_assert(ret == 0); - val.i32 = OGS_DIAM_SUBSCRIPTION_ID_TYPE_END_USER_IMSI; - ret = fd_msg_avp_setvalue (avpch1, &val); - ogs_assert(ret == 0); - ret = fd_msg_avp_add (avp, MSG_BRW_LAST_CHILD, avpch1); - ogs_assert(ret == 0); - - ret = fd_msg_avp_new(ogs_diam_subscription_id_data, 0, &avpch1); - ogs_assert(ret == 0); - val.os.data = (uint8_t *)smf_ue->imsi_bcd; - val.os.len = strlen(smf_ue->imsi_bcd); - ret = fd_msg_avp_setvalue (avpch1, &val); - ogs_assert(ret == 0); - ret = fd_msg_avp_add (avp, MSG_BRW_LAST_CHILD, avpch1); - ogs_assert(ret == 0); - - ret = fd_msg_avp_add(req, MSG_BRW_LAST_CHILD, avp); - ogs_assert(ret == 0); - - /* Termination-Cause */ - if (cc_request_type == OGS_DIAM_GY_CC_REQUEST_TYPE_TERMINATION_REQUEST) { - ret = fd_msg_avp_new(ogs_diam_termination_cause, 0, &avp); - ogs_assert(ret == 0); - val.i32 = OGS_DIAM_TERMINATION_CAUSE_DIAMETER_LOGOUT; /* TODO: set specific cause */ - ret = fd_msg_avp_setvalue(avp, &val); - ogs_assert(ret == 0); - ret = fd_msg_avp_add(req, MSG_BRW_LAST_CHILD, avp); - ogs_assert(ret == 0); - } - - /* Requested-Action */ - ret = fd_msg_avp_new(ogs_diam_gy_requested_action, 0, &avp); - ogs_assert(ret == 0); - val.i32 = OGS_DIAM_GY_REQUESTED_ACTION_DIRECT_DEBITING; - ret = fd_msg_avp_setvalue(avp, &val); - ogs_assert(ret == 0); - ret = fd_msg_avp_add(req, MSG_BRW_LAST_CHILD, avp); - ogs_assert(ret == 0); - - /* AoC-Request-Type */ - ret = fd_msg_avp_new(ogs_diam_gy_aoc_request_type, 0, &avp); - ogs_assert(ret == 0); - val.i32 = OGS_DIAM_GY_AoC_FULL; - ret = fd_msg_avp_setvalue(avp, &val); - ogs_assert(ret == 0); - ret = fd_msg_avp_add(req, MSG_BRW_LAST_CHILD, avp); - ogs_assert(ret == 0); - - /* Multiple-Services-Indicator */ - ret = fd_msg_avp_new(ogs_diam_gy_multiple_services_ind, 0, &avp); - ogs_assert(ret == 0); - val.i32 = OGS_DIAM_GY_MULTIPLE_SERVICES_NOT_SUPPORTED; - ret = fd_msg_avp_setvalue(avp, &val); - ogs_assert(ret == 0); - ret = fd_msg_avp_add(req, MSG_BRW_LAST_CHILD, avp); - ogs_assert(ret == 0); - - /* TS 32.299 7.1.9 Multiple-Services-Credit-Control AVP */ - fill_multiple_services_credit_control_ccr(sess, cc_request_type, req); - - /* OC-Supported-Features */ - - /* 3GPP-User-Location-Info */ - if (sess->gtp.user_location_information.presence) { - ogs_gtp_uli_t uli; - int16_t uli_len; - - uint8_t uli_buf[OGS_GTP_MAX_ULI_LEN]; - - uli_len = ogs_gtp_parse_uli( - &uli, &sess->gtp.user_location_information); - ogs_assert(sess->gtp.user_location_information.len == uli_len); - - ogs_assert(sess->gtp.user_location_information.data); - ogs_assert(sess->gtp.user_location_information.len); - memcpy(&uli_buf, sess->gtp.user_location_information.data, - sess->gtp.user_location_information.len); - - /* Update Gy ULI Type */ - if (uli.flags.tai && uli.flags.e_cgi) - uli_buf[0] = - OGS_DIAM_GY_3GPP_USER_LOCATION_INFO_TYPE_TAI_AND_ECGI; - else if (uli.flags.tai) - uli_buf[0] = OGS_DIAM_GY_3GPP_USER_LOCATION_INFO_TYPE_TAI; - else if (uli.flags.e_cgi) - uli_buf[0] = OGS_DIAM_GY_3GPP_USER_LOCATION_INFO_TYPE_ECGI; - - if (uli_buf[0]) { - ret = fd_msg_avp_new( - ogs_diam_gy_3gpp_user_location_info, 0, &avp); - ogs_assert(ret == 0); - val.os.data = (uint8_t *)&uli_buf; - val.os.len = sess->gtp.user_location_information.len; - ret = fd_msg_avp_setvalue(avp, &val); - ogs_assert(ret == 0); - ret = fd_msg_avp_add(req, MSG_BRW_LAST_CHILD, avp); - ogs_assert(ret == 0); - } - } - - /* 3GPP-MS-Timezone */ - if (sess->gtp.ue_timezone.presence && - sess->gtp.ue_timezone.len && sess->gtp.ue_timezone.data) { - ret = fd_msg_avp_new(ogs_diam_gy_3gpp_ms_timezone, 0, &avp); - ogs_assert(ret == 0); - val.os.data = sess->gtp.ue_timezone.data; - val.os.len = sess->gtp.ue_timezone.len; - ret = fd_msg_avp_setvalue(avp, &val); - ogs_assert(ret == 0); - ret = fd_msg_avp_add(req, MSG_BRW_LAST_CHILD, avp); - ogs_assert(ret == 0); - } - - /* 3GPP-SGSN-MCC-MNC */ - ret = fd_msg_avp_new(ogs_diam_gy_3gpp_sgsn_mcc_mnc, 0, &avp); - ogs_assert(ret == 0); - val.os.data = (uint8_t *)ogs_plmn_id_to_string(&sess->plmn_id, buf); - val.os.len = strlen(buf); - ret = fd_msg_avp_setvalue(avp, &val); - ogs_assert(ret == 0); - ret = fd_msg_avp_add(req, MSG_BRW_LAST_CHILD, avp); - ogs_assert(ret == 0); - - /* Called-Station-Id */ - ret = fd_msg_avp_new(ogs_diam_gy_called_station_id, 0, &avp); - ogs_assert(ret == 0); - ogs_assert(sess->session.name); - val.os.data = (uint8_t*)sess->session.name; - val.os.len = strlen(sess->session.name); - ret = fd_msg_avp_setvalue(avp, &val); - ogs_assert(ret == 0); - ret = fd_msg_avp_add(req, MSG_BRW_LAST_CHILD, avp); - ogs_assert(ret == 0); - - - ret = clock_gettime(CLOCK_REALTIME, &sess_data->ts); - - /* Keep a pointer to the session data for debug purpose, - * in real life we would not need it */ - svg = sess_data; - - /* Store this value in the session */ - ret = fd_sess_state_store(smf_gy_reg, session, &sess_data); - ogs_assert(ret == 0); - ogs_assert(sess_data == NULL); - - /* Send the request */ - ret = fd_msg_send(&req, smf_gy_cca_cb, svg); - ogs_assert(ret == 0); - - /* Increment the counter */ - ogs_assert(pthread_mutex_lock(&ogs_diam_logger_self()->stats_lock) == 0); - ogs_diam_logger_self()->stats.nb_sent++; - ogs_assert(pthread_mutex_unlock(&ogs_diam_logger_self()->stats_lock) == 0); -} - -static void smf_gy_cca_cb(void *data, struct msg **msg) -{ - int rv; - int ret; - - struct sess_state *sess_data = NULL; - struct timespec ts; - struct session *session; - struct avp *avp, *avpch1; - struct avp_hdr *hdr; - unsigned long dur; - int error = 0; - int new; - struct msg *req = NULL; - smf_event_t *e = NULL; - void *xact = NULL; - smf_sess_t *sess = NULL; - ogs_diam_gy_message_t *gy_message = NULL; - uint32_t cc_request_number = 0; - - ogs_debug("[Gy][Credit-Control-Answer]"); - - ret = clock_gettime(CLOCK_REALTIME, &ts); - ogs_assert(ret == 0); - - /* Get originating request of received message, if any */ - ret = fd_msg_answ_getq(*msg, &req); - ogs_assert(ret == 0); - - /* Search the session, retrieve its data */ - ret = fd_msg_sess_get(fd_g_config->cnf_dict, *msg, &session, &new); - ogs_assert(ret == 0); - ogs_assert(new == 0); - - ogs_debug(" Search the Gy session"); - - ret = fd_sess_state_retrieve(smf_gy_reg, session, &sess_data); - ogs_assert(ret == 0); - ogs_assert(sess_data); - ogs_assert((void *)sess_data == data); - - ogs_debug(" Retrieve its data: [%s]", sess_data->gy_sid); - - /* Value of CC-Request-Number */ - ret = fd_msg_search_avp(*msg, ogs_diam_gy_cc_request_number, &avp); - ogs_assert(ret == 0); - if (!avp && req) { - /* Attempt searching for CC-Request-* in original request. Error - * messages (like DIAMETER_UNABLE_TO_DELIVER) crafted internally may not - * have them. */ - ret = fd_msg_search_avp(req, ogs_diam_gy_cc_request_number, &avp); - ogs_assert(ret == 0); - } - if (!avp) { - ogs_error("no_CC-Request-Number"); - ogs_assert_if_reached(); - } - ret = fd_msg_avp_hdr(avp, &hdr); - ogs_assert(ret == 0); - cc_request_number = hdr->avp_value->i32; - - ogs_debug(" CC-Request-Number[%d]", cc_request_number); - - xact = sess_data->xact_data[cc_request_number].ptr; - ogs_assert(xact); - sess = sess_data->sess; - ogs_assert(sess); - - gy_message = ogs_calloc(1, sizeof(ogs_diam_gy_message_t)); - ogs_assert(gy_message); - - /* Set Credit Control Command */ - gy_message->cmd_code = OGS_DIAM_GY_CMD_CODE_CREDIT_CONTROL; - - /* Value of Result Code */ - ret = fd_msg_search_avp(*msg, ogs_diam_result_code, &avp); - ogs_assert(ret == 0); - if (avp) { - ret = fd_msg_avp_hdr(avp, &hdr); - ogs_assert(ret == 0); - gy_message->result_code = hdr->avp_value->i32; - gy_message->err = &gy_message->result_code; - ogs_debug(" Result Code: %d", hdr->avp_value->i32); - } else { - ret = fd_msg_search_avp(*msg, ogs_diam_experimental_result, &avp); - ogs_assert(ret == 0); - if (avp) { - ret = fd_avp_search_avp( - avp, ogs_diam_experimental_result_code, &avpch1); - ogs_assert(ret == 0); - if (avpch1) { - ret = fd_msg_avp_hdr(avpch1, &hdr); - ogs_assert(ret == 0); - gy_message->result_code = hdr->avp_value->i32; - gy_message->exp_err = &gy_message->result_code; - ogs_debug(" Experimental Result Code: %d", - gy_message->result_code); - } - } else { - ogs_error("no Result-Code"); - error++; - } - } - - /* Value of Origin-Host */ - ret = fd_msg_search_avp(*msg, ogs_diam_origin_host, &avp); - ogs_assert(ret == 0); - if (avp) { - ret = fd_msg_avp_hdr(avp, &hdr); - ogs_assert(ret == 0); - ogs_debug(" From '%.*s'", - (int)hdr->avp_value->os.len, hdr->avp_value->os.data); - } else { - ogs_error("no_Origin-Host"); - error++; - } - - /* Value of Origin-Realm */ - ret = fd_msg_search_avp(*msg, ogs_diam_origin_realm, &avp); - ogs_assert(ret == 0); - if (avp) { - ret = fd_msg_avp_hdr(avp, &hdr); - ogs_assert(ret == 0); - ogs_debug(" ('%.*s')", - (int)hdr->avp_value->os.len, hdr->avp_value->os.data); - } else { - ogs_error("no_Origin-Realm"); - error++; - } - - /* Value of CC-Request-Type */ - ret = fd_msg_search_avp(*msg, ogs_diam_gy_cc_request_type, &avp); - ogs_assert(ret == 0); - if (!avp && req) { - /* Attempt searching for CC-Request-* in original request. Error - * messages (like DIAMETER_UNABLE_TO_DELIVER) crafted internally may not - * have them. */ - ret = fd_msg_search_avp(req, ogs_diam_gy_cc_request_type, &avp); - ogs_assert(ret == 0); - } - if (!avp) { - ogs_error("no_CC-Request-Number"); - error++; - } - ret = fd_msg_avp_hdr(avp, &hdr); - ogs_assert(ret == 0); - gy_message->cc_request_type = hdr->avp_value->i32; - - if (gy_message->result_code != ER_DIAMETER_SUCCESS) { - ogs_warn("ERROR DIAMETER Result Code(%d)", gy_message->result_code); - goto out; - } - - ret = fd_msg_browse(*msg, MSG_BRW_FIRST_CHILD, &avp, NULL); - ogs_assert(ret == 0); - while (avp) { - ret = fd_msg_avp_hdr(avp, &hdr); - ogs_assert(ret == 0); - switch (hdr->avp_code) { - case AC_SESSION_ID: - case AC_ORIGIN_HOST: - if (sess_data->peer_host) - ogs_free(sess_data->peer_host); - sess_data->peer_host = - (os0_t)ogs_strdup((char *)hdr->avp_value->os.data); - ogs_assert(sess_data->peer_host); - break; - case AC_ORIGIN_REALM: - case AC_DESTINATION_REALM: - case AC_RESULT_CODE: - case AC_ROUTE_RECORD: - case AC_PROXY_INFO: - case AC_AUTH_APPLICATION_ID: - break; - case OGS_DIAM_GY_AVP_CODE_CC_REQUEST_TYPE: - case OGS_DIAM_GY_AVP_CODE_CC_REQUEST_NUMBER: - case OGS_DIAM_GY_AVP_CODE_SUPPORTED_FEATURES: - break; - case OGS_DIAM_GY_AVP_CODE_MULTIPLE_SERVICES_CREDIT_CONTROL: - ret = fd_msg_browse(avp, MSG_BRW_FIRST_CHILD, &avpch1, NULL); - ogs_assert(ret == 0); - while (avpch1) { - ret = fd_msg_avp_hdr(avpch1, &hdr); - ogs_assert(ret == 0); - switch (hdr->avp_code) { - case OGS_DIAM_GY_AVP_CODE_GRANTED_SERVICE_UNIT: - rv = decode_granted_service_unit( - &gy_message->cca.granted, avpch1, &error); - ogs_assert(rv == OGS_OK); - /*TODO: apply gsu */ - break; - case OGS_DIAM_GY_AVP_CODE_VALIDITY_TIME: - gy_message->cca.validity_time = hdr->avp_value->u32; - break; - default: - ogs_warn("Not supported(%d)", hdr->avp_code); - break; - } - fd_msg_browse(avpch1, MSG_BRW_NEXT, &avpch1, NULL); - } - break; - default: - ogs_warn("Not supported(%d)", hdr->avp_code); - break; - } - fd_msg_browse(avp, MSG_BRW_NEXT, &avp, NULL); - } - -out: - if (!error) { - e = smf_event_new(SMF_EVT_GY_MESSAGE); - ogs_assert(e); - - e->sess = sess; - e->gy_message = gy_message; - if (gy_message->cc_request_type == OGS_DIAM_GY_CC_REQUEST_TYPE_UPDATE_REQUEST) { - ogs_assert(sess_data->xact_data[sess_data->cc_request_number].pfcp == true); - e->pfcp_xact = xact; - } else { - ogs_assert(sess_data->xact_data[sess_data->cc_request_number].pfcp == false); - e->gtp_xact = xact; - } - rv = ogs_queue_push(ogs_app()->queue, e); - if (rv != OGS_OK) { - ogs_warn("ogs_queue_push() failed:%d", (int)rv); - ogs_free(gy_message); - smf_event_free(e); - } else { - ogs_pollset_notify(ogs_app()->pollset); - } - } else { - ogs_free(gy_message); - } - - /* Free the message */ - ogs_assert(pthread_mutex_lock(&ogs_diam_logger_self()->stats_lock) == 0); - dur = ((ts.tv_sec - sess_data->ts.tv_sec) * 1000000) + - ((ts.tv_nsec - sess_data->ts.tv_nsec) / 1000); - if (ogs_diam_logger_self()->stats.nb_recv) { - /* Ponderate in the avg */ - ogs_diam_logger_self()->stats.avg = (ogs_diam_logger_self()->stats.avg * - ogs_diam_logger_self()->stats.nb_recv + dur) / - (ogs_diam_logger_self()->stats.nb_recv + 1); - /* Min, max */ - if (dur < ogs_diam_logger_self()->stats.shortest) - ogs_diam_logger_self()->stats.shortest = dur; - if (dur > ogs_diam_logger_self()->stats.longest) - ogs_diam_logger_self()->stats.longest = dur; - } else { - ogs_diam_logger_self()->stats.shortest = dur; - ogs_diam_logger_self()->stats.longest = dur; - ogs_diam_logger_self()->stats.avg = dur; - } - if (error) - ogs_diam_logger_self()->stats.nb_errs++; - else - ogs_diam_logger_self()->stats.nb_recv++; - - ogs_assert(pthread_mutex_unlock(&ogs_diam_logger_self()->stats_lock) == 0); - - /* Display how long it took */ - if (ts.tv_nsec > sess_data->ts.tv_nsec) - ogs_trace("in %d.%06ld sec", - (int)(ts.tv_sec - sess_data->ts.tv_sec), - (long)(ts.tv_nsec - sess_data->ts.tv_nsec) / 1000); - else - ogs_trace("in %d.%06ld sec", - (int)(ts.tv_sec + 1 - sess_data->ts.tv_sec), - (long)(1000000000 + ts.tv_nsec - sess_data->ts.tv_nsec) / 1000); - - ogs_debug(" CC-Request-Type[%d] Number[%d] in Session Data", - sess_data->cc_request_type, sess_data->cc_request_number); - ogs_debug(" Current CC-Request-Number[%d]", cc_request_number); - if (sess_data->cc_request_type == - OGS_DIAM_GY_CC_REQUEST_TYPE_TERMINATION_REQUEST && - sess_data->cc_request_number <= cc_request_number) { - ogs_debug(" [LAST] state_cleanup(): [%s]", sess_data->gy_sid); - state_cleanup(sess_data, NULL, NULL); - } else { - ogs_debug(" fd_sess_state_store(): [%s]", sess_data->gy_sid); - ret = fd_sess_state_store(smf_gy_reg, session, &sess_data); - ogs_assert(ret == 0); - ogs_assert(sess_data == NULL); - } - - ret = fd_msg_free(*msg); - ogs_assert(ret == 0); - *msg = NULL; - - return; -} - -static int smf_gy_fb_cb(struct msg **msg, struct avp *avp, - struct session *sess, void *opaque, enum disp_action *act) -{ - /* This CB should never be called */ - ogs_warn("Unexpected message received!"); - - return ENOTSUP; -} - -static int smf_gy_rar_cb( struct msg **msg, struct avp *avp, - struct session *session, void *opaque, enum disp_action *act) -{ - int rv; - int ret; - - struct msg *ans; - union avp_value val; - struct sess_state *sess_data = NULL; - - smf_event_t *e = NULL; - smf_sess_t *sess = NULL; - ogs_diam_gy_message_t *gy_message = NULL; - - uint32_t result_code = OGS_DIAM_UNKNOWN_SESSION_ID; - - ogs_assert(msg); - - ogs_debug("Re-Auth-Request"); - - gy_message = ogs_calloc(1, sizeof(ogs_diam_gy_message_t)); - ogs_assert(gy_message); - - /* Set Credit Control Command */ - gy_message->cmd_code = OGS_DIAM_GY_CMD_RE_AUTH; - - /* Create answer header */ - ret = fd_msg_new_answer_from_req(fd_g_config->cnf_dict, msg, 0); - ogs_assert(ret == 0); - ans = *msg; - - ret = fd_sess_state_retrieve(smf_gy_reg, session, &sess_data); - ogs_assert(ret == 0); - if (!sess_data) { - ogs_error("No Session Data"); - goto out; - } - - /* Get Session Information */ - sess = sess_data->sess; - ogs_assert(sess); - - /* TODO: parsing of msg into gy_message */ - - /* Send Gy Event to SMF State Machine */ - e = smf_event_new(SMF_EVT_GY_MESSAGE); - ogs_assert(e); - - e->sess = sess; - e->gy_message = gy_message; - rv = ogs_queue_push(ogs_app()->queue, e); - if (rv != OGS_OK) { - ogs_warn("ogs_queue_push() failed:%d", (int)rv); - ogs_free(gy_message); - smf_event_free(e); - } else { - ogs_pollset_notify(ogs_app()->pollset); - } - - /* Set the Auth-Application-Id AVP */ - ret = fd_msg_avp_new(ogs_diam_auth_application_id, 0, &avp); - ogs_assert(ret == 0); - val.i32 = OGS_DIAM_GY_APPLICATION_ID; - ret = fd_msg_avp_setvalue(avp, &val); - ogs_assert(ret == 0); - ret = fd_msg_avp_add(ans, MSG_BRW_LAST_CHILD, avp); - ogs_assert(ret == 0); - - /* Set the Origin-Host, Origin-Realm, andResult-Code AVPs */ - ret = fd_msg_rescode_set(ans, (char *)"DIAMETER_SUCCESS", NULL, NULL, 1); - ogs_assert(ret == 0); - - /* Store this value in the session */ - ret = fd_sess_state_store(smf_gy_reg, session, &sess_data); - ogs_assert(ret == 0); - ogs_assert(sess_data == NULL); - - /* Send the answer */ - ret = fd_msg_send(msg, NULL, NULL); - ogs_assert(ret == 0); - - ogs_debug("Re-Auth-Answer"); - - /* Add this value to the stats */ - ogs_assert(pthread_mutex_lock(&ogs_diam_logger_self()->stats_lock) == 0); - ogs_diam_logger_self()->stats.nb_echoed++; - ogs_assert(pthread_mutex_unlock(&ogs_diam_logger_self()->stats_lock) == 0); - - return 0; - -out: - if (result_code == OGS_DIAM_UNKNOWN_SESSION_ID) { - ret = fd_msg_rescode_set(ans, - (char *)"DIAMETER_UNKNOWN_SESSION_ID", NULL, NULL, 1); - ogs_assert(ret == 0); - } else { - ret = ogs_diam_message_experimental_rescode_set(ans, result_code); - ogs_assert(ret == 0); - } - - /* Store this value in the session */ - ret = fd_sess_state_store(smf_gy_reg, session, &sess_data); - ogs_assert(sess_data == NULL); - - ret = fd_msg_send(msg, NULL, NULL); - ogs_assert(ret == 0); - - ogs_free(gy_message); - - return 0; -} - -int smf_gy_init(void) -{ - int ret; - struct disp_when data; - - ogs_thread_mutex_init(&sess_state_mutex); - ogs_pool_init(&sess_state_pool, ogs_app()->pool.sess); - - /* Install objects definitions for this application */ - ret = ogs_diam_gy_init(); - ogs_assert(ret == 0); - - /* Create handler for sessions */ - ret = fd_sess_handler_create(&smf_gy_reg, state_cleanup, NULL, NULL); - ogs_assert(ret == 0); - - memset(&data, 0, sizeof(data)); - data.app = ogs_diam_gy_application; - - ret = fd_disp_register(smf_gy_fb_cb, DISP_HOW_APPID, &data, NULL, - &hdl_gy_fb); - ogs_assert(ret == 0); - - data.command = ogs_diam_gy_cmd_rar; - ret = fd_disp_register(smf_gy_rar_cb, DISP_HOW_CC, &data, NULL, - &hdl_gy_rar); - ogs_assert(ret == 0); - - /* Advertise the support for the application in the peer */ - ret = fd_disp_app_support(ogs_diam_gy_application, NULL, 1, 0); - ogs_assert(ret == 0); - - return OGS_OK; -} - -void smf_gy_final(void) -{ - int ret; - - ret = fd_sess_handler_destroy(&smf_gy_reg, NULL); - ogs_assert(ret == 0); - - if (hdl_gy_fb) - (void) fd_disp_unregister(&hdl_gy_fb, NULL); - if (hdl_gy_rar) - (void) fd_disp_unregister(&hdl_gy_rar, NULL); - - ogs_pool_final(&sess_state_pool); - ogs_thread_mutex_destroy(&sess_state_mutex); -} - -static int decode_granted_service_unit( - ogs_diam_gy_service_unit_t *su, struct avp *avpch1, int *perror) -{ - int ret = 0, error = 0; - struct avp *avpch2; - struct avp_hdr *hdr; - - ogs_assert(su); - ogs_assert(avpch1); - memset(su, 0, sizeof(*su)); - - ret = fd_msg_browse(avpch1, MSG_BRW_FIRST_CHILD, &avpch2, NULL); - ogs_assert(ret == 0); - while (avpch2) { - ret = fd_msg_avp_hdr(avpch2, &hdr); - ogs_assert(ret == 0); - switch (hdr->avp_code) { - case OGS_DIAM_GY_AVP_CODE_CC_TIME: - su->cc_time_present = true; - su->cc_time = hdr->avp_value->u32; - break; - case OGS_DIAM_GY_AVP_CODE_CC_TOTAL_OCTETS: - su->cc_total_octets_present = true; - su->cc_total_octets = hdr->avp_value->u64; - break; - case OGS_DIAM_GY_AVP_CODE_CC_INPUT_OCTETS: - su->cc_input_octets_present = true; - su->cc_input_octets = hdr->avp_value->u64; - break; - case OGS_DIAM_GY_AVP_CODE_CC_OUTPUT_OCTETS: - su->cc_output_octets_present = true; - su->cc_output_octets = hdr->avp_value->u64; - break; - default: - ogs_error("Not implemented(%d)", hdr->avp_code); - break; - } - fd_msg_browse(avpch2, MSG_BRW_NEXT, &avpch2, NULL); - } - - if (perror) - *perror = error; - - return OGS_OK; -} diff --git a/src/smf/meson.build b/src/smf/meson.build index 1bd0b7d08..07fd3f849 100644 --- a/src/smf/meson.build +++ b/src/smf/meson.build @@ -46,7 +46,6 @@ libsmf_sources = files(''' s5c-handler.h fd-path.h gx-handler.h - gy-handler.h pfcp-path.h n4-build.h n4-handler.h @@ -83,10 +82,8 @@ libsmf_sources = files(''' s5c-handler.c fd-path.c gx-path.c - gy-path.c s6b-path.c gx-handler.c - gy-handler.c pfcp-path.c n4-build.c n4-handler.c @@ -116,7 +113,6 @@ libsmf = static_library('smf', libngap_dep, libnas_5gs_dep, libdiameter_gx_dep, - libdiameter_gy_dep, libdiameter_s6b_dep, libgtp_dep, libpfcp_dep], @@ -129,7 +125,6 @@ libsmf_dep = declare_dependency( libngap_dep, libnas_5gs_dep, libdiameter_gx_dep, - libdiameter_gy_dep, libdiameter_s6b_dep, libgtp_dep, libpfcp_dep]) diff --git a/src/smf/n4-build.c b/src/smf/n4-build.c index 9958adf82..a9d721341 100644 --- a/src/smf/n4-build.c +++ b/src/smf/n4-build.c @@ -114,8 +114,6 @@ ogs_pkbuf_t *smf_n4_build_session_modification_request( uint8_t type, smf_sess_t *sess, uint64_t modify_flags) { ogs_pfcp_pdr_t *pdr = NULL; - ogs_pfcp_urr_t *urr = NULL; - int i; ogs_pfcp_message_t pfcp_message; ogs_pfcp_session_modification_request_t *req = NULL; @@ -203,7 +201,7 @@ ogs_pkbuf_t *smf_n4_build_session_modification_request( &req->update_far[num_of_update_far], num_of_update_far, far); num_of_update_far++; - } else if (modify_flags == 0) { + } else { ogs_fatal("Invalid modify_flags = %lld", (long long)modify_flags); ogs_assert_if_reached(); @@ -212,13 +210,6 @@ ogs_pkbuf_t *smf_n4_build_session_modification_request( } - /* Update URR */ - i = 0; - ogs_list_for_each(&sess->pfcp.urr_list, urr) { - ogs_pfcp_build_update_urr(&req->update_urr[i], i, urr, modify_flags); - i++; - } - pfcp_message.h.type = type; pkbuf = ogs_pfcp_build_msg(&pfcp_message); diff --git a/src/smf/n4-handler.c b/src/smf/n4-handler.c index 0e667910a..4d4204c94 100644 --- a/src/smf/n4-handler.c +++ b/src/smf/n4-handler.c @@ -26,7 +26,6 @@ #include "binding.h" #include "sbi-path.h" #include "ngap-path.h" -#include "fd-path.h" uint8_t gtp_cause_from_pfcp(uint8_t pfcp_cause, uint8_t gtp_version) { @@ -928,6 +927,7 @@ void smf_epc_n4_handle_session_modification_response( if (flags & OGS_PFCP_MODIFY_SESSION) { /* If smf_epc_pfcp_send_session_modification_request() is called */ + } else { /* If smf_epc_pfcp_send_bearer_modification_request() is called */ bearer = xact->data; @@ -936,14 +936,9 @@ void smf_epc_n4_handle_session_modification_response( flags = xact->modify_flags; ogs_assert(flags); - /* OGS_PFCP_MODIFY_URR: Modification Response was originally triggered by - PFCP Session Report Request, xact->assoc_xact is not a gtp_xact. No - need to do anything. */ - if (!(flags & OGS_PFCP_MODIFY_URR)) { - gtp_xact = xact->assoc_xact; - gtp_pti = xact->gtp_pti; - gtp_cause = xact->gtp_cause; - } + gtp_xact = xact->assoc_xact; + gtp_pti = xact->gtp_pti; + gtp_cause = xact->gtp_cause; ogs_pfcp_xact_commit(xact); @@ -1131,8 +1126,6 @@ void smf_epc_n4_handle_session_deletion_response( uint8_t cause_value = 0; uint8_t resp_type = 0; ogs_gtp_xact_t *gtp_xact = NULL; - smf_bearer_t *bearer = NULL; - unsigned int i; ogs_assert(xact); ogs_assert(rsp); @@ -1183,64 +1176,36 @@ void smf_epc_n4_handle_session_deletion_response( ogs_assert(sess); - bearer = smf_default_bearer_in_sess(sess); - for (i = 0; i < OGS_ARRAY_SIZE(rsp->usage_report); i++) { - ogs_pfcp_tlv_usage_report_session_deletion_response_t *use_rep = &rsp->usage_report[i]; - uint32_t urr_id; - ogs_pfcp_volume_measurement_t volume; - if (use_rep->presence == 0) + if (gtp_xact) { + /* + * 1. MME sends Delete Session Request to SGW/SMF. + * 2. SMF sends Delete Session Response to SGW/MME. + */ + switch (gtp_version) { + case 1: + ogs_assert(OGS_OK == smf_gtp1_send_delete_pdp_context_response(sess, gtp_xact)); + break; + case 2: + ogs_assert(OGS_OK == smf_gtp_send_delete_session_response(sess, gtp_xact)); break; - if (use_rep->urr_id.presence == 0) - continue; - urr_id = use_rep->urr_id.u32; - if (!bearer || !bearer->urr || bearer->urr->id != urr_id) - continue; - ogs_pfcp_parse_volume_measurement(&volume, &use_rep->volume_measurement); - if (volume.ulvol) - sess->gy.ul_octets += volume.uplink_volume; - if (volume.dlvol) - sess->gy.dl_octets += volume.downlink_volume; - sess->gy.duration += use_rep->duration_measurement.u32; - } - - /* if !Gy */ - if (!ogs_diam_app_connected(OGS_DIAM_GY_APPLICATION_ID)) { - if (gtp_xact) { - /* - * 1. MME sends Delete Session Request to SGW/SMF. - * 2. SMF sends Delete Session Response to SGW/MME. - */ - switch (gtp_version) { - case 1: - ogs_assert(OGS_OK == smf_gtp1_send_delete_pdp_context_response(sess, gtp_xact)); - break; - case 2: - ogs_assert(OGS_OK == smf_gtp_send_delete_session_response(sess, gtp_xact)); - break; - } - } else { - /* - * 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. - * - * Note that the following messages are not processed here. - * - Bearer Resource Command - * - Delete Bearer Request/Response with DEDICATED BEARER. - */ } - SMF_SESS_CLEAR(sess); - return; + } else { + /* + * 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. + * + * Note that the following messages are not processed here. + * - Bearer Resource Command + * - Delete Bearer Request/Response with DEDICATED BEARER. + */ } - /* Gy is available, terminate the Gy session before terminating it towards the UE */ - /* TODO: here we iterate rsp->usage_report[i], if (report->type.usage_report) {... here we fill sess statistics...} */ - smf_gy_send_ccr(sess, gtp_xact, - OGS_DIAM_GY_CC_REQUEST_TYPE_TERMINATION_REQUEST); + SMF_SESS_CLEAR(sess); } void smf_n4_handle_session_report_request( @@ -1248,13 +1213,11 @@ void smf_n4_handle_session_report_request( ogs_pfcp_session_report_request_t *pfcp_req) { smf_bearer_t *qos_flow = NULL; - smf_bearer_t *bearer = NULL; ogs_pfcp_pdr_t *pdr = NULL; ogs_pfcp_report_type_t report_type; uint8_t cause_value = 0; uint16_t pdr_id = 0; - unsigned int i; ogs_assert(pfcp_xact); ogs_assert(pfcp_req); @@ -1380,37 +1343,8 @@ void smf_n4_handle_session_report_request( } } - if (report_type.usage_report) { - bearer = smf_default_bearer_in_sess(sess); - for (i = 0; i < OGS_ARRAY_SIZE(pfcp_req->usage_report); i++) { - ogs_pfcp_tlv_usage_report_session_report_request_t *use_rep = &pfcp_req->usage_report[i]; - uint32_t urr_id; - ogs_pfcp_volume_measurement_t volume; - if (use_rep->presence == 0) - break; - if (use_rep->urr_id.presence == 0) - continue; - urr_id = use_rep->urr_id.u32; - if (!bearer || !bearer->urr || bearer->urr->id != urr_id) - continue; - ogs_pfcp_parse_volume_measurement(&volume, &use_rep->volume_measurement); - if (volume.ulvol) - sess->gy.ul_octets += volume.uplink_volume; - if (volume.dlvol) - sess->gy.dl_octets += volume.downlink_volume; - sess->gy.duration += use_rep->duration_measurement.u32; - } - if (ogs_diam_app_connected(OGS_DIAM_GY_APPLICATION_ID)) { - smf_gy_send_ccr(sess, pfcp_xact, OGS_DIAM_GY_CC_REQUEST_TYPE_UPDATE_REQUEST); - } else { - ogs_error("No Gy Diameter Peer"); - } - } - /* TS 29.244 sec 8.2.21: At least one bit shall be set to "1". Several bits may be set to "1". */ - if (report_type.downlink_data_report || - report_type.error_indication_report || - report_type.usage_report) { + if (report_type.downlink_data_report || report_type.error_indication_report) { ogs_assert(OGS_OK == smf_pfcp_send_session_report_response( pfcp_xact, sess, OGS_PFCP_CAUSE_REQUEST_ACCEPTED)); diff --git a/src/smf/smf-sm.c b/src/smf/smf-sm.c index 5e54c0f2c..68ef56279 100644 --- a/src/smf/smf-sm.c +++ b/src/smf/smf-sm.c @@ -25,7 +25,6 @@ #include "s5c-handler.h" #include "gn-handler.h" #include "gx-handler.h" -#include "gy-handler.h" #include "nnrf-handler.h" #include "namf-handler.h" #include "npcf-handler.h" @@ -61,7 +60,6 @@ void smf_state_operational(ogs_fsm_t *s, smf_event_t *e) ogs_gtp1_message_t gtp1_message; ogs_diam_gx_message_t *gx_message = NULL; - ogs_diam_gy_message_t *gy_message = NULL; ogs_pfcp_node_t *pfcp_node = NULL; ogs_pfcp_xact_t *pfcp_xact = NULL; @@ -271,50 +269,6 @@ void smf_state_operational(ogs_fsm_t *s, smf_event_t *e) ogs_session_data_free(&gx_message->session_data); ogs_free(gx_message); break; - - case SMF_EVT_GY_MESSAGE: - ogs_assert(e); - gy_message = e->gy_message; - ogs_assert(gy_message); - - sess = e->sess; - ogs_assert(sess); - - switch(gy_message->cmd_code) { - case OGS_DIAM_GY_CMD_CODE_CREDIT_CONTROL: - switch(gy_message->cc_request_type) { - case OGS_DIAM_GY_CC_REQUEST_TYPE_INITIAL_REQUEST: - ogs_assert(e->gtp_xact); - smf_gy_handle_cca_initial_request( - sess, gy_message, e->gtp_xact); - break; - case OGS_DIAM_GY_CC_REQUEST_TYPE_UPDATE_REQUEST: - ogs_assert(e->pfcp_xact); - smf_gy_handle_cca_update_request( - sess, gy_message, e->pfcp_xact); - break; - case OGS_DIAM_GY_CC_REQUEST_TYPE_TERMINATION_REQUEST: - ogs_assert(e->gtp_xact); - smf_gy_handle_cca_termination_request( - sess, gy_message, e->gtp_xact); - break; - default: - ogs_error("Not implemented(%d)", gy_message->cc_request_type); - break; - } - - break; - case OGS_DIAM_GY_CMD_RE_AUTH: - smf_gy_handle_re_auth_request(sess, gy_message); - break; - default: - ogs_error("Invalid type(%d)", gy_message->cmd_code); - break; - } - - ogs_free(gy_message); - break; - case SMF_EVT_N4_MESSAGE: ogs_assert(e); recvbuf = e->pkbuf;