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:
@@ -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"
|
||||
|
||||
@@ -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_ */
|
||||
|
||||
@@ -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_ */
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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 **)>pv1u_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(>PV1U_ENB_CREATE_TUNNEL_RESP(message_p).enb_addr.buffer,
|
||||
>pv1u_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(>PV1U_ENB_CREATE_TUNNEL_RESP(message_p).enb_addr.buffer,
|
||||
>pv1u_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(>PV1U_ENB_CREATE_TUNNEL_RESP(message_p).enb_addr.buffer,
|
||||
>pv1u_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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
@@ -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.
|
||||
|
||||
|
||||
@@ -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 \
|
||||
|
||||
@@ -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
@@ -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(¤t_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,
|
||||
¤t_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);
|
||||
}
|
||||
|
||||
|
||||
Executable
+64
@@ -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;
|
||||
}
|
||||
Executable
+286
@@ -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;
|
||||
}
|
||||
Executable
+43
@@ -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_ */
|
||||
@@ -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;
|
||||
|
||||
@@ -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_ */
|
||||
|
||||
@@ -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_
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
Executable
+156
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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: {
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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_
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
/*
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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]);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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,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";
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
Executable
+177
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
Executable
+47
@@ -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
|
||||
@@ -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;
|
||||
|
||||
/********************************
|
||||
|
||||
@@ -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_ */
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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_ */
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
|
||||
|
||||
@@ -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
Reference in New Issue
Block a user