open5gs/src/smf/context.h

443 lines
14 KiB
C
Raw Normal View History

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/>.
*/
#ifndef SMF_CONTEXT_H
#define SMF_CONTEXT_H
#include "smf-config.h"
#include "ogs-gtp.h"
#include "ogs-diameter-gx.h"
2021-06-21 13:36:38 +00:00
#include "ogs-diameter-rx.h"
#include "ogs-diameter-s6b.h"
2020-04-26 19:36:05 +00:00
#include "ogs-pfcp.h"
2020-05-18 21:00:37 +00:00
#include "ogs-sbi.h"
2020-04-26 19:36:05 +00:00
#include "ogs-app.h"
2020-06-17 05:22:28 +00:00
#include "ogs-ngap.h"
#include "ogs-nas-5gs.h"
2020-04-26 19:36:05 +00:00
#include "ipfw/ogs-ipfw.h"
2020-05-14 17:38:26 +00:00
#include "timer.h"
#include "smf-sm.h"
#if HAVE_NET_IF_H
#include <net/if.h>
#endif
2020-04-26 19:36:05 +00:00
#ifdef __cplusplus
extern "C" {
#endif
extern int __smf_log_domain;
2020-06-17 05:22:28 +00:00
extern int __gsm_log_domain;
2020-04-26 19:36:05 +00:00
#undef OGS_LOG_DOMAIN
#define OGS_LOG_DOMAIN __smf_log_domain
typedef struct smf_context_s {
const char* diam_conf_path; /* SMF Diameter conf path */
ogs_diam_config_t *diam_config; /* SMF Diameter config */
2020-05-18 21:00:37 +00:00
OpenAPI_nf_type_e nf_type;
2020-04-26 19:36:05 +00:00
#define MAX_NUM_OF_DNS 2
const char *dns[MAX_NUM_OF_DNS];
const char *dns6[MAX_NUM_OF_DNS];
#define MAX_NUM_OF_P_CSCF 16
const char *p_cscf[MAX_NUM_OF_P_CSCF];
int num_of_p_cscf;
int p_cscf_index;
const char *p_cscf6[MAX_NUM_OF_P_CSCF];
int num_of_p_cscf6;
int p_cscf6_index;
ogs_list_t sgw_s5c_list; /* SGW GTPC Node List */
ogs_list_t ip_pool_list;
ogs_hash_t *supi_hash; /* hash table (SUPI) */
ogs_hash_t *imsi_hash; /* hash table (IMSI) */
2020-04-26 19:36:05 +00:00
ogs_hash_t *ipv4_hash; /* hash table (IPv4 Address) */
ogs_hash_t *ipv6_hash; /* hash table (IPv6 Address) */
2021-01-18 16:48:35 +00:00
ogs_hash_t *n1n2message_hash; /* hash table (N1N2Message Location) */
2020-04-26 19:36:05 +00:00
uint16_t mtu; /* MTU to advertise in PCO */
#define SMF_UE_IS_LAST_SESSION(__sMF) \
((__sMF) && (ogs_list_count(&(__sMF)->sess_list)) == 1)
ogs_list_t smf_ue_list;
2020-04-26 19:36:05 +00:00
} smf_context_t;
typedef struct smf_ue_s {
ogs_lnode_t lnode;
/* SUPI */
char *supi;
/* IMSI */
uint8_t imsi[OGS_MAX_IMSI_LEN];
int imsi_len;
char imsi_bcd[OGS_MAX_IMSI_BCD_LEN+1];
ogs_list_t sess_list;
} smf_ue_t;
#define SMF_NF_INSTANCE_CLEAR(_cAUSE, _nFInstance) \
do { \
ogs_assert(_nFInstance); \
if ((_nFInstance)->reference_count == 1) { \
ogs_info("[%s] (%s) NF removed", (_nFInstance)->id, (_cAUSE)); \
smf_nf_fsm_fini((_nFInstance)); \
} else { \
/* There is an assocation with other context */ \
ogs_info("[%s:%d] (%s) NF suspended", \
_nFInstance->id, _nFInstance->reference_count, (_cAUSE)); \
OGS_FSM_TRAN(&_nFInstance->sm, smf_nf_state_de_registered); \
ogs_fsm_dispatch(&_nFInstance->sm, NULL); \
} \
ogs_sbi_nf_instance_remove(_nFInstance); \
} while(0)
#define SMF_SESS_CLEAR(__sESS) \
do { \
smf_ue_t *smf_ue = NULL; \
ogs_assert(__sESS); \
smf_ue = __sESS->smf_ue; \
ogs_assert(smf_ue); \
if (SMF_UE_IS_LAST_SESSION(smf_ue)) \
smf_ue_remove(smf_ue); \
else \
smf_sess_remove(__sESS); \
} while(0)
typedef struct smf_bearer_s smf_bearer_t;
typedef struct smf_sess_s smf_sess_t;
typedef struct smf_pf_s {
ogs_lnode_t lnode;
ogs_lnode_t to_add_node;
ED3(uint8_t spare:2;,
uint8_t direction:2;,
uint8_t identifier:4;)
uint8_t precedence; /* Only used in EPC */
uint8_t epc_precedence; /* Only used in EPC */
uint8_t *identifier_node; /* Pool-Node for Identifier */
uint8_t *precedence_node; /* Pool-Node for Precedence */
2020-09-08 02:02:45 +00:00
ogs_ipfw_rule_t ipfw_rule;
char *flow_description;
smf_bearer_t *bearer;
} smf_pf_t;
typedef struct smf_bearer_s {
ogs_lnode_t lnode; /**< A node of list_t */
uint32_t index;
ogs_pfcp_pdr_t *dl_pdr;
ogs_pfcp_pdr_t *ul_pdr;
ogs_pfcp_far_t *dl_far;
ogs_pfcp_far_t *ul_far;
2021-10-04 13:28:32 +00:00
ogs_pfcp_urr_t *urr;
ogs_pfcp_qer_t *qer;
2020-09-02 03:04:35 +00:00
uint8_t *qfi_node; /* Pool-Node for 5GC-QFI */
uint8_t qfi; /* 5G Core QFI */
uint8_t ebi; /* EPC EBI */
uint32_t pgw_s5u_teid; /* PGW-S5U TEID */
ogs_sockaddr_t *pgw_s5u_addr; /* PGW-S5U IPv4 */
ogs_sockaddr_t *pgw_s5u_addr6; /* PGW-S5U IPv6 */
uint32_t sgw_s5u_teid; /* SGW-S5U TEID */
ogs_ip_t sgw_s5u_ip; /* SGW-S5U IPv4/IPv6 */
2021-01-01 02:07:08 +00:00
struct {
2021-06-21 13:36:38 +00:00
char *name; /* EPC: PCC Rule Name */
char *id; /* 5GC: PCC Rule Id */
2021-01-01 02:07:08 +00:00
} pcc_rule;
ogs_qos_t qos; /* QoS Infomration */
2020-09-08 02:02:45 +00:00
OGS_POOL(pf_identifier_pool, uint8_t);
/* Packet Filter List */
ogs_list_t pf_list;
ogs_list_t pf_to_add_list;
smf_sess_t *sess;
} smf_bearer_t;
#define SMF_SESS(pfcp_sess) ogs_container_of(pfcp_sess, smf_sess_t, pfcp)
2020-04-26 19:36:05 +00:00
typedef struct smf_sess_s {
2020-06-17 05:22:28 +00:00
ogs_sbi_object_t sbi;
2020-04-26 19:36:05 +00:00
uint32_t index; /**< An index of this node */
2020-06-17 05:22:28 +00:00
ogs_fsm_t sm; /* A state machine */
2020-04-26 19:36:05 +00:00
ogs_pfcp_sess_t pfcp; /* PFCP session context */
2021-01-01 02:07:08 +00:00
uint64_t smpolicycontrol_features; /* SBI features */
2020-04-26 19:36:05 +00:00
uint32_t smf_n4_teid; /* SMF-N4-TEID is derived from INDEX */
2021-06-21 13:36:38 +00:00
2020-04-26 19:36:05 +00:00
uint32_t sgw_s5c_teid; /* SGW-S5C-TEID is received from SGW */
2021-06-21 13:36:38 +00:00
ogs_ip_t sgw_s5c_ip; /* SGW-S5C IPv4/IPv6 */
2020-04-26 19:36:05 +00:00
uint64_t smf_n4_seid; /* SMF SEID is dervied from INDEX */
uint64_t upf_n4_seid; /* UPF SEID is received from Peer */
2020-07-20 01:42:58 +00:00
uint32_t upf_n3_teid; /* UPF-N3 TEID */
ogs_sockaddr_t *upf_n3_addr; /* UPF-N3 IPv4 */
ogs_sockaddr_t *upf_n3_addr6; /* UPF-N3 IPv6 */
uint32_t gnb_n3_teid; /* gNB-N3 TEID */
ogs_ip_t gnb_n3_ip; /* gNB-N3 IPv4/IPv6 */
2020-04-26 19:36:05 +00:00
char *gx_sid; /* Gx Session ID */
2021-06-21 13:36:38 +00:00
char *s6b_sid; /* S6b Session ID */
2020-04-26 19:36:05 +00:00
OGS_POOL(pf_precedence_pool, uint8_t);
#define CLEAR_QOS_FLOW_ID(__sESS) \
do { \
ogs_assert((__sESS)); \
smf_qfi_pool_final(__sESS); \
smf_qfi_pool_init(__sESS); \
} while(0)
OGS_POOL(qfi_pool, uint8_t);
2020-04-26 19:36:05 +00:00
char *sm_context_ref; /* smContextRef */
uint8_t psi; /* PDU session identity */
2020-06-22 03:07:14 +00:00
uint8_t pti; /* Procedure transaction identity */
2020-06-17 05:22:28 +00:00
2020-07-02 05:50:23 +00:00
char *sm_context_status_uri; /* SmContextStatusNotification */
struct {
ogs_sbi_client_t *client;
} namf;
2020-12-11 19:03:20 +00:00
/* PCF sends the RESPONSE
* of [POST] /npcf-smpolocycontrol/v1/policies */
char *policy_association_id;
2020-06-17 05:22:28 +00:00
/* PLMN ID & NID */
ogs_plmn_id_t plmn_id;
2020-07-09 05:38:09 +00:00
/* LTE Location */
ogs_eps_tai_t e_tai;
ogs_e_cgi_t e_cgi;
/* NR Location */
ogs_5gs_tai_t nr_tai;
ogs_nr_cgi_t nr_cgi;
ogs_time_t ue_location_timestamp;
2020-06-17 05:22:28 +00:00
2021-01-01 02:07:08 +00:00
/* PCF ID */
char *pcf_id;
2020-06-17 05:22:28 +00:00
/* Integrity protection maximum data rate */
struct {
uint8_t mbr_dl;
uint8_t mbr_ul;
} integrity_protection;
/* S_NSSAI */
ogs_s_nssai_t s_nssai;
ogs_s_nssai_t mapped_hplmn;
2020-06-17 05:22:28 +00:00
/* PDN Configuration */
ogs_session_t session;
2020-06-17 05:22:28 +00:00
uint8_t ue_pdu_session_type;
uint8_t ue_ssc_mode;
2020-04-26 19:36:05 +00:00
ogs_pfcp_ue_ip_t *ipv4;
ogs_pfcp_ue_ip_t *ipv6;
2021-06-21 13:36:38 +00:00
/* RAT Type */
uint8_t gtp_rat_type;
OpenAPI_rat_type_e sbi_rat_type;
2020-06-23 04:35:41 +00:00
struct {
ogs_tlv_octet_t ue_pco;
ogs_tlv_octet_t user_location_information;
ogs_tlv_octet_t ue_timezone;
2021-01-18 16:48:35 +00:00
bool create_session_response_apn_ambr;
bool create_session_response_bearer_qos;
2020-06-23 04:35:41 +00:00
} gtp; /* Saved from S5-C */
struct {
ogs_nas_extended_protocol_configuration_options_t ue_pco;
} nas; /* Saved from NAS-5GS */
2020-04-26 19:36:05 +00:00
ogs_pcc_rule_t pcc_rule[OGS_MAX_NUM_OF_PCC_RULE]; /* Saved from Gx */
int num_of_pcc_rule;
2021-01-18 16:48:35 +00:00
/* Paging */
2020-07-20 01:42:58 +00:00
struct {
2021-01-18 16:48:35 +00:00
bool ue_requested_pdu_session_establishment_done;
char *n1n2message_location;
} paging;
2020-06-22 03:07:14 +00:00
2020-07-30 03:26:12 +00:00
/* Release Holding timer of SMF session context */
ogs_timer_t *t_release_holding;
2021-01-18 16:48:35 +00:00
/* State */
#define SMF_NGAP_STATE_NONE 0
#define SMF_NGAP_STATE_DELETE_TRIGGER_UE_REQUESTED 1
#define SMF_NGAP_STATE_ERROR_INDICATION_RECEIVED_FROM_5G_AN 2
struct {
int pdu_session_resource_release;
} ngap_state;
2021-01-28 19:23:54 +00:00
/* Handover */
struct {
bool prepared;
bool data_forwarding_not_possible;
bool indirect_data_forwarding;
/* NG-U UP Transport Information Saved Temporally */
2021-01-28 19:23:54 +00:00
uint32_t gnb_n3_teid;
ogs_ip_t gnb_n3_ip;
/* Indirect DL Forwarding */
uint32_t upf_dl_teid;
ogs_sockaddr_t *upf_dl_addr;
ogs_sockaddr_t *upf_dl_addr6;
uint32_t gnb_dl_teid;
ogs_ip_t gnb_dl_ip;
} handover;
2021-01-28 19:23:54 +00:00
2021-06-21 13:36:38 +00:00
/* Charging */
struct {
uint32_t id;
} charging;
2021-03-15 01:01:55 +00:00
/* Data Forwarding between the CP and UP functions */
ogs_pfcp_pdr_t *cp2up_pdr;
ogs_pfcp_pdr_t *up2cp_pdr;
ogs_pfcp_far_t *cp2up_far;
ogs_pfcp_far_t *up2cp_far;
2020-04-26 19:36:05 +00:00
ogs_list_t bearer_list;
ogs_gtp_node_t *gnode;
ogs_pfcp_node_t *pfcp_node;
2020-06-17 05:22:28 +00:00
smf_ue_t *smf_ue;
2020-04-26 19:36:05 +00:00
} smf_sess_t;
void smf_context_init(void);
void smf_context_final(void);
smf_context_t *smf_self(void);
int smf_context_parse_config(void);
smf_ue_t *smf_ue_add_by_supi(char *supi);
smf_ue_t *smf_ue_add_by_imsi(uint8_t *imsi, int imsi_len);
void smf_ue_remove(smf_ue_t *smf_ue);
void smf_ue_remove_all(void);
smf_ue_t *smf_ue_find_by_supi(char *supi);
smf_ue_t *smf_ue_find_by_imsi(uint8_t *imsi, int imsi_len);
2020-06-17 05:22:28 +00:00
smf_sess_t *smf_sess_add_by_gtp_message(ogs_gtp_message_t *message);
2021-06-21 13:36:38 +00:00
smf_sess_t *smf_sess_add_by_apn(smf_ue_t *smf_ue, char *apn, uint8_t rat_type);
2020-04-26 19:36:05 +00:00
2020-06-17 05:22:28 +00:00
smf_sess_t *smf_sess_add_by_sbi_message(ogs_sbi_message_t *message);
smf_sess_t *smf_sess_add_by_psi(smf_ue_t *smf_ue, uint8_t psi);
2020-06-17 05:22:28 +00:00
2020-07-20 01:42:58 +00:00
void smf_sess_select_upf(smf_sess_t *sess);
uint8_t smf_sess_set_ue_ip(smf_sess_t *sess);
2021-01-18 16:48:35 +00:00
void smf_sess_set_paging_n1n2message_location(
smf_sess_t *sess, char *n1n2message_location);
2020-07-20 01:42:58 +00:00
void smf_sess_remove(smf_sess_t *sess);
void smf_sess_remove_all(smf_ue_t *smf_ue);
2020-04-26 19:36:05 +00:00
smf_sess_t *smf_sess_find(uint32_t index);
smf_sess_t *smf_sess_find_by_teid(uint32_t teid);
smf_sess_t *smf_sess_find_by_seid(uint64_t seid);
2021-06-21 13:36:38 +00:00
smf_sess_t *smf_sess_find_by_apn(smf_ue_t *smf_ue, char *apn, uint8_t rat_type);
smf_sess_t *smf_sess_find_by_psi(smf_ue_t *smf_ue, uint8_t psi);
2021-06-21 13:36:38 +00:00
smf_sess_t *smf_sess_find_by_charging_id(uint32_t charging_id);
2020-06-17 05:22:28 +00:00
smf_sess_t *smf_sess_find_by_sm_context_ref(char *sm_context_ref);
2020-04-26 19:36:05 +00:00
smf_sess_t *smf_sess_find_by_ipv4(uint32_t addr);
smf_sess_t *smf_sess_find_by_ipv6(uint32_t *addr6);
2021-01-18 16:48:35 +00:00
smf_sess_t *smf_sess_find_by_paging_n1n2message_location(
char *n1n2message_location);
smf_sess_t *smf_sess_find_by_error_indication_report(
smf_ue_t *smf_ue,
ogs_pfcp_tlv_error_indication_report_t *error_indication_report);
2020-04-26 19:36:05 +00:00
void smf_sess_create_indirect_data_forwarding(smf_sess_t *sess);
bool smf_sess_have_indirect_data_forwarding(smf_sess_t *sess);
void smf_sess_delete_indirect_data_forwarding(smf_sess_t *sess);
2021-03-15 01:01:55 +00:00
void smf_sess_create_cp_up_data_forwarding(smf_sess_t *sess);
void smf_sess_delete_cp_up_data_forwarding(smf_sess_t *sess);
2020-07-20 01:42:58 +00:00
smf_bearer_t *smf_qos_flow_add(smf_sess_t *sess);
smf_bearer_t *smf_qos_flow_find_by_qfi(smf_sess_t *sess, uint8_t qfi);
2021-01-01 02:07:08 +00:00
smf_bearer_t *smf_qos_flow_find_by_pcc_rule_id(
smf_sess_t *sess, char *pcc_rule_id);
2020-07-20 01:42:58 +00:00
2020-04-26 19:36:05 +00:00
smf_bearer_t *smf_bearer_add(smf_sess_t *sess);
int smf_bearer_remove(smf_bearer_t *bearer);
void smf_bearer_remove_all(smf_sess_t *sess);
smf_bearer_t *smf_bearer_find_by_pgw_s5u_teid(
smf_sess_t *sess, uint32_t pgw_s5u_teid);
2020-04-26 19:36:05 +00:00
smf_bearer_t *smf_bearer_find_by_ebi(smf_sess_t *sess, uint8_t ebi);
2021-01-01 02:07:08 +00:00
smf_bearer_t *smf_bearer_find_by_pcc_rule_name(
smf_sess_t *sess, char *pcc_rule_name);
smf_bearer_t *smf_bearer_find_by_pdr_id(
smf_sess_t *sess, ogs_pfcp_pdr_id_t pdr_id);
2020-04-26 19:36:05 +00:00
smf_bearer_t *smf_default_bearer_in_sess(smf_sess_t *sess);
smf_ue_t *smf_ue_cycle(smf_ue_t *smf_ue);
smf_sess_t *smf_sess_cycle(smf_sess_t *sess);
smf_bearer_t *smf_qos_flow_cycle(smf_bearer_t *qos_flow);
smf_bearer_t *smf_bearer_cycle(smf_bearer_t *bearer);
void smf_sess_select_nf(smf_sess_t *sess, OpenAPI_nf_type_e nf_type);
2021-01-01 02:07:08 +00:00
smf_pf_t *smf_pf_add(smf_bearer_t *bearer);
2020-04-26 19:36:05 +00:00
int smf_pf_remove(smf_pf_t *pf);
void smf_pf_remove_all(smf_bearer_t *bearer);
smf_pf_t *smf_pf_find_by_id(smf_bearer_t *smf_bearer, uint8_t id);
smf_pf_t *smf_pf_find_by_flow(
smf_bearer_t *bearer, uint8_t direction, char *flow_description);
2020-04-26 19:36:05 +00:00
smf_pf_t *smf_pf_first(smf_bearer_t *bearer);
smf_pf_t *smf_pf_next(smf_pf_t *pf);
2020-06-23 04:35:41 +00:00
int smf_pco_build(uint8_t *pco_buf, uint8_t *buffer, int length);
2020-04-26 19:36:05 +00:00
void smf_qfi_pool_init(smf_sess_t *sess);
void smf_qfi_pool_final(smf_sess_t *sess);
2020-09-08 02:02:45 +00:00
void smf_pf_identifier_pool_init(smf_bearer_t *bearer);
void smf_pf_identifier_pool_final(smf_bearer_t *bearer);
void smf_pf_precedence_pool_init(smf_sess_t *sess);
void smf_pf_precedence_pool_final(smf_sess_t *sess);
2020-04-26 19:36:05 +00:00
#ifdef __cplusplus
}
#endif
#endif /* SMF_CONTEXT_H */