For EPC, tested scenario is IMSI attach with EURECOM NAS UE, (not GUTI)

git-svn-id: http://svn.eurecom.fr/openair4G/trunk@5282 818b1a75-f10b-46b9-bf7c-635c3b92a50f
This commit is contained in:
Lionel Gauthier
2014-04-22 10:51:56 +00:00
parent 72fd579b8e
commit b3829736e3
122 changed files with 5794 additions and 2432 deletions
+1 -1
View File
@@ -5,7 +5,6 @@
// Messages files used between tasks
#include "gtpv1_u_messages_def.h"
#include "ip_forward_messages_def.h"
#include "mme_app_messages_def.h"
#include "nas_messages_def.h"
#include "s11_messages_def.h"
#include "s1ap_messages_def.h"
@@ -13,3 +12,4 @@
#include "sctp_messages_def.h"
#include "sgw_lite_def.h"
#include "udp_messages_def.h"
#include "mme_app_messages_def.h"
+1 -1
View File
@@ -15,7 +15,6 @@
#include "gtpv1_u_messages_types.h"
#include "ip_forward_messages_types.h"
#include "mme_app_messages_types.h"
#include "s11_messages_types.h"
#include "s1ap_messages_types.h"
#include "nas_messages_types.h"
@@ -23,5 +22,6 @@
#include "sctp_messages_types.h"
#include "sgw_lite_messages_types.h"
#include "udp_messages_types.h"
#include "mme_app_messages_types.h"
#endif /* MESSAGES_TYPES_H_ */
+3
View File
@@ -1,2 +1,5 @@
//WARNING: Do not include this header directly. Use intertask_interface.h instead.
MESSAGE_DEF(MME_APP_CONNECTION_ESTABLISHMENT_IND , MESSAGE_PRIORITY_MED, mme_app_connection_establishment_ind_t , mme_app_connection_establishment_ind)
MESSAGE_DEF(MME_APP_CONNECTION_ESTABLISHMENT_CNF , MESSAGE_PRIORITY_MED, mme_app_connection_establishment_cnf_t , mme_app_connection_establishment_cnf)
MESSAGE_DEF(MME_APP_INITIAL_CONTEXT_SETUP_RSP , MESSAGE_PRIORITY_MED, mme_app_initial_context_setup_rsp_t , mme_app_initial_context_setup_rsp)
@@ -2,5 +2,38 @@
#define MME_APP_MESSAGES_TYPES_H_
#define MME_APP_CONNECTION_ESTABLISHMENT_IND(mSGpTR) (mSGpTR)->ittiMsg.mme_app_connection_establishment_ind
#define MME_APP_CONNECTION_ESTABLISHMENT_CNF(mSGpTR) (mSGpTR)->ittiMsg.mme_app_connection_establishment_cnf
#define MME_APP_INITIAL_CONTEXT_SETUP_RSP(mSGpTR) (mSGpTR)->ittiMsg.mme_app_initial_context_setup_rsp
typedef struct mme_app_connection_establishment_ind_s {
uint32_t mme_ue_s1ap_id;
nas_establish_ind_t nas;
/* Transparent message from s1ap to be forwarded to MME_APP or
* to S1AP if connection establishment is rejected by NAS.
*/
s1ap_initial_ue_message_t transparent;
} mme_app_connection_establishment_ind_t;
typedef struct mme_app_connection_establishment_cnf_s {
ebi_t eps_bearer_id;
FTeid_t bearer_s1u_sgw_fteid;
qci_t bearer_qos_qci;
priority_level_t bearer_qos_prio_level;
pre_emp_vulnerability_t bearer_qos_pre_emp_vulnerability;
pre_emp_capability_t bearer_qos_pre_emp_capability;
ambr_t ambr;
nas_conn_est_cnf_t nas_conn_est_cnf;
} mme_app_connection_establishment_cnf_t;
typedef struct mme_app_initial_context_setup_rsp_s {
uint32_t mme_ue_s1ap_id;
ebi_t eps_bearer_id;
FTeid_t bearer_s1u_enb_fteid;
} mme_app_initial_context_setup_rsp_t;
#endif /* MME_APP_MESSAGES_TYPES_H_ */
+4 -3
View File
@@ -35,9 +35,10 @@ MESSAGE_DEF(NAS_RAB_RELEASE_REQ, MESSAGE_PRIORITY_MED, nas_rab_
MESSAGE_DEF(NAS_AUTHENTICATION_PARAM_REQ, MESSAGE_PRIORITY_MED, nas_auth_param_req_t, nas_auth_param_req)
/* MME app -> NAS layer messages */
MESSAGE_DEF(NAS_BEARER_PARAM, MESSAGE_PRIORITY_MED, nas_bearer_param_t, nas_bearer_param)
MESSAGE_DEF(NAS_AUTHENTICATION_PARAM_RSP, MESSAGE_PRIORITY_MED, nas_auth_param_rsp_t, nas_auth_param_rsp)
MESSAGE_DEF(NAS_AUTHENTICATION_PARAM_FAIL, MESSAGE_PRIORITY_MED, nas_auth_param_fail_t, nas_auth_param_fail)
MESSAGE_DEF(NAS_PDN_CONNECTIVITY_RSP, MESSAGE_PRIORITY_MED, nas_pdn_connectivity_rsp_t, nas_pdn_connectivity_rsp)
MESSAGE_DEF(NAS_PDN_CONNECTIVITY_FAIL, MESSAGE_PRIORITY_MED, nas_pdn_connectivity_fail_t, nas_pdn_connectivity_fail)
MESSAGE_DEF(NAS_AUTHENTICATION_PARAM_RSP, MESSAGE_PRIORITY_MED, nas_auth_param_rsp_t, nas_auth_param_rsp)
MESSAGE_DEF(NAS_AUTHENTICATION_PARAM_FAIL, MESSAGE_PRIORITY_MED, nas_auth_param_fail_t, nas_auth_param_fail)
#if defined(DISABLE_USE_NAS)
MESSAGE_DEF(NAS_ATTACH_REQ, MESSAGE_PRIORITY_MED, nas_attach_req_t, nas_attach_req)
+83 -39
View File
@@ -24,6 +24,8 @@
#define NAS_DL_DATA_REQ(mSGpTR) (mSGpTR)->ittiMsg.nas_dl_data_req
#define NAS_DL_DATA_CNF(mSGpTR) (mSGpTR)->ittiMsg.nas_dl_data_cnf
#define NAS_PDN_CONNECTIVITY_REQ(mSGpTR) (mSGpTR)->ittiMsg.nas_pdn_connectivity_req
#define NAS_PDN_CONNECTIVITY_RSP(mSGpTR) (mSGpTR)->ittiMsg.nas_pdn_connectivity_rsp
#define NAS_PDN_CONNECTIVITY_FAIL(mSGpTR) (mSGpTR)->ittiMsg.nas_pdn_connectivity_fail
#define NAS_CONN_EST_IND(mSGpTR) (mSGpTR)->ittiMsg.nas_conn_est_ind
#define NAS_CONNECTION_ESTABLISHMENT_CNF(mSGpTR) (mSGpTR)->ittiMsg.nas_conn_est_cnf
#define NAS_BEARER_PARAM(mSGpTR) (mSGpTR)->ittiMsg.nas_bearer_param
@@ -34,6 +36,8 @@
#define NAS_DATA_LENGHT_MAX 256
typedef enum {
EMM_MSG_HEADER = 1,
EMM_MSG_ATTACH_REQUEST,
@@ -67,6 +71,8 @@ typedef enum {
EMM_MSG_CS_SERVICE_NOTIFICATION,
} emm_message_ids_t;
typedef enum {
ESM_MSG_HEADER = 1,
ESM_MSG_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REQUEST,
@@ -93,50 +99,103 @@ typedef enum {
ESM_MSG_ESM_STATUS,
} esm_message_ids_t;
typedef struct nas_raw_msg_s {
uint32_t lenght;
uint8_t data[NAS_DATA_LENGHT_MAX];
} nas_raw_msg_t;
typedef struct nas_emm_plain_msg_s {
emm_message_ids_t present;
EMM_msg choice;
} nas_emm_plain_msg_t;
typedef struct nas_emm_protected_msg_s {
nas_message_security_header_t header;
emm_message_ids_t present;
EMM_msg choice;
} nas_emm_protected_msg_t;
typedef struct nas_esm_plain_msg_s {
esm_message_ids_t present;
ESM_msg choice;
} nas_esm_plain_msg_t;
typedef struct nas_esm_protected_msg_s {
nas_message_security_header_t header;
esm_message_ids_t present;
ESM_msg choice;
} nas_esm_protected_msg_t;
typedef struct nas_paging_ind_s {
} nas_paging_ind_t;
typedef struct nas_pdn_connectivity_req_s {
char imsi[16];
uint8_t imsi_length;
OctetString apn;
OctetString pdn_addr;
int mme_pdn_index;
network_qos_t esm_qos;
int is_emergency;
int pti; // nas ref Identity of the procedure transaction executed to activate the PDN connection entry
unsigned ue_id; // nas ref
char imsi[16];
uint8_t imsi_length;
network_qos_t qos;
OctetString apn;
OctetString pdn_addr;
int pdn_type;
void *proc_data;
int request_type;
} nas_pdn_connectivity_req_t;
typedef struct nas_pdn_connectivity_rsp_s {
int pti; // nas ref Identity of the procedure transaction executed to activate the PDN connection entry
unsigned ue_id; // nas ref
network_qos_t qos;
OctetString apn;
OctetString pdn_addr;
int pdn_type;
void *proc_data;
int request_type;
unsigned eNB_ue_s1ap_id:24;
uint32_t mme_ue_s1ap_id;
/* Key eNB */
uint8_t keNB[32];
ambr_t ambr;
ambr_t apn_ambr;
/* EPS bearer ID */
unsigned ebi:4;
/* QoS */
qci_t qci;
priority_level_t prio_level;
pre_emp_vulnerability_t pre_emp_vulnerability;
pre_emp_capability_t pre_emp_capability;
/* S-GW TEID for user-plane */
Teid_t sgw_s1u_teid;
/* S-GW IP address for User-Plane */
ip_address_t sgw_s1u_address;
} nas_pdn_connectivity_rsp_t;
typedef struct nas_pdn_connectivity_fail_s {
unsigned ue_id; // nas ref
} nas_pdn_connectivity_fail_t;
typedef struct nas_conn_est_ind_s {
nas_establish_ind_t nas;
@@ -146,8 +205,10 @@ typedef struct nas_conn_est_ind_s {
s1ap_initial_ue_message_t transparent;
} nas_conn_est_ind_t;
typedef nas_establish_rsp_t nas_conn_est_rej_t;
#if defined(DISABLE_USE_NAS)
typedef struct nas_conn_est_cnf_s {
uint32_t ue_id;
@@ -160,56 +221,35 @@ typedef struct nas_conn_est_cnf_s {
typedef nas_establish_cnf_t nas_conn_est_cnf_t;
#endif
typedef struct nas_bearer_param_s {
unsigned eNB_ue_s1ap_id:24;
uint32_t mme_ue_s1ap_id;
/* Key eNB */
uint8_t keNB[32];
ambr_t ambr;
ambr_t apn_ambr;
/* EPS bearer ID */
unsigned ebi:4;
/* QoS */
qci_t qci;
priority_level_t prio_level;
pre_emp_vulnerability_t pre_emp_vulnerability;
pre_emp_capability_t pre_emp_capability;
/* S-GW TEID for user-plane */
uint32_t sgw_s1u_teid;
/* S-GW IP address for User-Plane */
ip_address_t sgw_s1u_address;
} nas_bearer_param_t;
typedef struct nas_conn_rel_ind_s {
} nas_conn_rel_ind_t;
typedef ul_info_transfer_ind_t nas_ul_data_ind_t;
typedef dl_info_transfer_req_t nas_dl_data_req_t;
typedef dl_info_transfer_cnf_t nas_dl_data_cnf_t;
typedef struct nas_non_del_ind_s {
} nas_non_del_ind_t;
typedef struct nas_rab_est_req_s {
} nas_rab_est_req_t;
typedef struct nas_rab_est_rsp_s {
} nas_rab_est_rsp_t;
typedef struct nas_rab_rel_req_s {
} nas_rab_rel_req_t;
typedef struct nas_attach_req_s {
/* TODO: Set the correct size */
char apn[100];
@@ -219,6 +259,7 @@ typedef struct nas_attach_req_s {
s1ap_initial_ue_message_t transparent;
} nas_attach_req_t;
typedef struct nas_auth_req_s {
/* UE imsi */
char imsi[16];
@@ -229,6 +270,7 @@ typedef struct nas_auth_req_s {
int cause;
} nas_auth_req_t;
typedef struct nas_auth_resp_s {
char imsi[16];
} nas_auth_resp_t;
@@ -244,10 +286,11 @@ typedef struct nas_auth_param_req_s {
/* Indicates whether the procedure corresponds to a new connection or not */
uint8_t initial_req:1;
uint8_t re_synchronization:1;
uint8_t auts[14];
uint8_t re_synchronization:1;
uint8_t auts[14];
} nas_auth_param_req_t;
typedef struct nas_auth_param_rsp_s {
/* UE identifier */
uint32_t ue_id;
@@ -267,6 +310,7 @@ typedef struct nas_auth_param_fail_s {
nas_cause_t cause;
} nas_auth_param_fail_t;
#if defined(DISABLE_USE_NAS)
typedef struct nas_attach_accept_s {
s1ap_initial_ctxt_setup_req_t transparent;
+15 -15
View File
@@ -5,23 +5,23 @@
#define S1AP_DEREGISTER_UE_REQ(mSGpTR) (mSGpTR)->ittiMsg.s1ap_deregister_ue_req
typedef struct s1ap_initial_ue_message_s {
unsigned eNB_ue_s1ap_id:24;
uint32_t mme_ue_s1ap_id;
cgi_t e_utran_cgi;
unsigned eNB_ue_s1ap_id:24;
uint32_t mme_ue_s1ap_id;
cgi_t e_utran_cgi;
} s1ap_initial_ue_message_t;
typedef struct s1ap_initial_ctxt_setup_req_s {
unsigned eNB_ue_s1ap_id:24;
uint32_t mme_ue_s1ap_id;
unsigned eNB_ue_s1ap_id:24;
uint32_t mme_ue_s1ap_id;
/* Key eNB */
uint8_t keNB[32];
uint8_t keNB[32];
ambr_t ambr;
ambr_t apn_ambr;
ambr_t ambr;
ambr_t apn_ambr;
/* EPS bearer ID */
unsigned ebi:4;
unsigned ebi:4;
/* QoS */
qci_t qci;
@@ -30,16 +30,16 @@ typedef struct s1ap_initial_ctxt_setup_req_s {
pre_emp_capability_t pre_emp_capability;
/* S-GW TEID for user-plane */
uint32_t teid;
Teid_t teid;
/* S-GW IP address for User-Plane */
ip_address_t s_gw_address;
ip_address_t s_gw_address;
} s1ap_initial_ctxt_setup_req_t;
typedef struct s1ap_ue_cap_ind_s {
unsigned eNB_ue_s1ap_id:24;
uint32_t mme_ue_s1ap_id;
uint8_t radio_capabilities[100];
uint32_t radio_capabilities_length;
unsigned eNB_ue_s1ap_id:24;
uint32_t mme_ue_s1ap_id;
uint8_t radio_capabilities[100];
uint32_t radio_capabilities_length;
} s1ap_ue_cap_ind_t;
#define S1AP_ITTI_UE_PER_DEREGISTER_MESSAGE 20
+22 -8
View File
@@ -5,23 +5,37 @@
typedef struct s6a_update_location_req_s {
#define SKIP_SUBSCRIBER_DATA (0x1)
unsigned skip_subsriber_data:1;
unsigned skip_subscriber_data:1;
#define INITIAL_ATTACH (0x1)
unsigned initial_attach:1;
char imsi[IMSI_DIGITS_MAX + 1];
uint8_t imsi_length;
plmn_t visited_plmn;
rat_type_t rat_type;
char imsi[IMSI_DIGITS_MAX + 1]; // username
uint8_t imsi_length; // username
plmn_t visited_plmn; // visited plmn id
rat_type_t rat_type; // rat type
// missing // origin host
// missing // origin realm
// missing // destination host
// missing // destination realm
} s6a_update_location_req_t;
typedef struct s6a_update_location_ans_s {
s6a_result_t result; // Result of the update location request procedure
subscription_data_t subscription_data; // subscriber status,
// Maximum Requested Bandwidth Uplink, downlink
// access restriction data
// msisdn
apn_config_profile_t apn_config_profile;// APN configuration profile
network_access_mode_t access_mode;
rau_tau_timer_t rau_tau_timer;
char imsi[IMSI_DIGITS_MAX + 1];
uint8_t imsi_length;
/* Result of the update location request procedure */
s6a_result_t result;
subscription_data_t subscription_data;
} s6a_update_location_ans_t;
typedef struct s6a_auth_info_req_s {
+710 -49
View File
@@ -42,6 +42,14 @@
#ifndef SGW_LITE_MESSAGES_TYPES_H_
#define SGW_LITE_MESSAGES_TYPES_H_
#define SGW_CREATE_SESSION_REQUEST(mSGpTR) (mSGpTR)->ittiMsg.sgwCreateSessionRequest
#define SGW_CREATE_SESSION_RESPONSE(mSGpTR) (mSGpTR)->ittiMsg.sgwCreateSessionResponse
#define SGW_MODIFY_BEARER_REQUEST(mSGpTR) (mSGpTR)->ittiMsg.sgwModifyBearerRequest
#define SGW_MODIFY_BEARER_RESPONSE(mSGpTR) (mSGpTR)->ittiMsg.sgwModifyBearerResponse
#define SGW_DELETE_SESSION_REQUEST(mSGpTR) (mSGpTR)->ittiMsg.sgwDeleteSessionRequest
#define SGW_DELETE_SESSION_RESPONSE(mSGpTR) (mSGpTR)->ittiMsg.sgwDeleteSessionResponse
/** @struct SgwCreateSessionRequest
* @brief Create Session Request
*
@@ -52,29 +60,266 @@
* - Tracking Area Update procedure with Serving GW change
* - S1/X2-based handover with SGW change
*/
typedef struct {
typedef struct SgwCreateSessionRequest_s{
Teid_t teid; ///< S11- S-GW Tunnel Endpoint Identifier
Imsi_t imsi;
Msisdn_t msisdn;
Mei_t mei;
Uli_t uli;
ServingNetwork_t serving_network;
rat_type_t rat_type;
FTeid_t sender_fteid_for_cp; ///< Sender F-TEID for control plane (MME)
FTeid_t pgw_address_for_cp; ///< PGW S5/S8 address for control plane or PMIP
char apn[APN_MAX_LENGTH + 1]; ///< Access Point Name
SelectionMode_t selection_mode; ///< Selection Mode
pdn_type_t pdn_type; ///< PDN Type
PAA_t paa; ///< PDN Address Allocation
/* Shall include APN Restriction but not used in our case */
ambr_t ambr; ///< Aggregate Maximum Bit Rate
/* TODO: add Protocol Configuration options */
FQ_CSID_t mme_fq_csid;
UETimeZone_t ue_time_zone;
UCI_t uci; ///< User CSG Information
bearer_to_create_t bearer_to_create; ///< Bearer Contexts to be created
indication_flags_t indication_flags;
Imsi_t imsi; ///< The IMSI shall be included in the message on the S4/S11
///< interface, and on S5/S8 interface if provided by the
///< MME/SGSN, except for the case:
///< - If the UE is emergency attached and the UE is UICCless.
///< The IMSI shall be included in the message on the S4/S11
///< interface, and on S5/S8 interface if provided by the
///< MME/SGSN, but not used as an identifier
///< - if UE is emergency attached but IMSI is not authenticated.
///< The IMSI shall be included in the message on the S2b interface.
Msisdn_t msisdn; ///< For an E-UTRAN Initial Attach the IE shall be included
///< when used on the S11 interface, if provided in the
///< subscription data from the HSS.
///< For a PDP Context Activation procedure the IE shall be
///< included when used on the S4 interface, if provided in the
///< subscription data from the HSS.
///< The IE shall be included for the case of a UE Requested
///< PDN Connectivity, if the MME has it stored for that UE.
///< It shall be included when used on the S5/S8 interfaces if
///< provided by the MME/SGSN.
///< The ePDG shall include this IE on the S2b interface during
///< an Attach with GTP on S2b and a UE initiated Connectivity
///< to Additional PDN with GTP on S2b, if provided by the
///< HSS/AAA.
Mei_t mei; ///< The MME/SGSN shall include the ME Identity (MEI) IE on
///< the S11/S4 interface:
///< - If the UE is emergency attached and the UE is UICCless
///< - If the UE is emergency attached and the IMSI is not authenticated
///< For all other cases the MME/SGSN shall include the ME
///< Identity (MEI) IE on the S11/S4 interface if it is available.
///< If the SGW receives this IE, it shall forward it to the PGW
///< on the S5/S8 interface.
Uli_t uli; ///< This IE shall be included on the S11 interface for E-
///< UTRAN Initial Attach and UE-requested PDN Connectivity
///< procedures. It shall include ECGI&TAI. The MME/SGSN
///< shall also include it on the S11/S4 interface for
///< TAU/RAU/X2-Handover/Enhanced SRNS Relocation
///< procedure if the PGW has requested location information
///< change reporting and MME/SGSN support location
///< information change reporting. The SGW shall include this
///< IE on S5/S8 if it receives the ULI from MME/SGSN.
ServingNetwork_t serving_network; ///< This IE shall be included on the S4/S11, S5/S8 and S2b
///< interfaces for an E-UTRAN initial attach, a PDP Context
///< Activation, a UE requested PDN connectivity, an Attach
///< with GTP on S2b, a UE initiated Connectivity to Additional
///< PDN with GTP on S2b and a Handover to Untrusted Non-
///< 3GPP IP Access with GTP on S2b.
rat_type_t rat_type; ///< This IE shall be set to the 3GPP access type or to the
///< value matching the characteristics of the non-3GPP access
///< the UE is using to attach to the EPS.
///< The ePDG may use the access technology type of the
///< untrusted non-3GPP access network if it is able to acquire
///< it; otherwise it shall indicate Virtual as the RAT Type.
///< See NOTE 3, NOTE 4.
indication_flags_t indication_flags; ///< This IE shall be included if any one of the applicable flags
///< is set to 1.
///< Applicable flags are:
///< - S5/S8 Protocol Type: This flag shall be used on
///< the S11/S4 interfaces and set according to the
///< protocol chosen to be used on the S5/S8
///< interfaces.
///<
///< - Dual Address Bearer Flag: This flag shall be used
///< on the S2b, S11/S4 and S5/S8 interfaces and shall
///< be set to 1 when the PDN Type, determined based
///< on UE request and subscription record, is set to
///< IPv4v6 and all SGSNs which the UE may be
///< handed over to support dual addressing. This shall
///< be determined based on node pre-configuration by
///< the operator.
///<
///< - Handover Indication: This flag shall be set to 1 on
///< the S11/S4 and S5/S8 interface during an E-
///< UTRAN Initial Attach or a UE Requested PDN
///< Connectivity or aPDP Context Activation procedure
///< if the PDN connection/PDP Context is handed-over
///< from non-3GPP access.
///< This flag shall be set to 1 on the S2b interface
///< during a Handover to Untrusted Non-3GPP IP
///< Access with GTP on S2b and IP address
///< preservation is requested by the UE.
///<
///< ....
///< - Unauthenticated IMSI: This flag shall be set to 1
///< on the S4/S11 and S5/S8 interfaces if the IMSI
///< present in the message is not authenticated and is
///< for an emergency attached UE.
FTeid_t sender_fteid_for_cp; ///< Sender F-TEID for control plane (MME)
FTeid_t pgw_address_for_cp; ///< PGW S5/S8 address for control plane or PMIP
///< This IE shall be sent on the S11 / S4 interfaces. The TEID
///< or GRE Key is set to "0" in the E-UTRAN initial attach, the
///< PDP Context Activation and the UE requested PDN
///< connectivity procedures.
char apn[APN_MAX_LENGTH + 1]; ///< Access Point Name
SelectionMode_t selection_mode; ///< Selection Mode
///< This IE shall be included on the S4/S11 and S5/S8
///< interfaces for an E-UTRAN initial attach, a PDP Context
///< Activation and a UE requested PDN connectivity.
///< This IE shall be included on the S2b interface for an Initial
///< Attach with GTP on S2b and a UE initiated Connectivity to
///< Additional PDN with GTP on S2b.
///< It shall indicate whether a subscribed APN or a non
///< subscribed APN chosen by the MME/SGSN/ePDG was
///< selected.
///< CO: When available, this IE shall be sent by the MME/SGSN on
///< the S11/S4 interface during TAU/RAU/HO with SGW
///< relocation.
pdn_type_t pdn_type; ///< PDN Type
///< This IE shall be included on the S4/S11 and S5/S8
///< interfaces for an E-UTRAN initial attach, a PDP Context
///< Activation and a UE requested PDN connectivity.
///< This IE shall be set to IPv4, IPv6 or IPv4v6. This is based
///< on the UE request and the subscription record retrieved
///< from the HSS (for MME see 3GPP TS 23.401 [3], clause
///< 5.3.1.1, and for SGSN see 3GPP TS 23.060 [35], clause
///< 9.2.1). See NOTE 1.
PAA_t paa; ///< PDN Address Allocation
///< This IE shall be included the S4/S11, S5/S8 and S2b
///< interfaces for an E-UTRAN initial attach, a PDP Context
///< Activation, a UE requested PDN connectivity, an Attach
///< with GTP on S2b, a UE initiated Connectivity to Additional
///< PDN with GTP on S2b and a Handover to Untrusted Non-
///< 3GPP IP Access with GTP on S2b. For PMIP-based
///< S5/S8, this IE shall also be included on the S4/S11
///< interfaces for TAU/RAU/Handover cases involving SGW
///< relocation.
///< The PDN type field in the PAA shall be set to IPv4, or IPv6
///< or IPv4v6 by MME, based on the UE request and the
///< subscription record retrieved from the HSS.
///< For static IP address assignment (for MME see 3GPP TS
///< 23.401 [3], clause 5.3.1.1, for SGSN see 3GPP TS 23.060
///< [35], clause 9.2.1, and for ePDG see 3GPP TS 23.402 [45]
///< subclause 4.7.3), the MME/SGSN/ePDG shall set the IPv4
///< address and/or IPv6 prefix length and IPv6 prefix and
///< Interface Identifier based on the subscribed values
///< received from HSS, if available. The value of PDN Type
///< field shall be consistent with the value of the PDN Type IE,
///< if present in this message.
///< For a Handover to Untrusted Non-3GPP IP Access with
///< GTP on S2b, the ePDG shall set the IPv4 address and/or
///< IPv6 prefix length and IPv6 prefix and Interface Identifier
///< based on the IP address(es) received from the UE.
///< If static IP address assignment is not used, and for
///< scenarios other than a Handover to Untrusted Non-3GPP
///< IP Access with GTP on S2b, the IPv4 address shall be set
///< to 0.0.0.0, and/or the IPv6 Prefix Length and IPv6 prefix
///< and Interface Identifier shall all be set to zero.
///<
///< CO: This IE shall be sent by the MME/SGSN on S11/S4
///< interface during TAU/RAU/HO with SGW relocation.
// APN Restriction Maximum_APN_Restriction ///< This IE shall be included on the S4/S11 and S5/S8
///< interfaces in the E-UTRAN initial attach, PDP Context
///< Activation and UE Requested PDN connectivity
///< procedures.
///< This IE denotes the most stringent restriction as required
///< by any already active bearer context. If there are no
///< already active bearer contexts, this value is set to the least
///< restrictive type.
ambr_t ambr; ///< Aggregate Maximum Bit Rate (APN-AMBR)
///< This IE represents the APN-AMBR. It shall be included on
///< the S4/S11, S5/S8 and S2b interfaces for an E-UTRAN
///< initial attach, UE requested PDN connectivity, the PDP
///< Context Activation procedure using S4, the PS mobility
///< from the Gn/Gp SGSN to the S4 SGSN/MME procedures,
///< Attach with GTP on S2b and a UE initiated Connectivity to
///< Additional PDN with GTP on S2b.
// EBI Linked EPS Bearer ID ///< This IE shall be included on S4/S11 in RAU/TAU/HO
///< except in the Gn/Gp SGSN to MME/S4-SGSN
///< RAU/TAU/HO procedures with SGW change to identify the
///< default bearer of the PDN Connection
// PCO protocol_configuration_options ///< This IE is not applicable to TAU/RAU/Handover. If
///< MME/SGSN receives PCO from UE (during the attach
///< procedures), the MME/SGSN shall forward the PCO IE to
///< SGW. The SGW shall also forward it to PGW.
bearer_to_create_t bearer_to_create; ///< Bearer Contexts to be created
///< Several IEs with the same type and instance value shall be
///< included on the S4/S11 and S5/S8 interfaces as necessary
///< to represent a list of Bearers. One single IE shall be
///< included on the S2b interface.
///< One bearer shall be included for an E-UTRAN Initial
///< Attach, a PDP Context Activation, a UE requested PDN
///< Connectivity, an Attach with GTP on S2b, a UE initiated
///< Connectivity to Additional PDN with GTP on S2b and a
///< Handover to Untrusted Non-3GPP IP Access with GTP on
///< S2b.
///< One or more bearers shall be included for a
///< Handover/TAU/RAU with an SGW change.
///bearer_to_remove_t bearer_to_remove; ///< This IE shall be included on the S4/S11 interfaces for the
///< TAU/RAU/Handover cases where any of the bearers
///< existing before the TAU/RAU/Handover procedure will be
///< deactivated as consequence of the TAU/RAU/Handover
///< procedure.
///< For each of those bearers, an IE with the same type and
///< instance value shall be included.
// Trace Information trace_information ///< This IE shall be included on the S4/S11 interface if an
///< SGW trace is activated, and/or on the S5/S8 and S2b
///< interfaces if a PGW trace is activated. See 3GPP TS
///< 32.422 [18].
// Recovery Recovery ///< This IE shall be included on the S4/S11, S5/S8 and S2b
///< interfaces if contacting the peer for the first time
FQ_CSID_t mme_fq_csid; ///< This IE shall be included by the MME on the S11 interface
///< and shall be forwarded by an SGW on the S5/S8 interfaces
///< according to the requirements in 3GPP TS 23.007 [17].
FQ_CSID_t sgw_fq_csid; ///< This IE shall included by the SGW on the S5/S8 interfaces
///< according to the requirements in 3GPP TS 23.007 [17].
//FQ_CSID_t epdg_fq_csid; ///< This IE shall be included by the ePDG on the S2b interface
///< according to the requirements in 3GPP TS 23.007 [17].
UETimeZone_t ue_time_zone; ///< This IE shall be included by the MME over S11 during
///< Initial Attach, UE Requested PDN Connectivity procedure.
///< This IE shall be included by the SGSN over S4 during PDP
///< Context Activation procedure.
///< This IE shall be included by the MME/SGSN over S11/S4
///< TAU/RAU/Handover with SGW relocation.
///< C: If SGW receives this IE, SGW shall forward it to PGW
///< across S5/S8 interface.
UCI_t uci; ///< User CSG Information
///< CO This IE shall be included on the S4/S11 interface for E-
///< UTRAN Initial Attach, UE-requested PDN Connectivity and
///< PDP Context Activation using S4 procedures if the UE is
///< accessed via CSG cell or hybrid cell. The MME/SGSN
///< shall also include it for TAU/RAU/Handover procedures if
///< the PGW has requested CSG info reporting and
///< MME/SGSN support CSG info reporting. The SGW shall
///< include this IE on S5/S8 if it receives the User CSG
///< information from MME/SGSN.
// Charging Characteristics
// MME/S4-SGSN LDN
// SGW LDN
// ePDG LDN
// Signalling Priority Indication
// MMBR Max MBR/APN-AMBR
// Private Extension
/* S11 stack specific parameter. Not used in standalone epc mode */
void *trxn; ///< Transaction identifier
@@ -92,17 +337,157 @@ typedef struct {
* - Tracking Area Update procedure with SGW change
* - S1/X2-based handover with SGW change
*/
typedef struct {
typedef struct SgwCreateSessionResponse_s{
Teid_t teid; ///< Tunnel Endpoint Identifier
SGWCause_t cause;
// here fields listed in 3GPP TS 29.274
SGWCause_t cause; ///< If the SGW cannot accept any of the "Bearer Context Created" IEs within Create Session Request
///< message, the SGW shall send the Create Session Response with appropriate reject Cause value.
// change_reporting_action ///< This IE shall be included on the S5/S8 and S4/S11
///< interfaces with the appropriate Action field if the location
///< Change Reporting mechanism is to be started or stopped
///< for this subscriber in the SGSN/MME.
// csg_Information_reporting_action ///< This IE shall be included on the S5/S8 and S4/S11
///< interfaces with the appropriate Action field if the CSG Info
///< reporting mechanism is to be started or stopped for this
///< subscriber in the SGSN/MME.
FTeid_t s11_sgw_teid; ///< Sender F-TEID for control plane
FTeid_t s5_s8_pgw_teid; ///< Sender F-TEID for control plane
///< This IE shall be sent on the S11/S4 interfaces. For the
///< S5/S8/S2b interfaces it is not needed because its content
///< would be identical to the IE PGW S5/S8/S2b F-TEID for
///< PMIP based interface or for GTP based Control Plane
///< interface.
FTeid_t s5_s8_pgw_teid; ///< PGW S5/S8/S2b F-TEID for PMIP based interface or for GTP based Control Planeinterface
///< PGW shall include this IE on the S5/S8 interfaces during
///< the Initial Attach, UE requested PDN connectivity and PDP
///< Context Activation procedures.
///< If SGW receives this IE it shall forward the IE to MME/S4-
///< SGSN on S11/S4 interface.
///< This IE shall include the TEID in the GTP based S5/S8
///< case and the GRE key in the PMIP based S5/S8 case.
///< In PMIP based S5/S8 case, same IP address is used for
///< both control plane and the user plane communication.
///<
///< PGW shall include this IE on the S2b interface during the
///< Attach with GTP on S2b, UE initiated Connectivity to
///< Additional PDN with GTP on S2b and Handover to
///< Untrusted Non-3GPP IP Access with GTP on S2b
///< procedures.
PAA_t paa; ///< PDN Address Allocation
APNRestriction_t apn_restriction;
bearer_context_created_t bearer_context_created;
FQ_CSID_t pgw_fq_csid;
FQ_CSID_t sgw_fq_csid;
///< This IE shall be included on the S5/S8, S4/S11 and S2b
///< interfaces for the E-UTRAN initial attach, PDP Context
///< Activation, UE requested PDN connectivity, Attach with
///< GTP on S2b, UE initiated Connectivity to Additional PDN
///< with GTP on S2b and Handover to Untrusted Non-3GPP IP
///< Access with GTP on S2b procedures.
///< The PDN type field in the PAA shall be set to IPv4, or IPv6
///< or IPv4v6 by the PGW.
///< For the interfaces other than S2b, if the DHCPv4 is used
///< for IPv4 address allocation, the IPv4 address field shall be
///< set to 0.0.0.0.
APNRestriction_t apn_restriction; ///< This IE shall be included on the S5/S8 and S4/S11
///< interfaces in the E-UTRAN initial attach, PDP Context
///< Activation and UE Requested PDN connectivity
///< procedures.
///< This IE shall also be included on S4/S11 during the Gn/Gp
///< SGSN to S4 SGSN/MME RAU/TAU procedures.
///< This IE denotes the restriction on the combination of types
///< of APN for the APN associated with this EPS bearer
///< Context.
ambr_t ambr; ///< Aggregate Maximum Bit Rate (APN-AMBR)
///< This IE represents the APN-AMBR. It shall be included on
///< the S5/S8, S4/S11 and S2b interfaces if the received APN-
///< AMBR has been modified by the PCRF.
// EBI Linked EPS Bearer ID ///< This IE shall be sent on the S4/S11 interfaces during
///< Gn/Gp SGSN to S4-SGSN/MME RAU/TAU procedure to
///< identify the default bearer the PGW selects for the PDN
///< Connection.
// PCO protocol_configuration_options ///< This IE is not applicable for TAU/RAU/Handover. If PGW
///< decides to return PCO to the UE, PGW shall send PCO to
///< SGW. If SGW receives the PCO IE, SGW shall forward it
///< MME/SGSN.
bearer_context_created_t bearer_context_created;///< EPS bearers corresponding to Bearer Contexts sent in
///< request message. Several IEs with the same type and
///< instance value may be included on the S5/S8 and S4/S11
///< as necessary to represent a list of Bearers. One single IE
///< shall be included on the S2b interface.
///< One bearer shall be included for E-UTRAN Initial Attach,
///< PDP Context Activation or UE Requested PDN
///< Connectivity , Attach with GTP on S2b, UE initiated
///< Connectivity to Additional PDN with GTP on S2b, and
///< Handover to Untrusted Non-3GPP IP Access with GTP on
///< S2b.
///< One or more created bearers shall be included for a
///< Handover/TAU/RAU with an SGW change. See NOTE 2.
// Bearer_Context bearer_contexts_marked_for_removal ///< EPS bearers corresponding to Bearer Contexts to be
///< removed that were sent in the Create Session Request
///< message.
///< For each of those bearers an IE with the same type and
///< instance value shall be included on the S4/S11 interfaces.
// Recovery Recovery ///< This IE shall be included on the S4/S11, S5/S8 and S2b
///< interfaces if contacting the peer for the first time
// FQDN charging_Gateway_name ///< When Charging Gateway Function (CGF) Address is
///< configured, the PGW shall include this IE on the S5
///< interface.
///< NOTE 1: Both Charging Gateway Name and Charging Gateway Address shall not be included at the same
///< time. When both are available, the operator configures a preferred value.
// IP Address charging_Gateway_address ///< When Charging Gateway Function (CGF) Address is
///< configured, the PGW shall include this IE on the S5
///< interface. See NOTE 1.
FQ_CSID_t pgw_fq_csid; ///< This IE shall be included by the PGW on the S5/S8 and
///< S2b interfaces and, when received from S5/S8 be
///< forwarded by the SGW on the S11 interface according to
///< the requirements in 3GPP TS 23.007 [17].
FQ_CSID_t sgw_fq_csid; ///< This IE shall be included by the SGW on the S11 interface
///< according to the requirements in 3GPP TS 23.007 [17].
// Local Distinguished Name (LDN) SGW LDN ///< This IE is optionally sent by the SGW to the MME/SGSN
///< on the S11/S4 interfaces (see 3GPP TS 32.423 [44]),
///< when contacting the peer node for the first time.
///< Also:
///< This IE is optionally sent by the SGW to the MME/SGSN
///< on the S11/S4 interfaces (see 3GPP TS 32.423 [44]),
///< when communicating the LDN to the peer node for the first
///< time.
// Local Distinguished Name (LDN) PGW LDN ///< This IE is optionally included by the PGW on the S5/S8
///< and S2b interfaces (see 3GPP TS 32.423 [44]), when
///< contacting the peer node for the first time.
///< Also:
///< This IE is optionally included by the PGW on the S5/S8
///< interfaces (see 3GPP TS 32.423 [44]), when
///< communicating the LDN to the peer node for the first time.
// EPC_Timer pgw_back_off_time ///< This IE may be included on the S5/S8 and S4/S11
///< interfaces when the PDN GW rejects the Create Session
///< Request with the cause "APN congestion". It indicates the
///< time during which the MME or S4-SGSN should refrain
///< from sending subsequent PDN connection establishment
///< requests to the PGW for the congested APN for services
///< other than Service Users/emergency services.
///< See NOTE 3:
///< The last received value of the PGW Back-Off Time IE shall supersede any previous values received
///< from that PGW and for this APN in the MME/SGSN.
// Private Extension ///< This IE may be sent on the S5/S8, S4/S11 and S2b
///< interfaces.
/* S11 stack specific parameter. Not used in standalone epc mode */
void *trxn; ///< Transaction identifier
@@ -121,15 +506,208 @@ typedef struct {
* - UE requested PDN connectivity
* - X2-based handover without SGWrelocation
*/
typedef struct {
Teid_t teid; ///< Tunnel Endpoint Identifier
// FTeid_t s11_sgw_teid; ///< S11- S-GW Tunnel Endpoint Identifier
typedef struct SgwModifyBearerRequest_s {
Teid_t teid; ///< S11 SGW Tunnel Endpoint Identifier
// MEI ME Identity (MEI) ///< C:This IE shall be sent on the S5/S8 interfaces for the Gn/Gp
///< SGSN to MME TAU.
Uli_t uli; ///< C: The MME/SGSN shall include this IE for
///< TAU/RAU/Handover procedures if the PGW has requested
///< location information change reporting and MME/SGSN
///< support location information change reporting.
///< An MME/SGSN which supports location information
///< change shall include this IE for UE-initiated Service
///< Request procedure if the PGW has requested location
///< information change reporting and the UE’s location info
///< has changed.
///< The SGW shall include this IE on S5/S8 if it receives the
///< ULI from MME/SGSN.
///< CO:This IE shall also be included on the S4/S11 interface for a
///< TAU/RAU/Handover with MME/SGSN change without
///< SGW change procedure, if the level of support (User
///< Location Change Reporting and/or CSG Information
///< Change Reporting) changes the MME shall include the
///< ECGI/TAI in the ULI, the SGSN shall include the CGI/SAI
///< in the ULI.
///< The SGW shall include this IE on S5/S8 if it receives the
///< ULI from MME/SGSN.
ServingNetwork_t serving_network; ///< CO:This IE shall be included on S11/S4 interface during the
///< following procedures:
///< - TAU/RAU/handover if Serving Network is changed.
///< - TAU/RAU when the UE was ISR activated which is
///< indicated by ISRAU flag.
///< - UE triggered Service Request when UE is ISR
///< activated.
///< - UE initiated Service Request if ISR is not active, but
///< the Serving Network has changed during previous
///< mobility procedures, i.e. intra MME/S4-SGSN
///< TAU/RAU and the change has not been reported to
///< the PGW yet.
///< - TAU/RAU procedure as part of the optional network
///< triggered service restoration procedure with ISR, as
///< specified by 3GPP TS 23.007 [17].
///<
///< CO:This IE shall be included on S5/S8 if the SGW receives this
///< IE from MME/SGSN and if ISR is not active.
///< This IE shall be included on S5/S8 if the SGW receives this
///< IE from MME/SGSN and ISR is active and the Modify
///< Bearer Request message needs to be sent to the PGW as
///< specified in the 3GPP TS 23.401 [3].
rat_type_t rat_type; ///< C: This IE shall be sent on the S11 interface for a TAU with
///< an SGSN interaction, UE triggered Service Request or an I-
///< RAT Handover.
///< This IE shall be sent on the S4 interface for a RAU with
///< MME interaction, a RAU with an SGSN change, a UE
///< Initiated Service Request or an I-RAT Handover.
///< This IE shall be sent on the S5/S8 interface if the RAT type
///< changes.
///< CO: CO If SGW receives this IE from MME/SGSN during a
///< TAU/RAU/Handover with SGW change procedure, the
///< SGW shall forward it across S5/S8 interface to PGW.
///< CO: The IE shall be sent on the S11/S4 interface during the
///< following procedures:
///< - an inter MM TAU or inter SGSN RAU when UE was
///< ISR activated which is indicated by ISRAU flag.
///< - TAU/RAU procedure as part of optional network
///< triggered service restoration procedure with ISR, as
///< specified by 3GPP TS 23.007 [17].
///< If ISR is active, this IE shall also be included on the S11
///< interface in the S1-U GTP-U tunnel setup procedure during
///< an intra-MME intra-SGW TAU procedure.
indication_flags_t indication_flags; ///< C:This IE shall be included if any one of the applicable flags
///< is set to 1.
///< Applicable flags are:
///< -ISRAI: This flag shall be used on S4/S11 interface
///< and set to 1 if the ISR is established between the
///< MME and the S4 SGSN.
///< - Handover Indication: This flag shall be set to 1 on
///< the S4/S11 and S5/S8 interfaces during an E-
///< UTRAN Initial Attach or for a UE Requested PDN
///< Connectivity or a PDP Context Activation
///< procedure, if the PDN connection/PDP context is
///< handed-over from non-3GPP access.
///< - Direct Tunnel Flag: This flag shall be used on the
///< S4 interface and set to 1 if Direct Tunnel is used.
///< - Change Reporting support Indication: shall be
///< used on S4/S11, S5/S8 and set if the SGSN/MME
///< supports location Info Change Reporting. This flag
///< should be ignored by SGW if no message is sent
///< on S5/S8. See NOTE 4.
///< - CSG Change Reporting Support Indication: shall
///< be used on S4/S11, S5/S8 and set if the
///< SGSN/MME supports CSG Information Change
///< Reporting. This flag shall be ignored by SGW if no
///< message is sent on S5/S8. See NOTE 4.
///< - Change F-TEID support Indication: This flag shall
///< be used on S4/S11 for an IDLE state UE initiated
///< TAU/RAU procedure and set to 1 to allow the
///< SGW changing the GTP-U F-TEID.
FTeid_t sender_fteid_for_cp; ///< C: Sender F-TEID for control plane
///< This IE shall be sent on the S11 and S4 interfaces for a
///< TAU/RAU/ Handover with MME/SGSN change and without
///< any SGW change.
///< This IE shall be sent on the S5 and S8 interfaces for a
///< TAU/RAU/Handover with a SGW change.
ambr_t apn_ambr; ///< C: Aggregate Maximum Bit Rate (APN-AMBR)
///< The APN-AMBR shall be sent for the PS mobility from the
///< Gn/Gp SGSN to the S4 SGSN/MME procedures..
/* Delay Value in integer multiples of 50 millisecs, or zero */
DelayValue_t delay_dl_packet_notif_req;
bearer_context_to_modify_t bearer_context_to_modify;
FQ_CSID_t mme_fq_csid;
indication_flags_t indication_flags;
rat_type_t rat_type;
DelayValue_t delay_dl_packet_notif_req; ///<C:This IE shall be sent on the S11 interface for a UE
///< triggered Service Request.
///< CO: This IE shall be sent on the S4 interface for a UE triggered
///< Service Request.
bearer_context_to_modify_t bearer_context_to_modify;///< C: This IE shall be sent on the S4/S11 interface and S5/S8
///< interface except on the S5/S8 interface for a UE triggered
///< Service Request.
///< When Handover Indication flag is set to 1 (i.e., for
///< EUTRAN Initial Attach or UE Requested PDN Connectivity
///< when the UE comes from non-3GPP access), the PGW
///< shall ignore this IE. See NOTE 1.
///< Several IEs with the same type and instance value may be
///< included as necessary to represent a list of Bearers to be
///< modified.
///< During a TAU/RAU/Handover procedure with an SGW
///< change, the SGW includes all bearers it received from the
///< MME/SGSN (Bearer Contexts to be created, or Bearer
///< Contexts to be modified and also Bearer Contexts to be
///< removed) into the list of 'Bearer Contexts to be modified'
///< IEs, which are then sent on the S5/S8 interface to the
///< PGW (see NOTE 2).
// Bearer Context Bearer Contexts to be removed; ///< C: This IE shall be included on the S4 and S11 interfaces for
///< the TAU/RAU/Handover and Service Request procedures
///< where any of the bearers existing before the
///< TAU/RAU/Handover procedure and Service Request
///< procedures will be deactivated as consequence of the
///< TAU/RAU/Handover procedure and Service Request
///< procedures. (NOTE 3)
///< For each of those bearers, an IE with the same type and
///< instance value, shall be included.
// recovery_t(restart counter) recovery; ///< C: This IE shall be included if contacting the peer for the first
///< time.
UETimeZone_t ue_time_zone; ///< CO: This IE shall be included by the MME/SGSN on the S11/S4
///< interfaces if the UE Time Zone has changed in the case of
///< TAU/RAU/Handover.
///< C: If SGW receives this IE, SGW shall forward it to PGW
///< across S5/S8 interface.
FQ_CSID_t mme_fq_csid; ///< C: This IE shall be included by MME on S11 and shall be
///< forwarded by SGW on S5/S8 according to the
///< requirements in 3GPP TS 23.007 [17].
FQ_CSID_t sgw_fq_csid; ///< C: This IE shall be included by SGW on S5/S8 according to
///< the requirements in 3GPP TS 23.007 [17].
UCI_t uci; ///< CO: The MME/SGSN shall include this IE for
///< TAU/RAU/Handover procedures and UE-initiated Service
///< Request procedure if the PGW has requested CSG Info
///< reporting and the MME/SGSN support the CSG
///< information reporting. The SGW shall include this IE on
///< S5/S8 if it receives the User CSG Information from
///< MME/SGSN.
// Local Distinguished Name (LDN) MME/S4-SGSN LDN ///< O: This IE is optionally sent by the MME to the SGW on the
///< S11 interface and by the SGSN to the SGW on the S4
///< interface (see 3GPP TS 32.423 [44]), when communicating
///< the LDN to the peer node for the first time.
// Local Distinguished Name (LDN) SGW LDN ///< O: This IE is optionally sent by the SGW to the PGW on the
///< S5/S8 interfaces (see 3GPP TS 32.423 [44]), for inter-
///< SGW mobity, when communicating the LDN to the peer
///< node for the first time.
// MMBR Max MBR/APN-AMBR ///< CO: If the S4-SGSN supports Max MBR/APN-AMBR, this IE
///< shall be included by the S4-SGSN over S4 interface in the
///< following cases:
///< - during inter SGSN RAU/SRNS relocation without
///< SGW relocation and inter SGSN SRNS relocation
///< with SGW relocation if Higher bitrates than
///< 16 Mbps flag is not included in the MM Context IE
///< in the Context Response message or in the MM
///< Context IE in the Forward Relocation Request
///< message from the old S4-SGSN, while it is
///< received from target RNC or a local Max
///< MBR/APN-AMBR is configured based on
///< operator's policy.
///< - during Service Request procedure if Higher
///< bitrates than 16 Mbps flag is received but the S4-
///< SGSN has not received it before from an old RNC
///< or the S4-SGSN has not updated the Max
///< MBR/APN-AMBR to the PGW yet.
///< If SGW receives this IE, SGW shall forward it to PGW
///< across S5/S8 interface.
// Private Extension Private Extension
/* S11 stack specific parameter. Not used in standalone epc mode */
void *trxn; ///< Transaction identifier
@@ -147,33 +725,116 @@ typedef struct {
* - UE requested PDN connectivity
* - X2-based handover without SGWrelocation
*/
typedef struct {
Teid_t teid; ///< Tunnel Endpoint Identifier
SGWCause_t cause;
typedef struct SgwModifyBearerResponse_s{
Teid_t teid; ///< S11 MME Tunnel Endpoint Identifier
// here fields listed in 3GPP TS 29.274
SGWCause_t cause; ///<
ebi_t linked_eps_bearer_id;///< This IE shall be sent on S5/S8 when the UE moves from a
///< Gn/Gp SGSN to the S4 SGSN or MME to identify the
///< default bearer the PGW selects for the PDN Connection.
///< This IE shall also be sent by SGW on S11, S4 during
///< Gn/Gp SGSN to S4-SGSN/MME HO procedures to identify
///< the default bearer the PGW selects for the PDN
///< Connection.
ambr_t apn_ambr; ///< Aggregate Maximum Bit Rate (APN-AMBR)
///< This IE shall be included in the PS mobility from Gn/Gp
///< SGSN to the S4 SGSN/MME procedures if the received
///< APN-AMBR has been modified by the PCRF.
APNRestriction_t apn_restriction; ///< This IE denotes the restriction on the combination of types
///< of APN for the APN associated with this EPS bearer
///< Context. This IE shall be included over S5/S8 interfaces,
///< and shall be forwarded over S11/S4 interfaces during
///< Gn/Gp SGSN to MME/S4-SGSN handover procedures.
///< This IE shall also be included on S5/S8 interfaces during
///< the Gn/Gp SGSN to S4 SGSN/MME RAU/TAU
///< procedures.
///< The target MME or SGSN determines the Maximum APN
///< Restriction using the APN Restriction.
// PCO protocol_configuration_options ///< If SGW receives this IE from PGW on GTP or PMIP based
///< S5/S8, the SGW shall forward PCO to MME/S4-SGSN
///< during Inter RAT handover from the UTRAN or from the
///< GERAN to the E-UTRAN. See NOTE 2:
///< If MME receives the IE, but no NAS message is sent, MME discards the IE.
#define MODIFY_BEARER_RESPONSE_MOD 0x0
#define MODIFY_BEARER_RESPONSE_REM 0x1
unsigned present:1; ///< Choice present in union choice
unsigned bearer_present:1; ///< Choice present in union choice
union {
bearer_context_modified_t bearer_modified; ///< Bearer to be modified
bearer_for_removal_t bearer_for_removal; ///< Bearer to be removed
} choice;
bearer_context_modified_t bearer_contexts_modified;///< EPS bearers corresponding to Bearer Contexts to be
///< modified that were sent in Modify Bearer Request
///< message. Several IEs with the same type and instance
///< value may be included as necessary to represent a list of
///< the Bearers which are modified.
bearer_for_removal_t bearer_for_removal;///< EPS bearers corresponding to Bearer Contexts to be
///< removed sent in the Modify Bearer Request message.
///< Shall be included if request message contained Bearer
///< Contexts to be removed.
///< For each of those bearers an IE with the same type and
///< instance value shall be included.
} bearer_choice;
// change_reporting_action ///< This IE shall be included with the appropriate Action field If
///< the location Change Reporting mechanism is to be started
///< or stopped for this subscriber in the SGSN/MME.
// csg_Information_reporting_action ///< This IE shall be included with the appropriate Action field if
///< the location CSG Info change reporting mechanism is to be
///< started or stopped for this subscriber in the SGSN/MME.
// FQDN Charging Gateway Name ///< When Charging Gateway Function (CGF) Address is
///< configured, the PGW shall include this IE on the S5
///< interface during SGW relocation and when the UE moves
///< from Gn/Gp SGSN to S4-SGSN/MME. See NOTE 1:
///< Both Charging Gateway Name and Charging Gateway Address shall not be included at the same
///< time. When both are available, the operator configures a preferred value.
// IP Address Charging Gateway Address ///< When Charging Gateway Function (CGF) Address is
///< configured, the PGW shall include this IE on the S5
///< interface during SGW relocation and when the UE moves
///< from Gn/Gp SGSN to S4-SGSN/MME. See NOTE 1:
///< Both Charging Gateway Name and Charging Gateway Address shall not be included at the same
///< time. When both are available, the operator configures a preferred value.
FQ_CSID_t pgw_fq_csid; ///< This IE shall be included by PGW on S5/S8and shall be
///< forwarded by SGW on S11 according to the requirements
///< in 3GPP TS 23.007 [17].
FQ_CSID_t sgw_fq_csid; ///< This IE shall be included by SGW on S11 according to the
///< requirements in 3GPP TS 23.007 [17].
// recovery_t(restart counter) recovery; ///< This IE shall be included if contacting the peer for the first
///< time.
// Local Distinguished Name (LDN) SGW LDN ///< This IE is optionally sent by the SGW to the MME/SGSN
///< on the S11/S4 interfaces (see 3GPP TS 32.423 [44]),
///< when contacting the peer node for the first time.
// Local Distinguished Name (LDN) PGW LDN ///< This IE is optionally included by the PGW on the S5/S8
///< and S2b interfaces (see 3GPP TS 32.423 [44]), when
///< contacting the peer node for the first time.
// Private Extension Private Extension ///< optional
/* S11 stack specific parameter. Not used in standalone epc mode */
void *trxn; ///< Transaction identifier
} SgwModifyBearerResponse;
typedef struct {
typedef struct SgwDeleteSessionRequest_s{
Teid_t teid; ///< Tunnel Endpoint Identifier
EBI_t lbi; ///< Linked EPS Bearer ID
FTeid_t sender_fteid_for_cp; ///< Sender F-TEID for control plane
/* Operation Indication: This flag shall be set over S4/S11 interface
* if the SGW needs to forward the Delete Session Request message to
* the PGW. This flag shall not be set if the ISR associated GTP
* if the SGW needs to forward the Delete Session Request message to
* the PGW. This flag shall not be set if the ISR associated GTP
* entity sends this message to the SGW in the Detach procedure.
* This flag shall also not be set to 1 in the SRNS Relocation Cancel
* Using S4 (6.9.2.2.4a in 3GPP TS 23.060 [4]), Inter RAT handover
* Cancel procedure with SGW change TAU with Serving GW change,
* Using S4 (6.9.2.2.4a in 3GPP TS 23.060 [4]), Inter RAT handover
* Cancel procedure with SGW change TAU with Serving GW change,
* Gn/Gb based RAU (see 5.5.2.5, 5.3.3.1, D.3.5 in 3GPP TS 23.401 [3],
* respectively), S1 Based handover Cancel procedure with SGW change.
*/
@@ -197,7 +858,7 @@ typedef struct {
* - X2 Based Handover with SGW Relocation
* - S1 Based handover cancel with SGW change
*/
typedef struct {
typedef struct SgwDeleteSessionResponse_s{
Teid_t teid; ///< Remote Tunnel Endpoint Identifier
SGWCause_t cause;
+35 -23
View File
@@ -535,6 +535,9 @@ static int gtpv1u_create_s1u_tunnel(gtpv1u_enb_create_tunnel_req_t *create_tunne
int i;
ebi_t eps_bearer_id = 0;
int ipv4_addr = 0;
int ip_offset = 0;
in_addr_t in_addr;
int addrs_length_in_bytes= 0;
message_p = itti_alloc_new_message(TASK_GTPV1_U, GTPV1U_ENB_CREATE_TUNNEL_RESP);
GTPV1U_ENB_CREATE_TUNNEL_RESP(message_p).ue_index = create_tunnel_req_pP->ue_index;
@@ -542,6 +545,7 @@ static int gtpv1u_create_s1u_tunnel(gtpv1u_enb_create_tunnel_req_t *create_tunne
GTPV1U_ENB_CREATE_TUNNEL_RESP(message_p).num_tunnels = 0;
for (i = 0; i < create_tunnel_req_pP->num_tunnels; i++) {
ip_offset = 0;
eps_bearer_id = create_tunnel_req_pP->eps_bearer_id[i];
GTPU_DEBUG("Rx GTPV1U_ENB_CREATE_TUNNEL_REQ ue_index %u eps bearer id %u\n",
create_tunnel_req_pP->ue_index, eps_bearer_id);
@@ -564,36 +568,44 @@ static int gtpv1u_create_s1u_tunnel(gtpv1u_enb_create_tunnel_req_t *create_tunne
// PDCP->GTPV1U mapping
//-----------------------
hash_rc = hashtable_get(gtpv1u_data_g.ue_mapping, create_tunnel_req_pP->ue_index, (void **)&gtpv1u_ue_data_p);
if (hash_rc == HASH_TABLE_KEY_NOT_EXISTS) {
gtpv1u_ue_data_p = calloc (1, sizeof(gtpv1u_ue_data_t));
gtpv1u_ue_data_p->ue_id = create_tunnel_req_pP->ue_index;
gtpv1u_ue_data_p->instance_id = 0; // TO DO
memcpy(&GTPV1U_ENB_CREATE_TUNNEL_RESP(message_p).enb_addr.buffer,
&gtpv1u_data_g.enb_ip_address_for_S1u_S12_S4_up,
sizeof (in_addr_t));
GTPV1U_ENB_CREATE_TUNNEL_RESP(message_p).enb_addr.length = sizeof (in_addr_t);
AssertFatal(create_tunnel_req_pP->sgw_addr[i].length == 4, "Bad transport layer address for next operation, TO DO");
gtpv1u_ue_data_p->bearers[eps_bearer_id - GTPV1U_BEARER_OFFSET].sgw_ip_addr = *((in_addr_t*)create_tunnel_req_pP->sgw_addr[i].buffer);
if ((hash_rc == HASH_TABLE_KEY_NOT_EXISTS) || (hash_rc == HASH_TABLE_OK)) {
gtpv1u_ue_data_p->bearers[eps_bearer_id - GTPV1U_BEARER_OFFSET].state = BEARER_IN_CONFIG;
gtpv1u_ue_data_p->bearers[eps_bearer_id - GTPV1U_BEARER_OFFSET].teid_eNB = s1u_teid;
gtpv1u_ue_data_p->bearers[eps_bearer_id - GTPV1U_BEARER_OFFSET].teid_sgw = create_tunnel_req_pP->sgw_S1u_teid[i];
hash_rc = hashtable_insert(gtpv1u_data_g.ue_mapping, create_tunnel_req_pP->ue_index, gtpv1u_ue_data_p);
AssertFatal(hash_rc == HASH_TABLE_OK, "Error inserting ue_mapping in GTPV1U hashtable");
GTPV1U_ENB_CREATE_TUNNEL_RESP(message_p).enb_S1u_teid[i] = s1u_teid;
} else if (hash_rc == HASH_TABLE_OK) {
if (hash_rc == HASH_TABLE_KEY_NOT_EXISTS) {
gtpv1u_ue_data_p = calloc (1, sizeof(gtpv1u_ue_data_t));
hash_rc = hashtable_insert(gtpv1u_data_g.ue_mapping, create_tunnel_req_pP->ue_index, gtpv1u_ue_data_p);
AssertFatal(hash_rc == HASH_TABLE_OK, "Error inserting ue_mapping in GTPV1U hashtable");
}
gtpv1u_ue_data_p->ue_id = create_tunnel_req_pP->ue_index;
gtpv1u_ue_data_p->instance_id = 0; // TO DO
memcpy(&GTPV1U_ENB_CREATE_TUNNEL_RESP(message_p).enb_addr.buffer,
&gtpv1u_data_g.enb_ip_address_for_S1u_S12_S4_up,
sizeof (in_addr_t));
GTPV1U_ENB_CREATE_TUNNEL_RESP(message_p).enb_addr.length = sizeof (in_addr_t);
gtpv1u_ue_data_p->bearers[eps_bearer_id - GTPV1U_BEARER_OFFSET].sgw_ip_addr = *((in_addr_t*)create_tunnel_req_pP->sgw_addr[i].buffer);
gtpv1u_ue_data_p->instance_id = 0; // TO DO
memcpy(&GTPV1U_ENB_CREATE_TUNNEL_RESP(message_p).enb_addr.buffer,
&gtpv1u_data_g.enb_ip_address_for_S1u_S12_S4_up,
sizeof (in_addr_t));
GTPV1U_ENB_CREATE_TUNNEL_RESP(message_p).enb_addr.length = sizeof (in_addr_t);
addrs_length_in_bytes = create_tunnel_req_pP->sgw_addr[i].length / 8;
AssertFatal((addrs_length_in_bytes == 4) ||
(addrs_length_in_bytes == 16) ||
(addrs_length_in_bytes == 20),
"Bad transport layer address length %d (bits) %d (bytes)",
create_tunnel_req_pP->sgw_addr[i].length, addrs_length_in_bytes);
if ((addrs_length_in_bytes == 4) ||
(addrs_length_in_bytes == 20)) {
in_addr = *((in_addr_t*)create_tunnel_req_pP->sgw_addr[i].buffer);
ip_offset = 4;
gtpv1u_ue_data_p->bearers[eps_bearer_id - GTPV1U_BEARER_OFFSET].sgw_ip_addr = in_addr;
}
if ((addrs_length_in_bytes == 16) ||
(addrs_length_in_bytes == 20)) {
memcpy(gtpv1u_ue_data_p->bearers[eps_bearer_id - GTPV1U_BEARER_OFFSET].sgw_ip6_addr.s6_addr,
&create_tunnel_req_pP->sgw_addr[i].buffer[ip_offset],
16);
}
gtpv1u_ue_data_p->bearers[eps_bearer_id - GTPV1U_BEARER_OFFSET].state = BEARER_IN_CONFIG;
gtpv1u_ue_data_p->bearers[eps_bearer_id - GTPV1U_BEARER_OFFSET].teid_eNB = s1u_teid;
gtpv1u_ue_data_p->bearers[eps_bearer_id - GTPV1U_BEARER_OFFSET].teid_sgw = create_tunnel_req_pP->sgw_S1u_teid[i];
GTPV1U_ENB_CREATE_TUNNEL_RESP(message_p).enb_S1u_teid[i] = s1u_teid;
} else {
GTPV1U_ENB_CREATE_TUNNEL_RESP(message_p).enb_S1u_teid[i] = 0;
GTPV1U_ENB_CREATE_TUNNEL_RESP(message_p).status = 0xFF;
+5 -4
View File
@@ -68,10 +68,11 @@ typedef struct gtpv1u_teid_data_s {
typedef struct gtpv1u_bearer_s {
/* TEID used in dl and ul */
teid_t teid_eNB; ///< eNB TEID
teid_t teid_sgw; ///< Remote TEID
in_addr_t sgw_ip_addr;
tcp_udp_port_t port;
teid_t teid_eNB; ///< eNB TEID
teid_t teid_sgw; ///< Remote TEID
in_addr_t sgw_ip_addr;
struct in6_addr sgw_ip6_addr;
tcp_udp_port_t port;
//NwGtpv1uStackSessionHandleT stack_session;
bearer_state_t state;
} gtpv1u_bearer_t;
+15 -14
View File
@@ -167,22 +167,24 @@ NwGtpv1uRcT gtpv1u_process_stack_req(
data_ind_p->local_S1u_teid = pUlpApi->apiInfo.recvMsgInfo.teid;
if (data_ind_p->buffer == NULL) {
GTPU_ERROR("Failed to allocate new buffer\n");
free(message_p);
itti_free(ITTI_MSG_ORIGIN_ID(message_p), message_p);
message_p = NULL;
} else {
memcpy(data_ind_p->buffer, buffer, buffer_len);
data_ind_p->length = buffer_len;
if (itti_send_msg_to_task(TASK_FW_IP, INSTANCE_DEFAULT, message_p) < 0) {
GTPU_ERROR("Failed to send message to task\n");
free(message_p);
itti_free(ITTI_MSG_ORIGIN_ID(message_p), message_p);
message_p = NULL;
}
}
}
break;
case NW_GTPV1U_ULP_API_CREATE_TUNNEL_ENDPOINT:{
}
break;
default: {
GTPU_ERROR("Received undefined UlpApi (%02x) from gtpv1u stack!\n",
pUlpApi->apiType);
@@ -222,13 +224,12 @@ static int gtpv1u_create_s1u_tunnel(Gtpv1uCreateTunnelReq *create_tunnel_reqP)
memset(gtpv1u_teid2enb_info, 0, sizeof(gtpv1u_teid2enb_info_t));
gtpv1u_teid2enb_info->state = BEARER_IN_CONFIG;
#warning !!! hack because missing modify session request, so force enb address
gtpv1u_teid2enb_info->enb_ip_addr.pdn_type = IPv4;
gtpv1u_teid2enb_info->enb_ip_addr.address.ipv4_address[0] = 192;
gtpv1u_teid2enb_info->enb_ip_addr.address.ipv4_address[1] = 168;
gtpv1u_teid2enb_info->enb_ip_addr.address.ipv4_address[2] = 1;
gtpv1u_teid2enb_info->enb_ip_addr.address.ipv4_address[3] = 2;
gtpv1u_teid2enb_info->state = BEARER_IN_CONFIG;
//#warning !!! hack because missing modify session request, so force enb address
// gtpv1u_teid2enb_info->enb_ip_addr.pdn_type = IPv4;
// gtpv1u_teid2enb_info->enb_ip_addr.address.ipv4_address[0] = 192;
// gtpv1u_teid2enb_info->enb_ip_addr.address.ipv4_address[1] = 168;
// gtpv1u_teid2enb_info->enb_ip_addr.address.ipv4_address[2] = 1;
// gtpv1u_teid2enb_info->enb_ip_addr.address.ipv4_address[3] = 2;
message_p = itti_alloc_new_message(TASK_GTPV1_U, GTPV1U_CREATE_TUNNEL_RESP);
@@ -384,7 +385,7 @@ static void *gtpv1u_thread(void *args)
case UDP_DATA_IND: {
udp_data_ind_t *udp_data_ind_p;
udp_data_ind_p = &received_message_p->ittiMsg.udp_data_ind;
nwGtpv1uProcessUdpReq(gtpv1u_sgw_data.gtpv1u_stack,
nwGtpv1uProcessUdpReq(gtpv1u_sgw_data.gtpv1u_stack,
udp_data_ind_p->buffer,
udp_data_ind_p->buffer_length,
udp_data_ind_p->peer_port,
@@ -407,7 +408,7 @@ static void *gtpv1u_thread(void *args)
memset(&stack_req, 0, sizeof(NwGtpv1uUlpApiT));
/*
* typedef struct
* typedef struct
{
NW_IN NwU32T teid;
NW_IN NwU32T ipAddr;
@@ -470,7 +471,7 @@ static void *gtpv1u_thread(void *args)
}
break;
}
free(received_message_p);
itti_free(ITTI_MSG_ORIGIN_ID(received_message_p), received_message_p);
received_message_p = NULL;
}
return NULL;
+4 -4
View File
@@ -1,7 +1,7 @@
Installation Instructions
*************************
Copyright (C) 1994-1996, 1999-2002, 2004-2012 Free Software Foundation,
Copyright (C) 1994-1996, 1999-2002, 2004-2011 Free Software Foundation,
Inc.
Copying and distribution of this file, with or without modification,
@@ -309,10 +309,9 @@ causes the specified `gcc' to be used as the C compiler (unless it is
overridden in the site shell script).
Unfortunately, this technique does not work for `CONFIG_SHELL' due to
an Autoconf limitation. Until the limitation is lifted, you can use
this workaround:
an Autoconf bug. Until the bug is fixed you can use this workaround:
CONFIG_SHELL=/bin/bash ./configure CONFIG_SHELL=/bin/bash
CONFIG_SHELL=/bin/bash /bin/bash ./configure CONFIG_SHELL=/bin/bash
`configure' Invocation
======================
@@ -368,3 +367,4 @@ operates.
`configure' also accepts some other, not widely useful, options. Run
`configure --help' for more details.
+2
View File
@@ -19,10 +19,12 @@ noinst_LTLIBRARIES = libmmeapp.la
libmmeapp_la_LDFLAGS = -all-static
libmmeapp_la_SOURCES = \
mme_app_capabilities.c \
mme_app_context.c \
mme_app_main.c mme_app_defs.h \
mme_app_bearer.c \
mme_app_authentication.c \
mme_app_location.c \
mme_app_statistics.c mme_app_statistics.h \
mme_app_defs.h mme_app_extern.h \
mme_app_itti_messaging.h \
+84 -55
View File
@@ -1,7 +1,6 @@
/*******************************************************************************
Eurecom OpenAirInterface
Copyright(c) 1999 - 2013 Eurecom
Eurecom OpenAirInterface Core Network
Copyright(c) 1999 - 2014 Eurecom
This program is free software; you can redistribute it and/or modify it
under the terms and conditions of the GNU General Public License,
@@ -22,10 +21,13 @@
Contact Information
Openair Admin: openair_admin@eurecom.fr
Openair Tech : openair_tech@eurecom.fr
Forums : http://forums.eurecom.fr/openairinterface
Address : EURECOM, Campus SophiaTech, 450 Route des Chappes
06410 Biot FRANCE
Forums : http://forums.eurecom.fsr/openairinterface
Address : EURECOM,
Campus SophiaTech,
450 Route des Chappes,
CS 50193
06904 Biot Sophia Antipolis cedex,
FRANCE
*******************************************************************************/
#include <stdio.h>
@@ -55,8 +57,8 @@ int mme_app_request_authentication_info(const mme_app_imsi_t imsi,
const plmn_t *plmn,
const uint8_t *auts)
{
s6a_auth_info_req_t *auth_info_req;
MessageDef *message_p;
s6a_auth_info_req_t *auth_info_req = NULL;
MessageDef *message_p = NULL;
DevAssert(plmn != NULL);
@@ -77,20 +79,21 @@ int mme_app_request_authentication_info(const mme_app_imsi_t imsi,
return itti_send_msg_to_task(TASK_S6A, INSTANCE_DEFAULT, message_p);
}
int mme_app_handle_nas_auth_resp(nas_auth_resp_t *nas_auth_resp_p)
int mme_app_handle_nas_auth_resp(const nas_auth_resp_t * const nas_auth_resp_pP)
{
struct ue_context_s *ue_context;
uint64_t imsi;
struct ue_context_s *ue_context = NULL;
uint64_t imsi = 0;
DevAssert(nas_auth_resp_p != NULL);
DevAssert(nas_auth_resp_pP != NULL);
MME_APP_STRING_TO_IMSI((char *)nas_auth_resp_p->imsi, &imsi);
MME_APP_STRING_TO_IMSI((char *)nas_auth_resp_pP->imsi, &imsi);
MME_APP_DEBUG("Handling imsi %"IMSI_FORMAT"\n", imsi);
if ((ue_context = mme_ue_context_exists_imsi(&mme_app_desc.mme_ue_contexts,
imsi)) == NULL) {
MME_APP_ERROR("That's embarrassing as we don't know this IMSI\n");
AssertFatal(0, "That's embarrassing as we don't know this IMSI\n");
return -1;
}
@@ -101,8 +104,8 @@ int mme_app_handle_nas_auth_resp(nas_auth_resp_t *nas_auth_resp_p)
/* Now generate S6A ULR */
{
MessageDef *message_p;
s6a_update_location_req_t *s6a_ulr;
MessageDef *message_p = NULL;
s6a_update_location_req_t *s6a_ulr = NULL;
message_p = itti_alloc_new_message(TASK_MME_APP, S6A_UPDATE_LOCATION_REQ);
@@ -112,26 +115,27 @@ int mme_app_handle_nas_auth_resp(nas_auth_resp_t *nas_auth_resp_p)
s6a_ulr = &message_p->ittiMsg.s6a_update_location_req;
memcpy(s6a_ulr->imsi, nas_auth_resp_p->imsi, 16);
memcpy(s6a_ulr->imsi, nas_auth_resp_pP->imsi, 16);
s6a_ulr->initial_attach = INITIAL_ATTACH;
s6a_ulr->rat_type = RAT_EUTRAN;
/* Check if we already have UE data */
s6a_ulr->skip_subsriber_data = 0;
s6a_ulr->skip_subscriber_data = 0;
return itti_send_msg_to_task(TASK_S6A, INSTANCE_DEFAULT, message_p);
}
return -1;
}
int mme_app_handle_authentication_info_answer(s6a_auth_info_ans_t
*s6a_auth_info_ans_p)
int
mme_app_handle_authentication_info_answer(
const s6a_auth_info_ans_t * const s6a_auth_info_ans_pP)
{
struct ue_context_s *ue_context;
uint64_t imsi;
DevAssert(s6a_auth_info_ans_p != NULL);
DevAssert(s6a_auth_info_ans_pP != NULL);
MME_APP_STRING_TO_IMSI((char *)s6a_auth_info_ans_p->imsi, &imsi);
MME_APP_STRING_TO_IMSI((char *)s6a_auth_info_ans_pP->imsi, &imsi);
MME_APP_DEBUG("Handling imsi %"IMSI_FORMAT"\n", imsi);
@@ -141,15 +145,15 @@ int mme_app_handle_authentication_info_answer(s6a_auth_info_ans_t
return -1;
}
if ((s6a_auth_info_ans_p->result.present == S6A_RESULT_BASE) &&
(s6a_auth_info_ans_p->result.choice.base == DIAMETER_SUCCESS)) {
if ((s6a_auth_info_ans_pP->result.present == S6A_RESULT_BASE) &&
(s6a_auth_info_ans_pP->result.choice.base == DIAMETER_SUCCESS)) {
/* S6A procedure has succeeded.
* We have to request UE authentication.
*/
/* Check that list is not empty and contain only one element */
DevCheck(s6a_auth_info_ans_p->auth_info.nb_of_vectors == 1,
s6a_auth_info_ans_p->auth_info.nb_of_vectors, 1, 0);
DevCheck(s6a_auth_info_ans_pP->auth_info.nb_of_vectors == 1,
s6a_auth_info_ans_pP->auth_info.nb_of_vectors, 1, 0);
if (ue_context->vector_list == NULL) {
ue_context->vector_list = malloc(sizeof(eutran_vector_t));
@@ -161,22 +165,25 @@ int mme_app_handle_authentication_info_answer(s6a_auth_info_ans_t
DevAssert(ue_context->vector_list != NULL);
}
memcpy(&ue_context->vector_list[ue_context->nb_of_vectors],
&s6a_auth_info_ans_p->auth_info.eutran_vector, sizeof(eutran_vector_t));
&s6a_auth_info_ans_pP->auth_info.eutran_vector, sizeof(eutran_vector_t));
ue_context->vector_in_use = &ue_context->vector_list[ue_context->nb_of_vectors];
ue_context->nb_of_vectors += s6a_auth_info_ans_p->auth_info.nb_of_vectors;
ue_context->nb_of_vectors += s6a_auth_info_ans_pP->auth_info.nb_of_vectors;
MME_APP_ERROR("INFORMING NAS ABOUT AUTH RESP SUCCESS\n");
mme_app_itti_auth_rsp(ue_context->ue_id, 1,
&s6a_auth_info_ans_p->auth_info.eutran_vector);
&s6a_auth_info_ans_pP->auth_info.eutran_vector);
} else {
MME_APP_ERROR("INFORMING NAS ABOUT AUTH RESP ERROR CODE\n");
/* Inform NAS layer with the right failure */
if (s6a_auth_info_ans_p->result.present == S6A_RESULT_BASE) {
if (s6a_auth_info_ans_pP->result.present == S6A_RESULT_BASE) {
mme_app_itti_auth_fail(ue_context->ue_id, s6a_error_2_nas_cause(
s6a_auth_info_ans_p->result.choice.base, 0));
s6a_auth_info_ans_pP->result.choice.base, 0));
} else {
mme_app_itti_auth_fail(ue_context->ue_id, s6a_error_2_nas_cause(
s6a_auth_info_ans_p->result.choice.experimental, 1));
s6a_auth_info_ans_pP->result.choice.experimental, 1));
}
}
@@ -221,6 +228,7 @@ int mme_app_handle_attach_req(nas_attach_req_t *attach_req_p)
ue_context->eNB_ue_s1ap_id = attach_req_p->transparent.eNB_ue_s1ap_id;
ue_context->mme_ue_s1ap_id = attach_req_p->transparent.mme_ue_s1ap_id;
ue_context->ue_id = attach_req_p->transparent.mme_ue_s1ap_id;
// STAILQ_INIT(&ue_context->vector_list);
DevAssert(mme_insert_ue_context(&mme_app_desc.mme_ue_contexts, ue_context) == 0);
@@ -292,8 +300,9 @@ request_auth: {
return 0;
}
#else
void mme_app_handle_nas_auth_param_req(nas_auth_param_req_t
*nas_auth_param_req_p)
void
mme_app_handle_nas_auth_param_req(
const nas_auth_param_req_t * const nas_auth_param_req_pP)
{
static const plmn_t visited_plmn_eur = {
.MCCdigit3 = 2,
@@ -312,20 +321,35 @@ void mme_app_handle_nas_auth_param_req(nas_auth_param_req_t
.MNCdigit1 = 0xF,
};
plmn_t *visited_plmn;
struct ue_context_s *ue_context;
uint64_t imsi = 0;
DevAssert(nas_auth_param_req_p != NULL);
plmn_t *visited_plmn = NULL;
struct ue_context_s *ue_context = NULL;
uint64_t imsi = 0;
plmn_t visited_plmn_from_req = {
.MCCdigit3 = 0,
.MCCdigit2 = 0,
.MCCdigit1 = 0,
.MNCdigit1 = 0,
.MNCdigit2 = 0,
.MNCdigit3 = 0,
};
DevAssert(nas_auth_param_req_pP != NULL);
#if 1
visited_plmn = &visited_plmn_eur;
#else
visited_plmn = &visited_plmn_dongle;
#endif
//visited_plmn = &visited_plmn_eur;
//visited_plmn = &visited_plmn_dongle;
visited_plmn = &visited_plmn_from_req;
MME_APP_STRING_TO_IMSI(nas_auth_param_req_p->imsi, &imsi);
#warning "assume MNC on 2 digits only"
visited_plmn_from_req.MCCdigit3 = nas_auth_param_req_pP->imsi[0];
visited_plmn_from_req.MCCdigit2 = nas_auth_param_req_pP->imsi[1];
visited_plmn_from_req.MCCdigit1 = nas_auth_param_req_pP->imsi[2];
visited_plmn_from_req.MNCdigit1 = 0;
visited_plmn_from_req.MNCdigit2 = nas_auth_param_req_pP->imsi[3];
visited_plmn_from_req.MNCdigit3 = nas_auth_param_req_pP->imsi[4];
MME_APP_DEBUG("Handling imsi %"IMSI_FORMAT"\n", imsi);
MME_APP_STRING_TO_IMSI(nas_auth_param_req_pP->imsi, &imsi);
MME_APP_DEBUG("%s Handling imsi %"IMSI_FORMAT"\n", __FUNCTION__, imsi);
MME_APP_DEBUG("%s Handling imsi from req %s\n", __FUNCTION__, nas_auth_param_req_pP->imsi);
/* Fetch the context associated with this IMSI */
ue_context = mme_ue_context_exists_imsi(&mme_app_desc.mme_ue_contexts, imsi);
@@ -334,18 +358,23 @@ void mme_app_handle_nas_auth_param_req(nas_auth_param_req_t
/* Currently no context available -> trigger an authentication request
* to the HSS.
*/
MME_APP_DEBUG("UE context doesn't exist -> create one\n");
if ((ue_context = mme_create_new_ue_context()) == NULL) {
/* Error during ue context malloc */
/* TODO */
DevMessage("mme_create_new_ue_context");
return;
MME_APP_DEBUG("UE context search by IMSI failed, try by ue id\n");
ue_context = mme_ue_context_exists_nas_ue_id(&mme_app_desc.mme_ue_contexts, nas_auth_param_req_pP->ue_id);
if (ue_context == NULL) {
// should have been created by initial ue message
MME_APP_ERROR("UE context doesn't exist -> create one\n");
if ((ue_context = mme_create_new_ue_context()) == NULL) {
/* Error during ue context malloc */
/* TODO */
DevMessage("mme_create_new_ue_context");
return;
}
ue_context->ue_id = nas_auth_param_req_pP->ue_id;
ue_context->mme_ue_s1ap_id = nas_auth_param_req_pP->ue_id;
DevAssert(mme_insert_ue_context(&mme_app_desc.mme_ue_contexts, ue_context) == 0);
}
ue_context->imsi = imsi;
ue_context->ue_id = nas_auth_param_req_p->ue_id;
DevAssert(mme_insert_ue_context(&mme_app_desc.mme_ue_contexts, ue_context) == 0);
/* We have no vector for this UE, send an authentication request
* to the HSS.
*/
@@ -360,7 +389,7 @@ void mme_app_handle_nas_auth_param_req(nas_auth_param_req_t
} else {
memcpy(&ue_context->guti.gummei.plmn, visited_plmn, sizeof(plmn_t));
mme_app_request_authentication_info(imsi, 1, visited_plmn, nas_auth_param_req_p->auts);
mme_app_request_authentication_info(imsi, 1, visited_plmn, nas_auth_param_req_pP->auts);
}
}
#endif
+534 -222
View File
@@ -1,33 +1,40 @@
/*******************************************************************************
Eurecom OpenAirInterface Core Network
Copyright(c) 1999 - 2014 Eurecom
Eurecom OpenAirInterface
Copyright(c) 1999 - 2013 Eurecom
This program is free software; you can redistribute it and/or modify it
under the terms and conditions of the GNU General Public License,
version 2, as published by the Free Software Foundation.
This program is free software; you can redistribute it and/or modify it
under the terms and conditions of the GNU General Public License,
version 2, as published by the Free Software Foundation.
This program is distributed in the hope 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.
This program is distributed in the hope 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, write to the Free Software Foundation, Inc.,
51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
The full GNU General Public License is included in this distribution in
the file called "COPYING".
Contact Information
Openair Admin: openair_admin@eurecom.fr
Openair Tech : openair_tech@eurecom.fr
Forums : http://forums.eurecom.fr/openairinterface
Address : EURECOM, Campus SophiaTech, 450 Route des Chappes
06410 Biot FRANCE
The full GNU General Public License is included in this distribution in
the file called "COPYING".
Contact Information
Openair Admin: openair_admin@eurecom.fr
Openair Tech : openair_tech@eurecom.fr
Forums : http://forums.eurecom.fsr/openairinterface
Address : EURECOM,
Campus SophiaTech,
450 Route des Chappes,
CS 50193
06904 Biot Sophia Antipolis cedex,
FRANCE
*******************************************************************************/
/*! \file mme_app_bearer.c
* \brief
* \author Sebastien ROUX, Lionel Gauthier
* \company Eurecom
* \email: lionel.gauthier@eurecom.fr
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -42,246 +49,388 @@
#include "secu_defs.h"
#include "assertions.h"
#include "common_types.h"
int mme_app_create_bearer(s6a_update_location_ans_t *ula_p)
int
mme_app_send_s11_create_session_req(
struct ue_context_s * const ue_context_pP)
{
uint64_t imsi;
uint8_t i;
task_id_t to_task;
uint8_t i = 0;
task_id_t to_task = TASK_UNKNOWN;
/* Keep the identifier to the default APN */
context_identifier_t context_identifier;
MessageDef *message_p = NULL;
SgwCreateSessionRequest *session_request_p = NULL;
struct apn_configuration_s *default_apn_p = NULL;
struct ue_context_s *ue_context;
MessageDef *message_p;
SgwCreateSessionRequest *session_request_p;
/* Keep the identifier to the default APN */
context_identifier_t context_identifier;
struct apn_configuration_s *default_apn;
DevAssert(ula_p != NULL);
DevAssert(ue_context_pP != NULL);
#if defined(DISABLE_STANDALONE_EPC)
to_task = TASK_S11;
to_task = TASK_S11;
#else
to_task = TASK_SPGW_APP;
to_task = TASK_SPGW_APP;
#endif
if (ula_p->result.present == S6A_RESULT_BASE) {
if (ula_p->result.choice.base != DIAMETER_SUCCESS) {
/* The update location procedure has failed. Notify the NAS layer
* and don't initiate the bearer creation on S-GW side.
*/
DevMessage("ULR/ULA procedure returned non success\n");
}
} else {
/* The update location procedure has failed. Notify the NAS layer
* and don't initiate the bearer creation on S-GW side.
*/
DevMessage("ULR/ULA procedure returned non success\n");
}
MME_APP_STRING_TO_IMSI((char *)ula_p->imsi, &imsi);
MME_APP_DEBUG("Handling imsi %"IMSI_FORMAT"\n", ue_context_pP->imsi);
MME_APP_DEBUG("Handling imsi %"IMSI_FORMAT"\n", imsi);
if (ue_context_pP->sub_status != SS_SERVICE_GRANTED) {
/* HSS rejected the bearer creation or roaming is not allowed for this
* UE. This result will trigger an ESM Failure message sent to UE.
*/
DevMessage("Not implemented: ACCESS NOT GRANTED, send ESM Failure to NAS\n");
}
if ((ue_context = mme_ue_context_exists_imsi(&mme_app_desc.mme_ue_contexts, imsi)) == NULL) {
MME_APP_ERROR("That's embarrassing as we don't know this IMSI\n");
return -1;
}
message_p = itti_alloc_new_message(TASK_MME_APP, SGW_CREATE_SESSION_REQUEST);
ue_context->subscription_known = SUBSCRIPTION_KNOWN;
/* WARNING:
* Some parameters should be provided by NAS Layer:
* - ue_time_zone
* - mei
* - uli
* - uci
* Some parameters should be provided by HSS:
* - PGW address for CP
* - paa
* - ambr
* and by MME Application layer:
* - selection_mode
* Set these parameters with random values for now.
*/
ue_context->sub_status = ula_p->subscription_data.subscriber_status;
ue_context->access_restriction_data = ula_p->subscription_data.access_restriction;
session_request_p = &message_p->ittiMsg.sgwCreateSessionRequest;
memset(session_request_p, 0, sizeof(SgwCreateSessionRequest));
/* Copy the subscribed ambr to the sgw create session request message */
memcpy(&ue_context->subscribed_ambr, &ula_p->subscription_data.subscribed_ambr,
sizeof(ambr_t));
memcpy(ue_context->msisdn, ula_p->subscription_data.msisdn,
MSISDN_LENGTH);
/* As the create session request is the first exchanged message and as
* no tunnel had been previously setup, the distant teid is set to 0.
* The remote teid will be provided in the response message.
*/
session_request_p->teid = 0;
ue_context->rau_tau_timer = ula_p->subscription_data.rau_tau_timer;
ue_context->access_mode = ula_p->subscription_data.access_mode;
ue_context->rau_tau_timer = ula_p->subscription_data.rau_tau_timer;
MME_APP_IMSI_TO_STRING(ue_context_pP->imsi, (char *)session_request_p->imsi.digit);
// message content was set to 0
session_request_p->imsi.length = strlen((const char *)session_request_p->imsi.digit);
memcpy(&ue_context->apn_profile, &ula_p->subscription_data.apn_config_profile,
sizeof(apn_config_profile_t));
/* Copy the MSISDN */
memcpy(
session_request_p->msisdn.digit,
ue_context_pP->msisdn,
ue_context_pP->msisdn_length);
session_request_p->msisdn.length = ue_context_pP->msisdn_length;
// mme_app_dump_ue_contexts();
session_request_p->rat_type = RAT_EUTRAN;
if (ula_p->subscription_data.subscriber_status != SS_SERVICE_GRANTED) {
/* HSS rejected the bearer creation or roaming is not allowed for this
* UE. This result will trigger an ESM Failure message sent to UE.
*/
DevMessage("Not implemented: ACCESS NOT GRANTED, send ESM Failure to NAS\n");
}
/* Copy the subscribed ambr to the sgw create session request message */
memcpy(
&session_request_p->ambr,
&ue_context_pP->subscribed_ambr,
sizeof(ambr_t));
message_p = itti_alloc_new_message(TASK_MME_APP, SGW_CREATE_SESSION_REQUEST);
if (ue_context_pP->apn_profile.nb_apns == 0) {
DevMessage("No APN returned by the HSS");
}
/* WARNING:
* Some parameters should be provided by NAS Layer:
* - ue_time_zone
* - mei
* - uli
* - uci
* Some parameters should be provided by HSS:
* - PGW address for CP
* - paa
* - ambr
* and by MME Application layer:
* - selection_mode
* Set these parameters with random values for now.
*/
context_identifier = ue_context_pP->apn_profile.context_identifier;
for (i = 0; i < ue_context_pP->apn_profile.nb_apns; i++) {
default_apn_p = &ue_context_pP->apn_profile.apn_configuration[i];
/* OK we got our default APN */
if (default_apn_p->context_identifier == context_identifier)
break;
}
session_request_p = &message_p->ittiMsg.sgwCreateSessionRequest;
memset(session_request_p, 0, sizeof(SgwCreateSessionRequest));
if (!default_apn_p) {
/* Unfortunately we didn't find our default APN... */
DevMessage("No default APN found");
}
/* As the create session request is the first exchanged message and as
* no tunnel had been previously setup, the distant teid is set to 0.
* The remote teid will be provided in the response message.
*/
session_request_p->teid = 0;
memcpy(&session_request_p->bearer_to_create.bearer_level_qos.gbr,
&default_apn_p->ambr, sizeof(ambr_t));
memcpy(&session_request_p->bearer_to_create.bearer_level_qos.mbr,
&default_apn_p->ambr, sizeof(ambr_t));
memcpy(session_request_p->imsi.digit, ula_p->imsi,
ula_p->imsi_length);
session_request_p->imsi.length = ula_p->imsi_length;
session_request_p->bearer_to_create.bearer_level_qos.qci =
default_apn_p->subscribed_qos.qci;
/* Copy the MSISDN */
memcpy(session_request_p->msisdn.digit, ula_p->subscription_data.msisdn,
ula_p->subscription_data.msisdn_length);
session_request_p->msisdn.length = ula_p->subscription_data.msisdn_length;
session_request_p->bearer_to_create.bearer_level_qos.pvi =
default_apn_p->subscribed_qos.allocation_retention_priority.pre_emp_vulnerability;
session_request_p->bearer_to_create.bearer_level_qos.pci =
default_apn_p->subscribed_qos.allocation_retention_priority.pre_emp_capability;
session_request_p->bearer_to_create.bearer_level_qos.pl =
default_apn_p->subscribed_qos.allocation_retention_priority.priority_level;
session_request_p->rat_type = RAT_EUTRAN;
/* Asking for default bearer in initial UE message.
* Use the address of ue_context as unique TEID: Need to find better here
* and will generate unique id only for 32 bits platforms.
*/
session_request_p->sender_fteid_for_cp.teid = (uint32_t)ue_context_pP;
session_request_p->sender_fteid_for_cp.interface_type = S11_MME_GTP_C;
session_request_p->bearer_to_create.eps_bearer_id = 5;
/* Copy the subscribed ambr to the sgw create session request message */
memcpy(&session_request_p->ambr, &ula_p->subscription_data.subscribed_ambr,
sizeof(ambr_t));
ue_context_pP->mme_s11_teid = session_request_p->sender_fteid_for_cp.teid;
ue_context_pP->sgw_s11_teid = 0;
if (ula_p->subscription_data.apn_config_profile.nb_apns == 0) {
DevMessage("No APN returned by the HSS");
}
memcpy(session_request_p->apn, default_apn_p->service_selection,
default_apn_p->service_selection_length);
context_identifier = ula_p->subscription_data.apn_config_profile.context_identifier;
for (i = 0; i < ula_p->subscription_data.apn_config_profile.nb_apns; i++) {
default_apn = &ula_p->subscription_data.apn_config_profile.apn_configuration[i];
/* OK we got our default APN */
if (default_apn->context_identifier == context_identifier)
break;
}
/* Set PDN type for pdn_type and PAA even if this IE is redundant */
session_request_p->pdn_type = default_apn_p->pdn_type;
session_request_p->paa.pdn_type = default_apn_p->pdn_type;
if (default_apn_p->nb_ip_address == 0) {
/* UE DHCPv4 allocated ip address */
memset(session_request_p->paa.ipv4_address, 0, 4);
memset(session_request_p->paa.ipv6_address, 0, 16);
} else {
uint8_t j;
if (!default_apn) {
/* Unfortunately we didn't find our default APN... */
DevMessage("No default APN found");
}
memcpy(&session_request_p->bearer_to_create.bearer_level_qos.gbr,
&default_apn->ambr, sizeof(ambr_t));
memcpy(&session_request_p->bearer_to_create.bearer_level_qos.mbr,
&default_apn->ambr, sizeof(ambr_t));
session_request_p->bearer_to_create.bearer_level_qos.qci =
default_apn->subscribed_qos.qci;
session_request_p->bearer_to_create.bearer_level_qos.pvi =
default_apn->subscribed_qos.allocation_retention_priority.pre_emp_vulnerability;
session_request_p->bearer_to_create.bearer_level_qos.pci =
default_apn->subscribed_qos.allocation_retention_priority.pre_emp_capability;
session_request_p->bearer_to_create.bearer_level_qos.pl =
default_apn->subscribed_qos.allocation_retention_priority.priority_level;
/* Asking for default bearer in initial UE message.
* Use the address of ue_context as unique TEID: Need to find better here
* and will generate unique id only for 32 bits platforms.
*/
session_request_p->sender_fteid_for_cp.teid = (uint32_t)ue_context;
session_request_p->sender_fteid_for_cp.interface_type = S11_MME_GTP_C;
session_request_p->bearer_to_create.eps_bearer_id = 5;
ue_context->mme_s11_teid = session_request_p->sender_fteid_for_cp.teid;
ue_context->sgw_s11_teid = 0;
memcpy(session_request_p->apn, default_apn->service_selection,
default_apn->service_selection_length);
/* Set PDN type for pdn_type and PAA even if this IE is redundant */
session_request_p->pdn_type = default_apn->pdn_type;
session_request_p->paa.pdn_type = default_apn->pdn_type;
if (default_apn->nb_ip_address == 0) {
/* UE DHCPv4 allocated ip address */
memset(session_request_p->paa.ipv4_address, 0, 4);
memset(session_request_p->paa.ipv6_address, 0, 16);
} else {
uint8_t j;
for (j = 0; j < default_apn->nb_ip_address; j++) {
ip_address_t *ip_address;
ip_address = &default_apn->ip_address[j];
if (ip_address->pdn_type == IPv4) {
memcpy(session_request_p->paa.ipv4_address, ip_address->address.ipv4_address, 4);
} else if (ip_address->pdn_type == IPv6) {
memcpy(session_request_p->paa.ipv6_address, ip_address->address.ipv6_address, 16);
}
for (j = 0; j < default_apn_p->nb_ip_address; j++) {
ip_address_t *ip_address;
ip_address = &default_apn_p->ip_address[j];
if (ip_address->pdn_type == IPv4) {
memcpy(session_request_p->paa.ipv4_address, ip_address->address.ipv4_address, 4);
} else if (ip_address->pdn_type == IPv6) {
memcpy(session_request_p->paa.ipv6_address, ip_address->address.ipv6_address, 16);
}
// free(ip_address);
}
}
}
}
config_read_lock(&mme_config);
session_request_p->peer_ip = mme_config.ipv4.sgw_ip_address_for_S11;
config_unlock(&mme_config);
config_read_lock(&mme_config);
session_request_p->peer_ip = mme_config.ipv4.sgw_ip_address_for_S11;
config_unlock(&mme_config);
session_request_p->serving_network.mcc[0] = ue_context->e_utran_cgi.plmn.MCCdigit1;
session_request_p->serving_network.mcc[1] = ue_context->e_utran_cgi.plmn.MCCdigit2;
session_request_p->serving_network.mcc[2] = ue_context->e_utran_cgi.plmn.MCCdigit3;
session_request_p->serving_network.mcc[0] = ue_context_pP->e_utran_cgi.plmn.MCCdigit1;
session_request_p->serving_network.mcc[1] = ue_context_pP->e_utran_cgi.plmn.MCCdigit2;
session_request_p->serving_network.mcc[2] = ue_context_pP->e_utran_cgi.plmn.MCCdigit3;
session_request_p->serving_network.mnc[0] = ue_context->e_utran_cgi.plmn.MNCdigit1;
session_request_p->serving_network.mnc[1] = ue_context->e_utran_cgi.plmn.MNCdigit2;
session_request_p->serving_network.mnc[2] = ue_context->e_utran_cgi.plmn.MNCdigit3;
session_request_p->serving_network.mnc[0] = ue_context_pP->e_utran_cgi.plmn.MNCdigit1;
session_request_p->serving_network.mnc[1] = ue_context_pP->e_utran_cgi.plmn.MNCdigit2;
session_request_p->serving_network.mnc[2] = ue_context_pP->e_utran_cgi.plmn.MNCdigit3;
session_request_p->selection_mode = MS_O_N_P_APN_S_V;
return itti_send_msg_to_task(to_task, INSTANCE_DEFAULT, message_p);
session_request_p->selection_mode = MS_O_N_P_APN_S_V;
return itti_send_msg_to_task(to_task, INSTANCE_DEFAULT, message_p);
}
int mme_app_handle_create_sess_resp(SgwCreateSessionResponse *create_sess_resp_p)
int
mme_app_handle_nas_pdn_connectivity_req(
nas_pdn_connectivity_req_t * const nas_pdn_connectivity_req_pP)
{
struct ue_context_s *ue_context_p;
bearer_context_t *current_bearer_p;
struct ue_context_s *ue_context_p = NULL;
uint64_t imsi = 0;
MME_APP_DEBUG("Received NAS_PDN_CONNECTIVITY_REQ from NAS\n");
DevAssert(nas_pdn_connectivity_req_pP != NULL);
MME_APP_STRING_TO_IMSI((char *)nas_pdn_connectivity_req_pP->imsi, &imsi);
MME_APP_DEBUG("Handling imsi %"IMSI_FORMAT"\n", imsi);
if ((ue_context_p = mme_ue_context_exists_imsi(&mme_app_desc.mme_ue_contexts,
imsi)) == NULL) {
MME_APP_ERROR("That's embarrassing as we don't know this IMSI\n");
return -1;
}
/* Consider the UE authenticated */
ue_context_p->imsi_auth = IMSI_AUTHENTICATED;
// Temp: save request, in near future merge wisely params in context
memset(ue_context_p->pending_pdn_connectivity_req_imsi,0, 16);
AssertFatal((nas_pdn_connectivity_req_pP->imsi_length > 0) &&
(nas_pdn_connectivity_req_pP->imsi_length < 16),
"BAD IMSI LENGTH %d", nas_pdn_connectivity_req_pP->imsi_length);
AssertFatal((nas_pdn_connectivity_req_pP->imsi_length > 0) &&
(nas_pdn_connectivity_req_pP->imsi_length < 16),
"STOP ON IMSI LENGTH %d", nas_pdn_connectivity_req_pP->imsi_length);
memcpy(ue_context_p->pending_pdn_connectivity_req_imsi,
nas_pdn_connectivity_req_pP->imsi,
nas_pdn_connectivity_req_pP->imsi_length);
ue_context_p->pending_pdn_connectivity_req_imsi_length = nas_pdn_connectivity_req_pP->imsi_length;
DUP_OCTET_STRING(nas_pdn_connectivity_req_pP->apn, ue_context_p->pending_pdn_connectivity_req_apn);
FREE_OCTET_STRING(nas_pdn_connectivity_req_pP->apn)
// dup OctetString
DUP_OCTET_STRING(nas_pdn_connectivity_req_pP->pdn_addr, ue_context_p->pending_pdn_connectivity_req_pdn_addr);
FREE_OCTET_STRING(nas_pdn_connectivity_req_pP->pdn_addr)
ue_context_p->pending_pdn_connectivity_req_pti = nas_pdn_connectivity_req_pP->pti;
ue_context_p->pending_pdn_connectivity_req_ue_id = nas_pdn_connectivity_req_pP->ue_id;
memcpy(&ue_context_p->pending_pdn_connectivity_req_qos,
&nas_pdn_connectivity_req_pP->qos,
sizeof(network_qos_t));
ue_context_p->pending_pdn_connectivity_req_proc_data = nas_pdn_connectivity_req_pP->proc_data;
nas_pdn_connectivity_req_pP->proc_data = NULL;
ue_context_p->pending_pdn_connectivity_req_request_type = nas_pdn_connectivity_req_pP->request_type;
//if ((nas_pdn_connectivity_req_pP->apn.value == NULL) || (nas_pdn_connectivity_req_pP->apn.length == 0)) {
/* TODO: Get keys... */
/* Now generate S6A ULR */
return mme_app_send_s6a_update_location_req(ue_context_p);
//} else {
//return mme_app_send_s11_create_session_req(ue_context_p);
//}
//return -1;
}
// sent by NAS
void
mme_app_handle_conn_est_cnf(
const nas_conn_est_cnf_t * const nas_conn_est_cnf_pP)
{
struct ue_context_s *ue_context_p = NULL;
MessageDef *message_p = NULL;
mme_app_connection_establishment_cnf_t *establishment_cnf_p = NULL;
bearer_context_t *current_bearer_p = NULL;
ebi_t bearer_id = 0;
MME_APP_DEBUG("Received NAS_CONNECTION_ESTABLISHMENT_CNF from NAS\n");
ue_context_p = mme_ue_context_exists_nas_ue_id(&mme_app_desc.mme_ue_contexts, nas_conn_est_cnf_pP->UEid);
if (ue_context_p == NULL) {
MME_APP_ERROR("UE context doesn't exist\n");
return;
}
message_p = itti_alloc_new_message(TASK_MME_APP, MME_APP_CONNECTION_ESTABLISHMENT_CNF);
establishment_cnf_p = &message_p->ittiMsg.mme_app_connection_establishment_cnf;
memset(establishment_cnf_p, 0, sizeof(mme_app_connection_establishment_cnf_t));
memcpy(&establishment_cnf_p->nas_conn_est_cnf,
nas_conn_est_cnf_pP,
sizeof(nas_conn_est_cnf_t));
bearer_id = ue_context_p->default_bearer_id;
current_bearer_p = &ue_context_p->eps_bearers[bearer_id];
establishment_cnf_p->eps_bearer_id = bearer_id;
establishment_cnf_p->bearer_s1u_sgw_fteid.interface_type = S1_U_SGW_GTP_U;
establishment_cnf_p->bearer_s1u_sgw_fteid.teid = current_bearer_p->s_gw_teid;
if ((current_bearer_p->s_gw_address.pdn_type == IPv4) ||
(current_bearer_p->s_gw_address.pdn_type == IPv4_AND_v6)) {
establishment_cnf_p->bearer_s1u_sgw_fteid.ipv4 = 1;
memcpy(&establishment_cnf_p->bearer_s1u_sgw_fteid.ipv4_address,
current_bearer_p->s_gw_address.address.ipv4_address,
4);
}
if ((current_bearer_p->s_gw_address.pdn_type == IPv6) ||
(current_bearer_p->s_gw_address.pdn_type == IPv4_AND_v6)) {
establishment_cnf_p->bearer_s1u_sgw_fteid.ipv6 = 1;
memcpy(establishment_cnf_p->bearer_s1u_sgw_fteid.ipv6_address,
current_bearer_p->s_gw_address.address.ipv6_address,
16);
}
establishment_cnf_p->bearer_qos_qci = current_bearer_p->qci;
establishment_cnf_p->bearer_qos_prio_level = current_bearer_p->prio_level;
establishment_cnf_p->bearer_qos_pre_emp_vulnerability = current_bearer_p->pre_emp_vulnerability;
establishment_cnf_p->bearer_qos_pre_emp_capability = current_bearer_p->pre_emp_capability;
establishment_cnf_p->ambr = ue_context_p->used_ambr;
itti_send_msg_to_task(TASK_S1AP, INSTANCE_DEFAULT, message_p);
}
// sent by S1AP
void
mme_app_handle_conn_est_ind(
const mme_app_connection_establishment_ind_t * const conn_est_ind_pP)
{
struct ue_context_s *ue_context_p = NULL;
MessageDef *message_p = NULL;
MME_APP_DEBUG("Received MME_APP_CONNECTION_ESTABLISHMENT_IND from S1AP\n");
ue_context_p = mme_ue_context_exists_mme_ue_s1ap_id(
&mme_app_desc.mme_ue_contexts,
conn_est_ind_pP->mme_ue_s1ap_id);
if (ue_context_p == NULL) {
MME_APP_DEBUG("We didn't find this mme_ue_s1ap_id in list of UE: %08x\n",
conn_est_ind_pP->mme_ue_s1ap_id);
MME_APP_DEBUG("UE context doesn't exist -> create one\n");
if ((ue_context_p = mme_create_new_ue_context()) == NULL) {
/* Error during ue context malloc */
/* TODO */
DevMessage("mme_create_new_ue_context");
return;
}
// S1AP UE ID AND NAS UE ID ARE THE SAME
ue_context_p->mme_ue_s1ap_id = conn_est_ind_pP->mme_ue_s1ap_id;
ue_context_p->ue_id = conn_est_ind_pP->mme_ue_s1ap_id;
DevAssert(mme_insert_ue_context(&mme_app_desc.mme_ue_contexts, ue_context_p) == 0);
// test
ue_context_p = mme_ue_context_exists_mme_ue_s1ap_id(
&mme_app_desc.mme_ue_contexts,
conn_est_ind_pP->mme_ue_s1ap_id);
AssertFatal(ue_context_p != NULL, "mme_ue_context_exists_mme_ue_s1ap_id Failed");
}
message_p = itti_alloc_new_message(TASK_MME_APP, NAS_CONNECTION_ESTABLISHMENT_IND);
memcpy(&NAS_CONN_EST_IND(message_p).nas,
&conn_est_ind_pP->nas,
sizeof (nas_establish_ind_t));
itti_send_msg_to_task(TASK_NAS_MME, INSTANCE_DEFAULT, message_p);
}
int
mme_app_handle_create_sess_resp(
const SgwCreateSessionResponse * const create_sess_resp_pP)
{
struct ue_context_s *ue_context_p = NULL;
bearer_context_t *current_bearer_p = NULL;
MessageDef *message_p = NULL;
int16_t bearer_id;
DevAssert(create_sess_resp_p != NULL);
DevAssert(create_sess_resp_pP != NULL);
MME_APP_DEBUG("Received create session response from S+P-GW\n");
MME_APP_DEBUG("Received SGW_CREATE_SESSION_RESPONSE from S+P-GW\n");
ue_context_p = mme_ue_context_exists_s11_teid(&mme_app_desc.mme_ue_contexts,
create_sess_resp_p->teid);
create_sess_resp_pP->teid);
if (ue_context_p == NULL) {
MME_APP_DEBUG("We didn't find this teid in list of UE: %08x\n",
create_sess_resp_p->teid);
create_sess_resp_pP->teid);
return -1;
}
/* Store the S-GW teid */
ue_context_p->sgw_s11_teid = create_sess_resp_p->s11_sgw_teid.teid;
bearer_id = create_sess_resp_p->bearer_context_created.eps_bearer_id/* - 5*/;
ue_context_p->sgw_s11_teid = create_sess_resp_pP->s11_sgw_teid.teid;
//---------------------------------------------------------
// Process SgwCreateSessionResponse.bearer_context_created
//---------------------------------------------------------
bearer_id = create_sess_resp_pP->bearer_context_created.eps_bearer_id/* - 5*/;
/* Depending on s11 result we have to send reject or accept for bearers */
DevCheck((bearer_id < BEARERS_PER_UE) && (bearer_id >= 0), bearer_id,
BEARERS_PER_UE, 0);
DevCheck((bearer_id < BEARERS_PER_UE) && (bearer_id >= 0),
bearer_id,
BEARERS_PER_UE,
0);
ue_context_p->default_bearer_id = bearer_id;
if (create_sess_resp_p->bearer_context_created.cause != REQUEST_ACCEPTED) {
if (create_sess_resp_pP->bearer_context_created.cause != REQUEST_ACCEPTED) {
DevMessage("Cases where bearer cause != REQUEST_ACCEPTED are not handled\n");
}
DevAssert(create_sess_resp_p->bearer_context_created.s1u_sgw_fteid.interface_type == S1_U_SGW_GTP_U);
DevAssert(create_sess_resp_pP->bearer_context_created.s1u_sgw_fteid.interface_type == S1_U_SGW_GTP_U);
/* Updating statistics */
mme_app_desc.mme_ue_contexts.nb_bearers_managed++;
mme_app_desc.mme_ue_contexts.nb_bearers_since_last_stat++;
current_bearer_p = &ue_context_p->eps_bearers[bearer_id];
current_bearer_p->s_gw_teid = create_sess_resp_p->bearer_context_created.s1u_sgw_fteid.teid;
switch (create_sess_resp_p->bearer_context_created.s1u_sgw_fteid.ipv4 +
(create_sess_resp_p->bearer_context_created.s1u_sgw_fteid.ipv6 << 1))
current_bearer_p->s_gw_teid = create_sess_resp_pP->bearer_context_created.s1u_sgw_fteid.teid;
switch (create_sess_resp_pP->bearer_context_created.s1u_sgw_fteid.ipv4 +
(create_sess_resp_pP->bearer_context_created.s1u_sgw_fteid.ipv6 << 1))
{
default:
case 0: {
@@ -292,58 +441,221 @@ int mme_app_handle_create_sess_resp(SgwCreateSessionResponse *create_sess_resp_p
/* Only IPv4 address */
current_bearer_p->s_gw_address.pdn_type = IPv4;
memcpy(current_bearer_p->s_gw_address.address.ipv4_address,
&create_sess_resp_p->bearer_context_created.s1u_sgw_fteid.ipv4_address, 4);
&create_sess_resp_pP->bearer_context_created.s1u_sgw_fteid.ipv4_address, 4);
} break;
case 2: {
/* Only IPv6 address */
current_bearer_p->s_gw_address.pdn_type = IPv6;
memcpy(current_bearer_p->s_gw_address.address.ipv6_address,
create_sess_resp_p->bearer_context_created.s1u_sgw_fteid.ipv6_address, 16);
create_sess_resp_pP->bearer_context_created.s1u_sgw_fteid.ipv6_address, 16);
} break;
case 3: {
/* Both IPv4 and Ipv6 */
current_bearer_p->s_gw_address.pdn_type = IPv4_AND_v6;
memcpy(current_bearer_p->s_gw_address.address.ipv4_address,
&create_sess_resp_p->bearer_context_created.s1u_sgw_fteid.ipv4_address, 4);
&create_sess_resp_pP->bearer_context_created.s1u_sgw_fteid.ipv4_address, 4);
memcpy(current_bearer_p->s_gw_address.address.ipv6_address,
create_sess_resp_p->bearer_context_created.s1u_sgw_fteid.ipv6_address, 16);
create_sess_resp_pP->bearer_context_created.s1u_sgw_fteid.ipv6_address, 16);
} break;
}
current_bearer_p->p_gw_teid = create_sess_resp_pP->bearer_context_created.s5_s8_u_pgw_fteid.teid;
memset(&current_bearer_p->p_gw_address,0, sizeof(ip_address_t));
if (create_sess_resp_pP->bearer_context_created.bearer_level_qos != NULL) {
current_bearer_p->qci = create_sess_resp_pP->bearer_context_created.bearer_level_qos->qci;
current_bearer_p->prio_level = create_sess_resp_pP->bearer_context_created.bearer_level_qos->pl;
current_bearer_p->pre_emp_vulnerability = create_sess_resp_pP->bearer_context_created.bearer_level_qos->pvi;
current_bearer_p->pre_emp_capability = create_sess_resp_pP->bearer_context_created.bearer_level_qos->pci;
current_bearer_p->prio_level = create_sess_resp_pP->bearer_context_created.bearer_level_qos->pl;
}
mme_app_dump_ue_contexts(&mme_app_desc.mme_ue_contexts);
/* Generate attach accepted */
{
uint8_t *keNB;
MessageDef *message_p;
uint8_t *keNB = NULL;
message_p = itti_alloc_new_message(TASK_MME_APP, NAS_BEARER_PARAM);
message_p = itti_alloc_new_message(TASK_MME_APP, NAS_PDN_CONNECTIVITY_RSP);
memset((void*)&message_p->ittiMsg.nas_pdn_connectivity_rsp,
0,
sizeof(nas_pdn_connectivity_rsp_t));
derive_keNB(ue_context_p->vector_in_use->kasme, 156, &keNB);
memcpy(NAS_BEARER_PARAM(message_p).keNB, keNB, 32);
memcpy(NAS_PDN_CONNECTIVITY_RSP(message_p).keNB, keNB, 32);
free(keNB);
NAS_BEARER_PARAM(message_p).eNB_ue_s1ap_id = ue_context_p->eNB_ue_s1ap_id;
NAS_BEARER_PARAM(message_p).mme_ue_s1ap_id = ue_context_p->mme_ue_s1ap_id;
NAS_PDN_CONNECTIVITY_RSP(message_p).pti = ue_context_p->pending_pdn_connectivity_req_pti; // NAS internal ref
NAS_PDN_CONNECTIVITY_RSP(message_p).ue_id = ue_context_p->pending_pdn_connectivity_req_ue_id; // NAS internal ref
// TO REWORK:
if ((ue_context_p->pending_pdn_connectivity_req_apn.value != NULL)
&& (ue_context_p->pending_pdn_connectivity_req_apn.length != 0)) {
DUP_OCTET_STRING(
ue_context_p->pending_pdn_connectivity_req_apn,
NAS_PDN_CONNECTIVITY_RSP(message_p).apn);
MME_APP_DEBUG("SET APN FROM NAS PDN CONNECTIVITY CREATE: %s\n", NAS_PDN_CONNECTIVITY_RSP(message_p).apn.value);
} else {
int i;
context_identifier_t context_identifier = ue_context_p->apn_profile.context_identifier;
for (i = 0; i < ue_context_p->apn_profile.nb_apns; i++) {
if (ue_context_p->apn_profile.apn_configuration[i].context_identifier == context_identifier) {
AssertFatal(ue_context_p->apn_profile.apn_configuration[i].service_selection_length > 0, "Bad APN string (len = 0)");
if (ue_context_p->apn_profile.apn_configuration[i].service_selection_length > 0) {
NAS_PDN_CONNECTIVITY_RSP(message_p).apn.value = malloc(ue_context_p->apn_profile.apn_configuration[i].service_selection_length + 1);
NAS_PDN_CONNECTIVITY_RSP(message_p).apn.length = ue_context_p->apn_profile.apn_configuration[i].service_selection_length;
AssertFatal(ue_context_p->apn_profile.apn_configuration[i].service_selection_length <= APN_MAX_LENGTH,
"Bad APN string length %d",
ue_context_p->apn_profile.apn_configuration[i].service_selection_length);
memcpy(NAS_PDN_CONNECTIVITY_RSP(message_p).apn.value,
ue_context_p->apn_profile.apn_configuration[i].service_selection,
ue_context_p->apn_profile.apn_configuration[i].service_selection_length);
NAS_PDN_CONNECTIVITY_RSP(message_p).apn.value[ue_context_p->apn_profile.apn_configuration[i].service_selection_length] = '\0';
MME_APP_DEBUG("SET APN FROM HSS ULA: %s\n", NAS_PDN_CONNECTIVITY_RSP(message_p).apn.value);
break;
}
}
}
}
MME_APP_DEBUG("APN: %s\n", NAS_PDN_CONNECTIVITY_RSP(message_p).apn.value);
NAS_BEARER_PARAM(message_p).ebi = bearer_id;
switch (create_sess_resp_pP->paa.pdn_type) {
case IPv4:
NAS_PDN_CONNECTIVITY_RSP(message_p).pdn_addr.length = 4;
NAS_PDN_CONNECTIVITY_RSP(message_p).pdn_addr.value = malloc(NAS_PDN_CONNECTIVITY_RSP(message_p).pdn_addr.length+1);
DevAssert(NAS_PDN_CONNECTIVITY_RSP(message_p).pdn_addr.value != NULL);
memcpy(
NAS_PDN_CONNECTIVITY_RSP(message_p).pdn_addr.value,
create_sess_resp_pP->paa.ipv4_address,
NAS_PDN_CONNECTIVITY_RSP(message_p).pdn_addr.length);
NAS_PDN_CONNECTIVITY_RSP(message_p).pdn_addr.value[NAS_PDN_CONNECTIVITY_RSP(message_p).pdn_addr.length] = '0';
break;
case IPv6:
DevAssert(create_sess_resp_pP->paa.ipv6_prefix_length == 64); // NAS seems to only support 64 bits
NAS_PDN_CONNECTIVITY_RSP(message_p).pdn_addr.length = create_sess_resp_pP->paa.ipv6_prefix_length/8;
NAS_PDN_CONNECTIVITY_RSP(message_p).pdn_addr.value = malloc(NAS_PDN_CONNECTIVITY_RSP(message_p).pdn_addr.length+1);
DevAssert(NAS_PDN_CONNECTIVITY_RSP(message_p).pdn_addr.value != NULL);
memcpy(
NAS_PDN_CONNECTIVITY_RSP(message_p).pdn_addr.value,
create_sess_resp_pP->paa.ipv6_address,
NAS_PDN_CONNECTIVITY_RSP(message_p).pdn_addr.length);
NAS_PDN_CONNECTIVITY_RSP(message_p).pdn_addr.value[NAS_PDN_CONNECTIVITY_RSP(message_p).pdn_addr.length] = '0';
break;
case IPv4_AND_v6:
DevAssert(create_sess_resp_pP->paa.ipv6_prefix_length == 64); // NAS seems to only support 64 bits
NAS_PDN_CONNECTIVITY_RSP(message_p).pdn_addr.length = 4 + create_sess_resp_pP->paa.ipv6_prefix_length/8;
NAS_PDN_CONNECTIVITY_RSP(message_p).pdn_addr.value = malloc(NAS_PDN_CONNECTIVITY_RSP(message_p).pdn_addr.length+1);
DevAssert(NAS_PDN_CONNECTIVITY_RSP(message_p).pdn_addr.value != NULL);
memcpy(
NAS_PDN_CONNECTIVITY_RSP(message_p).pdn_addr.value,
create_sess_resp_pP->paa.ipv4_address,
4);
memcpy(
&NAS_PDN_CONNECTIVITY_RSP(message_p).pdn_addr.value[4],
create_sess_resp_pP->paa.ipv6_address,
create_sess_resp_pP->paa.ipv6_prefix_length/8);
NAS_PDN_CONNECTIVITY_RSP(message_p).pdn_addr.value[NAS_PDN_CONNECTIVITY_RSP(message_p).pdn_addr.length] = '0';
break;
case IPv4_OR_v6:
NAS_PDN_CONNECTIVITY_RSP(message_p).pdn_addr.length = 4;
NAS_PDN_CONNECTIVITY_RSP(message_p).pdn_addr.value = malloc(NAS_PDN_CONNECTIVITY_RSP(message_p).pdn_addr.length+1);
DevAssert(NAS_PDN_CONNECTIVITY_RSP(message_p).pdn_addr.value != NULL);
memcpy(
NAS_PDN_CONNECTIVITY_RSP(message_p).pdn_addr.value,
create_sess_resp_pP->paa.ipv4_address,
NAS_PDN_CONNECTIVITY_RSP(message_p).pdn_addr.length);
NAS_PDN_CONNECTIVITY_RSP(message_p).pdn_addr.value[NAS_PDN_CONNECTIVITY_RSP(message_p).pdn_addr.length] = '0';
break;
default:
DevAssert(0);
}
NAS_BEARER_PARAM(message_p).qci = current_bearer_p->qci;
NAS_BEARER_PARAM(message_p).prio_level = current_bearer_p->prio_level;
NAS_BEARER_PARAM(message_p).pre_emp_vulnerability = current_bearer_p->pre_emp_vulnerability;
NAS_BEARER_PARAM(message_p).pre_emp_capability = current_bearer_p->pre_emp_capability;
NAS_PDN_CONNECTIVITY_RSP(message_p).pdn_type = create_sess_resp_pP->paa.pdn_type;
NAS_PDN_CONNECTIVITY_RSP(message_p).proc_data = ue_context_p->pending_pdn_connectivity_req_proc_data; // NAS internal ref
ue_context_p->pending_pdn_connectivity_req_proc_data = NULL;
memcpy(&NAS_PDN_CONNECTIVITY_RSP(message_p).qos,
&ue_context_p->pending_pdn_connectivity_req_qos,
sizeof(network_qos_t));
memset(&ue_context_p->pending_pdn_connectivity_req_qos,
0,
sizeof(network_qos_t));
NAS_PDN_CONNECTIVITY_RSP(message_p).request_type = ue_context_p->pending_pdn_connectivity_req_request_type; // NAS internal ref
ue_context_p->pending_pdn_connectivity_req_request_type = 0;
NAS_BEARER_PARAM(message_p).sgw_s1u_teid = current_bearer_p->s_gw_teid;
memcpy(&NAS_BEARER_PARAM(message_p).sgw_s1u_address,
// here at this point OctetString are saved in resp, no loss of memory (apn, pdn_addr)
NAS_PDN_CONNECTIVITY_RSP(message_p).eNB_ue_s1ap_id = ue_context_p->eNB_ue_s1ap_id;
NAS_PDN_CONNECTIVITY_RSP(message_p).mme_ue_s1ap_id = ue_context_p->mme_ue_s1ap_id;
NAS_PDN_CONNECTIVITY_RSP(message_p).ebi = bearer_id;
NAS_PDN_CONNECTIVITY_RSP(message_p).qci = current_bearer_p->qci;
NAS_PDN_CONNECTIVITY_RSP(message_p).prio_level = current_bearer_p->prio_level;
NAS_PDN_CONNECTIVITY_RSP(message_p).pre_emp_vulnerability = current_bearer_p->pre_emp_vulnerability;
NAS_PDN_CONNECTIVITY_RSP(message_p).pre_emp_capability = current_bearer_p->pre_emp_capability;
NAS_PDN_CONNECTIVITY_RSP(message_p).sgw_s1u_teid = current_bearer_p->s_gw_teid;
memcpy(&NAS_PDN_CONNECTIVITY_RSP(message_p).sgw_s1u_address,
&current_bearer_p->s_gw_address, sizeof(ip_address_t));
memcpy(&NAS_BEARER_PARAM(message_p).ambr, &ue_context_p->subscribed_ambr,
memcpy(&NAS_PDN_CONNECTIVITY_RSP(message_p).ambr, &ue_context_p->subscribed_ambr,
sizeof(ambr_t));
return itti_send_msg_to_task(TASK_NAS_MME, INSTANCE_DEFAULT, message_p);
}
return 0;
}
void
mme_app_handle_initial_context_setup_rsp(
const mme_app_initial_context_setup_rsp_t * const initial_ctxt_setup_rsp_pP)
{
struct ue_context_s *ue_context_p = NULL;
MessageDef *message_p = NULL;
task_id_t to_task = TASK_UNKNOWN;
MME_APP_DEBUG("Received MME_APP_INITIAL_CONTEXT_SETUP_RSP from S1AP\n");
ue_context_p = mme_ue_context_exists_mme_ue_s1ap_id(
&mme_app_desc.mme_ue_contexts,
initial_ctxt_setup_rsp_pP->mme_ue_s1ap_id);
if (ue_context_p == NULL) {
MME_APP_DEBUG("We didn't find this mme_ue_s1ap_id in list of UE: %08x %d(dec)\n",
initial_ctxt_setup_rsp_pP->mme_ue_s1ap_id,
initial_ctxt_setup_rsp_pP->mme_ue_s1ap_id);
return;
}
#if defined(DISABLE_STANDALONE_EPC)
to_task = TASK_S11;
#else
to_task = TASK_SPGW_APP;
#endif
message_p = itti_alloc_new_message(TASK_MME_APP, SGW_MODIFY_BEARER_REQUEST);
AssertFatal(message_p != NULL, "itti_alloc_new_message Failed");
memset((void*)&message_p->ittiMsg.sgwModifyBearerRequest,
0,
sizeof(SgwModifyBearerRequest));
SGW_MODIFY_BEARER_REQUEST(message_p).teid = ue_context_p->sgw_s11_teid;
/* Delay Value in integer multiples of 50 millisecs, or zero */
SGW_MODIFY_BEARER_REQUEST(message_p).delay_dl_packet_notif_req = 0; // TO DO
SGW_MODIFY_BEARER_REQUEST(message_p).bearer_context_to_modify.eps_bearer_id = initial_ctxt_setup_rsp_pP->eps_bearer_id;
memcpy(&SGW_MODIFY_BEARER_REQUEST(message_p).bearer_context_to_modify.s1_eNB_fteid,
&initial_ctxt_setup_rsp_pP->bearer_s1u_enb_fteid,
sizeof(SGW_MODIFY_BEARER_REQUEST(message_p).bearer_context_to_modify.s1_eNB_fteid));
SGW_MODIFY_BEARER_REQUEST(message_p).mme_fq_csid.node_id_type = GLOBAL_UNICAST_IPv4; // TO DO
SGW_MODIFY_BEARER_REQUEST(message_p).mme_fq_csid.csid = 0; // TO DO ...
SGW_MODIFY_BEARER_REQUEST(message_p).indication_flags = 0; // TO DO
SGW_MODIFY_BEARER_REQUEST(message_p).rat_type = RAT_EUTRAN;
/* S11 stack specific parameter. Not used in standalone epc mode */
SGW_MODIFY_BEARER_REQUEST(message_p).trxn = NULL;
itti_send_msg_to_task(to_task, INSTANCE_DEFAULT, message_p);
}
+64
View File
@@ -0,0 +1,64 @@
/*******************************************************************************
Eurecom OpenAirInterface Core Network
Copyright(c) 1999 - 2014 Eurecom
This program is free software; you can redistribute it and/or modify it
under the terms and conditions of the GNU General Public License,
version 2, as published by the Free Software Foundation.
This program is distributed in the hope 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, write to the Free Software Foundation, Inc.,
51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
The full GNU General Public License is included in this distribution in
the file called "COPYING".
Contact Information
Openair Admin: openair_admin@eurecom.fr
Openair Tech : openair_tech@eurecom.fr
Forums : http://forums.eurecom.fsr/openairinterface
Address : EURECOM,
Campus SophiaTech,
450 Route des Chappes,
CS 50193
06904 Biot Sophia Antipolis cedex,
FRANCE
*******************************************************************************/
/*! \file mme_app_bearer.c
* \brief
* \author Lionel Gauthier
* \company Eurecom
* \email: lionel.gauthier@eurecom.fr
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "intertask_interface.h"
#include "mme_config.h"
#include "mme_app_extern.h"
#include "mme_app_ue_context.h"
#include "mme_app_defs.h"
#include "secu_defs.h"
#include "assertions.h"
#include "common_types.h"
int
mme_app_handle_s1ap_ue_capabilities_ind(
const s1ap_ue_cap_ind_t const * s1ap_ue_cap_ind_pP)
{
DevAssert(s1ap_ue_cap_ind_pP != NULL);
//unsigned eNB_ue_s1ap_id:24;
//uint32_t mme_ue_s1ap_id;
//uint8_t radio_capabilities[100];
//uint32_t radio_capabilities_length;
return 0;
}
+286
View File
@@ -0,0 +1,286 @@
/*******************************************************************************
Eurecom OpenAirInterface Core Network
Copyright(c) 1999 - 2014 Eurecom
This program is free software; you can redistribute it and/or modify it
under the terms and conditions of the GNU General Public License,
version 2, as published by the Free Software Foundation.
This program is distributed in the hope 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, write to the Free Software Foundation, Inc.,
51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
The full GNU General Public License is included in this distribution in
the file called "COPYING".
Contact Information
Openair Admin: openair_admin@eurecom.fr
Openair Tech : openair_tech@eurecom.fr
Forums : http://forums.eurecom.fsr/openairinterface
Address : EURECOM,
Campus SophiaTech,
450 Route des Chappes,
CS 50193
06904 Biot Sophia Antipolis cedex,
FRANCE
*******************************************************************************/
/*! \file mme_app_config.c
* \brief
* \author Lionel GAUTHIER
* \version 1.0
* \company Eurecom
* \email: lionel.gauthier@eurecom.fr
*/
#define MME_APP
#define MME_APP_CONFIG_C
#include <string.h>
#include <libconfig.h>
#include "mme_app_config.h"
int mme_app_config_init(char* lib_config_file_name_pP, mme_app_config_t* config_pP) {
config_t cfg;
config_setting_t *setting_sgw = NULL;
char *sgw_interface_name_for_S1u_S12_S4_up = NULL;
char *sgw_ipv4_address_for_S1u_S12_S4_up = NULL;
char *sgw_interface_name_for_S5_S8_up = NULL;
char *sgw_ipv4_address_for_S5_S8_up = NULL;
char *sgw_interface_name_for_S11 = NULL;
char *sgw_ipv4_address_for_S11 = NULL;
config_setting_t *setting_pgw = NULL;
config_setting_t *subsetting = NULL;
config_setting_t *sub2setting = NULL;
char *pgw_interface_name_for_S5_S8 = NULL;
char *pgw_ipv4_address_for_S5_S8 = NULL;
char *pgw_interface_name_for_SGI = NULL;
char *pgw_ipv4_address_for_SGI = NULL;
char *delimiters=NULL;
char *saveptr1= NULL;
char *astring = NULL;
char *atoken = NULL;
char *atoken2 = NULL;
char *address = NULL;
char *cidr = NULL;
char *mask = NULL;
int num = 0;
int i = 0;
int jh, jn;
unsigned char buf_in6_addr[sizeof(struct in6_addr)];
struct in6_addr addr6_start;
struct in6_addr addr6_mask;
int prefix_mask;
uint64_t counter64;
unsigned char buf_in_addr[sizeof(struct in_addr)];
struct in_addr addr_start;
struct in_addr addr_end;
memset((char*)config_pP, 0 , sizeof(mme_app_config_t));
config_init(&cfg);
if(lib_config_file_name_pP != NULL)
{
/* Read the file. If there is an error, report it and exit. */
if(! config_read_file(&cfg, lib_config_file_name_pP))
{
MME_APP_ERROR("%s:%d - %s\n", lib_config_file_name_pP, config_error_line(&cfg), config_error_text(&cfg));
config_destroy(&cfg);
AssertFatal (1 == 0, "Failed to parse eNB configuration file %s!\n", lib_config_file_name_pP);
}
}
else
{
SPGW_APP_ERROR("No SP-GW configuration file provided!\n");
config_destroy(&cfg);
AssertFatal (0, "No SP-GW configuration file provided!\n");
}
setting_sgw = config_lookup(&cfg, SGW_CONFIG_STRING_SGW_CONFIG);
if(setting_sgw != NULL) {
subsetting = config_setting_get_member (setting_sgw, SGW_CONFIG_STRING_NETWORK_INTERFACES_CONFIG);
if(subsetting != NULL) {
if( (
config_setting_lookup_string( subsetting, SGW_CONFIG_STRING_SGW_INTERFACE_NAME_FOR_S1U_S12_S4_UP, (const char **)&sgw_interface_name_for_S1u_S12_S4_up)
&& config_setting_lookup_string( subsetting, SGW_CONFIG_STRING_SGW_IPV4_ADDRESS_FOR_S1U_S12_S4_UP, (const char **)&sgw_ipv4_address_for_S1u_S12_S4_up)
&& config_setting_lookup_string( subsetting, SGW_CONFIG_STRING_SGW_INTERFACE_NAME_FOR_S5_S8_UP, (const char **)&sgw_interface_name_for_S5_S8_up)
&& config_setting_lookup_string( subsetting, SGW_CONFIG_STRING_SGW_IPV4_ADDRESS_FOR_S5_S8_UP, (const char **)&sgw_ipv4_address_for_S5_S8_up)
&& config_setting_lookup_string( subsetting, SGW_CONFIG_STRING_SGW_INTERFACE_NAME_FOR_S11, (const char **)&sgw_interface_name_for_S11)
&& config_setting_lookup_string( subsetting, SGW_CONFIG_STRING_SGW_IPV4_ADDRESS_FOR_S11, (const char **)&sgw_ipv4_address_for_S11)
)
) {
config_pP->sgw_config.ipv4.sgw_interface_name_for_S1u_S12_S4_up = strdup(sgw_interface_name_for_S1u_S12_S4_up);
cidr = strdup(sgw_ipv4_address_for_S1u_S12_S4_up);
address = strtok(cidr, "/");
mask = strtok(NULL, "/");
IPV4_STR_ADDR_TO_INT_NWBO ( address, config_pP->sgw_config.ipv4.sgw_ipv4_address_for_S1u_S12_S4_up, "BAD IP ADDRESS FORMAT FOR S1u_S12_S4 !\n" )
config_pP->sgw_config.ipv4.sgw_ip_netmask_for_S1u_S12_S4_up = atoi(mask);
free(cidr);
config_pP->sgw_config.ipv4.sgw_interface_name_for_S5_S8_up = strdup(sgw_interface_name_for_S5_S8_up);
cidr = strdup(sgw_ipv4_address_for_S5_S8_up);
address = strtok(cidr, "/");
mask = strtok(NULL, "/");
IPV4_STR_ADDR_TO_INT_NWBO ( address, config_pP->sgw_config.ipv4.sgw_ipv4_address_for_S5_S8_up, "BAD IP ADDRESS FORMAT FOR S5_S8 !\n" )
config_pP->sgw_config.ipv4.sgw_ip_netmask_for_S5_S8_up = atoi(mask);
free(cidr);
config_pP->sgw_config.ipv4.sgw_interface_name_for_S11 = strdup(sgw_interface_name_for_S11);
cidr = strdup(sgw_ipv4_address_for_S11);
address = strtok(cidr, "/");
mask = strtok(NULL, "/");
IPV4_STR_ADDR_TO_INT_NWBO ( address, config_pP->sgw_config.ipv4.sgw_ipv4_address_for_S11, "BAD IP ADDRESS FORMAT FOR S11 !\n" )
config_pP->sgw_config.ipv4.sgw_ip_netmask_for_S11 = atoi(mask);
free(cidr);
}
}
}
setting_pgw = config_lookup(&cfg, PGW_CONFIG_STRING_PGW_CONFIG);
if(setting_pgw != NULL)
{
subsetting = config_setting_get_member (setting_pgw, SGW_CONFIG_STRING_NETWORK_INTERFACES_CONFIG);
if(subsetting != NULL) {
if( (
config_setting_lookup_string(subsetting,
PGW_CONFIG_STRING_PGW_INTERFACE_NAME_FOR_S5_S8,
(const char **)&pgw_interface_name_for_S5_S8)
&& config_setting_lookup_string(subsetting,
PGW_CONFIG_STRING_PGW_IPV4_ADDRESS_FOR_S5_S8,
(const char **)&pgw_ipv4_address_for_S5_S8)
&& config_setting_lookup_string(subsetting,
PGW_CONFIG_STRING_PGW_INTERFACE_NAME_FOR_SGI,
(const char **)&pgw_interface_name_for_SGI)
&& config_setting_lookup_string(subsetting,
PGW_CONFIG_STRING_PGW_IPV4_ADDR_FOR_SGI,
(const char **)&pgw_ipv4_address_for_SGI)
)
) {
config_pP->pgw_config.ipv4.pgw_interface_name_for_S5_S8 = strdup(pgw_interface_name_for_S5_S8);
cidr = strdup(pgw_ipv4_address_for_S5_S8);
address = strtok(cidr, "/");
mask = strtok(NULL, "/");
IPV4_STR_ADDR_TO_INT_NWBO ( address, config_pP->pgw_config.ipv4.pgw_ipv4_address_for_S5_S8, "BAD IP ADDRESS FORMAT FOR S5_S8 !\n" )
config_pP->pgw_config.ipv4.pgw_ip_netmask_for_S5_S8 = atoi(mask);
free(cidr);
config_pP->pgw_config.ipv4.pgw_interface_name_for_SGI = strdup(pgw_interface_name_for_SGI);
cidr = strdup(pgw_ipv4_address_for_SGI);
address = strtok(cidr, "/");
mask = strtok(NULL, "/");
IPV4_STR_ADDR_TO_INT_NWBO ( address, config_pP->pgw_config.ipv4.pgw_ipv4_address_for_SGI, "BAD IP ADDRESS FORMAT FOR SGI !\n" )
config_pP->pgw_config.ipv4.pgw_ip_netmask_for_SGI = atoi(mask);
free(cidr);
}
}
subsetting = config_setting_get_member (setting_pgw, PGW_CONFIG_STRING_IP_ADDRESS_POOL);
if(subsetting != NULL) {
sub2setting = config_setting_get_member (subsetting, PGW_CONFIG_STRING_IPV4_ADDRESS_LIST);
if(sub2setting != NULL) {
num = config_setting_length(sub2setting);
for (i = 0; i < num; i++) {
astring = config_setting_get_string_elem(sub2setting,i);
if (astring != NULL) {
trim(astring, strlen(astring)+1);
if (inet_pton(AF_INET, astring, buf_in_addr) < 1) {
// failure, test if there is a range specified in the string
atoken = strtok(astring, PGW_CONFIG_STRING_IP_ADDRESS_RANGE_DELIMITERS);
if (inet_pton(AF_INET, astring, buf_in_addr) == 1) {
memcpy (&addr_start, buf_in_addr, sizeof(struct in_addr));
// valid address
atoken2 = strtok(NULL, PGW_CONFIG_STRING_IP_ADDRESS_RANGE_DELIMITERS);
if (inet_pton(AF_INET, atoken2, buf_in_addr) == 1) {
memcpy (&addr_end, buf_in_addr, sizeof(struct in_addr));
// valid address
for (jh = ntohl(addr_start.s_addr); jh <= ntohl(addr_end.s_addr); jh++) {
DevAssert(PGW_MAX_ALLOCATED_PDN_ADDRESSES > config_pP->pgw_config.pool_pdn_addresses.num_ipv4_addresses);
jn = htonl(jh);
if (IN_CLASSA(addr_start.s_addr)) {
if ((jh & 0xFF) && (jh & 0xFF) != 0xFF) {
config_pP->pgw_config.pool_pdn_addresses.ipv4_addresses[config_pP->pgw_config.pool_pdn_addresses.num_ipv4_addresses++].s_addr = jn;
}
} else if (IN_CLASSB(addr_start.s_addr)) {
if ((jh & 0xFF) && (jh & 0xFF) != 0xFF) {
config_pP->pgw_config.pool_pdn_addresses.ipv4_addresses[config_pP->pgw_config.pool_pdn_addresses.num_ipv4_addresses++].s_addr = jn;
}
} else if (IN_CLASSC(addr_start.s_addr)) {
if ((jh & 0xFF) && (jh & 0xFF) != 0xFF) {
config_pP->pgw_config.pool_pdn_addresses.ipv4_addresses[config_pP->pgw_config.pool_pdn_addresses.num_ipv4_addresses++].s_addr = jn;
}
} else {
printf("ERROR ON ADDRESS CLASS %d.%d.%d.%d\n", NIPADDR(jn));
}
}
}
}
} else {
DevAssert(PGW_MAX_ALLOCATED_PDN_ADDRESSES > config_pP->pgw_config.pool_pdn_addresses.num_ipv4_addresses);
memcpy (&addr_start, buf_in_addr, sizeof(struct in_addr));
config_pP->pgw_config.pool_pdn_addresses.ipv4_addresses[config_pP->pgw_config.pool_pdn_addresses.num_ipv4_addresses++].s_addr = addr_start.s_addr;
}
}
}
}
sub2setting = config_setting_get_member (subsetting, PGW_CONFIG_STRING_IPV6_ADDRESS_LIST);
if(sub2setting != NULL) {
num = config_setting_length(sub2setting);
for (i = 0; i < num; i++) {
astring = config_setting_get_string_elem(sub2setting,i);
if (astring != NULL) {
trim(astring, strlen(astring)+1);
if (inet_pton(AF_INET6, astring, buf_in6_addr) < 1) {
// failure, test if there is a range specified in the string
atoken = strtok(astring, PGW_CONFIG_STRING_IPV6_PREFIX_DELIMITER);
if (inet_pton(AF_INET6, astring, buf_in6_addr) == 1) {
atoken2 = strtok(NULL, PGW_CONFIG_STRING_IPV6_PREFIX_DELIMITER);
prefix_mask = atoi(atoken2);
// arbitrary values
DevAssert((prefix_mask < 128) && (prefix_mask >= 64));
memcpy (&addr6_start, buf_in6_addr, sizeof(struct in6_addr));
memcpy (&addr6_mask, buf_in6_addr, sizeof(struct in6_addr));
sgw_ipv6_mask_in6_addr(&addr6_mask, prefix_mask);
if (memcmp(&addr6_start, &addr6_mask, sizeof(struct in6_addr)) != 0) {
AssertFatal(0, "BAD IPV6 ADDR CONFIG/MASK PAIRING %s/%d\n", astring, prefix_mask);
}
counter64 = 0xFFFFFFFFFFFFFFFF >> prefix_mask; // address Prefix_mask/0..0 not valid
do {
addr6_start.s6_addr32[3] = addr6_start.s6_addr32[3] + htonl(1);
if (addr6_start.s6_addr32[3] == 0) {
addr6_start.s6_addr32[2] = addr6_start.s6_addr32[2] + htonl(1);
if (addr6_start.s6_addr32[2] == 0) {
// should not happen since mask is no less than 64
addr6_start.s6_addr32[1] = addr6_start.s6_addr32[1] + htonl(1);
if (addr6_start.s6_addr32[1] == 0) {
addr6_start.s6_addr32[0] = addr6_start.s6_addr32[0] + htonl(1);
}
}
}
memcpy (&config_pP->pgw_config.pool_pdn_addresses.ipv6_addresses[config_pP->pgw_config.pool_pdn_addresses.num_ipv6_addresses++],
&addr6_start,
sizeof(struct in6_addr));
counter64 = counter64 - 1;
} while (counter64 > 0);
}
} else {
DevAssert(PGW_MAX_ALLOCATED_PDN_ADDRESSES > config_pP->pgw_config.pool_pdn_addresses.num_ipv6_addresses);
memcpy (&config_pP->pgw_config.pool_pdn_addresses.ipv6_addresses[config_pP->pgw_config.pool_pdn_addresses.num_ipv6_addresses++],
buf_in6_addr,
sizeof(struct in6_addr));
}
}
}
} }
}
return 0;
}
+43
View File
@@ -0,0 +1,43 @@
/*******************************************************************************
Eurecom OpenAirInterface Core Network
Copyright(c) 1999 - 2014 Eurecom
This program is free software; you can redistribute it and/or modify it
under the terms and conditions of the GNU General Public License,
version 2, as published by the Free Software Foundation.
This program is distributed in the hope 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, write to the Free Software Foundation, Inc.,
51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
The full GNU General Public License is included in this distribution in
the file called "COPYING".
Contact Information
Openair Admin: openair_admin@eurecom.fr
Openair Tech : openair_tech@eurecom.fr
Forums : http://forums.eurecom.fsr/openairinterface
Address : EURECOM,
Campus SophiaTech,
450 Route des Chappes,
CS 50193
06904 Biot Sophia Antipolis cedex,
FRANCE
*******************************************************************************/
/*! \file mme_app_config.h
* \brief
* \author Lionel GAUTHIER
* \version 1.0
* \company Eurecom
* \email: lionel.gauthier@eurecom.fr
*/
#ifndef MME_APP_CONFIG_H_
#define MME_APP_CONFIG_H_
#endif /* MME_APP_CONFIG_H_ */
+78 -24
View File
@@ -1,31 +1,33 @@
/*******************************************************************************
Eurecom OpenAirInterface Core Network
Copyright(c) 1999 - 2014 Eurecom
Eurecom OpenAirInterface
Copyright(c) 1999 - 2013 Eurecom
This program is free software; you can redistribute it and/or modify it
under the terms and conditions of the GNU General Public License,
version 2, as published by the Free Software Foundation.
This program is free software; you can redistribute it and/or modify it
under the terms and conditions of the GNU General Public License,
version 2, as published by the Free Software Foundation.
This program is distributed in the hope 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.
This program is distributed in the hope 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, write to the Free Software Foundation, Inc.,
51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
The full GNU General Public License is included in this distribution in
the file called "COPYING".
Contact Information
Openair Admin: openair_admin@eurecom.fr
Openair Tech : openair_tech@eurecom.fr
Forums : http://forums.eurecom.fr/openairinterface
Address : EURECOM, Campus SophiaTech, 450 Route des Chappes
06410 Biot FRANCE
The full GNU General Public License is included in this distribution in
the file called "COPYING".
Contact Information
Openair Admin: openair_admin@eurecom.fr
Openair Tech : openair_tech@eurecom.fr
Forums : http://forums.eurecom.fsr/openairinterface
Address : EURECOM,
Campus SophiaTech,
450 Route des Chappes,
CS 50193
06904 Biot Sophia Antipolis cedex,
FRANCE
*******************************************************************************/
#include <pthread.h>
@@ -62,6 +64,11 @@ RB_GENERATE(ue_context_map, ue_context_s, rb_entry,
static inline int ue_context_compare_identifiers(
struct ue_context_s *p1, struct ue_context_s *p2)
{
MME_APP_DEBUG(" ue_context_compare_identifiers IMSI %"SCNu64"\n", p1->imsi);
MME_APP_DEBUG(" ue_context_compare_identifiers mme_s11_teid %08x\n" , p1->mme_s11_teid);
MME_APP_DEBUG(" ue_context_compare_identifiers mme_ue_s1ap_id %08x\n" , p1->mme_ue_s1ap_id);
MME_APP_DEBUG(" ue_context_compare_identifiers ue_id %08x\n" , p1->ue_id);
if (p1->imsi > 0) {
/* if IMSI provided */
if (p1->imsi > p2->imsi) {
@@ -78,6 +85,23 @@ static inline int ue_context_compare_identifiers(
if (p1->mme_s11_teid < p2->mme_s11_teid) {
return -1;
}
} else if (p1->mme_ue_s1ap_id > 0) {
MME_APP_DEBUG(" with mme_ue_s1ap_id %d\n" , p2->mme_ue_s1ap_id);
/* if s1ap ue id provided */
if (p1->mme_ue_s1ap_id > p2->mme_ue_s1ap_id) {
return 1;
}
if (p1->mme_ue_s1ap_id < p2->mme_ue_s1ap_id) {
return -1;
}
} else if (p1->ue_id > 0) {
/* if nas ue_id provided */
if (p1->ue_id > p2->ue_id) {
return 1;
}
if (p1->ue_id < p2->ue_id) {
return -1;
}
} else {
uint16_t mcc1;
uint16_t mnc1;
@@ -144,14 +168,44 @@ struct ue_context_s *mme_ue_context_exists_s11_teid(mme_ue_context_t *mme_ue_con
DevAssert(mme_ue_context != NULL);
memset(&reference, 0, sizeof(struct ue_context_s));
reference.imsi = 0;
reference.mme_s11_teid = teid;
return RB_FIND(ue_context_map, &mme_ue_context->ue_context_tree,
&reference);
}
inline
struct ue_context_s *mme_ue_context_exists_guti(mme_ue_context_t *mme_ue_context,
ue_context_t *mme_ue_context_exists_mme_ue_s1ap_id(
mme_ue_context_t *mme_ue_context,
uint32_t mme_ue_s1ap_id)
{
struct ue_context_s reference;
DevAssert(mme_ue_context != NULL);
memset(&reference, 0, sizeof(struct ue_context_s));
reference.mme_ue_s1ap_id = mme_ue_s1ap_id;
return RB_FIND(ue_context_map, &mme_ue_context->ue_context_tree,
&reference);
}
inline
ue_context_t *mme_ue_context_exists_nas_ue_id(
mme_ue_context_t *mme_ue_context,
uint32_t nas_ue_id)
{
struct ue_context_s reference;
DevAssert(mme_ue_context != NULL);
memset(&reference, 0, sizeof(struct ue_context_s));
reference.ue_id = nas_ue_id;
return RB_FIND(ue_context_map, &mme_ue_context->ue_context_tree,
&reference);
}
inline
ue_context_t *mme_ue_context_exists_guti(mme_ue_context_t *mme_ue_context,
GUTI_t guti)
{
struct ue_context_s reference;
+46 -29
View File
@@ -1,31 +1,33 @@
/*******************************************************************************
Eurecom OpenAirInterface Core Network
Copyright(c) 1999 - 2014 Eurecom
Eurecom OpenAirInterface
Copyright(c) 1999 - 2013 Eurecom
This program is free software; you can redistribute it and/or modify it
under the terms and conditions of the GNU General Public License,
version 2, as published by the Free Software Foundation.
This program is free software; you can redistribute it and/or modify it
under the terms and conditions of the GNU General Public License,
version 2, as published by the Free Software Foundation.
This program is distributed in the hope 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.
This program is distributed in the hope 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, write to the Free Software Foundation, Inc.,
51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
The full GNU General Public License is included in this distribution in
the file called "COPYING".
Contact Information
Openair Admin: openair_admin@eurecom.fr
Openair Tech : openair_tech@eurecom.fr
Forums : http://forums.eurecom.fr/openairinterface
Address : EURECOM, Campus SophiaTech, 450 Route des Chappes
06410 Biot FRANCE
The full GNU General Public License is included in this distribution in
the file called "COPYING".
Contact Information
Openair Admin: openair_admin@eurecom.fr
Openair Tech : openair_tech@eurecom.fr
Forums : http://forums.eurecom.fsr/openairinterface
Address : EURECOM,
Campus SophiaTech,
450 Route des Chappes,
CS 50193
06904 Biot Sophia Antipolis cedex,
FRANCE
*******************************************************************************/
/* This file contains definitions related to mme applicative layer and should
@@ -56,22 +58,37 @@ typedef struct {
extern mme_app_desc_t mme_app_desc;
int mme_app_create_bearer(s6a_update_location_ans_t *ula_p);
#if defined(DISABLE_USE_NAS)
int mme_app_handle_attach_req(nas_attach_req_t *attach_req_p);
#endif
int mme_app_handle_create_sess_resp(SgwCreateSessionResponse *create_sess_resp_p);
int mme_app_handle_s1ap_ue_capabilities_ind (const s1ap_ue_cap_ind_t const * s1ap_ue_cap_ind_pP);
int mme_app_handle_establish_ind(nas_establish_ind_t *nas_establish_ind_p);
int mme_app_send_s11_create_session_req (struct ue_context_s * const ue_context_pP);
int mme_app_handle_authentication_info_answer(s6a_auth_info_ans_t *s6a_auth_info_ans_p);
int mme_app_send_s6a_update_location_req (struct ue_context_s * const ue_context_pP);
int mme_app_handle_nas_auth_resp(nas_auth_resp_t *nas_auth_resp_p);
int mme_app_handle_s6a_update_location_ans (const s6a_update_location_ans_t * const ula_pP);
nas_cause_t s6a_error_2_nas_cause(uint32_t s6a_error, int experimental);
int mme_app_handle_nas_pdn_connectivity_req ( nas_pdn_connectivity_req_t * const nas_pdn_connectivity_req_p);
void mme_app_handle_nas_auth_param_req(nas_auth_param_req_t *nas_auth_param_req);
void mme_app_handle_conn_est_cnf (const nas_conn_est_cnf_t * const nas_conn_est_cnf_pP);
void mme_app_handle_conn_est_ind (const mme_app_connection_establishment_ind_t * const conn_est_ind_pP);
int mme_app_handle_create_sess_resp (const SgwCreateSessionResponse * const create_sess_resp_pP);
int mme_app_handle_establish_ind (const nas_establish_ind_t * const nas_establish_ind_pP);
int mme_app_handle_authentication_info_answer(const s6a_auth_info_ans_t * const s6a_auth_info_ans_pP);
int mme_app_handle_nas_auth_resp (const nas_auth_resp_t * const nas_auth_resp_pP);
nas_cause_t s6a_error_2_nas_cause (const uint32_t s6a_errorP, const int experimentalP);
void mme_app_handle_nas_auth_param_req (const nas_auth_param_req_t * const nas_auth_param_req_pP);
void mme_app_handle_initial_context_setup_rsp(const mme_app_initial_context_setup_rsp_t * const initial_ctxt_setup_rsp_pP);
#endif /* MME_APP_DEFS_H_ */
+24 -22
View File
@@ -1,31 +1,33 @@
/*******************************************************************************
Eurecom OpenAirInterface Core Network
Copyright(c) 1999 - 2014 Eurecom
Eurecom OpenAirInterface
Copyright(c) 1999 - 2013 Eurecom
This program is free software; you can redistribute it and/or modify it
under the terms and conditions of the GNU General Public License,
version 2, as published by the Free Software Foundation.
This program is free software; you can redistribute it and/or modify it
under the terms and conditions of the GNU General Public License,
version 2, as published by the Free Software Foundation.
This program is distributed in the hope 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.
This program is distributed in the hope 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, write to the Free Software Foundation, Inc.,
51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
The full GNU General Public License is included in this distribution in
the file called "COPYING".
Contact Information
Openair Admin: openair_admin@eurecom.fr
Openair Tech : openair_tech@eurecom.fr
Forums : http://forums.eurecom.fr/openairinterface
Address : EURECOM, Campus SophiaTech, 450 Route des Chappes
06410 Biot FRANCE
The full GNU General Public License is included in this distribution in
the file called "COPYING".
Contact Information
Openair Admin: openair_admin@eurecom.fr
Openair Tech : openair_tech@eurecom.fr
Forums : http://forums.eurecom.fsr/openairinterface
Address : EURECOM,
Campus SophiaTech,
450 Route des Chappes,
CS 50193
06904 Biot Sophia Antipolis cedex,
FRANCE
*******************************************************************************/
#ifndef MME_APP_EXTERN_H_
+34 -25
View File
@@ -1,37 +1,42 @@
/*******************************************************************************
Eurecom OpenAirInterface Core Network
Copyright(c) 1999 - 2014 Eurecom
Eurecom OpenAirInterface
Copyright(c) 1999 - 2013 Eurecom
This program is free software; you can redistribute it and/or modify it
under the terms and conditions of the GNU General Public License,
version 2, as published by the Free Software Foundation.
This program is free software; you can redistribute it and/or modify it
under the terms and conditions of the GNU General Public License,
version 2, as published by the Free Software Foundation.
This program is distributed in the hope 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.
This program is distributed in the hope 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, write to the Free Software Foundation, Inc.,
51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
The full GNU General Public License is included in this distribution in
the file called "COPYING".
Contact Information
Openair Admin: openair_admin@eurecom.fr
Openair Tech : openair_tech@eurecom.fr
Forums : http://forums.eurecom.fr/openairinterface
Address : EURECOM, Campus SophiaTech, 450 Route des Chappes
06410 Biot FRANCE
The full GNU General Public License is included in this distribution in
the file called "COPYING".
Contact Information
Openair Admin: openair_admin@eurecom.fr
Openair Tech : openair_tech@eurecom.fr
Forums : http://forums.eurecom.fsr/openairinterface
Address : EURECOM,
Campus SophiaTech,
450 Route des Chappes,
CS 50193
06904 Biot Sophia Antipolis cedex,
FRANCE
*******************************************************************************/
#ifndef MME_APP_ITTI_MESSAGING_H_
#define MME_APP_ITTI_MESSAGING_H_
static inline void mme_app_itti_auth_fail(uint32_t ue_id, nas_cause_t cause)
static inline void
mme_app_itti_auth_fail(
const uint32_t ue_id,
const nas_cause_t cause)
{
MessageDef *message_p;
@@ -43,8 +48,12 @@ static inline void mme_app_itti_auth_fail(uint32_t ue_id, nas_cause_t cause)
itti_send_msg_to_task(TASK_NAS_MME, INSTANCE_DEFAULT, message_p);
}
static inline void mme_app_itti_auth_rsp(uint32_t ue_id, uint8_t nb_vectors,
eutran_vector_t *vector)
static inline void mme_app_itti_auth_rsp(
const uint32_t ue_id,
const uint8_t nb_vectors,
const eutran_vector_t * const vector)
{
MessageDef *message_p;
+156
View File
@@ -0,0 +1,156 @@
/*******************************************************************************
Eurecom OpenAirInterface Core Network
Copyright(c) 1999 - 2014 Eurecom
This program is free software; you can redistribute it and/or modify it
under the terms and conditions of the GNU General Public License,
version 2, as published by the Free Software Foundation.
This program is distributed in the hope 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, write to the Free Software Foundation, Inc.,
51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
The full GNU General Public License is included in this distribution in
the file called "COPYING".
Contact Information
Openair Admin: openair_admin@eurecom.fr
Openair Tech : openair_tech@eurecom.fr
Forums : http://forums.eurecom.fsr/openairinterface
Address : EURECOM,
Campus SophiaTech,
450 Route des Chappes,
CS 50193
06904 Biot Sophia Antipolis cedex,
FRANCE
*******************************************************************************/
/*! \file mme_app_location.c
* \brief
* \author Sebastien ROUX, Lionel GAUTHIER
* \version 1.0
* \company Eurecom
* \email: lionel.gauthier@eurecom.fr
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "intertask_interface.h"
#include "mme_config.h"
#include "mme_app_extern.h"
#include "mme_app_ue_context.h"
#include "mme_app_defs.h"
#include "secu_defs.h"
#include "assertions.h"
#include "common_types.h"
int
mme_app_send_s6a_update_location_req(
struct ue_context_s * const ue_context_pP)
{
struct ue_context_s *ue_context_p = NULL;
uint64_t imsi = 0;
MessageDef *message_p = NULL;
s6a_update_location_req_t *s6a_ulr_p = NULL;
MME_APP_STRING_TO_IMSI((char *)ue_context_pP->pending_pdn_connectivity_req_imsi, &imsi);
MME_APP_DEBUG("Handling imsi %"IMSI_FORMAT"\n", imsi);
if ((ue_context_p = mme_ue_context_exists_imsi(&mme_app_desc.mme_ue_contexts,
imsi)) == NULL) {
MME_APP_ERROR("That's embarrassing as we don't know this IMSI\n");
return -1;
}
message_p = itti_alloc_new_message(TASK_MME_APP, S6A_UPDATE_LOCATION_REQ);
if (message_p == NULL) {
return -1;
}
s6a_ulr_p = &message_p->ittiMsg.s6a_update_location_req;
memset((void*)s6a_ulr_p, 0, sizeof(s6a_update_location_req_t));
MME_APP_IMSI_TO_STRING(imsi, s6a_ulr_p->imsi);
s6a_ulr_p->imsi_length = strlen(s6a_ulr_p->imsi);
s6a_ulr_p->initial_attach = INITIAL_ATTACH;
memcpy(&s6a_ulr_p->visited_plmn, &ue_context_p->guti.gummei.plmn, sizeof(plmn_t));
s6a_ulr_p->rat_type = RAT_EUTRAN;
/* Check if we already have UE data */
s6a_ulr_p->skip_subscriber_data = 0;
return itti_send_msg_to_task(TASK_S6A, INSTANCE_DEFAULT, message_p);
}
int
mme_app_handle_s6a_update_location_ans(
const s6a_update_location_ans_t * const ula_pP)
{
uint64_t imsi = 0;
struct ue_context_s *ue_context_p = NULL;
DevAssert(ula_pP != NULL);
if (ula_pP->result.present == S6A_RESULT_BASE) {
if (ula_pP->result.choice.base != DIAMETER_SUCCESS) {
/* The update location procedure has failed. Notify the NAS layer
* and don't initiate the bearer creation on S-GW side.
*/
DevMessage("ULR/ULA procedure returned non success\n");
}
} else {
/* The update location procedure has failed. Notify the NAS layer
* and don't initiate the bearer creation on S-GW side.
*/
DevMessage("ULR/ULA procedure returned non success\n");
}
MME_APP_STRING_TO_IMSI((char *)ula_pP->imsi, &imsi);
MME_APP_DEBUG("%s Handling imsi %"IMSI_FORMAT"\n", __FUNCTION__, imsi);
if ((ue_context_p = mme_ue_context_exists_imsi(&mme_app_desc.mme_ue_contexts, imsi)) == NULL) {
MME_APP_ERROR("That's embarrassing as we don't know this IMSI\n");
return -1;
}
ue_context_p->subscription_known = SUBSCRIPTION_KNOWN;
ue_context_p->sub_status = ula_pP->subscription_data.subscriber_status;
ue_context_p->access_restriction_data = ula_pP->subscription_data.access_restriction;
/* Copy the subscribed ambr to the sgw create session request message */
memcpy(&ue_context_p->subscribed_ambr, &ula_pP->subscription_data.subscribed_ambr,
sizeof(ambr_t));
memcpy(
ue_context_p->msisdn,
ula_pP->subscription_data.msisdn,
ula_pP->subscription_data.msisdn_length);
ue_context_p->msisdn_length = ula_pP->subscription_data.msisdn_length;
AssertFatal(ula_pP->subscription_data.msisdn_length != 0, "MSISDN LENGTH IS 0");
AssertFatal(ula_pP->subscription_data.msisdn_length <= MSISDN_LENGTH, "MSISDN LENGTH is too high %u", MSISDN_LENGTH);
ue_context_p->msisdn[ue_context_p->msisdn_length] = '\0';
ue_context_p->rau_tau_timer = ula_pP->subscription_data.rau_tau_timer;
ue_context_p->access_mode = ula_pP->subscription_data.access_mode;
memcpy(&ue_context_p->apn_profile, &ula_pP->subscription_data.apn_config_profile,
sizeof(apn_config_profile_t));
return mme_app_send_s11_create_session_req(ue_context_p);
}
+49 -24
View File
@@ -1,31 +1,33 @@
/*******************************************************************************
Eurecom OpenAirInterface Core Network
Copyright(c) 1999 - 2014 Eurecom
Eurecom OpenAirInterface
Copyright(c) 1999 - 2013 Eurecom
This program is free software; you can redistribute it and/or modify it
under the terms and conditions of the GNU General Public License,
version 2, as published by the Free Software Foundation.
This program is free software; you can redistribute it and/or modify it
under the terms and conditions of the GNU General Public License,
version 2, as published by the Free Software Foundation.
This program is distributed in the hope 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.
This program is distributed in the hope 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, write to the Free Software Foundation, Inc.,
51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
The full GNU General Public License is included in this distribution in
the file called "COPYING".
Contact Information
Openair Admin: openair_admin@eurecom.fr
Openair Tech : openair_tech@eurecom.fr
Forums : http://forums.eurecom.fr/openairinterface
Address : EURECOM, Campus SophiaTech, 450 Route des Chappes
06410 Biot FRANCE
The full GNU General Public License is included in this distribution in
the file called "COPYING".
Contact Information
Openair Admin: openair_admin@eurecom.fr
Openair Tech : openair_tech@eurecom.fr
Forums : http://forums.eurecom.fsr/openairinterface
Address : EURECOM,
Campus SophiaTech,
450 Route des Chappes,
CS 50193
06904 Biot Sophia Antipolis cedex,
FRANCE
*******************************************************************************/
#include <stdio.h>
@@ -71,13 +73,18 @@ void *mme_app_thread(void *args)
case S6A_UPDATE_LOCATION_ANS: {
/* We received the update location answer message from HSS -> Handle it */
mme_app_create_bearer(&received_message_p->ittiMsg.s6a_update_location_ans);
mme_app_handle_s6a_update_location_ans(&received_message_p->ittiMsg.s6a_update_location_ans);
} break;
case SGW_CREATE_SESSION_RESPONSE: {
mme_app_handle_create_sess_resp(&received_message_p->ittiMsg.sgwCreateSessionResponse);
} break;
case SGW_MODIFY_BEARER_RESPONSE: {
MME_APP_DEBUG(" TO DO HANDLE SGW_MODIFY_BEARER_RESPONSE");
// TO DO
} break;
#if defined(DISABLE_USE_NAS)
case NAS_ATTACH_REQ: {
mme_app_handle_attach_req(&received_message_p->ittiMsg.nas_attach_req);
@@ -91,6 +98,24 @@ void *mme_app_thread(void *args)
mme_app_handle_nas_auth_param_req(&received_message_p->ittiMsg.nas_auth_param_req);
} break;
#endif
case NAS_PDN_CONNECTIVITY_REQ: {
mme_app_handle_nas_pdn_connectivity_req(&received_message_p->ittiMsg.nas_pdn_connectivity_req);
} break;
//case NAS_CONNECTION_ESTABLISHMENT_CNF: {
case NAS_CONNECTION_ESTABLISHMENT_CNF: {
mme_app_handle_conn_est_cnf(&NAS_CONNECTION_ESTABLISHMENT_CNF(received_message_p));
} break;
case MME_APP_CONNECTION_ESTABLISHMENT_IND: {
mme_app_handle_conn_est_ind(&MME_APP_CONNECTION_ESTABLISHMENT_IND(received_message_p));
} break;
case MME_APP_INITIAL_CONTEXT_SETUP_RSP: {
mme_app_handle_initial_context_setup_rsp(&MME_APP_INITIAL_CONTEXT_SETUP_RSP(received_message_p));
} break;
case TIMER_HAS_EXPIRED: {
/* Check if it is the statistic timer */
if (received_message_p->ittiMsg.timer_has_expired.timer_id ==
@@ -105,7 +130,7 @@ void *mme_app_thread(void *args)
} break;
case S1AP_UE_CAPABILITIES_IND: {
// TO DO;
mme_app_handle_s1ap_ue_capabilities_ind(&received_message_p->ittiMsg.s1ap_ue_cap_ind);
} break;
default: {
+33 -1
View File
@@ -1,3 +1,34 @@
/*******************************************************************************
Eurecom OpenAirInterface Core Network
Copyright(c) 1999 - 2014 Eurecom
This program is free software; you can redistribute it and/or modify it
under the terms and conditions of the GNU General Public License,
version 2, as published by the Free Software Foundation.
This program is distributed in the hope 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, write to the Free Software Foundation, Inc.,
51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
The full GNU General Public License is included in this distribution in
the file called "COPYING".
Contact Information
Openair Admin: openair_admin@eurecom.fr
Openair Tech : openair_tech@eurecom.fr
Forums : http://forums.eurecom.fsr/openairinterface
Address : EURECOM,
Campus SophiaTech,
450 Route des Chappes,
CS 50193
06904 Biot Sophia Antipolis cedex,
FRANCE
*******************************************************************************/
#include <stdlib.h>
#include <stdio.h>
@@ -7,7 +38,8 @@
#include "mme_app_defs.h"
#include "mme_app_statistics.h"
int mme_app_statistics_display(void)
int
mme_app_statistics_display(void)
{
fprintf(stdout, "================== Statistics ==================\n");
fprintf(stdout, " | Global | Since last display |\n");
+31
View File
@@ -1,3 +1,34 @@
/*******************************************************************************
Eurecom OpenAirInterface Core Network
Copyright(c) 1999 - 2014 Eurecom
This program is free software; you can redistribute it and/or modify it
under the terms and conditions of the GNU General Public License,
version 2, as published by the Free Software Foundation.
This program is distributed in the hope 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, write to the Free Software Foundation, Inc.,
51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
The full GNU General Public License is included in this distribution in
the file called "COPYING".
Contact Information
Openair Admin: openair_admin@eurecom.fr
Openair Tech : openair_tech@eurecom.fr
Forums : http://forums.eurecom.fsr/openairinterface
Address : EURECOM,
Campus SophiaTech,
450 Route des Chappes,
CS 50193
06904 Biot Sophia Antipolis cedex,
FRANCE
*******************************************************************************/
#ifndef MME_APP_STATISTICS_H_
#define MME_APP_STATISTICS_H_
+89 -58
View File
@@ -1,31 +1,33 @@
/*******************************************************************************
Eurecom OpenAirInterface Core Network
Copyright(c) 1999 - 2014 Eurecom
Eurecom OpenAirInterface
Copyright(c) 1999 - 2013 Eurecom
This program is free software; you can redistribute it and/or modify it
under the terms and conditions of the GNU General Public License,
version 2, as published by the Free Software Foundation.
This program is free software; you can redistribute it and/or modify it
under the terms and conditions of the GNU General Public License,
version 2, as published by the Free Software Foundation.
This program is distributed in the hope 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.
This program is distributed in the hope 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, write to the Free Software Foundation, Inc.,
51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
The full GNU General Public License is included in this distribution in
the file called "COPYING".
Contact Information
Openair Admin: openair_admin@eurecom.fr
Openair Tech : openair_tech@eurecom.fr
Forums : http://forums.eurecom.fr/openairinterface
Address : EURECOM, Campus SophiaTech, 450 Route des Chappes
06410 Biot FRANCE
The full GNU General Public License is included in this distribution in
the file called "COPYING".
Contact Information
Openair Admin: openair_admin@eurecom.fr
Openair Tech : openair_tech@eurecom.fr
Forums : http://forums.eurecom.fsr/openairinterface
Address : EURECOM,
Campus SophiaTech,
450 Route des Chappes,
CS 50193
06904 Biot Sophia Antipolis cedex,
FRANCE
*******************************************************************************/
/*! \file mme_app_ue_context.h
@@ -42,6 +44,8 @@
#include <inttypes.h> /* For sscanf formats */
#include <time.h> /* to provide time_t */
#include "nas_messages_types.h"
#include "s6a_messages_types.h"
#include "security_types.h"
#include "tree.h"
@@ -67,13 +71,13 @@ typedef uint64_t mme_app_imsi_t;
*/
typedef struct bearer_context_s {
/* S-GW Tunnel Endpoint for User-Plane */
uint32_t s_gw_teid;
Teid_t s_gw_teid;
/* S-GW IP address for User-Plane */
ip_address_t s_gw_address;
/* P-GW Tunnel Endpoint for User-Plane */
uint32_t p_gw_teid;
Teid_t p_gw_teid;
/* P-GW IP address for User-Plane */
ip_address_t p_gw_address;
@@ -98,47 +102,48 @@ typedef struct ue_context_s {
/* Basic identifier for ue. IMSI is encoded on maximum of 15 digits of 4 bits,
* so usage of an unsigned integer on 64 bits is necessary.
*/
mme_app_imsi_t imsi;
mme_app_imsi_t imsi; // set by nas_auth_param_req_t
#define IMSI_UNAUTHENTICATED (0x0)
#define IMSI_AUTHENTICATED (0x1)
/* Indicator to show the IMSI authentication state */
unsigned imsi_auth:1;
unsigned imsi_auth:1; // set by nas_auth_resp_t
unsigned eNB_ue_s1ap_id:24;
uint32_t mme_ue_s1ap_id;
unsigned eNB_ue_s1ap_id:24;
uint32_t mme_ue_s1ap_id;
/* ue_id is equal to mme_ue_s1ap_id */
uint32_t ue_id;
uint8_t nb_of_vectors;
uint32_t ue_id; // set by nas_auth_param_req_t
uint8_t nb_of_vectors; // updated by S6A AUTHENTICATION ANSWER
/* List of authentication vectors for E-UTRAN */
eutran_vector_t *vector_list;
eutran_vector_t *vector_in_use;
eutran_vector_t *vector_list; // updated by S6A AUTHENTICATION ANSWER
// pointer in vector_list
eutran_vector_t *vector_in_use; // updated by S6A AUTHENTICATION ANSWER
#define SUBSCRIPTION_UNKNOWN 0x0
#define SUBSCRIPTION_KNOWN 0x1
unsigned subscription_known:1;
unsigned subscription_known:1; // set by S6A UPDATE LOCATION ANSWER
uint8_t msisdn[MSISDN_LENGTH+1]; // set by S6A UPDATE LOCATION ANSWER
uint8_t msisdn_length; // set by S6A UPDATE LOCATION ANSWER
uint8_t msisdn[MSISDN_LENGTH+1];
uint8_t msisdn_length;
mm_state_t mm_state;
mm_state_t mm_state; // not set/read
/* Globally Unique Temporary Identity */
GUTI_t guti;
me_identity_t me_identity;
GUTI_t guti; // guti.gummei.plmn set by nas_auth_param_req_t
// read by S6A UPDATE LOCATION REQUEST
me_identity_t me_identity; // not set/read except read by display utility
/* TODO: Add TAI list */
/* Last known cell identity */
cgi_t e_utran_cgi;
cgi_t e_utran_cgi; // set by nas_attach_req_t
// read for S11 CREATE_SESSION_REQUEST
/* Time when the cell identity was acquired */
time_t cell_age;
time_t cell_age; // set by nas_auth_param_req_t
/* TODO: add csg_id */
/* TODO: add csg_membership */
network_access_mode_t access_mode;
network_access_mode_t access_mode; // set by S6A UPDATE LOCATION ANSWER
/* TODO: add ue radio cap, ms classmarks, supported codecs */
@@ -147,27 +152,37 @@ typedef struct ue_context_s {
/* TODO: add DRX parameter */
apn_config_profile_t apn_profile;
apn_config_profile_t apn_profile; // set by S6A UPDATE LOCATION ANSWER
ard_t access_restriction_data; // set by S6A UPDATE LOCATION ANSWER
subscriber_status_t sub_status; // set by S6A UPDATE LOCATION ANSWER
ambr_t subscribed_ambr; // set by S6A UPDATE LOCATION ANSWER
ambr_t used_ambr;
ard_t access_restriction_data;
subscriber_status_t sub_status;
ambr_t subscribed_ambr;
ambr_t used_ambr;
rau_tau_timer_t rau_tau_timer;
rau_tau_timer_t rau_tau_timer; // set by S6A UPDATE LOCATION ANSWER
/* Store the radio capabilities as received in S1AP UE capability indication
* message.
*/
char *ue_radio_capabilities;
int ue_radio_cap_length;
char *ue_radio_capabilities; // not set/read
int ue_radio_cap_length; // not set/read
uint32_t mme_s11_teid;
uint32_t sgw_s11_teid;
Teid_t mme_s11_teid; // set by mme_app_send_s11_create_session_req
Teid_t sgw_s11_teid; // set by S11 CREATE_SESSION_RESPONSE
PAA_t paa; // set by S11 CREATE_SESSION_RESPONSE
bearer_context_t eps_bearers[BEARERS_PER_UE];
// temp
char pending_pdn_connectivity_req_imsi[16];
uint8_t pending_pdn_connectivity_req_imsi_length;
OctetString pending_pdn_connectivity_req_apn;
OctetString pending_pdn_connectivity_req_pdn_addr;
int pending_pdn_connectivity_req_pti;
unsigned pending_pdn_connectivity_req_ue_id;
network_qos_t pending_pdn_connectivity_req_qos;
void *pending_pdn_connectivity_req_proc_data;
int pending_pdn_connectivity_req_request_type;
ebi_t default_bearer_id;
bearer_context_t eps_bearers[BEARERS_PER_UE];
} ue_context_t;
typedef struct {
@@ -199,12 +214,28 @@ inline
ue_context_t *mme_ue_context_exists_s11_teid(mme_ue_context_t *mme_ue_context,
uint32_t teid);
/** \brief Retrieve an UE context by selecting the provided mme_ue_s1ap_id
* \param mme_ue_s1ap_id The UE id identifier used in S1AP MME (and NAS)
* @returns an UE context matching the mme_ue_s1ap_id or NULL if the context doesn't exists
**/
inline
ue_context_t *mme_ue_context_exists_mme_ue_s1ap_id(mme_ue_context_t *mme_ue_context,
uint32_t mme_ue_s1ap_id);
/** \brief Retrieve an UE context by selecting the provided nas_ue_id
* \param nas_ue_id The UE id identifier used in S1AP MME and NAS
* @returns an UE context matching the nas_ue_id or NULL if the context doesn't exists
**/
inline
ue_context_t *mme_ue_context_exists_nas_ue_id(mme_ue_context_t *mme_ue_context,
uint32_t nas_ue_id);
/** \brief Retrieve an UE context by selecting the provided guti
* \param guti The GUTI used by the UE
* @returns an UE context matching the guti or NULL if the context doesn't exists
**/
inline
struct ue_context_s *mme_ue_context_exists_guti(mme_ue_context_t *mme_ue_context,
ue_context_t *mme_ue_context_exists_guti(mme_ue_context_t *mme_ue_context,
GUTI_t guti);
/** \brief Insert a new UE context in the tree of known UEs.
+24 -22
View File
@@ -1,31 +1,33 @@
/*******************************************************************************
Eurecom OpenAirInterface Core Network
Copyright(c) 1999 - 2014 Eurecom
Eurecom OpenAirInterface
Copyright(c) 1999 - 2013 Eurecom
This program is free software; you can redistribute it and/or modify it
under the terms and conditions of the GNU General Public License,
version 2, as published by the Free Software Foundation.
This program is free software; you can redistribute it and/or modify it
under the terms and conditions of the GNU General Public License,
version 2, as published by the Free Software Foundation.
This program is distributed in the hope 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.
This program is distributed in the hope 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, write to the Free Software Foundation, Inc.,
51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
The full GNU General Public License is included in this distribution in
the file called "COPYING".
Contact Information
Openair Admin: openair_admin@eurecom.fr
Openair Tech : openair_tech@eurecom.fr
Forums : http://forums.eurecom.fr/openairinterface
Address : EURECOM, Campus SophiaTech, 450 Route des Chappes
06410 Biot FRANCE
The full GNU General Public License is included in this distribution in
the file called "COPYING".
Contact Information
Openair Admin: openair_admin@eurecom.fr
Openair Tech : openair_tech@eurecom.fr
Forums : http://forums.eurecom.fsr/openairinterface
Address : EURECOM,
Campus SophiaTech,
450 Route des Chappes,
CS 50193
06904 Biot Sophia Antipolis cedex,
FRANCE
*******************************************************************************/
#include "as_message.h"
+26 -5
View File
@@ -220,14 +220,22 @@ int emm_proc_attach(emm_proc_attach_type_t type)
/* Check whether the selected PLMN is neither the registered PLMN
* nor in the list of equivalent PLMNs */
if ( (!_emm_data.is_rplmn) && (!_emm_data.is_eplmn) ) {
LOG_TRACE(INFO, "EMM-PROC - Initiate EPS attach with IMSI");
/* Include the IMSI */
emm_as->UEid.imsi = _emm_data.imsi;
} else {
LOG_TRACE(INFO,
"EMM-PROC - Initiate EPS attach with NO IMSI, is registered PLMN %d, is equivalent PLMN %d",
_emm_data.is_rplmn,
_emm_data.is_eplmn);
}
} else if (_emm_data.guti) {
LOG_TRACE(INFO, "EMM-PROC - Initiate EPS attach with GUTI");
/* Include a valid GUTI and the last visited registered TAI */
emm_as->UEid.guti = _emm_data.guti;
emm_as->UEid.tai = _emm_data.tai;
} else if (!_emm_data.is_emergency) {
LOG_TRACE(INFO, "EMM-PROC - Initiate EPS attach with IMSI cause is no emergency and no GUTI");
/* Include the IMSI if no valid GUTI is available */
emm_as->UEid.imsi = _emm_data.imsi;
} else {
@@ -235,8 +243,10 @@ int emm_proc_attach(emm_proc_attach_type_t type)
* does not hold a valid GUTI */
if (_emm_data.imsi) {
/* Include the IMSI if valid (USIM is present) */
LOG_TRACE(INFO, "EMM-PROC - Initiate EPS attach with IMSI cause is emergency and no GUTI");
emm_as->UEid.imsi = _emm_data.imsi;
} else {
LOG_TRACE(INFO, "EMM-PROC - Initiate EPS attach with IMSI cause is emergency and no GUTI and no IMSI");
/* Include the IMEI if the IMSI is not valid */
emm_as->UEid.imei = _emm_data.imei;
}
@@ -2118,7 +2128,7 @@ static int _emm_attach(void *args)
/* Assign the TAI list the UE is registered to */
/* Allocate parameters of the retransmission timer callback */
attach_data_t *data = (attach_data_t *)malloc(sizeof(attach_data_t));
attach_data_t *data = (attach_data_t *)calloc(1,sizeof(attach_data_t));
if (data != NULL) {
/* Setup ongoing EMM procedure callback functions */
@@ -2134,6 +2144,7 @@ static int _emm_attach(void *args)
data->ueid = emm_ctx->ueid;
/* Reset the retransmission counter */
data->retransmission_count = 0;
#if defined(ORIGINAL_CODE)
/* Setup the ESM message container */
data->esm_msg.value = (uint8_t *)malloc(esm_sap.send.length);
if (data->esm_msg.value) {
@@ -2156,6 +2167,9 @@ static int _emm_attach(void *args)
rc = emm_sap_send(&emm_sap);
}
}
#else
rc = RETURNok;
#endif
}
} else if (esm_sap.err != ESM_SAP_DISCARDED) {
/*
@@ -2196,6 +2210,10 @@ static int _emm_attach(void *args)
LOG_FUNC_RETURN (rc);
}
int emm_cn_wrapper_attach_accept(emm_data_context_t *emm_ctx, void *data)
{
return _emm_attach_accept(emm_ctx,(attach_data_t *)data);
}
/****************************************************************************
** **
** Name: _emm_attach_accept() **
@@ -2228,13 +2246,13 @@ static int _emm_attach_accept(emm_data_context_t *emm_ctx, attach_data_t *data)
/* Implicit GUTI reallocation;
* include the new assigned GUTI in the Attach Accept message */
emm_sap.u.emm_as.u.establish.UEid.guti = emm_ctx->old_guti;
emm_sap.u.emm_as.u.establish.new_guti = emm_ctx->guti;
emm_sap.u.emm_as.u.establish.new_guti = emm_ctx->guti;
} else {
emm_sap.u.emm_as.u.establish.UEid.guti = emm_ctx->guti;
emm_sap.u.emm_as.u.establish.new_guti = NULL;
emm_sap.u.emm_as.u.establish.new_guti = NULL;
}
emm_sap.u.emm_as.u.establish.n_tacs = emm_ctx->n_tacs;
emm_sap.u.emm_as.u.establish.tac = emm_ctx->tac;
emm_sap.u.emm_as.u.establish.n_tacs = emm_ctx->n_tacs;
emm_sap.u.emm_as.u.establish.tac = emm_ctx->tac;
emm_sap.u.emm_as.u.establish.NASinfo = EMM_AS_NAS_INFO_ATTACH;
/* Setup EPS NAS security data */
emm_as_set_security_data(&emm_sap.u.emm_as.u.establish.sctx,
@@ -2242,6 +2260,9 @@ static int _emm_attach_accept(emm_data_context_t *emm_ctx, attach_data_t *data)
/* Get the activate default EPS bearer context request message to
* transfer within the ESM container of the attach accept message */
emm_sap.u.emm_as.u.establish.NASmsg = data->esm_msg;
LOG_TRACE(INFO,"EMM-PROC - NASmsg src size = %d NASmsg dst size = %d ",
data->esm_msg.length, emm_sap.u.emm_as.u.establish.NASmsg.length);
rc = emm_sap_send(&emm_sap);
if (rc != RETURNerror) {
@@ -509,7 +509,8 @@ int emm_proc_initialize(void)
* When switched on, the UE will try to automatically register
* to each previous PLMN within the ordered list of available
* PLMNs regardless of the network selection mode of operation */
_emm_plmn_list.hplmn = _emm_plmn_list.n_plmns;
_emm_plmn_list.hplmn = _emm_plmn_list.n_plmns - 1;
// LG_emm_plmn_list.hplmn = _emm_plmn_list.n_plmns;
/* Add the highest priority PLMN in the list of "equivalent HPLMNs"
if present and not empty, or the HPLMN derived from the IMSI */
@@ -891,9 +892,11 @@ int emm_proc_plmn_selection_end(int found, tac_t tac, ci_t ci, AcT_t rat)
if (_emm_plmn_list.splmn != -1) {
if (_emm_plmn_list.splmn == _emm_plmn_list.rplmn) {
/* The selected PLMN is the registered PLMN */
LOG_TRACE(INFO, "EMM-IDLE - The selected PLMN is the registered PLMN");
_emm_data.is_rplmn = TRUE;
} else if (_emm_plmn_list.splmn < _emm_plmn_list.hplmn) {
/* The selected PLMN is in the list of equivalent PLMNs */
LOG_TRACE(INFO, "EMM-IDLE - The selected PLMN is in the list of equivalent PLMNs");
_emm_data.is_eplmn = TRUE;
}
/*
+21 -21
View File
@@ -326,30 +326,30 @@ typedef struct emm_data_context_s {
RB_ENTRY(emm_data_context_s) entries;
#endif
unsigned int ueid; /* UE identifier */
int is_dynamic; /* Dynamically allocated context indicator */
int is_attached; /* Attachment indicator */
int is_emergency; /* Emergency bearer services indicator */
unsigned int ueid; /* UE identifier */
int is_dynamic; /* Dynamically allocated context indicator */
int is_attached; /* Attachment indicator */
int is_emergency;/* Emergency bearer services indicator */
imsi_t *imsi; /* The IMSI provided by the UE or the MME */
imei_t *imei; /* The IMEI provided by the UE */
int guti_is_new; /* New GUTI indicator */
GUTI_t *guti; /* The GUTI assigned to the UE */
GUTI_t *old_guti; /* The old GUTI */
int n_tacs; /* Number of concecutive tracking areas the UE is
* registered to */
tac_t tac; /* Code of the first tracking area the UE is
* registered to */
imsi_t *imsi; /* The IMSI provided by the UE or the MME */
imei_t *imei; /* The IMEI provided by the UE */
int guti_is_new; /* New GUTI indicator */
GUTI_t *guti; /* The GUTI assigned to the UE */
GUTI_t *old_guti; /* The old GUTI */
int n_tacs; /* Number of consecutive tracking areas the UE is
* registered to */
tac_t tac; /* Code of the first tracking area the UE is
* registered to */
int ksi; /* Security key set identifier provided by the UE */
int eea; /* EPS encryption algorithms supported by the UE */
int eia; /* EPS integrity algorithms supported by the UE */
auth_vector_t vector; /* EPS authentication vector */
emm_security_context_t *security; /* Current EPS NAS security context */
OctetString esm_msg; /* ESM message contained within the initial request */
int emm_cause; /* EMM failure cause code */
int ksi; /* Security key set identifier provided by the UE */
int eea; /* EPS encryption algorithms supported by the UE */
int eia; /* EPS integrity algorithms supported by the UE */
auth_vector_t vector;/* EPS authentication vector */
emm_security_context_t *security; /* Current EPS NAS security context */
OctetString esm_msg; /* ESM message contained within the initial request*/
int emm_cause; /* EMM failure cause code */
emm_fsm_state_t _emm_fsm_status;
emm_fsm_state_t _emm_fsm_status;
esm_data_context_t esm_data_ctx;
} emm_data_context_t;
@@ -6,6 +6,7 @@
#include "assertions.h"
#include "tree.h"
#include "emmData.h"
#include "nas_log.h"
static inline
int emm_data_ctxt_compare_ueid(struct emm_data_context_s *p1,
@@ -48,11 +49,13 @@ struct emm_data_context_s *emm_data_context_get(
struct emm_data_context_s *emm_data_context_remove(
emm_data_t *emm_data, struct emm_data_context_s *elm)
{
LOG_TRACE(INFO, "EMM-CTX - Remove in context %p UE id %u", elm, elm->ueid);
return RB_REMOVE(emm_data_context_map, &emm_data->ctx_map, elm);
}
void emm_data_context_add(emm_data_t *emm_data, struct emm_data_context_s *elm)
{
LOG_TRACE(INFO, "EMM-CTX - Add in context %p UE id %u", elm, elm->ueid);
RB_INSERT(emm_data_context_map, &emm_data->ctx_map, elm);
}
@@ -157,39 +157,45 @@ int encode_attach_accept(attach_accept_msg *attach_accept, uint8_t *buffer, uint
int encoded = 0;
int encode_result = 0;
LOG_FUNC_IN;
/* Checking IEI and pointer */
CHECK_PDU_POINTER_AND_LENGTH_ENCODER(buffer, ATTACH_ACCEPT_MINIMUM_LENGTH, len);
*(buffer + encoded) = (encode_u8_eps_attach_result(&attach_accept->epsattachresult) & 0x0f);
encoded++;
if ((encode_result = encode_gprs_timer(&attach_accept->t3412value, 0, buffer
+ encoded, len - encoded)) < 0) //Return in case of error
return encode_result;
else
+ encoded, len - encoded)) < 0) { //Return in case of error
LOG_TRACE(WARNING, "Failed encode_gprs_timer");
LOG_FUNC_RETURN(encode_result);
} else
encoded += encode_result;
if ((encode_result =
encode_tracking_area_identity_list(&attach_accept->tailist, 0, buffer
+ encoded, len - encoded)) < 0) //Return in case of error
return encode_result;
else
+ encoded, len - encoded)) < 0) { //Return in case of error
LOG_TRACE(WARNING, "Failed encode_tracking_area_identity_list");
LOG_FUNC_RETURN(encode_result);
} else
encoded += encode_result;
if ((encode_result =
encode_esm_message_container(&attach_accept->esmmessagecontainer, 0,
buffer + encoded, len - encoded)) < 0) //Return in case of error
return encode_result;
else
buffer + encoded, len - encoded)) < 0) { //Return in case of error
LOG_TRACE(WARNING, "Failed encode_esm_message_container");
LOG_FUNC_RETURN(encode_result);
} else
encoded += encode_result;
if ((attach_accept->presencemask & ATTACH_ACCEPT_GUTI_PRESENT)
== ATTACH_ACCEPT_GUTI_PRESENT)
{
if ((encode_result = encode_eps_mobile_identity(&attach_accept->guti,
ATTACH_ACCEPT_GUTI_IEI, buffer + encoded, len - encoded)) < 0)
ATTACH_ACCEPT_GUTI_IEI, buffer + encoded, len - encoded)) < 0) {
// Return in case of error
return encode_result;
else
LOG_TRACE(WARNING, "Failed encode_eps_mobile_identity");
LOG_FUNC_RETURN(encode_result);
} else
encoded += encode_result;
}
@@ -199,10 +205,11 @@ int encode_attach_accept(attach_accept_msg *attach_accept, uint8_t *buffer, uint
if ((encode_result =
encode_location_area_identification(&attach_accept->locationareaidentification,
ATTACH_ACCEPT_LOCATION_AREA_IDENTIFICATION_IEI, buffer + encoded,
len - encoded)) < 0)
len - encoded)) < 0) {
LOG_TRACE(WARNING, "Failed encode_location_area_identification");
// Return in case of error
return encode_result;
else
LOG_FUNC_RETURN(encode_result);
} else
encoded += encode_result;
}
@@ -211,10 +218,11 @@ int encode_attach_accept(attach_accept_msg *attach_accept, uint8_t *buffer, uint
{
if ((encode_result = encode_mobile_identity(&attach_accept->msidentity,
ATTACH_ACCEPT_MS_IDENTITY_IEI, buffer + encoded, len - encoded)) <
0)
0) {
LOG_TRACE(WARNING, "Failed encode_mobile_identity");
// Return in case of error
return encode_result;
else
LOG_FUNC_RETURN(encode_result);
} else
encoded += encode_result;
}
@@ -223,10 +231,10 @@ int encode_attach_accept(attach_accept_msg *attach_accept, uint8_t *buffer, uint
{
if ((encode_result = encode_emm_cause(&attach_accept->emmcause,
ATTACH_ACCEPT_EMM_CAUSE_IEI, buffer + encoded, len - encoded)) <
0)
0) {
// Return in case of error
return encode_result;
else
LOG_FUNC_RETURN(encode_result);
} else
encoded += encode_result;
}
@@ -235,10 +243,11 @@ int encode_attach_accept(attach_accept_msg *attach_accept, uint8_t *buffer, uint
{
if ((encode_result = encode_gprs_timer(&attach_accept->t3402value,
ATTACH_ACCEPT_T3402_VALUE_IEI, buffer + encoded, len - encoded)) <
0)
0) {
LOG_TRACE(WARNING, "Failed encode_gprs_timer");
// Return in case of error
return encode_result;
else
LOG_FUNC_RETURN(encode_result);
} else
encoded += encode_result;
}
@@ -247,10 +256,11 @@ int encode_attach_accept(attach_accept_msg *attach_accept, uint8_t *buffer, uint
{
if ((encode_result = encode_gprs_timer(&attach_accept->t3423value,
ATTACH_ACCEPT_T3423_VALUE_IEI, buffer + encoded, len - encoded)) <
0)
0) {
LOG_TRACE(WARNING, "Failed encode_gprs_timer");
// Return in case of error
return encode_result;
else
LOG_FUNC_RETURN(encode_result);
} else
encoded += encode_result;
}
@@ -259,10 +269,11 @@ int encode_attach_accept(attach_accept_msg *attach_accept, uint8_t *buffer, uint
{
if ((encode_result = encode_plmn_list(&attach_accept->equivalentplmns,
ATTACH_ACCEPT_EQUIVALENT_PLMNS_IEI, buffer + encoded, len -
encoded)) < 0)
encoded)) < 0) {
LOG_TRACE(WARNING, "Failed encode_plmn_list");
// Return in case of error
return encode_result;
else
LOG_FUNC_RETURN(encode_result);
} else
encoded += encode_result;
}
@@ -272,10 +283,11 @@ int encode_attach_accept(attach_accept_msg *attach_accept, uint8_t *buffer, uint
if ((encode_result =
encode_emergency_number_list(&attach_accept->emergencynumberlist,
ATTACH_ACCEPT_EMERGENCY_NUMBER_LIST_IEI, buffer + encoded, len -
encoded)) < 0)
encoded)) < 0) {
LOG_TRACE(WARNING, "Failed encode_emergency_number_list");
// Return in case of error
return encode_result;
else
LOG_FUNC_RETURN(encode_result);
} else
encoded += encode_result;
}
@@ -285,10 +297,11 @@ int encode_attach_accept(attach_accept_msg *attach_accept, uint8_t *buffer, uint
if ((encode_result =
encode_eps_network_feature_support(&attach_accept->epsnetworkfeaturesupport,
ATTACH_ACCEPT_EPS_NETWORK_FEATURE_SUPPORT_IEI, buffer + encoded,
len - encoded)) < 0)
len - encoded)) < 0) {
LOG_TRACE(WARNING, "Failed encode_eps_network_feature_support");
// Return in case of error
return encode_result;
else
LOG_FUNC_RETURN(encode_result);
} else
encoded += encode_result;
}
@@ -298,13 +311,14 @@ int encode_attach_accept(attach_accept_msg *attach_accept, uint8_t *buffer, uint
if ((encode_result =
encode_additional_update_result(&attach_accept->additionalupdateresult,
ATTACH_ACCEPT_ADDITIONAL_UPDATE_RESULT_IEI, buffer + encoded, len
- encoded)) < 0)
- encoded)) < 0) {
LOG_TRACE(WARNING, "Failed encode_additional_update_result");
// Return in case of error
return encode_result;
else
LOG_FUNC_RETURN(encode_result);
} else
encoded += encode_result;
}
return encoded;
LOG_FUNC_RETURN(encoded);
}
@@ -1708,6 +1708,8 @@ static int _emm_as_establish_cnf(const emm_as_establish_t *msg,
/* Setup the initial NAS information message */
if (emm_msg != NULL) switch (msg->NASinfo) {
case EMM_AS_NAS_INFO_ATTACH:
LOG_TRACE(WARNING, "EMMAS-SAP - emm_as_establish.nasMSG.length"\
"=%d", msg->NASmsg.length);
size = emm_send_attach_accept(msg, &emm_msg->attach_accept);
break;
+211 -1
View File
@@ -12,7 +12,7 @@ Product NAS stack
Subsystem EPS Core Network
Author Sebastien Roux
Author Sebastien Roux, Lionel GAUTHIER
Description
@@ -30,6 +30,26 @@ Description
#include "emm_proc.h"
#include "emm_cause.h"
#include "esm_send.h" // LG
#include "esm_proc.h" // LG
#include "esm_cause.h" // LG
#include "assertions.h"// LG
#include "emmData.h" // LG
#include "esm_sap.h" // LG
#include "EmmCommon.h" // LG
extern int emm_cn_wrapper_attach_accept(emm_data_context_t *emm_ctx, void *data);
/*
* Internal data used for attach procedure
*/
typedef struct {
unsigned int ueid; /* UE identifier */
#define ATTACH_COUNTER_MAX 5
unsigned int retransmission_count; /* Retransmission counter */
OctetString esm_msg; /* ESM message to be sent within
* the Attach Accept message */
} attach_data_t;
/*
* String representation of EMMCN-SAP primitives
*/
@@ -37,8 +57,13 @@ static const char *_emm_cn_primitive_str[] = {
"EMM_CN_AUTHENTICATION_PARAM_RES",
"EMM_CN_AUTHENTICATION_PARAM_FAIL",
"EMM_CN_DEREGISTER_UE",
"EMM_CN_PDN_CONNECTIVITY_RES",
"EMM_CN_PDN_CONNECTIVITY_FAIL",
};
#define EMM_CN_SAP_BUFFER_SIZE 4096
static char _emm_cn_sap_buffer[EMM_CN_SAP_BUFFER_SIZE];
static int _emm_cn_authentication_res(const emm_cn_auth_res_t *msg)
{
emm_data_context_t *emm_ctx = NULL;
@@ -111,6 +136,183 @@ static int _emm_cn_deregister_ue(const UInt32_t ue_id)
LOG_FUNC_RETURN (rc);
}
static int _emm_cn_pdn_connectivity_res(const emm_cn_pdn_res_t *msg_pP)
{
int rc = RETURNok;
struct emm_data_context_s *emm_ctx_p = NULL;
esm_proc_pdn_type_t esm_pdn_type = ESM_PDN_TYPE_IPV4;
esm_proc_data_t *esm_proc_data_p = NULL;
ESM_msg esm_msg;
EpsQualityOfService qos;
OctetString rsp = { 0, NULL};
int is_standalone = 0; // warning hardcoded
int triggered_by_ue = 1; // warning hardcoded
attach_data_t *data_p = NULL;
int esm_cause = ESM_CAUSE_SUCCESS;
int pid = 0;
unsigned int new_ebi = 0;
LOG_FUNC_IN;
emm_ctx_p = emm_data_context_get(&_emm_data, msg_pP->ue_id);
if (emm_ctx_p == NULL) {
LOG_TRACE(ERROR, "EMMCN-SAP - "
"Failed to find UE associated to id %u...", msg_pP->ue_id);
LOG_FUNC_RETURN (rc);
}
memset(&esm_msg, 0 , sizeof(ESM_msg));
switch (msg_pP->pdn_type) {
case IPv4:
esm_pdn_type = ESM_PDN_TYPE_IPV4;
break;
case IPv6:
esm_pdn_type = ESM_PDN_TYPE_IPV6;
break;
case IPv4_AND_v6:
esm_pdn_type = ESM_PDN_TYPE_IPV4V6;
break;
default:
esm_pdn_type = ESM_PDN_TYPE_IPV4;
}
qos.bitRatesPresent = 1;
qos.bitRatesExtPresent = 0;
qos.qci = msg_pP->qos.qci;
qos.bitRates.maxBitRateForUL = msg_pP->qos.mbrUL;
qos.bitRates.maxBitRateForDL = msg_pP->qos.mbrDL;
qos.bitRates.guarBitRateForUL = msg_pP->qos.gbrUL;
qos.bitRates.guarBitRateForDL = msg_pP->qos.gbrDL;
qos.bitRatesExt.maxBitRateForUL = 0;
qos.bitRatesExt.maxBitRateForDL = 0;
qos.bitRatesExt.guarBitRateForUL = 0;
qos.bitRatesExt.guarBitRateForDL = 0;
/*************************************************************************/
/* CODE THAT WAS IN esm_recv.c/esm_recv_pdn_connectivity_request() */
/*************************************************************************/
/* Execute the PDN connectivity procedure requested by the UE */
pid = esm_proc_pdn_connectivity_request(
emm_ctx_p,
msg_pP->pti,
msg_pP->request_type,
&msg_pP->apn,
esm_pdn_type,
&msg_pP->pdn_addr,
NULL,
&esm_cause);
LOG_TRACE(INFO, "EMM - APN = %s ", (char *)(msg_pP->apn.value));
if (pid != RETURNerror) {
/* Create local default EPS bearer context */
rc = esm_proc_default_eps_bearer_context(
emm_ctx_p,
pid,
&new_ebi,
&msg_pP->qos,
&esm_cause);
if (rc != RETURNerror) {
esm_cause = ESM_CAUSE_SUCCESS;
}
} else {
LOG_FUNC_RETURN (rc);
}
/**************************************************************************/
/* END OF CODE THAT WAS IN esm_recv.c/esm_recv_pdn_connectivity_request() */
/**************************************************************************/
LOG_TRACE(INFO, "EMM - APN = %s ", (char *)(msg_pP->apn.value));
/*************************************************************************/
/* CODE THAT WAS IN esm_sap.c/_esm_sap_recv() */
/*************************************************************************/
/* Return default EPS bearer context request message */
rc = esm_send_activate_default_eps_bearer_context_request(
msg_pP->pti,
new_ebi, //msg_pP->ebi,
&esm_msg.activate_default_eps_bearer_context_request,
&msg_pP->apn,
esm_pdn_type,
&msg_pP->pdn_addr,
&qos,
ESM_CAUSE_SUCCESS);
if (rc != RETURNerror) {
/* Encode the returned ESM response message */
int size = esm_msg_encode(&esm_msg, (uint8_t *)_emm_cn_sap_buffer,
EMM_CN_SAP_BUFFER_SIZE);
LOG_TRACE(INFO, "ESM encoded MSG size %d ", size);
if (size > 0) {
rsp.length = size;
rsp.value = (uint8_t *)(_emm_cn_sap_buffer);
}
/* Complete the relevant ESM procedure */
rc = esm_proc_default_eps_bearer_context_request(
is_standalone,
emm_ctx_p,
new_ebi, //0, //ESM_EBI_UNASSIGNED, //msg->ebi,
&rsp,
triggered_by_ue);
if (rc != RETURNok) {
/* Return indication that ESM procedure failed */
LOG_FUNC_RETURN (rc);
}
} else {
LOG_TRACE(INFO, "ESM send activate_default_eps_bearer_context_request failed");
}
/*************************************************************************/
/* END OF CODE THAT WAS IN esm_sap.c/_esm_sap_recv() */
/*************************************************************************/
LOG_TRACE(INFO, "EMM - APN = %s ", (char *)(msg_pP->apn.value));
data_p = (attach_data_t *)emm_proc_common_get_args(msg_pP->ue_id);
/* Setup the ESM message container */
data_p->esm_msg.value = (uint8_t *)malloc(rsp.length);
if (data_p->esm_msg.value) {
data_p->esm_msg.length = rsp.length;
LOG_TRACE(INFO, "EMM - copy ESM MSG %d bytes", data_p->esm_msg.length);
memcpy(data_p->esm_msg.value,
rsp.value,
rsp.length);
} else {
data_p->esm_msg.length = 0;
}
/* Send attach accept message to the UE */
rc = emm_cn_wrapper_attach_accept(emm_ctx_p, data_p);
if (rc != RETURNerror) {
if (emm_ctx_p->guti_is_new && emm_ctx_p->old_guti) {
/* Implicit GUTI reallocation;
* Notify EMM that common procedure has been initiated
*/
emm_sap_t emm_sap;
emm_sap.primitive = EMMREG_COMMON_PROC_REQ;
emm_sap.u.emm_reg.ueid = msg_pP->ue_id;
rc = emm_sap_send(&emm_sap);
}
}
LOG_TRACE(INFO, "EMM - APN = %s ", (char *)(msg_pP->apn.value));
LOG_FUNC_RETURN (rc);
}
static int _emm_cn_pdn_connectivity_fail(const emm_cn_pdn_fail_t *msg)
{
int rc = RETURNok;
LOG_FUNC_IN;
LOG_FUNC_RETURN (rc);
}
int emm_cn_send(const emm_cn_t *msg)
{
int rc = RETURNerror;
@@ -134,6 +336,14 @@ int emm_cn_send(const emm_cn_t *msg)
rc = _emm_cn_deregister_ue(msg->u.deregister.UEid);
break;
case EMMCN_PDN_CONNECTIVITY_RES:
rc = _emm_cn_pdn_connectivity_res(msg->u.emm_cn_pdn_res);
break;
case EMMCN_PDN_CONNECTIVITY_FAIL:
rc = _emm_cn_pdn_connectivity_fail(msg->u.emm_cn_pdn_fail);
break;
default:
/* Other primitives are forwarded to the Access Stratum */
rc = RETURNerror;
@@ -12,7 +12,7 @@ Product NAS stack
Subsystem EPS Core Network
Author Sebastien Roux
Author Sebastien Roux, Lionel GAUTHIER
Description
@@ -12,7 +12,7 @@ Product NAS stack
Subsystem EPS Core Network
Author Sebastien Roux
Author Sebastien Roux, Lionel GAUTHIER
Description
@@ -31,13 +31,17 @@ typedef enum emmcn_primitive_s {
_EMMCN_AUTHENTICATION_PARAM_RES,
_EMMCN_AUTHENTICATION_PARAM_FAIL,
_EMMCN_DEREGISTER_UE,
_EMMCN_PDN_CONNECTIVITY_RES, // LG
_EMMCN_PDN_CONNECTIVITY_FAIL,// LG
#endif
_EMMCN_END
} emm_cn_primitive_t;
#if defined(EPC_BUILD)
typedef nas_auth_param_rsp_t emm_cn_auth_res_t;
typedef nas_auth_param_fail_t emm_cn_auth_fail_t;
typedef nas_auth_param_rsp_t emm_cn_auth_res_t;
typedef nas_auth_param_fail_t emm_cn_auth_fail_t;
typedef nas_pdn_connectivity_rsp_t emm_cn_pdn_res_t;
typedef nas_pdn_connectivity_fail_t emm_cn_pdn_fail_t;
typedef struct emm_cn_deregister_ue_s {
UInt32_t UEid;
@@ -49,6 +53,8 @@ typedef struct emm_mme_ul_s {
emm_cn_auth_res_t *auth_res;
emm_cn_auth_fail_t *auth_fail;
emm_cn_deregister_ue_t deregister;
emm_cn_pdn_res_t *emm_cn_pdn_res;
emm_cn_pdn_fail_t *emm_cn_pdn_fail;
} u;
} emm_cn_t;
#endif
@@ -110,7 +110,9 @@ typedef enum {
#ifdef EPC_BUILD
EMMCN_AUTHENTICATION_PARAM_RES = _EMMCN_AUTHENTICATION_PARAM_RES,
EMMCN_AUTHENTICATION_PARAM_FAIL = _EMMCN_AUTHENTICATION_PARAM_FAIL,
EMMCN_DEREGISTER_UE = _EMMCN_DEREGISTER_UE
EMMCN_DEREGISTER_UE = _EMMCN_DEREGISTER_UE,
EMMCN_PDN_CONNECTIVITY_RES = _EMMCN_PDN_CONNECTIVITY_RES,
EMMCN_PDN_CONNECTIVITY_FAIL = _EMMCN_PDN_CONNECTIVITY_FAIL
#endif
} emm_primitive_t;
@@ -177,6 +177,7 @@ int emm_send_attach_request(const emm_as_establish_t *msg,
/* Mandatory - EPS mobile identity */
size += EPS_MOBILE_IDENTITY_MAXIMUM_LENGTH;
if (msg->UEid.guti) {
LOG_TRACE(INFO, "EMMAS-SAP - Send Attach Request message with GUTI");
/* Set GUTI mobile identity */
GutiEpsMobileIdentity_t *guti = &emm_msg->oldgutiorimsi.guti;
guti->typeofidentity = EPS_MOBILE_IDENTITY_GUTI;
@@ -191,6 +192,7 @@ int emm_send_attach_request(const emm_as_establish_t *msg,
guti->mncdigit2 = msg->UEid.guti->gummei.plmn.MNCdigit2;
guti->mncdigit3 = msg->UEid.guti->gummei.plmn.MNCdigit3;
} else if (msg->UEid.imsi) {
LOG_TRACE(INFO, "EMMAS-SAP - Send Attach Request message with IMSI");
/* Set IMSI mobile identity */
ImsiEpsMobileIdentity_t *imsi = &emm_msg->oldgutiorimsi.imsi;
imsi->typeofidentity = EPS_MOBILE_IDENTITY_IMSI;
@@ -211,6 +213,7 @@ int emm_send_attach_request(const emm_as_establish_t *msg,
imsi->digit14 = msg->UEid.imsi->u.num.digit14;
imsi->digit15 = msg->UEid.imsi->u.num.digit15;
} else if (msg->UEid.imei) {
LOG_TRACE(INFO, "EMMAS-SAP - Send Attach Request message with IMEI");
/* Set IMEI mobile identity */
ImeiEpsMobileIdentity_t *imei = &emm_msg->oldgutiorimsi.imei;
imei->typeofidentity = EPS_MOBILE_IDENTITY_IMEI;
@@ -897,6 +900,8 @@ int emm_send_attach_accept(const emm_as_establish_t *msg,
int size = EMM_HEADER_MAXIMUM_LENGTH;
LOG_TRACE(INFO, "EMMAS-SAP - Send Attach Accept message");
LOG_TRACE(INFO, "EMMAS-SAP - size = EMM_HEADER_MAXIMUM_LENGTH(%d)",
size);
/* Mandatory - Message type */
emm_msg->messagetype = ATTACH_ACCEPT;
@@ -908,6 +913,8 @@ int emm_send_attach_accept(const emm_as_establish_t *msg,
/* Mandatory - T3412 value */
size += GPRS_TIMER_MAXIMUM_LENGTH;
emm_msg->t3412value.unit = GPRS_TIMER_UNIT_0S;
LOG_TRACE(INFO, "EMMAS-SAP - size += GPRS_TIMER_MAXIMUM_LENGTH(%d) (%d)",
GPRS_TIMER_MAXIMUM_LENGTH, size);
/* Mandatory - Tracking area identity list */
size += TRACKING_AREA_IDENTITY_LIST_MINIMUM_LENGTH;
@@ -921,10 +928,20 @@ int emm_send_attach_accept(const emm_as_establish_t *msg,
emm_msg->tailist.mncdigit2 = msg->UEid.guti->gummei.plmn.MNCdigit2;
emm_msg->tailist.mncdigit3 = msg->UEid.guti->gummei.plmn.MNCdigit3;
emm_msg->tailist.tac = msg->tac;
LOG_TRACE(INFO,
"EMMAS-SAP - size += "\
"TRACKING_AREA_IDENTITY_LIST_MINIMUM_LENGTH(%d) (%d)",
TRACKING_AREA_IDENTITY_LIST_MINIMUM_LENGTH,
size);
/* Mandatory - ESM message container */
size += ESM_MESSAGE_CONTAINER_MINIMUM_LENGTH + msg->NASmsg.length;
emm_msg->esmmessagecontainer.esmmessagecontainercontents = msg->NASmsg;
LOG_TRACE(INFO,
"EMMAS-SAP - size += "\
"ESM_MESSAGE_CONTAINER_MINIMUM_LENGTH(%d) (%d)",
ESM_MESSAGE_CONTAINER_MINIMUM_LENGTH,
size);
/* Optional - GUTI */
if (msg->new_guti) {
@@ -941,6 +958,11 @@ int emm_send_attach_accept(const emm_as_establish_t *msg,
emm_msg->guti.guti.mncdigit1 = msg->new_guti->gummei.plmn.MNCdigit1;
emm_msg->guti.guti.mncdigit2 = msg->new_guti->gummei.plmn.MNCdigit2;
emm_msg->guti.guti.mncdigit3 = msg->new_guti->gummei.plmn.MNCdigit3;
LOG_TRACE(INFO,
"EMMAS-SAP - size += "\
"EPS_MOBILE_IDENTITY_MAXIMUM_LENGTH(%d) (%d)",
EPS_MOBILE_IDENTITY_MAXIMUM_LENGTH,
size);
}
LOG_FUNC_RETURN (size);
}
@@ -177,13 +177,16 @@ int esm_proc_default_eps_bearer_context_request(int is_standalone,
LOG_FUNC_IN;
LOG_TRACE(INFO,"ESM-PROC - Initiate default EPS bearer context activation "
"(ueid=%u, ebi=%d)", ctx->ueid, ebi);
if (is_standalone) {
/* Send activate default EPS bearer context request message and
* start timer T3485 */
LOG_TRACE(INFO,"ESM-PROC - Initiate standalone default EPS bearer context activation "
"(ueid=%u, ebi=%d)", ctx->ueid, ebi);
rc = _default_eps_bearer_activate(ctx, ebi, msg);
} else {
LOG_TRACE(INFO,"ESM-PROC - Initiate non standalone default EPS bearer context activation "
"(ueid=%u, ebi=%d)", ctx->ueid, ebi);
}
if (rc != RETURNerror) {
@@ -617,10 +617,11 @@ int esm_proc_pdn_connectivity_request(emm_data_context_t *ctx, int pti,
LOG_FUNC_IN;
LOG_TRACE(INFO, "ESM-PROC - PDN connectivity requested by the UE "
"(ueid=%u, pti=%d) PDN type = %s, APN = %s", ctx->ueid, pti,
"(ueid=%u, pti=%d) PDN type = %s, APN = %s pdn addr = %s", ctx->ueid, pti,
(pdn_type == ESM_PDN_TYPE_IPV4)? "IPv4" :
(pdn_type == ESM_PDN_TYPE_IPV6)? "IPv6" : "IPv4v6",
(apn) ? (char *)(apn->value) : "null");
(apn) ? (char *)(apn->value) : "null",
(pdn_addr) ? (char *)(pdn_addr->value) : "null");
#if !defined(EPC_BUILD)
/* UE identifier sanity check */
@@ -634,6 +635,9 @@ int esm_proc_pdn_connectivity_request(emm_data_context_t *ctx, int pti,
* Check network IP capabilities
*/
*esm_cause = ESM_CAUSE_SUCCESS;
LOG_TRACE(INFO, "ESM-PROC - _esm_data.conf.features %08x", _esm_data.conf.features);
#warning "Uncomment code about _esm_data.conf.features & (MME_API_IPV4 | MME_API_IPV6) later"
#if defined(ORIGINAL_CODE)
switch (_esm_data.conf.features & (MME_API_IPV4 | MME_API_IPV6)) {
case (MME_API_IPV4 | MME_API_IPV6):
/* The network supports both IPv4 and IPv6 connection */
@@ -660,11 +664,19 @@ int esm_proc_pdn_connectivity_request(emm_data_context_t *ctx, int pti,
rc = RETURNok;
}
break;
}
default:
LOG_TRACE(ERROR,
"ESM-PROC - _esm_data.conf.features incorrect value (no IPV4 or IPV6 ) %X",
_esm_data.conf.features);
}
#else
rc = RETURNok;
#endif
if (rc != RETURNerror) {
mme_api_ip_version_t mme_pdn_index;
int is_emergency = (request_type == ESM_PDN_REQUEST_EMERGENCY);
#if defined(ORIGINAL_CODE)
mme_api_ip_version_t mme_pdn_index;
mme_api_qos_t qos;
switch (pdn_type)
@@ -692,20 +704,21 @@ int esm_proc_pdn_connectivity_request(emm_data_context_t *ctx, int pti,
*esm_cause = ESM_CAUSE_REQUEST_REJECTED_UNSPECIFIED;
LOG_FUNC_RETURN (RETURNerror);
}
#endif
/* Create new PDN connection */
pid = _pdn_connectivity_create(ctx, pti, apn, pdn_type,
pdn_addr, is_emergency);
#if defined(ORIGINAL_CODE)
/* Setup ESM QoS parameters */
if (esm_qos) {
esm_qos->gbrUL = qos.gbr[MME_API_UPLINK];
esm_qos->gbrDL = qos.gbr[MME_API_DOWNLINK];
esm_qos->mbrUL = qos.mbr[MME_API_UPLINK];
esm_qos->mbrDL = qos.mbr[MME_API_DOWNLINK];
esm_qos->qci = qos.qci;
esm_qos->qci = qos.qci;
}
#endif
if (pid < 0) {
LOG_TRACE(WARNING, "ESM-PROC - Failed to create PDN connection");
*esm_cause = ESM_CAUSE_INSUFFICIENT_RESOURCES;
@@ -358,6 +358,8 @@ int esm_ebr_start_timer(emm_data_context_t *ctx, int ebi, const OctetString *msg
LOG_FUNC_IN;
if ( (ebi < ESM_EBI_MIN) || (ebi > ESM_EBI_MAX) ) {
LOG_TRACE(ERROR, "ESM-FSM - Retransmission timer bad ebi %d",
ebi);
LOG_FUNC_RETURN (RETURNerror);
}
@@ -365,6 +367,7 @@ int esm_ebr_start_timer(emm_data_context_t *ctx, int ebi, const OctetString *msg
ebr_ctx = ctx->esm_data_ctx.ebr.context[ebi - ESM_EBI_MIN];
if ( (ebr_ctx == NULL) || (ebr_ctx->ebi != ebi) ) {
/* EPS bearer context not assigned */
LOG_TRACE(ERROR, "ESM-FSM - EPS bearer context not assigned");
LOG_FUNC_RETURN (RETURNerror);
}
@@ -401,6 +404,10 @@ int esm_ebr_start_timer(emm_data_context_t *ctx, int ebi, const OctetString *msg
LOG_TRACE(INFO, "ESM-FSM - Retransmission timer %d expires in "
"%ld seconds", ebr_ctx->timer.id, ebr_ctx->timer.sec);
LOG_FUNC_RETURN (RETURNok);
} else {
LOG_TRACE(ERROR, "ESM-FSM - ebr_ctx->args == NULL(%p) or ebr_ctx->timer.id == NAS_TIMER_INACTIVE_ID == -1 (%d)" ,
ebr_ctx->args,
ebr_ctx->timer.id);
}
LOG_FUNC_RETURN (RETURNerror);
}
@@ -34,6 +34,14 @@ Description Defines functions used to handle EPS bearer contexts.
# include "assertions.h"
#endif
#ifdef NAS_UE
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#endif
/****************************************************************************/
/**************** E X T E R N A L D E F I N I T I O N S ****************/
/****************************************************************************/
@@ -184,6 +192,88 @@ int esm_ebr_context_create(
if (pdn->is_emergency) {
esm_ctx->emergency = TRUE;
}
#ifdef NAS_UE
// LG ADD TEMP
{
char *tmp = NULL;
char ipv4_addr[INET_ADDRSTRLEN];
char ipv6_addr[INET6_ADDRSTRLEN];
char *netmask = NULL;
char broadcast[INET_ADDRSTRLEN];
struct in_addr in_addr;
char command_line[128];
int res;
switch (pdn->type) {
case NET_PDN_TYPE_IPV4V6:
ipv6_addr[0] = pdn->ip_addr[4];
// etc
case NET_PDN_TYPE_IPV4:
in_addr.s_addr = pdn->ip_addr[0] << 24;
in_addr.s_addr |= pdn->ip_addr[1] << 16;
in_addr.s_addr |= pdn->ip_addr[2] << 8;
in_addr.s_addr |= pdn->ip_addr[3] ;
tmp = inet_ntoa(in_addr);
// AssertFatal(tmp ,
// "error in PDN IPv4 address %x",
// in_addr.s_addr);
strcpy(ipv4_addr, tmp);
if (IN_CLASSA(in_addr.s_addr)) {
netmask = "255.0.0.0";
in_addr.s_addr = pdn->ip_addr[0] << 24;
in_addr.s_addr |= 255 << 16;
in_addr.s_addr |= 255 << 8;
in_addr.s_addr |= 255 ;
tmp = inet_ntoa(in_addr);
// AssertFatal(tmp ,
// "error in PDN IPv4 address %x",
// in_addr.s_addr);
strcpy(broadcast, tmp);
} else if (IN_CLASSB(in_addr.s_addr)) {
netmask = "255.255.0.0";
in_addr.s_addr = pdn->ip_addr[0] << 24;
in_addr.s_addr |= pdn->ip_addr[1] << 16;
in_addr.s_addr |= 255 << 8;
in_addr.s_addr |= 255 ;
tmp = inet_ntoa(in_addr);
// AssertFatal(tmp ,
// "error in PDN IPv4 address %x",
// in_addr.s_addr);
strcpy(broadcast, tmp);
} else if (IN_CLASSC(in_addr.s_addr)) {
netmask = "255.255.255.0";
in_addr.s_addr = pdn->ip_addr[0] << 24;
in_addr.s_addr |= pdn->ip_addr[1] << 16;
in_addr.s_addr |= pdn->ip_addr[2] << 8;
in_addr.s_addr |= 255 ;
tmp = inet_ntoa(in_addr);
// AssertFatal(tmp ,
// "error in PDN IPv4 address %x",
// in_addr.s_addr);
strcpy(broadcast, tmp);
} else {
netmask = "255.255.255.255";
strcpy(broadcast, ipv4_addr);
}
res = sprintf(command_line,
"ifconfig oip1 %s netmask %s broadcast %s up",
ipv4_addr, netmask, broadcast);
// AssertFatal((res > 0) && (res < 128),
// "error in system command line");
LOG_TRACE(INFO, "ESM-PROC - executing %s ",
command_line);
system(command_line);
break;
case NET_PDN_TYPE_IPV6:
break;
default:
break;
}
}
// AssertFatal(0, "Forced stop in NAS UE");
#endif
}
/* Return the EPS bearer identity of the default EPS bearer
@@ -139,23 +139,26 @@ int encode_activate_default_eps_bearer_context_request(activate_default_eps_bear
if ((encode_result =
encode_eps_quality_of_service(&activate_default_eps_bearer_context_request->epsqos,
0, buffer + encoded, len - encoded)) < 0) //Return in case of error
0, buffer + encoded, len - encoded)) < 0) { //Return in case of error
LOG_TRACE(ERROR, "ESM ENCODE epsqos");
return encode_result;
else
} else
encoded += encode_result;
if ((encode_result =
encode_access_point_name(&activate_default_eps_bearer_context_request->accesspointname,
0, buffer + encoded, len - encoded)) < 0) //Return in case of error
0, buffer + encoded, len - encoded)) < 0) { //Return in case of error
LOG_TRACE(ERROR, "ESM ENCODE accesspointname");
return encode_result;
else
} else
encoded += encode_result;
if ((encode_result =
encode_pdn_address(&activate_default_eps_bearer_context_request->pdnaddress,
0, buffer + encoded, len - encoded)) < 0) //Return in case of error
0, buffer + encoded, len - encoded)) < 0) { //Return in case of error
LOG_TRACE(ERROR, "ESM ENCODE pdnaddress");
return encode_result;
else
} else
encoded += encode_result;
if ((activate_default_eps_bearer_context_request->presencemask & ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REQUEST_TRANSACTION_IDENTIFIER_PRESENT)
@@ -164,10 +167,11 @@ int encode_activate_default_eps_bearer_context_request(activate_default_eps_bear
if ((encode_result =
encode_transaction_identifier(&activate_default_eps_bearer_context_request->transactionidentifier,
ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REQUEST_TRANSACTION_IDENTIFIER_IEI,
buffer + encoded, len - encoded)) < 0)
buffer + encoded, len - encoded)) < 0) {
LOG_TRACE(ERROR, "ESM ENCODE transactionidentifier");
// Return in case of error
return encode_result;
else
} else
encoded += encode_result;
}
@@ -177,10 +181,11 @@ int encode_activate_default_eps_bearer_context_request(activate_default_eps_bear
if ((encode_result =
encode_quality_of_service(&activate_default_eps_bearer_context_request->negotiatedqos,
ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REQUEST_NEGOTIATED_QOS_IEI,
buffer + encoded, len - encoded)) < 0)
buffer + encoded, len - encoded)) < 0) {
LOG_TRACE(ERROR, "ESM ENCODE negotiatedqos");
// Return in case of error
return encode_result;
else
} else
encoded += encode_result;
}
@@ -190,10 +195,11 @@ int encode_activate_default_eps_bearer_context_request(activate_default_eps_bear
if ((encode_result =
encode_llc_service_access_point_identifier(&activate_default_eps_bearer_context_request->negotiatedllcsapi,
ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REQUEST_NEGOTIATED_LLC_SAPI_IEI,
buffer + encoded, len - encoded)) < 0)
buffer + encoded, len - encoded)) < 0) {
LOG_TRACE(ERROR, "ESM ENCODE negotiatedllcsapi");
// Return in case of error
return encode_result;
else
} else
encoded += encode_result;
}
@@ -203,10 +209,11 @@ int encode_activate_default_eps_bearer_context_request(activate_default_eps_bear
if ((encode_result =
encode_radio_priority(&activate_default_eps_bearer_context_request->radiopriority,
ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REQUEST_RADIO_PRIORITY_IEI,
buffer + encoded, len - encoded)) < 0)
buffer + encoded, len - encoded)) < 0) {
LOG_TRACE(ERROR, "ESM ENCODE radiopriority");
// Return in case of error
return encode_result;
else
} else
encoded += encode_result;
}
@@ -216,10 +223,11 @@ int encode_activate_default_eps_bearer_context_request(activate_default_eps_bear
if ((encode_result =
encode_packet_flow_identifier(&activate_default_eps_bearer_context_request->packetflowidentifier,
ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REQUEST_PACKET_FLOW_IDENTIFIER_IEI,
buffer + encoded, len - encoded)) < 0)
buffer + encoded, len - encoded)) < 0) {
LOG_TRACE(ERROR, "ESM ENCODE packetflowidentifier");
// Return in case of error
return encode_result;
else
} else
encoded += encode_result;
}
@@ -229,10 +237,11 @@ int encode_activate_default_eps_bearer_context_request(activate_default_eps_bear
if ((encode_result =
encode_apn_aggregate_maximum_bit_rate(&activate_default_eps_bearer_context_request->apnambr,
ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REQUEST_APNAMBR_IEI, buffer +
encoded, len - encoded)) < 0)
encoded, len - encoded)) < 0) {
LOG_TRACE(ERROR, "ESM ENCODE apnambr");
// Return in case of error
return encode_result;
else
} else
encoded += encode_result;
}
@@ -242,10 +251,11 @@ int encode_activate_default_eps_bearer_context_request(activate_default_eps_bear
if ((encode_result =
encode_esm_cause(&activate_default_eps_bearer_context_request->esmcause,
ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REQUEST_ESM_CAUSE_IEI, buffer
+ encoded, len - encoded)) < 0)
+ encoded, len - encoded)) < 0) {
LOG_TRACE(ERROR, "ESM ENCODE esmcause");
// Return in case of error
return encode_result;
else
} else
encoded += encode_result;
}
@@ -279,13 +289,14 @@ int encode_activate_default_eps_bearer_context_request(activate_default_eps_bear
if ((encode_result =
encode_protocol_configuration_options(&activate_default_eps_bearer_context_request->protocolconfigurationoptions,
ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REQUEST_PROTOCOL_CONFIGURATION_OPTIONS_IEI,
buffer + encoded, len - encoded)) < 0)
buffer + encoded, len - encoded)) < 0) {
LOG_TRACE(ERROR, "ESM ENCODE protocolconfigurationoptions");
// Return in case of error
return encode_result;
else
} else
encoded += encode_result;
}
LOG_TRACE(INFO, "ESM ENCODED activate_default_eps_bearer_context_request");
return encoded;
}
@@ -219,10 +219,12 @@ int esm_msg_encode(ESM_msg *msg, uint8_t *buffer, uint32_t len)
/* First encode the ESM message header */
header_result = _esm_msg_encode_header(&msg->header, buffer, len);
if (header_result < 0) {
LOG_TRACE(ERROR, "ESM-MSG - Failed to encode ESM message header "
"(%d)", header_result);
LOG_FUNC_RETURN(header_result);
LOG_TRACE(ERROR, "ESM-MSG - Failed to encode ESM message header "
"(%d)", header_result);
LOG_FUNC_RETURN(header_result);
}
LOG_TRACE(INFO, "ESM-MSG - Encoded ESM message header "
"(%d)", header_result);
buffer += header_result;
len -= header_result;
@@ -299,6 +301,7 @@ int esm_msg_encode(ESM_msg *msg, uint8_t *buffer, uint32_t len)
LOG_TRACE(ERROR, "ESM-MSG - Unexpected message type: 0x%x",
msg->header.message_type);
encode_result = TLV_ENCODE_WRONG_MESSAGE_TYPE;
break;
}
if (encode_result < 0) {
@@ -390,13 +393,14 @@ static int _esm_msg_encode_header(const esm_msg_header_t *header,
/* Check the buffer length */
if (len < sizeof(esm_msg_header_t)) {
return (TLV_ENCODE_BUFFER_TOO_SHORT);
LOG_TRACE(ERROR, "ESM-MSG - buffer too short");
return (TLV_ENCODE_BUFFER_TOO_SHORT);
}
/* Check the protocol discriminator */
else if (header->protocol_discriminator != EPS_SESSION_MANAGEMENT_MESSAGE) {
LOG_TRACE(ERROR, "ESM-MSG - Unexpected protocol discriminator: 0x%x",
header->protocol_discriminator);
return (TLV_ENCODE_PROTOCOL_NOT_SUPPORTED);
LOG_TRACE(ERROR, "ESM-MSG - Unexpected protocol discriminator: 0x%x",
header->protocol_discriminator);
return (TLV_ENCODE_PROTOCOL_NOT_SUPPORTED);
}
/* Encode the EPS bearer identity and the protocol discriminator */
@@ -29,7 +29,9 @@ Description Defines functions executed at the ESM Service Access
#include "esm_proc.h"
#include "esm_cause.h"
#ifdef NAS_MME
#include "nas_itti_messaging.h"
#endif
#ifdef NAS_UE
#include <stdlib.h> // malloc, free
#include <string.h> // memset
@@ -729,6 +731,7 @@ int esm_recv_pdn_connectivity_request(emm_data_context_t *ctx, int pti, int ebi,
request_type = ESM_PDN_REQUEST_EMERGENCY;
} else {
/* Unkown PDN request type */
LOG_TRACE(ERROR, "ESM-SAP - Invalid PDN request type");
LOG_FUNC_RETURN (ESM_CAUSE_INVALID_MANDATORY_INFO);
}
/* Get the value of the PDN type indicator */
@@ -740,6 +743,7 @@ int esm_recv_pdn_connectivity_request(emm_data_context_t *ctx, int pti, int ebi,
esm_data->pdn_type = ESM_PDN_TYPE_IPV4V6;
} else {
/* Unkown PDN type */
LOG_TRACE(ERROR, "ESM-SAP - Invalid PDN type");
LOG_FUNC_RETURN (ESM_CAUSE_UNKNOWN_PDN_TYPE);
}
@@ -765,7 +769,7 @@ int esm_recv_pdn_connectivity_request(emm_data_context_t *ctx, int pti, int ebi,
*/
//TODO: rc = esm_proc_information_request();
}
#if defined(ORIGINAL_CODE)
/* Execute the PDN connectivity procedure requested by the UE */
int pid = esm_proc_pdn_connectivity_request(ctx, pti, request_type,
&esm_data->apn,
@@ -773,6 +777,7 @@ int esm_recv_pdn_connectivity_request(emm_data_context_t *ctx, int pti, int ebi,
&esm_data->pdn_addr,
&esm_data->qos,
&esm_cause);
if (pid != RETURNerror) {
/* Create local default EPS bearer context */
int rc = esm_proc_default_eps_bearer_context(ctx, pid, new_ebi,
@@ -781,7 +786,17 @@ int esm_recv_pdn_connectivity_request(emm_data_context_t *ctx, int pti, int ebi,
esm_cause = ESM_CAUSE_SUCCESS;
}
}
#else
int is_emergency = (request_type == ESM_PDN_REQUEST_EMERGENCY);
nas_itti_pdn_connectivity_req(
pti,
ctx->ueid,
ctx->imsi,
esm_data,
request_type);
esm_cause = ESM_CAUSE_SUCCESS;
#endif
/* Return the ESM cause value */
LOG_FUNC_RETURN (esm_cause);
}
@@ -756,6 +756,8 @@ static int _esm_sap_recv(int msg_type, int is_standalone,
esm_proc_data_t data;
memset(&data, 0, sizeof(esm_proc_data_t));
LOG_TRACE(DEBUG, "ESM-SAP - PDN_CONNECTIVITY_REQUEST pti %u ebi %u", pti, ebi);
/*
* Process PDN connectivity request message received from the UE
*/
@@ -773,6 +775,7 @@ static int _esm_sap_recv(int msg_type, int is_standalone,
/* No ESM status message should be returned */
esm_cause = ESM_CAUSE_SUCCESS;
} else {
#if defined(ORIGINAL_CODE)
/* Setup PDN type */
int pdn_type = -1;
if (data.pdn_type == ESM_PDN_TYPE_IPV4) {
@@ -842,14 +845,20 @@ static int _esm_sap_recv(int msg_type, int is_standalone,
pti, ebi,
&esm_msg.activate_dedicated_eps_bearer_context_request,
ebi, &qos, &pkfs, 2);
#endif
esm_procedure = esm_proc_default_eps_bearer_context_request;
#else
esm_cause = ESM_CAUSE_SUCCESS;
#endif
/* Setup the callback function used to send default EPS bearer
* context request message onto the network */
esm_procedure = esm_proc_default_eps_bearer_context_request;
//esm_procedure = esm_proc_default_eps_bearer_context_request;
}
break;
}
case PDN_DISCONNECT_REQUEST:
/*
* Process PDN disconnect request message received from the UE
@@ -541,6 +541,12 @@ int esm_send_activate_default_eps_bearer_context_request(int pti, int ebi,
/* Mandatory - EPS QoS */
msg->epsqos = *qos;
if ((apn == NULL) || ((apn != NULL) && (apn->value == NULL))) {
LOG_TRACE(WARNING, "ESM-SAP - apn is NULL!");
}
LOG_TRACE(INFO, "ESM-SAP - apn is %s", apn->value);
/* Mandatory - Access Point Name */
msg->accesspointname.accesspointnamevalue = *apn;
+24 -2
View File
@@ -1490,16 +1490,38 @@ int nas_proc_deregister_ue(UInt32_t ue_id)
LOG_FUNC_RETURN (rc);
}
int nas_proc_bearer_param(nas_bearer_param_t *nas_bearer_param_pP)
int nas_proc_pdn_connectivity_res(emm_cn_pdn_res_t *emm_cn_pdn_res)
{
int rc = RETURNerror;
emm_sap_t emm_sap;
LOG_FUNC_IN;
rc = RETURNok;
emm_sap.primitive = EMMCN_PDN_CONNECTIVITY_RES;
emm_sap.u.emm_cn.u.emm_cn_pdn_res = emm_cn_pdn_res;
rc = emm_sap_send(&emm_sap);
LOG_FUNC_RETURN (rc);
}
int nas_proc_pdn_connectivity_fail(emm_cn_pdn_fail_t *emm_cn_pdn_fail)
{
int rc = RETURNerror;
emm_sap_t emm_sap;
LOG_FUNC_IN;
emm_sap.primitive = EMMCN_PDN_CONNECTIVITY_FAIL;
emm_sap.u.emm_cn.u.emm_cn_pdn_fail = emm_cn_pdn_fail;
rc = emm_sap_send(&emm_sap);
LOG_FUNC_RETURN (rc);
}
# endif
#endif // NAS_MME
+2 -1
View File
@@ -138,7 +138,8 @@ int nas_proc_ul_transfer_ind(UInt32_t ueid, const Byte_t *data, UInt32_t len);
int nas_proc_auth_param_res(emm_cn_auth_res_t *emm_cn_auth_res);
int nas_proc_auth_param_fail(emm_cn_auth_fail_t *emm_cn_auth_fail);
int nas_proc_deregister_ue(UInt32_t ue_id);
int nas_proc_bearer_param(nas_bearer_param_t *nas_bearer_param_pP);
int nas_proc_pdn_connectivity_res(nas_pdn_connectivity_rsp_t *nas_pdn_connectivity_rsp);
int nas_proc_pdn_connectivity_fail(nas_pdn_connectivity_fail_t *nas_pdn_connectivity_fail);
#endif
#endif /* __NAS_PROC_H__*/
@@ -6,6 +6,32 @@
#include "TLVDecoder.h"
#include "OctetString.h"
OctetString* dup_octet_string(OctetString *octetstring)
{
OctetString *os_p = NULL;
if (octetstring) {
os_p = calloc(1,sizeof(OctetString));
os_p->length = octetstring->length;
os_p->value = malloc(octetstring->length+1);
memcpy(os_p->value, octetstring->value, octetstring->length);
os_p->value[octetstring->length] = '\0';
}
return os_p;
}
void free_octet_string(OctetString *octetstring)
{
if (octetstring) {
if (octetstring->value) free(octetstring->value);
octetstring->value = NULL;
octetstring->length = 0;
free(octetstring);
}
}
int encode_octet_string(OctetString *octetstring, uint8_t *buffer, uint32_t buflen)
{
CHECK_PDU_POINTER_AND_LENGTH_ENCODER(buffer, octetstring->length, buflen);
@@ -1,4 +1,5 @@
#include <stdint.h>
#include <assert.h>
#ifndef OCTET_STRING_H_
#define OCTET_STRING_H_
@@ -7,6 +8,35 @@ typedef struct OctetString_tag {
uint32_t length;
uint8_t *value;
} OctetString;
#define FREE_OCTET_STRING(oCTETsTRING) \
do { \
if ((oCTETsTRING).value != NULL) { \
free((oCTETsTRING).value); \
(oCTETsTRING).value = NULL; \
} \
(oCTETsTRING).length = 0; \
} while (0);
#define DUP_OCTET_STRING(oCTETsTRINGoRIG,oCTETsTRINGcOPY) \
do { \
if ((oCTETsTRINGoRIG).value == NULL) { \
(oCTETsTRINGcOPY).length = 0; \
(oCTETsTRINGcOPY).value = NULL; \
break; \
} \
(oCTETsTRINGcOPY).length = strlen((const char*)(oCTETsTRINGoRIG).value);\
assert((oCTETsTRINGoRIG).length == (oCTETsTRINGcOPY).length); \
(oCTETsTRINGcOPY).value = malloc((oCTETsTRINGoRIG).length+1); \
memcpy((oCTETsTRINGcOPY).value, \
(oCTETsTRINGoRIG).value, \
(oCTETsTRINGoRIG).length); \
(oCTETsTRINGcOPY).value[(oCTETsTRINGoRIG).length] = '\0'; \
} while (0);
OctetString* dup_octet_string(OctetString*octetstring);
void free_octet_string(OctetString *octetstring);
int encode_octet_string(OctetString *octetstring, uint8_t *buffer, uint32_t len);
+3 -2
View File
@@ -83,7 +83,7 @@ int main (int argc, const char* argv[])
if (argc != 2) {
fprintf(stderr, "Invalid parameter\n");
_display_usage(argv[0]);
exit(EXIT_FAILURE);
exit(EXIT_FAILURE);
}
else if ( (strcmp(argv[1], "--gen") == 0) ||
(strcmp(argv[1], "-g") == 0) ) {
@@ -272,7 +272,8 @@ static void _gen_emm_data(emm_nvdata_t* data)
data->imsi.u.num.digit3 = 8; // MCC digit 3
data->imsi.u.num.digit4 = 1; // MNC digit 1
data->imsi.u.num.digit5 = 0; // MNC digit 2
data->imsi.u.num.digit6 = 0xF; // MNC digit 3
data->imsi.u.num.digit6 = 0; // MNC digit 3
//LG data->imsi.u.num.digit6 = 0xF; // MNC digit 3
data->imsi.u.num.digit7 = 0;
data->imsi.u.num.digit8 = 0;
data->imsi.u.num.digit9 = 0;
+12 -6
View File
@@ -86,7 +86,7 @@ int main (int argc, const char* argv[])
if (argc != 2) {
fprintf(stderr, "Invalid parameter\n");
_display_usage(argv[0]);
exit(EXIT_FAILURE);
exit(EXIT_FAILURE);
}
else if ( (strcmp(argv[1], "--gen") == 0) ||
(strcmp(argv[1], "-g") == 0) ) {
@@ -121,7 +121,8 @@ int main (int argc, const char* argv[])
usim_data.imsi.u.num.digit3 = 8; // MCC digit 3
usim_data.imsi.u.num.digit4 = 1; // MNC digit 1
usim_data.imsi.u.num.digit5 = 0; // MNC digit 2
usim_data.imsi.u.num.digit6 = 0b1111; // MNC digit 3
// LG usim_data.imsi.u.num.digit6 = 0b1111; // MNC digit 3
usim_data.imsi.u.num.digit6 = 0; // MNC digit 3
usim_data.imsi.u.num.digit7 = 0;
usim_data.imsi.u.num.digit8 = 0;
usim_data.imsi.u.num.digit9 = 0;
@@ -298,7 +299,12 @@ int main (int argc, const char* argv[])
usim_data.nasconfig.NMO_I_Behaviour.value[0] = 0x00;
usim_data.nasconfig.AttachWithImsi.type = USIM_ATTACH_WITH_IMSI_TAG;
usim_data.nasconfig.AttachWithImsi.length = 1;
#undefine START_WITH_GUTI
#if defined(START_WITH_GUTI)
usim_data.nasconfig.AttachWithImsi.value[0] = 0x00;
#else
usim_data.nasconfig.AttachWithImsi.value[0] = 0x01;
#endif
usim_data.nasconfig.MinimumPeriodicSearchTimer.type = USIM_MINIMUM_PERIODIC_SEARCH_TIMER_TAG;
usim_data.nasconfig.MinimumPeriodicSearchTimer.length = 1;
usim_data.nasconfig.MinimumPeriodicSearchTimer.value[0] = 0x00;
@@ -491,7 +497,7 @@ static void _display_usim_data(const usim_data_t* data)
printf("\tLAI\t: PLMN = "); PRINT_PLMN(data->loci.lai.plmn);
printf(", LAC = 0x%.2x\n", data->loci.lai.lac);
printf("\tstatus\t= %d\n\n", data->loci.status);
printf("PSLOCI:\n");
printf("\tP-TMSI = 0x%.4x\n", data->psloci.p_tmsi);
printf("\tsignature = 0x%x 0x%x 0x%x\n",
@@ -502,7 +508,7 @@ static void _display_usim_data(const usim_data_t* data)
printf(", LAC = 0x%.2x, RAC = 0x%.1x\n",
data->psloci.rai.lac, data->psloci.rai.rac);
printf("\tstatus\t= %d\n\n", data->psloci.status);
printf("EPSLOCI:\n");
printf("\tGUTI\t: GUMMEI\t: (PLMN = ");
PRINT_PLMN(data->epsloci.guti.gummei.plmn);
@@ -511,11 +517,11 @@ static void _display_usim_data(const usim_data_t* data)
data->epsloci.guti.gummei.MMEcode);
printf(", M-TMSI = 0x%.4x\n", data->epsloci.guti.m_tmsi);
printf("\tTAI\t: PLMN = ");
PRINT_PLMN(data->epsloci.tai.plmn);
PRINT_PLMN(data->epsloci.tai.plmn);
printf(", TAC = 0x%.2x\n",
data->epsloci.tai.tac);
printf("\tstatus\t= %d\n\n", data->epsloci.status);
printf("NASCONFIG:\n");
printf("\tNAS_SignallingPriority\t\t: 0x%.2x\n",
data->nasconfig.NAS_SignallingPriority.value[0]);
+123 -29
View File
@@ -32,47 +32,136 @@
#include <stdint.h>
#include <ctype.h>
#include "assertions.h"
#include "intertask_interface.h"
#include "esm_proc.h"
#ifndef NAS_ITTI_MESSAGING_H_
#define NAS_ITTI_MESSAGING_H_
# if ((defined(EPC_BUILD) && defined(NAS_MME)) || (defined(ENABLE_NAS_UE_LOGGING) && defined(UE_BUILD) && defined(NAS_UE)))
int nas_itti_plain_msg(const char *buffer, const nas_message_t *msg, const int length, const int instance);
int nas_itti_plain_msg(
const char *buffer,
const nas_message_t *msg,
const int lengthP,
const int instance);
int nas_itti_protected_msg(const char *buffer, const nas_message_t *msg, const int length, const int instance);
int nas_itti_protected_msg(
const char *buffer,
const nas_message_t *msg,
const int lengthP,
const int instance);
# endif
# if defined(EPC_BUILD) && defined(NAS_MME)
#include "conversions.h"
int nas_itti_dl_data_req(const uint32_t ue_id, void *const data,
const uint32_t length);
int nas_itti_dl_data_req(
const uint32_t ue_idP,
void *const data_pP,
const uint32_t lengthP);
static inline void nas_itti_establish_cnf(const uint32_t ue_id,
const nas_error_code_t error_code, void *const data,
const uint32_t length)
static inline void nas_itti_pdn_connectivity_req(
int ptiP,
unsigned int ueidP,
const imsi_t *const imsi_pP,
esm_proc_data_t *proc_data_pP,
esm_proc_pdn_request_t request_typeP)
{
MessageDef *message_p;
MessageDef *message_p = NULL;
message_p = itti_alloc_new_message(TASK_NAS_MME, NAS_CONNECTION_ESTABLISHMENT_CNF);
AssertFatal(imsi_pP != NULL, "imsi_pP param is NULL");
AssertFatal(proc_data_pP != NULL, "proc_data_pP param is NULL");
NAS_CONNECTION_ESTABLISHMENT_CNF(message_p).UEid = ue_id;
NAS_CONNECTION_ESTABLISHMENT_CNF(message_p).errCode = error_code;
NAS_CONNECTION_ESTABLISHMENT_CNF(message_p).nasMsg.data = data;
NAS_CONNECTION_ESTABLISHMENT_CNF(message_p).nasMsg.length = length;
itti_send_msg_to_task(TASK_S1AP, INSTANCE_DEFAULT, message_p);
message_p = itti_alloc_new_message(TASK_NAS_MME, NAS_PDN_CONNECTIVITY_REQ);
memset(&message_p->ittiMsg.nas_pdn_connectivity_req,
0,
sizeof(nas_pdn_connectivity_req_t));
hexa_to_ascii((uint8_t *)imsi_pP->u.value,
NAS_PDN_CONNECTIVITY_REQ(message_p).imsi,
8);
NAS_PDN_CONNECTIVITY_REQ(message_p).pti = ptiP;
NAS_PDN_CONNECTIVITY_REQ(message_p).ue_id = ueidP;
NAS_PDN_CONNECTIVITY_REQ(message_p).imsi[15] = '\0';
if (isdigit(NAS_PDN_CONNECTIVITY_REQ(message_p).imsi[14])) {
NAS_PDN_CONNECTIVITY_REQ(message_p).imsi_length = 15;
} else {
NAS_PDN_CONNECTIVITY_REQ(message_p).imsi_length = 14;
NAS_PDN_CONNECTIVITY_REQ(message_p).imsi[14] = '\0';
}
DUP_OCTET_STRING(proc_data_pP->apn, NAS_PDN_CONNECTIVITY_REQ(message_p).apn);
DUP_OCTET_STRING(proc_data_pP->pdn_addr, NAS_PDN_CONNECTIVITY_REQ(message_p).pdn_addr);
switch (proc_data_pP->pdn_type) {
case ESM_PDN_TYPE_IPV4:
NAS_PDN_CONNECTIVITY_REQ(message_p).pdn_type = IPv4;
break;
case ESM_PDN_TYPE_IPV6:
NAS_PDN_CONNECTIVITY_REQ(message_p).pdn_type = IPv6;
break;
case ESM_PDN_TYPE_IPV4V6:
NAS_PDN_CONNECTIVITY_REQ(message_p).pdn_type = IPv4_AND_v6;
break;
default:
NAS_PDN_CONNECTIVITY_REQ(message_p).pdn_type = IPv4;
break;
}
// not efficient but be careful about "typedef network_qos_t esm_proc_qos_t;"
NAS_PDN_CONNECTIVITY_REQ(message_p).qos.gbrUL = proc_data_pP->qos.gbrUL;
NAS_PDN_CONNECTIVITY_REQ(message_p).qos.gbrDL = proc_data_pP->qos.gbrDL;
NAS_PDN_CONNECTIVITY_REQ(message_p).qos.mbrUL = proc_data_pP->qos.mbrUL;
NAS_PDN_CONNECTIVITY_REQ(message_p).qos.mbrDL = proc_data_pP->qos.mbrDL;
NAS_PDN_CONNECTIVITY_REQ(message_p).qos.qci = proc_data_pP->qos.qci;
NAS_PDN_CONNECTIVITY_REQ(message_p).proc_data = proc_data_pP;
NAS_PDN_CONNECTIVITY_REQ(message_p).request_type = request_typeP;
itti_send_msg_to_task(TASK_MME_APP, INSTANCE_DEFAULT, message_p);
}
static inline void nas_itti_auth_info_req(const uint32_t ue_id,
const imsi_t *const imsi, uint8_t initial_req, const uint8_t *auts)
static inline void nas_itti_establish_cnf(
const uint32_t ue_idP,
const nas_error_code_t error_codeP,
void *const data_pP,
const uint32_t lengthP)
{
MessageDef *message_p = NULL;
message_p = itti_alloc_new_message(TASK_NAS_MME, NAS_CONNECTION_ESTABLISHMENT_CNF);
memset(&message_p->ittiMsg.nas_conn_est_cnf,
0,
sizeof(nas_conn_est_cnf_t));
NAS_CONNECTION_ESTABLISHMENT_CNF(message_p).UEid = ue_idP;
NAS_CONNECTION_ESTABLISHMENT_CNF(message_p).errCode = error_codeP;
NAS_CONNECTION_ESTABLISHMENT_CNF(message_p).nasMsg.data = data_pP;
NAS_CONNECTION_ESTABLISHMENT_CNF(message_p).nasMsg.length = lengthP;
itti_send_msg_to_task(TASK_MME_APP, INSTANCE_DEFAULT, message_p);
}
static inline void nas_itti_auth_info_req(
const uint32_t ue_idP,
const imsi_t *const imsi_pP,
uint8_t initial_reqP,
const uint8_t *auts_pP)
{
MessageDef *message_p;
message_p = itti_alloc_new_message(TASK_NAS_MME, NAS_AUTHENTICATION_PARAM_REQ);
memset(&message_p->ittiMsg.nas_auth_param_req,
0,
sizeof(nas_auth_param_req_t));
hexa_to_ascii((uint8_t *)imsi->u.value,
hexa_to_ascii((uint8_t *)imsi_pP->u.value,
NAS_AUTHENTICATION_PARAM_REQ(message_p).imsi, 8);
NAS_AUTHENTICATION_PARAM_REQ(message_p).imsi[15] = '\0';
@@ -83,13 +172,13 @@ static inline void nas_itti_auth_info_req(const uint32_t ue_id,
NAS_AUTHENTICATION_PARAM_REQ(message_p).imsi_length = 14;
NAS_AUTHENTICATION_PARAM_REQ(message_p).imsi[14] = '\0';
}
NAS_AUTHENTICATION_PARAM_REQ(message_p).initial_req = initial_req;
NAS_AUTHENTICATION_PARAM_REQ(message_p).ue_id = ue_id;
NAS_AUTHENTICATION_PARAM_REQ(message_p).initial_req = initial_reqP;
NAS_AUTHENTICATION_PARAM_REQ(message_p).ue_id = ue_idP;
/* Re-synchronisation */
if (auts != NULL) {
if (auts_pP != NULL) {
NAS_AUTHENTICATION_PARAM_REQ(message_p).re_synchronization = 1;
memcpy(NAS_AUTHENTICATION_PARAM_REQ(message_p).auts, auts, AUTS_LENGTH);
memcpy(NAS_AUTHENTICATION_PARAM_REQ(message_p).auts, auts_pP, AUTS_LENGTH);
} else {
NAS_AUTHENTICATION_PARAM_REQ(message_p).re_synchronization = 0;
memset(NAS_AUTHENTICATION_PARAM_REQ(message_p).auts, 0, AUTS_LENGTH);
@@ -98,14 +187,19 @@ static inline void nas_itti_auth_info_req(const uint32_t ue_id,
itti_send_msg_to_task(TASK_MME_APP, INSTANCE_DEFAULT, message_p);
}
static inline void nas_itti_establish_rej(const uint32_t ue_id,
const imsi_t *const imsi, uint8_t initial_req)
static inline void nas_itti_establish_rej(
const uint32_t ue_idP,
const imsi_t *const imsi_pP
, uint8_t initial_reqP)
{
MessageDef *message_p;
message_p = itti_alloc_new_message(TASK_NAS_MME, NAS_AUTHENTICATION_PARAM_REQ);
memset(&message_p->ittiMsg.nas_auth_param_req,
0,
sizeof(nas_auth_param_req_t));
hexa_to_ascii((uint8_t *)imsi->u.value,
hexa_to_ascii((uint8_t *)imsi_pP->u.value,
NAS_AUTHENTICATION_PARAM_REQ(message_p).imsi, 8);
NAS_AUTHENTICATION_PARAM_REQ(message_p).imsi[15] = '\0';
@@ -114,10 +208,10 @@ static inline void nas_itti_establish_rej(const uint32_t ue_id,
NAS_AUTHENTICATION_PARAM_REQ(message_p).imsi_length = 15;
} else {
NAS_AUTHENTICATION_PARAM_REQ(message_p).imsi_length = 14;
NAS_AUTHENTICATION_PARAM_REQ(message_p).imsi[14] = '\0';
NAS_AUTHENTICATION_PARAM_REQ(message_p).imsi[14] = '\0';
}
NAS_AUTHENTICATION_PARAM_REQ(message_p).initial_req = initial_req;
NAS_AUTHENTICATION_PARAM_REQ(message_p).ue_id = ue_id;
NAS_AUTHENTICATION_PARAM_REQ(message_p).initial_req = initial_reqP;
NAS_AUTHENTICATION_PARAM_REQ(message_p).ue_id = ue_idP;
itti_send_msg_to_task(TASK_MME_APP, INSTANCE_DEFAULT, message_p);
}
@@ -126,9 +220,9 @@ static inline void nas_itti_establish_rej(const uint32_t ue_id,
# if defined(UE_BUILD) && defined(NAS_UE)
int nas_itti_cell_info_req(const plmn_t plmnID, const Byte_t rat);
int nas_itti_nas_establish_req(as_cause_t cause, as_call_type_t type, as_stmsi_t s_tmsi, plmn_t plmnID, Byte_t *data, UInt32_t length);
int nas_itti_nas_establish_req(as_cause_t cause, as_call_type_t type, as_stmsi_t s_tmsi, plmn_t plmnID, Byte_t *data_pP, UInt32_t lengthP);
int nas_itti_ul_data_req(const uint32_t ue_id, void *const data, const uint32_t length);
int nas_itti_ul_data_req(const uint32_t ue_idP, void *const data_pP, const uint32_t lengthP);
int nas_itti_rab_establish_rsp(const as_stmsi_t s_tmsi, const as_rab_id_t rabID, const nas_error_code_t errCode);
# endif
+9 -1
View File
@@ -134,6 +134,14 @@ next_message:
nas_proc_auth_param_fail(&NAS_AUTHENTICATION_PARAM_FAIL(received_message_p));
} break;
#endif
case NAS_PDN_CONNECTIVITY_RSP: {
nas_proc_pdn_connectivity_res(&NAS_PDN_CONNECTIVITY_RSP(received_message_p));
} break;
case NAS_PDN_CONNECTIVITY_FAIL: {
nas_proc_pdn_connectivity_fail(&NAS_PDN_CONNECTIVITY_FAIL(received_message_p));
} break;
case TIMER_HAS_EXPIRED: {
#if !defined(DISABLE_USE_NAS)
@@ -180,7 +188,7 @@ int nas_init(mme_config_t *mme_config_p)
NAS_DEBUG("Initializing NAS task interface\n");
#if !defined(DISABLE_USE_NAS)
nas_log_init(0x2F);
nas_log_init(0x3F);
nas_network_initialize(mme_config_p);
#endif
+2 -2
View File
@@ -1,7 +1,7 @@
## MySQL mandatory options
MYSQL_server = "127.0.0.1";
MYSQL_user = "hssadmin";
MYSQL_pass = "admin";
MYSQL_user = "root";
MYSQL_pass = "linux";
MYSQL_db = "oai_db";
## Freediameter options
+4 -4
View File
@@ -4,9 +4,9 @@
Identity = "hss.eur";
# TLS configuration (see previous section)
TLS_Cred = "/homes/roux/lte-epc/openair3/OPENAIRHSS/conf/hss.cert.pem",
"/homes/roux/lte-epc/openair3/OPENAIRHSS/conf/hss.key.pem";
TLS_CA = "/homes/roux/lte-epc/openair3/OPENAIRHSS/conf/cacert.pem";
TLS_Cred = "/usr/local/src/trunk_co/openair-cn/OPENAIRHSS/conf/hss.cert.pem",
"/usr/local/src/trunk_co/openair-cn/OPENAIRHSS/conf/hss.key.pem";
TLS_CA = "/usr/local/src/trunk_co/openair-cn/OPENAIRHSS/conf/cacert.pem";
# Disable use of TCP protocol (only listen and connect in SCTP)
# Default : TCP enabled
@@ -32,7 +32,7 @@ AppServThreads = 4;
#LoadExtension = "rt_default.fdx" : "rtd.conf";
# Uncomment (and create acl.conf) to allow incoming connections from other peers.
#LoadExtension = "acl_wl.fdx" : "/homes/roux/lte-epc/openair3/OPENAIRHSS/conf/acl.conf";
#LoadExtension = "acl_wl.fdx" : "/usr/local/src/trunk_co/openair-cn/OPENAIRHSS/conf/acl.conf";
# Uncomment to display periodic state information
#LoadExtension = "dbg_monitor.fdx";
+2 -1
View File
@@ -156,7 +156,8 @@ int s11_mme_handle_create_session_response(NwGtpv2cStackHandleT *stack_p,
if (rc != NW_OK)
{
/* TODO: handle this case */
free(message_p);
itti_free(ITTI_MSG_ORIGIN_ID(message_p), message_p);
message_p = NULL;
rc = nwGtpv2cMsgParserDelete(*stack_p, pMsgParser);
DevAssert(NW_OK == rc);
+1 -1
View File
@@ -215,7 +215,7 @@ static void *s11_mme_thread(void *args)
}
break;
}
free(received_message_p);
itti_free(ITTI_MSG_ORIGIN_ID(received_message_p), received_message_p);
received_message_p = NULL;
}
return NULL;
+1 -1
View File
@@ -241,7 +241,7 @@ static void *s11_sgw_thread(void *args)
}
break;
}
free(received_message_p);
itti_free(ITTI_MSG_ORIGIN_ID(received_message_p), received_message_p);
received_message_p = NULL;
}
return NULL;
+2 -1
View File
@@ -142,7 +142,8 @@ int s11_sgw_handle_modify_bearer_request(NwGtpv2cStackHandleT *stack_p,
rc = nwGtpv2cProcessUlpReq(*stack_p, &ulp_req);
DevAssert(NW_OK == rc);
free(message_p);
itti_free(ITTI_MSG_ORIGIN_ID(message_p), message_p);
message_p = NULL;
rc = nwGtpv2cMsgParserDelete(*stack_p, pMsgParser);
DevAssert(NW_OK == rc);
+4 -2
View File
@@ -227,7 +227,8 @@ int s11_sgw_handle_create_session_request(NwGtpv2cStackHandleT *stack_p,
rc = nwGtpv2cProcessUlpReq(*stack_p, &ulp_req);
DevAssert(NW_OK == rc);
free(message_p);
itti_free(ITTI_MSG_ORIGIN_ID(message_p), message_p);
message_p = NULL;
rc = nwGtpv2cMsgParserDelete(*stack_p, pMsgParser);
DevAssert(NW_OK == rc);
@@ -427,7 +428,8 @@ int s11_sgw_handle_delete_session_request(NwGtpv2cStackHandleT *stack_p,
rc = nwGtpv2cProcessUlpReq(*stack_p, &ulp_req);
DevAssert(NW_OK == rc);
free(message_p);
itti_free(ITTI_MSG_ORIGIN_ID(message_p), message_p);
message_p = NULL;
rc = nwGtpv2cMsgParserDelete(*stack_p, pMsgParser);
DevAssert(NW_OK == rc);
+10 -8
View File
@@ -72,9 +72,9 @@ void s1ap_eNB_handle_sctp_association_resp(instance_t instance, sctp_new_associa
uint32_t s1ap_generate_eNB_id(void)
{
char *out;
char hostname[50];
int ret;
char *out;
char hostname[50];
int ret;
uint32_t eNB_id;
/* Retrieve the host name */
@@ -93,9 +93,9 @@ static void s1ap_eNB_register_mme(s1ap_eNB_instance_t *instance_p,
net_ip_address_t *mme_ip_address,
net_ip_address_t *local_ip_addr)
{
MessageDef *message_p;
sctp_new_association_req_t *sctp_new_association_req_p;
s1ap_eNB_mme_data_t *s1ap_mme_data_p;
MessageDef *message_p = NULL;
sctp_new_association_req_t *sctp_new_association_req_p = NULL;
s1ap_eNB_mme_data_t *s1ap_mme_data_p = NULL;
DevAssert(instance_p != NULL);
DevAssert(mme_ip_address != NULL);
@@ -107,10 +107,12 @@ static void s1ap_eNB_register_mme(s1ap_eNB_instance_t *instance_p,
sctp_new_association_req_p->port = S1AP_PORT_NUMBER;
sctp_new_association_req_p->ppid = S1AP_SCTP_PPID;
memcpy(&sctp_new_association_req_p->remote_address, mme_ip_address,
memcpy(&sctp_new_association_req_p->remote_address,
mme_ip_address,
sizeof(*mme_ip_address));
memcpy(&sctp_new_association_req_p->local_address, local_ip_addr,
memcpy(&sctp_new_association_req_p->local_address,
local_ip_addr,
sizeof(*local_ip_addr));
/* Create new MME descriptor */
+2 -2
View File
@@ -82,8 +82,8 @@ static int s1ap_eNB_decode_initiating_message(s1ap_message *message,
default:
S1AP_ERROR("Unknown procedure ID (%d) for initiating message\n",
(int)initiating_p->procedureCode);
//AssertFatal( 0 , "Unknown procedure ID (%d) for initiating message\n",
// (int)initiating_p->procedureCode);
AssertFatal( 0 , "Unknown procedure ID (%d) for initiating message\n",
(int)initiating_p->procedureCode);
return -1;
}
+3 -2
View File
@@ -454,8 +454,8 @@ int s1ap_eNB_handle_initial_context_request(uint32_t assoc_id,
S1AP_INITIAL_CONTEXT_SETUP_REQ(message_p).nb_of_e_rabs =
initialContextSetupRequest_p->e_RABToBeSetupListCtxtSUReq.s1ap_E_RABToBeSetupItemCtxtSUReq.count;
S1AP_INITIAL_CONTEXT_SETUP_REQ(message_p).ue_ambr.br_ul = initialContextSetupRequest_p->uEaggregateMaximumBitrate.uEaggregateMaximumBitRateUL;
S1AP_INITIAL_CONTEXT_SETUP_REQ(message_p).ue_ambr.br_dl = initialContextSetupRequest_p->uEaggregateMaximumBitrate.uEaggregateMaximumBitRateDL;
S1AP_INITIAL_CONTEXT_SETUP_REQ(message_p).ue_ambr.br_ul = 64;// TO DO(bitrate_t)(initialContextSetupRequest_p->uEaggregateMaximumBitrate.uEaggregateMaximumBitRateUL);
S1AP_INITIAL_CONTEXT_SETUP_REQ(message_p).ue_ambr.br_dl = 1024;//(bitrate_t)(initialContextSetupRequest_p->uEaggregateMaximumBitrate.uEaggregateMaximumBitRateDL);
S1AP_INITIAL_CONTEXT_SETUP_REQ(message_p).security_capabilities.encryption_algorithms =
BIT_STRING_to_uint16(&initialContextSetupRequest_p->ueSecurityCapabilities.encryptionAlgorithms);
@@ -473,6 +473,7 @@ int s1ap_eNB_handle_initial_context_request(uint32_t assoc_id,
item_p = (S1ap_E_RABToBeSetupItemCtxtSUReq_t *)initialContextSetupRequest_p->e_RABToBeSetupListCtxtSUReq.s1ap_E_RABToBeSetupItemCtxtSUReq.array[i];
S1AP_INITIAL_CONTEXT_SETUP_REQ(message_p).e_rab_param[i].e_rab_id = item_p->e_RAB_ID;
if (item_p->nAS_PDU != NULL) {
/* Only copy NAS pdu if present */
S1AP_INITIAL_CONTEXT_SETUP_REQ(message_p).e_rab_param[i].nas_pdu.length = item_p->nAS_PDU->size;
+25 -19
View File
@@ -52,16 +52,16 @@
int s1ap_eNB_handle_nas_first_req(
instance_t instance, s1ap_nas_first_req_t *s1ap_nas_first_req_p)
{
s1ap_eNB_instance_t *instance_p;
s1ap_eNB_instance_t *instance_p = NULL;
struct s1ap_eNB_mme_data_s *mme_desc_p = NULL;
struct s1ap_eNB_ue_context_s *ue_desc_p;
struct s1ap_eNB_ue_context_s *ue_desc_p = NULL;
s1ap_message message;
S1ap_InitialUEMessageIEs_t *initial_ue_message_p;
S1ap_InitialUEMessageIEs_t *initial_ue_message_p = NULL;
uint8_t *buffer;
uint32_t length;
uint8_t *buffer = NULL;
uint32_t length = 0;
DevAssert(s1ap_nas_first_req_p != NULL);
@@ -134,7 +134,9 @@ int s1ap_eNB_handle_nas_first_req(
if ((collision_p = RB_INSERT(s1ap_ue_map, &instance_p->s1ap_ue_head, ue_desc_p))
== NULL)
{
S1AP_DEBUG("Found usable eNB_ue_s1ap_id: 0x%06x\n", ue_desc_p->eNB_ue_s1ap_id);
S1AP_DEBUG("Found usable eNB_ue_s1ap_id: 0x%06x %d(10)\n",
ue_desc_p->eNB_ue_s1ap_id,
ue_desc_p->eNB_ue_s1ap_id);
/* Break the loop as the id is not already used by another UE */
break;
}
@@ -151,6 +153,7 @@ int s1ap_eNB_handle_nas_first_req(
initial_ue_message_p->rrC_Establishment_Cause = s1ap_nas_first_req_p->establishment_cause;
if (s1ap_nas_first_req_p->ue_identity.presenceMask & UE_IDENTITIES_s_tmsi) {
S1AP_DEBUG("S_TMSI_PRESENT");
initial_ue_message_p->presenceMask |= S1AP_INITIALUEMESSAGEIES_S_TMSI_PRESENT;
MME_CODE_TO_OCTET_STRING(s1ap_nas_first_req_p->ue_identity.s_tmsi.mme_code,
@@ -159,6 +162,7 @@ int s1ap_eNB_handle_nas_first_req(
&initial_ue_message_p->s_tmsi.m_TMSI);
}
if (s1ap_nas_first_req_p->ue_identity.presenceMask & UE_IDENTITIES_gummei) {
S1AP_DEBUG("GUMMEI_ID_PRESENT");
initial_ue_message_p->presenceMask |= S1AP_INITIALUEMESSAGEIES_GUMMEI_ID_PRESENT;
MCC_MNC_TO_PLMNID(
@@ -210,15 +214,15 @@ int s1ap_eNB_handle_nas_first_req(
return 0;
}
int s1ap_eNB_handle_nas_downlink(uint32_t assoc_id,
uint32_t stream,
struct s1ap_message_s *message_p)
int s1ap_eNB_handle_nas_downlink(const uint32_t assoc_id,
const uint32_t stream,
const struct s1ap_message_s *const message_p)
{
S1ap_DownlinkNASTransportIEs_t *downlink_NAS_transport_p;
S1ap_DownlinkNASTransportIEs_t *downlink_NAS_transport_p = NULL;
s1ap_eNB_mme_data_t *mme_desc_p;
s1ap_eNB_ue_context_t *ue_desc_p;
s1ap_eNB_instance_t *s1ap_eNB_instance;
s1ap_eNB_mme_data_t *mme_desc_p = NULL;
s1ap_eNB_ue_context_t *ue_desc_p = NULL;
s1ap_eNB_instance_t *s1ap_eNB_instance = NULL;
DevAssert(message_p != NULL);
@@ -232,8 +236,9 @@ int s1ap_eNB_handle_nas_downlink(uint32_t assoc_id,
}
if ((mme_desc_p = s1ap_eNB_get_MME(NULL, assoc_id, 0)) == NULL) {
S1AP_ERROR("[SCTP %d] Received NAS downlink message for non "
"existing MME context\n", assoc_id);
S1AP_ERROR(
"[SCTP %d] Received NAS downlink message for non existing MME context\n",
assoc_id);
return -1;
}
@@ -242,9 +247,10 @@ int s1ap_eNB_handle_nas_downlink(uint32_t assoc_id,
if ((ue_desc_p = s1ap_eNB_get_ue_context(s1ap_eNB_instance,
downlink_NAS_transport_p->eNB_UE_S1AP_ID)) == NULL)
{
S1AP_ERROR("[SCTP %d] Received NAS downlink message for non "
"existing UE context: 0x%06x\n", assoc_id,
downlink_NAS_transport_p->eNB_UE_S1AP_ID);
S1AP_ERROR("[SCTP %d] Received NAS downlink message for non existing UE context: 0x%08x %l(10)\n",
assoc_id,
downlink_NAS_transport_p->eNB_UE_S1AP_ID,
downlink_NAS_transport_p->eNB_UE_S1AP_ID);
return -1;
}
@@ -358,7 +364,7 @@ int s1ap_eNB_nas_uplink(instance_t instance, s1ap_uplink_nas_t *s1ap_uplink_nas_
return 0;
}
void s1ap_eNB_nas_non_delivery_ind(instance_t instance,
void s1ap_eNB_nas_non_delivery_ind(instance_t instance,
s1ap_nas_non_delivery_ind_t *s1ap_nas_non_delivery_ind)
{
struct s1ap_eNB_ue_context_s *ue_context_p;
+5 -4
View File
@@ -31,13 +31,14 @@
#ifndef S1AP_ENB_NAS_PROCEDURES_H_
#define S1AP_ENB_NAS_PROCEDURES_H_
int s1ap_eNB_handle_nas_downlink(uint32_t assoc_id,
uint32_t stream,
struct s1ap_message_s *message_p);
int s1ap_eNB_handle_nas_downlink(
const uint32_t assoc_id,
const uint32_t stream,
const struct s1ap_message_s *const message_p);
int s1ap_eNB_nas_uplink(instance_t instance, s1ap_uplink_nas_t *s1ap_uplink_nas_p);
void s1ap_eNB_nas_non_delivery_ind(instance_t instance,
void s1ap_eNB_nas_non_delivery_ind(instance_t instance,
s1ap_nas_non_delivery_ind_t *s1ap_nas_non_delivery_ind);
int s1ap_eNB_handle_nas_first_req(
+2 -2
View File
@@ -168,9 +168,9 @@ s1ap_eNB_nnsf_select_mme_by_gummei(s1ap_eNB_instance_t *instance_p,
rrc_establishment_cause_t cause,
s1ap_gummei_t gummei)
{
struct s1ap_eNB_mme_data_s *mme_data_p = NULL;
struct s1ap_eNB_mme_data_s *mme_data_p = NULL;
struct s1ap_eNB_mme_data_s *mme_highest_capacity_p = NULL;
uint8_t current_capacity = 0;
uint8_t current_capacity = 0;
RB_FOREACH(mme_data_p, s1ap_mme_map, &instance_p->s1ap_mme_head) {
struct served_gummei_s *gummei_p = NULL;
+7 -2
View File
@@ -157,8 +157,13 @@ void *s1ap_mme_thread(void *args)
s1ap_handle_attach_accepted(&received_message_p->ittiMsg.nas_attach_accept);
} break;
#else
case NAS_CONNECTION_ESTABLISHMENT_CNF: {
s1ap_handle_conn_est_cnf(&NAS_CONNECTION_ESTABLISHMENT_CNF(received_message_p));
// handled by MME_APP know
//case NAS_CONNECTION_ESTABLISHMENT_CNF: {
// s1ap_handle_conn_est_cnf(&NAS_CONNECTION_ESTABLISHMENT_CNF(received_message_p));
//} break;
case MME_APP_CONNECTION_ESTABLISHMENT_CNF: {
s1ap_handle_conn_est_cnf(&MME_APP_CONNECTION_ESTABLISHMENT_CNF(received_message_p));
} break;
#endif
+5 -6
View File
@@ -140,12 +140,11 @@ static int s1ap_mme_decode_initiating(
static int s1ap_mme_decode_successfull_outcome(
s1ap_message *message, S1ap_SuccessfulOutcome_t *successfullOutcome_p)
{
int ret = -1;
MessageDef *message_p;
char *message_string = NULL;
size_t message_string_size;
MessagesIds message_id;
int ret = -1;
MessageDef *message_p = NULL;
char *message_string = NULL;
size_t message_string_size = 0;
MessagesIds message_id = MESSAGES_ID_MAX;
DevAssert(successfullOutcome_p != NULL);
+30 -24
View File
@@ -488,26 +488,27 @@ int s1ap_mme_handle_initial_context_setup_response(
struct s1ap_message_s *message)
{
S1ap_InitialContextSetupResponseIEs_t *initialContextSetupResponseIEs_p;
S1ap_E_RABSetupItemCtxtSURes_t *eRABSetupItemCtxtSURes_p;
ue_description_t *ue_ref;
SgwModifyBearerRequest *modify_request_p;
MessageDef *message_p;
S1ap_InitialContextSetupResponseIEs_t *initialContextSetupResponseIEs_p = NULL;
S1ap_E_RABSetupItemCtxtSURes_t *eRABSetupItemCtxtSURes_p = NULL;
ue_description_t *ue_ref = NULL;
MessageDef *message_p = NULL;
initialContextSetupResponseIEs_p = &message->msg.s1ap_InitialContextSetupResponseIEs;
if ((ue_ref = s1ap_is_ue_mme_id_in_list(
(uint32_t)initialContextSetupResponseIEs_p->mme_ue_s1ap_id)) == NULL) {
S1AP_DEBUG("No UE is attached to this mme UE s1ap id: 0x%08x\n",
S1AP_DEBUG("No UE is attached to this mme UE s1ap id: 0x%08x %u(10)\n",
(uint32_t)initialContextSetupResponseIEs_p->mme_ue_s1ap_id,
(uint32_t)initialContextSetupResponseIEs_p->mme_ue_s1ap_id);
return -1;
}
if (ue_ref->eNB_ue_s1ap_id !=
initialContextSetupResponseIEs_p->eNB_UE_S1AP_ID) {
S1AP_DEBUG("Mismatch in eNB UE S1AP ID, known: 0x%06x, received: 0x%06x\n",
ue_ref->eNB_ue_s1ap_id,
(uint32_t)initialContextSetupResponseIEs_p->eNB_UE_S1AP_ID);
S1AP_DEBUG("Mismatch in eNB UE S1AP ID, known: 0x%06x %u(10), received: 0x%06x %u(10)\n",
ue_ref->eNB_ue_s1ap_id,
ue_ref->eNB_ue_s1ap_id,
(uint32_t)initialContextSetupResponseIEs_p->eNB_UE_S1AP_ID,
(uint32_t)initialContextSetupResponseIEs_p->eNB_UE_S1AP_ID);
return -1;
}
@@ -519,29 +520,32 @@ int s1ap_mme_handle_initial_context_setup_response(
ue_ref->s1_ue_state = S1AP_UE_CONNECTED;
message_p = itti_alloc_new_message(TASK_SPGW_APP, SGW_MODIFY_BEARER_REQUEST);
message_p = itti_alloc_new_message(TASK_S1AP, MME_APP_INITIAL_CONTEXT_SETUP_RSP);
if (message_p == NULL) {
return -1;
}
AssertFatal(message_p != NULL,"itti_alloc_new_message Failed");
memset((void*)&message_p->ittiMsg.mme_app_initial_context_setup_rsp,
0,
sizeof(mme_app_initial_context_setup_rsp_t));
/* Bad, very bad cast... */
eRABSetupItemCtxtSURes_p = (S1ap_E_RABSetupItemCtxtSURes_t *)
initialContextSetupResponseIEs_p->e_RABSetupListCtxtSURes.s1ap_E_RABSetupItemCtxtSURes.array[0];
modify_request_p = &message_p->ittiMsg.sgwModifyBearerRequest;
// modify_request_p->teid = ue_ref->teid;
modify_request_p->bearer_context_to_modify.eps_bearer_id =
eRABSetupItemCtxtSURes_p->e_RAB_ID;
modify_request_p->bearer_context_to_modify.s1_eNB_fteid.teid = *((
uint32_t *)eRABSetupItemCtxtSURes_p->gTP_TEID.buf);
modify_request_p->bearer_context_to_modify.s1_eNB_fteid.ipv4 = 1;
memcpy(&modify_request_p->bearer_context_to_modify.s1_eNB_fteid.ipv4_address,
eRABSetupItemCtxtSURes_p->transportLayerAddress.buf, 4);
return itti_send_msg_to_task(TASK_SPGW_APP, INSTANCE_DEFAULT, message_p);
MME_APP_INITIAL_CONTEXT_SETUP_RSP(message_p).mme_ue_s1ap_id = ue_ref->mme_ue_s1ap_id;
MME_APP_INITIAL_CONTEXT_SETUP_RSP(message_p).eps_bearer_id = eRABSetupItemCtxtSURes_p->e_RAB_ID ;
MME_APP_INITIAL_CONTEXT_SETUP_RSP(message_p).bearer_s1u_enb_fteid.ipv4 = 1; // TO DO
MME_APP_INITIAL_CONTEXT_SETUP_RSP(message_p).bearer_s1u_enb_fteid.ipv6 = 0; // TO DO
MME_APP_INITIAL_CONTEXT_SETUP_RSP(message_p).bearer_s1u_enb_fteid.interface_type = S1_U_ENODEB_GTP_U;
MME_APP_INITIAL_CONTEXT_SETUP_RSP(message_p).bearer_s1u_enb_fteid.teid = *((uint32_t *)eRABSetupItemCtxtSURes_p->gTP_TEID.buf);
memcpy(&MME_APP_INITIAL_CONTEXT_SETUP_RSP(message_p).bearer_s1u_enb_fteid.ipv4_address,
eRABSetupItemCtxtSURes_p->transportLayerAddress.buf,
4);
return itti_send_msg_to_task(TASK_MME_APP, INSTANCE_DEFAULT, message_p);
}
int s1ap_mme_handle_ue_context_release_request(uint32_t assoc_id,
uint32_t stream, struct s1ap_message_s *message)
{
@@ -802,6 +806,7 @@ int s1ap_handle_new_association(sctp_new_peer_t *sctp_new_peer_p)
//************************* E-RAB management *********************************//
////////////////////////////////////////////////////////////////////////////////
// NOT CALLED
int s1ap_handle_create_session_response(SgwCreateSessionResponse
*session_response_p)
{
@@ -824,6 +829,7 @@ int s1ap_handle_create_session_response(SgwCreateSessionResponse
S1ap_InitialContextSetupRequestIEs_t *initialContextSetupRequest_p;
S1ap_E_RABToBeSetupItemCtxtSUReq_t e_RABToBeSetup;
AssertFatal(0, "Not called anymore");
DevAssert(session_response_p != NULL);
DevCheck(session_response_p->bearer_context_created.cause == REQUEST_ACCEPTED,
+32
View File
@@ -45,6 +45,36 @@ int s1ap_mme_itti_nas_uplink_ind(const uint32_t ue_id, uint8_t *const buffer,
int s1ap_mme_itti_nas_downlink_cnf(const uint32_t ue_id,
nas_error_code_t error_code);
static inline void s1ap_mme_itti_mme_app_establish_ind(
const uint32_t ue_id,
const uint8_t * const nas_msg,
const uint32_t nas_msg_length,
const long cause,
const uint16_t tac)
{
MessageDef *message_p = NULL;
message_p = itti_alloc_new_message(TASK_S1AP, MME_APP_CONNECTION_ESTABLISHMENT_IND);
MME_APP_CONNECTION_ESTABLISHMENT_IND(message_p).mme_ue_s1ap_id = ue_id;
MME_APP_CONNECTION_ESTABLISHMENT_IND(message_p).nas.UEid = ue_id;
/* Mapping between asn1 definition and NAS definition */
MME_APP_CONNECTION_ESTABLISHMENT_IND(message_p).nas.asCause = cause + 1;
MME_APP_CONNECTION_ESTABLISHMENT_IND(message_p).nas.tac = tac;
MME_APP_CONNECTION_ESTABLISHMENT_IND(message_p).nas.initialNasMsg.length = nas_msg_length;
MME_APP_CONNECTION_ESTABLISHMENT_IND(message_p).nas.initialNasMsg.data = malloc(sizeof(uint8_t) * nas_msg_length);
memcpy(MME_APP_CONNECTION_ESTABLISHMENT_IND(message_p).nas.initialNasMsg.data, nas_msg, nas_msg_length);
// should be sent to MME_APP, but this one would forward it to NAS_MME, so send it directly to NAS_MME
// but let's see
itti_send_msg_to_task(TASK_MME_APP, INSTANCE_DEFAULT, message_p);
}
static inline void s1ap_mme_itti_nas_establish_ind(
const uint32_t ue_id, uint8_t * const nas_msg, const uint32_t nas_msg_length,
const long cause, const uint16_t tac)
@@ -62,6 +92,8 @@ static inline void s1ap_mme_itti_nas_establish_ind(
NAS_CONN_EST_IND(message_p).nas.initialNasMsg.data = malloc(sizeof(uint8_t) * nas_msg_length);
memcpy(NAS_CONN_EST_IND(message_p).nas.initialNasMsg.data, nas_msg, nas_msg_length);
// should be sent to MME_APP, but this one would forward it to NAS_MME, so send it directly to NAS_MME
// but let's see
itti_send_msg_to_task(TASK_NAS_MME, INSTANCE_DEFAULT, message_p);
}
+242 -75
View File
@@ -55,6 +55,8 @@
static uint32_t mme_ue_s1ap_id = 0;
static uint8_t mme_ue_s1ap_id_has_wrapped = 0;
int s1ap_mme_handle_initial_ue_message(uint32_t assoc_id, uint32_t stream,
struct s1ap_message_s *message)
{
@@ -130,15 +132,27 @@ int s1ap_mme_handle_initial_ue_message(uint32_t assoc_id, uint32_t stream,
/* We received the first NAS transport message: initial UE message.
* Send a NAS ESTABLISH IND to NAS layer
*/
s1ap_mme_itti_nas_establish_ind(ue_ref->mme_ue_s1ap_id,
initialUEMessage_p->nas_pdu.buf,
initialUEMessage_p->nas_pdu.size,
initialUEMessage_p->rrC_Establishment_Cause,
tac);
#if defined(ORIGINAL_CODE)
s1ap_mme_itti_nas_establish_ind(
ue_ref->mme_ue_s1ap_id,
initialUEMessage_p->nas_pdu.buf,
initialUEMessage_p->nas_pdu.size,
initialUEMessage_p->rrC_Establishment_Cause,
tac);
#else
s1ap_mme_itti_mme_app_establish_ind(
ue_ref->mme_ue_s1ap_id,
initialUEMessage_p->nas_pdu.buf,
initialUEMessage_p->nas_pdu.size,
initialUEMessage_p->rrC_Establishment_Cause,
tac);
#endif
}
return 0;
}
int s1ap_mme_handle_uplink_nas_transport(uint32_t assoc_id, uint32_t stream,
struct s1ap_message_s *message)
{
@@ -168,6 +182,8 @@ int s1ap_mme_handle_uplink_nas_transport(uint32_t assoc_id, uint32_t stream,
return 0;
}
int s1ap_mme_handle_nas_non_delivery(uint32_t assoc_id, uint32_t stream,
struct s1ap_message_s *message)
{
@@ -199,7 +215,7 @@ int s1ap_generate_downlink_nas_transport(const uint32_t ue_id, void * const data
/* We have fount the UE in the list.
* Create new IE list message and encode it.
*/
S1ap_DownlinkNASTransportIEs_t *downlinkNasTransport;
S1ap_DownlinkNASTransportIEs_t *downlinkNasTransport = NULL;
s1ap_message message;
@@ -223,6 +239,10 @@ int s1ap_generate_downlink_nas_transport(const uint32_t ue_id, void * const data
// TODO: handle something
return -1;
}
S1AP_DEBUG("Send S1ap_ProcedureCode_id_downlinkNASTransport ue_id = 0x%08X mme_ue_s1ap_id = 0x%08X eNB_UE_S1AP_ID = 0x%08X\n",
ue_id,
downlinkNasTransport->mme_ue_s1ap_id,
downlinkNasTransport->eNB_UE_S1AP_ID);
s1ap_mme_itti_send_sctp_request(buffer_p, length,
ue_ref->eNB->sctp_assoc_id,
@@ -359,30 +379,179 @@ int s1ap_handle_attach_accepted(nas_attach_accept_t *attach_accept_p)
ue_ref->sctp_stream_send);
}
#else
void s1ap_handle_conn_est_cnf(nas_conn_est_cnf_t *nas_conn_est_cnf_p)
//void s1ap_handle_conn_est_cnf(nas_conn_est_cnf_t *nas_conn_est_cnf_p)
//{
// /* We received create session response from S-GW on S11 interface abstraction.
// * At least one bearer has been established. We can now send s1ap initial context setup request
// * message to eNB.
// */
// uint8_t supportedAlgorithms[] = { 0x00, 0x00 };
// uint8_t offset = 0;
// uint8_t *buffer_p;
// uint32_t length, teid = 12;
//
// ue_description_t *ue_ref = NULL;
// s1ap_message message;
//
// S1ap_InitialContextSetupRequestIEs_t *initialContextSetupRequest_p;
// S1ap_E_RABToBeSetupItemCtxtSUReq_t e_RABToBeSetup;
// S1ap_NAS_PDU_t nas_pdu;
//
// DevAssert(nas_conn_est_cnf_p != NULL);
//
// if ((ue_ref = s1ap_is_ue_mme_id_in_list(nas_conn_est_cnf_p->UEid)) == NULL) {
// S1AP_DEBUG("This mme ue s1ap id (%08x) is not attached to any UE context\n",
// nas_conn_est_cnf_p->UEid);
// DevParam(nas_conn_est_cnf_p->UEid, 0, 0);
// }
//
// /* Start the outcome response timer.
// * When time is reached, MME consider that procedure outcome has failed.
// */
//// timer_setup(mme_config.s1ap_config.outcome_drop_timer_sec, 0, TASK_S1AP, INSTANCE_DEFAULT,
//// TIMER_ONE_SHOT,
//// NULL,
//// &ue_ref->outcome_response_timer_id);
// /* Insert the timer in the MAP of mme_ue_s1ap_id <-> timer_id */
//// s1ap_timer_insert(ue_ref->mme_ue_s1ap_id, ue_ref->outcome_response_timer_id);
//
// memset(&message, 0, sizeof(s1ap_message));
// memset(&e_RABToBeSetup, 0, sizeof(S1ap_E_RABToBeSetupItemCtxtSUReq_t));
//
// message.procedureCode = S1ap_ProcedureCode_id_InitialContextSetup;
// message.direction = S1AP_PDU_PR_initiatingMessage;
//
// initialContextSetupRequest_p = &message.msg.s1ap_InitialContextSetupRequestIEs;
//
// initialContextSetupRequest_p->mme_ue_s1ap_id = (unsigned long)ue_ref->mme_ue_s1ap_id;
// initialContextSetupRequest_p->eNB_UE_S1AP_ID = (unsigned long)ue_ref->eNB_ue_s1ap_id;
//
// /* uEaggregateMaximumBitrateDL and uEaggregateMaximumBitrateUL expressed in term of bits/sec */
//// initialContextSetupRequest_p->uEaggregateMaximumBitrate.uEaggregateMaximumBitRateDL = initial_p->ambr.br_dl;
//// initialContextSetupRequest_p->uEaggregateMaximumBitrate.uEaggregateMaximumBitRateUL = initial_p->ambr.br_ul;
//
// initialContextSetupRequest_p->uEaggregateMaximumBitrate.uEaggregateMaximumBitRateDL = 1024 * 1024;
// initialContextSetupRequest_p->uEaggregateMaximumBitrate.uEaggregateMaximumBitRateDL = 512 * 1024;
//
//// e_RABToBeSetup.e_RAB_ID = initial_p->ebi;
// e_RABToBeSetup.e_RAB_ID = 5;
//// e_RABToBeSetup.e_RABlevelQoSParameters.qCI = initial_p->qci;
// e_RABToBeSetup.e_RABlevelQoSParameters.qCI = 0;
//
// memset(&nas_pdu, 0, sizeof(nas_pdu));
//
// nas_pdu.size = nas_conn_est_cnf_p->nasMsg.length;
// nas_pdu.buf = nas_conn_est_cnf_p->nasMsg.data;
//
// e_RABToBeSetup.nAS_PDU = &nas_pdu;
// e_RABToBeSetup.e_RABlevelQoSParameters.allocationRetentionPriority.priorityLevel =
// S1ap_PriorityLevel_lowest;
// e_RABToBeSetup.e_RABlevelQoSParameters.allocationRetentionPriority.pre_emptionCapability =
// S1ap_Pre_emptionCapability_shall_not_trigger_pre_emption;
// e_RABToBeSetup.e_RABlevelQoSParameters.allocationRetentionPriority.pre_emptionVulnerability =
// S1ap_Pre_emptionVulnerability_not_pre_emptable;
// INT32_TO_OCTET_STRING(teid, &e_RABToBeSetup.gTP_TEID);
//// e_RABToBeSetup.e_RABlevelQoSParameters.allocationRetentionPriority.priorityLevel
//// = initial_p->prio_level; //No priority
//// e_RABToBeSetup.e_RABlevelQoSParameters.allocationRetentionPriority.pre_emptionCapability
//// = initial_p->pre_emp_capability;
//// e_RABToBeSetup.e_RABlevelQoSParameters.allocationRetentionPriority.pre_emptionVulnerability
//// = initial_p->pre_emp_vulnerability;
//
// /* Set the GTP-TEID. This is the S1-U S-GW TEID */
//// INT32_TO_OCTET_STRING(initial_p->teid, &e_RABToBeSetup.gTP_TEID);
//
// /* S-GW IP address(es) for user-plane */
//// if ((initial_p->s_gw_address.pdn_type == IPv4) ||
//// (initial_p->s_gw_address.pdn_type == IPv4_AND_v6))
//// {
//// e_RABToBeSetup.transportLayerAddress.buf = calloc(4, sizeof(uint8_t));
//// /* Only IPv4 supported */
//// memcpy(e_RABToBeSetup.transportLayerAddress.buf,
//// initial_p->s_gw_address.address.ipv4_address,
//// 4);
//// offset += 4;
//// e_RABToBeSetup.transportLayerAddress.size = 4;
//// e_RABToBeSetup.transportLayerAddress.bits_unused = 0;
//// }
//// if ((initial_p->s_gw_address.pdn_type == IPv6) ||
//// (initial_p->s_gw_address.pdn_type == IPv4_AND_v6))
//// {
//// if (offset == 0) {
//// /* Both IPv4 and IPv6 provided */
//// /* TODO: check memory allocation */
//// e_RABToBeSetup.transportLayerAddress.buf = calloc(16, sizeof(uint8_t));
//// } else {
//// /* Only IPv6 supported */
//// /* TODO: check memory allocation */
//// e_RABToBeSetup.transportLayerAddress.buf
//// = realloc(e_RABToBeSetup.transportLayerAddress.buf, (16 + offset) * sizeof(uint8_t));
//// }
//// memcpy(&e_RABToBeSetup.transportLayerAddress.buf[offset],
//// initial_p->s_gw_address.address.ipv6_address,
//// 16);
//// e_RABToBeSetup.transportLayerAddress.size = 16 + offset;
//// e_RABToBeSetup.transportLayerAddress.bits_unused = 0;
//// }
//
// ASN_SEQUENCE_ADD(&initialContextSetupRequest_p->e_RABToBeSetupListCtxtSUReq,
// &e_RABToBeSetup);
//
// initialContextSetupRequest_p->ueSecurityCapabilities.encryptionAlgorithms.buf =
// (uint8_t *)supportedAlgorithms;
// initialContextSetupRequest_p->ueSecurityCapabilities.encryptionAlgorithms.size = 2;
// initialContextSetupRequest_p->ueSecurityCapabilities.encryptionAlgorithms.bits_unused
// = 0;
//
// initialContextSetupRequest_p->ueSecurityCapabilities.integrityProtectionAlgorithms.buf
// = (uint8_t *)supportedAlgorithms;
// initialContextSetupRequest_p->ueSecurityCapabilities.integrityProtectionAlgorithms.size
// = 2;
// initialContextSetupRequest_p->ueSecurityCapabilities.integrityProtectionAlgorithms.bits_unused
// = 0;
//
//// initialContextSetupRequest_p->securityKey.buf = initial_p->keNB; /* 256 bits length */
// uint8_t keNB[32];
// memset(keNB, 0, sizeof(keNB));
//
// initialContextSetupRequest_p->securityKey.buf = keNB;
// initialContextSetupRequest_p->securityKey.size = 32;
// initialContextSetupRequest_p->securityKey.bits_unused = 0;
//
// if (s1ap_mme_encode_pdu(&message, &buffer_p, &length) < 0) {
// // TODO: handle something
// DevMessage("Failed to encode initial context setup request message\n");
// }
//
// free(nas_conn_est_cnf_p->nasMsg.data);
//
// s1ap_mme_itti_send_sctp_request(buffer_p, length, ue_ref->eNB->sctp_assoc_id,
// ue_ref->sctp_stream_send);
//}
void s1ap_handle_conn_est_cnf(const mme_app_connection_establishment_cnf_t * const conn_est_cnf_pP)
{
/* We received create session response from S-GW on S11 interface abstraction.
* At least one bearer has been established. We can now send s1ap initial context setup request
* message to eNB.
*/
uint8_t supportedAlgorithms[] = { 0x00, 0x00 };
uint8_t offset = 0;
uint8_t *buffer_p;
uint32_t length, teid = 12;
ue_description_t *ue_ref = NULL;
s1ap_message message;
S1ap_InitialContextSetupRequestIEs_t *initialContextSetupRequest_p;
uint8_t supportedAlgorithms[] = { 0x00, 0x00 };
uint8_t offset = 0;
uint8_t *buffer_p = NULL;
uint32_t length = 0;
ue_description_t *ue_ref = NULL;
S1ap_InitialContextSetupRequestIEs_t *initialContextSetupRequest_p = NULL;
S1ap_E_RABToBeSetupItemCtxtSUReq_t e_RABToBeSetup;
S1ap_NAS_PDU_t nas_pdu;
s1ap_message message;
DevAssert(nas_conn_est_cnf_p != NULL);
DevAssert(conn_est_cnf_pP != NULL);
if ((ue_ref = s1ap_is_ue_mme_id_in_list(nas_conn_est_cnf_p->UEid)) == NULL) {
if ((ue_ref = s1ap_is_ue_mme_id_in_list(conn_est_cnf_pP->nas_conn_est_cnf.UEid)) == NULL) {
S1AP_DEBUG("This mme ue s1ap id (%08x) is not attached to any UE context\n",
nas_conn_est_cnf_p->UEid);
DevParam(nas_conn_est_cnf_p->UEid, 0, 0);
conn_est_cnf_pP->nas_conn_est_cnf.UEid);
DevParam(conn_est_cnf_pP->nas_conn_est_cnf.UEid, 0, 0);
}
/* Start the outcome response timer.
@@ -407,72 +576,66 @@ void s1ap_handle_conn_est_cnf(nas_conn_est_cnf_t *nas_conn_est_cnf_p)
initialContextSetupRequest_p->eNB_UE_S1AP_ID = (unsigned long)ue_ref->eNB_ue_s1ap_id;
/* uEaggregateMaximumBitrateDL and uEaggregateMaximumBitrateUL expressed in term of bits/sec */
// initialContextSetupRequest_p->uEaggregateMaximumBitrate.uEaggregateMaximumBitRateDL = initial_p->ambr.br_dl;
// initialContextSetupRequest_p->uEaggregateMaximumBitrate.uEaggregateMaximumBitRateUL = initial_p->ambr.br_ul;
initialContextSetupRequest_p->uEaggregateMaximumBitrate.uEaggregateMaximumBitRateDL = conn_est_cnf_pP->ambr.br_dl;
initialContextSetupRequest_p->uEaggregateMaximumBitrate.uEaggregateMaximumBitRateUL = conn_est_cnf_pP->ambr.br_ul;
initialContextSetupRequest_p->uEaggregateMaximumBitrate.uEaggregateMaximumBitRateDL = 1024 * 1024;
initialContextSetupRequest_p->uEaggregateMaximumBitrate.uEaggregateMaximumBitRateDL = 512 * 1024;
e_RABToBeSetup.e_RAB_ID = conn_est_cnf_pP->eps_bearer_id; //5;
e_RABToBeSetup.e_RABlevelQoSParameters.qCI = conn_est_cnf_pP->bearer_qos_qci;
// e_RABToBeSetup.e_RAB_ID = initial_p->ebi;
e_RABToBeSetup.e_RAB_ID = 5;
// e_RABToBeSetup.e_RABlevelQoSParameters.qCI = initial_p->qci;
e_RABToBeSetup.e_RABlevelQoSParameters.qCI = 0;
memset(&nas_pdu, 0, sizeof(nas_pdu));
nas_pdu.size = nas_conn_est_cnf_p->nasMsg.length;
nas_pdu.buf = nas_conn_est_cnf_p->nasMsg.data;
nas_pdu.size = conn_est_cnf_pP->nas_conn_est_cnf.nasMsg.length;
nas_pdu.buf = conn_est_cnf_pP->nas_conn_est_cnf.nasMsg.data;
e_RABToBeSetup.nAS_PDU = &nas_pdu;
#if defined(ORIGINAL_S1AP_CODE)
e_RABToBeSetup.e_RABlevelQoSParameters.allocationRetentionPriority.priorityLevel =
S1ap_PriorityLevel_lowest;
e_RABToBeSetup.e_RABlevelQoSParameters.allocationRetentionPriority.pre_emptionCapability =
S1ap_Pre_emptionCapability_shall_not_trigger_pre_emption;
e_RABToBeSetup.e_RABlevelQoSParameters.allocationRetentionPriority.pre_emptionVulnerability =
S1ap_Pre_emptionVulnerability_not_pre_emptable;
INT32_TO_OCTET_STRING(teid, &e_RABToBeSetup.gTP_TEID);
// e_RABToBeSetup.e_RABlevelQoSParameters.allocationRetentionPriority.priorityLevel
// = initial_p->prio_level; //No priority
// e_RABToBeSetup.e_RABlevelQoSParameters.allocationRetentionPriority.pre_emptionCapability
// = initial_p->pre_emp_capability;
// e_RABToBeSetup.e_RABlevelQoSParameters.allocationRetentionPriority.pre_emptionVulnerability
// = initial_p->pre_emp_vulnerability;
#else
e_RABToBeSetup.e_RABlevelQoSParameters.allocationRetentionPriority.priorityLevel =
conn_est_cnf_pP->bearer_qos_prio_level;
e_RABToBeSetup.e_RABlevelQoSParameters.allocationRetentionPriority.pre_emptionCapability =
conn_est_cnf_pP->bearer_qos_pre_emp_capability;
e_RABToBeSetup.e_RABlevelQoSParameters.allocationRetentionPriority.pre_emptionVulnerability =
conn_est_cnf_pP->bearer_qos_pre_emp_vulnerability;
#endif
/* Set the GTP-TEID. This is the S1-U S-GW TEID */
// INT32_TO_OCTET_STRING(initial_p->teid, &e_RABToBeSetup.gTP_TEID);
INT32_TO_OCTET_STRING(conn_est_cnf_pP->bearer_s1u_sgw_fteid.teid, &e_RABToBeSetup.gTP_TEID);
/* S-GW IP address(es) for user-plane */
// if ((initial_p->s_gw_address.pdn_type == IPv4) ||
// (initial_p->s_gw_address.pdn_type == IPv4_AND_v6))
// {
// e_RABToBeSetup.transportLayerAddress.buf = calloc(4, sizeof(uint8_t));
// /* Only IPv4 supported */
// memcpy(e_RABToBeSetup.transportLayerAddress.buf,
// initial_p->s_gw_address.address.ipv4_address,
// 4);
// offset += 4;
// e_RABToBeSetup.transportLayerAddress.size = 4;
// e_RABToBeSetup.transportLayerAddress.bits_unused = 0;
// }
// if ((initial_p->s_gw_address.pdn_type == IPv6) ||
// (initial_p->s_gw_address.pdn_type == IPv4_AND_v6))
// {
// if (offset == 0) {
// /* Both IPv4 and IPv6 provided */
// /* TODO: check memory allocation */
// e_RABToBeSetup.transportLayerAddress.buf = calloc(16, sizeof(uint8_t));
// } else {
// /* Only IPv6 supported */
// /* TODO: check memory allocation */
// e_RABToBeSetup.transportLayerAddress.buf
// = realloc(e_RABToBeSetup.transportLayerAddress.buf, (16 + offset) * sizeof(uint8_t));
// }
// memcpy(&e_RABToBeSetup.transportLayerAddress.buf[offset],
// initial_p->s_gw_address.address.ipv6_address,
// 16);
// e_RABToBeSetup.transportLayerAddress.size = 16 + offset;
// e_RABToBeSetup.transportLayerAddress.bits_unused = 0;
// }
if (conn_est_cnf_pP->bearer_s1u_sgw_fteid.ipv4)
{
e_RABToBeSetup.transportLayerAddress.buf = calloc(4, sizeof(uint8_t));
/* Only IPv4 supported */
memcpy(e_RABToBeSetup.transportLayerAddress.buf,
&conn_est_cnf_pP->bearer_s1u_sgw_fteid.ipv4_address,
4);
offset += 4;
e_RABToBeSetup.transportLayerAddress.size = 4;
e_RABToBeSetup.transportLayerAddress.bits_unused = 0;
}
if (conn_est_cnf_pP->bearer_s1u_sgw_fteid.ipv6)
{
if (offset == 0) {
/* Both IPv4 and IPv6 provided */
/* TODO: check memory allocation */
e_RABToBeSetup.transportLayerAddress.buf = calloc(16, sizeof(uint8_t));
} else {
/* Only IPv6 supported */
/* TODO: check memory allocation */
e_RABToBeSetup.transportLayerAddress.buf
= realloc(e_RABToBeSetup.transportLayerAddress.buf, (16 + offset) * sizeof(uint8_t));
}
memcpy(&e_RABToBeSetup.transportLayerAddress.buf[offset],
conn_est_cnf_pP->bearer_s1u_sgw_fteid.ipv6_address,
16);
e_RABToBeSetup.transportLayerAddress.size = 16 + offset;
e_RABToBeSetup.transportLayerAddress.bits_unused = 0;
}
ASN_SEQUENCE_ADD(&initialContextSetupRequest_p->e_RABToBeSetupListCtxtSUReq,
&e_RABToBeSetup);
@@ -503,9 +666,13 @@ void s1ap_handle_conn_est_cnf(nas_conn_est_cnf_t *nas_conn_est_cnf_p)
DevMessage("Failed to encode initial context setup request message\n");
}
free(nas_conn_est_cnf_p->nasMsg.data);
free(conn_est_cnf_pP->nas_conn_est_cnf.nasMsg.data);
s1ap_mme_itti_send_sctp_request(buffer_p, length, ue_ref->eNB->sctp_assoc_id,
ue_ref->sctp_stream_send);
s1ap_mme_itti_send_sctp_request(
buffer_p,
length,
ue_ref->eNB->sctp_assoc_id,
ue_ref->sctp_stream_send);
}
#endif
+1 -1
View File
@@ -67,7 +67,7 @@ int s1ap_mme_handle_nas_non_delivery(uint32_t assocId, uint32_t stream,
#if defined(DISABLE_USE_NAS)
int s1ap_handle_attach_accepted(nas_attach_accept_t *attach_accept_p);
#else
void s1ap_handle_conn_est_cnf(nas_conn_est_cnf_t *nas_conn_est_cnf);
void s1ap_handle_conn_est_cnf(const mme_app_connection_establishment_cnf_t * const conn_est_cnf_p);
#endif
int s1ap_generate_downlink_nas_transport(const uint32_t ue_id, void * const data,
+12 -8
View File
@@ -179,13 +179,13 @@ int s6a_aia_cb(struct msg **msg, struct avp *paramavp,
struct session *sess, void *opaque,
enum disp_action *act)
{
struct msg *ans;
struct msg *qry;
struct avp *avp;
struct avp_hdr *hdr;
struct msg *ans = NULL;
struct msg *qry = NULL;
struct avp *avp = NULL;
struct avp_hdr *hdr = NULL;
MessageDef *message_p;
s6a_auth_info_ans_t *s6a_auth_info_ans_p;
MessageDef *message_p = NULL;
s6a_auth_info_ans_t *s6a_auth_info_ans_p = NULL;
int skip_auth_res = 0;
@@ -223,6 +223,10 @@ int s6a_aia_cb(struct msg **msg, struct avp *paramavp,
S6A_ERROR("Got error %u:%s\n", hdr->avp_value->u32,
retcode_2_string(hdr->avp_value->u32));
goto err;
} else {
S6A_DEBUG("Received S6A Result code %u:%s\n",
s6a_auth_info_ans_p->result.choice.base,
retcode_2_string(s6a_auth_info_ans_p->result.choice.base));
}
} else {
/* The result-code is not present, may be it is an experimental result
@@ -340,11 +344,11 @@ int s6a_generate_authentication_info_req(s6a_auth_info_req_t *air_p)
/* Adding the visited plmn id */
{
uint8_t plmn[3] = { 0x02, 0xF8, 0x29 };
uint8_t plmn[3] = { 0x00, 0x00, 0x00 }; //{ 0x02, 0xF8, 0x29 };
CHECK_FCT(fd_msg_avp_new(s6a_fd_cnf.dataobj_s6a_visited_plmn_id, 0, &avp));
PLMN_T_TO_TBCD(air_p->visited_plmn, plmn);
value.os.data = plmn;
value.os.len = 3;
CHECK_FCT(fd_msg_avp_setvalue(avp, &value));
+1 -1
View File
@@ -94,7 +94,7 @@ void *s6a_thread(void *args)
ITTI_MSG_ID(received_message_p), ITTI_MSG_NAME(received_message_p));
} break;
}
free(received_message_p);
itti_free(ITTI_MSG_ORIGIN_ID(received_message_p), received_message_p);
received_message_p = NULL;
}
return NULL;
+89 -84
View File
@@ -40,68 +40,71 @@
#include "s6a_defs.h"
#include "s6a_messages.h"
int s6a_ula_cb(struct msg **msg, struct avp *paramavp,
struct session *sess, void *opaque,
enum disp_action *act)
int s6a_ula_cb(
struct msg **msg_pP,
struct avp *paramavp_pP,
struct session *sess_pP,
void *opaque_pP,
enum disp_action *act_pP)
{
struct msg *ans;
struct msg *qry;
struct avp *avp;
struct avp_hdr *hdr;
struct msg *ans_p = NULL;
struct msg *qry_p = NULL;
struct avp *avp_p = NULL;
struct avp_hdr *hdr_p = NULL;
MessageDef *message_p = NULL;
s6a_update_location_ans_t *s6a_update_location_ans_p = NULL;
MessageDef *message_p;
s6a_update_location_ans_t *s6a_update_location_ans_p;
DevAssert(msg_pP != NULL);
DevAssert(msg != NULL);
ans = *msg;
ans_p = *msg_pP;
/* Retrieve the original query associated with the asnwer */
CHECK_FCT(fd_msg_answ_getq(ans, &qry));
CHECK_FCT(fd_msg_answ_getq(ans_p, &qry_p));
DevAssert(qry != NULL);
DevAssert(qry_p != NULL);
message_p = itti_alloc_new_message(TASK_S6A, S6A_UPDATE_LOCATION_ANS);
s6a_update_location_ans_p = &message_p->ittiMsg.s6a_update_location_ans;
CHECK_FCT(fd_msg_search_avp(qry, s6a_fd_cnf.dataobj_s6a_user_name, &avp));
if (avp) {
CHECK_FCT(fd_msg_avp_hdr(avp, &hdr));
memcpy(s6a_update_location_ans_p->imsi, hdr->avp_value->os.data, hdr->avp_value->os.len);
s6a_update_location_ans_p->imsi[hdr->avp_value->os.len] = '\0';
s6a_update_location_ans_p->imsi_length = hdr->avp_value->os.len;
CHECK_FCT(fd_msg_search_avp(qry_p, s6a_fd_cnf.dataobj_s6a_user_name, &avp_p));
if (avp_p) {
CHECK_FCT(fd_msg_avp_hdr(avp_p, &hdr_p));
memcpy(s6a_update_location_ans_p->imsi, hdr_p->avp_value->os.data, hdr_p->avp_value->os.len);
s6a_update_location_ans_p->imsi[hdr_p->avp_value->os.len] = '\0';
s6a_update_location_ans_p->imsi_length = hdr_p->avp_value->os.len;
S6A_DEBUG("Received s6a ula for imsi=%*s\n",
(int)hdr->avp_value->os.len,
hdr->avp_value->os.data);
(int)hdr_p->avp_value->os.len,
hdr_p->avp_value->os.data);
} else {
DevMessage("Query has been freed before we received the answer\n");
}
/* Retrieve the result-code */
CHECK_FCT(fd_msg_search_avp(ans, s6a_fd_cnf.dataobj_s6a_result_code, &avp));
if (avp) {
CHECK_FCT(fd_msg_avp_hdr(avp, &hdr));
CHECK_FCT(fd_msg_search_avp(ans_p, s6a_fd_cnf.dataobj_s6a_result_code, &avp_p));
if (avp_p) {
CHECK_FCT(fd_msg_avp_hdr(avp_p, &hdr_p));
s6a_update_location_ans_p->result.present = S6A_RESULT_BASE;
s6a_update_location_ans_p->result.choice.base = hdr->avp_value->u32;
s6a_update_location_ans_p->result.choice.base = hdr_p->avp_value->u32;
if (hdr->avp_value->u32 != ER_DIAMETER_SUCCESS) {
S6A_ERROR("Got error %u:%s\n", hdr->avp_value->u32,
retcode_2_string(hdr->avp_value->u32));
if (hdr_p->avp_value->u32 != ER_DIAMETER_SUCCESS) {
S6A_ERROR("Got error %u:%s\n", hdr_p->avp_value->u32,
retcode_2_string(hdr_p->avp_value->u32));
goto err;
}
} else {
/* The result-code is not present, may be it is an experimental result
* avp indicating a 3GPP specific failure.
* avp_p indicating a 3GPP specific failure.
*/
CHECK_FCT(fd_msg_search_avp(ans, s6a_fd_cnf.dataobj_s6a_experimental_result, &avp));
if (avp) {
CHECK_FCT(fd_msg_search_avp(ans_p, s6a_fd_cnf.dataobj_s6a_experimental_result, &avp_p));
if (avp_p) {
/* The procedure has failed within the HSS.
* NOTE: contrary to result-code, the experimental-result is a grouped
* AVP and requires parsing its childs to get the code back.
*/
s6a_update_location_ans_p->result.present = S6A_RESULT_EXPERIMENTAL;
s6a_parse_experimental_result(avp, &s6a_update_location_ans_p->result.choice.experimental);
s6a_parse_experimental_result(avp_p, &s6a_update_location_ans_p->result.choice.experimental);
goto err;
} else {
@@ -115,14 +118,14 @@ int s6a_ula_cb(struct msg **msg, struct avp *paramavp,
}
/* Retrieving the ULA flags */
CHECK_FCT(fd_msg_search_avp(ans, s6a_fd_cnf.dataobj_s6a_ula_flags, &avp));
if (avp) {
CHECK_FCT(fd_msg_avp_hdr(avp, &hdr));
CHECK_FCT(fd_msg_search_avp(ans_p, s6a_fd_cnf.dataobj_s6a_ula_flags, &avp_p));
if (avp_p) {
CHECK_FCT(fd_msg_avp_hdr(avp_p, &hdr_p));
/* This bit, when set, indicates that the HSS stores SGSN number
* and MME number in separate memory. A Rel-8 HSS shall set
* the bit.
*/
if (!FLAG_IS_SET(hdr->avp_value->u32, ULA_SEPARATION_IND)) {
if (!FLAG_IS_SET(hdr_p->avp_value->u32, ULA_SEPARATION_IND)) {
S6A_ERROR("ULA-Flags does not indicate the HSS is post Rel.8: "
"This behaviour is not compliant\n");
goto err;
@@ -137,20 +140,20 @@ int s6a_ula_cb(struct msg **msg, struct avp *paramavp,
goto err;
}
CHECK_FCT(fd_msg_search_avp(ans, s6a_fd_cnf.dataobj_s6a_subscription_data, &avp));
if (avp) {
CHECK_FCT(s6a_parse_subscription_data(avp, &s6a_update_location_ans_p->subscription_data));
CHECK_FCT(fd_msg_search_avp(ans_p, s6a_fd_cnf.dataobj_s6a_subscription_data, &avp_p));
if (avp_p) {
CHECK_FCT(s6a_parse_subscription_data(avp_p, &s6a_update_location_ans_p->subscription_data));
#if defined(DISABLE_USE_NAS)
#else
DevParam(0, 0, 0);
// LG COMMENTED THIS (2014/04/01)-> DevParam(0, 0, 0);
#endif
}
err:
ans = NULL;
ans_p = NULL;
itti_send_msg_to_task(TASK_MME_APP, INSTANCE_DEFAULT, message_p);
@@ -159,41 +162,43 @@ err:
return 0;
}
int s6a_generate_update_location(s6a_update_location_req_t *ulr_p)
int s6a_generate_update_location(s6a_update_location_req_t *ulr_pP)
{
struct avp *avp;
struct msg *msg;
struct session *sess;
struct avp *avp_p = NULL;
struct msg *msg_p = NULL;
struct session *sess_p = NULL;
union avp_value value;
DevAssert(ulr_p != NULL);
DevAssert(ulr_pP != NULL);
/* Create the new update location request message */
CHECK_FCT(fd_msg_new(s6a_fd_cnf.dataobj_s6a_ulr, 0, &msg));
CHECK_FCT(fd_msg_new(s6a_fd_cnf.dataobj_s6a_ulr, 0, &msg_p));
/* Create a new session */
CHECK_FCT(fd_sess_new(&sess, fd_g_config->cnf_diamid,
CHECK_FCT(fd_sess_new(&sess_p, fd_g_config->cnf_diamid,
fd_g_config->cnf_diamid_len, (os0_t)"apps6a", 6));
{
os0_t sid;
size_t sidlen;
CHECK_FCT(fd_sess_getsid(sess, &sid, &sidlen));
CHECK_FCT(fd_msg_avp_new(s6a_fd_cnf.dataobj_s6a_session_id, 0, &avp));
CHECK_FCT(fd_sess_getsid(sess_p, &sid, &sidlen));
CHECK_FCT(fd_msg_avp_new(s6a_fd_cnf.dataobj_s6a_session_id, 0, &avp_p));
value.os.data = sid;
value.os.len = sidlen;
CHECK_FCT(fd_msg_avp_setvalue(avp, &value));
CHECK_FCT(fd_msg_avp_add(msg, MSG_BRW_FIRST_CHILD, avp));
CHECK_FCT(fd_msg_avp_setvalue(avp_p, &value));
CHECK_FCT(fd_msg_avp_add(msg_p, MSG_BRW_FIRST_CHILD, avp_p));
}
CHECK_FCT(fd_msg_avp_new(s6a_fd_cnf.dataobj_s6a_auth_session_state, 0, &avp));
CHECK_FCT(fd_msg_avp_new(s6a_fd_cnf.dataobj_s6a_auth_session_state, 0, &avp_p));
/* No State maintained */
value.i32 = 1;
CHECK_FCT(fd_msg_avp_setvalue(avp, &value));
CHECK_FCT(fd_msg_avp_add(msg, MSG_BRW_LAST_CHILD, avp));
CHECK_FCT(fd_msg_avp_setvalue(avp_p, &value));
CHECK_FCT(fd_msg_avp_add(msg_p, MSG_BRW_LAST_CHILD, avp_p));
/* Add Origin_Host & Origin_Realm */
CHECK_FCT(fd_msg_add_origin(msg, 0));
CHECK_FCT(fd_msg_add_origin(msg_p, 0));
config_read_lock(&mme_config);
@@ -206,79 +211,79 @@ int s6a_generate_update_location(s6a_update_location_req_t *ulr_p)
hostlen = strlen(host);
CHECK_FCT(fd_msg_avp_new(s6a_fd_cnf.dataobj_s6a_destination_host, 0, &avp));
CHECK_FCT(fd_msg_avp_new(s6a_fd_cnf.dataobj_s6a_destination_host, 0, &avp_p));
value.os.data = (unsigned char *)host;
value.os.len = hostlen;
CHECK_FCT(fd_msg_avp_setvalue(avp, &value));
CHECK_FCT(fd_msg_avp_setvalue(avp_p, &value));
CHECK_FCT(fd_msg_avp_add(msg, MSG_BRW_LAST_CHILD, avp));
CHECK_FCT(fd_msg_avp_add(msg_p, MSG_BRW_LAST_CHILD, avp_p));
}
/* Destination_Realm */
{
char *realm = mme_config.realm;
size_t realmlen = strlen(realm);
CHECK_FCT(fd_msg_avp_new(s6a_fd_cnf.dataobj_s6a_destination_realm, 0, &avp));
CHECK_FCT(fd_msg_avp_new(s6a_fd_cnf.dataobj_s6a_destination_realm, 0, &avp_p));
value.os.data = (unsigned char *)realm;
value.os.len = realmlen;
CHECK_FCT(fd_msg_avp_setvalue(avp, &value));
CHECK_FCT(fd_msg_avp_setvalue(avp_p, &value));
CHECK_FCT(fd_msg_avp_add(msg, MSG_BRW_LAST_CHILD, avp));
CHECK_FCT(fd_msg_avp_add(msg_p, MSG_BRW_LAST_CHILD, avp_p));
}
config_unlock(&mme_config);
/* Adding the User-Name (IMSI) */
CHECK_FCT(fd_msg_avp_new(s6a_fd_cnf.dataobj_s6a_user_name, 0, &avp));
value.os.data = (unsigned char *)ulr_p->imsi;
value.os.len = strlen(ulr_p->imsi);
CHECK_FCT(fd_msg_avp_setvalue(avp, &value));
CHECK_FCT(fd_msg_avp_add(msg, MSG_BRW_LAST_CHILD, avp));
CHECK_FCT(fd_msg_avp_new(s6a_fd_cnf.dataobj_s6a_user_name, 0, &avp_p));
value.os.data = (unsigned char *)ulr_pP->imsi;
value.os.len = strlen(ulr_pP->imsi);
CHECK_FCT(fd_msg_avp_setvalue(avp_p, &value));
CHECK_FCT(fd_msg_avp_add(msg_p, MSG_BRW_LAST_CHILD, avp_p));
/* Adding the visited plmn id */
{
uint8_t plmn[3];
CHECK_FCT(fd_msg_avp_new(s6a_fd_cnf.dataobj_s6a_visited_plmn_id, 0, &avp));
CHECK_FCT(fd_msg_avp_new(s6a_fd_cnf.dataobj_s6a_visited_plmn_id, 0, &avp_p));
PLMN_T_TO_TBCD(ulr_p->visited_plmn, plmn);
PLMN_T_TO_TBCD(ulr_pP->visited_plmn, plmn);
printf("PLMN: %3s\n", plmn);
value.os.data = plmn;
value.os.len = 3;
CHECK_FCT(fd_msg_avp_setvalue(avp, &value));
CHECK_FCT(fd_msg_avp_setvalue(avp_p, &value));
CHECK_FCT(fd_msg_avp_add(msg, MSG_BRW_LAST_CHILD, avp));
CHECK_FCT(fd_msg_avp_add(msg_p, MSG_BRW_LAST_CHILD, avp_p));
}
/* Adding the RAT-Type */
CHECK_FCT(fd_msg_avp_new(s6a_fd_cnf.dataobj_s6a_rat_type, 0, &avp));
DevCheck(ulr_p->rat_type == RAT_EUTRAN, ulr_p->rat_type, 0, 0);
value.u32 = ulr_p->rat_type;
CHECK_FCT(fd_msg_avp_setvalue(avp, &value));
CHECK_FCT(fd_msg_avp_add(msg, MSG_BRW_LAST_CHILD, avp));
CHECK_FCT(fd_msg_avp_new(s6a_fd_cnf.dataobj_s6a_rat_type, 0, &avp_p));
DevCheck(ulr_pP->rat_type == RAT_EUTRAN, ulr_pP->rat_type, 0, 0);
value.u32 = ulr_pP->rat_type;
CHECK_FCT(fd_msg_avp_setvalue(avp_p, &value));
CHECK_FCT(fd_msg_avp_add(msg_p, MSG_BRW_LAST_CHILD, avp_p));
/* Adding ULR-Flags */
CHECK_FCT(fd_msg_avp_new(s6a_fd_cnf.dataobj_s6a_ulr_flags, 0, &avp));
CHECK_FCT(fd_msg_avp_new(s6a_fd_cnf.dataobj_s6a_ulr_flags, 0, &avp_p));
value.u32 = 0;
/* Identify the ULR as coming from S6A interface (i.e. from MME) */
FLAGS_SET(value.u32, ULR_S6A_S6D_INDICATOR);
/* Set the ulr-flags as indicated by upper layer */
if (ulr_p->skip_subsriber_data) {
if (ulr_pP->skip_subscriber_data) {
FLAGS_SET(value.u32, ULR_SKIP_SUBSCRIBER_DATA);
}
if (ulr_p->initial_attach) {
if (ulr_pP->initial_attach) {
FLAGS_SET(value.u32, ULR_INITIAL_ATTACH_IND);
}
CHECK_FCT(fd_msg_avp_setvalue(avp, &value));
CHECK_FCT(fd_msg_avp_add(msg, MSG_BRW_LAST_CHILD, avp));
CHECK_FCT(fd_msg_avp_setvalue(avp_p, &value));
CHECK_FCT(fd_msg_avp_add(msg_p, MSG_BRW_LAST_CHILD, avp_p));
CHECK_FCT(fd_msg_send(&msg, NULL, NULL));
CHECK_FCT(fd_msg_send(&msg_p, NULL, NULL));
S6A_DEBUG("Sending s6a ulr for imsi=%s\n", ulr_p->imsi);
S6A_DEBUG("Sending s6a ulr for imsi=%s\n", ulr_pP->imsi);
return 0;
}
+5 -1
View File
@@ -188,6 +188,7 @@ static int sctp_remove_assoc_from_list(int32_t assoc_id)
}
}
free(assoc_desc);
assoc_desc = NULL;
sctp_desc.number_of_connections --;
return 0;
}
@@ -535,6 +536,7 @@ void *sctp_receiver_thread(void *args_p)
SCTP_ERROR("[%d] Select() error: %s",
sctp_arg_p->sd, strerror(errno));
free(args_p);
args_p = NULL;
pthread_exit(NULL);
}
@@ -547,6 +549,7 @@ void *sctp_receiver_thread(void *args_p)
if ((clientsock = accept(sctp_arg_p->sd, NULL, NULL)) < 0) {
SCTP_ERROR("[%d] accept: %s:%d\n", sctp_arg_p->sd, strerror(errno), errno);
free(args_p);
args_p = NULL;
pthread_exit(NULL);
} else {
FD_SET(clientsock, &master); /* add to master set */
@@ -578,6 +581,7 @@ void *sctp_receiver_thread(void *args_p)
}
}
free(args_p);
args_p = NULL;
return NULL;
}
@@ -627,7 +631,7 @@ static void *sctp_intertask_interface(void *args_p)
ITTI_MSG_NAME(received_message_p));
} break;
}
free(received_message_p);
itti_free(ITTI_MSG_ORIGIN_ID(received_message_p), received_message_p);
received_message_p = NULL;
}
return NULL;
+4 -2
View File
@@ -256,7 +256,8 @@ static int sgi_nfqueue_callback(struct nfq_q_handle *myQueue, struct nfgenmsg *m
data_req_p->buffer = malloc(sizeof(uint8_t) * len);
if (data_req_p->buffer == NULL) {
SGI_IF_ERROR("Failed to allocate new buffer\n");
free(message_p);
itti_free(ITTI_MSG_ORIGIN_ID(message_p), message_p);
message_p = NULL;
return -1;
} else {
// MAY BE TO BE CHANGED
@@ -272,7 +273,8 @@ static int sgi_nfqueue_callback(struct nfq_q_handle *myQueue, struct nfgenmsg *m
if (itti_send_msg_to_task(TASK_GTPV1_U, INSTANCE_DEFAULT, message_p) < 0) {
SGI_IF_ERROR("Failed to send message to task\n");
free(message_p);
itti_free(ITTI_MSG_ORIGIN_ID(message_p), message_p);
message_p = NULL;
}
verdict = NF_STOLEN;
return nfq_set_verdict(myQueue, id, verdict, 0, NULL);
+2 -2
View File
@@ -103,7 +103,7 @@ static void* sgi_task_thread(void *args_p)
req_p = &received_message_p->ittiMsg.sgiCreateEndpointReq;
sgi_create_endpoint_request(sgi_data_p, req_p);
}
break;
@@ -121,7 +121,7 @@ static void* sgi_task_thread(void *args_p)
}
break;
}
free(received_message_p);
itti_free(ITTI_MSG_ORIGIN_ID(received_message_p), received_message_p);
received_message_p = NULL;
}
return NULL;
+2 -1
View File
@@ -20,4 +20,5 @@ libsgw_lite_la_SOURCES= \
sgw_lite_task.c \
sgw_lite_handlers.c sgw_lite_handlers.h \
sgw_lite_context_manager.c sgw_lite_context_manager.h \
sgw_lite.h sgw_lite_defs.h sgw_lite_ie_defs.h
sgw_lite.h sgw_lite_defs.h sgw_lite_ie_defs.h \
pgw_lite_paa.c pgw_lite_paa.h
+177
View File
@@ -0,0 +1,177 @@
/*******************************************************************************
Eurecom OpenAirInterface core network
Copyright(c) 1999 - 2014 Eurecom
This program is free software; you can redistribute it and/or modify it
under the terms and conditions of the GNU General Public License,
version 2, as published by the Free Software Foundation.
This program is distributed in the hope 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, write to the Free Software Foundation, Inc.,
51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
The full GNU General Public License is included in this distribution in
the file called "COPYING".
Contact Information
Openair Admin: openair_admin@eurecom.fr
Openair Tech : openair_tech@eurecom.fr
Forums : http://forums.eurecom.fsr/openairinterface
Address : EURECOM,
Campus SophiaTech,
450 Route des Chappes,
CS 50193
06904 Biot Sophia Antipolis cedex,
FRANCE
*******************************************************************************/
/*! \file pgw_lite_paa.c
* \brief
* \author Lionel Gauthier
* \company Eurecom
* \email: lionel.gauthier@eurecom.fr
*/
#include <stdint.h>
#include <errno.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include "intertask_interface.h"
#include "assertions.h"
#include "queue.h"
#include "pgw_lite_paa.h"
#include "sgw_lite_defs.h"
#include "spgw_config.h"
#include "sgw_lite.h"
//#define PGW_LITE_FREE_ADDR_POOL_CONFIG 1
extern pgw_app_t pgw_app;
// Load in PGW pool, configured PAA address pool
void pgw_lite_load_pool_ip_addresses(void) {
struct pgw_lite_conf_ipv4_list_elm_s *conf_ipv4_p = NULL;
struct pgw_lite_ipv4_list_elm_s *ipv4_p = NULL;
struct pgw_lite_conf_ipv6_list_elm_s *conf_ipv6_p = NULL;
struct pgw_lite_ipv6_list_elm_s *ipv6_p = NULL;
char print_buffer[INET6_ADDRSTRLEN];
STAILQ_INIT(&pgw_app.pgw_lite_ipv4_list_free);
STAILQ_INIT(&pgw_app.pgw_lite_ipv4_list_allocated);
STAILQ_INIT(&pgw_app.pgw_lite_ipv6_list_free);
STAILQ_INIT(&pgw_app.pgw_lite_ipv6_list_allocated);
STAILQ_FOREACH(conf_ipv4_p, &spgw_config.pgw_config.pgw_lite_ipv4_pool_list, ipv4_entries) {
ipv4_p = calloc(1, sizeof(struct pgw_lite_ipv4_list_elm_s));
ipv4_p->addr.s_addr = ntohl(conf_ipv4_p->addr.s_addr);
STAILQ_INSERT_TAIL(&pgw_app.pgw_lite_ipv4_list_free, ipv4_p, ipv4_entries);
SPGW_APP_DEBUG("Loaded IPv4 PAA address in pool: %s\n",
inet_ntoa(conf_ipv4_p->addr));
}
STAILQ_FOREACH(conf_ipv6_p, &spgw_config.pgw_config.pgw_lite_ipv6_pool_list, ipv6_entries) {
ipv6_p = calloc(1, sizeof(struct pgw_lite_ipv6_list_elm_s));
ipv6_p->addr = conf_ipv6_p->addr;
ipv6_p->prefix_len = conf_ipv6_p->prefix_len;
ipv6_p->num_allocated = 0;
STAILQ_INSERT_TAIL(&pgw_app.pgw_lite_ipv6_list_free, ipv6_p, ipv6_entries);
if (inet_ntop(AF_INET6, &ipv6_p->addr, print_buffer, INET6_ADDRSTRLEN) == NULL) {
SPGW_APP_ERROR("Could not Load IPv6 PAA address in pool: %s\n", strerror(errno));
} else {
SPGW_APP_DEBUG("Loaded IPv6 PAA prefix in pool: %s\n",print_buffer);
}
}
#if defined(PGW_LITE_FREE_ADDR_POOL_CONFIG)
while ((conf_ipv4_p = STAILQ_FIRST(&spgw_config.pgw_config.pgw_lite_ipv4_pool_list))) {
STAILQ_REMOVE_HEAD(&spgw_config.pgw_config.pgw_lite_ipv4_pool_list, ipv4_entries);
free(conf_ipv4_p);
}
while ((conf_ipv6_p = STAILQ_FIRST(&spgw_config.pgw_config.pgw_lite_ipv6_pool_list))) {
STAILQ_REMOVE_HEAD(&spgw_config.pgw_config.pgw_lite_ipv6_pool_list, ipv6_entries);
free(conf_ipv6_p);
}
#endif
}
int pgw_lite_get_free_ipv4_paa_address(struct in_addr * const addr_pP) {
struct pgw_lite_ipv4_list_elm_s *ipv4_p = NULL;
if (STAILQ_EMPTY(&pgw_app.pgw_lite_ipv4_list_free)) {
addr_pP->s_addr = INADDR_ANY;
return -1;
}
ipv4_p = STAILQ_FIRST(&pgw_app.pgw_lite_ipv4_list_free);
STAILQ_REMOVE(&pgw_app.pgw_lite_ipv4_list_free, ipv4_p, pgw_lite_ipv4_list_elm_s, ipv4_entries);
STAILQ_INSERT_TAIL(&pgw_app.pgw_lite_ipv4_list_allocated, ipv4_p, ipv4_entries);
addr_pP->s_addr = ipv4_p->addr.s_addr;
return 0;
}
int pgw_lite_release_free_ipv4_paa_address(const struct in_addr * const addr_pP) {
struct pgw_lite_ipv4_list_elm_s *ipv4_p = NULL;
STAILQ_FOREACH(ipv4_p, &pgw_app.pgw_lite_ipv4_list_allocated, ipv4_entries) {
if (ipv4_p->addr.s_addr == addr_pP->s_addr) {
STAILQ_REMOVE(&pgw_app.pgw_lite_ipv4_list_allocated, ipv4_p, pgw_lite_ipv4_list_elm_s, ipv4_entries);
STAILQ_INSERT_TAIL(&pgw_app.pgw_lite_ipv4_list_free, ipv4_p, ipv4_entries);
return 0;
}
}
return -1;
}
int pgw_lite_get_free_ipv6_paa_prefix(struct in6_addr * const addr_pP) {
struct pgw_lite_ipv6_list_elm_s *ipv6_p = NULL;
if (STAILQ_EMPTY(&pgw_app.pgw_lite_ipv6_list_free)) {
*addr_pP = in6addr_any;
return -1;
}
ipv6_p = STAILQ_FIRST(&pgw_app.pgw_lite_ipv6_list_free);
ipv6_p->num_allocated += 1;
ipv6_p->num_free -= 1;
if (ipv6_p->num_free == 0) {
STAILQ_REMOVE(&pgw_app.pgw_lite_ipv6_list_free, ipv6_p, pgw_lite_ipv6_list_elm_s, ipv6_entries);
STAILQ_INSERT_TAIL(&pgw_app.pgw_lite_ipv6_list_allocated, ipv6_p, ipv6_entries);
}
*addr_pP = ipv6_p->addr;
return 0;
}
int pgw_lite_release_free_ipv6_paa_prefix(const struct in6_addr * const addr_pP) {
struct pgw_lite_ipv6_list_elm_s *ipv6_p = NULL;
ipv6_p = STAILQ_FIRST(&pgw_app.pgw_lite_ipv6_list_free);
if (IN6_ARE_ADDR_EQUAL(&ipv6_p->addr, addr_pP)) {
ipv6_p->num_allocated -= 1;
ipv6_p->num_free += 1;
}
STAILQ_FOREACH(ipv6_p, &pgw_app.pgw_lite_ipv6_list_allocated, ipv6_entries) {
if (IN6_ARE_ADDR_EQUAL(&ipv6_p->addr, addr_pP)) {
STAILQ_REMOVE(&pgw_app.pgw_lite_ipv6_list_allocated, ipv6_p, pgw_lite_ipv6_list_elm_s, ipv6_entries);
ipv6_p->num_allocated -= 1;
ipv6_p->num_free += 1;
STAILQ_INSERT_TAIL(&pgw_app.pgw_lite_ipv6_list_free, ipv6_p, ipv6_entries);
return 0;
}
}
return -1;
}
+47
View File
@@ -0,0 +1,47 @@
/*******************************************************************************
Eurecom OpenAirInterface core network
Copyright(c) 1999 - 2014 Eurecom
This program is free software; you can redistribute it and/or modify it
under the terms and conditions of the GNU General Public License,
version 2, as published by the Free Software Foundation.
This program is distributed in the hope 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, write to the Free Software Foundation, Inc.,
51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
The full GNU General Public License is included in this distribution in
the file called "COPYING".
Contact Information
Openair Admin: openair_admin@eurecom.fr
Openair Tech : openair_tech@eurecom.fr
Forums : http://forums.eurecom.fsr/openairinterface
Address : EURECOM,
Campus SophiaTech,
450 Route des Chappes,
CS 50193
06904 Biot Sophia Antipolis cedex,
FRANCE
*******************************************************************************/
/*! \file pgw_lite_paa.h
* \brief
* \author Lionel Gauthier
* \company Eurecom
* \email: lionel.gauthier@eurecom.fr
*/
#ifndef PGW_LITE_PAA_H_
#define PGW_LITE_PAA_H_
void pgw_lite_load_pool_ip_addresses (void);
int pgw_lite_get_free_ipv4_paa_address (struct in_addr * const addr_P);
int pgw_lite_release_free_ipv4_paa_address (const struct in_addr * const addr_P);
int pgw_lite_get_free_ipv6_paa_prefix (struct in6_addr * const addr_pP);
int pgw_lite_release_free_ipv6_paa_prefix (const struct in6_addr * const addr_pP);
#endif
+22 -11
View File
@@ -38,7 +38,7 @@ Address : EURECOM,
#ifndef SGW_LITE_H_
#define SGW_LITE_H_
#include <netinet/in.h>
#include "hashtable.h"
#include "tree.h"
#include "commonDef.h"
@@ -46,7 +46,7 @@ Address : EURECOM,
#include "sgw_lite_context_manager.h"
typedef struct sgw_app_s{
char *sgw_interface_name_for_S1u_S12_S4_up;
uint32_t sgw_ip_address_for_S1u_S12_S4_up;
@@ -63,22 +63,33 @@ typedef struct sgw_app_s{
// the key of this hashtable is the S11 s-gw local teid.
hash_table_t *s11_bearer_context_information_hashtable;
} sgw_app_t;
typedef struct ipv4_address_s {
}ipv4_address_t;
typedef struct ipv6_address_s {
struct pgw_lite_ipv4_list_elm_s {
STAILQ_ENTRY(pgw_lite_ipv4_list_elm_s) ipv4_entries;
struct in_addr addr;
};
struct pgw_lite_ipv6_list_elm_s {
STAILQ_ENTRY(pgw_lite_ipv6_list_elm_s) ipv6_entries;
struct in6_addr addr;
int prefix_len;
int num_allocated;
int num_free;
} ;
}ipv6_address_t;
typedef struct pgw_app_s{
STAILQ_HEAD(free_ipv4_addresses_head_s, ipv4_address_s) free_ipv4_addresses_head;
STAILQ_HEAD(free_ipv6_addresses_head_s, ipv6_address_s) free_ipv6_addresses_head;
STAILQ_HEAD(allocated_ipv4_addresses_head_s, ipv4_address_s) allocated_ipv4_addresses_head;
STAILQ_HEAD(allocated_ipv6_addresses_head_s, ipv6_address_s) allocated_ipv6_addresses_head;
STAILQ_HEAD(pgw_lite_ipv4_list_free_head_s, pgw_lite_ipv4_list_elm_s) pgw_lite_ipv4_list_free;
STAILQ_HEAD(pgw_lite_ipv4_list_allocated_head_s, pgw_lite_ipv4_list_elm_s) pgw_lite_ipv4_list_allocated;
STAILQ_HEAD(pgw_lite_ipv6_list_free_head_s, pgw_lite_ipv6_list_elm_s) pgw_lite_ipv6_list_free;
STAILQ_HEAD(pgw_lite_ipv6_list_allocated_head_s, pgw_lite_ipv6_list_elm_s) pgw_lite_ipv6_list_allocated;
} pgw_app_t;
#endif
@@ -237,6 +237,7 @@ sgw_pdn_connection_t * sgw_lite_cm_create_pdn_connection(void)
if ( pdn_connection->sgw_eps_bearers == NULL) {
SPGW_APP_ERROR("Failed to create eps bearers collection object\n");
free(pdn_connection);
pdn_connection = NULL;
return NULL;
}
@@ -353,7 +354,7 @@ sgw_eps_bearer_entry_t * sgw_lite_cm_create_eps_bearer_entry_in_collection(hash_
SPGW_APP_DEBUG("Invalid sgw_eps_bearers hashtable for display\n");
}
/* CHECK DUPLICATES IN HASH TABLES ? if (temp == 1) {
SPGW_APP_WARNING("This EPS bearer entry already exists: %u\n", eps_bearer_idP);
SPGW_APP_WARN("This EPS bearer entry already exists: %u\n", eps_bearer_idP);
free(new_eps_bearer_entry);
new_eps_bearer_entry = collision_p;
}*/
@@ -192,7 +192,7 @@ typedef struct sgw_eps_bearer_context_information_s {
void *trxn;
uint32_t peer_ip;
MessageDef* initial_message_p;
SgwCreateSessionRequest saved_message;
} sgw_eps_bearer_context_information_t;
/********************************
+16 -11
View File
@@ -39,19 +39,24 @@ Address : EURECOM,
#ifndef SGW_LITE_DEFS_H_
#define SGW_LITE_DEFS_H_
#ifndef SPGW_APP_DEBUG
# define SPGW_APP_DEBUG(x, args...) do { fprintf(stdout, "[SPGW-APP] [D]"x, ##args); } \
while(0)
#endif
#ifndef SPGW_APP_WARNING
# define SPGW_APP_WARNING(x, args...) do { fprintf(stdout, "[SPGW-APP] [W]"x, ##args); } \
while(0)
#endif
#ifndef SPGW_APP_ERROR
# define SPGW_APP_ERROR(x, args...) do { fprintf(stderr, "[SPGW-APP] [E]"x, ##args); } \
while(0)
#if defined(ENB_MODE)
# include "UTIL/LOG/log.h"
# define SPGW_APP_ERROR(x, args...) LOG_E(SPGW, x, ##args)
# define SPGW_APP_WARN(x, args...) LOG_W(SPGW, x, ##args)
# define SPGW_APP_TRACE(x, args...) LOG_T(SPGW, x, ##args)
# define SPGW_APP_INFO(x, args...) LOG_I(SPGW, x, ##args)
# define SPGW_APP_DEBUG(x, args...) LOG_I(SPGW, x, ##args)
#else
# define SPGW_APP_ERROR(x, args...) do { fprintf(stdout, "[SPGW-APP][E]"x, ##args); } while(0)
# define SPGW_APP_WARN(x, args...) do { fprintf(stdout, "[SPGW-APP][W]"x, ##args); } while(0)
# define SPGW_APP_TRACE(x, args...) do { fprintf(stdout, "[SPGW-APP][T]"x, ##args); } while(0)
# define SPGW_APP_INFO(x, args...) do { fprintf(stdout, "[SPGW-APP][I]"x, ##args); } while(0)
# define SPGW_APP_DEBUG(x, args...) do { fprintf(stdout, "[SPGW-APP][D]"x, ##args); } while(0)
#endif
int sgw_lite_init(char* config_file_name_pP);
#endif /* SGW_LITE_DEFS_H_ */
+306 -206
View File
@@ -42,8 +42,10 @@ Address : EURECOM,
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <netinet/in.h>
#include "assertions.h"
#include "conversions.h"
#include "common_types.h"
#include "intertask_interface.h"
#include "mme_config.h"
@@ -52,22 +54,27 @@ Address : EURECOM,
#include "sgw_lite_handlers.h"
#include "sgw_lite_context_manager.h"
#include "sgw_lite.h"
#include "pgw_lite_paa.h"
extern sgw_app_t sgw_app;
int sgw_lite_handle_create_session_request(SgwCreateSessionRequest *session_req_p)
int
sgw_lite_handle_create_session_request(
const SgwCreateSessionRequest * const session_req_pP)
{
mme_sgw_tunnel_t* new_endpoint = NULL;
s_plus_p_gw_eps_bearer_context_information_t* s_plus_p_gw_eps_bearer_context_information = NULL;
sgw_eps_bearer_entry_t* eps_bearer_entry_p = NULL;
MessageDef* message_p = NULL;
mme_sgw_tunnel_t* new_endpoint_p = NULL;
s_plus_p_gw_eps_bearer_context_information_t* s_plus_p_gw_eps_bearer_ctxt_info_p = NULL;
sgw_eps_bearer_entry_t* eps_bearer_entry_p = NULL;
MessageDef* message_p = NULL;
/* Upon reception of create session request from MME,
* S-GW should create UE, eNB and MME contexts and forward message to P-GW.
*/
if (session_req_p->rat_type != RAT_EUTRAN) {
SPGW_APP_WARNING("Received session request with RAT != RAT_TYPE_EUTRAN: type %d\n",
session_req_p->rat_type);
if (session_req_pP->rat_type != RAT_EUTRAN) {
SPGW_APP_WARN("Received session request with RAT != RAT_TYPE_EUTRAN: type %d\n",
session_req_pP->rat_type);
}
/* As we are abstracting GTP-C transport, FTeid ip address is useless.
@@ -78,29 +85,31 @@ int sgw_lite_handle_create_session_request(SgwCreateSessionRequest *session_req_
* Communication between MME and S-GW involves S11 interface so we are expecting
* S11_MME_GTP_C (11) as interface_type.
*/
if ((session_req_p->sender_fteid_for_cp.teid == 0) &&
(session_req_p->sender_fteid_for_cp.interface_type != S11_MME_GTP_C)) {
if ((session_req_pP->sender_fteid_for_cp.teid == 0) &&
(session_req_pP->sender_fteid_for_cp.interface_type != S11_MME_GTP_C)) {
/* MME sent request with teid = 0. This is not valid... */
SPGW_APP_WARNING("F-TEID parameter mismatch\n");
SPGW_APP_WARN("F-TEID parameter mismatch\n");
return -1;
}
new_endpoint = sgw_lite_cm_create_s11_tunnel(session_req_p->sender_fteid_for_cp.teid, sgw_lite_get_new_S11_tunnel_id());
if (new_endpoint == NULL) {
SPGW_APP_WARNING("Could not create new tunnel endpoint between S-GW and MME "
new_endpoint_p = sgw_lite_cm_create_s11_tunnel(
session_req_pP->sender_fteid_for_cp.teid,
sgw_lite_get_new_S11_tunnel_id());
if (new_endpoint_p == NULL) {
SPGW_APP_WARN("Could not create new tunnel endpoint between S-GW and MME "
"for S11 abstraction\n");
return -1;
}
SPGW_APP_DEBUG("Rx CREATE-SESSION-REQUEST MME S11 teid %u S-GW S11 teid %u APN %s EPS bearer Id %d\n",
new_endpoint->remote_teid,
new_endpoint->local_teid,
session_req_p->apn,
session_req_p->bearer_to_create.eps_bearer_id);
new_endpoint_p->remote_teid,
new_endpoint_p->local_teid,
session_req_pP->apn,
session_req_pP->bearer_to_create.eps_bearer_id);
SPGW_APP_DEBUG(" IMSI %c%c%c%c%c%c%c%c%c%c%c%c%c%c%c\n",
IMSI(&session_req_p->imsi));
IMSI(&session_req_pP->imsi));
s_plus_p_gw_eps_bearer_context_information = sgw_lite_cm_create_bearer_context_information_in_collection(new_endpoint->local_teid);
if (s_plus_p_gw_eps_bearer_context_information != NULL) {
s_plus_p_gw_eps_bearer_ctxt_info_p = sgw_lite_cm_create_bearer_context_information_in_collection(new_endpoint_p->local_teid);
if (s_plus_p_gw_eps_bearer_ctxt_info_p != NULL) {
/* We try to create endpoint for S11 interface. A NULL endpoint means that
* either the teid is already in list of known teid or ENOMEM error has been
* raised during malloc.
@@ -109,20 +118,20 @@ int sgw_lite_handle_create_session_request(SgwCreateSessionRequest *session_req_
//--------------------------------------------------
// copy informations from create session request to bearer context information
//--------------------------------------------------
memcpy(s_plus_p_gw_eps_bearer_context_information->sgw_eps_bearer_context_information.imsi.digit, session_req_p->imsi.digit, IMSI_DIGITS_MAX);
memcpy(s_plus_p_gw_eps_bearer_context_information->pgw_eps_bearer_context_information.imsi.digit, session_req_p->imsi.digit, IMSI_DIGITS_MAX);
s_plus_p_gw_eps_bearer_context_information->sgw_eps_bearer_context_information.imsi_unauthenticated_indicator = 1;
s_plus_p_gw_eps_bearer_context_information->pgw_eps_bearer_context_information.imsi_unauthenticated_indicator = 1;
memcpy(s_plus_p_gw_eps_bearer_ctxt_info_p->sgw_eps_bearer_context_information.imsi.digit, session_req_pP->imsi.digit, IMSI_DIGITS_MAX);
memcpy(s_plus_p_gw_eps_bearer_ctxt_info_p->pgw_eps_bearer_context_information.imsi.digit, session_req_pP->imsi.digit, IMSI_DIGITS_MAX);
s_plus_p_gw_eps_bearer_ctxt_info_p->sgw_eps_bearer_context_information.imsi_unauthenticated_indicator = 1;
s_plus_p_gw_eps_bearer_ctxt_info_p->pgw_eps_bearer_context_information.imsi_unauthenticated_indicator = 1;
s_plus_p_gw_eps_bearer_context_information->sgw_eps_bearer_context_information.mme_teid_for_S11 = session_req_p->sender_fteid_for_cp.teid;
s_plus_p_gw_eps_bearer_context_information->sgw_eps_bearer_context_information.s_gw_teid_for_S11_S4 = new_endpoint->local_teid;
s_plus_p_gw_eps_bearer_context_information->sgw_eps_bearer_context_information.trxn = session_req_p->trxn;
s_plus_p_gw_eps_bearer_context_information->sgw_eps_bearer_context_information.peer_ip = session_req_p->peer_ip;
s_plus_p_gw_eps_bearer_ctxt_info_p->sgw_eps_bearer_context_information.mme_teid_for_S11 = session_req_pP->sender_fteid_for_cp.teid;
s_plus_p_gw_eps_bearer_ctxt_info_p->sgw_eps_bearer_context_information.s_gw_teid_for_S11_S4 = new_endpoint_p->local_teid;
s_plus_p_gw_eps_bearer_ctxt_info_p->sgw_eps_bearer_context_information.trxn = session_req_pP->trxn;
s_plus_p_gw_eps_bearer_ctxt_info_p->sgw_eps_bearer_context_information.peer_ip = session_req_pP->peer_ip;
// may use ntohl or reverse, will see
FTEID_T_2_IP_ADDRESS_T(
(&session_req_p->sender_fteid_for_cp) ,
(&s_plus_p_gw_eps_bearer_context_information->sgw_eps_bearer_context_information.mme_ip_address_for_S11));
(&session_req_pP->sender_fteid_for_cp) ,
(&s_plus_p_gw_eps_bearer_ctxt_info_p->sgw_eps_bearer_context_information.mme_ip_address_for_S11));
//--------------------------------------
// PDN connection
@@ -134,48 +143,52 @@ int sgw_lite_handle_create_session_request(SgwCreateSessionRequest *session_req_
SPGW_APP_ERROR("Failed to create new PDN connection\n");
return -1;
}*/
memset(&s_plus_p_gw_eps_bearer_context_information->sgw_eps_bearer_context_information.pdn_connection, 0, sizeof(sgw_pdn_connection_t));
s_plus_p_gw_eps_bearer_context_information->sgw_eps_bearer_context_information.pdn_connection.sgw_eps_bearers = hashtable_create(12, NULL, NULL);
if ( s_plus_p_gw_eps_bearer_context_information->sgw_eps_bearer_context_information.pdn_connection.sgw_eps_bearers == NULL) {
memset(&s_plus_p_gw_eps_bearer_ctxt_info_p->sgw_eps_bearer_context_information.pdn_connection, 0, sizeof(sgw_pdn_connection_t));
s_plus_p_gw_eps_bearer_ctxt_info_p->sgw_eps_bearer_context_information.pdn_connection.sgw_eps_bearers = hashtable_create(12, NULL, NULL);
if ( s_plus_p_gw_eps_bearer_ctxt_info_p->sgw_eps_bearer_context_information.pdn_connection.sgw_eps_bearers == NULL) {
SPGW_APP_ERROR("Failed to create eps bearers collection object\n");
DevMessage("Failed to create eps bearers collection object\n");
return -1;
}
if (session_req_p->apn) {
s_plus_p_gw_eps_bearer_context_information->sgw_eps_bearer_context_information.pdn_connection.apn_in_use = strdup(session_req_p->apn);
} else {
s_plus_p_gw_eps_bearer_context_information->sgw_eps_bearer_context_information.pdn_connection.apn_in_use = "NO APN";
}
s_plus_p_gw_eps_bearer_context_information->sgw_eps_bearer_context_information.pdn_connection.default_bearer = session_req_p->bearer_to_create.eps_bearer_id;
//obj_hashtable_insert(s_plus_p_gw_eps_bearer_context_information->sgw_eps_bearer_context_information.pdn_connections, pdn_connection->apn_in_use, strlen(pdn_connection->apn_in_use), pdn_connection);
if (session_req_pP->apn) {
s_plus_p_gw_eps_bearer_ctxt_info_p->sgw_eps_bearer_context_information.pdn_connection.apn_in_use = strdup(session_req_pP->apn);
} else {
s_plus_p_gw_eps_bearer_ctxt_info_p->sgw_eps_bearer_context_information.pdn_connection.apn_in_use = "NO APN";
}
s_plus_p_gw_eps_bearer_ctxt_info_p->sgw_eps_bearer_context_information.pdn_connection.default_bearer = session_req_pP->bearer_to_create.eps_bearer_id;
//obj_hashtable_insert(s_plus_p_gw_eps_bearer_ctxt_info_p->sgw_eps_bearer_context_information.pdn_connections, pdn_connection->apn_in_use, strlen(pdn_connection->apn_in_use), pdn_connection);
//--------------------------------------
// EPS bearer entry
//--------------------------------------
eps_bearer_entry_p = sgw_lite_cm_create_eps_bearer_entry_in_collection(
s_plus_p_gw_eps_bearer_context_information->sgw_eps_bearer_context_information.pdn_connection.sgw_eps_bearers,
session_req_p->bearer_to_create.eps_bearer_id);
s_plus_p_gw_eps_bearer_ctxt_info_p->sgw_eps_bearer_context_information.pdn_connection.sgw_eps_bearers,
session_req_pP->bearer_to_create.eps_bearer_id);
sgw_lite_display_s11teid2mme_mappings();
sgw_lite_display_s11_bearer_context_information_mapping();
if (eps_bearer_entry_p == NULL) {
SPGW_APP_ERROR("Failed to create new EPS bearer entry\n");
// TO DO FREE new_bearer_context_information_p and by cascade...
// TO DO FREE new_bearer_ctxt_info_p and by cascade...
return -1;
}
eps_bearer_entry_p->eps_bearer_qos = session_req_p->bearer_to_create.bearer_level_qos;
eps_bearer_entry_p->eps_bearer_qos = session_req_pP->bearer_to_create.bearer_level_qos;
//s_plus_p_gw_eps_bearer_context_information->sgw_eps_bearer_context_informationteid = teid;
//s_plus_p_gw_eps_bearer_ctxt_info_p->sgw_eps_bearer_context_informationteid = teid;
/* Trying to insert the new tunnel into the tree.
* If collision_p is not NULL (0), it means tunnel is already present.
*/
//s_plus_p_gw_eps_bearer_context_information->sgw_eps_bearer_context_informations_gw_ip_address_for_S11_S4 =
//s_plus_p_gw_eps_bearer_ctxt_info_p->sgw_eps_bearer_context_informations_gw_ip_address_for_S11_S4 =
memcpy(&s_plus_p_gw_eps_bearer_ctxt_info_p->sgw_eps_bearer_context_information.saved_message,
session_req_pP,
sizeof(SgwCreateSessionRequest));
/* Establishing EPS bearer. Requesting S1-U (GTPV1-U) task to create a
* tunnel for S1 user plane interface. If status in response is successfull (0),
@@ -183,35 +196,40 @@ int sgw_lite_handle_create_session_request(SgwCreateSessionRequest *session_req_
*/
message_p = itti_alloc_new_message(TASK_SPGW_APP, GTPV1U_CREATE_TUNNEL_REQ);
if (message_p == NULL) {
sgw_lite_cm_remove_s11_tunnel(new_endpoint->remote_teid);
sgw_lite_cm_remove_s11_tunnel(new_endpoint_p->remote_teid);
return -1;
}
message_p->ittiMsg.gtpv1uCreateTunnelReq.context_teid = new_endpoint->local_teid;
message_p->ittiMsg.gtpv1uCreateTunnelReq.eps_bearer_id = session_req_p->bearer_to_create.eps_bearer_id;
message_p->ittiMsg.gtpv1uCreateTunnelReq.context_teid = new_endpoint_p->local_teid;
message_p->ittiMsg.gtpv1uCreateTunnelReq.eps_bearer_id = session_req_pP->bearer_to_create.eps_bearer_id;
SPGW_APP_DEBUG("Tx GTPV1U_CREATE_TUNNEL_REQ -> TASK_GTPV1_U, Context: S-GW S11 teid %u eps bearer id %d (from session req)\n",
message_p->ittiMsg.gtpv1uCreateTunnelReq.context_teid,
message_p->ittiMsg.gtpv1uCreateTunnelReq.eps_bearer_id);
message_p->ittiMsg.gtpv1uCreateTunnelReq.context_teid,
message_p->ittiMsg.gtpv1uCreateTunnelReq.eps_bearer_id);
return itti_send_msg_to_task(TASK_GTPV1_U, INSTANCE_DEFAULT, message_p);
} else {
SPGW_APP_WARNING("Could not create new transaction for SESSION_CREATE message\n");
free(new_endpoint);
SPGW_APP_WARN("Could not create new transaction for SESSION_CREATE message\n");
free(new_endpoint_p);
new_endpoint_p = NULL;
return -1;
}
}
int sgw_lite_handle_sgi_endpoint_created(SGICreateEndpointResp *resp_p)
int
sgw_lite_handle_sgi_endpoint_created(
const SGICreateEndpointResp * const resp_pP)
{
task_id_t to_task;
SgwCreateSessionResponse *create_session_response_p = NULL;
s_plus_p_gw_eps_bearer_context_information_t *new_bearer_context_information_p = NULL;
MessageDef *message_p = NULL;
hashtable_rc_t hash_rc;
SgwCreateSessionResponse *create_session_response_p = NULL;
s_plus_p_gw_eps_bearer_context_information_t *new_bearer_ctxt_info_p = NULL;
MessageDef *message_p = NULL;
hashtable_rc_t hash_rc;
SPGW_APP_DEBUG("Rx SGI_CREATE_ENDPOINT_RESPONSE,Context: S11 teid %u, SGW S1U teid %u EPS bearer id %u\n",
resp_p->context_teid, resp_p->sgw_S1u_teid, resp_p->eps_bearer_id);
hash_rc = hashtable_get(sgw_app.s11_bearer_context_information_hashtable, resp_p->context_teid, (void**)&new_bearer_context_information_p);
resp_pP->context_teid, resp_pP->sgw_S1u_teid, resp_pP->eps_bearer_id);
hash_rc = hashtable_get(sgw_app.s11_bearer_context_information_hashtable, resp_pP->context_teid, (void**)&new_bearer_ctxt_info_p);
#if defined(ENABLE_STANDALONE_EPC)
to_task = TASK_MME_APP;
@@ -226,21 +244,25 @@ int sgw_lite_handle_sgi_endpoint_created(SGICreateEndpointResp *resp_p)
}
create_session_response_p = &message_p->ittiMsg.sgwCreateSessionResponse;
memset(create_session_response_p, 0, sizeof(SgwCreateSessionResponse));
if (hash_rc == HASH_TABLE_OK) {
create_session_response_p->teid = new_bearer_context_information_p->sgw_eps_bearer_context_information.mme_teid_for_S11;
create_session_response_p->teid = new_bearer_ctxt_info_p->sgw_eps_bearer_context_information.mme_teid_for_S11;
/* Preparing to send create session response on S11 abstraction interface.
* we set the cause value regarding the S1-U bearer establishment result status.
*/
if (resp_p->status == 0) {
if (resp_pP->status == 0) {
uint32_t address = sgw_app.sgw_ip_address_for_S1u_S12_S4_up;
create_session_response_p->bearer_context_created.s1u_sgw_fteid.teid = resp_p->sgw_S1u_teid;
create_session_response_p->bearer_context_created.s1u_sgw_fteid.teid = resp_pP->sgw_S1u_teid;
create_session_response_p->bearer_context_created.s1u_sgw_fteid.interface_type = S1_U_SGW_GTP_U;
create_session_response_p->bearer_context_created.s1u_sgw_fteid.ipv4 = 1;
/* Should be filled in with S-GW S1-U local address. Running everything on localhost for now */
create_session_response_p->bearer_context_created.s1u_sgw_fteid.ipv4_address = address;
memcpy(&create_session_response_p->paa,
&resp_pP->paa,
sizeof(PAA_t));
/* Set the Cause information from bearer context created.
* "Request accepted" is returned when the GTPv2 entity has accepted a control plane request.
*/
@@ -250,10 +272,10 @@ int sgw_lite_handle_sgi_endpoint_created(SGICreateEndpointResp *resp_p)
create_session_response_p->cause = M_PDN_APN_NOT_ALLOWED;
create_session_response_p->bearer_context_created.cause = M_PDN_APN_NOT_ALLOWED;
}
create_session_response_p->s11_sgw_teid.teid = resp_p->context_teid;
create_session_response_p->bearer_context_created.eps_bearer_id = resp_p->eps_bearer_id;
create_session_response_p->trxn = new_bearer_context_information_p->sgw_eps_bearer_context_information.trxn;
create_session_response_p->peer_ip = new_bearer_context_information_p->sgw_eps_bearer_context_information.peer_ip;
create_session_response_p->s11_sgw_teid.teid = resp_pP->context_teid;
create_session_response_p->bearer_context_created.eps_bearer_id = resp_pP->eps_bearer_id;
create_session_response_p->trxn = new_bearer_ctxt_info_p->sgw_eps_bearer_context_information.trxn;
create_session_response_p->peer_ip = new_bearer_ctxt_info_p->sgw_eps_bearer_context_information.peer_ip;
} else {
create_session_response_p->cause = CONTEXT_NOT_FOUND;
create_session_response_p->bearer_context_created.cause = CONTEXT_NOT_FOUND;
@@ -270,16 +292,22 @@ int sgw_lite_handle_sgi_endpoint_created(SGICreateEndpointResp *resp_p)
return itti_send_msg_to_task(to_task, INSTANCE_DEFAULT, message_p);
}
int sgw_lite_handle_gtpv1uCreateTunnelResp(Gtpv1uCreateTunnelResp *endpoint_created_p)
int
sgw_lite_handle_gtpv1uCreateTunnelResp(
const Gtpv1uCreateTunnelResp * const endpoint_created_pP)
{
task_id_t to_task;
SgwCreateSessionResponse *create_session_response_p = NULL;
s_plus_p_gw_eps_bearer_context_information_t *new_bearer_context_information_p = NULL;
SGICreateEndpointReq *sgi_create_endpoint_req_p = NULL;
MessageDef *message_p = NULL;
sgw_eps_bearer_entry_t *eps_bearer_entry_p = NULL;
hashtable_rc_t hash_rc;
SgwCreateSessionResponse *create_session_response_p = NULL;
s_plus_p_gw_eps_bearer_context_information_t *new_bearer_ctxt_info_p = NULL;
SGICreateEndpointReq *sgi_create_endpoint_req_p = NULL;
MessageDef *message_p = NULL;
sgw_eps_bearer_entry_t *eps_bearer_entry_p = NULL;
hashtable_rc_t hash_rc;
struct in_addr inaddr ;
struct in6_addr in6addr = IN6ADDR_ANY_INIT;
#if defined(ENABLE_STANDALONE_EPC)
to_task = TASK_MME_APP;
@@ -288,19 +316,28 @@ int sgw_lite_handle_gtpv1uCreateTunnelResp(Gtpv1uCreateTunnelResp *endpoint_crea
#endif
SPGW_APP_DEBUG("Rx GTPV1U_CREATE_TUNNEL_RESP, Context S-GW S11 teid %u, S-GW S1U teid %u EPS bearer id %u status %d\n",
endpoint_created_p->context_teid,
endpoint_created_p->S1u_teid,
endpoint_created_p->eps_bearer_id,
endpoint_created_p->status);
hash_rc = hashtable_get(sgw_app.s11_bearer_context_information_hashtable, endpoint_created_p->context_teid, (void**)&new_bearer_context_information_p);
endpoint_created_pP->context_teid,
endpoint_created_pP->S1u_teid,
endpoint_created_pP->eps_bearer_id,
endpoint_created_pP->status);
hash_rc = hashtable_get(
sgw_app.s11_bearer_context_information_hashtable,
endpoint_created_pP->context_teid,
(void**)&new_bearer_ctxt_info_p);
if (hash_rc == HASH_TABLE_OK) {
hash_rc = hashtable_get (new_bearer_context_information_p->sgw_eps_bearer_context_information.pdn_connection.sgw_eps_bearers, endpoint_created_p->eps_bearer_id, (void**)&eps_bearer_entry_p);
hash_rc = hashtable_get (
new_bearer_ctxt_info_p->sgw_eps_bearer_context_information.pdn_connection.sgw_eps_bearers,
endpoint_created_pP->eps_bearer_id,
(void**)&eps_bearer_entry_p);
DevAssert(hash_rc == HASH_TABLE_OK);
SPGW_APP_DEBUG("Updated eps_bearer_entry_p eps_b_id %u with SGW S1U teid %u\n", endpoint_created_p->eps_bearer_id, endpoint_created_p->S1u_teid);
eps_bearer_entry_p->s_gw_teid_for_S1u_S12_S4_up = endpoint_created_p->S1u_teid;
SPGW_APP_DEBUG("Updated eps_bearer_entry_p eps_b_id %u with SGW S1U teid %u\n",
endpoint_created_pP->eps_bearer_id,
endpoint_created_pP->S1u_teid);
eps_bearer_entry_p->s_gw_teid_for_S1u_S12_S4_up = endpoint_created_pP->S1u_teid;
sgw_lite_display_s11_bearer_context_information_mapping();
@@ -309,17 +346,64 @@ int sgw_lite_handle_gtpv1uCreateTunnelResp(Gtpv1uCreateTunnelResp *endpoint_crea
if (message_p == NULL) {
return -1;
}
sgi_create_endpoint_req_p = &message_p->ittiMsg.sgiCreateEndpointReq;
// IP forward will forward packets to this teid
sgi_create_endpoint_req_p->context_teid = endpoint_created_p->context_teid;
sgi_create_endpoint_req_p->sgw_S1u_teid = endpoint_created_p->S1u_teid;
sgi_create_endpoint_req_p->eps_bearer_id = endpoint_created_p->eps_bearer_id;
//create_sgi_endpoint_req_p->pdn_type = new_bearer_context_information_p->
sgi_create_endpoint_req_p = &message_p->ittiMsg.sgiCreateEndpointReq;
memset(sgi_create_endpoint_req_p, 0, sizeof(SGICreateEndpointReq));
// IP forward will forward packets to this teid
sgi_create_endpoint_req_p->context_teid = endpoint_created_pP->context_teid;
sgi_create_endpoint_req_p->sgw_S1u_teid = endpoint_created_pP->S1u_teid;
sgi_create_endpoint_req_p->eps_bearer_id = endpoint_created_pP->eps_bearer_id;
// TO DO NOW
sgi_create_endpoint_req_p->paa.pdn_type = new_bearer_ctxt_info_p->sgw_eps_bearer_context_information.saved_message.pdn_type;
switch (sgi_create_endpoint_req_p->paa.pdn_type) {
case IPv4_OR_v6:
if (pgw_lite_get_free_ipv4_paa_address(&inaddr) == 0) {
IN_ADDR_TO_BUFFER(inaddr, sgi_create_endpoint_req_p->paa.ipv4_address);
} else {
SPGW_APP_WARN("Failed to allocate IPv4 PAA for PDN type IPv4_OR_v6\n");
if (pgw_lite_get_free_ipv6_paa_prefix(&in6addr) == 0) {
IN6_ADDR_TO_BUFFER(in6addr, sgi_create_endpoint_req_p->paa.ipv6_address);
} else {
SPGW_APP_ERROR("Failed to allocate IPv6 PAA for PDN type IPv4_OR_v6\n");
}
}
break;
case IPv4:
if (pgw_lite_get_free_ipv4_paa_address(&inaddr) == 0) {
IN_ADDR_TO_BUFFER(inaddr, sgi_create_endpoint_req_p->paa.ipv4_address);
} else {
SPGW_APP_ERROR("Failed to allocate IPv4 PAA for PDN type IPv4\n");
}
break;
case IPv6:
if (pgw_lite_get_free_ipv6_paa_prefix(&in6addr) == 0) {
IN6_ADDR_TO_BUFFER(in6addr, sgi_create_endpoint_req_p->paa.ipv6_address);
} else {
SPGW_APP_ERROR("Failed to allocate IPv6 PAA for PDN type IPv6\n");
}
break;
case IPv4_AND_v6:
if (pgw_lite_get_free_ipv4_paa_address(&inaddr) == 0) {
IN_ADDR_TO_BUFFER(inaddr, sgi_create_endpoint_req_p->paa.ipv4_address);
} else {
SPGW_APP_ERROR("Failed to allocate IPv4 PAA for PDN type IPv4_AND_v6\n");
}
if (pgw_lite_get_free_ipv6_paa_prefix(&in6addr) == 0) {
IN6_ADDR_TO_BUFFER(in6addr, sgi_create_endpoint_req_p->paa.ipv6_address);
} else {
SPGW_APP_ERROR("Failed to allocate IPv6 PAA for PDN type IPv4_AND_v6\n");
}
break;
default:
AssertFatal(0,"BAD paa.pdn_type %d", sgi_create_endpoint_req_p->paa.pdn_type);
break;
}
// TO DO TFT, QOS
return itti_send_msg_to_task(TASK_FW_IP, INSTANCE_DEFAULT, message_p);
} else {
SPGW_APP_DEBUG("Rx SGW_S1U_ENDPOINT_CREATED, Context: teid %u NOT FOUND\n", endpoint_created_p->context_teid);
SPGW_APP_DEBUG("Rx SGW_S1U_ENDPOINT_CREATED, Context: teid %u NOT FOUND\n", endpoint_created_pP->context_teid);
message_p = itti_alloc_new_message(TASK_SPGW_APP, SGW_CREATE_SESSION_RESPONSE);
if (message_p == NULL) {
return -1;
@@ -332,14 +416,18 @@ int sgw_lite_handle_gtpv1uCreateTunnelResp(Gtpv1uCreateTunnelResp *endpoint_crea
}
}
int sgw_lite_handle_gtpv1uUpdateTunnelResp(Gtpv1uUpdateTunnelResp *endpoint_updated_p)
int
sgw_lite_handle_gtpv1uUpdateTunnelResp(
const Gtpv1uUpdateTunnelResp * const endpoint_updated_pP)
{
SgwModifyBearerResponse *modify_response_p = NULL;
SGIUpdateEndpointReq *update_request_p = NULL;
s_plus_p_gw_eps_bearer_context_information_t *new_bearer_context_information_p = NULL;
MessageDef *message_p = NULL;
sgw_eps_bearer_entry_t *eps_bearer_entry_p = NULL;
hashtable_rc_t hash_rc;
SgwModifyBearerResponse *modify_response_p = NULL;
SGIUpdateEndpointReq *update_request_p = NULL;
s_plus_p_gw_eps_bearer_context_information_t *new_bearer_ctxt_info_p = NULL;
MessageDef *message_p = NULL;
sgw_eps_bearer_entry_t *eps_bearer_entry_p = NULL;
hashtable_rc_t hash_rc;
task_id_t to_task;
#if defined(ENABLE_STANDALONE_EPC)
@@ -349,22 +437,22 @@ int sgw_lite_handle_gtpv1uUpdateTunnelResp(Gtpv1uUpdateTunnelResp *endpoint_upda
#endif
SPGW_APP_DEBUG("Rx GTPV1U_UPDATE_TUNNEL_RESP, Context teid %u, SGW S1U teid %u, eNB S1U teid %u, EPS bearer id %u, status %d\n",
endpoint_updated_p->context_teid,
endpoint_updated_p->sgw_S1u_teid,
endpoint_updated_p->enb_S1u_teid,
endpoint_updated_p->eps_bearer_id,
endpoint_updated_p->status);
endpoint_updated_pP->context_teid,
endpoint_updated_pP->sgw_S1u_teid,
endpoint_updated_pP->enb_S1u_teid,
endpoint_updated_pP->eps_bearer_id,
endpoint_updated_pP->status);
hash_rc = hashtable_get(sgw_app.s11_bearer_context_information_hashtable, endpoint_updated_p->context_teid, (void**)&new_bearer_context_information_p);
hash_rc = hashtable_get(sgw_app.s11_bearer_context_information_hashtable, endpoint_updated_pP->context_teid, (void**)&new_bearer_ctxt_info_p);
if (hash_rc == HASH_TABLE_OK) {
hash_rc = hashtable_get (new_bearer_context_information_p->sgw_eps_bearer_context_information.pdn_connection.sgw_eps_bearers, endpoint_updated_p->eps_bearer_id, (void**)&eps_bearer_entry_p);
hash_rc = hashtable_get (new_bearer_ctxt_info_p->sgw_eps_bearer_context_information.pdn_connection.sgw_eps_bearers, endpoint_updated_pP->eps_bearer_id, (void**)&eps_bearer_entry_p);
if ((hash_rc == HASH_TABLE_KEY_NOT_EXISTS) || (hash_rc == HASH_TABLE_BAD_PARAMETER_HASHTABLE)) {
SPGW_APP_DEBUG("Sending SGW_MODIFY_BEARER_RESPONSE trxn %p bearer %u CONTEXT_NOT_FOUND (sgw_eps_bearers)\n",
new_bearer_context_information_p->sgw_eps_bearer_context_information.trxn,
endpoint_updated_p->eps_bearer_id);
new_bearer_ctxt_info_p->sgw_eps_bearer_context_information.trxn,
endpoint_updated_pP->eps_bearer_id);
message_p = itti_alloc_new_message(TASK_SPGW_APP, SGW_MODIFY_BEARER_RESPONSE);
if (message_p == NULL) {
@@ -372,11 +460,11 @@ int sgw_lite_handle_gtpv1uUpdateTunnelResp(Gtpv1uUpdateTunnelResp *endpoint_upda
}
modify_response_p = &message_p->ittiMsg.sgwModifyBearerResponse;
memset(modify_response_p, 0, sizeof(SgwModifyBearerResponse));
modify_response_p->present = MODIFY_BEARER_RESPONSE_REM;
modify_response_p->choice.bearer_for_removal.eps_bearer_id = endpoint_updated_p->eps_bearer_id;
modify_response_p->choice.bearer_for_removal.cause = CONTEXT_NOT_FOUND;
modify_response_p->cause = CONTEXT_NOT_FOUND;
modify_response_p->trxn = new_bearer_context_information_p->sgw_eps_bearer_context_information.trxn;
modify_response_p->bearer_present = MODIFY_BEARER_RESPONSE_REM;
modify_response_p->bearer_choice.bearer_for_removal.eps_bearer_id = endpoint_updated_pP->eps_bearer_id;
modify_response_p->bearer_choice.bearer_for_removal.cause = CONTEXT_NOT_FOUND;
modify_response_p->cause = CONTEXT_NOT_FOUND;
modify_response_p->trxn = new_bearer_ctxt_info_p->sgw_eps_bearer_context_information.trxn;
return itti_send_msg_to_task(to_task, INSTANCE_DEFAULT, message_p);
} else if (hash_rc == HASH_TABLE_OK) {
@@ -387,17 +475,17 @@ int sgw_lite_handle_gtpv1uUpdateTunnelResp(Gtpv1uUpdateTunnelResp *endpoint_upda
}
update_request_p = &message_p->ittiMsg.sgiUpdateEndpointReq;
memset(update_request_p, 0, sizeof(SGIUpdateEndpointReq));
update_request_p->context_teid = endpoint_updated_p->context_teid;
update_request_p->sgw_S1u_teid = endpoint_updated_p->sgw_S1u_teid;
update_request_p->enb_S1u_teid = endpoint_updated_p->enb_S1u_teid;
update_request_p->eps_bearer_id = endpoint_updated_p->eps_bearer_id;
update_request_p->context_teid = endpoint_updated_pP->context_teid;
update_request_p->sgw_S1u_teid = endpoint_updated_pP->sgw_S1u_teid;
update_request_p->enb_S1u_teid = endpoint_updated_pP->enb_S1u_teid;
update_request_p->eps_bearer_id = endpoint_updated_pP->eps_bearer_id;
return itti_send_msg_to_task(TASK_FW_IP, INSTANCE_DEFAULT, message_p);
}
} else {
SPGW_APP_DEBUG("Sending SGW_MODIFY_BEARER_RESPONSE trxn %p bearer %u CONTEXT_NOT_FOUND (s11_bearer_context_information_hashtable)\n",
new_bearer_context_information_p->sgw_eps_bearer_context_information.trxn,
endpoint_updated_p->eps_bearer_id);
new_bearer_ctxt_info_p->sgw_eps_bearer_context_information.trxn,
endpoint_updated_pP->eps_bearer_id);
message_p = itti_alloc_new_message(TASK_SPGW_APP, SGW_MODIFY_BEARER_RESPONSE);
if (message_p == NULL) {
@@ -406,23 +494,27 @@ int sgw_lite_handle_gtpv1uUpdateTunnelResp(Gtpv1uUpdateTunnelResp *endpoint_upda
modify_response_p = &message_p->ittiMsg.sgwModifyBearerResponse;
memset(modify_response_p, 0, sizeof(SgwModifyBearerResponse));
modify_response_p->present = MODIFY_BEARER_RESPONSE_REM;
modify_response_p->choice.bearer_for_removal.eps_bearer_id = endpoint_updated_p->eps_bearer_id;
modify_response_p->choice.bearer_for_removal.cause = CONTEXT_NOT_FOUND;
modify_response_p->cause = CONTEXT_NOT_FOUND;
modify_response_p->trxn = new_bearer_context_information_p->sgw_eps_bearer_context_information.trxn;
modify_response_p->bearer_present = MODIFY_BEARER_RESPONSE_REM;
modify_response_p->bearer_choice.bearer_for_removal.eps_bearer_id = endpoint_updated_pP->eps_bearer_id;
modify_response_p->bearer_choice.bearer_for_removal.cause = CONTEXT_NOT_FOUND;
modify_response_p->cause = CONTEXT_NOT_FOUND;
modify_response_p->trxn = new_bearer_ctxt_info_p->sgw_eps_bearer_context_information.trxn;
return itti_send_msg_to_task(to_task, INSTANCE_DEFAULT, message_p);
}
return -1;
}
int sgw_lite_handle_sgi_endpoint_updated(SGIUpdateEndpointResp *resp_p)
int
sgw_lite_handle_sgi_endpoint_updated(
const SGIUpdateEndpointResp * const resp_pP)
{
SgwModifyBearerResponse *modify_response_p = NULL;
s_plus_p_gw_eps_bearer_context_information_t *new_bearer_context_information_p = NULL;
MessageDef *message_p = NULL;
sgw_eps_bearer_entry_t *eps_bearer_entry_p = NULL;
hashtable_rc_t hash_rc;
SgwModifyBearerResponse *modify_response_p = NULL;
s_plus_p_gw_eps_bearer_context_information_t *new_bearer_ctxt_info_p = NULL;
MessageDef *message_p = NULL;
sgw_eps_bearer_entry_t *eps_bearer_entry_p = NULL;
hashtable_rc_t hash_rc;
task_id_t to_task;
#if defined(ENABLE_STANDALONE_EPC)
@@ -432,11 +524,11 @@ int sgw_lite_handle_sgi_endpoint_updated(SGIUpdateEndpointResp *resp_p)
#endif
SPGW_APP_DEBUG("Rx SGI_UPDATE_ENDPOINT_RESPONSE, Context teid %u, SGW S1U teid %u, eNB S1U teid %u, EPS bearer id %u, status %d\n",
resp_p->context_teid,
resp_p->sgw_S1u_teid,
resp_p->enb_S1u_teid,
resp_p->eps_bearer_id,
resp_p->status);
resp_pP->context_teid,
resp_pP->sgw_S1u_teid,
resp_pP->enb_S1u_teid,
resp_pP->eps_bearer_id,
resp_pP->status);
message_p = itti_alloc_new_message(TASK_SPGW_APP, SGW_MODIFY_BEARER_RESPONSE);
if (message_p == NULL) {
@@ -445,58 +537,62 @@ int sgw_lite_handle_sgi_endpoint_updated(SGIUpdateEndpointResp *resp_p)
modify_response_p = &message_p->ittiMsg.sgwModifyBearerResponse;
memset(modify_response_p, 0, sizeof(SgwModifyBearerResponse));
hash_rc = hashtable_get(sgw_app.s11_bearer_context_information_hashtable, resp_p->context_teid, (void**)&new_bearer_context_information_p);
hash_rc = hashtable_get(sgw_app.s11_bearer_context_information_hashtable, resp_pP->context_teid, (void**)&new_bearer_ctxt_info_p);
if (hash_rc == HASH_TABLE_OK) {
hash_rc = hashtable_get (new_bearer_context_information_p->sgw_eps_bearer_context_information.pdn_connection.sgw_eps_bearers,
resp_p->eps_bearer_id,
hash_rc = hashtable_get (new_bearer_ctxt_info_p->sgw_eps_bearer_context_information.pdn_connection.sgw_eps_bearers,
resp_pP->eps_bearer_id,
(void**)&eps_bearer_entry_p);
if ((hash_rc == HASH_TABLE_KEY_NOT_EXISTS) || (hash_rc == HASH_TABLE_BAD_PARAMETER_HASHTABLE)) {
SPGW_APP_DEBUG("Rx SGI_UPDATE_ENDPOINT_RESPONSE: CONTEXT_NOT_FOUND (pdn_connection.sgw_eps_bearers context)\n");
modify_response_p->teid = resp_p->context_teid; // TO BE CHECKED IF IT IS THIS TEID
modify_response_p->present = MODIFY_BEARER_RESPONSE_REM;
modify_response_p->choice.bearer_for_removal.eps_bearer_id = resp_p->eps_bearer_id;
modify_response_p->choice.bearer_for_removal.cause = CONTEXT_NOT_FOUND;
modify_response_p->cause = CONTEXT_NOT_FOUND;
modify_response_p->trxn = 0;
modify_response_p->teid = resp_pP->context_teid; // TO BE CHECKED IF IT IS THIS TEID
modify_response_p->bearer_present = MODIFY_BEARER_RESPONSE_REM;
modify_response_p->bearer_choice.bearer_for_removal.eps_bearer_id = resp_pP->eps_bearer_id;
modify_response_p->bearer_choice.bearer_for_removal.cause = CONTEXT_NOT_FOUND;
modify_response_p->cause = CONTEXT_NOT_FOUND;
modify_response_p->trxn = 0;
return itti_send_msg_to_task(to_task, INSTANCE_DEFAULT, message_p);
} else if (hash_rc == HASH_TABLE_OK) {
SPGW_APP_DEBUG("Rx SGI_UPDATE_ENDPOINT_RESPONSE: REQUEST_ACCEPTED\n");
// accept anyway
modify_response_p->teid = resp_p->context_teid; // TO BE CHECKED IF IT IS THIS TEID
modify_response_p->present = MODIFY_BEARER_RESPONSE_MOD;
modify_response_p->choice.bearer_modified.eps_bearer_id = resp_p->eps_bearer_id;
modify_response_p->choice.bearer_modified.cause = REQUEST_ACCEPTED;
modify_response_p->cause = REQUEST_ACCEPTED;
modify_response_p->trxn = new_bearer_context_information_p->sgw_eps_bearer_context_information.trxn;
modify_response_p->teid = resp_pP->context_teid; // TO BE CHECKED IF IT IS THIS TEID
modify_response_p->bearer_present = MODIFY_BEARER_RESPONSE_MOD;
modify_response_p->bearer_choice.bearer_contexts_modified.eps_bearer_id = resp_pP->eps_bearer_id;
modify_response_p->bearer_choice.bearer_contexts_modified.cause = REQUEST_ACCEPTED;
modify_response_p->cause = REQUEST_ACCEPTED;
modify_response_p->trxn = new_bearer_ctxt_info_p->sgw_eps_bearer_context_information.trxn;
}
return itti_send_msg_to_task(to_task, INSTANCE_DEFAULT, message_p);
} else {
SPGW_APP_DEBUG("Rx SGI_UPDATE_ENDPOINT_RESPONSE: CONTEXT_NOT_FOUND (S11 context)\n");
modify_response_p->teid = resp_p->context_teid; // TO BE CHECKED IF IT IS THIS TEID
modify_response_p->present = MODIFY_BEARER_RESPONSE_REM;
modify_response_p->choice.bearer_for_removal.eps_bearer_id = resp_p->eps_bearer_id;
modify_response_p->choice.bearer_for_removal.cause = CONTEXT_NOT_FOUND;
modify_response_p->cause = CONTEXT_NOT_FOUND;
modify_response_p->trxn = 0;
modify_response_p->teid = resp_pP->context_teid; // TO BE CHECKED IF IT IS THIS TEID
modify_response_p->bearer_present = MODIFY_BEARER_RESPONSE_REM;
modify_response_p->bearer_choice.bearer_for_removal.eps_bearer_id = resp_pP->eps_bearer_id;
modify_response_p->bearer_choice.bearer_for_removal.cause = CONTEXT_NOT_FOUND;
modify_response_p->cause = CONTEXT_NOT_FOUND;
modify_response_p->trxn = 0;
return itti_send_msg_to_task(to_task, INSTANCE_DEFAULT, message_p);
}
}
int sgw_lite_handle_modify_bearer_request(SgwModifyBearerRequest *modify_bearer_p)
int
sgw_lite_handle_modify_bearer_request(
const SgwModifyBearerRequest * const modify_bearer_pP)
{
SgwModifyBearerResponse *modify_response_p = NULL;
Gtpv1uUpdateTunnelReq *gtpv1u_update_tunnel_req_p = NULL;
s_plus_p_gw_eps_bearer_context_information_t *new_bearer_context_information_p = NULL;
MessageDef *message_p = NULL;
sgw_eps_bearer_entry_t *eps_bearer_entry_p = NULL;
hashtable_rc_t hash_rc;
SgwModifyBearerResponse *modify_response_p = NULL;
Gtpv1uUpdateTunnelReq *gtpv1u_update_tunnel_req_p = NULL;
s_plus_p_gw_eps_bearer_context_information_t *new_bearer_ctxt_info_p = NULL;
MessageDef *message_p = NULL;
sgw_eps_bearer_entry_t *eps_bearer_entry_p = NULL;
hashtable_rc_t hash_rc;
task_id_t to_task;
#if defined(ENABLE_STANDALONE_EPC)
@@ -506,25 +602,25 @@ int sgw_lite_handle_modify_bearer_request(SgwModifyBearerRequest *modify_bearer_
#endif
SPGW_APP_DEBUG("Rx MODIFY_BEARER_REQUEST, teid %u, EPS bearer id %u\n",
modify_bearer_p->teid,
modify_bearer_p->bearer_context_to_modify.eps_bearer_id);
modify_bearer_pP->teid,
modify_bearer_pP->bearer_context_to_modify.eps_bearer_id);
sgw_lite_display_s11teid2mme_mappings();
sgw_lite_display_s11_bearer_context_information_mapping();
hash_rc = hashtable_get(
sgw_app.s11_bearer_context_information_hashtable,
modify_bearer_p->teid,
(void**)&new_bearer_context_information_p);
modify_bearer_pP->teid,
(void**)&new_bearer_ctxt_info_p);
if (hash_rc == HASH_TABLE_OK) {
new_bearer_context_information_p->sgw_eps_bearer_context_information.pdn_connection.default_bearer = modify_bearer_p->bearer_context_to_modify.eps_bearer_id;
new_bearer_context_information_p->sgw_eps_bearer_context_information.trxn = modify_bearer_p->trxn;
new_bearer_ctxt_info_p->sgw_eps_bearer_context_information.pdn_connection.default_bearer = modify_bearer_pP->bearer_context_to_modify.eps_bearer_id;
new_bearer_ctxt_info_p->sgw_eps_bearer_context_information.trxn = modify_bearer_pP->trxn;
hash_rc = hashtable_is_key_exists (
new_bearer_context_information_p->sgw_eps_bearer_context_information.pdn_connection.sgw_eps_bearers,
modify_bearer_p->bearer_context_to_modify.eps_bearer_id);
new_bearer_ctxt_info_p->sgw_eps_bearer_context_information.pdn_connection.sgw_eps_bearers,
modify_bearer_pP->bearer_context_to_modify.eps_bearer_id);
if (hash_rc == HASH_TABLE_KEY_NOT_EXISTS) {
message_p = itti_alloc_new_message(TASK_SPGW_APP, SGW_MODIFY_BEARER_RESPONSE);
@@ -533,23 +629,23 @@ int sgw_lite_handle_modify_bearer_request(SgwModifyBearerRequest *modify_bearer_
}
modify_response_p = &message_p->ittiMsg.sgwModifyBearerResponse;
memset(modify_response_p, 0, sizeof(SgwModifyBearerResponse));
modify_response_p->present = MODIFY_BEARER_RESPONSE_REM;
modify_response_p->choice.bearer_for_removal.eps_bearer_id = modify_bearer_p->bearer_context_to_modify.eps_bearer_id;
modify_response_p->choice.bearer_for_removal.cause = CONTEXT_NOT_FOUND;
modify_response_p->cause = CONTEXT_NOT_FOUND;
modify_response_p->trxn = modify_bearer_p->trxn;
modify_response_p->bearer_present = MODIFY_BEARER_RESPONSE_REM;
modify_response_p->bearer_choice.bearer_for_removal.eps_bearer_id = modify_bearer_pP->bearer_context_to_modify.eps_bearer_id;
modify_response_p->bearer_choice.bearer_for_removal.cause = CONTEXT_NOT_FOUND;
modify_response_p->cause = CONTEXT_NOT_FOUND;
modify_response_p->trxn = modify_bearer_pP->trxn;
SPGW_APP_DEBUG("Rx MODIFY_BEARER_REQUEST, eps_bearer_id %u CONTEXT_NOT_FOUND\n",
modify_bearer_p->bearer_context_to_modify.eps_bearer_id);
modify_bearer_pP->bearer_context_to_modify.eps_bearer_id);
return itti_send_msg_to_task(to_task, INSTANCE_DEFAULT, message_p);
} else if (hash_rc == HASH_TABLE_OK) {
// TO DO
hash_rc = hashtable_get (
new_bearer_context_information_p->sgw_eps_bearer_context_information.pdn_connection.sgw_eps_bearers,
modify_bearer_p->bearer_context_to_modify.eps_bearer_id,
new_bearer_ctxt_info_p->sgw_eps_bearer_context_information.pdn_connection.sgw_eps_bearers,
modify_bearer_pP->bearer_context_to_modify.eps_bearer_id,
(void**)&eps_bearer_entry_p);
FTEID_T_2_IP_ADDRESS_T( (&modify_bearer_p->bearer_context_to_modify.s1_eNB_fteid) , (&eps_bearer_entry_p->enb_ip_address_for_S1u) );
eps_bearer_entry_p->enb_teid_for_S1u = modify_bearer_p->bearer_context_to_modify.s1_eNB_fteid.teid;
FTEID_T_2_IP_ADDRESS_T( (&modify_bearer_pP->bearer_context_to_modify.s1_eNB_fteid) , (&eps_bearer_entry_p->enb_ip_address_for_S1u) );
eps_bearer_entry_p->enb_teid_for_S1u = modify_bearer_pP->bearer_context_to_modify.s1_eNB_fteid.teid;
// UPDATE GTPV1U mapping tables with eNB references (teid, addresses)
message_p = itti_alloc_new_message(TASK_SPGW_APP, GTPV1U_UPDATE_TUNNEL_REQ);
@@ -558,15 +654,15 @@ int sgw_lite_handle_modify_bearer_request(SgwModifyBearerRequest *modify_bearer_
}
gtpv1u_update_tunnel_req_p = &message_p->ittiMsg.gtpv1uUpdateTunnelReq;
memset(gtpv1u_update_tunnel_req_p, 0, sizeof(Gtpv1uUpdateTunnelReq));
gtpv1u_update_tunnel_req_p->context_teid = modify_bearer_p->teid;
gtpv1u_update_tunnel_req_p->context_teid = modify_bearer_pP->teid;
gtpv1u_update_tunnel_req_p->sgw_S1u_teid = eps_bearer_entry_p->s_gw_teid_for_S1u_S12_S4_up; ///< SGW S1U local Tunnel Endpoint Identifier
gtpv1u_update_tunnel_req_p->enb_S1u_teid = eps_bearer_entry_p->enb_teid_for_S1u; ///< eNB S1U Tunnel Endpoint Identifier
gtpv1u_update_tunnel_req_p->enb_ip_address_for_S1u = eps_bearer_entry_p->enb_ip_address_for_S1u;
gtpv1u_update_tunnel_req_p->eps_bearer_id = eps_bearer_entry_p->eps_bearer_id;
SPGW_APP_DEBUG("Rx MODIFY_BEARER_REQUEST, gtpv1u_update_tunnel_req_p->context_teid = %u\n",modify_bearer_p->teid);
SPGW_APP_DEBUG("Rx MODIFY_BEARER_REQUEST, gtpv1u_update_tunnel_req_p->context_teid = %u\n",modify_bearer_pP->teid);
SPGW_APP_DEBUG("Rx MODIFY_BEARER_REQUEST, gtpv1u_update_tunnel_req_p->sgw_S1u_teid = %u\n",gtpv1u_update_tunnel_req_p->sgw_S1u_teid);
SPGW_APP_DEBUG("Rx MODIFY_BEARER_REQUEST, gtpv1u_update_tunnel_req_p->enb_S1u_teid = %u\n",gtpv1u_update_tunnel_req_p->enb_S1u_teid);
//SPGW_APP_DEBUG("Rx MODIFY_BEARER_REQUEST, gtpv1u_update_tunnel_req_p->enb_ip_address_for_S1u = %u\n",modify_bearer_p->enb_ip_address_for_S1u);
//SPGW_APP_DEBUG("Rx MODIFY_BEARER_REQUEST, gtpv1u_update_tunnel_req_p->enb_ip_address_for_S1u = %u\n",modify_bearer_pP->enb_ip_address_for_S1u);
SPGW_APP_DEBUG("Rx MODIFY_BEARER_REQUEST, gtpv1u_update_tunnel_req_p->eps_bearer_id = %u\n",gtpv1u_update_tunnel_req_p->eps_bearer_id);
return itti_send_msg_to_task(TASK_GTPV1_U, INSTANCE_DEFAULT, message_p);
@@ -578,27 +674,31 @@ int sgw_lite_handle_modify_bearer_request(SgwModifyBearerRequest *modify_bearer_
}
modify_response_p = &message_p->ittiMsg.sgwModifyBearerResponse;
modify_response_p->present = MODIFY_BEARER_RESPONSE_REM;
modify_response_p->choice.bearer_for_removal.eps_bearer_id = modify_bearer_p->bearer_context_to_modify.eps_bearer_id;
modify_response_p->choice.bearer_for_removal.cause = CONTEXT_NOT_FOUND;
modify_response_p->cause = CONTEXT_NOT_FOUND;
modify_response_p->trxn = modify_bearer_p->trxn;
modify_response_p->bearer_present = MODIFY_BEARER_RESPONSE_REM;
modify_response_p->bearer_choice.bearer_for_removal.eps_bearer_id = modify_bearer_pP->bearer_context_to_modify.eps_bearer_id;
modify_response_p->bearer_choice.bearer_for_removal.cause = CONTEXT_NOT_FOUND;
modify_response_p->cause = CONTEXT_NOT_FOUND;
modify_response_p->trxn = modify_bearer_pP->trxn;
SPGW_APP_DEBUG("Rx MODIFY_BEARER_REQUEST, teid %u CONTEXT_NOT_FOUND\n",
modify_bearer_p->teid);
modify_bearer_pP->teid);
return itti_send_msg_to_task(to_task, INSTANCE_DEFAULT, message_p);
}
return -1;
}
int sgw_lite_handle_delete_session_request(SgwDeleteSessionRequest *delete_session_req_p)
int
sgw_lite_handle_delete_session_request(
const SgwDeleteSessionRequest * const delete_session_req_pP)
{
task_id_t to_task;
hashtable_rc_t hash_rc;
SgwDeleteSessionResponse *delete_session_resp_p;
MessageDef *message_p = NULL;
s_plus_p_gw_eps_bearer_context_information_t *ctx_p = NULL;
SgwDeleteSessionResponse *delete_session_resp_p = NULL;
MessageDef *message_p = NULL;
s_plus_p_gw_eps_bearer_context_information_t *ctx_p = NULL;
#if defined(ENABLE_STANDALONE_EPC)
to_task = TASK_MME_APP;
@@ -612,34 +712,34 @@ int sgw_lite_handle_delete_session_request(SgwDeleteSessionRequest *delete_sessi
}
delete_session_resp_p = &message_p->ittiMsg.sgwDeleteSessionResponse;
SPGW_APP_WARNING("Delete session handler needs to be completed...\n");
SPGW_APP_WARN("Delete session handler needs to be completed...\n");
if (delete_session_req_p->indication_flags & OI_FLAG) {
if (delete_session_req_pP->indication_flags & OI_FLAG) {
SPGW_APP_DEBUG("OI flag is set for this message indicating the request"
"should be forwarded to P-GW entity\n");
}
hash_rc = hashtable_get(sgw_app.s11_bearer_context_information_hashtable,
delete_session_req_p->teid,
delete_session_req_pP->teid,
(void**)&ctx_p);
if (hash_rc == HASH_TABLE_OK) {
if ((delete_session_req_p->sender_fteid_for_cp.ipv4 != 0) &&
(delete_session_req_p->sender_fteid_for_cp.ipv6 != 0)) {
if ((delete_session_req_pP->sender_fteid_for_cp.ipv4 != 0) &&
(delete_session_req_pP->sender_fteid_for_cp.ipv6 != 0)) {
/* Sender F-TEID IE present */
if (delete_session_resp_p->teid != ctx_p->sgw_eps_bearer_context_information.mme_teid_for_S11) {
delete_session_resp_p->teid = ctx_p->sgw_eps_bearer_context_information.mme_teid_for_S11;
delete_session_resp_p->cause = INVALID_PEER;
SPGW_APP_DEBUG("Mismatch in MME Teid for CP\n");
} else {
delete_session_resp_p->teid = delete_session_req_p->sender_fteid_for_cp.teid;
delete_session_resp_p->teid = delete_session_req_pP->sender_fteid_for_cp.teid;
}
} else {
delete_session_resp_p->cause = REQUEST_ACCEPTED;
delete_session_resp_p->teid = ctx_p->sgw_eps_bearer_context_information.mme_teid_for_S11;
}
delete_session_resp_p->trxn = delete_session_req_p->trxn;
delete_session_resp_p->peer_ip = delete_session_req_p->peer_ip;
delete_session_resp_p->trxn = delete_session_req_pP->trxn;
delete_session_resp_p->peer_ip = delete_session_req_pP->peer_ip;
return itti_send_msg_to_task(to_task, INSTANCE_DEFAULT, message_p);
} else {
@@ -652,15 +752,15 @@ int sgw_lite_handle_delete_session_request(SgwDeleteSessionRequest *delete_sessi
}
delete_session_resp_p = &message_p->ittiMsg.sgwDeleteSessionResponse;
if ((delete_session_req_p->sender_fteid_for_cp.ipv4 == 0) &&
(delete_session_req_p->sender_fteid_for_cp.ipv6 == 0)) {
if ((delete_session_req_pP->sender_fteid_for_cp.ipv4 == 0) &&
(delete_session_req_pP->sender_fteid_for_cp.ipv6 == 0)) {
delete_session_resp_p->teid = 0;
} else {
delete_session_resp_p->teid = delete_session_req_p->sender_fteid_for_cp.teid;
delete_session_resp_p->teid = delete_session_req_pP->sender_fteid_for_cp.teid;
}
delete_session_resp_p->cause = CONTEXT_NOT_FOUND;
delete_session_resp_p->trxn = delete_session_req_p->trxn;
delete_session_resp_p->peer_ip = delete_session_req_p->peer_ip;
delete_session_resp_p->trxn = delete_session_req_pP->trxn;
delete_session_resp_p->peer_ip = delete_session_req_pP->peer_ip;
return itti_send_msg_to_task(to_task, INSTANCE_DEFAULT, message_p);
}
+7 -7
View File
@@ -39,12 +39,12 @@ Address : EURECOM,
#ifndef SGW_LITE_HANDLERS_H_
#define SGW_LITE_HANDLERS_H_
int sgw_lite_handle_create_session_request(SgwCreateSessionRequest *session_req_p);
int sgw_lite_handle_sgi_endpoint_created (SGICreateEndpointResp *resp_p);
int sgw_lite_handle_sgi_endpoint_updated (SGIUpdateEndpointResp *resp_p);
int sgw_lite_handle_gtpv1uCreateTunnelResp(Gtpv1uCreateTunnelResp *endpoint_created_p);
int sgw_lite_handle_gtpv1uUpdateTunnelResp(Gtpv1uUpdateTunnelResp *endpoint_updated_p);
int sgw_lite_handle_modify_bearer_request (SgwModifyBearerRequest *modify_bearer_p);
int sgw_lite_handle_delete_session_request(SgwDeleteSessionRequest *delete_session_p);
int sgw_lite_handle_create_session_request(const SgwCreateSessionRequest * const session_req_p);
int sgw_lite_handle_sgi_endpoint_created (const SGICreateEndpointResp * const resp_p);
int sgw_lite_handle_sgi_endpoint_updated (const SGIUpdateEndpointResp * const resp_p);
int sgw_lite_handle_gtpv1uCreateTunnelResp(const Gtpv1uCreateTunnelResp * const endpoint_created_p);
int sgw_lite_handle_gtpv1uUpdateTunnelResp(const Gtpv1uUpdateTunnelResp * const endpoint_updated_p);
int sgw_lite_handle_modify_bearer_request (const SgwModifyBearerRequest * const modify_bearer_p);
int sgw_lite_handle_delete_session_request(const SgwDeleteSessionRequest * const delete_session_p);
#endif /* SGW_LITE_HANDLERS_H_ */
+9 -3
View File
@@ -51,6 +51,7 @@ Address : EURECOM,
#include "sgw_lite.h"
#include "hashtable.h"
#include "spgw_config.h"
#include "pgw_lite_paa.h"
spgw_config_t spgw_config;
sgw_app_t sgw_app;
@@ -109,19 +110,25 @@ static void *sgw_lite_intertask_interface(void *args_p)
default: {
SPGW_APP_DEBUG("Unkwnon message ID %d:%s\n",
ITTI_MSG_ID(received_message_p), ITTI_MSG_NAME(received_message_p));
ITTI_MSG_ID(received_message_p),
ITTI_MSG_NAME(received_message_p));
} break;
}
free(received_message_p);
itti_free(ITTI_MSG_ORIGIN_ID(received_message_p), received_message_p);
received_message_p = NULL;
}
return NULL;
}
int sgw_lite_init(char* config_file_name_pP)
{
SPGW_APP_DEBUG("Initializing SPGW-APP task interface\n");
spgw_config_init(config_file_name_pP, &spgw_config);
pgw_lite_load_pool_ip_addresses();
sgw_app.s11teid2mme_hashtable = hashtable_create (8192, NULL, NULL);
if (sgw_app.s11teid2mme_hashtable == NULL) {
perror("hashtable_create");
@@ -151,7 +158,6 @@ int sgw_lite_init(char* config_file_name_pP)
//sgw_app.sgw_ip_address_for_S5_S8_cp = spgw_config.sgw_config.ipv4.sgw_ip_address_for_S5_S8_cp;
sgw_app.sgw_ip_address_for_S5_S8_up = spgw_config.sgw_config.ipv4.sgw_ipv4_address_for_S5_S8_up;
SPGW_APP_DEBUG("Initializing SPGW-APP task interface\n");
if (itti_create_task(TASK_SPGW_APP,
&sgw_lite_intertask_interface, NULL) < 0) {
perror("pthread_create");
+76 -63
View File
@@ -82,7 +82,14 @@ Address : EURECOM,
&& ((((__const uint32_t *) (a))[2] & (((__const uint32_t *) (m))[2])) == (((__const uint32_t *) (b))[2] & (((__const uint32_t *) (m))[2]))) \
&& ((((__const uint32_t *) (a))[3] & (((__const uint32_t *) (m))[3])) == (((__const uint32_t *) (b))[3] & (((__const uint32_t *) (m))[3]))))
void trim(char* srcP, int sizeP)
void trim(char* srcP, int sizeP);
void sgw_ipv6_mask_in6_addr( struct in6_addr *addr6_pP, int maskP);
void
trim(
char* srcP,
int sizeP)
{
if(srcP == NULL)
return;
@@ -99,7 +106,13 @@ void trim(char* srcP, int sizeP)
srcP[i] = '\0';
}
void sgw_ipv6_mask_in6_addr( struct in6_addr *addr6_pP, int maskP) {
void
sgw_ipv6_mask_in6_addr(
struct in6_addr *addr6_pP,
int maskP)
{
int addr8_idx;
addr8_idx = maskP / 8;
@@ -113,6 +126,8 @@ void sgw_ipv6_mask_in6_addr( struct in6_addr *addr6_pP, int maskP) {
addr6_pP->s6_addr[addr8_idx++] = 0;
}
}
/*int is_valid_ip_address(char *addr_pP, int ai_familyP , struct sockaddr *sock_addr_pP) {
struct addrinfo hints;
struct addrinfo *result, *rp;
@@ -170,27 +185,31 @@ int spgw_config_init(char* lib_config_file_name_pP, spgw_config_t* config_pP) {
char *pgw_ipv4_address_for_SGI = NULL;
char *delimiters=NULL;
char *saveptr1= NULL;
char *astring = NULL;
char *atoken = NULL;
char *atoken2 = NULL;
char *address = NULL;
char *cidr = NULL;
char *mask = NULL;
int num = 0;
int i = 0;
char *saveptr1 = NULL;
char *astring = NULL;
char *atoken = NULL;
char *atoken2 = NULL;
char *address = NULL;
char *cidr = NULL;
char *mask = NULL;
int num = 0;
int i = 0;
int jh, jn;
unsigned char buf_in6_addr[sizeof(struct in6_addr)];
struct in6_addr addr6_start;
struct in6_addr addr6_mask;
int prefix_mask;
uint64_t counter64;
int prefix_mask = 0;
uint64_t counter64 = 0;
unsigned char buf_in_addr[sizeof(struct in_addr)];
struct in_addr addr_start;
struct in_addr addr_end;
struct in_addr addr_mask;
pgw_lite_conf_ipv4_list_elm_t *ip4_ref = NULL;
pgw_lite_conf_ipv6_list_elm_t *ip6_ref = NULL;
memset((char*)config_pP, 0 , sizeof(spgw_config_t));
STAILQ_INIT(&config_pP->pgw_config.pgw_lite_ipv4_pool_list);
STAILQ_INIT(&config_pP->pgw_config.pgw_lite_ipv6_pool_list);
config_init(&cfg);
@@ -210,6 +229,7 @@ int spgw_config_init(char* lib_config_file_name_pP, spgw_config_t* config_pP) {
config_destroy(&cfg);
AssertFatal (0, "No SP-GW configuration file provided!\n");
}
SPGW_APP_INFO("Parsing configuration file provided %s\n", lib_config_file_name_pP);
setting_sgw = config_lookup(&cfg, SGW_CONFIG_STRING_SGW_CONFIG);
if(setting_sgw != NULL) {
@@ -299,42 +319,49 @@ int spgw_config_init(char* lib_config_file_name_pP, spgw_config_t* config_pP) {
trim(astring, strlen(astring)+1);
if (inet_pton(AF_INET, astring, buf_in_addr) < 1) {
// failure, test if there is a range specified in the string
atoken = strtok(astring, PGW_CONFIG_STRING_IP_ADDRESS_RANGE_DELIMITERS);
if (inet_pton(AF_INET, astring, buf_in_addr) == 1) {
atoken = strtok(astring, PGW_CONFIG_STRING_IPV4_PREFIX_DELIMITER);
if (inet_pton(AF_INET, atoken, buf_in_addr) == 1) {
memcpy (&addr_start, buf_in_addr, sizeof(struct in_addr));
// valid address
atoken2 = strtok(NULL, PGW_CONFIG_STRING_IP_ADDRESS_RANGE_DELIMITERS);
if (inet_pton(AF_INET, atoken2, buf_in_addr) == 1) {
memcpy (&addr_end, buf_in_addr, sizeof(struct in_addr));
// valid address
for (jh = ntohl(addr_start.s_addr); jh <= ntohl(addr_end.s_addr); jh++) {
DevAssert(PGW_MAX_ALLOCATED_PDN_ADDRESSES > config_pP->pgw_config.pool_pdn_addresses.num_ipv4_addresses);
jn = htonl(jh);
if (IN_CLASSA(addr_start.s_addr)) {
if ((jh & 0xFF) && (jh & 0xFF) != 0xFF) {
config_pP->pgw_config.pool_pdn_addresses.ipv4_addresses[config_pP->pgw_config.pool_pdn_addresses.num_ipv4_addresses++].s_addr = jn;
}
} else if (IN_CLASSB(addr_start.s_addr)) {
if ((jh & 0xFF) && (jh & 0xFF) != 0xFF) {
config_pP->pgw_config.pool_pdn_addresses.ipv4_addresses[config_pP->pgw_config.pool_pdn_addresses.num_ipv4_addresses++].s_addr = jn;
}
} else if (IN_CLASSC(addr_start.s_addr)) {
if ((jh & 0xFF) && (jh & 0xFF) != 0xFF) {
config_pP->pgw_config.pool_pdn_addresses.ipv4_addresses[config_pP->pgw_config.pool_pdn_addresses.num_ipv4_addresses++].s_addr = jn;
}
} else {
printf("ERROR ON ADDRESS CLASS %d.%d.%d.%d\n", NIPADDR(jn));
}
atoken2 = strtok(NULL, PGW_CONFIG_STRING_IPV4_PREFIX_DELIMITER);
prefix_mask = atoi(atoken2);
if ((prefix_mask >= 2)&&(prefix_mask < 32)) {
memcpy (&addr_start, buf_in_addr, sizeof(struct in_addr));
memcpy (&addr_mask, buf_in_addr, sizeof(struct in_addr));
addr_mask.s_addr = addr_mask.s_addr & htonl(0xFFFFFFFF << (32 - prefix_mask));
if (memcmp(&addr_start, &addr_mask, sizeof(struct in_addr)) != 0) {
AssertFatal(0, "BAD IPV4 ADDR CONFIG/MASK PAIRING %s/%d addr %X mask %X\n",
astring, prefix_mask, addr_start.s_addr, addr_mask.s_addr);
}
counter64 = 0x00000000FFFFFFFF >> prefix_mask; // address Prefix_mask/0..0 not valid
counter64 = counter64 - 1;
do {
addr_start.s_addr = addr_start.s_addr + htonl(1);
ip4_ref = calloc(1, sizeof(pgw_lite_conf_ipv4_list_elm_t));
ip4_ref->addr = addr_start;
STAILQ_INSERT_TAIL(&config_pP->pgw_config.pgw_lite_ipv4_pool_list, ip4_ref, ipv4_entries);
counter64 = counter64 - 1;
} while (counter64 > 0);
} else {
SPGW_APP_ERROR("CONFIG POOL ADDR IPV4: BAD MASQ: %s\n", atoken2);
}
} else {
SPGW_APP_ERROR("CONFIG POOL ADDR IPV4: ADDR not recognized: %s\n", atoken);
}
} else {
DevAssert(PGW_MAX_ALLOCATED_PDN_ADDRESSES > config_pP->pgw_config.pool_pdn_addresses.num_ipv4_addresses);
memcpy (&addr_start, buf_in_addr, sizeof(struct in_addr));
config_pP->pgw_config.pool_pdn_addresses.ipv4_addresses[config_pP->pgw_config.pool_pdn_addresses.num_ipv4_addresses++].s_addr = addr_start.s_addr;
ip4_ref = calloc(1, sizeof(pgw_lite_conf_ipv4_list_elm_t));
ip4_ref->addr = addr_start;
STAILQ_INSERT_TAIL(&config_pP->pgw_config.pgw_lite_ipv4_pool_list, ip4_ref, ipv4_entries);
}
}
}
} else {
SPGW_APP_WARN("CONFIG POOL ADDR IPV4: NO IPV4 ADDRESS FOUND\n");
}
sub2setting = config_setting_get_member (subsetting, PGW_CONFIG_STRING_IPV6_ADDRESS_LIST);
if(sub2setting != NULL) {
@@ -360,34 +387,20 @@ int spgw_config_init(char* lib_config_file_name_pP, spgw_config_t* config_pP) {
AssertFatal(0, "BAD IPV6 ADDR CONFIG/MASK PAIRING %s/%d\n", astring, prefix_mask);
}
counter64 = 0xFFFFFFFFFFFFFFFF >> prefix_mask; // address Prefix_mask/0..0 not valid
do {
addr6_start.s6_addr32[3] = addr6_start.s6_addr32[3] + htonl(1);
if (addr6_start.s6_addr32[3] == 0) {
addr6_start.s6_addr32[2] = addr6_start.s6_addr32[2] + htonl(1);
if (addr6_start.s6_addr32[2] == 0) {
// should not happen since mask is no less than 64
addr6_start.s6_addr32[1] = addr6_start.s6_addr32[1] + htonl(1);
if (addr6_start.s6_addr32[1] == 0) {
addr6_start.s6_addr32[0] = addr6_start.s6_addr32[0] + htonl(1);
}
}
}
memcpy (&config_pP->pgw_config.pool_pdn_addresses.ipv6_addresses[config_pP->pgw_config.pool_pdn_addresses.num_ipv6_addresses++],
&addr6_start,
sizeof(struct in6_addr));
counter64 = counter64 - 1;
} while (counter64 > 0);
ip6_ref = calloc(1, sizeof(pgw_lite_conf_ipv6_list_elm_t));
ip6_ref->addr = addr6_start;
ip6_ref->prefix_len = prefix_mask;
STAILQ_INSERT_TAIL(&config_pP->pgw_config.pgw_lite_ipv6_pool_list, ip6_ref, ipv6_entries);
}
} else {
DevAssert(PGW_MAX_ALLOCATED_PDN_ADDRESSES > config_pP->pgw_config.pool_pdn_addresses.num_ipv6_addresses);
memcpy (&config_pP->pgw_config.pool_pdn_addresses.ipv6_addresses[config_pP->pgw_config.pool_pdn_addresses.num_ipv6_addresses++],
buf_in6_addr,
sizeof(struct in6_addr));
SPGW_APP_WARN("CONFIG POOL ADDR IPV6: FAILED WHILE PARSING %s\n", astring);
}
}
}
} }
}
}
}
return 0;
}
+18 -8
View File
@@ -42,7 +42,7 @@ Address : EURECOM,
#include <netinet/in.h> // inet_aton
#include <arpa/inet.h> // inet_aton
#include "queue.h"
#define SGW_CONFIG_STRING_SGW_CONFIG "S-GW"
#define SGW_CONFIG_STRING_NETWORK_INTERFACES_CONFIG "NETWORK_INTERFACES"
@@ -63,7 +63,7 @@ Address : EURECOM,
#define PGW_CONFIG_STRING_IP_ADDRESS_POOL "IP_ADDRESS_POOL"
#define PGW_CONFIG_STRING_IPV4_ADDRESS_LIST "IPV4_LIST"
#define PGW_CONFIG_STRING_IPV6_ADDRESS_LIST "IPV6_LIST"
#define PGW_CONFIG_STRING_IP_ADDRESS_RANGE_DELIMITERS " -<>"
#define PGW_CONFIG_STRING_IPV4_PREFIX_DELIMITER " /"
#define PGW_CONFIG_STRING_IPV6_PREFIX_DELIMITER " /"
#define PGW_CONFIG_STRING_INTERFACE_DISABLED "none"
@@ -96,6 +96,20 @@ typedef struct sgw_config_s {
// may be more
#define PGW_MAX_ALLOCATED_PDN_ADDRESSES 1024
typedef struct pgw_lite_conf_ipv4_list_elm_s {
STAILQ_ENTRY(pgw_lite_conf_ipv4_list_elm_s) ipv4_entries;
struct in_addr addr;
} pgw_lite_conf_ipv4_list_elm_t;
typedef struct pgw_lite_conf_ipv6_list_elm_s {
STAILQ_ENTRY(pgw_lite_conf_ipv6_list_elm_s) ipv6_entries;
struct in6_addr addr;
int prefix_len;
} pgw_lite_conf_ipv6_list_elm_t;
typedef struct pgw_config_s {
struct {
char *pgw_interface_name_for_S5_S8;
@@ -107,12 +121,8 @@ typedef struct pgw_config_s {
int pgw_ip_netmask_for_SGI;
} ipv4;
struct {
int num_ipv4_addresses;
struct in_addr ipv4_addresses[PGW_MAX_ALLOCATED_PDN_ADDRESSES];
int num_ipv6_addresses;
struct in6_addr ipv6_addresses[PGW_MAX_ALLOCATED_PDN_ADDRESSES];
} pool_pdn_addresses;
STAILQ_HEAD(pgw_lite_ipv4_pool_head_s, pgw_lite_conf_ipv4_list_elm_s) pgw_lite_ipv4_pool_list;
STAILQ_HEAD(pgw_lite_ipv6_pool_head_s, pgw_lite_conf_ipv6_list_elm_s) pgw_lite_ipv6_pool_list;
} pgw_config_t;
typedef struct spgw_config_s {
+1 -1
View File
@@ -281,7 +281,7 @@ static void *udp_intertask_interface(void *args_p)
} break;
}
on_error:
free(received_message_p);
itti_free(ITTI_MSG_ORIGIN_ID(received_message_p), received_message_p);
received_message_p = NULL;
}
return NULL;
+22
View File
@@ -50,6 +50,28 @@
# define hton_int16(x) (x)
#endif
#define IN_ADDR_TO_BUFFER(X,bUFF) INT32_TO_BUFFER((X).s_addr,(char*)bUFF)
#define IN6_ADDR_TO_BUFFER(X,bUFF) \
do { \
((uint8_t*)(bUFF))[0] = (X).s6_addr[0]; \
((uint8_t*)(bUFF))[1] = (X).s6_addr[1]; \
((uint8_t*)(bUFF))[2] = (X).s6_addr[2]; \
((uint8_t*)(bUFF))[3] = (X).s6_addr[3]; \
((uint8_t*)(bUFF))[4] = (X).s6_addr[4]; \
((uint8_t*)(bUFF))[5] = (X).s6_addr[5]; \
((uint8_t*)(bUFF))[6] = (X).s6_addr[6]; \
((uint8_t*)(bUFF))[7] = (X).s6_addr[7]; \
((uint8_t*)(bUFF))[8] = (X).s6_addr[8]; \
((uint8_t*)(bUFF))[9] = (X).s6_addr[9]; \
((uint8_t*)(bUFF))[10] = (X).s6_addr[10]; \
((uint8_t*)(bUFF))[11] = (X).s6_addr[11]; \
((uint8_t*)(bUFF))[12] = (X).s6_addr[12]; \
((uint8_t*)(bUFF))[13] = (X).s6_addr[13]; \
((uint8_t*)(bUFF))[14] = (X).s6_addr[14]; \
((uint8_t*)(bUFF))[15] = (X).s6_addr[15]; \
} while(0)
#define BUFFER_TO_INT8(buf, x) (x = ((buf)[0]))
#define INT8_TO_BUFFER(x, buf) ((buf)[0] = (x))
+10
View File
@@ -185,6 +185,16 @@ static int config_parse_file(mme_config_t *mme_config_p)
else
mme_config_p->unauthenticated_imsi_supported = 0;
}
if( (config_setting_lookup_string( setting_mme, MME_CONFIG_STRING_ASN1_VERBOSITY, (const char **)&astring) )) {
if (strcasecmp(astring , MME_CONFIG_STRING_ASN1_VERBOSITY_NONE) == 0)
mme_config_p->verbosity_level = 0;
else if (strcasecmp(astring , MME_CONFIG_STRING_ASN1_VERBOSITY_ANNOYING) == 0)
mme_config_p->verbosity_level = 2;
else if (strcasecmp(astring , MME_CONFIG_STRING_ASN1_VERBOSITY_INFO) == 0)
mme_config_p->verbosity_level = 1;
else
mme_config_p->verbosity_level = 0;
}
// ITTI SETTING
setting = config_setting_get_member (setting_mme, MME_CONFIG_STRING_INTERTASK_INTERFACE_CONFIG);
+5
View File
@@ -73,6 +73,11 @@
#define MME_CONFIG_STRING_INTERFACE_NAME_FOR_S11_MME "MME_INTERFACE_NAME_FOR_S11_MME"
#define MME_CONFIG_STRING_IPV4_ADDRESS_FOR_S11_MME "MME_IPV4_ADDRESS_FOR_S11_MME"
#define MME_CONFIG_STRING_ASN1_VERBOSITY "VERBOSITY"
#define MME_CONFIG_STRING_ASN1_VERBOSITY_NONE "none"
#define MME_CONFIG_STRING_ASN1_VERBOSITY_ANNOYING "annoying"
#define MME_CONFIG_STRING_ASN1_VERBOSITY_INFO "info"
typedef struct mme_config_s {
/* Reader/writer lock for this configuration */
+10 -1
View File
@@ -191,6 +191,13 @@ AC_ARG_ENABLE([nas],
[])
AM_CONDITIONAL([DISABLE_USE_NAS], [test x$enable_nas == xno])
AC_ARG_ENABLE([s11],
AS_HELP_STRING([--disable-s11], [Disable S11 layer]),
[CFLAGS="$CFLAGS -DDISABLE_S11"],
[])
AM_CONDITIONAL([DISABLE_S11], [test x$enable_s11 == xno])
dnl *** Enable PCAP for SGI ***
AC_ARG_ENABLE([pcap_for_sgi],
AS_HELP_STRING([--enable-pcap-for-sgi], [Enable PCAP for SGI layer]),
@@ -371,4 +378,6 @@ fi
if test x$raw_socket_for_sgi == xtrue; then
echo "SGI raw socket.: yes"
fi
fi
+1 -1
View File
@@ -191,7 +191,7 @@ typedef struct transport_layer_addr_s {
* silently forward it to S1-U.
*/
uint8_t length;
uint8_t buffer[20];
uint8_t buffer[20]; // in network byte order
} transport_layer_addr_t;
#define TRANSPORT_LAYER_ADDR_COPY(dEST,sOURCE) \

Some files were not shown because too many files have changed in this diff Show More