git-svn-id: http://svn.eurecom.fr/openair4G/trunk@4234 818b1a75-f10b-46b9-bf7c-635c3b92a50f
This commit is contained in:
@@ -0,0 +1 @@
|
||||
|
||||
@@ -0,0 +1,526 @@
|
||||
/*****************************************************************************
|
||||
Eurecom OpenAirInterface 3
|
||||
Copyright(c) 2012 Eurecom
|
||||
|
||||
Source as_message.h
|
||||
|
||||
Version 0.1
|
||||
|
||||
Date 2012/10/18
|
||||
|
||||
Product NAS stack
|
||||
|
||||
Subsystem Application Programming Interface
|
||||
|
||||
Author Frederic Maurel
|
||||
|
||||
Description Defines the messages supported by the Access Stratum sublayer
|
||||
protocol (usually RRC and S1AP for E-UTRAN) and functions used
|
||||
to encode and decode
|
||||
|
||||
*****************************************************************************/
|
||||
#ifndef __AS_MESSAGE_H__
|
||||
#define __AS_MESSAGE_H__
|
||||
|
||||
#include "commonDef.h"
|
||||
// #include "networkDef.h"
|
||||
|
||||
/****************************************************************************/
|
||||
/********************* G L O B A L C O N S T A N T S *******************/
|
||||
/****************************************************************************/
|
||||
|
||||
/*
|
||||
* --------------------------------------------------------------------------
|
||||
* Access Stratum message types
|
||||
* --------------------------------------------------------------------------
|
||||
*/
|
||||
#define AS_REQUEST 0x0100
|
||||
#define AS_RESPONSE 0x0200
|
||||
#define AS_INDICATION 0x0400
|
||||
#define AS_CONFIRM 0x0800
|
||||
|
||||
/*
|
||||
* --------------------------------------------------------------------------
|
||||
* Access Stratum message identifiers
|
||||
* --------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/* Broadcast information */
|
||||
#define AS_BROADCAST_INFO 0x01
|
||||
#define AS_BROADCAST_INFO_IND (AS_BROADCAST_INFO | AS_INDICATION)
|
||||
|
||||
/* Cell information relevant for cell selection processing */
|
||||
#define AS_CELL_INFO 0x02
|
||||
#define AS_CELL_INFO_REQ (AS_CELL_INFO | AS_REQUEST)
|
||||
#define AS_CELL_INFO_CNF (AS_CELL_INFO | AS_CONFIRM)
|
||||
#define AS_CELL_INFO_IND (AS_CELL_INFO | AS_INDICATION)
|
||||
|
||||
/* Paging information */
|
||||
#define AS_PAGING 0x03
|
||||
#define AS_PAGING_REQ (AS_PAGING | AS_REQUEST)
|
||||
#define AS_PAGING_IND (AS_PAGING | AS_INDICATION)
|
||||
|
||||
/* NAS signalling connection establishment */
|
||||
#define AS_NAS_ESTABLISH 0x04
|
||||
#define AS_NAS_ESTABLISH_REQ (AS_NAS_ESTABLISH | AS_REQUEST)
|
||||
#define AS_NAS_ESTABLISH_IND (AS_NAS_ESTABLISH | AS_INDICATION)
|
||||
#define AS_NAS_ESTABLISH_RSP (AS_NAS_ESTABLISH | AS_RESPONSE)
|
||||
#define AS_NAS_ESTABLISH_CNF (AS_NAS_ESTABLISH | AS_CONFIRM)
|
||||
|
||||
/* NAS signalling connection release */
|
||||
#define AS_NAS_RELEASE 0x05
|
||||
#define AS_NAS_RELEASE_REQ (AS_NAS_RELEASE | AS_REQUEST)
|
||||
#define AS_NAS_RELEASE_IND (AS_NAS_RELEASE | AS_INDICATION)
|
||||
|
||||
/* Uplink information transfer */
|
||||
#define AS_UL_INFO_TRANSFER 0x06
|
||||
#define AS_UL_INFO_TRANSFER_REQ (AS_UL_INFO_TRANSFER | AS_REQUEST)
|
||||
#define AS_UL_INFO_TRANSFER_CNF (AS_UL_INFO_TRANSFER | AS_CONFIRM)
|
||||
#define AS_UL_INFO_TRANSFER_IND (AS_UL_INFO_TRANSFER | AS_INDICATION)
|
||||
|
||||
/* Downlink information transfer */
|
||||
#define AS_DL_INFO_TRANSFER 0x07
|
||||
#define AS_DL_INFO_TRANSFER_REQ (AS_DL_INFO_TRANSFER | AS_REQUEST)
|
||||
#define AS_DL_INFO_TRANSFER_CNF (AS_DL_INFO_TRANSFER | AS_CONFIRM)
|
||||
#define AS_DL_INFO_TRANSFER_IND (AS_DL_INFO_TRANSFER | AS_INDICATION)
|
||||
|
||||
/* Radio Access Bearer establishment */
|
||||
#define AS_RAB_ESTABLISH 0x08
|
||||
#define AS_RAB_ESTABLISH_REQ (AS_RAB_ESTABLISH | AS_REQUEST)
|
||||
#define AS_RAB_ESTABLISH_IND (AS_RAB_ESTABLISH | AS_INDICATION)
|
||||
#define AS_RAB_ESTABLISH_RSP (AS_RAB_ESTABLISH | AS_RESPONSE)
|
||||
#define AS_RAB_ESTABLISH_CNF (AS_RAB_ESTABLISH | AS_CONFIRM)
|
||||
|
||||
/* Radio Access Bearer release */
|
||||
#define AS_RAB_RELEASE 0x09
|
||||
#define AS_RAB_RELEASE_REQ (AS_RAB_RELEASE | AS_REQUEST)
|
||||
#define AS_RAB_RELEASE_IND (AS_RAB_RELEASE | AS_INDICATION)
|
||||
|
||||
/* NAS Cause */
|
||||
#define EPS_SERVICES_AND_NON_EPS_SERVICES_NOT_ALLOWED (8)
|
||||
#define EPS_SERVICES_NOT_ALLOWED (7)
|
||||
#define PLMN_NOT_ALLOWED (11)
|
||||
#define TRACKING_AREA_NOT_ALLOWED (12)
|
||||
#define ROAMING_NOT_ALLOWED_IN_THIS_TRACKING_AREA (13)
|
||||
#define EPS_SERVICES_NOT_ALLOWED_IN_THIS_PLMN (14)
|
||||
#define NO_SUITABLE_CELLS_IN_TRACKING_AREA (15)
|
||||
#define NETWORK_FAILURE (17)
|
||||
#define ESM_FAILURE (19)
|
||||
|
||||
/*
|
||||
* --------------------------------------------------------------------------
|
||||
* Access Stratum message global parameters
|
||||
* --------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/* Error code */
|
||||
enum {
|
||||
AS_SUCCESS = 1, /* Success code, transaction is going on */
|
||||
AS_TERMINATED_NAS, /* Transaction terminated by NAS */
|
||||
AS_TERMINATED_AS, /* Transaction terminated by AS */
|
||||
AS_FAILURE /* Failure code */
|
||||
};
|
||||
|
||||
/* Core network domain */
|
||||
enum {
|
||||
AS_PS = 1, /* Packet-Switched */
|
||||
AS_CS /* Circuit-Switched */
|
||||
};
|
||||
|
||||
/* SAE Temporary Mobile Subscriber Identity */
|
||||
typedef struct {
|
||||
UInt8_t MMEcode; /* MME code that allocated the GUTI */
|
||||
UInt32_t m_tmsi; /* M-Temporary Mobile Subscriber Identity */
|
||||
} as_stmsi_t;
|
||||
|
||||
/* Dedicated NAS information */
|
||||
typedef struct {
|
||||
UInt32_t length; /* Length of the NAS information data */
|
||||
Byte_t* data; /* Dedicated NAS information data container */
|
||||
} as_nas_info_t;
|
||||
|
||||
/* Radio Access Bearer identity */
|
||||
typedef UInt8_t as_rab_id_t;
|
||||
|
||||
/****************************************************************************/
|
||||
/************************ G L O B A L T Y P E S ************************/
|
||||
/****************************************************************************/
|
||||
|
||||
/*
|
||||
* --------------------------------------------------------------------------
|
||||
* Broadcast information
|
||||
* --------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/*
|
||||
* AS->NAS - Broadcast information indication
|
||||
* AS may asynchronously report to NAS available PLMNs within specific
|
||||
* location area
|
||||
*/
|
||||
typedef struct {
|
||||
#define PLMN_LIST_MAX_SIZE 6
|
||||
PLMN_LIST_T(PLMN_LIST_MAX_SIZE) plmnIDs; /* List of PLMN identifiers */
|
||||
ci_t cellID; /* Identity of the cell serving the listed PLMNs */
|
||||
tac_t tac; /* Code of the tracking area the cell belongs to */
|
||||
} broadcast_info_ind_t;
|
||||
|
||||
/*
|
||||
* --------------------------------------------------------------------------
|
||||
* Cell information relevant for cell selection processing
|
||||
* --------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/* Radio access technologies supported by the network */
|
||||
#define AS_GSM (1 << NET_ACCESS_GSM)
|
||||
#define AS_COMPACT (1 << NET_ACCESS_COMPACT)
|
||||
#define AS_UTRAN (1 << NET_ACCESS_UTRAN)
|
||||
#define AS_EGPRS (1 << NET_ACCESS_EGPRS)
|
||||
#define AS_HSDPA (1 << NET_ACCESS_HSDPA)
|
||||
#define AS_HSUPA (1 << NET_ACCESS_HSUPA)
|
||||
#define AS_HSDUPA (1 << NET_ACCESS_HSDUPA)
|
||||
#define AS_EUTRAN (1 << NET_ACCESS_EUTRAN)
|
||||
|
||||
/*
|
||||
* NAS->AS - Cell Information request
|
||||
* NAS request AS to search for a suitable cell belonging to the selected
|
||||
* PLMN to camp on.
|
||||
*/
|
||||
typedef struct {
|
||||
plmn_t plmnID; /* Selected PLMN identity */
|
||||
Byte_t rat; /* Bitmap - set of radio access technologies */
|
||||
} cell_info_req_t;
|
||||
|
||||
/*
|
||||
* AS->NAS - Cell Information confirm
|
||||
* AS search for a suitable cell and respond to NAS. If found, the cell
|
||||
* is selected to camp on.
|
||||
*/
|
||||
typedef struct {
|
||||
UInt8_t errCode; /* Error code */
|
||||
ci_t cellID; /* Identity of the cell serving the selected PLMN */
|
||||
tac_t tac; /* Code of the tracking area the cell belongs to */
|
||||
AcT_t rat; /* Radio access technology supported by the cell */
|
||||
UInt8_t rsrq; /* Reference signal received quality */
|
||||
UInt8_t rsrp; /* Reference signal received power */
|
||||
} cell_info_cnf_t;
|
||||
|
||||
/*
|
||||
* AS->NAS - Cell Information indication
|
||||
* AS may change cell selection if a more suitable cell is found.
|
||||
*/
|
||||
typedef struct {
|
||||
ci_t cellID; /* Identity of the new serving cell */
|
||||
tac_t tac; /* Code of the tracking area the cell belongs to */
|
||||
} cell_info_ind_t;
|
||||
|
||||
/*
|
||||
* --------------------------------------------------------------------------
|
||||
* Paging information
|
||||
* --------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/* Paging cause */
|
||||
enum {
|
||||
AS_CONNECTION_ESTABLISH, /* Establish NAS signalling connection */
|
||||
AS_EPS_ATTACH, /* Perform local detach and initiate EPS
|
||||
* attach procedure */
|
||||
AS_CS_FALLBACK /* Inititate CS fallback procedure */
|
||||
};
|
||||
|
||||
/*
|
||||
* NAS->AS - Paging Information request
|
||||
* NAS requests the AS that NAS signalling messages or user data is pending
|
||||
* to be sent.
|
||||
*/
|
||||
typedef struct {
|
||||
as_stmsi_t s_tmsi; /* UE identity */
|
||||
UInt8_t CN_domain; /* Core network domain */
|
||||
} paging_req_t;
|
||||
|
||||
/*
|
||||
* AS->NAS - Paging Information indication
|
||||
* AS reports to the NAS that appropriate procedure has to be initiated.
|
||||
*/
|
||||
typedef struct {
|
||||
UInt8_t cause; /* Paging cause */
|
||||
} paging_ind_t;
|
||||
|
||||
/*
|
||||
* --------------------------------------------------------------------------
|
||||
* NAS signalling connection establishment
|
||||
* --------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/* Cause of RRC connection establishment */
|
||||
#define AS_CAUSE_EMERGENCY (NET_ESTABLISH_CAUSE_EMERGENCY)
|
||||
#define AS_CAUSE_HIGH_PRIO (NET_ESTABLISH_CAUSE_HIGH_PRIO)
|
||||
#define AS_CAUSE_MT_ACCESS (NET_ESTABLISH_CAUSE_MT_ACCESS)
|
||||
#define AS_CAUSE_MO_SIGNAL (NET_ESTABLISH_CAUSE_MO_SIGNAL)
|
||||
#define AS_CAUSE_MO_DATA (NET_ESTABLISH_CAUSE_MO_DATA)
|
||||
#define AS_CAUSE_V1020 (NET_ESTABLISH_CAUSE_V1020)
|
||||
|
||||
/* Type of the call associated to the RRC connection establishment */
|
||||
#define AS_TYPE_ORIGINATING_SIGNAL (NET_ESTABLISH_TYPE_ORIGINATING_SIGNAL)
|
||||
#define AS_TYPE_EMERGENCY_CALLS (NET_ESTABLISH_TYPE_EMERGENCY_CALLS)
|
||||
#define AS_TYPE_ORIGINATING_CALLS (NET_ESTABLISH_TYPE_ORIGINATING_CALLS)
|
||||
#define AS_TYPE_TERMINATING_CALLS (NET_ESTABLISH_TYPE_TERMINATING_CALLS)
|
||||
#define AS_TYPE_MO_CS_FALLBACK (NET_ESTABLISH_TYPE_MO_CS_FALLBACK)
|
||||
|
||||
|
||||
/*
|
||||
* NAS->AS - NAS signalling connection establishment request
|
||||
* NAS requests the AS to perform the RRC connection establishment procedure
|
||||
* to transfer initial NAS message to the network while UE is in IDLE mode.
|
||||
*/
|
||||
typedef struct {
|
||||
UInt8_t cause; /* RRC connection establishment cause */
|
||||
UInt8_t type; /* RRC associated call type */
|
||||
as_stmsi_t s_tmsi; /* UE identity */
|
||||
plmn_t plmnID; /* Selected PLMN identity */
|
||||
as_nas_info_t initialNasMsg; /* Initial NAS message to transfer */
|
||||
} nas_establish_req_t;
|
||||
|
||||
/*
|
||||
* AS->NAS - NAS signalling connection establishment indication
|
||||
* AS transfers the initial NAS message to the NAS.
|
||||
*/
|
||||
typedef struct {
|
||||
UInt32_t UEid; /* UE lower layer identifier */
|
||||
tac_t tac; /* Code of the tracking area the initiating
|
||||
* UE belongs to */
|
||||
as_nas_info_t initialNasMsg; /* Initial NAS message to transfer */
|
||||
} nas_establish_ind_t;
|
||||
|
||||
/*
|
||||
* NAS->AS - NAS signalling connection establishment response
|
||||
* NAS responds to the AS that initial answer message has to be provided to
|
||||
* the UE.
|
||||
*/
|
||||
typedef struct {
|
||||
UInt32_t UEid; /* UE lower layer identifier */
|
||||
as_stmsi_t s_tmsi; /* UE identity */
|
||||
UInt8_t errCode; /* Transaction status */
|
||||
as_nas_info_t nasMsg; /* NAS message to transfer */
|
||||
} nas_establish_rsp_t;
|
||||
|
||||
/*
|
||||
* AS->NAS - NAS signalling connection establishment confirm
|
||||
* AS transfers the initial answer message to the NAS.
|
||||
*/
|
||||
typedef struct {
|
||||
UInt8_t errCode; /* Transaction status */
|
||||
as_nas_info_t nasMsg; /* NAS message to transfer */
|
||||
} nas_establish_cnf_t;
|
||||
|
||||
/*
|
||||
* --------------------------------------------------------------------------
|
||||
* NAS signalling connection release
|
||||
* --------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/* Release cause */
|
||||
enum {
|
||||
AS_AUTHENTICATION_FAILURE = 1, /* Authentication procedure failed */
|
||||
AS_DETACH /* Detach requested */
|
||||
};
|
||||
|
||||
/*
|
||||
* NAS->AS - NAS signalling connection release request
|
||||
* NAS requests the termination of the connection with the UE.
|
||||
*/
|
||||
typedef struct {
|
||||
UInt32_t UEid; /* UE lower layer identifier */
|
||||
as_stmsi_t s_tmsi; /* UE identity */
|
||||
UInt8_t cause; /* Release cause */
|
||||
} nas_release_req_t;
|
||||
|
||||
/*
|
||||
* AS->NAS - NAS signalling connection release indication
|
||||
* AS reports that connection has been terminated by the network.
|
||||
*/
|
||||
typedef struct {
|
||||
UInt8_t cause; /* Release cause */
|
||||
} nas_release_ind_t;
|
||||
|
||||
/*
|
||||
* --------------------------------------------------------------------------
|
||||
* NAS information transfer
|
||||
* --------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/*
|
||||
* NAS->AS - Uplink data transfer request
|
||||
* NAS requests the AS to transfer uplink information to the NAS that
|
||||
* operates at the network side.
|
||||
*/
|
||||
typedef struct {
|
||||
UInt32_t UEid; /* UE lower layer identifier */
|
||||
as_stmsi_t s_tmsi; /* UE identity */
|
||||
as_nas_info_t nasMsg; /* Uplink NAS message */
|
||||
} ul_info_transfer_req_t;
|
||||
|
||||
/*
|
||||
* AS->NAS - Uplink data transfer confirm
|
||||
* AS immediately notifies the NAS whether uplink information has been
|
||||
* successfully sent to the network or not.
|
||||
*/
|
||||
typedef struct {
|
||||
UInt32_t UEid; /* UE lower layer identifier */
|
||||
UInt8_t errCode; /* Transaction status */
|
||||
} ul_info_transfer_cnf_t;
|
||||
|
||||
/*
|
||||
* AS->NAS - Uplink data transfer indication
|
||||
* AS delivers the uplink information message to the NAS that operates
|
||||
* at the network side.
|
||||
*/
|
||||
typedef struct {
|
||||
UInt32_t UEid; /* UE lower layer identifier */
|
||||
as_nas_info_t nasMsg; /* Uplink NAS message */
|
||||
} ul_info_transfer_ind_t;
|
||||
|
||||
/*
|
||||
* NAS->AS - Downlink data transfer request
|
||||
* NAS requests the AS to transfer downlink information to the NAS that
|
||||
* operates at the UE side.
|
||||
*/
|
||||
typedef ul_info_transfer_req_t dl_info_transfer_req_t;
|
||||
|
||||
/*
|
||||
* AS->NAS - Downlink data transfer confirm
|
||||
* AS immediately notifies the NAS whether downlink information has been
|
||||
* successfully sent to the network or not.
|
||||
*/
|
||||
typedef ul_info_transfer_cnf_t dl_info_transfer_cnf_t;
|
||||
|
||||
/*
|
||||
* AS->NAS - Downlink data transfer indication
|
||||
* AS delivers the downlink information message to the NAS that operates
|
||||
* at the UE side.
|
||||
*/
|
||||
typedef ul_info_transfer_ind_t dl_info_transfer_ind_t;
|
||||
|
||||
/*
|
||||
* --------------------------------------------------------------------------
|
||||
* Radio Access Bearer establishment
|
||||
* --------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/* TODO: Quality of Service parameters */
|
||||
typedef struct {} as_qos_t;
|
||||
|
||||
/*
|
||||
* NAS->AS - Radio access bearer establishment request
|
||||
* NAS requests the AS to allocate transmission resources to radio access
|
||||
* bearer initialized at the network side.
|
||||
*/
|
||||
typedef struct {
|
||||
as_stmsi_t s_tmsi; /* UE identity */
|
||||
as_rab_id_t rabID; /* Radio access bearer identity */
|
||||
as_qos_t QoS; /* Requested Quality of Service */
|
||||
} rab_establish_req_t;
|
||||
|
||||
/*
|
||||
* AS->NAS - Radio access bearer establishment indication
|
||||
* AS notifies the NAS that specific radio access bearer has to be setup.
|
||||
*/
|
||||
typedef struct {
|
||||
as_rab_id_t rabID; /* Radio access bearer identity */
|
||||
} rab_establish_ind_t;
|
||||
|
||||
/*
|
||||
* NAS->AS - Radio access bearer establishment response
|
||||
* NAS responds to AS whether the specified radio access bearer has been
|
||||
* successfully setup or not.
|
||||
*/
|
||||
typedef struct {
|
||||
as_stmsi_t s_tmsi; /* UE identity */
|
||||
as_rab_id_t rabID; /* Radio access bearer identity */
|
||||
UInt8_t errCode; /* Transaction status */
|
||||
} rab_establish_rsp_t;
|
||||
|
||||
/*
|
||||
* AS->NAS - Radio access bearer establishment confirm
|
||||
* AS notifies NAS whether the specified radio access bearer has been
|
||||
* successfully setup at the UE side or not.
|
||||
*/
|
||||
typedef struct {
|
||||
as_rab_id_t rabID; /* Radio access bearer identity */
|
||||
UInt8_t errCode; /* Transaction status */
|
||||
} rab_establish_cnf_t;
|
||||
|
||||
/*
|
||||
* --------------------------------------------------------------------------
|
||||
* Radio Access Bearer release
|
||||
* --------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/*
|
||||
* NAS->AS - Radio access bearer release request
|
||||
* NAS requests the AS to release transmission resources previously allocated
|
||||
* to specific radio access bearer at the network side.
|
||||
*/
|
||||
typedef struct {
|
||||
as_stmsi_t s_tmsi; /* UE identity */
|
||||
as_rab_id_t rabID; /* Radio access bearer identity */
|
||||
} rab_release_req_t;
|
||||
|
||||
/*
|
||||
* AS->NAS - Radio access bearer release indication
|
||||
* AS notifies NAS that specific radio access bearer has been released.
|
||||
*/
|
||||
typedef struct {
|
||||
as_rab_id_t rabID; /* Radio access bearer identity */
|
||||
} rab_release_ind_t;
|
||||
|
||||
/*
|
||||
* --------------------------------------------------------------------------
|
||||
* Structure of the AS messages handled by the network sublayer
|
||||
* --------------------------------------------------------------------------
|
||||
*/
|
||||
typedef struct {
|
||||
UInt16_t msgID;
|
||||
union {
|
||||
broadcast_info_ind_t broadcast_info_ind;
|
||||
cell_info_req_t cell_info_req;
|
||||
cell_info_cnf_t cell_info_cnf;
|
||||
cell_info_ind_t cell_info_ind;
|
||||
paging_req_t paging_req;
|
||||
paging_ind_t paging_ind;
|
||||
nas_establish_req_t nas_establish_req;
|
||||
nas_establish_ind_t nas_establish_ind;
|
||||
nas_establish_rsp_t nas_establish_rsp;
|
||||
nas_establish_cnf_t nas_establish_cnf;
|
||||
nas_release_req_t nas_release_req;
|
||||
nas_release_ind_t nas_release_ind;
|
||||
ul_info_transfer_req_t ul_info_transfer_req;
|
||||
ul_info_transfer_cnf_t ul_info_transfer_cnf;
|
||||
ul_info_transfer_ind_t ul_info_transfer_ind;
|
||||
dl_info_transfer_req_t dl_info_transfer_req;
|
||||
dl_info_transfer_cnf_t dl_info_transfer_cnf;
|
||||
dl_info_transfer_ind_t dl_info_transfer_ind;
|
||||
rab_establish_req_t rab_establish_req;
|
||||
rab_establish_ind_t rab_establish_ind;
|
||||
rab_establish_rsp_t rab_establish_rsp;
|
||||
rab_establish_cnf_t rab_establish_cnf;
|
||||
rab_release_req_t rab_release_req;
|
||||
rab_release_ind_t rab_release_ind;
|
||||
} __attribute__((__packed__)) msg;
|
||||
} as_message_t;
|
||||
|
||||
/****************************************************************************/
|
||||
/******************** G L O B A L V A R I A B L E S ********************/
|
||||
/****************************************************************************/
|
||||
|
||||
/****************************************************************************/
|
||||
/****************** E X P O R T E D F U N C T I O N S ******************/
|
||||
/****************************************************************************/
|
||||
|
||||
int as_message_decode(const char* buffer, as_message_t* msg, int length);
|
||||
|
||||
int as_message_encode(char* buffer, as_message_t* msg, int length);
|
||||
|
||||
/* Implemented in the network_api.c body file */
|
||||
int as_message_send(as_message_t* as_msg);
|
||||
|
||||
#endif /* __AS_MESSAGE_H__*/
|
||||
@@ -0,0 +1,249 @@
|
||||
/*****************************************************************************
|
||||
Eurecom OpenAirInterface 3
|
||||
Copyright(c) 2012 Eurecom
|
||||
|
||||
Source commonDef.h
|
||||
|
||||
Version 0.1
|
||||
|
||||
Date 2012/02/27
|
||||
|
||||
Product NAS stack
|
||||
|
||||
Subsystem include
|
||||
|
||||
Author Frederic Maurel
|
||||
|
||||
Description Contains global common definitions
|
||||
|
||||
*****************************************************************************/
|
||||
#ifndef __COMMONDEF_H__
|
||||
#define __COMMONDEF_H__
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
/****************************************************************************/
|
||||
/********************* G L O B A L C O N S T A N T S *******************/
|
||||
/****************************************************************************/
|
||||
|
||||
#define RETURNok (0)
|
||||
#define RETURNerror (-1)
|
||||
|
||||
#ifndef FALSE
|
||||
#define FALSE (0)
|
||||
#endif
|
||||
#ifndef TRUE
|
||||
#define TRUE (1)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Name of the environment variable which defines the default directory
|
||||
* where the NAS application is executed and where are located files
|
||||
* where non-volatile data are stored
|
||||
*/
|
||||
#define DEFAULT_NAS_PATH "PWD"
|
||||
|
||||
/****************************************************************************/
|
||||
/************************ G L O B A L T Y P E S ************************/
|
||||
/****************************************************************************/
|
||||
|
||||
/*
|
||||
-----------------------------------------------------------------------------
|
||||
Standard data type definitions
|
||||
-----------------------------------------------------------------------------
|
||||
*/
|
||||
typedef int8_t SByte_t; /* 8 bit signed integer */
|
||||
typedef int8_t Int8_t; /* 8 bit signed integer */
|
||||
typedef int16_t Int16_t; /* 16 bit signed integer */
|
||||
typedef int32_t Int32_t; /* 32 bit signed integer */
|
||||
typedef int64_t Int64_t; /* 64 bit signed integer */
|
||||
|
||||
|
||||
typedef uint8_t Byte_t; /* 8 bit unsigned integer */
|
||||
typedef uint8_t UInt8_t; /* 8 bit unsigned integer */
|
||||
typedef uint16_t UInt16_t; /* 16 bit unsigned integer */
|
||||
typedef uint32_t UInt32_t; /* 32 bit unsigned integer */
|
||||
typedef uint64_t UInt64_t; /* 64 bit unsigned integer */
|
||||
|
||||
/*
|
||||
-----------------------------------------------------------------------------
|
||||
Common NAS data type definitions
|
||||
-----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
typedef UInt8_t Stat_t; /* Registration status */
|
||||
typedef UInt16_t lac_t; /* Location Area Code */
|
||||
typedef UInt8_t rac_t; /* Routing Area Code */
|
||||
typedef UInt16_t tac_t; /* Tracking Area Code */
|
||||
typedef UInt32_t ci_t; /* Cell Identifier */
|
||||
typedef UInt8_t AcT_t; /* Access Technology */
|
||||
|
||||
/*
|
||||
* International Mobile Subscriber Identity
|
||||
*/
|
||||
typedef struct {
|
||||
Byte_t length;
|
||||
union {
|
||||
struct {
|
||||
Byte_t digit15:4;
|
||||
Byte_t digit14:4;
|
||||
Byte_t digit13:4;
|
||||
Byte_t digit12:4;
|
||||
Byte_t digit11:4;
|
||||
Byte_t digit10:4;
|
||||
Byte_t digit9:4;
|
||||
Byte_t digit8:4;
|
||||
Byte_t digit7:4;
|
||||
Byte_t digit6:4;
|
||||
Byte_t digit5:4;
|
||||
Byte_t digit4:4;
|
||||
Byte_t digit3:4;
|
||||
Byte_t digit2:4;
|
||||
Byte_t digit1:4;
|
||||
#define EVEN_PARITY 0
|
||||
#define ODD_PARITY 1
|
||||
Byte_t parity:4;
|
||||
} num;
|
||||
#define IMSI_SIZE 8
|
||||
Byte_t value[IMSI_SIZE];
|
||||
} u;
|
||||
} imsi_t;
|
||||
|
||||
/*
|
||||
* Mobile subscriber dialing number
|
||||
*/
|
||||
typedef struct {
|
||||
Byte_t ext:1;
|
||||
/* Type Of Number */
|
||||
#define MSISDN_TON_UNKNOWKN 0b000
|
||||
#define MSISDN_TON_INTERNATIONAL 0b001
|
||||
#define MSISDN_TON_NATIONAL 0b010
|
||||
#define MSISDN_TON_NETWORK 0b011
|
||||
#define MSISDN_TON_SUBCRIBER 0b100
|
||||
#define MSISDN_TON_ABBREVIATED 0b110
|
||||
#define MSISDN_TON_RESERVED 0b111
|
||||
Byte_t ton:3;
|
||||
/* Numbering Plan Identification */
|
||||
#define MSISDN_NPI_UNKNOWN 0b0000
|
||||
#define MSISDN_NPI_ISDN_TELEPHONY 0b0001
|
||||
#define MSISDN_NPI_GENERIC 0b0010
|
||||
#define MSISDN_NPI_DATA 0b0011
|
||||
#define MSISDN_NPI_TELEX 0b0100
|
||||
#define MSISDN_NPI_MARITIME_MOBILE 0b0101
|
||||
#define MSISDN_NPI_LAND_MOBILE 0b0110
|
||||
#define MSISDN_NPI_ISDN_MOBILE 0b0111
|
||||
#define MSISDN_NPI_PRIVATE 0b1110
|
||||
#define MSISDN_NPI_RESERVED 0b1111
|
||||
Byte_t npi:4;
|
||||
/* Dialing Number */
|
||||
struct {
|
||||
Byte_t lsb:4;
|
||||
Byte_t msb:4;
|
||||
#define MSISDN_DIGIT_SIZE 10
|
||||
} digit[MSISDN_DIGIT_SIZE];
|
||||
} msisdn_t;
|
||||
|
||||
/*
|
||||
* International Mobile Equipment Identity
|
||||
*/
|
||||
typedef imsi_t imei_t;
|
||||
|
||||
/*
|
||||
* Public Land Mobile Network identifier
|
||||
* PLMN = BCD encoding (Mobile Country Code + Mobile Network Code)
|
||||
*/
|
||||
typedef struct {
|
||||
Byte_t MCCdigit2:4;
|
||||
Byte_t MCCdigit1:4;
|
||||
Byte_t MNCdigit3:4;
|
||||
Byte_t MCCdigit3:4;
|
||||
Byte_t MNCdigit2:4;
|
||||
Byte_t MNCdigit1:4;
|
||||
} plmn_t;
|
||||
|
||||
/*
|
||||
* Location Area Identification
|
||||
*/
|
||||
typedef struct {
|
||||
plmn_t plmn; /* <MCC> + <MNC> */
|
||||
lac_t lac; /* Location Area Code */
|
||||
} lai_t;
|
||||
|
||||
/*
|
||||
* GPRS Routing Area Identification
|
||||
*/
|
||||
typedef struct {
|
||||
plmn_t plmn; /* <MCC> + <MNC> */
|
||||
lac_t lac; /* Location Area Code */
|
||||
rac_t rac; /* Routing Area Code */
|
||||
} RAI_t;
|
||||
|
||||
/*
|
||||
* EPS Tracking Area Identification
|
||||
*/
|
||||
typedef struct {
|
||||
plmn_t plmn; /* <MCC> + <MNC> */
|
||||
tac_t tac; /* Tracking Area Code */
|
||||
} tai_t;
|
||||
|
||||
/*
|
||||
* EPS Globally Unique MME Identity
|
||||
*/
|
||||
typedef struct {
|
||||
plmn_t plmn; /* <MCC> + <MNC> */
|
||||
UInt16_t MMEgid; /* MME group identifier */
|
||||
UInt8_t MMEcode; /* MME code */
|
||||
} gummei_t;
|
||||
|
||||
/*
|
||||
* EPS Globally Unique Temporary UE Identity
|
||||
*/
|
||||
typedef struct {
|
||||
gummei_t gummei; /* Globally Unique MME Identity */
|
||||
UInt32_t m_tmsi; /* M-Temporary Mobile Subscriber Identity */
|
||||
} GUTI_t;
|
||||
|
||||
/* Checks PLMN validity */
|
||||
#define PLMN_IS_VALID(plmn) (((plmn).MCCdigit1 & \
|
||||
(plmn).MCCdigit2 & \
|
||||
(plmn).MCCdigit3) != 0x0F)
|
||||
|
||||
/* Checks TAC validity */
|
||||
#define TAC_IS_VALID(tac) (((tac) != 0x0000) && ((tac) != 0xFFF0))
|
||||
|
||||
/* Checks TAI validity */
|
||||
#define TAI_IS_VALID(tai) (PLMN_IS_VALID((tai).plmn) && \
|
||||
TAC_IS_VALID((tai).tac))
|
||||
/*
|
||||
* A list of PLMNs
|
||||
*/
|
||||
#define PLMN_LIST_T(SIZE) struct {Byte_t n_plmns; plmn_t plmn[SIZE];}
|
||||
|
||||
/*
|
||||
* A list of TACs
|
||||
*/
|
||||
#define TAC_LIST_T(SIZE) struct {Byte_t n_tacs; TAC_t tac[SIZE];}
|
||||
|
||||
/*
|
||||
* A list of TAIs
|
||||
*/
|
||||
#define TAI_LIST_T(SIZE) struct {Byte_t n_tais; tai_t tai[SIZE];}
|
||||
|
||||
/*
|
||||
* User notification callback, executed whenever a change of data with
|
||||
* respect of network information (e.g. network registration and/or
|
||||
* location change, new PLMN becomes available) is notified by the
|
||||
* EPS Mobility Management sublayer
|
||||
*/
|
||||
typedef int (*indication_callback_t) (Stat_t, tac_t, ci_t, AcT_t, const char*, size_t);
|
||||
|
||||
/****************************************************************************/
|
||||
/******************** G L O B A L V A R I A B L E S ********************/
|
||||
/****************************************************************************/
|
||||
|
||||
/****************************************************************************/
|
||||
/****************** E X P O R T E D F U N C T I O N S ******************/
|
||||
/****************************************************************************/
|
||||
|
||||
#endif /* __COMMONDEF_H__*/
|
||||
@@ -0,0 +1,250 @@
|
||||
/*******************************************************************************
|
||||
|
||||
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 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.fr/openairinterface
|
||||
Address : EURECOM, Campus SophiaTech, 450 Route des Chappes
|
||||
06410 Biot FRANCE
|
||||
|
||||
*******************************************************************************/
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "commonDef.h"
|
||||
|
||||
#include "queue.h"
|
||||
|
||||
#ifndef COMMON_TYPES_H_
|
||||
#define COMMON_TYPES_H_
|
||||
|
||||
#define MSISDN_LENGTH (15)
|
||||
#define IMSI_DIGITS_MAX (15)
|
||||
#define APN_MAX_LENGTH (100)
|
||||
#define PRIORITY_LEVEL_MAX (15)
|
||||
#define PRIORITY_LEVEL_MIN (1)
|
||||
#define BEARERS_PER_UE (11)
|
||||
#define MAX_APN_PER_UE (5)
|
||||
|
||||
typedef enum {
|
||||
RAT_WLAN = 0,
|
||||
RAT_VIRTUAL = 1,
|
||||
RAT_UTRAN = 1000,
|
||||
RAT_GERAN = 1001,
|
||||
RAT_GAN = 1002,
|
||||
RAT_HSPA_EVOLUTION = 1003,
|
||||
RAT_EUTRAN = 1004,
|
||||
RAT_CDMA2000_1X = 2000,
|
||||
RAT_HRPD = 2001,
|
||||
RAT_UMB = 2002,
|
||||
RAT_EHRPD = 2003,
|
||||
} rat_type_t;
|
||||
|
||||
#define NUMBER_OF_RAT_TYPE 11
|
||||
|
||||
typedef enum {
|
||||
SS_SERVICE_GRANTED = 0,
|
||||
SS_OPERATOR_DETERMINED_BARRING = 1,
|
||||
SS_MAX,
|
||||
} subscriber_status_t;
|
||||
|
||||
typedef enum {
|
||||
NAM_PACKET_AND_CIRCUIT = 0,
|
||||
NAM_RESERVED = 1,
|
||||
NAM_ONLY_PACKET = 2,
|
||||
NAM_MAX,
|
||||
} network_access_mode_t;
|
||||
|
||||
typedef uint32_t bitrate_t;
|
||||
|
||||
typedef uint8_t ebi_t;
|
||||
typedef char* APN_t;
|
||||
typedef uint8_t APNRestriction_t;
|
||||
typedef uint8_t DelayValue_t;
|
||||
typedef uint8_t priority_level_t;
|
||||
typedef uint32_t Teid_t;
|
||||
typedef uint32_t SequenceNumber_t;
|
||||
typedef uint32_t access_restriction_t;
|
||||
typedef uint32_t context_identifier_t;
|
||||
typedef uint32_t rau_tau_timer_t;
|
||||
|
||||
typedef uint32_t ard_t;
|
||||
#define ARD_UTRAN_NOT_ALLOWED (1U)
|
||||
#define ARD_GERAN_NOT_ALLOWED (1U << 1)
|
||||
#define ARD_GAN_NOT_ALLOWED (1U << 2)
|
||||
#define ARD_I_HSDPA_EVO_NOT_ALLOWED (1U << 3)
|
||||
#define ARD_E_UTRAN_NOT_ALLOWED (1U << 4)
|
||||
#define ARD_HO_TO_NON_3GPP_NOT_ALLOWED (1U << 5)
|
||||
#define ARD_MAX (1U << 6)
|
||||
|
||||
typedef struct {
|
||||
plmn_t plmn;
|
||||
unsigned cell_identity:28;
|
||||
} cgi_t;
|
||||
|
||||
typedef union {
|
||||
struct {
|
||||
uint8_t imei[13];
|
||||
uint8_t sotfware_version[2];
|
||||
} id;
|
||||
uint8_t imeisv[15];
|
||||
} me_identity_t;
|
||||
|
||||
typedef struct {
|
||||
bitrate_t br_ul;
|
||||
bitrate_t br_dl;
|
||||
} ambr_t;
|
||||
|
||||
typedef enum {
|
||||
IPv4 = 0,
|
||||
IPv6 = 1,
|
||||
IPv4_AND_v6 = 2,
|
||||
IPv4_OR_v6 = 3,
|
||||
IP_MAX,
|
||||
} pdn_type_t;
|
||||
|
||||
typedef struct {
|
||||
pdn_type_t pdn_type;
|
||||
struct {
|
||||
uint8_t ipv4_address[4];
|
||||
uint8_t ipv6_address[16];
|
||||
} address;
|
||||
} ip_address_t;
|
||||
|
||||
typedef enum {
|
||||
QCI_1 = 1,
|
||||
QCI_2 = 2,
|
||||
QCI_3 = 3,
|
||||
QCI_4 = 4,
|
||||
QCI_5 = 5,
|
||||
QCI_6 = 6,
|
||||
QCI_7 = 7,
|
||||
QCI_8 = 8,
|
||||
QCI_9 = 9,
|
||||
/* Values from 128 to 254 are operator specific.
|
||||
* Other are reserved.
|
||||
*/
|
||||
QCI_MAX,
|
||||
} qci_t;
|
||||
|
||||
typedef enum {
|
||||
PRE_EMPTION_CAPABILITY_ENABLED = 0,
|
||||
PRE_EMPTION_CAPABILITY_DISABLED = 1,
|
||||
PRE_EMPTION_CAPABILITY_MAX,
|
||||
} pre_emp_capability_t;
|
||||
|
||||
typedef enum {
|
||||
PRE_EMPTION_VULNERABILITY_ENABLED = 0,
|
||||
PRE_EMPTION_VULNERABILITY_DISABLED = 1,
|
||||
PRE_EMPTION_VULNERABILITY_MAX,
|
||||
} pre_emp_vulnerability_t;
|
||||
|
||||
typedef struct {
|
||||
priority_level_t priority_level;
|
||||
pre_emp_vulnerability_t pre_emp_vulnerability;
|
||||
pre_emp_capability_t pre_emp_capability;
|
||||
} allocation_retention_priority_t;
|
||||
|
||||
typedef struct eps_subscribed_qos_profile_s {
|
||||
qci_t qci;
|
||||
allocation_retention_priority_t allocation_retention_priority;
|
||||
} eps_subscribed_qos_profile_t;
|
||||
|
||||
typedef struct apn_configuration_s {
|
||||
context_identifier_t context_identifier;
|
||||
|
||||
/* Each APN configuration can have 0, 1, or 2 ip address:
|
||||
* - 0 means subscribed is dynamically allocated by P-GW depending on the
|
||||
* pdn_type
|
||||
* - 1 Only one type of IP address is returned by HSS
|
||||
* - 2 IPv4 and IPv6 address are returned by HSS and are statically
|
||||
* allocated
|
||||
*/
|
||||
uint8_t nb_ip_address;
|
||||
ip_address_t ip_address[2];
|
||||
|
||||
pdn_type_t pdn_type;
|
||||
char service_selection[APN_MAX_LENGTH];
|
||||
int service_selection_length;
|
||||
eps_subscribed_qos_profile_t subscribed_qos;
|
||||
ambr_t ambr;
|
||||
} apn_configuration_t;
|
||||
|
||||
typedef enum {
|
||||
ALL_APN_CONFIGURATIONS_INCLUDED = 0,
|
||||
MODIFIED_ADDED_APN_CONFIGURATIONS_INCLUDED = 1,
|
||||
ALL_APN_MAX,
|
||||
} all_apn_conf_ind_t;
|
||||
|
||||
typedef struct {
|
||||
context_identifier_t context_identifier;
|
||||
all_apn_conf_ind_t all_apn_conf_ind;
|
||||
/* Number of APNs provided */
|
||||
uint8_t nb_apns;
|
||||
/* List of APNs configuration 1 to n elements */
|
||||
struct apn_configuration_s apn_configuration[MAX_APN_PER_UE];
|
||||
} apn_config_profile_t;
|
||||
|
||||
typedef struct {
|
||||
subscriber_status_t subscriber_status;
|
||||
char msisdn[MSISDN_LENGTH + 1];
|
||||
uint8_t msisdn_length;
|
||||
network_access_mode_t access_mode;
|
||||
access_restriction_t access_restriction;
|
||||
ambr_t subscribed_ambr;
|
||||
apn_config_profile_t apn_config_profile;
|
||||
rau_tau_timer_t rau_tau_timer;
|
||||
} subscription_data_t;
|
||||
|
||||
typedef struct {
|
||||
uint8_t nb_of_vectors;
|
||||
STAILQ_HEAD(e_utran_vector_list, eutran_vector_s) e_utran_vectors;
|
||||
} authentication_info_t;
|
||||
|
||||
typedef enum {
|
||||
DIAMETER_AUTHENTICATION_DATA_UNAVAILABLE = 4181,
|
||||
DIAMETER_ERROR_USER_UNKNOWN = 5001,
|
||||
DIAMETER_ERROR_ROAMING_NOT_ALLOWED = 5004,
|
||||
DIAMETER_ERROR_UNKNOWN_EPS_SUBSCRIPTION = 5420,
|
||||
DIAMETER_ERROR_RAT_NOT_ALLOWED = 5421,
|
||||
DIAMETER_ERROR_EQUIPMENT_UNKNOWN = 5422,
|
||||
DIAMETER_ERROR_UNKOWN_SERVING_NODE = 5423,
|
||||
} s6a_experimental_result_t;
|
||||
|
||||
typedef enum {
|
||||
DIAMETER_SUCCESS = 2001,
|
||||
} s6a_base_result_t;
|
||||
|
||||
typedef struct {
|
||||
#define S6A_RESULT_BASE 0x0
|
||||
#define S6A_RESULT_EXPERIMENTAL 0x1
|
||||
unsigned present:1;
|
||||
|
||||
union {
|
||||
/* Experimental result as defined in 3GPP TS 29.272 */
|
||||
s6a_experimental_result_t experimental;
|
||||
/* Diameter basics results as defined in RFC 3588 */
|
||||
s6a_base_result_t base;
|
||||
} choice;
|
||||
} s6a_result_t;
|
||||
|
||||
#endif /* COMMON_TYPES_H_ */
|
||||
@@ -0,0 +1,8 @@
|
||||
MESSAGE_DEF(GTPV1U_CREATE_TUNNEL_REQ, MESSAGE_PRIORITY_MED, Gtpv1uCreateTunnelReq, gtpv1uCreateTunnelReq)
|
||||
MESSAGE_DEF(GTPV1U_CREATE_TUNNEL_RESP, MESSAGE_PRIORITY_MED, Gtpv1uCreateTunnelResp, gtpv1uCreateTunnelResp)
|
||||
MESSAGE_DEF(GTPV1U_UPDATE_TUNNEL_REQ, MESSAGE_PRIORITY_MED, Gtpv1uUpdateTunnelReq, gtpv1uUpdateTunnelReq)
|
||||
MESSAGE_DEF(GTPV1U_UPDATE_TUNNEL_RESP, MESSAGE_PRIORITY_MED, Gtpv1uUpdateTunnelResp, gtpv1uUpdateTunnelResp)
|
||||
MESSAGE_DEF(GTPV1U_DELETE_TUNNEL_REQ, MESSAGE_PRIORITY_MED, Gtpv1uDeleteTunnelReq, gtpv1uDeleteTunnelReq)
|
||||
MESSAGE_DEF(GTPV1U_DELETE_TUNNEL_RESP, MESSAGE_PRIORITY_MED, Gtpv1uDeleteTunnelResp, gtpv1uDeleteTunnelResp)
|
||||
MESSAGE_DEF(GTPV1U_TUNNEL_DATA_IND, MESSAGE_PRIORITY_MED, Gtpv1uTunnelDataInd, gtpv1uTunnelDataInd)
|
||||
MESSAGE_DEF(GTPV1U_TUNNEL_DATA_REQ, MESSAGE_PRIORITY_MED, Gtpv1uTunnelDataReq, gtpv1uTunnelDataReq)
|
||||
@@ -0,0 +1,58 @@
|
||||
#ifndef GTPV1_U_MESSAGES_TYPES_H_
|
||||
#define GTPV1_U_MESSAGES_TYPES_H_
|
||||
|
||||
#include "../SGW-LITE/sgw_lite_ie_defs.h"
|
||||
|
||||
typedef struct {
|
||||
Teid_t context_teid; ///< Tunnel Endpoint Identifier
|
||||
ebi_t eps_bearer_id;
|
||||
} Gtpv1uCreateTunnelReq;
|
||||
|
||||
typedef struct {
|
||||
uint8_t status; ///< Status of S1U endpoint creation (Failed = 0xFF or Success = 0x0)
|
||||
Teid_t context_teid; ///< local SGW S11 Tunnel Endpoint Identifier
|
||||
Teid_t S1u_teid; ///< Tunnel Endpoint Identifier
|
||||
ebi_t eps_bearer_id;
|
||||
} Gtpv1uCreateTunnelResp;
|
||||
|
||||
typedef struct {
|
||||
Teid_t context_teid; ///< S11 Tunnel Endpoint Identifier
|
||||
Teid_t sgw_S1u_teid; ///< SGW S1U local Tunnel Endpoint Identifier
|
||||
Teid_t enb_S1u_teid; ///< eNB S1U Tunnel Endpoint Identifier
|
||||
ip_address_t enb_ip_address_for_S1u;
|
||||
ebi_t eps_bearer_id;
|
||||
} Gtpv1uUpdateTunnelReq;
|
||||
|
||||
typedef struct {
|
||||
uint8_t status; ///< Status (Failed = 0xFF or Success = 0x0)
|
||||
Teid_t context_teid; ///< S11 Tunnel Endpoint Identifier
|
||||
Teid_t sgw_S1u_teid; ///< SGW S1U local Tunnel Endpoint Identifier
|
||||
Teid_t enb_S1u_teid; ///< eNB S1U Tunnel Endpoint Identifier
|
||||
ebi_t eps_bearer_id;
|
||||
} Gtpv1uUpdateTunnelResp;
|
||||
|
||||
typedef struct {
|
||||
Teid_t context_teid; ///< local SGW S11 Tunnel Endpoint Identifier
|
||||
Teid_t S1u_teid; ///< local S1U Tunnel Endpoint Identifier to be deleted
|
||||
} Gtpv1uDeleteTunnelReq;
|
||||
|
||||
typedef struct {
|
||||
uint8_t status; ///< Status of S1U endpoint deleteion (Failed = 0xFF or Success = 0x0)
|
||||
Teid_t context_teid; ///< local SGW S11 Tunnel Endpoint Identifier
|
||||
Teid_t S1u_teid; ///< local S1U Tunnel Endpoint Identifier to be deleted
|
||||
} Gtpv1uDeleteTunnelResp;
|
||||
|
||||
typedef struct {
|
||||
uint8_t *buffer;
|
||||
uint32_t length;
|
||||
Teid_t local_S1u_teid; ///< Tunnel Endpoint Identifier
|
||||
} Gtpv1uTunnelDataInd;
|
||||
|
||||
typedef struct {
|
||||
uint8_t *buffer;
|
||||
uint32_t length;
|
||||
Teid_t local_S1u_teid; ///< Tunnel Endpoint Identifier
|
||||
Teid_t S1u_enb_teid; ///< Tunnel Endpoint Identifier
|
||||
} Gtpv1uTunnelDataReq;
|
||||
|
||||
#endif /* GTPV1_U_MESSAGES_TYPES_H_ */
|
||||
Executable
+6
@@ -0,0 +1,6 @@
|
||||
MESSAGE_DEF(SGI_CREATE_ENDPOINT_REQUEST, MESSAGE_PRIORITY_MED, SGICreateEndpointReq, sgiCreateEndpointReq)
|
||||
MESSAGE_DEF(SGI_CREATE_ENDPOINT_RESPONSE, MESSAGE_PRIORITY_MED, SGICreateEndpointResp, sgiCreateEndpointResp)
|
||||
MESSAGE_DEF(SGI_UPDATE_ENDPOINT_REQUEST, MESSAGE_PRIORITY_MED, SGIUpdateEndpointReq, sgiUpdateEndpointReq)
|
||||
MESSAGE_DEF(SGI_UPDATE_ENDPOINT_RESPONSE, MESSAGE_PRIORITY_MED, SGIUpdateEndpointResp, sgiUpdateEndpointResp)
|
||||
MESSAGE_DEF(SGI_DELETE_ENDPOINT_REQUEST, MESSAGE_PRIORITY_MED, SGIDeleteEndpointReq, sgiDeleteEndpointReq)
|
||||
MESSAGE_DEF(SGI_DELETE_ENDPOINT_RESPONSE, MESSAGE_PRIORITY_MED, SGIDeleteEndpointResp, sgiDeleteEndpointResp)
|
||||
+67
@@ -0,0 +1,67 @@
|
||||
#ifndef SGI_FORWARD_MESSAGES_TYPES_H_
|
||||
#define SGI_FORWARD_MESSAGES_TYPES_H_
|
||||
|
||||
typedef enum SGIStatus_e {
|
||||
SGI_STATUS_OK = 0,
|
||||
SGI_STATUS_ERROR_CONTEXT_ALREADY_EXIST = 50,
|
||||
SGI_STATUS_ERROR_CONTEXT_NOT_FOUND = 51,
|
||||
SGI_STATUS_ERROR_INVALID_MESSAGE_FORMAT = 52,
|
||||
SGI_STATUS_ERROR_SERVICE_NOT_SUPPORTED = 53,
|
||||
SGI_STATUS_ERROR_SYSTEM_FAILURE = 54,
|
||||
SGI_STATUS_ERROR_NO_RESOURCES_AVAILABLE = 55,
|
||||
SGI_STATUS_ERROR_NO_MEMORY_AVAILABLE = 56,
|
||||
SGI_STATUS_MAX,
|
||||
} SGIStatus_t;
|
||||
|
||||
|
||||
typedef struct {
|
||||
Teid_t context_teid; ///< Tunnel Endpoint Identifier S11
|
||||
Teid_t sgw_S1u_teid; ///< Tunnel Endpoint Identifier S1-U
|
||||
ebi_t eps_bearer_id; ///< EPS bearer identifier
|
||||
pdn_type_t pdn_type; ///< PDN Type
|
||||
PAA_t paa; ///< PDN Address Allocation
|
||||
} SGICreateEndpointReq;
|
||||
|
||||
typedef struct {
|
||||
SGIStatus_t status; ///< Status of endpoint creation (Failed = 0xFF or Success = 0x0)
|
||||
Teid_t context_teid; ///< Tunnel Endpoint Identifier S11
|
||||
Teid_t sgw_S1u_teid; ///< Tunnel Endpoint Identifier S1-U
|
||||
ebi_t eps_bearer_id; ///< EPS bearer identifier
|
||||
pdn_type_t pdn_type; ///< PDN Type
|
||||
PAA_t paa; ///< PDN Address Allocation
|
||||
} SGICreateEndpointResp;
|
||||
|
||||
typedef struct {
|
||||
Teid_t context_teid; ///< Tunnel Endpoint Identifier S11
|
||||
Teid_t sgw_S1u_teid; ///< Tunnel Endpoint Identifier S1-U
|
||||
Teid_t enb_S1u_teid; ///< Tunnel Endpoint Identifier S1-U
|
||||
ebi_t eps_bearer_id; ///< EPS bearer identifier
|
||||
} SGIUpdateEndpointReq;
|
||||
|
||||
typedef struct {
|
||||
SGIStatus_t status; ///< Status of endpoint creation (Failed = 0xFF or Success = 0x0)
|
||||
Teid_t context_teid; ///< Tunnel Endpoint Identifier S11
|
||||
Teid_t sgw_S1u_teid; ///< Tunnel Endpoint Identifier S1-U
|
||||
Teid_t enb_S1u_teid; ///< Tunnel Endpoint Identifier S1-U
|
||||
ebi_t eps_bearer_id; ///< EPS bearer identifier
|
||||
} SGIUpdateEndpointResp;
|
||||
|
||||
|
||||
typedef struct {
|
||||
Teid_t context_teid; ///< Tunnel Endpoint Identifier S11
|
||||
Teid_t sgw_S1u_teid; ///< Tunnel Endpoint Identifier S1-U
|
||||
ebi_t eps_bearer_id; ///< EPS bearer identifier
|
||||
pdn_type_t pdn_type; ///< PDN Type
|
||||
PAA_t paa; ///< PDN Address Allocation
|
||||
} SGIDeleteEndpointReq;
|
||||
|
||||
typedef struct {
|
||||
SGIStatus_t status; ///< Status of endpoint deletion (Failed = 0xFF or Success = 0x0)
|
||||
Teid_t context_teid; ///< Tunnel Endpoint Identifier S11
|
||||
Teid_t sgw_S1u_teid; ///< Tunnel Endpoint Identifier S1-U
|
||||
ebi_t eps_bearer_id; ///< EPS bearer identifier
|
||||
pdn_type_t pdn_type; ///< PDN Type
|
||||
PAA_t paa; ///< PDN Address Allocation
|
||||
} SGIDeleteEndpointResp;
|
||||
|
||||
#endif /* SGI_FORWARD_MESSAGES_TYPES_H_ */
|
||||
@@ -0,0 +1,15 @@
|
||||
// These messages files are mandatory and must always be placed in first position
|
||||
#include "intertask_messages_def.h"
|
||||
#include "timer_messages_def.h"
|
||||
|
||||
// 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"
|
||||
#include "s6a_messages_def.h"
|
||||
#include "sctp_messages_def.h"
|
||||
#include "sgw_lite_def.h"
|
||||
#include "udp_messages_def.h"
|
||||
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* messages_types.h
|
||||
*
|
||||
* Created on: Oct 14, 2013
|
||||
* Author: winckel
|
||||
*/
|
||||
|
||||
#ifndef MESSAGES_TYPES_H_
|
||||
#define MESSAGES_TYPES_H_
|
||||
|
||||
#include "timer_messages_types.h"
|
||||
|
||||
#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"
|
||||
#include "s6a_messages_types.h"
|
||||
#include "sctp_messages_types.h"
|
||||
#include "sgw_lite_messages_types.h"
|
||||
#include "udp_messages_types.h"
|
||||
|
||||
#endif /* MESSAGES_TYPES_H_ */
|
||||
@@ -0,0 +1,3 @@
|
||||
//WARNING: Do not include this header directly. Use intertask_interface.h instead.
|
||||
|
||||
//MESSAGE_DEF(S1AP_SCTP_NEW_MESSAGE_IND, MESSAGE_PRIORITY_MED, S1apSctpNewMessageInd, s1apSctpNewMessageInd)
|
||||
@@ -0,0 +1,6 @@
|
||||
#ifndef MME_APP_MESSAGES_TYPES_H_
|
||||
#define MME_APP_MESSAGES_TYPES_H_
|
||||
|
||||
|
||||
|
||||
#endif /* MME_APP_MESSAGES_TYPES_H_ */
|
||||
@@ -0,0 +1,16 @@
|
||||
//WARNING: Do not include this header directly. Use intertask_interface.h instead.
|
||||
|
||||
MESSAGE_DEF(NAS_PAGING_IND, MESSAGE_PRIORITY_MED, nas_paging_ind_t, nas_paging_ind)
|
||||
MESSAGE_DEF(NAS_CONNECTION_ESTABLISHMENT_IND, MESSAGE_PRIORITY_MED, nas_conn_est_ind_t, nas_conn_est_ind)
|
||||
MESSAGE_DEF(NAS_CONNECTION_ESTABLISHMENT_RSP, MESSAGE_PRIORITY_MED, nas_conn_est_rsp_t, nas_conn_est_rsp)
|
||||
MESSAGE_DEF(NAS_CONNECTION_RELEASE_IND, MESSAGE_PRIORITY_MED, nas_conn_rel_ind_t, nas_conn_rel_ind)
|
||||
MESSAGE_DEF(NAS_UPLINK_DATA_IND, MESSAGE_PRIORITY_MED, nas_ul_data_ind_t, nas_ul_data_ind)
|
||||
MESSAGE_DEF(NAS_DOWNLINK_DATA_IND, MESSAGE_PRIORITY_MED, nas_dl_data_ind_t, nas_dl_data_ind)
|
||||
MESSAGE_DEF(NAS_NON_DELIVERY_IND, MESSAGE_PRIORITY_MED, nas_non_del_ind_t, nas_non_del_ind)
|
||||
MESSAGE_DEF(NAS_RAB_ESTABLISHMENT_REQ, MESSAGE_PRIORITY_MED, nas_rab_est_req_t, nas_rab_est_req)
|
||||
MESSAGE_DEF(NAS_RAB_ESTABLISHMENT_RESP, MESSAGE_PRIORITY_MED, nas_rab_est_rsp_t, nas_rab_est_rsp)
|
||||
MESSAGE_DEF(NAS_RAB_RELEASE_REQ, MESSAGE_PRIORITY_MED, nas_rab_rel_req_t, nas_rab_rel_req)
|
||||
MESSAGE_DEF(NAS_ATTACH_REQ, MESSAGE_PRIORITY_MED, nas_attach_req_t, nas_attach_req)
|
||||
MESSAGE_DEF(NAS_ATTACH_ACCEPT, MESSAGE_PRIORITY_MED, nas_attach_accept_t, nas_attach_accept)
|
||||
MESSAGE_DEF(NAS_AUTHENTICATION_REQ, MESSAGE_PRIORITY_MED, nas_auth_req_t, nas_auth_req)
|
||||
MESSAGE_DEF(NAS_AUTHENTICATION_RESP, MESSAGE_PRIORITY_MED, nas_auth_resp_t, nas_auth_resp)
|
||||
@@ -0,0 +1,77 @@
|
||||
#include "as_message.h"
|
||||
|
||||
#ifndef NAS_MESSAGES_TYPES_H_
|
||||
#define NAS_MESSAGES_TYPES_H_
|
||||
|
||||
typedef struct {
|
||||
|
||||
} nas_paging_ind_t;
|
||||
|
||||
typedef struct {
|
||||
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;
|
||||
} nas_conn_est_ind_t;
|
||||
|
||||
typedef struct {
|
||||
|
||||
} nas_conn_est_rsp_t;
|
||||
|
||||
typedef struct {
|
||||
|
||||
} nas_conn_rel_ind_t;
|
||||
|
||||
typedef struct {
|
||||
|
||||
} nas_ul_data_ind_t;
|
||||
|
||||
typedef dl_info_transfer_req_t nas_dl_data_ind_t;
|
||||
|
||||
typedef struct {
|
||||
|
||||
} nas_non_del_ind_t;
|
||||
|
||||
typedef struct {
|
||||
|
||||
} nas_rab_est_req_t;
|
||||
|
||||
typedef struct {
|
||||
|
||||
} nas_rab_est_rsp_t;
|
||||
|
||||
typedef struct {
|
||||
|
||||
} nas_rab_rel_req_t;
|
||||
|
||||
typedef struct {
|
||||
/* TODO: Set the correct size */
|
||||
char apn[100];
|
||||
char imsi[16];
|
||||
#define INITIAL_REQUEST (0x1)
|
||||
unsigned initial:1;
|
||||
s1ap_initial_ue_message_t transparent;
|
||||
} nas_attach_req_t;
|
||||
|
||||
typedef struct {
|
||||
char imsi[16];
|
||||
|
||||
#define NAS_FAILURE_OK 0x0
|
||||
#define NAS_FAILURE_IND 0x1
|
||||
unsigned failure:1;
|
||||
int cause;
|
||||
|
||||
} nas_auth_req_t;
|
||||
|
||||
typedef struct {
|
||||
char imsi[16];
|
||||
} nas_auth_resp_t;
|
||||
|
||||
typedef struct {
|
||||
|
||||
s1ap_initial_ctxt_setup_req_t transparent;
|
||||
} nas_attach_accept_t;
|
||||
|
||||
#endif /* NAS_MESSAGES_TYPES_H_ */
|
||||
@@ -0,0 +1 @@
|
||||
//WARNING: Do not include this header directly. Use intertask_interface.h instead.
|
||||
@@ -0,0 +1,4 @@
|
||||
#ifndef S11_MESSAGES_TYPES_H_
|
||||
#define S11_MESSAGES_TYPES_H_
|
||||
|
||||
#endif /* S11_MESSAGES_TYPES_H_ */
|
||||
@@ -0,0 +1,4 @@
|
||||
//WARNING: Do not include this header directly. Use intertask_interface.h instead.
|
||||
|
||||
MESSAGE_DEF(S1AP_SCTP_NEW_MESSAGE_IND, MESSAGE_PRIORITY_MED, s1ap_sctp_new_msg_ind_t, s1ap_sctp_new_msg_ind)
|
||||
MESSAGE_DEF(S1AP_UE_CAPABILITIES_IND, MESSAGE_PRIORITY_MED, s1ap_ue_cap_ind_t, s1ap_ue_cap_ind)
|
||||
@@ -0,0 +1,51 @@
|
||||
#ifndef S1AP_MESSAGES_TYPES_H_
|
||||
#define S1AP_MESSAGES_TYPES_H_
|
||||
|
||||
typedef struct {
|
||||
uint8_t *buffer; ///< SCTP buffer
|
||||
uint32_t buf_length; ///< SCTP buffer length
|
||||
int32_t assoc_id; ///< SCTP physical association ID
|
||||
uint8_t stream; ///< Stream number on which data had been received
|
||||
uint16_t instreams; ///< Number of input streams for the SCTP connection between peers
|
||||
uint16_t outstreams; ///< Number of output streams for the SCTP connection between peers
|
||||
} s1ap_sctp_new_msg_ind_t;
|
||||
|
||||
typedef struct s1ap_initial_ue_message_s {
|
||||
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;
|
||||
|
||||
/* 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 teid;
|
||||
/* S-GW IP address for User-Plane */
|
||||
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;
|
||||
} s1ap_ue_cap_ind_t;
|
||||
|
||||
#endif /* S1AP_MESSAGES_TYPES_H_ */
|
||||
@@ -0,0 +1,5 @@
|
||||
//WARNING: Do not include this header directly. Use intertask_interface.h instead.
|
||||
MESSAGE_DEF(S6A_UPDATE_LOCATION_REQ, MESSAGE_PRIORITY_MED, s6a_update_location_req_t, s6a_update_location_req)
|
||||
MESSAGE_DEF(S6A_UPDATE_LOCATION_ANS, MESSAGE_PRIORITY_MED, s6a_update_location_ans_t, s6a_update_location_ans)
|
||||
MESSAGE_DEF(S6A_AUTH_INFO_REQ, MESSAGE_PRIORITY_MED, s6a_auth_info_req_t, s6a_auth_info_req)
|
||||
MESSAGE_DEF(S6A_AUTH_INFO_ANS, MESSAGE_PRIORITY_MED, s6a_auth_info_ans_t, s6a_auth_info_ans)
|
||||
@@ -0,0 +1,43 @@
|
||||
#ifndef S6A_MESSAGES_TYPES_H_
|
||||
#define S6A_MESSAGES_TYPES_H_
|
||||
|
||||
typedef struct {
|
||||
#define SKIP_SUBSRIBER_DATA (0x1)
|
||||
unsigned skip_subsriber_data:1;
|
||||
#define INITIAL_ATTACH (0x1)
|
||||
unsigned initial_attach:1;
|
||||
|
||||
char imsi[IMSI_DIGITS_MAX];
|
||||
uint8_t imsi_length;
|
||||
plmn_t visited_plmn;
|
||||
rat_type_t rat_type;
|
||||
} s6a_update_location_req_t;
|
||||
|
||||
typedef struct {
|
||||
char imsi[IMSI_DIGITS_MAX];
|
||||
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 {
|
||||
char imsi[IMSI_DIGITS_MAX];
|
||||
uint8_t imsi_length;
|
||||
plmn_t visited_plmn;
|
||||
/* Number of vectors to retrieve from HSS, should be equal to one */
|
||||
uint8_t nb_of_vectors;
|
||||
} s6a_auth_info_req_t;
|
||||
|
||||
typedef struct {
|
||||
char imsi[IMSI_DIGITS_MAX];
|
||||
uint8_t imsi_length;
|
||||
|
||||
/* Result of the authentication information procedure */
|
||||
s6a_result_t result;
|
||||
/* Authentication info containing the vector(s) */
|
||||
authentication_info_t auth_info;
|
||||
} s6a_auth_info_ans_t;
|
||||
|
||||
#endif /* S6A_MESSAGES_TYPES_H_ */
|
||||
@@ -0,0 +1,6 @@
|
||||
//WARNING: Do not include this header directly. Use intertask_interface.h instead.
|
||||
|
||||
MESSAGE_DEF(SCTP_INIT_MSG, MESSAGE_PRIORITY_MED, SctpInit, sctpInit)
|
||||
MESSAGE_DEF(SCTP_NEW_DATA_REQ, MESSAGE_PRIORITY_MED, SctpNewDataReq, sctpNewDataReq)
|
||||
MESSAGE_DEF(SCTP_NEW_ASSOCIATION, MESSAGE_PRIORITY_MAX, sctp_new_peer_t, sctp_new_peer)
|
||||
MESSAGE_DEF(SCTP_CLOSE_ASSOCIATION, MESSAGE_PRIORITY_MAX, sctp_close_association_t, sctp_close_association)
|
||||
@@ -0,0 +1,34 @@
|
||||
#ifndef SCTP_MESSAGES_TYPES_H_
|
||||
#define SCTP_MESSAGES_TYPES_H_
|
||||
|
||||
typedef struct {
|
||||
uint8_t *buffer;
|
||||
uint32_t bufLen;
|
||||
uint32_t assocId;
|
||||
uint16_t stream;
|
||||
} SctpNewDataReq;
|
||||
|
||||
typedef struct {
|
||||
/* Request usage of ipv4 */
|
||||
unsigned ipv4:1;
|
||||
/* Request usage of ipv6 */
|
||||
unsigned ipv6:1;
|
||||
uint8_t nb_ipv4_addr;
|
||||
uint32_t ipv4_address[10];
|
||||
uint8_t nb_ipv6_addr;
|
||||
char *ipv6_address[10];
|
||||
uint16_t port;
|
||||
uint32_t ppid;
|
||||
} SctpInit;
|
||||
|
||||
typedef struct {
|
||||
uint32_t assoc_id;
|
||||
} sctp_close_association_t;
|
||||
|
||||
typedef struct {
|
||||
uint32_t instreams;
|
||||
uint32_t outstreams;
|
||||
uint32_t assoc_id;
|
||||
} sctp_new_peer_t;
|
||||
|
||||
#endif /* SCTP_MESSAGES_TYPES_H_ */
|
||||
@@ -0,0 +1,183 @@
|
||||
#if HAVE_CONFIG_H
|
||||
# include "config.h"
|
||||
#endif
|
||||
|
||||
#if !defined(HAVE_UINT128_T)
|
||||
# include <gmp.h>
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
#include "queue.h"
|
||||
|
||||
#ifndef SECURITY_TYPES_H_
|
||||
#define SECURITY_TYPES_H_
|
||||
|
||||
#define RAND_LENGTH_BITS (128)
|
||||
#define RAND_LENGTH_OCTETS (RAND_LENGTH_BITS/8)
|
||||
#define AUTH_KEY_LENGTH_BITS (128)
|
||||
#define AUTH_KEY_LENGTH_OCTETS (AUTH_KEY_LENGTH_BITS/8)
|
||||
#define KASME_LENGTH_BITS (256)
|
||||
#define KASME_LENGTH_OCTETS (KASME_LENGTH_BITS/8)
|
||||
/* In OCTETS */
|
||||
#define XRES_LENGTH_MIN (4)
|
||||
#define XRES_LENGTH_MAX (16)
|
||||
#define AUTN_LENGTH_BITS (128)
|
||||
#define AUTN_LENGTH_OCTETS (AUTN_LENGTH_BITS/8)
|
||||
|
||||
/* Some methods to convert a string to an int64_t */
|
||||
/*
|
||||
#define STRING_TO_64BITS(sTRING, cONTAINER) \
|
||||
sscanf(sTRING, "%" SCN64, cONTAINER)
|
||||
#define STRING_TO_U64BITS(sTRING, cONTAINER) \
|
||||
sscanf(sTRING, "%" SCNu64, cONTAINER)
|
||||
*/
|
||||
|
||||
/* GCC supports 128 bits integers on certain architectures */
|
||||
#if defined(ENABLE_GMP_TYPES)
|
||||
/* Use gmplib in case GCC doesn't support 128 bits integers natively */
|
||||
typedef mpz_t rand_t;
|
||||
typedef mpz_t auth_key_t;
|
||||
typedef mpz_t auth_res_t;
|
||||
typedef mpz_t kasme_t;
|
||||
typedef mpz_t autn_t;
|
||||
|
||||
/* RES amd XRES can have a variable length of 4-16 octets */
|
||||
typedef struct {
|
||||
ssize_t size;
|
||||
auth_res_t data;
|
||||
} res_t;
|
||||
|
||||
/* Converts a string to 128 bits gmplib integer holder */
|
||||
# define STRING_TO_XBITS(sTRING, lENGTH, cONTAINER, rET) \
|
||||
do { \
|
||||
char temp[129]; \
|
||||
if (lENGTH > 64) { \
|
||||
rET = -1; \
|
||||
} else { \
|
||||
hexa_to_ascii(sTRING, temp, lENGTH); \
|
||||
temp[2 * lENGTH] = '\0'; \
|
||||
rET = mpz_init_set_str (cONTAINER, temp, 16); \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
# define STRING_TO_128BITS(sTRING, cONTAINER, rET) \
|
||||
STRING_TO_XBITS(sTRING, 16, cONTAINER, rET)
|
||||
|
||||
# define STRING_TO_256BITS(sTRING, cONTAINER, rET) \
|
||||
STRING_TO_XBITS(sTRING, 32, cONTAINER, rET)
|
||||
|
||||
# define STRING_TO_RAND STRING_TO_128BITS
|
||||
# define STRING_TO_AUTH_KEY STRING_TO_128BITS
|
||||
# define STRING_TO_AUTH_RES STRING_TO_128BITS
|
||||
# define STRING_TO_AUTN STRING_TO_128BITS
|
||||
# define STRING_TO_KASME STRING_TO_256BITS
|
||||
# define STRING_TO_XRES(sTRING, lENGTH, cONTAINER, rET) \
|
||||
do { \
|
||||
STRING_TO_XBITS(sTRING, lENGTH, (cONTAINER)->data, rET); \
|
||||
if (rET != -1) \
|
||||
(cONTAINER)->size = mpz_sizeinbase((cONTAINER)->data, 16); \
|
||||
} while(0)
|
||||
|
||||
/* Holds an E-UTRAN authentication vector */
|
||||
typedef struct eutran_vector_s {
|
||||
rand_t rand;
|
||||
res_t xres;
|
||||
autn_t autn;
|
||||
kasme_t kasme;
|
||||
|
||||
/* one UE can have multiple vectors so use STAILQ lists for easy management */
|
||||
STAILQ_ENTRY(eutran_vector_s) entries;
|
||||
} eutran_vector_t;
|
||||
|
||||
#else /* defined(ENABLE_GMP_TYPES) */
|
||||
|
||||
/* Converts a string to 128 bits gmplib integer holder */
|
||||
# define STRING_TO_XBITS(sTRING, lENGTH, cONTAINER, rET) \
|
||||
do { \
|
||||
memcpy(cONTAINER, sTRING, lENGTH); \
|
||||
rET = 0; \
|
||||
} while(0)
|
||||
|
||||
# define STRING_TO_128BITS(sTRING, cONTAINER, rET) \
|
||||
STRING_TO_XBITS(sTRING, 16, cONTAINER, rET)
|
||||
|
||||
# define STRING_TO_256BITS(sTRING, cONTAINER, rET) \
|
||||
STRING_TO_XBITS(sTRING, 32, cONTAINER, rET)
|
||||
|
||||
# define STRING_TO_RAND STRING_TO_128BITS
|
||||
# define STRING_TO_AUTH_KEY STRING_TO_128BITS
|
||||
# define STRING_TO_AUTH_RES STRING_TO_128BITS
|
||||
# define STRING_TO_AUTN STRING_TO_128BITS
|
||||
# define STRING_TO_KASME STRING_TO_256BITS
|
||||
# define STRING_TO_XRES(sTRING, lENGTH, cONTAINER, rET) \
|
||||
do { \
|
||||
STRING_TO_XBITS(sTRING, lENGTH, (cONTAINER)->data, rET); \
|
||||
if (rET != -1) \
|
||||
(cONTAINER)->size = lENGTH; \
|
||||
} while(0)
|
||||
|
||||
/* RES amd XRES can have a variable length of 4-16 octets */
|
||||
typedef struct {
|
||||
ssize_t size;
|
||||
uint8_t data[XRES_LENGTH_MAX];
|
||||
} res_t;
|
||||
|
||||
#define FORMAT_128BITS "%02x,%02x,%02x,%02x,%02x,%02x,%02x,%02x,%02x,%02x,%02x,%02x,%02x,%02x,%02x,%02x"
|
||||
#define RAND_FORMAT FORMAT_128BITS
|
||||
#define AUTN_FORMAT FORMAT_128BITS
|
||||
#define KASME_FORMAT FORMAT_128BITS
|
||||
|
||||
#define DISPLAY_128BITS(bUFFER) \
|
||||
bUFFER[0], bUFFER[1], bUFFER[2], bUFFER[3], bUFFER[4], bUFFER[5], bUFFER[6], bUFFER[7], \
|
||||
bUFFER[8], bUFFER[9], bUFFER[10], bUFFER[11], bUFFER[12], bUFFER[13], bUFFER[14], bUFFER[15]
|
||||
#define DISPLAY_128BITS_2(bUFFER) \
|
||||
bUFFER[16], bUFFER[17], bUFFER[18], bUFFER[19], bUFFER[20], bUFFER[21], bUFFER[22], bUFFER[23], \
|
||||
bUFFER[24], bUFFER[25], bUFFER[26], bUFFER[27], bUFFER[28], bUFFER[29], bUFFER[30], bUFFER[31]
|
||||
|
||||
#define RAND_DISPLAY(bUFFER) DISPLAY_128BITS(bUFFER)
|
||||
#define AUTN_DISPLAY(bUFFER) DISPLAY_128BITS(bUFFER)
|
||||
/* Display only first 128 bits of KASME */
|
||||
#define KASME_DISPLAY_1(bUFFER) DISPLAY_128BITS(bUFFER)
|
||||
#define KASME_DISPLAY_2(bUFFER) DISPLAY_128BITS_2(bUFFER)
|
||||
|
||||
/* Holds an E-UTRAN authentication vector */
|
||||
typedef struct eutran_vector_s {
|
||||
uint8_t rand[RAND_LENGTH_OCTETS];
|
||||
res_t xres;
|
||||
uint8_t autn[AUTN_LENGTH_OCTETS];
|
||||
uint8_t kasme[KASME_LENGTH_OCTETS];
|
||||
|
||||
/* one UE can have multiple vectors so use STAILQ lists for easy management */
|
||||
STAILQ_ENTRY(eutran_vector_s) entries;
|
||||
} eutran_vector_t;
|
||||
|
||||
#endif /* defined(ENABLE_GMP_TYPES) */
|
||||
|
||||
#define FC_KASME (0x10)
|
||||
#define FC_KENB (0x11)
|
||||
#define FC_NH (0x12)
|
||||
#define FC_KENB_STAR (0x13)
|
||||
/* 33401 #A.7 Algorithm for key derivation function.
|
||||
* This FC should be used for:
|
||||
* - NAS Encryption algorithm
|
||||
* - NAS Integrity algorithm
|
||||
* - RRC Encryption algorithm
|
||||
* - RRC Integrity algorithm
|
||||
* - User Plane Encryption algorithm
|
||||
*/
|
||||
#define FC_ALG_KEY_DER (0x15)
|
||||
#define FC_KASME_TO_CK (0x16)
|
||||
|
||||
typedef enum {
|
||||
NAS_ENC_ALG = 0x01,
|
||||
NAS_INT_ALG = 0x02,
|
||||
RRC_ENC_ALG = 0x03,
|
||||
RRC_INT_ALG = 0x04,
|
||||
UP_ENC_ALG = 0x05,
|
||||
UP_INT_ALG = 0x06
|
||||
} algorithm_type_dist_t;
|
||||
|
||||
#endif /* SECURITY_TYPES_H_ */
|
||||
@@ -0,0 +1,6 @@
|
||||
MESSAGE_DEF(SGW_CREATE_SESSION_REQUEST, MESSAGE_PRIORITY_MED, SgwCreateSessionRequest, sgwCreateSessionRequest)
|
||||
MESSAGE_DEF(SGW_CREATE_SESSION_RESPONSE, MESSAGE_PRIORITY_MED, SgwCreateSessionResponse, sgwCreateSessionResponse)
|
||||
MESSAGE_DEF(SGW_MODIFY_BEARER_REQUEST, MESSAGE_PRIORITY_MED, SgwModifyBearerRequest, sgwModifyBearerRequest)
|
||||
MESSAGE_DEF(SGW_MODIFY_BEARER_RESPONSE, MESSAGE_PRIORITY_MED, SgwModifyBearerResponse, sgwModifyBearerResponse)
|
||||
MESSAGE_DEF(SGW_DELETE_SESSION_REQUEST, MESSAGE_PRIORITY_MED, SgwDeleteSessionRequest, sgwDeleteSessionRequest)
|
||||
MESSAGE_DEF(SGW_DELETE_SESSION_RESPONSE, MESSAGE_PRIORITY_MED, SgwDeleteSessionResponse, sgwDeleteSessionResponse)
|
||||
@@ -0,0 +1,209 @@
|
||||
/*******************************************************************************
|
||||
|
||||
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 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.fr/openairinterface
|
||||
Address : EURECOM, Campus SophiaTech, 450 Route des Chappes
|
||||
06410 Biot FRANCE
|
||||
|
||||
*******************************************************************************/
|
||||
|
||||
/*! \file sgw_lite_messages_types.h
|
||||
* \brief S11 definitions for interaction between MME and S11
|
||||
* 3GPP TS 29.274.
|
||||
* Messages are the same as for GTPv2-C but here we abstract the UDP layer
|
||||
* \author Sebastien ROUX <sebastien.roux@eurecom.fr>
|
||||
* \date 2013
|
||||
* \version 0.1
|
||||
*/
|
||||
|
||||
#include "../SGW-LITE/sgw_lite_ie_defs.h"
|
||||
|
||||
#ifndef SGW_LITE_MESSAGES_TYPES_H_
|
||||
#define SGW_LITE_MESSAGES_TYPES_H_
|
||||
|
||||
/** @struct SgwCreateSessionRequest
|
||||
* @brief Create Session Request
|
||||
*
|
||||
* The Create Session Request will be sent on S11 interface as
|
||||
* part of these procedures:
|
||||
* - E-UTRAN Initial Attach
|
||||
* - UE requested PDN connectivity
|
||||
* - Tracking Area Update procedure with Serving GW change
|
||||
* - S1/X2-based handover with SGW change
|
||||
*/
|
||||
typedef struct {
|
||||
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;
|
||||
|
||||
/* S11 stack specific parameter. Not used in standalone epc mode */
|
||||
void *trxn; ///< Transaction identifier
|
||||
uint32_t peer_ip; ///< MME ipv4 address for S-GW or S-GW ipv4 address for MME
|
||||
uint16_t peer_port; ///< MME port for S-GW or S-GW port for MME
|
||||
} SgwCreateSessionRequest;
|
||||
|
||||
/** @struct SgwCreateSessionResponse
|
||||
* @brief Create Session Response
|
||||
*
|
||||
* The Create Session Response will be sent on S11 interface as
|
||||
* part of these procedures:
|
||||
* - E-UTRAN Initial Attach
|
||||
* - UE requested PDN connectivity
|
||||
* - Tracking Area Update procedure with SGW change
|
||||
* - S1/X2-based handover with SGW change
|
||||
*/
|
||||
typedef struct {
|
||||
Teid_t teid; ///< Tunnel Endpoint Identifier
|
||||
|
||||
SGWCause_t cause;
|
||||
FTeid_t s11_sgw_teid; ///< Sender F-TEID for control plane
|
||||
FTeid_t s5_s8_pgw_teid; ///< Sender F-TEID for control plane
|
||||
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;
|
||||
|
||||
/* S11 stack specific parameter. Not used in standalone epc mode */
|
||||
void *trxn; ///< Transaction identifier
|
||||
uint32_t peer_ip; ///< MME ipv4 address
|
||||
} SgwCreateSessionResponse;
|
||||
|
||||
/** @struct SgwModifyBearerRequest
|
||||
* @brief Modify Bearer Request
|
||||
*
|
||||
* The Modify Bearer Request will be sent on S11 interface as
|
||||
* part of these procedures:
|
||||
* - E-UTRAN Tracking Area Update without SGW Change
|
||||
* - UE triggered Service Request
|
||||
* - S1-based Handover
|
||||
* - E-UTRAN Initial Attach
|
||||
* - 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
|
||||
/* 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;
|
||||
|
||||
/* S11 stack specific parameter. Not used in standalone epc mode */
|
||||
void *trxn; ///< Transaction identifier
|
||||
} SgwModifyBearerRequest;
|
||||
|
||||
/** @struct SgwModifyBearerResponse
|
||||
* @brief Modify Bearer Response
|
||||
*
|
||||
* The Modify Bearer Response will be sent on S11 interface as
|
||||
* part of these procedures:
|
||||
* - E-UTRAN Tracking Area Update without SGW Change
|
||||
* - UE triggered Service Request
|
||||
* - S1-based Handover
|
||||
* - E-UTRAN Initial Attach
|
||||
* - UE requested PDN connectivity
|
||||
* - X2-based handover without SGWrelocation
|
||||
*/
|
||||
typedef struct {
|
||||
Teid_t teid; ///< Tunnel Endpoint Identifier
|
||||
SGWCause_t cause;
|
||||
#define MODIFY_BEARER_RESPONSE_MOD 0x0
|
||||
#define MODIFY_BEARER_RESPONSE_REM 0x1
|
||||
unsigned 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;
|
||||
|
||||
/* S11 stack specific parameter. Not used in standalone epc mode */
|
||||
void *trxn; ///< Transaction identifier
|
||||
} SgwModifyBearerResponse;
|
||||
|
||||
typedef struct {
|
||||
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
|
||||
* 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,
|
||||
* 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.
|
||||
*/
|
||||
indication_flags_t indication_flags;
|
||||
|
||||
/* GTPv2-C specific parameters */
|
||||
void *trxn;
|
||||
uint32_t peer_ip;
|
||||
} SgwDeleteSessionRequest;
|
||||
|
||||
/** @struct SgwDeleteSessionResponse
|
||||
* @brief Delete Session Response
|
||||
*
|
||||
* The Delete Session Response will be sent on S11 interface as
|
||||
* part of these procedures:
|
||||
* - EUTRAN Initial Attach
|
||||
* - UE, HSS or MME Initiated Detach
|
||||
* - UE or MME Requested PDN Disconnection
|
||||
* - Tracking Area Update with SGW Change
|
||||
* - S1 Based Handover with SGW Change
|
||||
* - X2 Based Handover with SGW Relocation
|
||||
* - S1 Based handover cancel with SGW change
|
||||
*/
|
||||
typedef struct {
|
||||
Teid_t teid; ///< Remote Tunnel Endpoint Identifier
|
||||
SGWCause_t cause;
|
||||
|
||||
/* GTPv2-C specific parameters */
|
||||
void *trxn;
|
||||
uint32_t peer_ip;
|
||||
} SgwDeleteSessionResponse;
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,25 @@
|
||||
// This task is mandatory and must always be placed in first position
|
||||
TASK_DEF(TASK_TIMER, TASK_PRIORITY_MED)
|
||||
|
||||
// Other possible tasks in the process
|
||||
|
||||
/// GTPV1-U task
|
||||
TASK_DEF(TASK_GTPV1_U, TASK_PRIORITY_MED)
|
||||
/// FW_IP task
|
||||
TASK_DEF(TASK_FW_IP, TASK_PRIORITY_MED)
|
||||
/// MME Applicative task
|
||||
TASK_DEF(TASK_MME_APP, TASK_PRIORITY_MED)
|
||||
/// NAS task
|
||||
TASK_DEF(TASK_NAS, TASK_PRIORITY_MED)
|
||||
/// S1AP task
|
||||
TASK_DEF(TASK_S11, TASK_PRIORITY_MED)
|
||||
/// S1AP task
|
||||
TASK_DEF(TASK_S1AP, TASK_PRIORITY_MED)
|
||||
/// S6a task
|
||||
TASK_DEF(TASK_S6A, TASK_PRIORITY_MED)
|
||||
/// SCTP task
|
||||
TASK_DEF(TASK_SCTP, TASK_PRIORITY_MED)
|
||||
/// Serving and Proxy Gateway Application task
|
||||
TASK_DEF(TASK_SPGW_APP, TASK_PRIORITY_MED)
|
||||
/// UDP task
|
||||
TASK_DEF(TASK_UDP, TASK_PRIORITY_MED)
|
||||
@@ -0,0 +1,3 @@
|
||||
MESSAGE_DEF(UDP_INIT, MESSAGE_PRIORITY_MED, udp_init_t, udp_init)
|
||||
MESSAGE_DEF(UDP_DATA_REQ, MESSAGE_PRIORITY_MED, udp_data_req_t, udp_data_req)
|
||||
MESSAGE_DEF(UDP_DATA_IND, MESSAGE_PRIORITY_MED, udp_data_ind_t, udp_data_ind)
|
||||
@@ -0,0 +1,16 @@
|
||||
#ifndef UDP_MESSAGES_TYPES_H_
|
||||
#define UDP_MESSAGES_TYPES_H_
|
||||
|
||||
typedef struct {
|
||||
uint32_t port;
|
||||
char *address;
|
||||
} udp_init_t;
|
||||
|
||||
typedef struct {
|
||||
uint8_t *buffer;
|
||||
uint32_t buffer_length;
|
||||
uint32_t peer_address;
|
||||
uint32_t peer_port;
|
||||
} udp_data_req_t, udp_data_ind_t;
|
||||
|
||||
#endif /* UDP_MESSAGES_TYPES_H_ */
|
||||
@@ -0,0 +1,674 @@
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 3, 29 June 2007
|
||||
|
||||
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The GNU General Public License is a free, copyleft license for
|
||||
software and other kinds of works.
|
||||
|
||||
The licenses for most software and other practical works are designed
|
||||
to take away your freedom to share and change the works. By contrast,
|
||||
the GNU General Public License is intended to guarantee your freedom to
|
||||
share and change all versions of a program--to make sure it remains free
|
||||
software for all its users. We, the Free Software Foundation, use the
|
||||
GNU General Public License for most of our software; it applies also to
|
||||
any other work released this way by its authors. You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
them if you wish), that you receive source code or can get it if you
|
||||
want it, that you can change the software or use pieces of it in new
|
||||
free programs, and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to prevent others from denying you
|
||||
these rights or asking you to surrender the rights. Therefore, you have
|
||||
certain responsibilities if you distribute copies of the software, or if
|
||||
you modify it: responsibilities to respect the freedom of others.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must pass on to the recipients the same
|
||||
freedoms that you received. You must make sure that they, too, receive
|
||||
or can get the source code. And you must show them these terms so they
|
||||
know their rights.
|
||||
|
||||
Developers that use the GNU GPL protect your rights with two steps:
|
||||
(1) assert copyright on the software, and (2) offer you this License
|
||||
giving you legal permission to copy, distribute and/or modify it.
|
||||
|
||||
For the developers' and authors' protection, the GPL clearly explains
|
||||
that there is no warranty for this free software. For both users' and
|
||||
authors' sake, the GPL requires that modified versions be marked as
|
||||
changed, so that their problems will not be attributed erroneously to
|
||||
authors of previous versions.
|
||||
|
||||
Some devices are designed to deny users access to install or run
|
||||
modified versions of the software inside them, although the manufacturer
|
||||
can do so. This is fundamentally incompatible with the aim of
|
||||
protecting users' freedom to change the software. The systematic
|
||||
pattern of such abuse occurs in the area of products for individuals to
|
||||
use, which is precisely where it is most unacceptable. Therefore, we
|
||||
have designed this version of the GPL to prohibit the practice for those
|
||||
products. If such problems arise substantially in other domains, we
|
||||
stand ready to extend this provision to those domains in future versions
|
||||
of the GPL, as needed to protect the freedom of users.
|
||||
|
||||
Finally, every program is threatened constantly by software patents.
|
||||
States should not allow patents to restrict development and use of
|
||||
software on general-purpose computers, but in those that do, we wish to
|
||||
avoid the special danger that patents applied to a free program could
|
||||
make it effectively proprietary. To prevent this, the GPL assures that
|
||||
patents cannot be used to render the program non-free.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
TERMS AND CONDITIONS
|
||||
|
||||
0. Definitions.
|
||||
|
||||
"This License" refers to version 3 of the GNU General Public License.
|
||||
|
||||
"Copyright" also means copyright-like laws that apply to other kinds of
|
||||
works, such as semiconductor masks.
|
||||
|
||||
"The Program" refers to any copyrightable work licensed under this
|
||||
License. Each licensee is addressed as "you". "Licensees" and
|
||||
"recipients" may be individuals or organizations.
|
||||
|
||||
To "modify" a work means to copy from or adapt all or part of the work
|
||||
in a fashion requiring copyright permission, other than the making of an
|
||||
exact copy. The resulting work is called a "modified version" of the
|
||||
earlier work or a work "based on" the earlier work.
|
||||
|
||||
A "covered work" means either the unmodified Program or a work based
|
||||
on the Program.
|
||||
|
||||
To "propagate" a work means to do anything with it that, without
|
||||
permission, would make you directly or secondarily liable for
|
||||
infringement under applicable copyright law, except executing it on a
|
||||
computer or modifying a private copy. Propagation includes copying,
|
||||
distribution (with or without modification), making available to the
|
||||
public, and in some countries other activities as well.
|
||||
|
||||
To "convey" a work means any kind of propagation that enables other
|
||||
parties to make or receive copies. Mere interaction with a user through
|
||||
a computer network, with no transfer of a copy, is not conveying.
|
||||
|
||||
An interactive user interface displays "Appropriate Legal Notices"
|
||||
to the extent that it includes a convenient and prominently visible
|
||||
feature that (1) displays an appropriate copyright notice, and (2)
|
||||
tells the user that there is no warranty for the work (except to the
|
||||
extent that warranties are provided), that licensees may convey the
|
||||
work under this License, and how to view a copy of this License. If
|
||||
the interface presents a list of user commands or options, such as a
|
||||
menu, a prominent item in the list meets this criterion.
|
||||
|
||||
1. Source Code.
|
||||
|
||||
The "source code" for a work means the preferred form of the work
|
||||
for making modifications to it. "Object code" means any non-source
|
||||
form of a work.
|
||||
|
||||
A "Standard Interface" means an interface that either is an official
|
||||
standard defined by a recognized standards body, or, in the case of
|
||||
interfaces specified for a particular programming language, one that
|
||||
is widely used among developers working in that language.
|
||||
|
||||
The "System Libraries" of an executable work include anything, other
|
||||
than the work as a whole, that (a) is included in the normal form of
|
||||
packaging a Major Component, but which is not part of that Major
|
||||
Component, and (b) serves only to enable use of the work with that
|
||||
Major Component, or to implement a Standard Interface for which an
|
||||
implementation is available to the public in source code form. A
|
||||
"Major Component", in this context, means a major essential component
|
||||
(kernel, window system, and so on) of the specific operating system
|
||||
(if any) on which the executable work runs, or a compiler used to
|
||||
produce the work, or an object code interpreter used to run it.
|
||||
|
||||
The "Corresponding Source" for a work in object code form means all
|
||||
the source code needed to generate, install, and (for an executable
|
||||
work) run the object code and to modify the work, including scripts to
|
||||
control those activities. However, it does not include the work's
|
||||
System Libraries, or general-purpose tools or generally available free
|
||||
programs which are used unmodified in performing those activities but
|
||||
which are not part of the work. For example, Corresponding Source
|
||||
includes interface definition files associated with source files for
|
||||
the work, and the source code for shared libraries and dynamically
|
||||
linked subprograms that the work is specifically designed to require,
|
||||
such as by intimate data communication or control flow between those
|
||||
subprograms and other parts of the work.
|
||||
|
||||
The Corresponding Source need not include anything that users
|
||||
can regenerate automatically from other parts of the Corresponding
|
||||
Source.
|
||||
|
||||
The Corresponding Source for a work in source code form is that
|
||||
same work.
|
||||
|
||||
2. Basic Permissions.
|
||||
|
||||
All rights granted under this License are granted for the term of
|
||||
copyright on the Program, and are irrevocable provided the stated
|
||||
conditions are met. This License explicitly affirms your unlimited
|
||||
permission to run the unmodified Program. The output from running a
|
||||
covered work is covered by this License only if the output, given its
|
||||
content, constitutes a covered work. This License acknowledges your
|
||||
rights of fair use or other equivalent, as provided by copyright law.
|
||||
|
||||
You may make, run and propagate covered works that you do not
|
||||
convey, without conditions so long as your license otherwise remains
|
||||
in force. You may convey covered works to others for the sole purpose
|
||||
of having them make modifications exclusively for you, or provide you
|
||||
with facilities for running those works, provided that you comply with
|
||||
the terms of this License in conveying all material for which you do
|
||||
not control copyright. Those thus making or running the covered works
|
||||
for you must do so exclusively on your behalf, under your direction
|
||||
and control, on terms that prohibit them from making any copies of
|
||||
your copyrighted material outside their relationship with you.
|
||||
|
||||
Conveying under any other circumstances is permitted solely under
|
||||
the conditions stated below. Sublicensing is not allowed; section 10
|
||||
makes it unnecessary.
|
||||
|
||||
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
|
||||
|
||||
No covered work shall be deemed part of an effective technological
|
||||
measure under any applicable law fulfilling obligations under article
|
||||
11 of the WIPO copyright treaty adopted on 20 December 1996, or
|
||||
similar laws prohibiting or restricting circumvention of such
|
||||
measures.
|
||||
|
||||
When you convey a covered work, you waive any legal power to forbid
|
||||
circumvention of technological measures to the extent such circumvention
|
||||
is effected by exercising rights under this License with respect to
|
||||
the covered work, and you disclaim any intention to limit operation or
|
||||
modification of the work as a means of enforcing, against the work's
|
||||
users, your or third parties' legal rights to forbid circumvention of
|
||||
technological measures.
|
||||
|
||||
4. Conveying Verbatim Copies.
|
||||
|
||||
You may convey verbatim copies of the Program's source code as you
|
||||
receive it, in any medium, provided that you conspicuously and
|
||||
appropriately publish on each copy an appropriate copyright notice;
|
||||
keep intact all notices stating that this License and any
|
||||
non-permissive terms added in accord with section 7 apply to the code;
|
||||
keep intact all notices of the absence of any warranty; and give all
|
||||
recipients a copy of this License along with the Program.
|
||||
|
||||
You may charge any price or no price for each copy that you convey,
|
||||
and you may offer support or warranty protection for a fee.
|
||||
|
||||
5. Conveying Modified Source Versions.
|
||||
|
||||
You may convey a work based on the Program, or the modifications to
|
||||
produce it from the Program, in the form of source code under the
|
||||
terms of section 4, provided that you also meet all of these conditions:
|
||||
|
||||
a) The work must carry prominent notices stating that you modified
|
||||
it, and giving a relevant date.
|
||||
|
||||
b) The work must carry prominent notices stating that it is
|
||||
released under this License and any conditions added under section
|
||||
7. This requirement modifies the requirement in section 4 to
|
||||
"keep intact all notices".
|
||||
|
||||
c) You must license the entire work, as a whole, under this
|
||||
License to anyone who comes into possession of a copy. This
|
||||
License will therefore apply, along with any applicable section 7
|
||||
additional terms, to the whole of the work, and all its parts,
|
||||
regardless of how they are packaged. This License gives no
|
||||
permission to license the work in any other way, but it does not
|
||||
invalidate such permission if you have separately received it.
|
||||
|
||||
d) If the work has interactive user interfaces, each must display
|
||||
Appropriate Legal Notices; however, if the Program has interactive
|
||||
interfaces that do not display Appropriate Legal Notices, your
|
||||
work need not make them do so.
|
||||
|
||||
A compilation of a covered work with other separate and independent
|
||||
works, which are not by their nature extensions of the covered work,
|
||||
and which are not combined with it such as to form a larger program,
|
||||
in or on a volume of a storage or distribution medium, is called an
|
||||
"aggregate" if the compilation and its resulting copyright are not
|
||||
used to limit the access or legal rights of the compilation's users
|
||||
beyond what the individual works permit. Inclusion of a covered work
|
||||
in an aggregate does not cause this License to apply to the other
|
||||
parts of the aggregate.
|
||||
|
||||
6. Conveying Non-Source Forms.
|
||||
|
||||
You may convey a covered work in object code form under the terms
|
||||
of sections 4 and 5, provided that you also convey the
|
||||
machine-readable Corresponding Source under the terms of this License,
|
||||
in one of these ways:
|
||||
|
||||
a) Convey the object code in, or embodied in, a physical product
|
||||
(including a physical distribution medium), accompanied by the
|
||||
Corresponding Source fixed on a durable physical medium
|
||||
customarily used for software interchange.
|
||||
|
||||
b) Convey the object code in, or embodied in, a physical product
|
||||
(including a physical distribution medium), accompanied by a
|
||||
written offer, valid for at least three years and valid for as
|
||||
long as you offer spare parts or customer support for that product
|
||||
model, to give anyone who possesses the object code either (1) a
|
||||
copy of the Corresponding Source for all the software in the
|
||||
product that is covered by this License, on a durable physical
|
||||
medium customarily used for software interchange, for a price no
|
||||
more than your reasonable cost of physically performing this
|
||||
conveying of source, or (2) access to copy the
|
||||
Corresponding Source from a network server at no charge.
|
||||
|
||||
c) Convey individual copies of the object code with a copy of the
|
||||
written offer to provide the Corresponding Source. This
|
||||
alternative is allowed only occasionally and noncommercially, and
|
||||
only if you received the object code with such an offer, in accord
|
||||
with subsection 6b.
|
||||
|
||||
d) Convey the object code by offering access from a designated
|
||||
place (gratis or for a charge), and offer equivalent access to the
|
||||
Corresponding Source in the same way through the same place at no
|
||||
further charge. You need not require recipients to copy the
|
||||
Corresponding Source along with the object code. If the place to
|
||||
copy the object code is a network server, the Corresponding Source
|
||||
may be on a different server (operated by you or a third party)
|
||||
that supports equivalent copying facilities, provided you maintain
|
||||
clear directions next to the object code saying where to find the
|
||||
Corresponding Source. Regardless of what server hosts the
|
||||
Corresponding Source, you remain obligated to ensure that it is
|
||||
available for as long as needed to satisfy these requirements.
|
||||
|
||||
e) Convey the object code using peer-to-peer transmission, provided
|
||||
you inform other peers where the object code and Corresponding
|
||||
Source of the work are being offered to the general public at no
|
||||
charge under subsection 6d.
|
||||
|
||||
A separable portion of the object code, whose source code is excluded
|
||||
from the Corresponding Source as a System Library, need not be
|
||||
included in conveying the object code work.
|
||||
|
||||
A "User Product" is either (1) a "consumer product", which means any
|
||||
tangible personal property which is normally used for personal, family,
|
||||
or household purposes, or (2) anything designed or sold for incorporation
|
||||
into a dwelling. In determining whether a product is a consumer product,
|
||||
doubtful cases shall be resolved in favor of coverage. For a particular
|
||||
product received by a particular user, "normally used" refers to a
|
||||
typical or common use of that class of product, regardless of the status
|
||||
of the particular user or of the way in which the particular user
|
||||
actually uses, or expects or is expected to use, the product. A product
|
||||
is a consumer product regardless of whether the product has substantial
|
||||
commercial, industrial or non-consumer uses, unless such uses represent
|
||||
the only significant mode of use of the product.
|
||||
|
||||
"Installation Information" for a User Product means any methods,
|
||||
procedures, authorization keys, or other information required to install
|
||||
and execute modified versions of a covered work in that User Product from
|
||||
a modified version of its Corresponding Source. The information must
|
||||
suffice to ensure that the continued functioning of the modified object
|
||||
code is in no case prevented or interfered with solely because
|
||||
modification has been made.
|
||||
|
||||
If you convey an object code work under this section in, or with, or
|
||||
specifically for use in, a User Product, and the conveying occurs as
|
||||
part of a transaction in which the right of possession and use of the
|
||||
User Product is transferred to the recipient in perpetuity or for a
|
||||
fixed term (regardless of how the transaction is characterized), the
|
||||
Corresponding Source conveyed under this section must be accompanied
|
||||
by the Installation Information. But this requirement does not apply
|
||||
if neither you nor any third party retains the ability to install
|
||||
modified object code on the User Product (for example, the work has
|
||||
been installed in ROM).
|
||||
|
||||
The requirement to provide Installation Information does not include a
|
||||
requirement to continue to provide support service, warranty, or updates
|
||||
for a work that has been modified or installed by the recipient, or for
|
||||
the User Product in which it has been modified or installed. Access to a
|
||||
network may be denied when the modification itself materially and
|
||||
adversely affects the operation of the network or violates the rules and
|
||||
protocols for communication across the network.
|
||||
|
||||
Corresponding Source conveyed, and Installation Information provided,
|
||||
in accord with this section must be in a format that is publicly
|
||||
documented (and with an implementation available to the public in
|
||||
source code form), and must require no special password or key for
|
||||
unpacking, reading or copying.
|
||||
|
||||
7. Additional Terms.
|
||||
|
||||
"Additional permissions" are terms that supplement the terms of this
|
||||
License by making exceptions from one or more of its conditions.
|
||||
Additional permissions that are applicable to the entire Program shall
|
||||
be treated as though they were included in this License, to the extent
|
||||
that they are valid under applicable law. If additional permissions
|
||||
apply only to part of the Program, that part may be used separately
|
||||
under those permissions, but the entire Program remains governed by
|
||||
this License without regard to the additional permissions.
|
||||
|
||||
When you convey a copy of a covered work, you may at your option
|
||||
remove any additional permissions from that copy, or from any part of
|
||||
it. (Additional permissions may be written to require their own
|
||||
removal in certain cases when you modify the work.) You may place
|
||||
additional permissions on material, added by you to a covered work,
|
||||
for which you have or can give appropriate copyright permission.
|
||||
|
||||
Notwithstanding any other provision of this License, for material you
|
||||
add to a covered work, you may (if authorized by the copyright holders of
|
||||
that material) supplement the terms of this License with terms:
|
||||
|
||||
a) Disclaiming warranty or limiting liability differently from the
|
||||
terms of sections 15 and 16 of this License; or
|
||||
|
||||
b) Requiring preservation of specified reasonable legal notices or
|
||||
author attributions in that material or in the Appropriate Legal
|
||||
Notices displayed by works containing it; or
|
||||
|
||||
c) Prohibiting misrepresentation of the origin of that material, or
|
||||
requiring that modified versions of such material be marked in
|
||||
reasonable ways as different from the original version; or
|
||||
|
||||
d) Limiting the use for publicity purposes of names of licensors or
|
||||
authors of the material; or
|
||||
|
||||
e) Declining to grant rights under trademark law for use of some
|
||||
trade names, trademarks, or service marks; or
|
||||
|
||||
f) Requiring indemnification of licensors and authors of that
|
||||
material by anyone who conveys the material (or modified versions of
|
||||
it) with contractual assumptions of liability to the recipient, for
|
||||
any liability that these contractual assumptions directly impose on
|
||||
those licensors and authors.
|
||||
|
||||
All other non-permissive additional terms are considered "further
|
||||
restrictions" within the meaning of section 10. If the Program as you
|
||||
received it, or any part of it, contains a notice stating that it is
|
||||
governed by this License along with a term that is a further
|
||||
restriction, you may remove that term. If a license document contains
|
||||
a further restriction but permits relicensing or conveying under this
|
||||
License, you may add to a covered work material governed by the terms
|
||||
of that license document, provided that the further restriction does
|
||||
not survive such relicensing or conveying.
|
||||
|
||||
If you add terms to a covered work in accord with this section, you
|
||||
must place, in the relevant source files, a statement of the
|
||||
additional terms that apply to those files, or a notice indicating
|
||||
where to find the applicable terms.
|
||||
|
||||
Additional terms, permissive or non-permissive, may be stated in the
|
||||
form of a separately written license, or stated as exceptions;
|
||||
the above requirements apply either way.
|
||||
|
||||
8. Termination.
|
||||
|
||||
You may not propagate or modify a covered work except as expressly
|
||||
provided under this License. Any attempt otherwise to propagate or
|
||||
modify it is void, and will automatically terminate your rights under
|
||||
this License (including any patent licenses granted under the third
|
||||
paragraph of section 11).
|
||||
|
||||
However, if you cease all violation of this License, then your
|
||||
license from a particular copyright holder is reinstated (a)
|
||||
provisionally, unless and until the copyright holder explicitly and
|
||||
finally terminates your license, and (b) permanently, if the copyright
|
||||
holder fails to notify you of the violation by some reasonable means
|
||||
prior to 60 days after the cessation.
|
||||
|
||||
Moreover, your license from a particular copyright holder is
|
||||
reinstated permanently if the copyright holder notifies you of the
|
||||
violation by some reasonable means, this is the first time you have
|
||||
received notice of violation of this License (for any work) from that
|
||||
copyright holder, and you cure the violation prior to 30 days after
|
||||
your receipt of the notice.
|
||||
|
||||
Termination of your rights under this section does not terminate the
|
||||
licenses of parties who have received copies or rights from you under
|
||||
this License. If your rights have been terminated and not permanently
|
||||
reinstated, you do not qualify to receive new licenses for the same
|
||||
material under section 10.
|
||||
|
||||
9. Acceptance Not Required for Having Copies.
|
||||
|
||||
You are not required to accept this License in order to receive or
|
||||
run a copy of the Program. Ancillary propagation of a covered work
|
||||
occurring solely as a consequence of using peer-to-peer transmission
|
||||
to receive a copy likewise does not require acceptance. However,
|
||||
nothing other than this License grants you permission to propagate or
|
||||
modify any covered work. These actions infringe copyright if you do
|
||||
not accept this License. Therefore, by modifying or propagating a
|
||||
covered work, you indicate your acceptance of this License to do so.
|
||||
|
||||
10. Automatic Licensing of Downstream Recipients.
|
||||
|
||||
Each time you convey a covered work, the recipient automatically
|
||||
receives a license from the original licensors, to run, modify and
|
||||
propagate that work, subject to this License. You are not responsible
|
||||
for enforcing compliance by third parties with this License.
|
||||
|
||||
An "entity transaction" is a transaction transferring control of an
|
||||
organization, or substantially all assets of one, or subdividing an
|
||||
organization, or merging organizations. If propagation of a covered
|
||||
work results from an entity transaction, each party to that
|
||||
transaction who receives a copy of the work also receives whatever
|
||||
licenses to the work the party's predecessor in interest had or could
|
||||
give under the previous paragraph, plus a right to possession of the
|
||||
Corresponding Source of the work from the predecessor in interest, if
|
||||
the predecessor has it or can get it with reasonable efforts.
|
||||
|
||||
You may not impose any further restrictions on the exercise of the
|
||||
rights granted or affirmed under this License. For example, you may
|
||||
not impose a license fee, royalty, or other charge for exercise of
|
||||
rights granted under this License, and you may not initiate litigation
|
||||
(including a cross-claim or counterclaim in a lawsuit) alleging that
|
||||
any patent claim is infringed by making, using, selling, offering for
|
||||
sale, or importing the Program or any portion of it.
|
||||
|
||||
11. Patents.
|
||||
|
||||
A "contributor" is a copyright holder who authorizes use under this
|
||||
License of the Program or a work on which the Program is based. The
|
||||
work thus licensed is called the contributor's "contributor version".
|
||||
|
||||
A contributor's "essential patent claims" are all patent claims
|
||||
owned or controlled by the contributor, whether already acquired or
|
||||
hereafter acquired, that would be infringed by some manner, permitted
|
||||
by this License, of making, using, or selling its contributor version,
|
||||
but do not include claims that would be infringed only as a
|
||||
consequence of further modification of the contributor version. For
|
||||
purposes of this definition, "control" includes the right to grant
|
||||
patent sublicenses in a manner consistent with the requirements of
|
||||
this License.
|
||||
|
||||
Each contributor grants you a non-exclusive, worldwide, royalty-free
|
||||
patent license under the contributor's essential patent claims, to
|
||||
make, use, sell, offer for sale, import and otherwise run, modify and
|
||||
propagate the contents of its contributor version.
|
||||
|
||||
In the following three paragraphs, a "patent license" is any express
|
||||
agreement or commitment, however denominated, not to enforce a patent
|
||||
(such as an express permission to practice a patent or covenant not to
|
||||
sue for patent infringement). To "grant" such a patent license to a
|
||||
party means to make such an agreement or commitment not to enforce a
|
||||
patent against the party.
|
||||
|
||||
If you convey a covered work, knowingly relying on a patent license,
|
||||
and the Corresponding Source of the work is not available for anyone
|
||||
to copy, free of charge and under the terms of this License, through a
|
||||
publicly available network server or other readily accessible means,
|
||||
then you must either (1) cause the Corresponding Source to be so
|
||||
available, or (2) arrange to deprive yourself of the benefit of the
|
||||
patent license for this particular work, or (3) arrange, in a manner
|
||||
consistent with the requirements of this License, to extend the patent
|
||||
license to downstream recipients. "Knowingly relying" means you have
|
||||
actual knowledge that, but for the patent license, your conveying the
|
||||
covered work in a country, or your recipient's use of the covered work
|
||||
in a country, would infringe one or more identifiable patents in that
|
||||
country that you have reason to believe are valid.
|
||||
|
||||
If, pursuant to or in connection with a single transaction or
|
||||
arrangement, you convey, or propagate by procuring conveyance of, a
|
||||
covered work, and grant a patent license to some of the parties
|
||||
receiving the covered work authorizing them to use, propagate, modify
|
||||
or convey a specific copy of the covered work, then the patent license
|
||||
you grant is automatically extended to all recipients of the covered
|
||||
work and works based on it.
|
||||
|
||||
A patent license is "discriminatory" if it does not include within
|
||||
the scope of its coverage, prohibits the exercise of, or is
|
||||
conditioned on the non-exercise of one or more of the rights that are
|
||||
specifically granted under this License. You may not convey a covered
|
||||
work if you are a party to an arrangement with a third party that is
|
||||
in the business of distributing software, under which you make payment
|
||||
to the third party based on the extent of your activity of conveying
|
||||
the work, and under which the third party grants, to any of the
|
||||
parties who would receive the covered work from you, a discriminatory
|
||||
patent license (a) in connection with copies of the covered work
|
||||
conveyed by you (or copies made from those copies), or (b) primarily
|
||||
for and in connection with specific products or compilations that
|
||||
contain the covered work, unless you entered into that arrangement,
|
||||
or that patent license was granted, prior to 28 March 2007.
|
||||
|
||||
Nothing in this License shall be construed as excluding or limiting
|
||||
any implied license or other defenses to infringement that may
|
||||
otherwise be available to you under applicable patent law.
|
||||
|
||||
12. No Surrender of Others' Freedom.
|
||||
|
||||
If conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot convey a
|
||||
covered work so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you may
|
||||
not convey it at all. For example, if you agree to terms that obligate you
|
||||
to collect a royalty for further conveying from those to whom you convey
|
||||
the Program, the only way you could satisfy both those terms and this
|
||||
License would be to refrain entirely from conveying the Program.
|
||||
|
||||
13. Use with the GNU Affero General Public License.
|
||||
|
||||
Notwithstanding any other provision of this License, you have
|
||||
permission to link or combine any covered work with a work licensed
|
||||
under version 3 of the GNU Affero General Public License into a single
|
||||
combined work, and to convey the resulting work. The terms of this
|
||||
License will continue to apply to the part which is the covered work,
|
||||
but the special requirements of the GNU Affero General Public License,
|
||||
section 13, concerning interaction through a network will apply to the
|
||||
combination as such.
|
||||
|
||||
14. Revised Versions of this License.
|
||||
|
||||
The Free Software Foundation may publish revised and/or new versions of
|
||||
the GNU General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the
|
||||
Program specifies that a certain numbered version of the GNU General
|
||||
Public License "or any later version" applies to it, you have the
|
||||
option of following the terms and conditions either of that numbered
|
||||
version or of any later version published by the Free Software
|
||||
Foundation. If the Program does not specify a version number of the
|
||||
GNU General Public License, you may choose any version ever published
|
||||
by the Free Software Foundation.
|
||||
|
||||
If the Program specifies that a proxy can decide which future
|
||||
versions of the GNU General Public License can be used, that proxy's
|
||||
public statement of acceptance of a version permanently authorizes you
|
||||
to choose that version for the Program.
|
||||
|
||||
Later license versions may give you additional or different
|
||||
permissions. However, no additional obligations are imposed on any
|
||||
author or copyright holder as a result of your choosing to follow a
|
||||
later version.
|
||||
|
||||
15. Disclaimer of Warranty.
|
||||
|
||||
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
|
||||
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
|
||||
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
|
||||
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
|
||||
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
|
||||
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
|
||||
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||
|
||||
16. Limitation of Liability.
|
||||
|
||||
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
|
||||
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
|
||||
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
|
||||
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
|
||||
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
|
||||
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
|
||||
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
|
||||
SUCH DAMAGES.
|
||||
|
||||
17. Interpretation of Sections 15 and 16.
|
||||
|
||||
If the disclaimer of warranty and limitation of liability provided
|
||||
above cannot be given local legal effect according to their terms,
|
||||
reviewing courts shall apply local law that most closely approximates
|
||||
an absolute waiver of all civil liability in connection with the
|
||||
Program, unless a warranty or assumption of liability accompanies a
|
||||
copy of the Program in return for a fee.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest
|
||||
to attach them to the start of each source file to most effectively
|
||||
state the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program does terminal interaction, make it output a short
|
||||
notice like this when it starts in an interactive mode:
|
||||
|
||||
<program> Copyright (C) <year> <name of author>
|
||||
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
|
||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||
parts of the General Public License. Of course, your program's commands
|
||||
might be different; for a GUI interface, you would use an "about box".
|
||||
|
||||
You should also get your employer (if you work as a programmer) or school,
|
||||
if any, to sign a "copyright disclaimer" for the program, if necessary.
|
||||
For more information on this, and how to apply and follow the GNU GPL, see
|
||||
<http://www.gnu.org/licenses/>.
|
||||
|
||||
The GNU General Public License does not permit incorporating your program
|
||||
into proprietary programs. If your program is a subroutine library, you
|
||||
may consider it more useful to permit linking proprietary applications with
|
||||
the library. If this is what you want to do, use the GNU Lesser General
|
||||
Public License instead of this License. But first, please read
|
||||
<http://www.gnu.org/philosophy/why-not-lgpl.html>.
|
||||
@@ -0,0 +1,15 @@
|
||||
v0.1:
|
||||
- Build system
|
||||
- SCTP layer v0.1
|
||||
- S1AP layer v0.1
|
||||
v0.2:
|
||||
- Updated S1AP messages to RELEASE9 v9.8
|
||||
- S1-U layer using nw-gtpv1u
|
||||
v0.3:
|
||||
- Updated S1AP messages to RELEASE10 v10.5
|
||||
- Added NAS interface
|
||||
- Added MME APPlication
|
||||
- Converted sctp_bind to sctp_bindx for multi-homing support
|
||||
- Added configuration file parsing
|
||||
- S6a layer v0.1 using freeDiameter
|
||||
- KeNB key derivy function
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,22 @@
|
||||
if HAVE_DOXYGEN
|
||||
directory = $(top_srcdir)/DOCS/Documentation
|
||||
|
||||
if HAVE_PDFLATEX
|
||||
doc_DATA = $(directory)oaisim_mme.pdf
|
||||
else
|
||||
doc_DATA = $(directory)
|
||||
endif
|
||||
$(directory): doxyfile.stamp
|
||||
|
||||
doxyfile.stamp:
|
||||
$(DOXYGEN) Doxyfile
|
||||
echo Timestamp > doxyfile.stamp
|
||||
|
||||
CLEANFILES = doxyfile.stamp
|
||||
|
||||
all-local: doxyfile.stamp
|
||||
clean-local:
|
||||
rm -f doxyfile.stamp
|
||||
rm -rf $(top_srcdir)/DOCS/Documentation/html
|
||||
rm -rf $(top_srcdir)/DOCS/Documentation/latex
|
||||
endif
|
||||
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
@@ -0,0 +1,774 @@
|
||||
\documentclass[a4paper,oneside]{report}
|
||||
\usepackage{pgfplots}
|
||||
\ifx\HCode\UnDef\else\def\pgfsysdriver{pgfsys-tex4ht.def}\fi
|
||||
\usepackage{verbatim}
|
||||
\usepackage{listings}
|
||||
\usepackage{tikz,graphicx}
|
||||
\usepackage{caption}
|
||||
\usepackage{float}
|
||||
\usepackage{hyperref}
|
||||
\usepackage{subfiles}
|
||||
\usepackage{nomencl}
|
||||
\usepackage{chngcntr}
|
||||
\makenomenclature
|
||||
|
||||
\usepackage{makeidx}
|
||||
\makeindex
|
||||
|
||||
\counterwithout{figure}{chapter}
|
||||
|
||||
\usetikzlibrary{external,calc,trees,positioning,arrows,chains,shapes.geometric,%
|
||||
decorations.pathreplacing,decorations.pathmorphing,shapes,%
|
||||
matrix,fit,shapes.symbols,backgrounds,fit}
|
||||
\captionsetup[figure]{labelformat=simple}
|
||||
|
||||
\renewcommand{\figurename}{Figure}
|
||||
% Returns three nodes: The argument, and the projections of the argument on the left and right borders of the bounding box
|
||||
\newcommand{\extendnode}[1]{
|
||||
(#1)
|
||||
($(current bounding box.north east)!(#1)!(current bounding box.south east)$)
|
||||
($(current bounding box.north west)!(#1)!(current bounding box.south west)$)
|
||||
}
|
||||
|
||||
\usetikzlibrary{calc,trees,positioning,arrows,chains,shapes.geometric,%
|
||||
decorations.pathreplacing,decorations.pathmorphing,shapes,%
|
||||
matrix,shapes.symbols,backgrounds,fit,intersections}
|
||||
|
||||
\title{OAI EPC current development}
|
||||
\author{Sebastien ROUX\\Eurecom\\sebastien.roux@eurecom.fr}
|
||||
|
||||
\definecolor{javared}{rgb}{0.6,0,0} % for strings
|
||||
\definecolor{javagreen}{rgb}{0.25,0.5,0.35} % comments
|
||||
\definecolor{ckeyw}{rgb}{0,0,0.8} % keywords
|
||||
\definecolor{ccomment}{rgb}{0.6,0.6,0.6} % javadoc
|
||||
|
||||
\lstset{
|
||||
language=C,
|
||||
basicstyle=\ttfamily,
|
||||
keywordstyle=\color{ckeyw}\bfseries,
|
||||
stringstyle=\color{javared},
|
||||
commentstyle=\color{ccomment},
|
||||
morecomment=[s][\color{ccomment}]{/**}{*/},
|
||||
numbers=left,
|
||||
numberstyle=\tiny\color{black},
|
||||
stepnumber=1,
|
||||
numbersep=10pt,
|
||||
tabsize=4,
|
||||
showspaces=false,
|
||||
showstringspaces=false,
|
||||
breaklines
|
||||
}
|
||||
|
||||
|
||||
\tikzset{
|
||||
table nodes/.style={
|
||||
rectangle,
|
||||
rounded corners=0.6mm,
|
||||
draw=black,
|
||||
align=center,
|
||||
minimum height=7mm,
|
||||
minimum width=22mm,
|
||||
text depth=0.5ex,
|
||||
text height=2ex,
|
||||
% inner xsep=0pt,
|
||||
outer sep=0pt,
|
||||
},
|
||||
table/.style={
|
||||
matrix of nodes,
|
||||
% row sep=-\pgflinewidth,
|
||||
% column sep=-\pgflinewidth,
|
||||
rectangle,
|
||||
nodes={
|
||||
table nodes
|
||||
},
|
||||
execute at empty cell={\node[draw=none]{};}
|
||||
},
|
||||
cps/.style={
|
||||
draw=black,
|
||||
fill=blue!20,
|
||||
rounded corners=0.6mm,
|
||||
},
|
||||
ups/.style={
|
||||
draw=black,
|
||||
fill=yellow!30,
|
||||
rounded corners=0.6mm,
|
||||
},
|
||||
stdlinux/.style={
|
||||
draw=black,
|
||||
fill=green!10,
|
||||
rounded corners=0.6mm,
|
||||
},
|
||||
rect/.style={
|
||||
rectangle,
|
||||
draw,
|
||||
},
|
||||
schritt/.style={
|
||||
draw,
|
||||
rounded corners,
|
||||
fill=blue!20,
|
||||
inner xsep=2em,
|
||||
},
|
||||
t0/.style={draw,fill=blue!20},
|
||||
t1/.style={draw,fill=blue!40},
|
||||
background/.style={
|
||||
draw,
|
||||
fill=yellow!30,
|
||||
align=center,
|
||||
dashed,
|
||||
},
|
||||
background2/.style={
|
||||
draw,
|
||||
fill=green!15,
|
||||
align=center,
|
||||
},
|
||||
connector/.style={
|
||||
-latex,
|
||||
font=\scriptsize
|
||||
},
|
||||
rectangle connector/.style={
|
||||
connector,
|
||||
to path={(\tikztostart) -| (\tikztotarget) },
|
||||
pos=0.5
|
||||
},
|
||||
rectangle connector/.default=-2cm,
|
||||
straight connector/.style={
|
||||
connector,
|
||||
to path=--(\tikztotarget) \tikztonodes
|
||||
},
|
||||
queue/.style={
|
||||
draw,
|
||||
fill=yellow!30,
|
||||
cylinder,
|
||||
aspect=0.7,
|
||||
minimum height=1cm,
|
||||
minimum width=0.7cm
|
||||
},
|
||||
}
|
||||
\renewcommand{\nomname}{List of Abbreviations}
|
||||
\renewcommand{\thefigure}{\Alph{figure}}
|
||||
|
||||
\begin{document}
|
||||
\maketitle
|
||||
\tableofcontents
|
||||
\printnomenclature[2cm]
|
||||
|
||||
\chapter*{MME and S+P-Gateway} \stepcounter{chapter}
|
||||
\addcontentsline{toc}{chapter}{MME and S+P-Gateway}
|
||||
|
||||
% \nomenclature{MME}{Mobility Management Entity}
|
||||
% \nomenclature{S-GW}{Serving Gateway}
|
||||
% \nomenclature{P-GW}{PDN Gateway}
|
||||
\begin{figure}[H]
|
||||
\begin{center}
|
||||
\begin{tikzpicture}
|
||||
\tikzstyle{every node}=[font=\footnotesize]
|
||||
\matrix (table) [row sep=0.5cm, column sep={3.2cm,between origins}, table,text width=3mm,name=table] {
|
||||
& & &\\
|
||||
& & &\\
|
||||
& & &\\
|
||||
& & &\\
|
||||
& & &\\
|
||||
};
|
||||
\node(MMEAPP)[cps,draw,fit=(table-1-1)(table-1-2),table nodes]{MME Application};
|
||||
\node(SPGW)[cps,draw,fit=(table-1-3)(table-1-4),table nodes]{S+P-GW Application};
|
||||
\node(NAS)[cps,draw,fit=(table-2-2),table nodes]{NAS};
|
||||
\node(S6A)[dashed,cps,draw,fit=(table-3-1),table nodes]{S6a/Diameter};
|
||||
\node(S1AP)[cps,draw,fit=(table-3-2),table nodes]{S1-MME/S1AP};
|
||||
\node(S1U)[ups,draw,fit=(table-3-3),table nodes]{S1-U/GTPU};
|
||||
\node(SGI)[dashed,ups,draw,fit=(table-3-4),table nodes]{SGi};
|
||||
\node(SCTP)[stdlinux,draw,fit=(table-4-1)(table-4-2),table nodes]{SCTP};
|
||||
\node(UDP)[stdlinux,draw,fit=(table-4-3),table nodes]{UDP};
|
||||
\node(IP)[stdlinux,draw,fit=(table-5-1)(table-5-2)(table-5-3)(table-5-4),table nodes]{IP};
|
||||
|
||||
\draw[<->, dashed, draw=red] (MMEAPP) -- node(arrow1)[above, align=center]{S11}(SPGW);
|
||||
\draw[<-,dashed] (S1U) -- (SPGW.south-|S1U);
|
||||
\draw[<-,dashed] (SGI) -- (SPGW.south-|SGI);
|
||||
\draw[-] (S6A) -- (MMEAPP.south-|S6A);
|
||||
\draw[-] (NAS) -- (MMEAPP.south-|NAS);
|
||||
\draw[-] (S1AP) -- (NAS);
|
||||
\draw[-] (S1U) -- (SGI);
|
||||
\draw[-] (S1U) -- (UDP);
|
||||
\draw[-] (S1AP) -- (SCTP.north-|S1AP);
|
||||
\draw[-] (S6A) -- (SCTP.north-|S6A);
|
||||
\draw[-] (SCTP) -- (IP.north-|SCTP);
|
||||
\draw[-] (UDP) -- (IP.north-|UDP);
|
||||
\draw[-] (SGI) -- (IP.north-|SGI);
|
||||
\draw[-] (MMEAPP.south) |- (S1AP.west);
|
||||
|
||||
\draw($(table.north west) + (-2mm,1mm)$) rectangle ($(table.south east) + (2mm,-1mm)$);
|
||||
|
||||
\node[cps, minimum width=5mm,minimum height=5mm,below=of IP.south west,anchor=west](l1){};
|
||||
\node[right=2mm of l1](ct1) {Control Plane};
|
||||
\node[ups,minimum width=5mm,minimum height=5mm,below=0.3cm of l1](l2){};
|
||||
\node[below=0.3cm of ct1, right=2mm of l2](ct2) {User Plane};
|
||||
\node[stdlinux,minimum width=5mm,minimum height=5mm,below=0.3cm of l2](l3){};
|
||||
\node[below=0.3cm of ct2, right=2mm of l3](ct3) {Linux IP Stack};
|
||||
\draw[minimum width=5mm,minimum height=5mm,below=0.3cm of l3,<->,dashed, draw=red]
|
||||
($(l3.south west) - (0,0.55cm)$) -- node(l4){} ($(l3.south east) - (0,0.55cm)$);
|
||||
\node[right=2mm of l4.north east](ct4) {Abstraction link};
|
||||
\draw[minimum width=5mm,minimum height=5mm,below=0.3cm of l4,->,dashed]
|
||||
($(l4.south west) - (0,0.25cm)$) -- node(l5){} ($(l4.south east) - (0,0.25cm)$);
|
||||
\node[right=2mm of l5.north east](ct5) {Control};
|
||||
\node[draw,fit=(ct1)(l1)(ct2)(l2)(ct3)(l3)(ct4)(l4)(ct5)(l5)] {};
|
||||
|
||||
\end{tikzpicture}
|
||||
\caption{MME and S+P-GW architecture} \label{fig:MMEoverall}
|
||||
\end{center}
|
||||
\end{figure}
|
||||
|
||||
Figure \ref{fig:MMEoverall} shows the targeted implementation of Eurecom
|
||||
EPC.
|
||||
|
||||
\chapter*{S1AP layer} \stepcounter{chapter}
|
||||
\addcontentsline{toc}{chapter}{S1AP layer}
|
||||
|
||||
\nomenclature{S1AP}{S1 Application Protocol}S1AP layer relies on
|
||||
\nomenclature{ASN.1}{Abstract Syntax Notation.1}ASN.1 messages
|
||||
description. Generating C code from the specification
|
||||
implies three steps:
|
||||
\begin{enumerate}
|
||||
\item Modify .asn files to match tools limitation.
|
||||
\item Generate \nomenclature{IE}{Informations Elements}IEs with the help of the asn1c free tool.
|
||||
\item Use the provided script which generates \nomenclature{PDU}{Protocol Data Unit}PDU codec\footnote{Encode/Decode}.
|
||||
\end{enumerate}
|
||||
|
||||
\chapter*{Inter-task interface} \stepcounter{chapter}
|
||||
\addcontentsline{toc}{chapter}{Inter-task interface}
|
||||
|
||||
\section{Concurrency}
|
||||
|
||||
Code divided in layers should be able to be executed in parallel to use the full
|
||||
\nomenclature{CPU}{Control Processing Unit}CPUs power. We can achieve better performance
|
||||
by using some mechanisms that runs part of code in parallel on UNIX platforms:
|
||||
\begin{itemize}
|
||||
\item Multi-process: no link between processes, usage of sockets or pipes is mandatory.
|
||||
\item Forks: code is duplicated and data are stored in different spaces.
|
||||
\item Threads: only code is duplicated, data space is shared between processes
|
||||
\end{itemize}
|
||||
Data synchronization is the first issue to think about when using such mechanisms.
|
||||
|
||||
\section{Overall description}
|
||||
|
||||
A single \nomenclature{API}{Application Programming Interface}API
|
||||
(called ITTI\footnote{InTer-Task Interface}) is used to manage messages
|
||||
exchanged between the tasks which are running on separate threads.
|
||||
This will lead in better usage of multi-core environments.
|
||||
\begin{figure}[h]
|
||||
\begin{center}
|
||||
\begin{tikzpicture}
|
||||
\node[](t1) { Task A };
|
||||
\node[below=of t1,yshift=7mm,font=\tiny](s1) { send msg to task };
|
||||
\node[queue,rotate=90,below=of t1.south,anchor=top](c1) {};
|
||||
\node[right=of t1,xshift=15mm](t2) { Task B };
|
||||
\node[below=of t2,yshift=7mm,font=\tiny](r2) { recv msg from task };
|
||||
\node[queue,rotate=90,below=of t2.south,anchor=top](c2) {};
|
||||
\node[dashed,fit=(c1)(t1)(s1),draw](T1){};
|
||||
\node[dashed,fit=(c2)(t2)(r2),draw](T2){};
|
||||
\node[draw](ITTI) at ($(T1)!0.5!(T2) + (0, -2.3)$){ITTI interface};
|
||||
\draw[->] (T1) |- (ITTI);
|
||||
\draw[->] (ITTI.east) -| (c2.bottom);
|
||||
\draw[->] (c2.east) -- (r2);
|
||||
\node[queue,rotate=90,minimum width=5mm,minimum height=7mm,right=of c2,anchor=top,yshift=-15mm](c3) {};
|
||||
\node[dashed,rectangle,minimum width=5mm,minimum height=5mm,draw,below=7mm of c3,anchor=east](c4) {};
|
||||
\node[right=4mm of c3.shape center](x3){Message queue};
|
||||
\node[right=4mm of c4.center](x4){Thread};
|
||||
\node[draw,fit=(c3)(x3)(x4)(c4)](T4){};
|
||||
\end{tikzpicture}
|
||||
\caption{Overall process} \label{fig:Overall process}
|
||||
\end{center}
|
||||
\end{figure}
|
||||
Figure \ref{fig:Overall process} describes the basic fonctionnement of the inter-task interface.
|
||||
A message sent from
|
||||
Task A is en-queued to the message queue belonging to the target task. Note that
|
||||
tasks can send messages to themselves. Another API (See Figure \ref{fig:Broadcasting process}) defines broadcast messaging
|
||||
where any task can send a broadcast message to every other task.
|
||||
\begin{figure}[H]
|
||||
\begin{center}
|
||||
\begin{tikzpicture}
|
||||
\node[](t1) { Task A };
|
||||
\node[below=of t1,yshift=7mm,font=\tiny](s1) { send broadcast msg };
|
||||
\node[queue,rotate=90,below=of t1.south,anchor=top](c1) {};
|
||||
|
||||
\node[right=of t1,xshift=35mm](t2) { Task B };
|
||||
\node[below=of t2,yshift=7mm,font=\tiny](r2) { recv msg from task };
|
||||
\node[queue,rotate=90,below=of t2.south,anchor=top](c2) {};
|
||||
|
||||
\node[right=of t2,xshift=15mm](tn) { Task N };
|
||||
\node[below=of tn,yshift=7mm,font=\tiny](rn) { recv msg from task };
|
||||
\node[queue,rotate=90,below=of tn.south,anchor=top](cn) {};
|
||||
\node[dashed,fit=(c1)(t1)(s1),draw](T1){};
|
||||
\node[dashed,fit=(c2)(t2)(r2),draw](T2){};
|
||||
\node[dashed,fit=(cn)(tn)(rn),draw](TN){};
|
||||
|
||||
\node[](ITTI) at ($(T2)!0.5!(TN)$){...};
|
||||
\node[draw](ITTI) at ($(T1)!0.5!(T2) + (0, -2.3)$){ITTI interface};
|
||||
\draw[->] (T1) |- (ITTI);
|
||||
\draw[->] (ITTI.east) -| (c2.bottom);
|
||||
\draw[->] (ITTI.east) -| (cn.bottom);
|
||||
\draw[->] (c2.east) -- (r2);
|
||||
\draw[->] (cn.east) -- (rn);
|
||||
\node[queue,rotate=90,minimum width=5mm,minimum height=7mm,below=23mm of T1](c3) {};
|
||||
\node[dashed,rectangle,minimum width=5mm,minimum height=5mm,draw,below=7mm of c3,anchor=east](c4) {};
|
||||
\node[right=4mm of c3.shape center](x3){Message queue};
|
||||
\node[right=4mm of c4.center](x4){Thread};
|
||||
\node[draw,fit=(c3)(x3)(x4)(c4)](T4){};
|
||||
\end{tikzpicture}
|
||||
\caption{Broadcasting process} \label{fig:Broadcasting process}
|
||||
\end{center}
|
||||
\end{figure}
|
||||
Once a task received a new message and if the task is in sleep mode (i.e. not handling
|
||||
any message), the task is waken up and the message is de-queued. We can imagine a limit
|
||||
in number of parallel tasks, for example N+1 CPU's. Architectures using hyper-threading
|
||||
mechanism can have this value extended to 2 x CPU's.
|
||||
Every task is running in a separated pthread, awaiting for new messages to handle.
|
||||
|
||||
\section{Signals from kernel}
|
||||
|
||||
Handling of signals from kernel is the more critical part as a signal can be raised
|
||||
at any moment and will interrupt one of the running thread. Used signals should be restricted
|
||||
to a single task that will handle them (using the POSIX sigmask function) . Moreover, it isn't
|
||||
thread-safe to use mutexes inside a signal handler, a synchronization flag should be used to
|
||||
notify the signal handler task. This task will then send the appropriate message
|
||||
to the right task. For example, handling of signals can be done in the main thread or by a background task
|
||||
scheduled periodically.
|
||||
To overcome these issues, sigtimedwait and sigwaitinfo API functions can be used
|
||||
to wait for a signal to happen. Signals will be received in the thread context, as far as
|
||||
other threads block these signals.
|
||||
|
||||
\section{Priority handling}
|
||||
|
||||
Usage of message prioritization enables tasks to send critical messages with a faster
|
||||
delivery time regarding other messages en-queued for the target task.
|
||||
For now only seven priority levels can be applied when defining tasks:
|
||||
\begin{itemize}
|
||||
\item TASK\_PRIORITY\_MAX
|
||||
\item TASK\_PRIORITY\_MAX\_LEAST
|
||||
\item TASK\_PRIORITY\_MED\_PLUS
|
||||
\item TASK\_PRIORITY\_MED
|
||||
\item TASK\_PRIORITY\_MED\_LEAST
|
||||
\item TASK\_PRIORITY\_MIN\_PLUS
|
||||
\item TASK\_PRIORITY\_MIN
|
||||
\end{itemize}
|
||||
For now message priority does not involve any suitable scheduler: every time a message is de-queued,
|
||||
message priority of other messages is incremented by one.
|
||||
|
||||
\section{Message scheduling}
|
||||
Currently, there is no software limit on the maximum number of threads executed in parallel.
|
||||
When a task sends a message, it is en-queued in the right message queue, belonging to
|
||||
the target task. The queue is a double-linked list. A mutex prevents other tasks
|
||||
from modifying this queue while a task is en-queueing or removing a message.
|
||||
|
||||
\section{Message definition}
|
||||
Messages are defined using a single macro that adds the message to the ids enumeration
|
||||
and maps data of the message to the union of messages.
|
||||
\begin{lstlisting}
|
||||
MESSAGE_DEF(S1AP_SCTP_NEW_MESSAGE_IND, TASK_PRIORITY_MED, S1apSctpNewMessageInd s1apSctpNewMessageInd)
|
||||
\end{lstlisting}
|
||||
and the associated data:
|
||||
\begin{lstlisting}
|
||||
typedef struct {
|
||||
uint8_t *buffer; ///< SCTP buffer
|
||||
uint32_t bufLen; ///< SCTP buffer length
|
||||
int32_t assocId; ///< SCTP physical association ID
|
||||
uint8_t stream; ///< Stream number on which data had been received
|
||||
uint16_t instreams; ///< Number of input streams for the SCTP connection between peers
|
||||
uint16_t outstreams; ///< Number of output streams for the SCTP connection between peers
|
||||
} S1apSctpNewMessageInd;
|
||||
\end{lstlisting}
|
||||
\section{Task message handling}
|
||||
\begin{lstlisting}
|
||||
void* s1ap_mme_thread(void *args) {
|
||||
while(1) {
|
||||
/* Trying to fetch a message from the message queue.
|
||||
* If the queue is empty, this function will block till a
|
||||
* message is sent to the task.
|
||||
*/
|
||||
receive_msg(TASK_S1AP, &receivedMessage);
|
||||
assert(receivedMessage != NULL);
|
||||
switch(receivedMessage->messageId) {
|
||||
case S1AP_SCTP_NEW_MESSAGE_IND:
|
||||
{
|
||||
//Some processing
|
||||
} break;
|
||||
default:
|
||||
{
|
||||
S1AP_DEBUG("Unkwnon message ID %d\n", receivedMessage->messageId);
|
||||
} break;
|
||||
}
|
||||
free(receivedMessage);
|
||||
receivedMessage = NULL;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
\end{lstlisting}
|
||||
\section{Messages logging}
|
||||
\begin{figure}[H]
|
||||
\begin{center}
|
||||
\begin{tikzpicture}
|
||||
\node[](p1) { Process };
|
||||
\node[below=5mm of p1](i1) { ITTI };
|
||||
\node[queue,right=of i1,rotate=90,anchor=base](q1) {};
|
||||
\node[draw,fit=(i1)(q1)](s1) { };
|
||||
\node[fit=(p1)(i1)(q1)(s1),draw](T1){};
|
||||
\node[queue,fill=red!30,right=of s1.east,yshift=-5mm](c1) { TCP socket };
|
||||
\node[right=of c1](r1){ Remote host n };
|
||||
\node[fit=(r1),draw](R2){};
|
||||
\node[queue,fill=red!30,right=of s1.east,yshift=5mm](c2) { TCP socket };
|
||||
\node[right=of c2](r1){ Remote host 1 };
|
||||
\node[fit=(r1),draw](R1){};
|
||||
\draw[-] (q1.base) -- ++ (1,0) -| ++ (0,.6) -- (c2.west);
|
||||
\draw[-] (c2) -- (R1);
|
||||
\draw[-] (q1.base) -- ++ (1,0) -| ++ (0,-.4) -- (c1.west);
|
||||
\draw[-] (c1) -- (R2);
|
||||
\end{tikzpicture}
|
||||
\caption{Remote debugging} \label{fig:Remote debugging}
|
||||
\end{center}
|
||||
\end{figure}
|
||||
Logging of inter-tasks messages can be setup using an external tool that will be
|
||||
connected to the ITTI. Based on an array of dumped messages, they are serialized
|
||||
to produce an array of byte sent over a socket. A remote tool can then decode
|
||||
messages and display fields, message number, time.\\
|
||||
Additionaly, logs from standard output can be printed over the debug tool.
|
||||
Multi-user debugging on only one running process can be achieved using this interface.
|
||||
Messages to dump should be queued for a pure asynchronous communication between the
|
||||
dump task and the remote hosts.
|
||||
Another interesting feature could be to send a message to a task from an host,
|
||||
allowing run-time re-configuration.
|
||||
The C pre-processor can be used to generate messages definition (using
|
||||
\nomenclature{XML}{Extensible Markup Language}XML templates
|
||||
for example).\\
|
||||
\section{Limitations}
|
||||
Data pointers belonging to one task should never be passed to another task.
|
||||
The presented mechanism does not prevent a task from being locked. In such a case,
|
||||
the blocked task will no more handle messages incoming from other tasks.
|
||||
|
||||
\section{Benefits}
|
||||
\begin{itemize}
|
||||
\item Only a single entry point between all tasks (easy inter-task communication tracking and debugging).
|
||||
\item Usage of message queues enables parallelization of layers.
|
||||
\item Message prioritization and scheduling.
|
||||
\item Protection of data between threads is done by the API at an higher level.
|
||||
\end{itemize}
|
||||
|
||||
\section{To do}
|
||||
\begin{itemize}
|
||||
\item Implement a priority based scheduler. Currently the queue of messages works as a FIFO.
|
||||
\item Limit the number of tasks thread that can be run in parallel
|
||||
\end{itemize}
|
||||
|
||||
\chapter*{Signal API} \stepcounter{chapter}
|
||||
\addcontentsline{toc}{chapter}{Signal API}
|
||||
|
||||
On LINUX platforms, processes will receive signals comming from Kernel.
|
||||
A single blocking entry point handles all used signals that are requested by the
|
||||
MME. The main application thread is reserved to signal handling as this thread will
|
||||
be blocked till a new signal is ready for handling.\\
|
||||
Using this method prevents threads from being interrupted by signals handler which
|
||||
can interrupt the thread at any time and as a consequence create some misbehaving
|
||||
in threads contexts.
|
||||
Following is a sample list of signals handled:
|
||||
\begin{itemize}
|
||||
\item SIGABRT This is signal is sent to the process when abort() function is called
|
||||
within the process and kill the process. Process can for example display the stack
|
||||
once this signal is received.
|
||||
\item SIGRTMIN This signal is used by the timer API and is raised everytime a
|
||||
timer has expired.
|
||||
\end{itemize}
|
||||
Till now there is no way for tasks to request a new signal.
|
||||
|
||||
\chapter*{Timer API} \stepcounter{chapter}
|
||||
\addcontentsline{toc}{chapter}{Timer API}
|
||||
|
||||
Timer API doesn't consist of a task (i.e. tasks cannot send messages to it).
|
||||
Handling of UNIX signal associated to the timers is a Real-time signal with an id (SIGRTMIN)
|
||||
depending on the platform. Management of this signal is done by the signal interface
|
||||
and developpers should not care about handling timer signals incoming from Kernel.
|
||||
Once a timer has expired the task which has requested it will receive the TIMER\_HAS\_EXPIRED
|
||||
signal.
|
||||
Note that timer\_id is of type long and thus its size is platform specific.
|
||||
|
||||
\section{Timer types}
|
||||
|
||||
\begin{itemize}
|
||||
\item TIMER\_ONE\_SHOT After expiry and its associated signal, the timer is removed.
|
||||
\item TIMER\_PERIODIC The timer is automatically reloaded on each expiry while the task
|
||||
which has setup this timer doesn't cancel it.
|
||||
\end{itemize}
|
||||
|
||||
\section{Requesting a new signal}
|
||||
Any task can request a new signal by invoking the following API:
|
||||
\begin{lstlisting}
|
||||
int timer_setup(
|
||||
uint32_t interval_sec,
|
||||
uint32_t interval_us,
|
||||
task_id_t task_id,
|
||||
timer_type_t type,
|
||||
long *timer_id);
|
||||
\end{lstlisting}
|
||||
|
||||
Note that timer id is a unique identifier to distinguish timers.
|
||||
|
||||
\section{Disable and remove a timer}
|
||||
|
||||
Disable and remove the timer referenced by timer\_id.
|
||||
\begin{lstlisting}
|
||||
int timer_remove(long timer_id);
|
||||
\end{lstlisting}
|
||||
|
||||
\section{Timer signal expiry}
|
||||
|
||||
Once the signal dispatcher receives the SIGRTMIN signal, a new signal is sent
|
||||
to the task which has requested the timer. Contrary to signal request, timer
|
||||
expiry notification is achieved using the intertask mechanism.
|
||||
The signal data associated to this event follows:
|
||||
\begin{lstlisting}
|
||||
typedef struct {
|
||||
long timer_id;
|
||||
} timer_has_expired_t;
|
||||
\end{lstlisting}
|
||||
|
||||
\chapter*{Compiling core EPC} \stepcounter{chapter}
|
||||
\addcontentsline{toc}{chapter}{Compiling core EPC}
|
||||
|
||||
The core EPC software has been tested on Ubuntu 12.04LTS x86 and ia64.
|
||||
Before compiling the core EPC, some packages should be installed on the platform.
|
||||
|
||||
\section{Dependencies}
|
||||
|
||||
\begin{itemize}
|
||||
\item libsctp-dev
|
||||
\item libpthread-dev
|
||||
\item automake and autoconf
|
||||
\item libtoolize
|
||||
\item gcc, g++, make
|
||||
\item flex and bison
|
||||
\item openssl-dev
|
||||
\item asn1c (see section \ref{sec:asn1c})
|
||||
\item libnettle (see section \ref{sec:libnettle})
|
||||
\item freediameter (see section \ref{sec:freediameter}) and gnutls 3.1.0
|
||||
(see section \ref{sec:gnutls})
|
||||
\end{itemize}
|
||||
Command-line to install the required packages:
|
||||
\begin{lstlisting}
|
||||
sudo apt-get install cmake make gcc flex bison \
|
||||
libsctp1 libsctp-dev libidn2-0-dev libidn11-dev \
|
||||
libmysqlclient-dev libxml2-dev swig python-dev \
|
||||
cmake-curses-gui valgrind guile-2.0-dev \
|
||||
libgmp-dev libgcrypt11-dev gdb unzip \
|
||||
libtasn1-3-dev g++ autoconf automake \
|
||||
openssl-dev -y
|
||||
\end{lstlisting}
|
||||
|
||||
\subsection{ASN1c}
|
||||
\label{sec:asn1c}
|
||||
|
||||
\subsection{libnettle}
|
||||
\label{sec:libnettle}
|
||||
|
||||
The nettle library is used by freediameter for certificate encryption and by core
|
||||
EPC for key derivation.
|
||||
\begin{lstlisting}
|
||||
wget ftp://ftp.lysator.liu.se/pub/security/lsh/nettle-2.5.tar.gz
|
||||
gunzip nettle-2.5.tar.gz
|
||||
tar -xvf nettle-2.5.tar
|
||||
cd nettle-2.5/
|
||||
./configure --disable-openssl --enable-shared
|
||||
make
|
||||
make check
|
||||
sudo make install
|
||||
\end{lstlisting}
|
||||
The commands provided above will download the required packages sources, configure
|
||||
and install them on the system.
|
||||
Note that any packages which is not in the Ubuntu repository is installed by default
|
||||
in /usr/local instead of /usr.
|
||||
This behaviour can be overriden at configuration time by providing --prefix=/usr to
|
||||
the configuration script (configure).
|
||||
|
||||
\subsection{gnutls}
|
||||
\label{sec:gnutls}
|
||||
|
||||
The GNUTls library is only used by freediameter for certificate handling and as a
|
||||
consequence should be installed before trying to compile the freediameter library.
|
||||
\begin{lstlisting}
|
||||
wget ftp://ftp.gnutls.org/gcrypt/gnutls/v3.1/gnutls-3.1.0.tar.xz
|
||||
tar -xvf gnutls-3.1.0.tar.xz
|
||||
cd gnutls-3.1.0/
|
||||
./configure LDFLAGS='-L/usr/local/lib'
|
||||
make
|
||||
sudo make install
|
||||
\end{lstlisting}
|
||||
Note: when dependencies are installed in /usr/local instead of /usr,
|
||||
LDFLAGS has to be overriden with the path to libraries when configuring the package:
|
||||
LDFLAGS='-L/usr/local/lib'.
|
||||
|
||||
\subsection{freediameter}
|
||||
\label{sec:freediameter}
|
||||
Freediameter is the package that provides diameter capabilities to the MME/HSS.
|
||||
On top of this stack, S6A avp dictionnary is used to enable a compliant S6A interface.
|
||||
\begin{lstlisting}
|
||||
wget http://www.freediameter.net/hg/freeDiameter/archive/1.1.5.tar.gz
|
||||
tar -xvf 1.1.5.tar.gz
|
||||
cd freeDiameter-1.1.5
|
||||
patch -p1 < ../../freediameter-1.1.5.patch
|
||||
mkdir build
|
||||
cd build
|
||||
cmake ../
|
||||
make
|
||||
make test
|
||||
sudo make install
|
||||
\end{lstlisting}
|
||||
If you want ot install this package in /usr instead of /usr/local,\\
|
||||
-DCMAKE\_INSTALL\_PREFIX:PATH=/usr should be passed to cmake at configuration.
|
||||
|
||||
\chapter*{System configuration} \stepcounter{chapter}
|
||||
\addcontentsline{toc}{chapter}{System configuration}
|
||||
|
||||
Currently there is two ways to configure the system:
|
||||
\begin{itemize}
|
||||
\item Compilation configuration
|
||||
\item Boot-up configuration
|
||||
\end{itemize}
|
||||
In the first type of configuration, the single system configuration structure
|
||||
is filled in with default values that can be found in the mme\_default\_values.h
|
||||
header file.\\
|
||||
When Boot-up configuration is used, a configuration file is passed to the process
|
||||
by using the either -c filename.conf or --conf=filename.conf. This file is then parsed
|
||||
by the bison interpreter and values are replaced in the global system configuration
|
||||
structure.
|
||||
|
||||
\section{Global MME parameters}
|
||||
|
||||
\subsection{Relative MME capacity}
|
||||
Even though this parameter is not used by the MME for controlling the MME load
|
||||
balancing within a pool (at least for now), the parameter has to be to forwarded
|
||||
to the eNBs during association procedure.
|
||||
This parameter is encoded on 8bits, acceptable values going from 0 to 255.
|
||||
(Default value = 15)
|
||||
\begin{lstlisting}
|
||||
RELATIVE_CAPACITY = 10;
|
||||
\end{lstlisting}
|
||||
|
||||
\subsection{Maximum number of UE}
|
||||
\label{sec:Maximum number of UE}
|
||||
This limit is present here only for debug purposes and is used to restrict
|
||||
the number of served UE the MME can handle. In real network another mechanism
|
||||
will trigger an MME overload for certain eNBs and will restrict certain types of
|
||||
traffic. Such a mechanism would imply the Relative MME capacity.
|
||||
\begin{lstlisting}
|
||||
MAXUE = 100;
|
||||
\end{lstlisting}
|
||||
|
||||
\subsection{Maximum number of eNB}
|
||||
Refer to \ref{sec:Maximum number of UE}.
|
||||
\begin{lstlisting}
|
||||
MAXENB = 10;
|
||||
\end{lstlisting}
|
||||
|
||||
\subsection{Tracking Area Identity}
|
||||
\nomenclature{TAI}{Tracking Area Identity}TAI is the concatenation of
|
||||
\nomenclature{MCC}{Mobile Country Code}MCC, \nomenclature{MNC}{Mobile Network Code}MNC and
|
||||
\nomenclature{TAC}{Tracking Area Code}TAC.
|
||||
The TAC uniquely identifies a PLMN within a Cell Id.
|
||||
\begin{lstlisting}
|
||||
PLMN = mcc.mnc:tac;
|
||||
\end{lstlisting}
|
||||
Multiple values can be given using a comma separator. Example:
|
||||
\begin{lstlisting}
|
||||
PLMN = 208.38:0,209.130:4,208.35:8;
|
||||
\end{lstlisting}
|
||||
|
||||
\subsection{MME Code}
|
||||
A list of a maximum of 256 values can be provided.
|
||||
\nomenclature{MMEC}{MME Code}MME Code is encoded on 8 bits,
|
||||
so acceptable range is: 0 to 255.
|
||||
Example:
|
||||
\begin{lstlisting}
|
||||
MME_CODE = 30,56,1,8;
|
||||
\end{lstlisting}
|
||||
|
||||
\subsection{MME Group Id}
|
||||
A list of a maximum of 65356 values can be provided.
|
||||
\nomenclature{MMEGID}{MME Group Id}MME Group Id is encoded on 16 bits,
|
||||
so acceptable range is: 0 to 65535.
|
||||
Example:
|
||||
\begin{lstlisting}
|
||||
MME_GID = 3,4,5,30,8,9,50021;
|
||||
\end{lstlisting}
|
||||
|
||||
\section{Intertask parameters}
|
||||
\subsection{Queue size per task}
|
||||
To restrict the number of messages in queues or to detect a possible MME overload,
|
||||
an upper bound for the queue size can be defined like this:
|
||||
\begin{lstlisting}
|
||||
ITTI_QUEUE_SIZE = 2000000;
|
||||
\end{lstlisting}
|
||||
This parameter is expressed in bytes. Note that all messages exchanged by tasks
|
||||
have the same size.
|
||||
|
||||
\section{SCTP parameters}
|
||||
\subsection{IN/OUT streams number}
|
||||
The number of input/output streams can be configured to limit the number of streams
|
||||
used for UE-associated signalling. Note that stream with id = 0 is reserved for
|
||||
non-UE associated signalling. At least two streams should be used by the MME.
|
||||
(Default value = 64/64 streams)
|
||||
\begin{lstlisting}
|
||||
SCTP_INSTREAMS = 32;
|
||||
SCTP_OUTSTREAMS = 32;
|
||||
\end{lstlisting}
|
||||
|
||||
\section{S1AP parameters}
|
||||
\subsection{Outcome timer}
|
||||
Once an outcome is sent from MME to eNB, the MME locally starts a timer to abort
|
||||
the procedure and release UE contexts if the expected answer to this outcome is not
|
||||
received at the expiry of this timer.\\
|
||||
This timer is expressed in seconds. (Default value = 5 seconds)
|
||||
\begin{lstlisting}
|
||||
S1AP_OUTCOME_TIMER = 10;
|
||||
\end{lstlisting}
|
||||
|
||||
\section{Network interfaces parameters}
|
||||
|
||||
Three paramters can be tuned in the configuration file:
|
||||
\begin{itemize}
|
||||
\item Interface Name: The related interface will be bind to this interface name
|
||||
\item IP address: Currently only IPv4 address is allowed
|
||||
\item IP netwmask: Netmask for the LAN
|
||||
\end{itemize}
|
||||
These three paramters can be setup for five different interfaces used:
|
||||
\begin{itemize}
|
||||
\item SGW interface for S11
|
||||
\item SGW interface for S1U/S12/S4 in user plane
|
||||
\item SGW interface for S5/S8 in user plane
|
||||
\item PGW interface for S5/S8
|
||||
\item PGW interface for SGi
|
||||
\item MME interface for S1-MME in control plane
|
||||
\end{itemize}
|
||||
Example of configuration:
|
||||
\begin{lstlisting}
|
||||
# ------- Interfaces definitions
|
||||
SGW_INTERFACE_NAME_FOR_S11 = "s11sgw";
|
||||
SGW_IP_ADDRESS_FOR_S11 = "192.168.10.1";
|
||||
SGW_IP_NETMASK_FOR_S11 = 24;
|
||||
|
||||
SGW_INTERFACE_NAME_FOR_S1U_S12_S4_UP = "upsgw0";
|
||||
SGW_IP_ADDRESS_FOR_S1U_S12_S4_UP = "192.168.1.1";
|
||||
SGW_IP_NETMASK_FOR_S1U_S12_S4_UP = 24;
|
||||
|
||||
SGW_INTERFACE_NAME_FOR_S5_S8_UP = "upsgw1";
|
||||
SGW_IP_ADDRESS_FOR_S5_S8_UP = "192.168.5.2";
|
||||
SGW_IP_NETMASK_FOR_S5_S8_UP = 24;
|
||||
|
||||
PGW_INTERFACE_NAME_FOR_S5_S8 = "uppgw0";
|
||||
PGW_IP_ADDRESS_FOR_S5_S8 = "192.168.5.1";
|
||||
PGW_IP_NETMASK_FOR_S5_S8 = 24;
|
||||
|
||||
PGW_INTERFACE_NAME_FOR_SGI = "eth1";
|
||||
PGW_IP_ADDR_FOR_SGI = "192.168.12.30";
|
||||
PGW_IP_NETMASK_FOR_SGI = 24;
|
||||
|
||||
MME_INTERFACE_NAME_FOR_S1_MME = "cpmme0";
|
||||
MME_IP_ADDRESS_FOR_S1_MME = "192.168.11.1";
|
||||
MME_IP_NETMASK_FOR_S1_MME = 24;
|
||||
\end{lstlisting}
|
||||
|
||||
\end{document}
|
||||
@@ -0,0 +1,9 @@
|
||||
MYFILE=EPC
|
||||
|
||||
all:
|
||||
pdflatex $(MYFILE).tex
|
||||
pdflatex $(MYFILE).tex
|
||||
makeindex $(MYFILE).nlo -s nomencl.ist -o $(MYFILE).nls
|
||||
pdflatex $(MYFILE).tex
|
||||
|
||||
.PHONY: all
|
||||
@@ -0,0 +1 @@
|
||||
SUBDIRS = DOXYGEN
|
||||
@@ -0,0 +1,31 @@
|
||||
AM_CFLAGS = @ADD_CFLAGS@ \
|
||||
-I$(top_srcdir)/COMMON \
|
||||
-I$(top_srcdir)/INTERTASK_INTERFACE \
|
||||
-I$(top_srcdir)/GTPV1-U/nw-gtpv1u/include \
|
||||
-I$(top_srcdir)/GTPV1-U/nw-gtpv1u/shared \
|
||||
-I$(top_srcdir)/UTILS \
|
||||
-I$(top_srcdir)/UTILS/HASHTABLE \
|
||||
-I$(top_srcdir)/UTILS/TIMER
|
||||
|
||||
noinst_LTLIBRARIES = libgtpv1u.la
|
||||
|
||||
libgtpv1u_la_LDFLAGS = -all-static
|
||||
|
||||
libgtpv1u_la_SOURCES = \
|
||||
gtpv1u_task.c gtpv1u.h \
|
||||
gtpv1u_teid_pool.c \
|
||||
nw-gtpv1u/shared/NwTypes.h \
|
||||
nw-gtpv1u/shared/NwUtils.h \
|
||||
nw-gtpv1u/shared/NwGtpv1uError.h \
|
||||
nw-gtpv1u/shared/NwLog.h \
|
||||
nw-gtpv1u/shared/NwGtpv1uIe.h \
|
||||
nw-gtpv1u/shared/NwGtpv1uMsg.h \
|
||||
nw-gtpv1u/shared/NwGtpv1u.h \
|
||||
nw-gtpv1u/include/NwGtpv1uPrivate.h \
|
||||
nw-gtpv1u/include/NwGtpv1uLog.h \
|
||||
nw-gtpv1u/include/NwGtpv1uTrxn.h \
|
||||
nw-gtpv1u/include/NwGtpv1uTunnelEndPoint.h \
|
||||
nw-gtpv1u/src/NwGtpv1uTunnelEndPoint.c \
|
||||
nw-gtpv1u/src/NwGtpv1uTrxn.c \
|
||||
nw-gtpv1u/src/NwGtpv1uMsg.c \
|
||||
nw-gtpv1u/src/NwGtpv1u.c
|
||||
@@ -0,0 +1,49 @@
|
||||
all: libgtpv1u.a
|
||||
|
||||
libgtpv1u_OBJECTS = \
|
||||
nw-gtpv1u/src/NwGtpv1uTunnelEndPoint.o \
|
||||
nw-gtpv1u/src/NwGtpv1uTrxn.o \
|
||||
nw-gtpv1u/src/NwGtpv1uMsg.o \
|
||||
nw-gtpv1u/src/NwGtpv1u.o \
|
||||
gtpv1u_eNB.o \
|
||||
gtpv1u_teid_pool.o \
|
||||
|
||||
|
||||
CFLAGS = \
|
||||
-I./nw-gtpv1u/shared \
|
||||
-I./nw-gtpv1u/include \
|
||||
-I../UTILS \
|
||||
-I../UTILS/HASHTABLE \
|
||||
-I../UDP \
|
||||
-I$(OPENAIR2_DIR) \
|
||||
-DUSER_MODE \
|
||||
-DENABLE_USE_MME \
|
||||
-DUSER_MODE \
|
||||
-DNB_ANTENNAS_RX=2 -DNB_ANTENNAS_TXRX=2 -DNB_ANTENNAS_TX=2 \
|
||||
-g \
|
||||
-O2 \
|
||||
-Wall \
|
||||
-Werror=implicit-function-declaration
|
||||
|
||||
-include .deps/*.d
|
||||
-include .deps/nw-gtpv1u/src/*.d
|
||||
|
||||
$(libgtpv1u_OBJECTS): %.o : %.c
|
||||
@echo "Compiling $<"
|
||||
@$(CC) -c $(CFLAGS) -o $@ $<
|
||||
@if ! test -d ".deps/nw-gtpv1u/src/" ; then mkdir -p .deps/nw-gtpv1u/src/; fi
|
||||
@$(CC) -MM $(CFLAGS) $*.c > .deps/$*.d
|
||||
@mv -f .deps/$*.d .deps/$*.d.tmp
|
||||
@sed -e 's|.*:|$*.o:|' < .deps/$*.d.tmp > .deps/$*.d
|
||||
@sed -e 's/.*://' -e 's/\\$$//' < .deps/$*.d.tmp | fmt -1 | \
|
||||
sed -e 's/^ *//' -e 's/$$/:/' >> .deps/$*.d
|
||||
@rm -f .deps/$*.d.tmp
|
||||
|
||||
libgtpv1u.a: $(libgtpv1u_OBJECTS)
|
||||
@echo Creating GTP-U archive
|
||||
@$(AR) rcvs $@ $(libgtpv1u_OBJECTS)
|
||||
|
||||
clean:
|
||||
rm -f libgtpv1u.a
|
||||
rm -rf .deps/
|
||||
rm -f $(libgtpv1u_OBJECTS)
|
||||
@@ -0,0 +1,51 @@
|
||||
/*******************************************************************************
|
||||
|
||||
Eurecom OpenAirInterface
|
||||
Copyright(c) 1999 - 2012 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.fr/openairinterface
|
||||
Address : EURECOM, Campus SophiaTech, 450 Route des Chappes
|
||||
06410 Biot FRANCE
|
||||
|
||||
*******************************************************************************/
|
||||
|
||||
#ifndef GTPV1_U_H_
|
||||
#define GTPV1_U_H_
|
||||
|
||||
/* When gtpv1u is compiled for eNB use MACRO from UTILS/log.h,
|
||||
* otherwise use standard fprintf as logger.
|
||||
*/
|
||||
#if defined(ENB_MODE)
|
||||
# define GTPU_DEBUG(x, args...) LOG_D(GTPU, x, ##args)
|
||||
# define GTPU_INFO(x, args...) LOG_I(GTPU, x, ##args)
|
||||
# define GTPU_WARN(x, args...) LOG_W(GTPU, x, ##args)
|
||||
# define GTPU_ERROR(x, args...) LOG_E(GTPU, x, ##args)
|
||||
#else
|
||||
# define GTPU_DEBUG(x, args...) fprintf(stdout, "[GTPU][D]"x, ##args)
|
||||
# define GTPU_INFO(x, args...) fprintf(stdout, "[GTPU][I]"x, ##args)
|
||||
# define GTPU_WARN(x, args...) fprintf(stdout, "[GTPU][W]"x, ##args)
|
||||
# define GTPU_ERROR(x, args...) fprintf(stderr, "[GTPU][E]"x, ##args)
|
||||
#endif
|
||||
|
||||
uint32_t gtpv1u_new_teid(void);
|
||||
|
||||
#endif /* GTPV1_U_H_ */
|
||||
@@ -0,0 +1,520 @@
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
|
||||
|
||||
#include "NwGtpv1u.h"
|
||||
#include "NwGtpv1uMsg.h"
|
||||
#include "NwLog.h"
|
||||
|
||||
#include "log.h"
|
||||
|
||||
#include "gtpv1u_eNB_defs.h"
|
||||
|
||||
#include "udp_primitives_client.h"
|
||||
#include "UTIL/LOG/log.h"
|
||||
#include "COMMON/platform_types.h"
|
||||
|
||||
#ifdef GTPU_IN_KERNEL
|
||||
#include <netinet/in.h>
|
||||
#include <net/if.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#endif
|
||||
|
||||
|
||||
extern unsigned char pdcp_data_req (module_id_t module_id, u32_t frame, u8_t eNB_flag, rb_id_t rab_id, u32 muiP, u32 confirmP, sdu_size_t sdu_buffer_size, unsigned char* sdu_buffer, u8 is_data_pdu);
|
||||
|
||||
|
||||
inline NwGtpv1uRcT gtpv1u_eNB_log_request(NwGtpv1uLogMgrHandleT hLogMgr,
|
||||
NwU32T logLevel,
|
||||
NwCharT *file,
|
||||
NwU32T line,
|
||||
NwCharT *logStr)
|
||||
{
|
||||
logIt(GTPU, logLevel, "%s\n", logStr);
|
||||
return NW_GTPV1U_OK;
|
||||
}
|
||||
|
||||
/* Callback called when a gtpv1u message arrived on UDP interface */
|
||||
NwGtpv1uRcT gtpv1u_process_stack_req(
|
||||
NwGtpv1uUlpHandleT hUlp,
|
||||
NwGtpv1uUlpApiT *pUlpApi)
|
||||
{
|
||||
switch(pUlpApi->apiType) {
|
||||
/* Here there are two type of messages handled:
|
||||
* - T-PDU
|
||||
* - END-MARKER
|
||||
*/
|
||||
case NW_GTPV1U_ULP_API_RECV_TPDU: {
|
||||
uint8_t buffer[4096];
|
||||
uint32_t buffer_len;
|
||||
|
||||
/* Nw-gptv1u stack has processed a PDU. we can schedule it to PDCP
|
||||
* for transmission.
|
||||
*/
|
||||
if (NW_GTPV1U_OK != nwGtpv1uMsgGetTpdu(pUlpApi->apiInfo.recvMsgInfo.hMsg,
|
||||
buffer, &buffer_len)) {
|
||||
GTPU_ERROR("Error while retrieving T-PDU");
|
||||
}
|
||||
GTPU_DEBUG("Received T-PDU from gtpv1u stack %u with size %d",
|
||||
pUlpApi->apiInfo.recvMsgInfo.teid, buffer_len);
|
||||
|
||||
pdcp_data_req(0, // module_id,
|
||||
0, // frame
|
||||
1, // enb flag
|
||||
5, // rb id
|
||||
0, // mui
|
||||
0, // confirm
|
||||
buffer_len,
|
||||
buffer,
|
||||
1);
|
||||
}
|
||||
break;
|
||||
default: {
|
||||
GTPU_ERROR("Received undefined UlpApi (%02x) from gtpv1u stack!\n",
|
||||
pUlpApi->apiType);
|
||||
}
|
||||
}
|
||||
return NW_GTPV1U_OK;
|
||||
}
|
||||
|
||||
NwGtpv1uRcT gtpv1u_eNB_udp_req(NwGtpv1uUdpHandleT udpHandle,
|
||||
NwU8T *dataBuf,
|
||||
NwU32T dataSize,
|
||||
NwU32T peerIpAddr,
|
||||
NwU16T peerPort)
|
||||
{
|
||||
udp_data_t *udp_data_p;
|
||||
|
||||
if (udpHandle == 0) {
|
||||
return NW_GTPV1U_FAILURE;
|
||||
}
|
||||
|
||||
udp_data_p = (udp_data_t *)udpHandle;
|
||||
|
||||
LOG_D(GTPU, "New udp req triggered with sd %d, data size %u\n",
|
||||
udp_data_p->sd, dataSize);
|
||||
|
||||
if (udp_send_to(udp_data_p->sd, peerPort, peerIpAddr, dataBuf, dataSize) < 0) {
|
||||
return NW_GTPV1U_FAILURE;
|
||||
}
|
||||
|
||||
return NW_GTPV1U_OK;
|
||||
}
|
||||
|
||||
int data_recv_callback(uint16_t port,
|
||||
uint32_t address,
|
||||
uint8_t *buffer,
|
||||
uint32_t length,
|
||||
void *arg_p)
|
||||
{
|
||||
gtpv1u_data_t *gtpv1u_data_p;
|
||||
|
||||
if (arg_p == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
gtpv1u_data_p = (gtpv1u_data_t *)arg_p;
|
||||
|
||||
return nwGtpv1uProcessUdpReq(gtpv1u_data_p->gtpv1u_stack,
|
||||
buffer,
|
||||
length,
|
||||
port,
|
||||
address);
|
||||
}
|
||||
|
||||
int gtpv1u_create_tunnel_endpoint(gtpv1u_data_t *gtpv1u_data_p, uint8_t ue_id,
|
||||
uint8_t rab_id, char *sgw_ip_addr, uint16_t port)
|
||||
{
|
||||
uint32_t teid;
|
||||
uint8_t max_attempt = 100;
|
||||
NwGtpv1uRcT rc;
|
||||
NwGtpv1uUlpApiT ulp_req;
|
||||
struct gtpv1u_ue_data_s *new_ue_p;
|
||||
struct gtpv1u_ue_data_s *temp;
|
||||
struct gtpv1u_bearer_s *bearer;
|
||||
hashtbl_rc_t hash_rc;
|
||||
|
||||
if (rab_id > MAX_BEARERS_PER_UE) {
|
||||
LOG_E(GTPU, "Could not use rab_id %d > max %d\n",
|
||||
rab_id, MAX_BEARERS_PER_UE);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
if ((hash_rc = hashtbl_get(gtpv1u_data_p->ue_mapping, (uint64_t)ue_id, (void**)&new_ue_p)) == HASH_TABLE_OK) {
|
||||
/* A context for this UE already exist in the tree, use it */
|
||||
/* We check that the tunnel is not already configured */
|
||||
if (new_ue_p->bearers[rab_id].state != BEARER_DOWN) {
|
||||
LOG_E(GTPU, "Cannot create new end-point over already existing tunnel\n");
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
/* Context doesn't exist, create it */
|
||||
if (rab_id != 0) {
|
||||
/* UE should first establish Default bearer before trying to setup
|
||||
* additional bearers.
|
||||
*/
|
||||
LOG_E(GTPU, "UE context is not known and rab_id != 0\n");
|
||||
return -1;
|
||||
}
|
||||
new_ue_p = calloc(1, sizeof(struct gtpv1u_ue_data_s));
|
||||
new_ue_p->ue_id = ue_id;
|
||||
|
||||
hash_rc = hashtbl_insert(gtpv1u_data_p->ue_mapping, (uint64_t)ue_id, new_ue_p);
|
||||
|
||||
if ((hash_rc != HASH_TABLE_OK) && (hash_rc != HASH_TABLE_INSERT_OVERWRITTEN_DATA)) {
|
||||
LOG_E(GTPU, "Failed to insert new UE context\n");
|
||||
free(new_ue_p);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
bearer = &new_ue_p->bearers[rab_id];
|
||||
|
||||
/* Configure the bearer */
|
||||
bearer->state = BEARER_IN_CONFIG;
|
||||
bearer->sgw_ip_addr = inet_addr(sgw_ip_addr);
|
||||
bearer->port = port;
|
||||
|
||||
/* Create the new stack api request */
|
||||
memset(&ulp_req, 0, sizeof(NwGtpv1uUlpApiT));
|
||||
ulp_req.apiType = NW_GTPV1U_ULP_API_CREATE_TUNNEL_ENDPOINT;
|
||||
|
||||
/* Try to create new tunnel-endpoint.
|
||||
* If teid generated is already present in the stack, just peek another random
|
||||
* teid. This could be ok for small number of tunnel but more errors could be
|
||||
* thrown if we reached high number of tunnels.
|
||||
* TODO: find a solution for teid
|
||||
*/
|
||||
do {
|
||||
/* Request for a new random TEID */
|
||||
teid = gtpv1u_new_teid();
|
||||
ulp_req.apiInfo.createTunnelEndPointInfo.teid = teid;
|
||||
|
||||
rc = nwGtpv1uProcessUlpReq(gtpv1u_data_p->gtpv1u_stack, &ulp_req);
|
||||
|
||||
if (rc == NW_GTPV1U_OK) {
|
||||
// LOG_D(GTPU, "Successfully created new tunnel endpoint for teid 0x%x\n",
|
||||
// teid);
|
||||
bearer->teid_eNB = teid;
|
||||
// gtpv1u_initial_req(gtpv1u_data_p, teid, GTPV1U_UDP_PORT,
|
||||
// inet_addr("192.168.56.101"));
|
||||
LOG_I(GTPU, "Created eNB tunnel endpoint %u for ue id %u, rab id %u\n", teid, ue_id, rab_id);
|
||||
return 0;
|
||||
} else {
|
||||
LOG_W(GTPU, "Teid %u already in use... %s\n",
|
||||
teid, (max_attempt > 1) ? "Trying another one" : "Last chance");
|
||||
}
|
||||
} while(max_attempt-- && rc != NW_GTPV1U_OK);
|
||||
|
||||
bearer->state = BEARER_DOWN;
|
||||
LOG_I(GTPU, "Failed to created eNB tunnel endpoint %u for ue id %u, rab id %u, bearer down\n", teid, ue_id, rab_id);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
int gtpv1u_initial_req(gtpv1u_data_t *gtpv1u_data_p, uint32_t teid,
|
||||
uint16_t port, uint32_t address)
|
||||
{
|
||||
NwGtpv1uUlpApiT ulp_req;
|
||||
NwGtpv1uRcT rc;
|
||||
|
||||
memset(&ulp_req, 0, sizeof(NwGtpv1uUlpApiT));
|
||||
|
||||
ulp_req.apiType = NW_GTPV1U_ULP_API_INITIAL_REQ;
|
||||
ulp_req.apiInfo.initialReqInfo.teid = teid;
|
||||
ulp_req.apiInfo.initialReqInfo.peerPort = port;
|
||||
ulp_req.apiInfo.initialReqInfo.peerIp = address;
|
||||
|
||||
rc = nwGtpv1uProcessUlpReq(gtpv1u_data_p->gtpv1u_stack, &ulp_req);
|
||||
if (rc == NW_GTPV1U_OK) {
|
||||
LOG_D(GTPU, "Successfully sent initial req for teid %u\n", teid);
|
||||
} else {
|
||||
LOG_W(GTPU, "Could not send initial req for teid %u\n", teid);
|
||||
}
|
||||
return (rc == NW_GTPV1U_OK) ? 0 : -1;
|
||||
}
|
||||
|
||||
int gtpv1u_new_data_req(gtpv1u_data_t *gtpv1u_data_p,
|
||||
uint8_t ue_id, uint8_t rab_id,
|
||||
uint8_t *buffer, uint32_t buf_len)
|
||||
{
|
||||
#ifdef GTPU_IN_KERNEL
|
||||
struct sockaddr_in dummy_dest_addr;
|
||||
socklen_t socklen = sizeof(struct sockaddr_in);
|
||||
#endif
|
||||
NwGtpv1uUlpApiT stack_req;
|
||||
NwGtpv1uRcT rc;
|
||||
struct gtpv1u_ue_data_s ue;
|
||||
struct gtpv1u_ue_data_s *ue_inst_p;
|
||||
struct gtpv1u_bearer_s *bearer_p;
|
||||
hashtbl_rc_t hash_rc;
|
||||
|
||||
memset(&ue, 0, sizeof(struct gtpv1u_ue_data_s));
|
||||
|
||||
ue.ue_id = ue_id;
|
||||
|
||||
assert(gtpv1u_data_p != NULL);
|
||||
assert(rab_id <= MAX_BEARERS_PER_UE);
|
||||
|
||||
/* Check that UE context is present in ue map. */
|
||||
hash_rc = hashtbl_get(gtpv1u_data_p->ue_mapping, (uint64_t)ue_id, (void**)&ue_inst_p);
|
||||
|
||||
if (hash_rc == HASH_TABLE_KEY_NOT_EXISTS ) {
|
||||
LOG_E(GTPU, "[UE %d] Trying to send data on non-existing UE context\n", ue_id);
|
||||
return -1;
|
||||
}
|
||||
|
||||
bearer_p = &ue_inst_p->bearers[rab_id];
|
||||
|
||||
/* Ensure the bearer in ready.
|
||||
* TODO: handle the cases where the bearer is in HANDOVER state.
|
||||
* In such case packets should be placed in FIFO.
|
||||
*/
|
||||
if (bearer_p->state != BEARER_UP) {
|
||||
LOG_W(GTPU, "Trying to send data over bearer with state(%u) != BEARER_UP\n",
|
||||
bearer_p->state);
|
||||
#warning LG: HACK WHILE WAITING FOR NAS, normally return -1
|
||||
if (bearer_p->state != BEARER_IN_CONFIG)
|
||||
return -1;
|
||||
}
|
||||
#ifdef GTPU_IN_KERNEL
|
||||
dummy_dest_addr.sin_family = AF_INET;
|
||||
dummy_dest_addr.sin_port = 5001;
|
||||
dummy_dest_addr.sin_addr.s_addr = inet_addr("178.179.180.181");
|
||||
if (sendto(gtpv1u_data_p->sock_desc[rab_id], (void *)buffer, buf_len, 0, (struct sockaddr *)&dummy_dest_addr, socklen) < 0) {
|
||||
LOG_E(GTPU, "Error during send to socket %d : (%s:%d)\n", gtpv1u_data_p->sock_desc[rab_id], strerror(errno), errno);
|
||||
return -1;
|
||||
} else {
|
||||
LOG_D(GTPU, "send to UDP socket %d, packet should be handled by iptables\n", gtpv1u_data_p->sock_desc[rab_id]);
|
||||
}
|
||||
#else
|
||||
|
||||
memset(&stack_req, 0, sizeof(NwGtpv1uUlpApiT));
|
||||
|
||||
stack_req.apiType = NW_GTPV1U_ULP_API_SEND_TPDU;
|
||||
// LG HACK stack_req.apiInfo.sendtoInfo.teid = bearer_p->teid_sgw;
|
||||
stack_req.apiInfo.sendtoInfo.teid = 1;// LG HACK
|
||||
stack_req.apiInfo.sendtoInfo.ipAddr = bearer_p->sgw_ip_addr;
|
||||
|
||||
rc = nwGtpv1uGpduMsgNew(gtpv1u_data_p->gtpv1u_stack,
|
||||
//bearer_p->teid_sgw,
|
||||
1, // LG FORCING 1 instead of bearer_p->teid_sgw
|
||||
NW_FALSE,
|
||||
gtpv1u_data_p->seq_num++,
|
||||
buffer,
|
||||
buf_len,
|
||||
&(stack_req.apiInfo.sendtoInfo.hMsg));
|
||||
|
||||
if (rc != NW_GTPV1U_OK) {
|
||||
LOG_E(GTPU, "nwGtpv1uGpduMsgNew failed: 0x%x\n", rc);
|
||||
return -1;
|
||||
}
|
||||
rc = nwGtpv1uProcessUlpReq(gtpv1u_data_p->gtpv1u_stack,
|
||||
&stack_req);
|
||||
if (rc != NW_GTPV1U_OK) {
|
||||
LOG_E(GTPU, "nwGtpv1uProcessUlpReq failed: 0x%x\n", rc);
|
||||
return -1;
|
||||
}
|
||||
rc = nwGtpv1uMsgDelete(gtpv1u_data_p->gtpv1u_stack,
|
||||
stack_req.apiInfo.sendtoInfo.hMsg);
|
||||
if (rc != NW_GTPV1U_OK) {
|
||||
LOG_E(GTPU, "nwGtpv1uMsgDelete failed: 0x%x\n", rc);
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
LOG_E(GTPU, "%s() return code OK\n", __FUNCTION__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef GTPU_IN_KERNEL
|
||||
|
||||
#undef GTPV1U_PACKET_RX_RING
|
||||
/// The number of frames in the ring
|
||||
// This number is not set in stone. Nor are block_size, block_nr or frame_size
|
||||
#define CONF_RING_FRAMES 128
|
||||
|
||||
/// Offset of data from start of frame
|
||||
#define PKT_OFFSET (TPACKET_ALIGN(sizeof(struct tpacket_hdr)) + \
|
||||
TPACKET_ALIGN(sizeof(struct sockaddr_ll)))
|
||||
|
||||
int gtpv1u_eNB_create_sockets(gtpv1u_data_t *gtpv1u_data_p)
|
||||
{
|
||||
int value, mark;
|
||||
const int *val_p=&value;
|
||||
struct ifreq ifr;
|
||||
#ifdef GTPV1U_PACKET_RX_RING
|
||||
struct tpacket_req tp;
|
||||
#endif
|
||||
int i;
|
||||
|
||||
if (gtpv1u_data_p == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
GTPU_DEBUG("Creating socket for GTPV1U on %s if index %u\n", gtpv1u_data_p->interface_name, gtpv1u_data_p->interface_index);
|
||||
|
||||
for (mark = 0; mark <= 15; mark++) {
|
||||
|
||||
gtpv1u_data_p->sock_desc[mark] = socket( PF_INET , SOCK_DGRAM, 0);
|
||||
if (gtpv1u_data_p->sock_desc[mark] < 0) {
|
||||
GTPU_ERROR("Error during socket creation (%s:%d)\n",strerror(errno), errno);
|
||||
goto error;
|
||||
}
|
||||
|
||||
// // socket options, tell the kernel we provide the IP structure
|
||||
// if(setsockopt(sgi_data_p->sd[rab_id], IPPROTO_IP, IP_HDRINCL, &on, sizeof(on)) < 0)
|
||||
// {
|
||||
// SGI_IF_ERROR("Error during socket setsockopt IP_HDRINCL (%s:%d)\n", strerror(errno), errno);
|
||||
// goto error;
|
||||
// }
|
||||
//
|
||||
//
|
||||
// setting socket option to use MARK value
|
||||
//value = rab_id + SGI_MIN_EPS_BEARER_ID;
|
||||
value = mark;
|
||||
if (setsockopt (gtpv1u_data_p->sock_desc[mark], SOL_SOCKET, SO_MARK, val_p, sizeof (value)) < 0)
|
||||
{
|
||||
GTPU_ERROR("error notifying kernel about MARK");
|
||||
goto error;
|
||||
}
|
||||
GTPU_DEBUG("Created socket %d for rab_id %d (for any UE context)\n", gtpv1u_data_p->sock_desc[mark], value);
|
||||
|
||||
#ifdef SGI_PACKET_RX_RING
|
||||
// tell kernel to export data through mmap()ped ring
|
||||
tp.tp_block_size = CONF_RING_FRAMES * getpagesize();
|
||||
tp.tp_block_nr = 1;
|
||||
tp.tp_frame_size = getpagesize();
|
||||
tp.tp_frame_nr = CONF_RING_FRAMES;
|
||||
|
||||
if (setsockopt(gtpv1u_data_p->sock_desc[mark], SOL_PACKET, PACKET_RX_RING, (void*) &tp, sizeof(tp))) {
|
||||
GTPU_ERROR("setsockopt() ring\n");
|
||||
goto error;
|
||||
}
|
||||
|
||||
// open ring
|
||||
gtpv1u_data_p->sock_mmap_ring[mark] = mmap(0, tp.tp_block_size * tp.tp_block_nr, PROT_READ | PROT_WRITE, MAP_SHARED, sgi_data_p->sd[mark], 0);
|
||||
if (!gtpv1u_data_p->sock_mmap_ring[mark]) {
|
||||
GTPU_ERROR("Failed to mmap socket (%s:%d)\n", strerror(errno), errno);
|
||||
goto error;
|
||||
}
|
||||
/* Setup our ringbuffer */
|
||||
gtpv1u_data_p->malloc_ring[mark] = malloc(tp.tp_frame_nr * sizeof(struct iovec));
|
||||
for(i=0; i<tp.tp_frame_nr; i++) {
|
||||
gtpv1u_data_p->malloc_ring[mark][i].iov_base=(void *)((long)gtpv1u_data_p->sock_mmap_ring[mark])+(i*tp.tp_frame_size);
|
||||
gtpv1u_data_p->malloc_ring[mark][i].iov_len=tp.tp_frame_size;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
memset(&ifr, 0, sizeof(ifr));
|
||||
snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), gtpv1u_data_p->interface_name);
|
||||
if (setsockopt (gtpv1u_data_p->sock_desc[mark], SOL_SOCKET, SO_BINDTODEVICE,(void *)&ifr, sizeof(ifr)) < 0)
|
||||
{
|
||||
GTPU_ERROR("error notifying kernel about MARK");
|
||||
goto error;
|
||||
}
|
||||
GTPU_DEBUG("Created socket %d for rab_id %d (for any UE context)\n", gtpv1u_data_p->sock_desc[mark], value);
|
||||
}
|
||||
return 0;
|
||||
error:
|
||||
GTPU_ERROR("ERROR (%s)\n", strerror(errno));
|
||||
for (mark = 0; mark <= 15; mark++) {
|
||||
if (gtpv1u_data_p->sock_desc[mark] > 0) {
|
||||
close(gtpv1u_data_p->sock_desc[mark]);
|
||||
}
|
||||
gtpv1u_data_p->sock_desc[mark] = -1;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
int gtpv1u_eNB_init(gtpv1u_data_t *gtpv1u_data_p)
|
||||
{
|
||||
NwGtpv1uRcT rc;
|
||||
NwGtpv1uLogMgrEntityT log;
|
||||
NwGtpv1uUdpEntityT udp;
|
||||
NwGtpv1uUlpEntityT ulp;
|
||||
|
||||
if (gtpv1u_data_p == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
//(gtpv1u_data_p was allocated with calloc (zeroed))
|
||||
|
||||
// GTPU_INFO("Initializing GTPU stack for eNB %u\n",
|
||||
// gtpv1u_data_p->eNB_id);
|
||||
|
||||
/* Initialize UE tree */
|
||||
//RB_INIT(>pv1u_data_p->gtpv1u_ue_map_head);
|
||||
|
||||
#ifdef GTPU_IN_KERNEL
|
||||
#warning hardcoded ENB GTPV1U interface name
|
||||
gtpv1u_data_p->interface_name = "upenb0";
|
||||
gtpv1u_data_p->interface_index = if_nametoindex(gtpv1u_data_p->interface_name);
|
||||
|
||||
gtpv1u_eNB_create_sockets(gtpv1u_data_p);
|
||||
#endif
|
||||
/* Initialize UE hashtable */
|
||||
gtpv1u_data_p->ue_mapping = hashtbl_create (256, NULL, NULL);
|
||||
if (gtpv1u_data_p->ue_mapping == NULL) {
|
||||
perror("hashtbl_create");
|
||||
GTPU_ERROR("Initializing TASK_GTPV1_U task interface: ERROR\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (udp_create_connection(gtpv1u_data_p->ip_addr, GTPV1U_UDP_PORT,
|
||||
>pv1u_data_p->udp_data, data_recv_callback, (void *)gtpv1u_data_p) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Initializing GTPv1-U stack */
|
||||
if ((rc = nwGtpv1uInitialize(>pv1u_data_p->gtpv1u_stack)) != NW_GTPV1U_OK) {
|
||||
GTPU_ERROR("Failed to setup nwGtpv1u stack %x\n", rc);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Set up the log interface and register the log entity */
|
||||
log.logReqCallback = gtpv1u_eNB_log_request;
|
||||
|
||||
if ((rc = nwGtpv1uSetLogMgrEntity(gtpv1u_data_p->gtpv1u_stack,
|
||||
&log)) != NW_GTPV1U_OK) {
|
||||
GTPU_ERROR("nwGtpv1uSetLogMgrEntity: %x\n", rc);
|
||||
return -1;
|
||||
}
|
||||
|
||||
udp.hUdp = (NwGtpv1uUdpHandleT) >pv1u_data_p->udp_data;
|
||||
udp.udpDataReqCallback = gtpv1u_eNB_udp_req;
|
||||
|
||||
if ((rc = nwGtpv1uSetUdpEntity(gtpv1u_data_p->gtpv1u_stack,
|
||||
&udp)) != NW_GTPV1U_OK) {
|
||||
GTPU_ERROR("nwGtpv1uSetUdpEntity: %x\n", rc);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Set the ULP API callback. Called once message have been processed by the
|
||||
* nw-gtpv1u stack.
|
||||
*/
|
||||
ulp.ulpReqCallback = gtpv1u_process_stack_req;
|
||||
|
||||
if ((rc = nwGtpv1uSetUlpEntity(gtpv1u_data_p->gtpv1u_stack,
|
||||
&ulp)) != NW_GTPV1U_OK) {
|
||||
GTPU_ERROR("nwGtpv1uSetUlpEntity: %x\n", rc);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((rc = nwGtpv1uSetLogLevel(gtpv1u_data_p->gtpv1u_stack,
|
||||
NW_LOG_LEVEL_DEBG)) != NW_GTPV1U_OK) {
|
||||
GTPU_ERROR("nwGtpv1uSetLogLevel: %x\n", rc);
|
||||
return -1;
|
||||
}
|
||||
|
||||
gtpv1u_create_tunnel_endpoint(gtpv1u_data_p, 0, 0, "192.168.1.1", 2152);
|
||||
|
||||
// GTPU_INFO("Initializing GTPU stack for eNB %u: DONE\n",
|
||||
// gtpv1u_data_p->eNB_id);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
#include "NwGtpv1u.h"
|
||||
#include "gtpv1u.h"
|
||||
#include "udp_primitives_client.h"
|
||||
#include "hashtable.h"
|
||||
|
||||
//TEST LG #define GTPU_IN_KERNEL
|
||||
|
||||
//#include "tree.h"
|
||||
|
||||
#ifndef GTPV1U_ENB_DEFS_H_
|
||||
#define GTPV1U_ENB_DEFS_H_
|
||||
|
||||
#define GTPV1U_UDP_PORT (2152)
|
||||
|
||||
#define MAX_BEARERS_PER_UE (11)
|
||||
|
||||
typedef enum {
|
||||
BEARER_DOWN = 0,
|
||||
BEARER_IN_CONFIG,
|
||||
BEARER_UP,
|
||||
BEARER_DL_HANDOVER,
|
||||
BEARER_UL_HANDOVER,
|
||||
BEARER_MAX,
|
||||
} bearer_state_t;
|
||||
|
||||
typedef struct gtpv1u_bearer_s {
|
||||
/* TEID used in dl and ul */
|
||||
uint32_t teid_eNB; ///< eNB TEID
|
||||
uint32_t teid_sgw; ///< Remote TEID
|
||||
uint32_t sgw_ip_addr;
|
||||
uint16_t port;
|
||||
NwGtpv1uStackSessionHandleT stack_session;
|
||||
bearer_state_t state;
|
||||
} gtpv1u_bearer_t;
|
||||
|
||||
typedef struct gtpv1u_ue_data_s {
|
||||
/* UE identifier for oaisim stack */
|
||||
uint8_t ue_id;
|
||||
|
||||
/* Unique identifier used between PDCP and GTP-U to distinguish UEs */
|
||||
uint32_t instance_id;
|
||||
|
||||
/* Bearer related data.
|
||||
* Note that the first LCID available for data is 3 and we fixed the maximum
|
||||
* number of e-rab per UE to be 11. The real rb id will 3 + rab_id (0..10).
|
||||
*/
|
||||
gtpv1u_bearer_t bearers[MAX_BEARERS_PER_UE];
|
||||
|
||||
//RB_ENTRY(gtpv1u_ue_data_s) gtpv1u_ue_node;
|
||||
} gtpv1u_ue_data_t;
|
||||
|
||||
typedef struct gtpv1u_data_s{
|
||||
/* nwgtpv1u stack internal data */
|
||||
NwGtpv1uStackHandleT gtpv1u_stack;
|
||||
/* RB tree of UEs */
|
||||
hash_table_t *ue_mapping;
|
||||
|
||||
//RB_HEAD(gtpv1u_ue_map, gtpv1u_ue_data_s) gtpv1u_ue_map_head;
|
||||
/* Local IP address to use */
|
||||
char *ip_addr;
|
||||
/* UDP internal data */
|
||||
udp_data_t udp_data;
|
||||
|
||||
uint16_t seq_num;
|
||||
uint8_t restart_counter;
|
||||
|
||||
#ifdef GTPU_IN_KERNEL
|
||||
char *interface_name;
|
||||
int interface_index;
|
||||
|
||||
struct iovec *malloc_ring;
|
||||
void *sock_mmap_ring[16];
|
||||
int sock_desc[16]; // indexed by marking
|
||||
#endif
|
||||
} gtpv1u_data_t;
|
||||
|
||||
int gtpv1u_new_data_req(gtpv1u_data_t *gtpv1u_data_p,
|
||||
uint8_t ue_id, uint8_t rab_id,
|
||||
uint8_t *buffer, uint32_t buf_len);
|
||||
|
||||
int gtpv1u_initial_req(gtpv1u_data_t *gtpv1u_data_p, uint32_t teid,
|
||||
uint16_t port, uint32_t address);
|
||||
|
||||
int gtpv1u_eNB_init(gtpv1u_data_t *gtpv1u_data_p);
|
||||
|
||||
#endif /* GTPV1U_ENB_DEFS_H_ */
|
||||
@@ -0,0 +1,78 @@
|
||||
#ifndef GTPV1U_SGW_DEFS_H_
|
||||
#define GTPV1U_SGW_DEFS_H_
|
||||
|
||||
#include "mme_config.h"
|
||||
#include "NwGtpv1u.h"
|
||||
#include "gtpv1u.h"
|
||||
#include "hashtable.h"
|
||||
#include "common_types.h"
|
||||
|
||||
#define GTPV1U_UDP_PORT (2152)
|
||||
|
||||
#define MAX_BEARERS_PER_UE (11)
|
||||
|
||||
typedef enum {
|
||||
BEARER_DOWN = 0,
|
||||
BEARER_IN_CONFIG,
|
||||
BEARER_UP,
|
||||
BEARER_DL_HANDOVER,
|
||||
BEARER_UL_HANDOVER,
|
||||
BEARER_MAX,
|
||||
} bearer_state_t;
|
||||
|
||||
#define BUFFER_TO_NwU32T(buf, x) \
|
||||
do { \
|
||||
x = ((NwU32T)((buf)[0]) ) | \
|
||||
((NwU32T)((buf)[1]) << 8) | \
|
||||
((NwU32T)((buf)[2]) << 16) | \
|
||||
((NwU32T)((buf)[3]) << 24); \
|
||||
} while(0)
|
||||
|
||||
|
||||
|
||||
typedef struct gtpv1u_teid2enb_info_s {
|
||||
/* TEID used in dl and ul */
|
||||
uint32_t teid_enb; ///< Remote eNB TEID
|
||||
ip_address_t enb_ip_addr;
|
||||
bearer_state_t state;
|
||||
uint16_t port; /// LG ???
|
||||
} gtpv1u_teid2enb_info_t;
|
||||
|
||||
/*struct gtpv1u_ue_data_s {
|
||||
// UE identifier for oaisim stack
|
||||
uint8_t ue_id;
|
||||
|
||||
// Unique identifier used between PDCP and GTP-U to distinguish UEs
|
||||
uint32_t instance_id;
|
||||
|
||||
// Bearer related data.
|
||||
// Note that the first LCID available for data is 3 and we fixed the maximum
|
||||
// number of e-rab per UE to be 11. The real rb id will 3 + rab_id (0..10).
|
||||
//
|
||||
struct gtpv1u_bearer_s bearers[MAX_BEARERS_PER_UE];
|
||||
|
||||
RB_ENTRY(gtpv1u_ue_data_s) gtpv1u_ue_node;
|
||||
};*/
|
||||
|
||||
typedef struct {
|
||||
/* nwgtpv1u stack internal data */
|
||||
NwGtpv1uStackHandleT gtpv1u_stack;
|
||||
/* RB tree of UEs */
|
||||
//RB_HEAD(gtpv1u_ue_map, gtpv1u_ue_data_s) gtpv1u_ue_map_head;
|
||||
/* Local IP address to use */
|
||||
uint32_t sgw_ip_address_for_S1u_S12_S4_up;
|
||||
char *ip_addr;
|
||||
/* UDP internal data */
|
||||
//udp_data_t udp_data;
|
||||
|
||||
uint16_t seq_num;
|
||||
uint8_t restart_counter;
|
||||
//gtpv1u_teid2enb_info_t* teid2enb_mapping[];
|
||||
hash_table_t *S1U_mapping;
|
||||
|
||||
} gtpv1u_data_t;
|
||||
|
||||
|
||||
int gtpv1u_init(const mme_config_t *mme_config);
|
||||
|
||||
#endif /* GTPV1U_SGW_DEFS_H_ */
|
||||
@@ -0,0 +1,553 @@
|
||||
/*******************************************************************************
|
||||
|
||||
Eurecom OpenAirInterface
|
||||
Copyright(c) 1999 - 2012 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.fr/openairinterface
|
||||
Address : EURECOM, Campus SophiaTech, 450 Route des Chappes
|
||||
06410 Biot FRANCE
|
||||
|
||||
*******************************************************************************/
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "mme_config.h"
|
||||
|
||||
#include "assertions.h"
|
||||
#include "intertask_interface.h"
|
||||
#include "timer.h"
|
||||
|
||||
#include "gtpv1u.h"
|
||||
#include "NwGtpv1u.h"
|
||||
#include "NwGtpv1uMsg.h"
|
||||
#include "NwLog.h"
|
||||
#include "gtpv1u_sgw_defs.h"
|
||||
|
||||
//static NwGtpv1uStackHandleT gtpv1u_stack = 0;
|
||||
static gtpv1u_data_t gtpv1u_sgw_data;
|
||||
|
||||
static int gtpv1u_send_init_udp(uint16_t port_number);
|
||||
static int gtpv1u_create_s1u_tunnel(Gtpv1uCreateTunnelReq *create_tunnel_reqP);
|
||||
static int gtpv1u_delete_s1u_tunnel(Teid_t context_teidP, Teid_t S1U_teidP);
|
||||
static int gtpv1u_update_s1u_tunnel(Gtpv1uUpdateTunnelReq *reqP);
|
||||
static void *gtpv1u_thread(void *args);
|
||||
|
||||
NwGtpv1uRcT gtpv1u_send_udp_msg(
|
||||
NwGtpv1uUdpHandleT udpHandle,
|
||||
NwU8T *buffer,
|
||||
NwU32T buffer_len,
|
||||
NwU32T peerIpAddr,
|
||||
NwU32T peerPort);
|
||||
|
||||
NwGtpv1uRcT gtpv1u_log_request(
|
||||
NwGtpv1uLogMgrHandleT hLogMgr,
|
||||
NwU32T logLevel,
|
||||
NwCharT *file,
|
||||
NwU32T line,
|
||||
NwCharT *logStr);
|
||||
|
||||
NwGtpv1uRcT gtpv1u_process_stack_req(
|
||||
NwGtpv1uUlpHandleT hUlp,
|
||||
NwGtpv1uUlpApiT *pUlpApi);
|
||||
|
||||
static int gtpv1u_send_init_udp(uint16_t port_number)
|
||||
{
|
||||
// Create and alloc new message
|
||||
MessageDef *message_p;
|
||||
struct in_addr addr;
|
||||
|
||||
message_p = alloc_new_message(TASK_GTPV1_U, UDP_INIT);
|
||||
if (message_p == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
message_p->msg.udp_init.port = port_number;
|
||||
//LG message_p->msg.udp_init.address = "0.0.0.0"; //ANY address
|
||||
|
||||
addr.s_addr = gtpv1u_sgw_data.sgw_ip_address_for_S1u_S12_S4_up;
|
||||
message_p->msg.udp_init.address = inet_ntoa(addr);
|
||||
GTPU_DEBUG("Tx UDP_INIT IP addr %s\n", message_p->msg.udp_init.address);
|
||||
|
||||
return send_msg_to_task(TASK_UDP, INSTANCE_DEFAULT, message_p);
|
||||
}
|
||||
|
||||
NwGtpv1uRcT gtpv1u_log_request(NwGtpv1uLogMgrHandleT hLogMgr,
|
||||
NwU32T logLevel,
|
||||
NwCharT *file,
|
||||
NwU32T line,
|
||||
NwCharT *logStr)
|
||||
{
|
||||
GTPU_DEBUG("%s\n", logStr);
|
||||
return NW_GTPV1U_OK;
|
||||
}
|
||||
|
||||
NwGtpv1uRcT gtpv1u_send_udp_msg(
|
||||
NwGtpv1uUdpHandleT udpHandle,
|
||||
NwU8T *buffer,
|
||||
NwU32T buffer_len,
|
||||
NwU32T peerIpAddr,
|
||||
NwU32T peerPort)
|
||||
{
|
||||
// Create and alloc new message
|
||||
MessageDef *message_p;
|
||||
udp_data_req_t *udp_data_req_p;
|
||||
|
||||
message_p = alloc_new_message(TASK_GTPV1_U, UDP_DATA_REQ);
|
||||
|
||||
udp_data_req_p = &message_p->msg.udp_data_req;
|
||||
|
||||
udp_data_req_p->peer_address = peerIpAddr;
|
||||
udp_data_req_p->peer_port = peerPort;
|
||||
udp_data_req_p->buffer = buffer;
|
||||
udp_data_req_p->buffer_length = buffer_len;
|
||||
|
||||
return send_msg_to_task(TASK_UDP, INSTANCE_DEFAULT, message_p);
|
||||
}
|
||||
|
||||
/* Callback called when a gtpv1u message arrived on UDP interface */
|
||||
NwGtpv1uRcT gtpv1u_process_stack_req(
|
||||
NwGtpv1uUlpHandleT hUlp,
|
||||
NwGtpv1uUlpApiT *pUlpApi)
|
||||
{
|
||||
switch(pUlpApi->apiType) {
|
||||
/* Here there are two type of messages handled:
|
||||
* - T-PDU
|
||||
* - END-MARKER
|
||||
*/
|
||||
case NW_GTPV1U_ULP_API_RECV_TPDU: {
|
||||
uint8_t buffer[4096];
|
||||
uint32_t buffer_len;
|
||||
MessageDef *message_p;
|
||||
Gtpv1uTunnelDataInd *data_ind_p;
|
||||
|
||||
/* Nw-gptv1u stack has processed a PDU. we can forward it to IPV4
|
||||
* task for transmission.
|
||||
*/
|
||||
if (NW_GTPV1U_OK != nwGtpv1uMsgGetTpdu(pUlpApi->apiInfo.recvMsgInfo.hMsg,
|
||||
buffer, (NwU32T *)&buffer_len)) {
|
||||
GTPU_ERROR("Error while retrieving T-PDU");
|
||||
}
|
||||
GTPU_DEBUG("Received TPDU from gtpv1u stack %u with size %d", pUlpApi->apiInfo.recvMsgInfo.teid, buffer_len);
|
||||
|
||||
message_p = alloc_new_message(TASK_GTPV1_U, GTPV1U_TUNNEL_DATA_IND);
|
||||
if (message_p == NULL) {
|
||||
return -1;
|
||||
}
|
||||
data_ind_p = &message_p->msg.gtpv1uTunnelDataInd;
|
||||
data_ind_p->buffer = malloc(sizeof(uint8_t) * buffer_len);
|
||||
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);
|
||||
} else {
|
||||
memcpy(data_ind_p->buffer, buffer, buffer_len);
|
||||
data_ind_p->length = buffer_len;
|
||||
if (send_msg_to_task(TASK_FW_IP, INSTANCE_DEFAULT, message_p) < 0) {
|
||||
GTPU_ERROR("Failed to send message to task\n");
|
||||
free(message_p);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case NW_GTPV1U_ULP_API_CREATE_TUNNEL_ENDPOINT:{
|
||||
}
|
||||
break;
|
||||
|
||||
default: {
|
||||
GTPU_ERROR("Received undefined UlpApi (%02x) from gtpv1u stack!\n",
|
||||
pUlpApi->apiType);
|
||||
}
|
||||
}
|
||||
return NW_GTPV1U_OK;
|
||||
}
|
||||
|
||||
static int gtpv1u_create_s1u_tunnel(Gtpv1uCreateTunnelReq *create_tunnel_reqP)
|
||||
{
|
||||
/* Create a new nw-gtpv1-u stack req using API */
|
||||
NwGtpv1uUlpApiT stack_req;
|
||||
NwGtpv1uRcT rc;
|
||||
/* Local tunnel end-point identifier */
|
||||
uint32_t s1u_teid;
|
||||
gtpv1u_teid2enb_info_t *gtpv1u_teid2enb_info;
|
||||
MessageDef *message_p;
|
||||
hashtbl_rc_t hash_rc;
|
||||
|
||||
GTPU_DEBUG("Rx GTPV1U_CREATE_TUNNEL_REQ Context %d\n", create_tunnel_reqP->context_teid);
|
||||
memset(&stack_req, 0, sizeof(NwGtpv1uUlpApiT));
|
||||
|
||||
stack_req.apiType = NW_GTPV1U_ULP_API_CREATE_TUNNEL_ENDPOINT;
|
||||
|
||||
do {
|
||||
s1u_teid = gtpv1u_new_teid();
|
||||
GTPU_DEBUG("gtpv1u_create_s1u_tunnel() %u\n", s1u_teid);
|
||||
stack_req.apiInfo.createTunnelEndPointInfo.teid = s1u_teid;
|
||||
stack_req.apiInfo.createTunnelEndPointInfo.hUlpSession = 0;
|
||||
stack_req.apiInfo.createTunnelEndPointInfo.hStackSession = 0;
|
||||
|
||||
rc = nwGtpv1uProcessUlpReq(gtpv1u_sgw_data.gtpv1u_stack, &stack_req);
|
||||
GTPU_DEBUG(".\n");
|
||||
} while (rc != NW_GTPV1U_OK);
|
||||
|
||||
gtpv1u_teid2enb_info = malloc (sizeof(gtpv1u_teid2enb_info_t));
|
||||
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;
|
||||
|
||||
|
||||
message_p = alloc_new_message(TASK_GTPV1_U, GTPV1U_CREATE_TUNNEL_RESP);
|
||||
message_p->msg.gtpv1uCreateTunnelResp.S1u_teid = s1u_teid;
|
||||
message_p->msg.gtpv1uCreateTunnelResp.context_teid = create_tunnel_reqP->context_teid;
|
||||
message_p->msg.gtpv1uCreateTunnelResp.eps_bearer_id = create_tunnel_reqP->eps_bearer_id;
|
||||
|
||||
hash_rc = hashtbl_is_key_exists(gtpv1u_sgw_data.S1U_mapping, s1u_teid);
|
||||
|
||||
if (hash_rc == HASH_TABLE_KEY_NOT_EXISTS) {
|
||||
hash_rc = hashtbl_insert(gtpv1u_sgw_data.S1U_mapping, s1u_teid, gtpv1u_teid2enb_info);
|
||||
message_p->msg.gtpv1uCreateTunnelResp.status = 0;
|
||||
} else {
|
||||
message_p->msg.gtpv1uCreateTunnelResp.status = 0xFF;
|
||||
}
|
||||
|
||||
GTPU_DEBUG("Tx GTPV1U_CREATE_TUNNEL_RESP Context %u teid %u eps bearer id %u status %d\n",
|
||||
message_p->msg.gtpv1uCreateTunnelResp.context_teid,
|
||||
message_p->msg.gtpv1uCreateTunnelResp.S1u_teid,
|
||||
message_p->msg.gtpv1uCreateTunnelResp.eps_bearer_id,
|
||||
message_p->msg.gtpv1uCreateTunnelResp.status);
|
||||
return send_msg_to_task(TASK_SPGW_APP, INSTANCE_DEFAULT, message_p);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static int gtpv1u_delete_s1u_tunnel(Teid_t context_teidP, Teid_t S1U_teidP)
|
||||
{
|
||||
/* Local tunnel end-point identifier */
|
||||
MessageDef *message_p;
|
||||
|
||||
GTPU_DEBUG("Rx GTPV1U_DELETE_TUNNEL Context %u S1U teid %u\n", context_teidP, S1U_teidP);
|
||||
message_p = alloc_new_message(TASK_GTPV1_U, GTPV1U_DELETE_TUNNEL_RESP);
|
||||
|
||||
message_p->msg.gtpv1uDeleteTunnelResp.S1u_teid = S1U_teidP;
|
||||
message_p->msg.gtpv1uDeleteTunnelResp.context_teid = context_teidP;
|
||||
|
||||
if (hashtbl_remove(gtpv1u_sgw_data.S1U_mapping, S1U_teidP) == HASH_TABLE_OK ) {
|
||||
message_p->msg.gtpv1uDeleteTunnelResp.status = 0;
|
||||
} else {
|
||||
message_p->msg.gtpv1uDeleteTunnelResp.status = -1;
|
||||
}
|
||||
GTPU_DEBUG("Tx SGW_S1U_ENDPOINT_CREATED Context %u teid %u status %d\n", context_teidP, S1U_teidP, message_p->msg.gtpv1uDeleteTunnelResp.status);
|
||||
return send_msg_to_task(TASK_SPGW_APP, INSTANCE_DEFAULT, message_p);
|
||||
}
|
||||
|
||||
|
||||
static int gtpv1u_update_s1u_tunnel(Gtpv1uUpdateTunnelReq *reqP)
|
||||
{
|
||||
hashtbl_rc_t hash_rc;
|
||||
gtpv1u_teid2enb_info_t *gtpv1u_teid2enb_info;
|
||||
MessageDef *message_p;
|
||||
|
||||
GTPU_DEBUG("Rx GTPV1U_UPDATE_TUNNEL_REQ Context %u, S-GW S1U teid %u, eNB S1U teid %u\n",
|
||||
reqP->context_teid,
|
||||
reqP->sgw_S1u_teid,
|
||||
reqP->enb_S1u_teid);
|
||||
message_p = alloc_new_message(TASK_GTPV1_U, GTPV1U_UPDATE_TUNNEL_RESP);
|
||||
|
||||
hash_rc = hashtbl_get(gtpv1u_sgw_data.S1U_mapping, reqP->sgw_S1u_teid, (void**)>pv1u_teid2enb_info);
|
||||
|
||||
if (hash_rc == HASH_TABLE_OK) {
|
||||
gtpv1u_teid2enb_info->teid_enb = reqP->enb_S1u_teid;
|
||||
gtpv1u_teid2enb_info->enb_ip_addr = reqP->enb_ip_address_for_S1u;
|
||||
gtpv1u_teid2enb_info->state = BEARER_UP;
|
||||
gtpv1u_teid2enb_info->port = GTPV1U_UDP_PORT;
|
||||
message_p->msg.gtpv1uUpdateTunnelResp.status = 0; ///< Status (Failed = 0xFF or Success = 0x0)
|
||||
} else {
|
||||
GTPU_ERROR("Mapping not found\n");
|
||||
message_p->msg.gtpv1uUpdateTunnelResp.status = 0xFF; ///< Status (Failed = 0xFF or Success = 0x0)
|
||||
}
|
||||
message_p->msg.gtpv1uUpdateTunnelResp.context_teid = reqP->context_teid;
|
||||
message_p->msg.gtpv1uUpdateTunnelResp.sgw_S1u_teid = reqP->sgw_S1u_teid;
|
||||
message_p->msg.gtpv1uUpdateTunnelResp.enb_S1u_teid = reqP->enb_S1u_teid;
|
||||
message_p->msg.gtpv1uUpdateTunnelResp.eps_bearer_id = reqP->eps_bearer_id;
|
||||
return send_msg_to_task(TASK_SPGW_APP, INSTANCE_DEFAULT, message_p);
|
||||
}
|
||||
|
||||
|
||||
static NwGtpv1uRcT gtpv1u_start_timer_wrapper(
|
||||
NwGtpv1uTimerMgrHandleT tmrMgrHandle,
|
||||
NwU32T timeoutSec,
|
||||
NwU32T timeoutUsec,
|
||||
NwU32T tmrType,
|
||||
void *timeoutArg,
|
||||
NwGtpv1uTimerHandleT *hTmr)
|
||||
{
|
||||
|
||||
NwGtpv1uRcT rc = NW_GTPV1U_OK;
|
||||
long timer_id;
|
||||
|
||||
if (tmrType == NW_GTPV1U_TMR_TYPE_ONE_SHOT) {
|
||||
timer_setup(timeoutSec,
|
||||
timeoutUsec,
|
||||
TASK_GTPV1_U,
|
||||
INSTANCE_DEFAULT,
|
||||
TIMER_ONE_SHOT,
|
||||
timeoutArg,
|
||||
&timer_id);
|
||||
} else {
|
||||
timer_setup(timeoutSec,
|
||||
timeoutUsec,
|
||||
TASK_GTPV1_U,
|
||||
INSTANCE_DEFAULT,
|
||||
TIMER_PERIODIC,
|
||||
timeoutArg,
|
||||
&timer_id);
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static NwGtpv1uRcT gtpv1u_stop_timer_wrapper(
|
||||
NwGtpv1uTimerMgrHandleT tmrMgrHandle,
|
||||
NwGtpv1uTimerHandleT hTmr)
|
||||
{
|
||||
|
||||
NwGtpv1uRcT rc = NW_GTPV1U_OK;
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static void *gtpv1u_thread(void *args)
|
||||
{
|
||||
intertask_interface_mark_task_ready(TASK_GTPV1_U);
|
||||
while(1) {
|
||||
/* Trying to fetch a message from the message queue.
|
||||
* If the queue is empty, this function will block till a
|
||||
* message is sent to the task.
|
||||
*/
|
||||
MessageDef *received_message_p = NULL;
|
||||
receive_msg(TASK_GTPV1_U, &received_message_p);
|
||||
DevAssert(received_message_p != NULL);
|
||||
|
||||
switch(received_message_p->header.messageId) {
|
||||
case GTPV1U_CREATE_TUNNEL_REQ: {
|
||||
gtpv1u_create_s1u_tunnel(&received_message_p->msg.gtpv1uCreateTunnelReq);
|
||||
}
|
||||
break;
|
||||
|
||||
case GTPV1U_DELETE_TUNNEL_REQ: {
|
||||
gtpv1u_delete_s1u_tunnel(received_message_p->msg.gtpv1uDeleteTunnelReq.context_teid, received_message_p->msg.gtpv1uDeleteTunnelReq.S1u_teid);
|
||||
}
|
||||
break;
|
||||
|
||||
case GTPV1U_UPDATE_TUNNEL_REQ: {
|
||||
gtpv1u_update_s1u_tunnel(&received_message_p->msg.gtpv1uUpdateTunnelReq);
|
||||
}
|
||||
break;
|
||||
|
||||
// DATA COMING FROM UDP
|
||||
case UDP_DATA_IND: {
|
||||
udp_data_ind_t *udp_data_ind_p;
|
||||
udp_data_ind_p = &received_message_p->msg.udp_data_ind;
|
||||
nwGtpv1uProcessUdpReq(gtpv1u_sgw_data.gtpv1u_stack,
|
||||
udp_data_ind_p->buffer,
|
||||
udp_data_ind_p->buffer_length,
|
||||
udp_data_ind_p->peer_port,
|
||||
udp_data_ind_p->peer_address);
|
||||
free(udp_data_ind_p->buffer);
|
||||
}
|
||||
break;
|
||||
|
||||
// DATA TO BE SENT TO UDP
|
||||
case GTPV1U_TUNNEL_DATA_REQ: {
|
||||
Gtpv1uTunnelDataReq *data_req_p;
|
||||
NwGtpv1uUlpApiT stack_req;
|
||||
NwGtpv1uRcT rc;
|
||||
hashtbl_rc_t hash_rc;
|
||||
gtpv1u_teid2enb_info_t *gtpv1u_teid2enb_info;
|
||||
|
||||
data_req_p = &received_message_p->msg.gtpv1uTunnelDataReq;
|
||||
//ipv4_send_data(ipv4_data_p->sd, data_ind_p->buffer, data_ind_p->length);
|
||||
|
||||
memset(&stack_req, 0, sizeof(NwGtpv1uUlpApiT));
|
||||
|
||||
/*
|
||||
* typedef struct
|
||||
{
|
||||
NW_IN NwU32T teid;
|
||||
NW_IN NwU32T ipAddr;
|
||||
NW_IN NwU8T flags;
|
||||
NW_IN NwGtpv1uMsgHandleT hMsg;
|
||||
} NwGtpv1uSendtoInfoT;*/
|
||||
|
||||
hash_rc = hashtbl_get(gtpv1u_sgw_data.S1U_mapping, (uint64_t)data_req_p->local_S1u_teid, (void**)>pv1u_teid2enb_info);
|
||||
|
||||
if (hash_rc == HASH_TABLE_KEY_NOT_EXISTS) {
|
||||
GTPU_ERROR("nwGtpv1uProcessUlpReq failed: while getting teid %u in hashtable S1U_mapping\n", data_req_p->local_S1u_teid);
|
||||
} else {
|
||||
stack_req.apiType = NW_GTPV1U_ULP_API_SEND_TPDU;
|
||||
stack_req.apiInfo.sendtoInfo.teid = data_req_p->local_S1u_teid;
|
||||
BUFFER_TO_NwU32T(gtpv1u_teid2enb_info->enb_ip_addr.address.ipv4_address, stack_req.apiInfo.sendtoInfo.ipAddr);
|
||||
|
||||
/*nwGtpv1uGpduMsgNew( NW_IN NwGtpv1uStackHandleT hGtpuStackHandle,
|
||||
NW_IN NwU32T teid,
|
||||
NW_IN NwU8T seqNumFlag,
|
||||
NW_IN NwU16T seqNum,
|
||||
NW_IN NwU8T *tpdu,
|
||||
NW_IN NwU16T tpduLength,
|
||||
NW_OUT NwGtpv1uMsgHandleT *phMsg)*/
|
||||
rc = nwGtpv1uGpduMsgNew(gtpv1u_sgw_data.gtpv1u_stack,
|
||||
00,// TO DO bearer_p->port, but not needed when looking at processing
|
||||
NW_FALSE,
|
||||
gtpv1u_sgw_data.seq_num++,
|
||||
data_req_p->buffer,
|
||||
data_req_p->length,
|
||||
&(stack_req.apiInfo.sendtoInfo.hMsg));
|
||||
|
||||
if (rc != NW_GTPV1U_OK) {
|
||||
GTPU_ERROR("nwGtpv1uGpduMsgNew failed: 0x%x\n", rc);
|
||||
} else {
|
||||
rc = nwGtpv1uProcessUlpReq(gtpv1u_sgw_data.gtpv1u_stack, &stack_req);
|
||||
if (rc != NW_GTPV1U_OK) {
|
||||
GTPU_ERROR("nwGtpv1uProcessUlpReq failed: 0x%x\n", rc);
|
||||
}
|
||||
rc = nwGtpv1uMsgDelete(gtpv1u_sgw_data.gtpv1u_stack,
|
||||
stack_req.apiInfo.sendtoInfo.hMsg);
|
||||
if (rc != NW_GTPV1U_OK) {
|
||||
GTPU_ERROR("nwGtpv1uMsgDelete failed: 0x%x\n", rc);
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Buffer is no longer needed, free it */
|
||||
free(data_req_p->buffer);
|
||||
}
|
||||
break;
|
||||
case TIMER_HAS_EXPIRED:
|
||||
nwGtpv1uProcessTimeout(&received_message_p->msg.timer_has_expired.arg);
|
||||
break;
|
||||
default: {
|
||||
GTPU_ERROR("Unkwnon message ID %s:%d\n",
|
||||
get_message_name(received_message_p->header.messageId),
|
||||
received_message_p->header.messageId);
|
||||
}
|
||||
break;
|
||||
}
|
||||
free(received_message_p);
|
||||
received_message_p = NULL;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int gtpv1u_init(const mme_config_t *mme_config_p)
|
||||
{
|
||||
int ret;
|
||||
NwGtpv1uRcT rc;
|
||||
NwGtpv1uUlpEntityT ulp;
|
||||
NwGtpv1uUdpEntityT udp;
|
||||
NwGtpv1uLogMgrEntityT log;
|
||||
NwGtpv1uTimerMgrEntityT tmr;
|
||||
|
||||
GTPU_DEBUG("Initializing GTPV1U interface\n");
|
||||
|
||||
memset(>pv1u_sgw_data, 0, sizeof(gtpv1u_sgw_data));
|
||||
|
||||
gtpv1u_sgw_data.S1U_mapping = hashtbl_create (8192, NULL, NULL);
|
||||
if (gtpv1u_sgw_data.S1U_mapping == NULL) {
|
||||
perror("hashtbl_create");
|
||||
GTPU_ERROR("Initializing TASK_GTPV1_U task interface: ERROR\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
gtpv1u_sgw_data.sgw_ip_address_for_S1u_S12_S4_up = mme_config_p->ipv4.sgw_ip_address_for_S1u_S12_S4_up;
|
||||
|
||||
/* Initializing GTPv1-U stack */
|
||||
if ((rc = nwGtpv1uInitialize(>pv1u_sgw_data.gtpv1u_stack)) != NW_GTPV1U_OK) {
|
||||
GTPU_ERROR("Failed to setup nwGtpv1u stack %x\n", rc);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((rc = nwGtpv1uSetLogLevel(gtpv1u_sgw_data.gtpv1u_stack,
|
||||
NW_LOG_LEVEL_DEBG)) != NW_GTPV1U_OK) {
|
||||
GTPU_ERROR("Failed to setup loglevel for stack %x\n", rc);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Set the ULP API callback. Called once message have been processed by the
|
||||
* nw-gtpv1u stack.
|
||||
*/
|
||||
ulp.ulpReqCallback = gtpv1u_process_stack_req;
|
||||
|
||||
if ((rc = nwGtpv1uSetUlpEntity(gtpv1u_sgw_data.gtpv1u_stack, &ulp)) != NW_GTPV1U_OK) {
|
||||
GTPU_ERROR("nwGtpv1uSetUlpEntity: %x", rc);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* nw-gtpv1u stack requires an udp callback to send data over UDP.
|
||||
* We provide a wrapper to UDP task.
|
||||
*/
|
||||
udp.udpDataReqCallback = gtpv1u_send_udp_msg;
|
||||
|
||||
if ((rc = nwGtpv1uSetUdpEntity(gtpv1u_sgw_data.gtpv1u_stack, &udp)) != NW_GTPV1U_OK) {
|
||||
GTPU_ERROR("nwGtpv1uSetUdpEntity: %x", rc);
|
||||
return -1;
|
||||
}
|
||||
|
||||
log.logReqCallback = gtpv1u_log_request;
|
||||
|
||||
if ((rc = nwGtpv1uSetLogMgrEntity(gtpv1u_sgw_data.gtpv1u_stack, &log)) != NW_GTPV1U_OK) {
|
||||
GTPU_ERROR("nwGtpv1uSetLogMgrEntity: %x", rc);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Timer interface is more complicated as both wrappers doesn't send a message
|
||||
* to the timer task but call the timer API functions start/stop timer.
|
||||
*/
|
||||
tmr.tmrMgrHandle = 0;
|
||||
tmr.tmrStartCallback = gtpv1u_start_timer_wrapper;
|
||||
tmr.tmrStopCallback = gtpv1u_stop_timer_wrapper;
|
||||
|
||||
if ((rc = nwGtpv1uSetTimerMgrEntity(gtpv1u_sgw_data.gtpv1u_stack, &tmr)) != NW_GTPV1U_OK) {
|
||||
GTPU_ERROR("nwGtpv1uSetTimerMgrEntity: %x", rc);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (intertask_interface_create_task(TASK_GTPV1_U, >pv1u_thread, NULL) < 0) {
|
||||
GTPU_ERROR("gtpv1u phtread_create: %s", strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = gtpv1u_send_init_udp(mme_config_p->gtpv1u_config.port_number);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
GTPU_DEBUG("Initializing GTPV1U interface: DONE\n");
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "gtpv1u.h"
|
||||
|
||||
#define GTPV1U_LINEAR_TEID_ALLOCATION 1
|
||||
|
||||
#ifdef GTPV1U_LINEAR_TEID_ALLOCATION
|
||||
static uint32_t g_gtpv1u_teid = 0;
|
||||
#endif
|
||||
|
||||
uint32_t gtpv1u_new_teid(void)
|
||||
{
|
||||
#ifdef GTPV1U_LINEAR_TEID_ALLOCATION
|
||||
g_gtpv1u_teid = g_gtpv1u_teid + 1;
|
||||
return g_gtpv1u_teid;
|
||||
#else
|
||||
return random() + random() % (RAND_MAX - 1) + 1;
|
||||
#endif
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
Amit Chawre
|
||||
@@ -0,0 +1,26 @@
|
||||
Copyright (c) 2010-2011 Amit Chawre <http://www.amitchawre.net/contact.html>
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
3. The name of the author may not be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
@@ -0,0 +1,83 @@
|
||||
/*----------------------------------------------------------------------------*
|
||||
* *
|
||||
* n w - g t p v 2 u *
|
||||
* G P R S T u n n e l i n g P r o t o c o l v 2 u S t a c k *
|
||||
* *
|
||||
* *
|
||||
* Copyright (c) 2010-2011 Amit Chawre *
|
||||
* All rights reserved. *
|
||||
* *
|
||||
* Redistribution and use in source and binary forms, with or without *
|
||||
* modification, are permitted provided that the following conditions *
|
||||
* are met: *
|
||||
* *
|
||||
* 1. Redistributions of source code must retain the above copyright *
|
||||
* notice, this list of conditions and the following disclaimer. *
|
||||
* 2. Redistributions in binary form must reproduce the above copyright *
|
||||
* notice, this list of conditions and the following disclaimer in the *
|
||||
* documentation and/or other materials provided with the distribution. *
|
||||
* 3. The name of the author may not be used to endorse or promote products *
|
||||
* derived from this software without specific prior written permission. *
|
||||
* *
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR *
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES *
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. *
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, *
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT *
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, *
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY *
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT *
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF *
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef __NW_GTPV1U_LOG_H__
|
||||
#define __NW_GTPV1U_LOG_H__
|
||||
|
||||
#include <stdio.h>
|
||||
#include "NwLog.h"
|
||||
|
||||
/**
|
||||
* @file NwGtpv1uLog.h
|
||||
* @brief This header contains logging related definitions.
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
* Log Macro Definition
|
||||
*--------------------------------------------------------------------------*/
|
||||
|
||||
#define NW_LOG(_gtpv1uHandle, _logLevel, ...) \
|
||||
do { \
|
||||
if(((NwGtpv1uStackT*)(_gtpv1uHandle))->logLevel >= _logLevel) \
|
||||
{ \
|
||||
char _logBuf[1024]; \
|
||||
snprintf(_logBuf, 1024, __VA_ARGS__); \
|
||||
((NwGtpv1uStackT*)(_gtpv1uHandle))->logMgr.logReqCallback(((NwGtpv1uStackT*)_gtpv1uHandle)->logMgr.logMgrHandle, _logLevel, __FILE__, __LINE__, _logBuf);\
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
#define NW_ENTER(_gtpv1uHandle) \
|
||||
do { \
|
||||
NW_LOG(_gtpv1uHandle, NW_LOG_LEVEL_DEBG, "Entering '%s'", __func__);\
|
||||
} while(0)
|
||||
|
||||
#define NW_LEAVE(_gtpv1uHandle) \
|
||||
do { \
|
||||
NW_LOG(_gtpv1uHandle, NW_LOG_LEVEL_DEBG, "Leaving '%s'", __func__);\
|
||||
} while(0)
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __NW_TYPES_H__ */
|
||||
|
||||
|
||||
/*--------------------------------------------------------------------------*
|
||||
* E N D O F F I L E *
|
||||
*--------------------------------------------------------------------------*/
|
||||
|
||||
@@ -0,0 +1,230 @@
|
||||
/*----------------------------------------------------------------------------*
|
||||
* *
|
||||
* n w - g t p v 2 u *
|
||||
* n w - g t p v 2 u *
|
||||
* G P R S T u n n e l i n g P r o t o c o l v 2 u S t a c k *
|
||||
* *
|
||||
* *
|
||||
* Copyright (c) 2010-2011 Amit Chawre *
|
||||
* All rights reserved. *
|
||||
* *
|
||||
* Redistribution and use in source and binary forms, with or without *
|
||||
* modification, are permitted provided that the following conditions *
|
||||
* are met: *
|
||||
* *
|
||||
* 1. Redistributions of source code must retain the above copyright *
|
||||
* notice, this list of conditions and the following disclaimer. *
|
||||
* 2. Redistributions in binary form must reproduce the above copyright *
|
||||
* notice, this list of conditions and the following disclaimer in the *
|
||||
* documentation and/or other materials provided with the distribution. *
|
||||
* 3. The name of the author may not be used to endorse or promote products *
|
||||
* derived from this software without specific prior written permission. *
|
||||
* *
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR *
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES *
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. *
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, *
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT *
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, *
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY *
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT *
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF *
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef __NW_GTPV1U_PRIVATE_H__
|
||||
#define __NW_GTPV1U_PRIVATE_H__
|
||||
|
||||
#include "tree.h"
|
||||
#include "queue.h"
|
||||
|
||||
#include "NwTypes.h"
|
||||
#include "NwGtpv1uError.h"
|
||||
#include "NwGtpv1u.h"
|
||||
#include "NwGtpv1uMsg.h"
|
||||
|
||||
|
||||
/**
|
||||
* @file NwGtpv1uPrivate.h
|
||||
* @brief This header file contains nw-gtpv1u private definitions not to be
|
||||
* exposed to user application.
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define NW_GTPV1U_MALLOC(_stack, _size, _mem, _type) \
|
||||
do { \
|
||||
if(((NwGtpv1uStackT*)(_stack))->memMgr.memAlloc && ((NwGtpv1uStackT*)(_stack))->memMgr.memFree )\
|
||||
{ \
|
||||
_mem = (_type) ((NwGtpv1uStackT*) (_stack))->memMgr.memAlloc(((NwGtpv1uStackT*) (_stack))->memMgr.hMemMgr, _size, __FILE__, __LINE__);\
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
_mem = (_type) malloc (_size); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
/*--------------------------------------------------------------------------*
|
||||
* G T P U S T A C K O B J E C T T Y P E D E F I N I T I O N *
|
||||
*--------------------------------------------------------------------------*/
|
||||
|
||||
/*--------------------------------------------------------------------------*
|
||||
* GRPS Tunneling Protocol Stack Class Definition
|
||||
*--------------------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* gtpv1u stack class definition
|
||||
*/
|
||||
|
||||
typedef struct NwGtpv1uStack
|
||||
{
|
||||
NwU32T id;
|
||||
NwU32T seq;
|
||||
NwGtpv1uUlpEntityT ulp;
|
||||
NwGtpv1uUdpEntityT udp;
|
||||
NwGtpv1uMemMgrEntityT memMgr;
|
||||
NwGtpv1uTimerMgrEntityT tmrMgr;
|
||||
NwGtpv1uLogMgrEntityT logMgr;
|
||||
NwU32T logLevel;
|
||||
RB_HEAD( NwGtpv1uOutstandingTxSeqNumTrxnMap, NwGtpv1uTrxn) outstandingTxSeqNumMap;
|
||||
RB_HEAD( NwGtpv1uOutstandingRxSeqNumTrxnMap, NwGtpv1uTrxn) outstandingRxSeqNumMap;
|
||||
RB_HEAD(NwGtpv1uTunnelEndPointTMap, NwGtpv1uTunnelEndPoint) sessionMap;
|
||||
RB_HEAD(NwGtpv1uTunnelEndPointIdentifierMap, NwGtpv1uTunnelEndPoint) teidMap;
|
||||
} NwGtpv1uStackT;
|
||||
|
||||
/**
|
||||
* GTP Tunnel End Point class definition
|
||||
*/
|
||||
|
||||
typedef struct NwGtpv1uTunnelEndPoint
|
||||
{
|
||||
NwU32T teid; /**< Gtpu Tunnel End Point Identifier */
|
||||
NwU32T peerAddr; /**< Peer IP address for the session */
|
||||
NwGtpv1uStackT* pStack; /**< Pointer to the parent stack */
|
||||
NwGtpv1uUlpSessionHandleT hUlpSession; /**< ULP session handle for the session */
|
||||
RB_ENTRY (NwGtpv1uTunnelEndPoint) sessionMapRbtNode; /**< RB Tree Data Structure Node */
|
||||
struct NwGtpv1uTunnelEndPoint *next;
|
||||
} NwGtpv1uTunnelEndPointT;
|
||||
|
||||
|
||||
/*--------------------------------------------------------------------------*
|
||||
* Timeout Info Type Definition
|
||||
*--------------------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* gtpv1u timeout info
|
||||
*/
|
||||
|
||||
typedef struct NwGtpv1uTimeoutInfo
|
||||
{
|
||||
NwGtpv1uStackHandleT hStack;
|
||||
void* timeoutArg;
|
||||
NwGtpv1uRcT (*timeoutCallbackFunc)(void*);
|
||||
} NwGtpv1uTimeoutInfoT;
|
||||
|
||||
/**
|
||||
* Start a transaction response timer
|
||||
*
|
||||
* @param[in] thiz Pointer to stack instance
|
||||
* @param[in] timeoutArg Arg to timeout function.
|
||||
* @param[out] phTmr Pointer to timer handle.
|
||||
* @return NW_GTPV1U_OK on success.
|
||||
*/
|
||||
|
||||
NwGtpv1uRcT
|
||||
nwGtpStartTrxnPeerRspTimer(NwGtpv1uStackT* thiz, NwGtpv1uTimeoutInfoT* timeoutInfo, NwGtpv1uTimerHandleT* phTmr);
|
||||
|
||||
/**
|
||||
* Stop a transaction response timer
|
||||
*
|
||||
* @param[in] thiz Pointer to stack instance
|
||||
* @param[out] phTmr Pointer to timer handle.
|
||||
* @return NW_GTPV1U_OK on success.
|
||||
*/
|
||||
|
||||
NwGtpv1uRcT
|
||||
nwGtpStopTrxnPeerRspTimer(NwGtpv1uStackT* thiz, NwGtpv1uTimerHandleT* phTmr);
|
||||
|
||||
|
||||
#define NW_GTPV1U_MAX_MSG_LEN (4096) /**< Maximum supported gtpv1u packet length including header */
|
||||
|
||||
/**
|
||||
* NwGtpv1uMsgT holds gtpv1u messages to/from the peer.
|
||||
*/
|
||||
typedef struct NwGtpv1uMsg
|
||||
{
|
||||
NwU8T version;
|
||||
NwU8T protocolType;
|
||||
NwU8T extHdrFlag;
|
||||
NwU8T seqNumFlag;
|
||||
NwU16T npduNumFlag;
|
||||
NwU32T msgType;
|
||||
NwU16T msgLen;
|
||||
NwU32T teid;
|
||||
NwU16T seqNum;
|
||||
NwU8T npduNum;
|
||||
NwU8T nextExtHdrType;
|
||||
NwU8T msgBuf[NW_GTPV1U_MAX_MSG_LEN];
|
||||
struct NwGtpv1uMsg* next;
|
||||
} NwGtpv1uMsgT;
|
||||
|
||||
|
||||
/*--------------------------------------------------------------------------*
|
||||
* R6/R4 Transaction Context Type Definition
|
||||
*--------------------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* Transaction structure
|
||||
*/
|
||||
|
||||
typedef struct NwGtpv1uTrxn
|
||||
{
|
||||
NwU32T seqNum;
|
||||
NwU32T peerIp;
|
||||
NwU32T peerPort;
|
||||
NwU8T maxRetries;
|
||||
NwU8T t3Timer;
|
||||
NwGtpv1uTimerHandleT hRspTmr;
|
||||
NwGtpv1uTimeoutInfoT peerRspTimeoutInfo;
|
||||
NwGtpv1uStackT* pStack;
|
||||
NwGtpv1uTunnelEndPointT* pSession;
|
||||
NwU32T hUlpTrxn;
|
||||
NwGtpv1uMsgT* pMsg;
|
||||
RB_ENTRY (NwGtpv1uTrxn) outstandingTxSeqNumMapRbtNode; /**< RB Tree Data Structure Node */
|
||||
RB_ENTRY (NwGtpv1uTrxn) outstandingRxSeqNumMapRbtNode; /**< RB Tree Data Structure Node */
|
||||
struct NwGtpv1uTrxn* next;
|
||||
} NwGtpv1uTrxnT;
|
||||
|
||||
|
||||
/**
|
||||
* GTPv2 message header structure
|
||||
*/
|
||||
|
||||
#pragma pack(1)
|
||||
|
||||
typedef struct NwGtpv1uMsgHeader
|
||||
{
|
||||
NwU8T PN:1;
|
||||
NwU8T S:1;
|
||||
NwU8T E:1;
|
||||
NwU8T spare:1;
|
||||
NwU8T PT:1;
|
||||
NwU8T version:3;
|
||||
NwU8T msgType;
|
||||
NwU16T msgLength;
|
||||
NwU32T teid;
|
||||
} NwGtpv1uMsgHeaderT;
|
||||
|
||||
#pragma pack()
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __NW_GTPV1U_PRIVATE_H__ */
|
||||
/*--------------------------------------------------------------------------*
|
||||
* E N D O F F I L E *
|
||||
*--------------------------------------------------------------------------*/
|
||||
|
||||
@@ -0,0 +1,88 @@
|
||||
/*----------------------------------------------------------------------------*
|
||||
* *
|
||||
* n w - g t p v 2 u *
|
||||
* G P R S T u n n e l i n g P r o t o c o l v 2 u S t a c k *
|
||||
* *
|
||||
* *
|
||||
* Copyright (c) 2010-2011 Amit Chawre *
|
||||
* All rights reserved. *
|
||||
* *
|
||||
* Redistribution and use in source and binary forms, with or without *
|
||||
* modification, are permitted provided that the following conditions *
|
||||
* are met: *
|
||||
* *
|
||||
* 1. Redistributions of source code must retain the above copyright *
|
||||
* notice, this list of conditions and the following disclaimer. *
|
||||
* 2. Redistributions in binary form must reproduce the above copyright *
|
||||
* notice, this list of conditions and the following disclaimer in the *
|
||||
* documentation and/or other materials provided with the distribution. *
|
||||
* 3. The name of the author may not be used to endorse or promote products *
|
||||
* derived from this software without specific prior written permission. *
|
||||
* *
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR *
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES *
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. *
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, *
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT *
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, *
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY *
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT *
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF *
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @file NwGtpv1uTrxn.h
|
||||
* @author Amit Chawre
|
||||
* @brief
|
||||
*
|
||||
* This header file contains required definitions and functions
|
||||
* prototypes used by gtpv1u transactions.
|
||||
*
|
||||
**/
|
||||
|
||||
|
||||
#ifndef __NW_GTPV1U_TRXN_H__
|
||||
#define __NW_GTPV1U_TRXN_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
NwGtpv1uRcT
|
||||
nwGtpv1uTrxnNew( NW_IN NwGtpv1uStackT* thiz,
|
||||
NW_OUT NwGtpv1uTrxnT **ppTrxn);
|
||||
|
||||
|
||||
NwGtpv1uRcT
|
||||
nwGtpv1uTrxnWithSeqNew( NW_IN NwGtpv1uStackT* thiz,
|
||||
NW_IN NwU32T seqNum,
|
||||
NW_OUT NwGtpv1uTrxnT **ppTrxn);
|
||||
|
||||
NwGtpv1uRcT
|
||||
nwGtpv1uTrxnDelete( NW_INOUT NwGtpv1uTrxnT **ppTrxn);
|
||||
|
||||
NwGtpv1uRcT
|
||||
nwGtpv1uTrxnNew( NW_IN NwGtpv1uStackT* thiz,
|
||||
NW_OUT NwGtpv1uTrxnT **ppTrxn);
|
||||
|
||||
NwGtpv1uRcT
|
||||
nwGtpv1uTrxnDelete( NW_INOUT NwGtpv1uTrxnT **pthiz);
|
||||
|
||||
NwGtpv1uRcT
|
||||
nwGtpv1uTrxnCreateAndSendMsg( NW_IN NwGtpv1uStackT* thiz,
|
||||
NW_IN NwGtpv1uTrxnT *pTrxn,
|
||||
NW_IN NwU32T peerIp,
|
||||
NW_IN NwU32T peerPort,
|
||||
NW_IN NwGtpv1uMsgT *pMsg);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __NW_GTPV1U_TRXN_H__ */
|
||||
|
||||
/*--------------------------------------------------------------------------*
|
||||
* E N D O F F I L E *
|
||||
*--------------------------------------------------------------------------*/
|
||||
|
||||
@@ -0,0 +1,85 @@
|
||||
/*----------------------------------------------------------------------------*
|
||||
* *
|
||||
* n w - g t p v 2 u *
|
||||
* G P R S T u n n e l i n g P r o t o c o l v 2 u S t a c k *
|
||||
* *
|
||||
* *
|
||||
* Copyright (c) 2010-2011 Amit Chawre *
|
||||
* All rights reserved. *
|
||||
* *
|
||||
* Redistribution and use in source and binary forms, with or without *
|
||||
* modification, are permitted provided that the following conditions *
|
||||
* are met: *
|
||||
* *
|
||||
* 1. Redistributions of source code must retain the above copyright *
|
||||
* notice, this list of conditions and the following disclaimer. *
|
||||
* 2. Redistributions in binary form must reproduce the above copyright *
|
||||
* notice, this list of conditions and the following disclaimer in the *
|
||||
* documentation and/or other materials provided with the distribution. *
|
||||
* 3. The name of the author may not be used to endorse or promote products *
|
||||
* derived from this software without specific prior written permission. *
|
||||
* *
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR *
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES *
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. *
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, *
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT *
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, *
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY *
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT *
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF *
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "NwTypes.h"
|
||||
#include "NwUtils.h"
|
||||
#include "NwGtpv1uError.h"
|
||||
#include "NwGtpv1uPrivate.h"
|
||||
#include "NwGtpv1uMsg.h"
|
||||
#include "NwGtpv1u.h"
|
||||
#include "NwGtpv1uLog.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef __NW_GTPV1U_CONNECTION_H__
|
||||
#define __NW_GTPV1U_CONNECTION_H__
|
||||
|
||||
/**
|
||||
Constructor
|
||||
|
||||
@return Pointer to session on success, NULL n failure.
|
||||
*/
|
||||
|
||||
NwGtpv1uTunnelEndPointT*
|
||||
nwGtpTunnelEndPointNew(struct NwGtpv1uStack* pStack);
|
||||
|
||||
/**
|
||||
Destructor
|
||||
|
||||
@param[in] thiz: Pointer to session
|
||||
@return NW_GTPV1U_OK on success.
|
||||
*/
|
||||
|
||||
NwGtpv1uRcT
|
||||
nwGtpTunnelEndPointDestroy(struct NwGtpv1uStack* pStack, NwGtpv1uTunnelEndPointT* thiz);
|
||||
|
||||
NwGtpv1uRcT
|
||||
nwGtpSessionSendMsgApiToUlpEntity(NwGtpv1uTunnelEndPointT* thiz,
|
||||
NwGtpv1uMsgT *pMsg);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
/*--------------------------------------------------------------------------*
|
||||
* E N D O F F I L E *
|
||||
*--------------------------------------------------------------------------*/
|
||||
|
||||
@@ -0,0 +1,578 @@
|
||||
/*----------------------------------------------------------------------------*
|
||||
* *
|
||||
* n w - g t p v 2 u *
|
||||
* G P R S T u n n e l i n g P r o t o c o l v 2 u S t a c k *
|
||||
* *
|
||||
* *
|
||||
* Copyright (c) 2010-2011 Amit Chawre *
|
||||
* All rights reserved. *
|
||||
* *
|
||||
* Redistribution and use in source and binary forms, with or without *
|
||||
* modification, are permitted provided that the following conditions *
|
||||
* are met: *
|
||||
* *
|
||||
* 1. Redistributions of source code must retain the above copyright *
|
||||
* notice, this list of conditions and the following disclaimer. *
|
||||
* 2. Redistributions in binary form must reproduce the above copyright *
|
||||
* notice, this list of conditions and the following disclaimer in the *
|
||||
* documentation and/or other materials provided with the distribution. *
|
||||
* 3. The name of the author may not be used to endorse or promote products *
|
||||
* derived from this software without specific prior written permission. *
|
||||
* *
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR *
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES *
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. *
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, *
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT *
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, *
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY *
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT *
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF *
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef __NW_GTPV1U_H__
|
||||
#define __NW_GTPV1U_H__
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <arpa/inet.h>
|
||||
#include "NwTypes.h"
|
||||
#include "NwGtpv1uError.h"
|
||||
|
||||
|
||||
/**
|
||||
* @file NwGtpv1u.h
|
||||
* @author Amit Chawre
|
||||
* @brief
|
||||
*
|
||||
* This header file contains all required definitions and functions
|
||||
* prototypes for using nw-gtpv1u library.
|
||||
*
|
||||
**/
|
||||
|
||||
#define NW_GTPU_VERSION (0x01)
|
||||
#define NW_GTP_PROTOCOL_TYPE_GTP (0x01)
|
||||
#define NW_GTP_PROTOCOL_TYPE_GTP_PRIME (0x00)
|
||||
|
||||
/*--------------------------------------------------------------------------*
|
||||
* S H A R E D A P I M A C R O S *
|
||||
*--------------------------------------------------------------------------*/
|
||||
|
||||
#define NW_GTP_ECHO_REQ (1)
|
||||
#define NW_GTP_ECHO_RSP (2)
|
||||
#define NW_GTP_ERROR_INDICATION (26)
|
||||
#define NW_GTP_SUPPORTED_EXTENSION_HEADER_INDICATION (31)
|
||||
#define NW_GTP_END_MARKER (254)
|
||||
#define NW_GTP_GPDU (255)
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
* Opaque Gtpv2 Stack Handles
|
||||
*--------------------------------------------------------------------------*/
|
||||
|
||||
typedef NwPtrT NwGtpv1uStackHandleT; /**< Gtpv2 Stack Handle */
|
||||
typedef NwPtrT NwGtpv1uUlpHandleT; /**< Gtpv2 Stack Ulp Entity Handle */
|
||||
typedef NwPtrT NwGtpv1uUdpHandleT; /**< Gtpv2 Stack Udp Entity Handle */
|
||||
typedef NwPtrT NwGtpv1uMemMgrHandleT; /**< Gtpv2 Stack Mem Manager Handle */
|
||||
typedef NwPtrT NwGtpv1uTimerMgrHandleT; /**< Gtpv2 Stack Timer Manager Handle */
|
||||
typedef NwPtrT NwGtpv1uLogMgrHandleT; /**< Gtpv2 Stack Log Mnagaer Handle */
|
||||
typedef NwPtrT NwGtpv1uTimerHandleT; /**< Gtpv2 Stack Timer Handle */
|
||||
typedef NwPtrT NwGtpv1uMsgHandleT; /**< Gtpv2 Msg Handle */
|
||||
|
||||
typedef struct NwGtpv1uStackConfig
|
||||
{
|
||||
NwU16T udpSrcPort;
|
||||
} NwGtpv1uStackConfigT;
|
||||
|
||||
/*--------------------------------------------------------------------------*
|
||||
* S T A C K A P I D E F I N I T I O N S *
|
||||
*--------------------------------------------------------------------------*/
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
* Gtpv2 Stack ULP API type definitions
|
||||
*--------------------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* APIs types between ULP and Stack
|
||||
*/
|
||||
|
||||
typedef enum
|
||||
{
|
||||
/* APIs from ULP to stack */
|
||||
|
||||
NW_GTPV1U_ULP_API_CREATE_TUNNEL_ENDPOINT = 0x00000000, /**< Create a local teid context on stack */
|
||||
NW_GTPV1U_ULP_API_DESTROY_TUNNEL_ENDPOINT, /**< Delete a local teid context on stack */
|
||||
NW_GTPV1U_ULP_API_INITIAL_REQ, /**< Send a Initial Request over a session */
|
||||
NW_GTPV1U_ULP_API_TRIGGERED_REQ, /**< Send a Initial Request over a session */
|
||||
NW_GTPV1U_ULP_API_TRIGGERED_RSP, /**< Send a Trigger Response over a session */
|
||||
NW_GTPV1U_ULP_API_SEND_TPDU, /**< Send a T-PDU message over teid context */
|
||||
|
||||
/* APIs from stack to ULP */
|
||||
|
||||
NW_GTPV1U_ULP_API_RECV_TPDU, /**< Receive a gtpv1u T-PDU from stack */
|
||||
NW_GTPV1U_ULP_API_RECV_MSG, /**< Receive a gtpv1u message from stack */
|
||||
NW_GTPV1U_ULP_API_RSP_FAILURE, /**< Rsp failure for gtpv2 message from stack */
|
||||
|
||||
/* Do not add below this */
|
||||
|
||||
NW_GTPV1U_ULP_API_END = 0xFFFFFFFF,
|
||||
} NwGtpv1uUlpApiTypeT;
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
* Gtpv2 Stack API information elements definitions
|
||||
*--------------------------------------------------------------------------*/
|
||||
|
||||
typedef NwU32T NwGtpv1uStackSessionHandleT;/**< Gtpv2 Stack session Handle */
|
||||
typedef NwU8T NwGtpv1uMsgTypeT; /**< Gtpv2 Msg Type */
|
||||
typedef NwU32T NwGtpv1uTrxnHandleT; /**< Gtpv2 Transaction Handle */
|
||||
typedef NwU32T NwGtpv1uUlpTrxnHandleT; /**< Gtpv2 Ulp Transaction Handle */
|
||||
typedef NwU32T NwGtpv1uUlpSessionHandleT; /**< Gtpv2 Ulp session Handle */
|
||||
|
||||
/**
|
||||
* API information elements between ULP and Stack for
|
||||
* creating a session.
|
||||
*/
|
||||
|
||||
typedef struct
|
||||
{
|
||||
NW_IN NwU32T teid;
|
||||
NW_IN NwGtpv1uUlpSessionHandleT hUlpSession;
|
||||
NW_OUT NwGtpv1uStackSessionHandleT hStackSession;
|
||||
} NwGtpv1uCreateTunnelEndPointT;
|
||||
|
||||
/**
|
||||
* API information elements between ULP and Stack for
|
||||
* destroying a session.
|
||||
*/
|
||||
|
||||
typedef struct
|
||||
{
|
||||
NW_IN NwGtpv1uStackSessionHandleT hStackSessionHandle;
|
||||
} NwGtpv1uDestroyTunnelEndPointT;
|
||||
|
||||
/**
|
||||
* API information elements between ULP and Stack for
|
||||
* sending a Gtpv1u initial message.
|
||||
*/
|
||||
|
||||
typedef struct
|
||||
{
|
||||
NW_IN NwGtpv1uUlpTrxnHandleT hUlpTrxn;
|
||||
NW_IN NwU32T peerIp;
|
||||
NW_IN NwU32T peerPort;
|
||||
NW_IN NwU8T flags;
|
||||
NW_IN NwU32T teid;
|
||||
} NwGtpv1uInitialReqInfoT;
|
||||
|
||||
/**
|
||||
* API information elements between ULP and Stack for
|
||||
* sending a Gtpv1u triggered response message.
|
||||
*/
|
||||
|
||||
typedef struct
|
||||
{
|
||||
NW_IN NwGtpv1uUlpTrxnHandleT hUlpTrxn;
|
||||
NW_IN NwU32T peerIp;
|
||||
NW_IN NwU32T peerPort;
|
||||
NW_IN NwU8T flags;
|
||||
NW_IN NwU32T teid;
|
||||
NW_IN NwU32T seqNum;
|
||||
NW_IN NwGtpv1uMsgHandleT hMsg;
|
||||
} NwGtpv1uTriggeredRspInfoT;
|
||||
|
||||
/**
|
||||
* API information elements between ULP and Stack for
|
||||
* sending a Gtpv1u triggered request message.
|
||||
*/
|
||||
|
||||
typedef struct
|
||||
{
|
||||
NW_IN NwGtpv1uUlpTrxnHandleT hUlpTrxn;
|
||||
NW_IN NwU32T peerIp;
|
||||
NW_IN NwU32T peerPort;
|
||||
NW_IN NwU8T flags;
|
||||
NW_IN NwU32T teid;
|
||||
NW_IN NwU32T seqNum;
|
||||
NW_IN NwGtpv1uMsgHandleT hMsg;
|
||||
} NwGtpv1uTriggeredReqInfoT;
|
||||
|
||||
|
||||
/**
|
||||
* API information elements between ULP and Stack for
|
||||
* sending a Gtpv2 message over a session.
|
||||
*/
|
||||
|
||||
typedef struct
|
||||
{
|
||||
NW_IN NwU32T teid;
|
||||
NW_IN NwU32T ipAddr;
|
||||
NW_IN NwU8T flags;
|
||||
NW_IN NwGtpv1uMsgHandleT hMsg;
|
||||
} NwGtpv1uSendtoInfoT;
|
||||
|
||||
|
||||
/**
|
||||
* API information elements between ULP and Stack for
|
||||
* sending a Gtpv2 message over a session.
|
||||
*/
|
||||
|
||||
typedef struct
|
||||
{
|
||||
NW_OUT NwGtpv1uStackSessionHandleT hStackSessionHandle;
|
||||
NW_INOUT NwGtpv1uTrxnHandleT hTrxn;
|
||||
NW_IN NwGtpv1uUlpTrxnHandleT hUlpTrxn;
|
||||
NW_IN NwGtpv1uMsgTypeT msgType;
|
||||
NW_IN NwU8T flags;
|
||||
NW_IN NwGtpv1uMsgHandleT hMsg;
|
||||
} NwGtpv1uSendMsgInfoT;
|
||||
|
||||
/**
|
||||
* API information elements between ULP and Stack for
|
||||
* receiving a Gtpv2 message over a session from stack.
|
||||
*/
|
||||
|
||||
typedef struct
|
||||
{
|
||||
NW_IN NwGtpv1uUlpSessionHandleT hUlpSession;
|
||||
NW_IN NwGtpv1uUlpTrxnHandleT hUlpTrxn;
|
||||
NW_IN NwU32T teid;
|
||||
NW_IN NwU32T peerIp;
|
||||
NW_IN NwU32T peerPort;
|
||||
NW_IN NwU32T msgType; /**< Message type */
|
||||
NW_IN NwGtpv1uMsgHandleT hMsg; /**< Gtp Message handle */
|
||||
} NwGtpv1uRecvMsgInfoT;
|
||||
|
||||
/**
|
||||
* API information elements between ULP and Stack for
|
||||
* receiving a Gtpv2 message over a session from stack.
|
||||
*/
|
||||
|
||||
typedef struct
|
||||
{
|
||||
NW_IN NwGtpv1uUlpSessionHandleT hUlpSession;
|
||||
NW_IN NwGtpv1uTrxnHandleT hTrxn;
|
||||
} NwGtpv1uNackInfoT;
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
* Gtpv2 Stack API structure definition
|
||||
*--------------------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* API structure between ULP and Stack
|
||||
*/
|
||||
|
||||
typedef struct
|
||||
{
|
||||
NwGtpv1uUlpApiTypeT apiType;
|
||||
NwGtpv1uMsgHandleT hMsg;
|
||||
union
|
||||
{
|
||||
NwGtpv1uCreateTunnelEndPointT createTunnelEndPointInfo;
|
||||
NwGtpv1uDestroyTunnelEndPointT destroyTunnelEndPointInfo;
|
||||
NwGtpv1uInitialReqInfoT initialReqInfo;
|
||||
NwGtpv1uTriggeredRspInfoT triggeredRspInfo;
|
||||
NwGtpv1uTriggeredReqInfoT triggeredReqInfo;
|
||||
NwGtpv1uSendtoInfoT sendtoInfo;
|
||||
NwGtpv1uSendMsgInfoT sendMsgInfo;
|
||||
NwGtpv1uRecvMsgInfoT recvMsgInfo;
|
||||
NwGtpv1uNackInfoT nackMsgInfo;
|
||||
} apiInfo;
|
||||
} NwGtpv1uUlpApiT;
|
||||
|
||||
|
||||
/*--------------------------------------------------------------------------*
|
||||
* S T A C K E N T I T I E S D E F I N I T I O N S *
|
||||
*--------------------------------------------------------------------------*/
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
* ULP Entity Definitions
|
||||
*--------------------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* Gtpv2 ULP entity definition
|
||||
*/
|
||||
|
||||
typedef struct
|
||||
{
|
||||
NwGtpv1uUlpHandleT hUlp;
|
||||
NwGtpv1uRcT (*ulpReqCallback) ( NW_IN NwGtpv1uUlpHandleT hUlp,
|
||||
NW_IN NwGtpv1uUlpApiT *pUlpApi);
|
||||
} NwGtpv1uUlpEntityT;
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
* UDP Entity Definitions
|
||||
*--------------------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* Gtpv2 UDP entity definition
|
||||
*/
|
||||
|
||||
typedef struct
|
||||
{
|
||||
NwGtpv1uUdpHandleT hUdp;
|
||||
NwGtpv1uRcT (*udpDataReqCallback) ( NW_IN NwGtpv1uUdpHandleT udpHandle,
|
||||
NW_IN NwU8T* dataBuf,
|
||||
NW_IN NwU32T dataSize,
|
||||
NW_IN NwU32T peerIP,
|
||||
NW_IN NwU16T peerPort);
|
||||
} NwGtpv1uUdpEntityT;
|
||||
|
||||
/**
|
||||
* Gtpv1u Memory Manager entity definition
|
||||
*/
|
||||
|
||||
typedef struct
|
||||
{
|
||||
NwGtpv1uMemMgrHandleT hMemMgr;
|
||||
void* (*memAlloc)( NW_IN NwGtpv1uMemMgrHandleT hMemMgr,
|
||||
NW_IN NwU32T memSize,
|
||||
NW_IN NwCharT* fileName,
|
||||
NW_IN NwU32T lineNumber);
|
||||
|
||||
void (*memFree) ( NW_IN NwGtpv1uMemMgrHandleT hMemMgr,
|
||||
NW_IN void* hMem,
|
||||
NW_IN NwCharT* fileName,
|
||||
NW_IN NwU32T lineNumber);
|
||||
} NwGtpv1uMemMgrEntityT;
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
* Timer Entity Definitions
|
||||
*--------------------------------------------------------------------------*/
|
||||
|
||||
#define NW_GTPV1U_TMR_TYPE_ONE_SHOT (0)
|
||||
#define NW_GTPV1U_TMR_TYPE_REPETITIVE (1)
|
||||
|
||||
/**
|
||||
* Gtpv2 Timer Manager entity definition
|
||||
*/
|
||||
|
||||
typedef struct
|
||||
{
|
||||
NwGtpv1uTimerMgrHandleT tmrMgrHandle;
|
||||
NwGtpv1uRcT (*tmrStartCallback)( NW_IN NwGtpv1uTimerMgrHandleT tmrMgrHandle,
|
||||
NW_IN NwU32T timeoutSecs,
|
||||
NW_IN NwU32T timeoutUsec,
|
||||
NW_IN NwU32T tmrType,
|
||||
NW_IN void* tmrArg,
|
||||
NW_OUT NwGtpv1uTimerHandleT* tmrHandle);
|
||||
|
||||
NwGtpv1uRcT (*tmrStopCallback) ( NW_IN NwGtpv1uTimerMgrHandleT tmrMgrHandle,
|
||||
NW_IN NwGtpv1uTimerHandleT tmrHandle);
|
||||
} NwGtpv1uTimerMgrEntityT;
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
* Log Entity Definitions
|
||||
*--------------------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* Gtpv2 Log manager entity definition
|
||||
*/
|
||||
|
||||
typedef struct
|
||||
{
|
||||
NwGtpv1uLogMgrHandleT logMgrHandle;
|
||||
NwGtpv1uRcT (*logReqCallback) (NW_IN NwGtpv1uLogMgrHandleT logMgrHandle,
|
||||
NW_IN NwU32T logLevel,
|
||||
NW_IN NwCharT* file,
|
||||
NW_IN NwU32T line,
|
||||
NW_IN NwCharT* logStr);
|
||||
} NwGtpv1uLogMgrEntityT;
|
||||
|
||||
|
||||
/*--------------------------------------------------------------------------*
|
||||
* P U B L I C F U N C T I O N S *
|
||||
*--------------------------------------------------------------------------*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
* Constructor
|
||||
*--------------------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
Initialize the nw-gtpv1u stack.
|
||||
|
||||
@param[in,out] phGtpv1uStackHandle : Pointer to stack handle
|
||||
*/
|
||||
|
||||
NwGtpv1uRcT
|
||||
nwGtpv1uInitialize( NW_INOUT NwGtpv1uStackHandleT* phGtpv1uStackHandle);
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
* Destructor
|
||||
*--------------------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
Destroy the nw-gtpv1u stack.
|
||||
|
||||
@param[in] hGtpv1uStackHandle : Stack handle
|
||||
*/
|
||||
|
||||
NwGtpv1uRcT
|
||||
nwGtpv1uFinalize( NW_IN NwGtpv1uStackHandleT hGtpv1uStackHandle);
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
* Configuration Get/Set Operations
|
||||
*--------------------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
Set Configuration for the nw-gtpv1u stack.
|
||||
|
||||
@param[in,out] phGtpv1uStackHandle : Pointer to stack handle
|
||||
*/
|
||||
|
||||
NwGtpv1uRcT
|
||||
NwGtpv1uConfigSet( NW_IN NwGtpv1uStackHandleT* phGtpv1uStackHandle, NW_IN NwGtpv1uStackConfigT* pConfig);
|
||||
|
||||
/**
|
||||
Get Configuration for the nw-gtpv1u stack.
|
||||
|
||||
@param[in,out] phGtpv1uStackHandle : Pointer to stack handle
|
||||
*/
|
||||
|
||||
NwGtpv1uRcT
|
||||
NwGtpv1uConfigGet( NW_IN NwGtpv1uStackHandleT* phGtpv1uStackHandle, NW_OUT NwGtpv1uStackConfigT* pConfig);
|
||||
|
||||
/**
|
||||
Set ULP entity for the stack.
|
||||
|
||||
@param[in] hGtpv1uStackHandle : Stack handle
|
||||
@param[in] pUlpEntity : Pointer to ULP entity.
|
||||
@return NW_GTPV1U_OK on success.
|
||||
*/
|
||||
|
||||
NwGtpv1uRcT
|
||||
nwGtpv1uSetUlpEntity( NW_IN NwGtpv1uStackHandleT hGtpv1uStackHandle,
|
||||
NW_IN NwGtpv1uUlpEntityT* pUlpEntity);
|
||||
|
||||
/**
|
||||
Set UDP entity for the stack.
|
||||
|
||||
@param[in] hGtpv1uStackHandle : Stack handle
|
||||
@param[in] pUdpEntity : Pointer to UDP entity.
|
||||
@return NW_GTPV1U_OK on success.
|
||||
*/
|
||||
|
||||
NwGtpv1uRcT
|
||||
nwGtpv1uSetUdpEntity( NW_IN NwGtpv1uStackHandleT hGtpv1uStackHandle,
|
||||
NW_IN NwGtpv1uUdpEntityT* pUdpEntity);
|
||||
|
||||
/**
|
||||
Set MemMgr entity for the stack.
|
||||
|
||||
@param[in] hGtpv1uStackHandle : Stack handle
|
||||
@param[in] pMemMgr : Pointer to Memory Manager.
|
||||
@return NW_GTPV1U_OK on success.
|
||||
*/
|
||||
|
||||
NwGtpv1uRcT
|
||||
nwGtpv1uSetMemMgrEntity( NW_IN NwGtpv1uStackHandleT hGtpv1uStackHandle,
|
||||
NW_IN NwGtpv1uMemMgrEntityT* pMemMgr);
|
||||
|
||||
|
||||
/**
|
||||
Set TmrMgr entity for the stack.
|
||||
|
||||
@param[in] hGtpv1uStackHandle : Stack handle
|
||||
@param[in] pTmrMgr : Pointer to Timer Manager.
|
||||
@return NW_GTPV1U_OK on success.
|
||||
*/
|
||||
|
||||
NwGtpv1uRcT
|
||||
nwGtpv1uSetTimerMgrEntity( NW_IN NwGtpv1uStackHandleT hGtpv1uStackHandle,
|
||||
NW_IN NwGtpv1uTimerMgrEntityT* pTmrMgr);
|
||||
|
||||
/**
|
||||
Set LogMgr entity for the stack.
|
||||
|
||||
@param[in] hGtpv1uStackHandle : Stack handle
|
||||
@param[in] pLogMgr : Pointer to Log Manager.
|
||||
@return NW_GTPV1U_OK on success.
|
||||
*/
|
||||
|
||||
NwGtpv1uRcT
|
||||
nwGtpv1uSetLogMgrEntity( NW_IN NwGtpv1uStackHandleT hGtpv1uStackHandle,
|
||||
NW_IN NwGtpv1uLogMgrEntityT* pLogMgr);
|
||||
|
||||
/**
|
||||
Set log level for the stack.
|
||||
|
||||
@param[in] hGtpv1uStackHandle : Stack handle
|
||||
@param[in] logLevel : Log level.
|
||||
@return NW_GTPV1U_OK on success.
|
||||
*/
|
||||
|
||||
NwGtpv1uRcT
|
||||
nwGtpv1uSetLogLevel( NW_IN NwGtpv1uStackHandleT hGtpuStackHandle,
|
||||
NW_IN NwU32T logLevel);
|
||||
/*---------------------------------------------------------------------------
|
||||
* Process Request from Udp Layer
|
||||
*--------------------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
Process Data Request from UDP entity.
|
||||
|
||||
@param[in] hGtpv1uStackHandle : Stack handle
|
||||
@param[in] udpData : Pointer to received UDP data.
|
||||
@param[in] udpDataLen : Received data length.
|
||||
@param[in] dstPort : Received on port.
|
||||
@param[in] from : Received from peer information.
|
||||
@return NW_GTPV1U_OK on success.
|
||||
*/
|
||||
|
||||
NwGtpv1uRcT
|
||||
nwGtpv1uProcessUdpReq( NW_IN NwGtpv1uStackHandleT hGtpv1uStackHandle,
|
||||
NW_IN NwU8T* udpData,
|
||||
NW_IN NwU32T udpDataLen,
|
||||
NW_IN NwU16T peerPort,
|
||||
NW_IN NwU32T peerIP);
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
* Process Request from Upper Layer
|
||||
*--------------------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
Process Request from ULP entity.
|
||||
|
||||
@param[in] hGtpv1uStackHandle : Stack handle
|
||||
@param[in] pLogMgr : Pointer to Ulp Req.
|
||||
@return NW_GTPV1U_OK on success.
|
||||
*/
|
||||
|
||||
NwGtpv1uRcT
|
||||
nwGtpv1uProcessUlpReq( NW_IN NwGtpv1uStackHandleT hGtpv1uStackHandle,
|
||||
NW_IN NwGtpv1uUlpApiT *ulpReq);
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
* Process Timer timeout Request from Timer Manager
|
||||
*--------------------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
Process Timer timeout Request from Timer Manager
|
||||
|
||||
@param[in] pLogMgr : Pointer timeout arguments.
|
||||
@return NW_GTPV1U_OK on success.
|
||||
*/
|
||||
|
||||
NwGtpv1uRcT
|
||||
nwGtpv1uProcessTimeout( NW_IN void* timeoutArg);
|
||||
|
||||
NwGtpv1uRcT
|
||||
nwGtpv1uPeerRspTimeout(void* arg);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __NW_GTPV1U_H__ */
|
||||
|
||||
/*--------------------------------------------------------------------------*
|
||||
* E N D O F F I L E *
|
||||
*--------------------------------------------------------------------------*/
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
/*----------------------------------------------------------------------------*
|
||||
* *
|
||||
* n w - g t p v 2 c *
|
||||
* G P R S T u n n e l i n g P r o t o c o l v 2 c S t a c k *
|
||||
* *
|
||||
* *
|
||||
* Copyright (c) 2010-2011 Amit Chawre *
|
||||
* All rights reserved. *
|
||||
* *
|
||||
* Redistribution and use in source and binary forms, with or without *
|
||||
* modification, are permitted provided that the following conditions *
|
||||
* are met: *
|
||||
* *
|
||||
* 1. Redistributions of source code must retain the above copyright *
|
||||
* notice, this list of conditions and the following disclaimer. *
|
||||
* 2. Redistributions in binary form must reproduce the above copyright *
|
||||
* notice, this list of conditions and the following disclaimer in the *
|
||||
* documentation and/or other materials provided with the distribution. *
|
||||
* 3. The name of the author may not be used to endorse or promote products *
|
||||
* derived from this software without specific prior written permission. *
|
||||
* *
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR *
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES *
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. *
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, *
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT *
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, *
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY *
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT *
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF *
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
#ifndef __NW_GTPV1U_ERROR_H__
|
||||
#define __NW_GTPV1U_ERROR_H__
|
||||
|
||||
/**
|
||||
* @file NwGtpv1uError.h
|
||||
* @brief This header file contains return error code type definitions.
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef enum {
|
||||
|
||||
NW_GTPV1U_OK = 0x00000000,
|
||||
NW_GTPV1U_MANDATORY_IE_DUPLICATE,
|
||||
NW_GTPV1U_MANDATORY_IE_MISSING,
|
||||
NW_GTPV1U_MSG_MALFORMED,
|
||||
NW_GTPV1U_FAILURE = 0xFFFFFFFE
|
||||
} NwGtpv1uRcT;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __NW_GTPV1U_ERROR_H__*/
|
||||
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
/*----------------------------------------------------------------------------*
|
||||
* *
|
||||
* n w - g t p v 2 u *
|
||||
* G P R S T u n n e l i n g P r o t o c o l v 2 u S t a c k *
|
||||
* *
|
||||
* *
|
||||
* Copyright (c) 2010-2011 Amit Chawre *
|
||||
* All rights reserved. *
|
||||
* *
|
||||
* Redistribution and use in source and binary forms, with or without *
|
||||
* modification, are permitted provided that the following conditions *
|
||||
* are met: *
|
||||
* *
|
||||
* 1. Redistributions of source code must retain the above copyright *
|
||||
* notice, this list of conditions and the following disclaimer. *
|
||||
* 2. Redistributions in binary form must reproduce the above copyright *
|
||||
* notice, this list of conditions and the following disclaimer in the *
|
||||
* documentation and/or other materials provided with the distribution. *
|
||||
* 3. The name of the author may not be used to endorse or promote products *
|
||||
* derived from this software without specific prior written permission. *
|
||||
* *
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR *
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES *
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. *
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, *
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT *
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, *
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY *
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT *
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF *
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @file NwGtpv1uIe.h
|
||||
* @brief This header file contains Information Element definitions for GTPv1u
|
||||
* as per 3GPP TS 29281-930.
|
||||
*/
|
||||
|
||||
#ifndef __NW_GTPV1U_IE_H__
|
||||
#define __NW_GTPV1U_IE_H__
|
||||
|
||||
/*--------------------------------------------------------------------------*
|
||||
* G T P V 2 U I E T Y P E M A C R O D E F I N I T I O N S *
|
||||
*--------------------------------------------------------------------------*/
|
||||
|
||||
#define NW_GTPV1U_IE_RECOVERY (14)
|
||||
#define NW_GTPV1U_IE_TEID_DATA_I (15)
|
||||
#define NW_GTPV1U_IE_GSN_ADDRESS (133)
|
||||
#define NW_GTPV1U_IE_EXT_HDR_TYPE_LIST (141)
|
||||
#define NW_GTPV1U_IE_PRIVATE_EXTENSION (255)
|
||||
|
||||
|
||||
/*--------------------------------------------------------------------------*
|
||||
* G T P V 2 U C A U S E V A L U E D E F I N I T I O N S *
|
||||
*--------------------------------------------------------------------------*/
|
||||
|
||||
#define NW_GTPV1U_CAUSE_REQUEST_ACCEPTED (16)
|
||||
#define NW_GTPV1U_CAUSE_MANDATORY_IE_MISSING (70)
|
||||
|
||||
#endif /* __NW_GTPV1U_IE_H__ */
|
||||
|
||||
/*--------------------------------------------------------------------------*
|
||||
* E N D O F F I L E *
|
||||
*--------------------------------------------------------------------------*/
|
||||
|
||||
@@ -0,0 +1,320 @@
|
||||
/*----------------------------------------------------------------------------*
|
||||
* *
|
||||
* n w - g t p v 2 u *
|
||||
* G P R S T u n n e l i n g P r o t o c o l v 2 u S t a c k *
|
||||
* *
|
||||
* *
|
||||
* Copyright (c) 2010-2011 Amit Chawre *
|
||||
* All rights reserved. *
|
||||
* *
|
||||
* Redistribution and use in source and binary forms, with or without *
|
||||
* modification, are permitted provided that the following conditions *
|
||||
* are met: *
|
||||
* *
|
||||
* 1. Redistributions of source code must retain the above copyright *
|
||||
* notice, this list of conditions and the following disclaimer. *
|
||||
* 2. Redistributions in binary form must reproduce the above copyright *
|
||||
* notice, this list of conditions and the following disclaimer in the *
|
||||
* documentation and/or other materials provided with the distribution. *
|
||||
* 3. The name of the author may not be used to endorse or promote products *
|
||||
* derived from this software without specific prior written permission. *
|
||||
* *
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR *
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES *
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. *
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, *
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT *
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, *
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY *
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT *
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF *
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef __NW_GTPV1U_MSG_H__
|
||||
#define __NW_GTPV1U_MSG_H__
|
||||
|
||||
#include "NwTypes.h"
|
||||
#include "NwGtpv1u.h"
|
||||
|
||||
/**
|
||||
* @file NwGtpv1uMsg.h
|
||||
* @brief This file defines APIs for to build new outgoing gtpv1u messages and to parse incoming messages.
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*--------------------------------------------------------------------------*
|
||||
* G T P V 2 C I E D A T A - T Y P E D E F I N I T I O N S *
|
||||
*--------------------------------------------------------------------------*/
|
||||
|
||||
#pragma pack(1)
|
||||
|
||||
typedef struct NwGtpv1uIeTv1
|
||||
{
|
||||
NwU8T t;
|
||||
NwU8T v;
|
||||
} NwGtpv1uIeTv1T;
|
||||
|
||||
typedef struct NwGtpv1uIeTv2
|
||||
{
|
||||
NwU8T t;
|
||||
NwU8T v;
|
||||
} NwGtpv1uIeTv2T;
|
||||
|
||||
typedef struct NwGtpv1uIeTv4
|
||||
{
|
||||
NwU8T t;
|
||||
NwU32T v;
|
||||
} NwGtpv1uIeTv4T;
|
||||
|
||||
typedef struct NwGtpv1uIeTlv
|
||||
{
|
||||
NwU8T t;
|
||||
NwU16T l;
|
||||
} NwGtpv1uIeTlvT;
|
||||
|
||||
#pragma pack()
|
||||
|
||||
|
||||
/**
|
||||
* Allocate a GPDU gtpv1u message.
|
||||
*
|
||||
* @param[in] hGtpuStackHandle : gtpv1u stack handle.
|
||||
* @param[in] teidPresent : TEID is present flag.
|
||||
* @param[in] teid : TEID for this message.
|
||||
* @param[in] seqNum : Sequence number for this message.
|
||||
* @param[out] phMsg : Pointer to message handle.
|
||||
*/
|
||||
|
||||
NwGtpv1uRcT
|
||||
nwGtpv1uMsgNew( NW_IN NwGtpv1uStackHandleT hGtpuStackHandle,
|
||||
NW_IN NwU8T seqNumFlag,
|
||||
NW_IN NwU8T npduNumFlag,
|
||||
NW_IN NwU8T extHdrFlag,
|
||||
NW_IN NwU8T msgType,
|
||||
NW_IN NwU8T teid,
|
||||
NW_IN NwU16T seqNum,
|
||||
NW_IN NwU8T npduNum,
|
||||
NW_IN NwU8T nextExtHeader,
|
||||
NW_OUT NwGtpv1uMsgHandleT *phMsg);
|
||||
|
||||
|
||||
/**
|
||||
* Allocate a gtpv1u message.
|
||||
*
|
||||
* @param[in] hGtpuStackHandle : gtpv1u stack handle.
|
||||
* @param[in] teid : TEID for this message.
|
||||
* @param[in] seqNumFlag : Sequence number flag for this message.
|
||||
* @param[in] seqNum : Sequence number for this message.
|
||||
* @param[in] pTpdu: T-PDU for this message.
|
||||
* @param[in] tpduLength: T-PDU length for this message.
|
||||
* @param[out] phMsg : Pointer to message handle.
|
||||
*/
|
||||
|
||||
NwGtpv1uRcT
|
||||
nwGtpv1uGpduMsgNew( NW_IN NwGtpv1uStackHandleT hGtpuStackHandle,
|
||||
NW_IN NwU32T teid,
|
||||
NW_IN NwU8T seqNumFlag,
|
||||
NW_IN NwU16T seqNum,
|
||||
NW_IN NwU8T* tpdu,
|
||||
NW_IN NwU16T tpduLength,
|
||||
NW_OUT NwGtpv1uMsgHandleT *phMsg);
|
||||
|
||||
/**
|
||||
* Allocate a gtpv1u message from another gtpv1u message.
|
||||
*
|
||||
* @param[in] hGtpuStackHandle : gtpv1u stack handle.
|
||||
* @param[out] hMsg : Handle to input message.
|
||||
* @param[out] phMsg : Pointer to message handle.
|
||||
*/
|
||||
|
||||
NwGtpv1uRcT
|
||||
nwGtpv1uMsgFromMsgNew( NW_IN NwGtpv1uStackHandleT hGtpuStackHandle,
|
||||
NW_IN NwGtpv1uMsgHandleT hMsg,
|
||||
NW_OUT NwGtpv1uMsgHandleT *phMsg);
|
||||
/**
|
||||
* Allocate a gtpv1u message from data buffer.
|
||||
*
|
||||
* @param[in] hGtpuStackHandle : gtpv1u stack handle.
|
||||
* @param[in] pBuf: Buffer to be copied in this message.
|
||||
* @param[in] bufLen: Buffer length to be copied in this message.
|
||||
* @param[out] phMsg : Pointer to message handle.
|
||||
*/
|
||||
|
||||
NwGtpv1uRcT
|
||||
nwGtpv1uMsgFromBufferNew( NW_IN NwGtpv1uStackHandleT hGtpuStackHandle,
|
||||
NW_IN NwU8T* pBuf,
|
||||
NW_IN NwU32T bufLen,
|
||||
NW_OUT NwGtpv1uMsgHandleT *phMsg);
|
||||
|
||||
/**
|
||||
* Free a gtpv1u message.
|
||||
*
|
||||
* @param[in] hGtpuStackHandle : gtpv1u stack handle.
|
||||
* @param[in] hMsg : Message handle.
|
||||
*/
|
||||
|
||||
NwGtpv1uRcT
|
||||
nwGtpv1uMsgDelete( NW_IN NwGtpv1uStackHandleT hGtpuStackHandle,
|
||||
NW_IN NwGtpv1uMsgHandleT hMsg);
|
||||
|
||||
/**
|
||||
* Set TEID for gtpv1u message.
|
||||
*
|
||||
* @param[in] hMsg : Message handle.
|
||||
* @param[in] teid: TEID value.
|
||||
*/
|
||||
|
||||
NwGtpv1uRcT
|
||||
nwGtpv1uMsgSetTeid(NW_IN NwGtpv1uMsgHandleT hMsg, NwU32T teid);
|
||||
|
||||
/**
|
||||
* Set TEID present flag for gtpv1u message.
|
||||
*
|
||||
* @param[in] hMsg : Message handle.
|
||||
* @param[in] teidPesent: Flag boolean value.
|
||||
*/
|
||||
|
||||
NwGtpv1uRcT
|
||||
nwGtpv1uMsgSetTeidPresent(NW_IN NwGtpv1uMsgHandleT hMsg, NwBoolT teidPresent);
|
||||
|
||||
/**
|
||||
* Set sequence for gtpv1u message.
|
||||
*
|
||||
* @param[in] hMsg : Message handle.
|
||||
* @param[in] seqNum: Flag boolean value.
|
||||
*/
|
||||
|
||||
NwGtpv1uRcT
|
||||
nwGtpv1uMsgSetSeqNumber(NW_IN NwGtpv1uMsgHandleT hMsg, NwU32T seqNum);
|
||||
|
||||
/**
|
||||
* Get TEID present for gtpv1u message.
|
||||
*
|
||||
* @param[in] hMsg : Message handle.
|
||||
*/
|
||||
|
||||
NwU32T
|
||||
nwGtpv1uMsgGetTeid(NW_IN NwGtpv1uMsgHandleT hMsg);
|
||||
|
||||
/**
|
||||
* Get TEID present for gtpv1u message.
|
||||
*
|
||||
* @param[in] hMsg : Message handle.
|
||||
*/
|
||||
|
||||
NwBoolT
|
||||
nwGtpv1uMsgGetTeidPresent(NW_IN NwGtpv1uMsgHandleT hMsg);
|
||||
|
||||
/**
|
||||
* Get sequence number for gtpv1u message.
|
||||
*
|
||||
* @param[in] hMsg : Message handle.
|
||||
*/
|
||||
|
||||
NwU32T
|
||||
nwGtpv1uMsgGetSeqNumber(NW_IN NwGtpv1uMsgHandleT hMsg);
|
||||
|
||||
/**
|
||||
* Get tpdu for gtpv1u message.
|
||||
*
|
||||
* @param[in] hMsg : Message handle.
|
||||
* @param[inout] pTpduBuf : Buffer to copy the T-PDU.
|
||||
* @param[out] hMsg : T-PDU length.
|
||||
*/
|
||||
|
||||
NwU32T
|
||||
nwGtpv1uMsgGetTpdu(NW_IN NwGtpv1uMsgHandleT hMsg, NwU8T* pTpduBuf, NwU32T* pTpduLength);
|
||||
|
||||
NwU8T*
|
||||
nwGtpv1uMsgGetTpduHandle(NW_IN NwGtpv1uMsgHandleT hMsg);
|
||||
|
||||
NwU32T
|
||||
nwGtpv1uMsgGetTpduLength(NW_IN NwGtpv1uMsgHandleT hMsg);
|
||||
|
||||
/**
|
||||
* Add a gtpv1u information element of length 1 to gtpv1u mesasge.
|
||||
*
|
||||
* @param[in] hMsg : Handle to gtpv1u message.
|
||||
* @param[in] type : IE type.
|
||||
* @param[in] value : IE value.
|
||||
*/
|
||||
|
||||
NwGtpv1uRcT
|
||||
nwGtpv1uMsgAddIeTV1(NW_IN NwGtpv1uMsgHandleT hMsg,
|
||||
NW_IN NwU8T type,
|
||||
NW_IN NwU8T value);
|
||||
|
||||
|
||||
/**
|
||||
* Add a gtpv1u information element of length 2 to gtpv1u mesasge.
|
||||
*
|
||||
* @param[in] hMsg : Handle to gtpv1u message.
|
||||
* @param[in] type : IE type.
|
||||
* @param[in] value : IE value.
|
||||
*/
|
||||
|
||||
NwGtpv1uRcT
|
||||
nwGtpv1uMsgAddIeTV2(NW_IN NwGtpv1uMsgHandleT hMsg,
|
||||
NW_IN NwU8T type,
|
||||
NW_IN NwU16T length,
|
||||
NW_IN NwU16T value);
|
||||
|
||||
|
||||
/**
|
||||
* Add a gtpv1u information element of length 4 to gtpv1u mesasge.
|
||||
*
|
||||
* @param[in] hMsg : Handle to gtpv1u message.
|
||||
* @param[in] type : IE type.
|
||||
* @param[in] value : IE value.
|
||||
*/
|
||||
|
||||
NwGtpv1uRcT
|
||||
nwGtpv1uMsgAddIeTV4(NW_IN NwGtpv1uMsgHandleT hMsg,
|
||||
NW_IN NwU8T type,
|
||||
NW_IN NwU16T length,
|
||||
NW_IN NwU32T value);
|
||||
|
||||
|
||||
/**
|
||||
* Add a gtpv1u information element of variable length to gtpv1u mesasge.
|
||||
*
|
||||
* @param[in] hMsg : Handle to gtpv1u message.
|
||||
* @param[in] type : IE type.
|
||||
* @param[in] length : IE length.
|
||||
* @param[in] value : IE value.
|
||||
*/
|
||||
|
||||
NwGtpv1uRcT
|
||||
nwGtpv1uMsgAddIe(NW_IN NwGtpv1uMsgHandleT hMsg,
|
||||
NW_IN NwU8T type,
|
||||
NW_IN NwU16T length,
|
||||
NW_IN NwU8T* pVal);
|
||||
|
||||
/**
|
||||
* Dump the contents of gtpv1u mesasge.
|
||||
*
|
||||
* @param[in] hMsg : Handle to gtpv1u message.
|
||||
* @param[in] fp: Pointer to output file.
|
||||
*/
|
||||
|
||||
NwGtpv1uRcT
|
||||
nwGtpv1uMsgHexDump(NwGtpv1uMsgHandleT hMsg, FILE* fp);
|
||||
|
||||
NwU32T
|
||||
nwGtpv1uMsgGetMsgType(NW_IN NwGtpv1uMsgHandleT hMsg);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __NW_TYPES_H__ */
|
||||
|
||||
|
||||
/*--------------------------------------------------------------------------*
|
||||
* E N D O F F I L E *
|
||||
*--------------------------------------------------------------------------*/
|
||||
|
||||
@@ -0,0 +1,88 @@
|
||||
/*----------------------------------------------------------------------------*
|
||||
* *
|
||||
* n w - g t p v 2 c *
|
||||
* G P R S T u n n e l i n g P r o t o c o l v 2 c S t a c k *
|
||||
* *
|
||||
* *
|
||||
* Copyright (c) 2010-2011 Amit Chawre *
|
||||
* All rights reserved. *
|
||||
* *
|
||||
* Redistribution and use in source and binary forms, with or without *
|
||||
* modification, are permitted provided that the following conditions *
|
||||
* are met: *
|
||||
* *
|
||||
* 1. Redistributions of source code must retain the above copyright *
|
||||
* notice, this list of conditions and the following disclaimer. *
|
||||
* 2. Redistributions in binary form must reproduce the above copyright *
|
||||
* notice, this list of conditions and the following disclaimer in the *
|
||||
* documentation and/or other materials provided with the distribution. *
|
||||
* 3. The name of the author may not be used to endorse or promote products *
|
||||
* derived from this software without specific prior written permission. *
|
||||
* *
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR *
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES *
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. *
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, *
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT *
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, *
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY *
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT *
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF *
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
#ifndef __NW_LOG_H__
|
||||
#define __NW_LOG_H__
|
||||
|
||||
#include <libgen.h>
|
||||
|
||||
#include "NwTypes.h"
|
||||
|
||||
/**
|
||||
* @file NwLog.h
|
||||
* @brief This header file contains global shared logging definitions.
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
* Log Level Definitions
|
||||
*--------------------------------------------------------------------------*/
|
||||
|
||||
#define NW_LOG_LEVEL_EMER (0) /**< system is unusable */
|
||||
#define NW_LOG_LEVEL_ALER (1) /**< action must be taken immediately*/
|
||||
#define NW_LOG_LEVEL_CRIT (2) /**< critical conditions */
|
||||
#define NW_LOG_LEVEL_ERRO (3) /**< error conditions */
|
||||
#define NW_LOG_LEVEL_WARN (4) /**< warning conditions */
|
||||
#define NW_LOG_LEVEL_NOTI (5) /**< normal but signification condition */
|
||||
#define NW_LOG_LEVEL_INFO (6) /**< informational */
|
||||
#define NW_LOG_LEVEL_DEBG (7) /**< debug-level messages */
|
||||
|
||||
// static
|
||||
// NwCharT* gLogLevelStr[] = {"EMER", "ALER", "CRIT", "ERRO", "WARN", "NOTI", "INFO", "DEBG"};
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
* IPv4 logging macros
|
||||
*--------------------------------------------------------------------------*/
|
||||
#define NW_IPV4_ADDR "%u.%u.%u.%u"
|
||||
#define NW_IPV4_ADDR_FORMAT(__addr) (NwU8T)((__addr) & 0x000000ff), \
|
||||
(NwU8T)(((__addr) & 0x0000ff00) >> 8 ), \
|
||||
(NwU8T)(((__addr) & 0x00ff0000) >> 16), \
|
||||
(NwU8T)(((__addr) & 0xff000000) >> 24)
|
||||
|
||||
#define NW_IPV4_ADDR_FORMATP(__paddr) (NwU8T)(*((NwU8T*)(__paddr)) & 0x000000ff), \
|
||||
(NwU8T)(*((NwU8T*)(__paddr + 1)) & 0x000000ff), \
|
||||
(NwU8T)(*((NwU8T*)(__paddr + 2)) & 0x000000ff), \
|
||||
(NwU8T)(*((NwU8T*)(__paddr + 3)) & 0x000000ff)
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __NW_LOG_H__ */
|
||||
|
||||
|
||||
@@ -0,0 +1,83 @@
|
||||
/*----------------------------------------------------------------------------*
|
||||
* *
|
||||
* n w - g t p v 2 c *
|
||||
* G P R S T u n n e l i n g P r o t o c o l v 2 c S t a c k *
|
||||
* *
|
||||
* *
|
||||
* Copyright (c) 2010-2011 Amit Chawre *
|
||||
* All rights reserved. *
|
||||
* *
|
||||
* Redistribution and use in source and binary forms, with or without *
|
||||
* modification, are permitted provided that the following conditions *
|
||||
* are met: *
|
||||
* *
|
||||
* 1. Redistributions of source code must retain the above copyright *
|
||||
* notice, this list of conditions and the following disclaimer. *
|
||||
* 2. Redistributions in binary form must reproduce the above copyright *
|
||||
* notice, this list of conditions and the following disclaimer in the *
|
||||
* documentation and/or other materials provided with the distribution. *
|
||||
* 3. The name of the author may not be used to endorse or promote products *
|
||||
* derived from this software without specific prior written permission. *
|
||||
* *
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR *
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES *
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. *
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, *
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT *
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, *
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY *
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT *
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF *
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#ifndef __NW_TYPES_H__
|
||||
#define __NW_TYPES_H__
|
||||
|
||||
/**
|
||||
* @file NwTypes.h
|
||||
* @brief This header file contains basic type definitions.
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define NW_IN /**< An input argument */
|
||||
#define NW_OUT /**< An output argumnet */
|
||||
#define NW_INOUT /**< An input and output argument */
|
||||
|
||||
#define NW_TRUE (1) /**< Truth value */
|
||||
#define NW_FALSE (0) /**< False value */
|
||||
|
||||
typedef unsigned char NwU8T; /**< Unsigned 1 byte */
|
||||
typedef unsigned short NwU16T; /**< Unsigned 2 byte */
|
||||
typedef unsigned int NwU32T; /**< Unsigned 4 byte */
|
||||
typedef unsigned long long NwU64T; /**< Unsigned 8 byte */
|
||||
|
||||
typedef signed char NwS8T; /**< Signed 1 byte */
|
||||
typedef signed short NwS16T; /**< Signed 2 byte */
|
||||
typedef signed int NwS32T; /**< Signed 4 byte */
|
||||
typedef signed long long NwS64T; /**< Signed 8 byte */
|
||||
|
||||
typedef uintptr_t NwPtrT; /**< Use this for generic pointers */
|
||||
typedef unsigned int NwHandleT; /**< Use this for generic handles */
|
||||
|
||||
typedef char NwBoolT; /**< Use this for booleans */
|
||||
|
||||
typedef char NwCharT; /**< Use this for strings */
|
||||
|
||||
typedef signed int NwFdT; /**< Use this for file descriptor */
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __NW_TYPES_H__ */
|
||||
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
/*----------------------------------------------------------------------------*
|
||||
* *
|
||||
* n w - g t p v 2 c *
|
||||
* G P R S T u n n e l i n g P r o t o c o l v 2 c S t a c k *
|
||||
* *
|
||||
* *
|
||||
* Copyright (c) 2010-2011 Amit Chawre *
|
||||
* All rights reserved. *
|
||||
* *
|
||||
* Redistribution and use in source and binary forms, with or without *
|
||||
* modification, are permitted provided that the following conditions *
|
||||
* are met: *
|
||||
* *
|
||||
* 1. Redistributions of source code must retain the above copyright *
|
||||
* notice, this list of conditions and the following disclaimer. *
|
||||
* 2. Redistributions in binary form must reproduce the above copyright *
|
||||
* notice, this list of conditions and the following disclaimer in the *
|
||||
* documentation and/or other materials provided with the distribution. *
|
||||
* 3. The name of the author may not be used to endorse or promote products *
|
||||
* derived from this software without specific prior written permission. *
|
||||
* *
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR *
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES *
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. *
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, *
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT *
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, *
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY *
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT *
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF *
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#ifndef __NW_UTILS_H__
|
||||
#define __NW_UTILS_H__
|
||||
|
||||
|
||||
/**
|
||||
* @file NwUtils.h
|
||||
* @brief This header file contains utility macro and function definitions.
|
||||
*/
|
||||
|
||||
#define NW_ASSERT assert /**< Assertion */
|
||||
|
||||
#define NW_CHK_NULL_PTR(_ptr) NW_ASSERT(_ptr != NULL) /**< Null pointer check */
|
||||
|
||||
#define NW_HTONS(x) ( ( ((x) & 0xff00) >> 8 ) | ( ((x) & 0x00ff) << 8 ) )
|
||||
|
||||
#define NW_HTONL(x) ( ( ((x) & 0xff000000) >> 24 ) | ( ( (x) & 0x00ff0000 ) >> 8 ) | \
|
||||
( ( (x) & 0x0000ff00 ) << 8 ) | ( ( (x) & 0x000000ff) << 24 ) )
|
||||
|
||||
#define NW_HTONLL(x) ( \
|
||||
( ( ((NwU64T)x) & 0xff00000000000000ULL ) >> 56 ) | ( ( ((NwU64T)x) & 0x00ff000000000000ULL ) >> 40 ) | \
|
||||
( ( ((NwU64T)x) & 0x0000ff0000000000ULL ) >> 24 ) | ( ( ((NwU64T)x) & 0x000000ff00000000ULL ) >> 8 ) | \
|
||||
( ( ((NwU64T)x) & 0x000000000000ff00ULL ) << 40 ) | ( ( ((NwU64T)x) & 0x00000000000000ffULL ) << 56 ) | \
|
||||
( ( ((NwU64T)x) & 0x0000000000ff0000ULL ) << 24 ) | ( ( ((NwU64T)x) & 0x00000000ff000000ULL ) << 8 ) \
|
||||
)
|
||||
|
||||
#define NW_NTOHS NW_HTONS
|
||||
#define NW_NTOHL NW_HTONL
|
||||
#define NW_NTOHLL NW_HTONLL
|
||||
|
||||
|
||||
#endif /* __NW_UTILS_H__ */
|
||||
|
||||
|
||||
@@ -0,0 +1,886 @@
|
||||
/*----------------------------------------------------------------------------*
|
||||
* *
|
||||
* n w - g t p v 2 u *
|
||||
* G P R S T u n n e l i n g P r o t o c o l v 2 u S t a c k *
|
||||
* *
|
||||
* *
|
||||
* Copyright (c) 2010-2011 Amit Chawre *
|
||||
* All rights reserved. *
|
||||
* *
|
||||
* Redistribution and use in source and binary forms, with or without *
|
||||
* modification, are permitted provided that the following conditions *
|
||||
* are met: *
|
||||
* *
|
||||
* 1. Redistributions of source code must retain the above copyright *
|
||||
* notice, this list of conditions and the following disclaimer. *
|
||||
* 2. Redistributions in binary form must reproduce the above copyright *
|
||||
* notice, this list of conditions and the following disclaimer in the *
|
||||
* documentation and/or other materials provided with the distribution. *
|
||||
* 3. The name of the author may not be used to endorse or promote products *
|
||||
* derived from this software without specific prior written permission. *
|
||||
* *
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR *
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES *
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. *
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, *
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT *
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, *
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY *
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT *
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF *
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "NwTypes.h"
|
||||
#include "NwUtils.h"
|
||||
#include "NwGtpv1uError.h"
|
||||
#include "NwGtpv1uPrivate.h"
|
||||
#include "NwGtpv1uTunnelEndPoint.h"
|
||||
#include "NwGtpv1uTrxn.h"
|
||||
#include "NwGtpv1u.h"
|
||||
#include "NwGtpv1uIe.h"
|
||||
#include "NwGtpv1uLog.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*--------------------------------------------------------------------------*
|
||||
* P R I V A T E F U N C T I O N S *
|
||||
*--------------------------------------------------------------------------*/
|
||||
|
||||
void
|
||||
nwGtpv1uDisplayBanner(void)
|
||||
{
|
||||
printf(" *----------------------------------------------------------------------------*\n");
|
||||
printf(" * *\n");
|
||||
printf(" * n w - g t p v 2 u *\n");
|
||||
printf(" * G P R S T u n n e l i n g P r o t o c o l v 2 u S t a c k *\n");
|
||||
printf(" * *\n");
|
||||
printf(" * *\n");
|
||||
printf(" * Copyright (c) 2010-2011 Amit Chawre *\n");
|
||||
printf(" * All rights reserved. *\n");
|
||||
printf(" * *\n");
|
||||
printf(" * Redistribution and use in source and binary forms, with or without *\n");
|
||||
printf(" * modification, are permitted provided that the following conditions *\n");
|
||||
printf(" * are met: *\n");
|
||||
printf(" * *\n");
|
||||
printf(" * 1. Redistributions of source code must retain the above copyright *\n");
|
||||
printf(" * notice, this list of conditions and the following disclaimer. *\n");
|
||||
printf(" * 2. Redistributions in binary form must reproduce the above copyright *\n");
|
||||
printf(" * notice, this list of conditions and the following disclaimer in the *\n");
|
||||
printf(" * documentation and/or other materials provided with the distribution. *\n");
|
||||
printf(" * 3. The name of the author may not be used to endorse or promote products *\n");
|
||||
printf(" * derived from this software without specific prior written permission. *\n");
|
||||
printf(" * *\n");
|
||||
printf(" * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR *\n");
|
||||
printf(" * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES *\n");
|
||||
printf(" * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. *\n");
|
||||
printf(" * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, *\n");
|
||||
printf(" * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT *\n");
|
||||
printf(" * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, *\n");
|
||||
printf(" * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY *\n");
|
||||
printf(" * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT *\n");
|
||||
printf(" * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF *\n");
|
||||
printf(" * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *\n");
|
||||
printf(" *----------------------------------------------------------------------------*\n\n");
|
||||
|
||||
}
|
||||
/*---------------------------------------------------------------------------
|
||||
* RBTree Search Functions
|
||||
*--------------------------------------------------------------------------*/
|
||||
|
||||
static inline NwS32T
|
||||
nwGtpv1uCompareTeid(struct NwGtpv1uTunnelEndPoint *a,
|
||||
struct NwGtpv1uTunnelEndPoint *b);
|
||||
|
||||
static inline NwS32T
|
||||
nwGtpv1uCompareSeqNum(struct NwGtpv1uTrxn *a, struct NwGtpv1uTrxn *b);
|
||||
|
||||
RB_PROTOTYPE(NwGtpv1uOutstandingTxSeqNumTrxnMap, NwGtpv1uTrxn,
|
||||
outstandingTxSeqNumMapRbtNode, nwGtpv1uCompareSeqNum)
|
||||
RB_PROTOTYPE(NwGtpv1uOutstandingRxSeqNumTrxnMap, NwGtpv1uTrxn,
|
||||
outstandingRxSeqNumMapRbtNode, nwGtpv1uCompareSeqNum)
|
||||
RB_PROTOTYPE(NwGtpv1uTunnelEndPointTMap, NwGtpv1uTunnelEndPoint,
|
||||
sessionMapRbtNode, nwGtpv1uCompareTeid)
|
||||
RB_PROTOTYPE(NwGtpv1uTunnelEndPointIdentifierMap, NwGtpv1uTunnelEndPoint,
|
||||
sessionMapRbtNode, nwGtpv1uCompareTeid)
|
||||
|
||||
RB_GENERATE(NwGtpv1uOutstandingTxSeqNumTrxnMap, NwGtpv1uTrxn,
|
||||
outstandingTxSeqNumMapRbtNode, nwGtpv1uCompareSeqNum)
|
||||
RB_GENERATE(NwGtpv1uOutstandingRxSeqNumTrxnMap, NwGtpv1uTrxn,
|
||||
outstandingRxSeqNumMapRbtNode, nwGtpv1uCompareSeqNum)
|
||||
RB_GENERATE(NwGtpv1uTunnelEndPointTMap, NwGtpv1uTunnelEndPoint,
|
||||
sessionMapRbtNode, nwGtpv1uCompareTeid)
|
||||
RB_GENERATE(NwGtpv1uTunnelEndPointIdentifierMap, NwGtpv1uTunnelEndPoint,
|
||||
sessionMapRbtNode, nwGtpv1uCompareTeid)
|
||||
|
||||
/**
|
||||
Comparator funtion for comparing two sessions.
|
||||
|
||||
@param[in] a: Pointer to session a.
|
||||
@param[in] b: Pointer to session b.
|
||||
@return An integer greater than, equal to or less than zero according to whether the
|
||||
object pointed to by a is greater than, equal to or less than the object pointed to by b.
|
||||
*/
|
||||
|
||||
static inline NwS32T
|
||||
nwGtpv1uCompareTeid(struct NwGtpv1uTunnelEndPoint *a,
|
||||
struct NwGtpv1uTunnelEndPoint *b)
|
||||
{
|
||||
if(a->teid > b->teid) {
|
||||
return 1;
|
||||
}
|
||||
if(a->teid < b->teid) {
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
Comparator funtion for comparing two sequence number transactions.
|
||||
|
||||
@param[in] a: Pointer to session a.
|
||||
@param[in] b: Pointer to session b.
|
||||
@return An integer greater than, equal to or less than zero according to whether the
|
||||
object pointed to by a is greater than, equal to or less than the object pointed to by b.
|
||||
*/
|
||||
|
||||
static inline NwS32T
|
||||
nwGtpv1uCompareSeqNum(struct NwGtpv1uTrxn *a, struct NwGtpv1uTrxn *b)
|
||||
{
|
||||
if(a->seqNum > b->seqNum) {
|
||||
return 1;
|
||||
}
|
||||
if(a->seqNum < b->seqNum) {
|
||||
return -1;
|
||||
}
|
||||
if(a->peerIp > b->peerIp) {
|
||||
return 1;
|
||||
}
|
||||
if(a->peerIp < b->peerIp) {
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
Create and Send GTPU message.
|
||||
|
||||
@param[in] thiz: Stack handle
|
||||
@return NW_GTPV1U_OK on success.
|
||||
*/
|
||||
|
||||
static NwGtpv1uRcT
|
||||
nwGtpv1uCreateAndSendMsg( NwGtpv1uStackT *thiz, NwU32T peerIp, NwU16T peerPort,
|
||||
NwGtpv1uMsgT *pMsg)
|
||||
{
|
||||
NwGtpv1uRcT rc = NW_GTPV1U_FAILURE;
|
||||
NwU8T *msgHdr;
|
||||
|
||||
NW_ASSERT(thiz);
|
||||
NW_ASSERT(pMsg);
|
||||
|
||||
NW_ENTER(thiz);
|
||||
|
||||
msgHdr = pMsg->msgBuf;
|
||||
NW_ASSERT(msgHdr != NULL);
|
||||
|
||||
*(msgHdr++) = (pMsg->version << 5) |
|
||||
(pMsg->protocolType << 4) |
|
||||
(pMsg->extHdrFlag << 2) |
|
||||
(pMsg->seqNumFlag << 1) |
|
||||
(pMsg->npduNumFlag);
|
||||
|
||||
*(msgHdr++) = (pMsg->msgType);
|
||||
*((NwU16T *) msgHdr) = htons(pMsg->msgLen);
|
||||
msgHdr += 2;
|
||||
|
||||
*((NwU32T *) msgHdr) = htonl(pMsg->teid);
|
||||
msgHdr += 4;
|
||||
NW_LOG(thiz, NW_LOG_LEVEL_ERRO, "nwGtpv1uCreateAndSendMsg to teid %u\n", pMsg->teid);
|
||||
|
||||
if(pMsg->seqNumFlag || pMsg->extHdrFlag || pMsg->npduNumFlag) {
|
||||
*((NwU16T *) msgHdr) = (pMsg->seqNumFlag ? htons(pMsg->seqNum) : 0x0000);
|
||||
msgHdr += 2;
|
||||
|
||||
*((NwU8T *) msgHdr) = (pMsg->npduNumFlag ? htons(pMsg->npduNum) : 0x00);
|
||||
msgHdr++;
|
||||
|
||||
*((NwU8T *) msgHdr) = (pMsg->extHdrFlag ? htons(pMsg->nextExtHdrType) : 0x00);
|
||||
msgHdr++;
|
||||
}
|
||||
|
||||
rc = thiz->udp.udpDataReqCallback(thiz->udp.hUdp,
|
||||
pMsg->msgBuf,
|
||||
pMsg->msgLen,
|
||||
peerIp,
|
||||
peerPort);
|
||||
|
||||
NW_LEAVE(thiz);
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
* Send GTPv1u Message Indication to ULP entity.
|
||||
*
|
||||
* @param[in] hGtpuStackHandle : Stack handle
|
||||
* @return NW_GTPV1U_OK on success.
|
||||
*/
|
||||
|
||||
static NwGtpv1uRcT
|
||||
nwGtpv1uSendUlpMessageIndication( NW_IN NwGtpv1uStackT *thiz,
|
||||
NW_IN NwU32T hUlpTrxn,
|
||||
NW_IN NwU32T apiType,
|
||||
NW_IN NwU32T msgType,
|
||||
NW_IN NwU32T peerIp,
|
||||
NW_IN NwU16T peerPort,
|
||||
NW_IN NwU8T *pMsgBuf,
|
||||
NW_IN NwU16T msgLength)
|
||||
{
|
||||
NwGtpv1uRcT rc = NW_GTPV1U_FAILURE;
|
||||
NwGtpv1uUlpApiT ulpApi;
|
||||
|
||||
NW_ENTER(thiz);
|
||||
|
||||
ulpApi.apiType = apiType;
|
||||
ulpApi.apiInfo.recvMsgInfo.msgType = msgType;
|
||||
ulpApi.apiInfo.recvMsgInfo.hUlpTrxn = hUlpTrxn;
|
||||
ulpApi.apiInfo.recvMsgInfo.peerIp = peerIp;
|
||||
ulpApi.apiInfo.recvMsgInfo.peerPort = peerPort;
|
||||
|
||||
if(pMsgBuf && msgLength) {
|
||||
rc = nwGtpv1uMsgFromBufferNew((NwGtpv1uStackHandleT)thiz, pMsgBuf, msgLength,
|
||||
&(ulpApi.apiInfo.recvMsgInfo.hMsg));
|
||||
NW_ASSERT(rc == NW_GTPV1U_OK);
|
||||
}
|
||||
|
||||
rc = thiz->ulp.ulpReqCallback(thiz->ulp.hUlp, &ulpApi);
|
||||
NW_ASSERT(rc == NW_GTPV1U_OK);
|
||||
|
||||
NW_LEAVE(thiz);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
NwGtpv1uRcT
|
||||
nwGtpv1uPeerRspTimeout(void *arg)
|
||||
{
|
||||
NwGtpv1uRcT rc = NW_GTPV1U_OK;
|
||||
NwGtpv1uTrxnT *thiz;
|
||||
NwGtpv1uTimeoutInfoT *timeoutInfo = arg;
|
||||
|
||||
printf("Retransmission timer expired\n");
|
||||
|
||||
thiz = ((NwGtpv1uTrxnT *)timeoutInfo->timeoutArg);
|
||||
rc = thiz->pStack->udp.udpDataReqCallback(thiz->pStack->udp.hUdp,
|
||||
thiz->pMsg->msgBuf,
|
||||
thiz->pMsg->msgLen,
|
||||
thiz->peerIp,
|
||||
thiz->peerPort);
|
||||
|
||||
if(thiz->maxRetries) {
|
||||
rc = thiz->pStack->tmrMgr.tmrStartCallback(thiz->pStack->tmrMgr.tmrMgrHandle,
|
||||
5, 0, NW_GTPV1U_TMR_TYPE_ONE_SHOT, (void *)timeoutInfo, &thiz->hRspTmr);
|
||||
thiz->maxRetries--;
|
||||
} else {
|
||||
/* Inform session layer about path fialure */
|
||||
printf("Max retries over!\n");
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
* ULP API Processing Functions
|
||||
*--------------------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
Process NW_GTPV1U_ULP_API_CREATE_TUNNEL_ENDPOINT Request from ULP entity.
|
||||
|
||||
@param[in] hGtpuStackHandle : Stack handle
|
||||
@param[in] pUlpReq : Pointer to Ulp Req.
|
||||
@return NW_GTPV1U_OK on success.
|
||||
*/
|
||||
|
||||
static NwGtpv1uRcT
|
||||
NwGtpv1uCreateTunnelEndPoint( NW_IN NwGtpv1uStackT *thiz,
|
||||
NW_IN NwU32T teid,
|
||||
NW_IN NwGtpv1uUlpSessionHandleT hUlpSession,
|
||||
NW_OUT NwGtpv1uStackSessionHandleT *phStackSession )
|
||||
{
|
||||
NwGtpv1uRcT rc = NW_GTPV1U_OK;
|
||||
NwGtpv1uTunnelEndPointT *pTunnelEndPoint;
|
||||
NwGtpv1uTunnelEndPointT *pCollision;
|
||||
|
||||
NW_ENTER(thiz);
|
||||
|
||||
pTunnelEndPoint = nwGtpTunnelEndPointNew(thiz);
|
||||
|
||||
if(pTunnelEndPoint) {
|
||||
|
||||
pTunnelEndPoint->teid = teid;
|
||||
pTunnelEndPoint->pStack = thiz;
|
||||
pTunnelEndPoint->hUlpSession = hUlpSession;
|
||||
|
||||
pCollision = RB_INSERT(NwGtpv1uTunnelEndPointIdentifierMap, &(thiz->teidMap),
|
||||
pTunnelEndPoint);
|
||||
|
||||
if(pCollision) {
|
||||
NW_LOG(thiz, NW_LOG_LEVEL_ERRO,
|
||||
"Tunnel end-point cannot be created for teid 0x%x. "
|
||||
"Tunnel already exists", teid);
|
||||
rc = nwGtpTunnelEndPointDestroy(thiz, pTunnelEndPoint);
|
||||
NW_ASSERT(rc == NW_GTPV1U_OK);
|
||||
*phStackSession = (NwGtpv1uStackSessionHandleT) 0;
|
||||
NW_ASSERT(0);
|
||||
rc = NW_GTPV1U_FAILURE;
|
||||
} else {
|
||||
*phStackSession = (NwGtpv1uStackSessionHandleT) pTunnelEndPoint;
|
||||
pTunnelEndPoint = RB_FIND(NwGtpv1uTunnelEndPointIdentifierMap,
|
||||
&(thiz->teidMap), pTunnelEndPoint);
|
||||
NW_ASSERT(pTunnelEndPoint);
|
||||
NW_LOG(thiz, NW_LOG_LEVEL_DEBG,
|
||||
"Tunnel end-point 0x%x creation successful for teid 0x%x",
|
||||
(unsigned int)pTunnelEndPoint, teid);
|
||||
}
|
||||
|
||||
} else {
|
||||
*phStackSession = (NwGtpv1uStackSessionHandleT) 0;
|
||||
rc = NW_GTPV1U_FAILURE;
|
||||
}
|
||||
|
||||
NW_LEAVE(thiz);
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
Process NW_GTPV1U_ULP_API_DESTROY_TUNNEL_ENDPOINT Request from ULP entity.
|
||||
|
||||
@param[in] hGtpuStackHandle : Stack handle
|
||||
@param[in] pUlpReq : Pointer to Ulp Req.
|
||||
@return NW_GTPV1U_OK on success.
|
||||
*/
|
||||
|
||||
static NwGtpv1uRcT
|
||||
nwGtpv1uDestroyTunnelEndPoint( NwGtpv1uStackT *thiz,
|
||||
NW_IN NwGtpv1uUlpApiT *pUlpReq)
|
||||
{
|
||||
NwGtpv1uRcT rc = NW_GTPV1U_OK;
|
||||
NwGtpv1uTunnelEndPointT *pRemovedTeid;
|
||||
|
||||
if(pUlpReq->apiInfo.destroyTunnelEndPointInfo.hStackSessionHandle) {
|
||||
NW_LOG(thiz, NW_LOG_LEVEL_DEBG, "Destroying Tunnel end-point '%x'",
|
||||
pUlpReq->apiInfo.destroyTunnelEndPointInfo.hStackSessionHandle);
|
||||
pRemovedTeid = RB_REMOVE(NwGtpv1uTunnelEndPointIdentifierMap, &(thiz->teidMap),
|
||||
(NwGtpv1uTunnelEndPointT *)(
|
||||
pUlpReq->apiInfo.destroyTunnelEndPointInfo.hStackSessionHandle));
|
||||
|
||||
NW_ASSERT(pRemovedTeid == (NwGtpv1uTunnelEndPointT *)(
|
||||
pUlpReq->apiInfo.destroyTunnelEndPointInfo.hStackSessionHandle));
|
||||
|
||||
rc = nwGtpTunnelEndPointDestroy(thiz,
|
||||
(NwGtpv1uTunnelEndPointT *)
|
||||
pUlpReq->apiInfo.destroyTunnelEndPointInfo.hStackSessionHandle);
|
||||
} else {
|
||||
NW_LOG(thiz, NW_LOG_LEVEL_WARN, "Non-existent Tunnel end-point handle '%x'",
|
||||
pUlpReq->apiInfo.destroyTunnelEndPointInfo.hStackSessionHandle);
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
Process NW_GTPV1U_ULP_API_INITIAL_REQ Request from ULP entity.
|
||||
|
||||
@param[in] hGtpuStackHandle : Stack handle
|
||||
@param[in] pUlpReq : Pointer to Ulp Req.
|
||||
@return NW_GTPV1U_OK on success.
|
||||
*/
|
||||
|
||||
static NwGtpv1uRcT
|
||||
nwGtpv1uInitialReq( NW_IN NwGtpv1uStackT *thiz, NW_IN NwGtpv1uUlpApiT *pUlpReq)
|
||||
{
|
||||
NwGtpv1uRcT rc = NW_GTPV1U_FAILURE;
|
||||
NwGtpv1uTrxnT *pTrxn;
|
||||
|
||||
NW_ENTER(thiz);
|
||||
|
||||
/* Create New Transaction */
|
||||
rc = nwGtpv1uTrxnNew(thiz, &pTrxn);
|
||||
|
||||
if(pTrxn) {
|
||||
rc = nwGtpv1uTrxnCreateAndSendMsg(thiz,
|
||||
pTrxn,
|
||||
pUlpReq->apiInfo.initialReqInfo.peerIp,
|
||||
pUlpReq->apiInfo.initialReqInfo.peerPort,
|
||||
(NwGtpv1uMsgT *) pUlpReq->hMsg);
|
||||
|
||||
if(rc == NW_GTPV1U_OK) {
|
||||
/* Insert into search tree */
|
||||
RB_INSERT(NwGtpv1uOutstandingTxSeqNumTrxnMap, &(thiz->outstandingTxSeqNumMap),
|
||||
pTrxn);
|
||||
} else {
|
||||
rc = nwGtpv1uTrxnDelete(&pTrxn);
|
||||
NW_ASSERT(rc == NW_GTPV1U_OK);
|
||||
}
|
||||
}
|
||||
|
||||
NW_LEAVE(thiz);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
Process NW_GTPV1U_ULP_API_SEND_TPDU Request from ULP entity.
|
||||
|
||||
@param[in] thiz: Stack handle
|
||||
@param[in] pUlpReq : Pointer to Ulp Req.
|
||||
@return NW_GTPV1U_OK on success.
|
||||
*/
|
||||
|
||||
static NwGtpv1uRcT
|
||||
nwGtpv1uSendto( NwGtpv1uStackT *thiz, NW_IN NwGtpv1uUlpApiT *pUlpReq)
|
||||
{
|
||||
NwGtpv1uRcT rc = NW_GTPV1U_FAILURE;
|
||||
|
||||
NW_ASSERT(thiz);
|
||||
NW_ENTER(thiz);
|
||||
|
||||
(void) nwGtpv1uMsgSetTeid(pUlpReq->apiInfo.sendtoInfo.hMsg,
|
||||
pUlpReq->apiInfo.sendtoInfo.teid);
|
||||
|
||||
rc = nwGtpv1uCreateAndSendMsg(thiz,
|
||||
pUlpReq->apiInfo.sendtoInfo.ipAddr,
|
||||
2152,
|
||||
(NwGtpv1uMsgT *) (NwGtpv1uMsgT *) pUlpReq->apiInfo.sendtoInfo.hMsg);
|
||||
|
||||
NW_LEAVE(thiz);
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
Process GPDU from UDP entity.
|
||||
|
||||
@param[in] thiz: Stack handle
|
||||
@param[in] pUlpReq : Pointer to Ulp Req.
|
||||
@return NW_GTPV1U_OK on success.
|
||||
*/
|
||||
|
||||
static NwGtpv1uRcT
|
||||
nwGtpv1uProcessGpdu( NwGtpv1uStackT *thiz,
|
||||
NW_IN NwU8T *gpdu,
|
||||
NW_IN NwU32T gdpuLen,
|
||||
NW_IN NwU32T peerIp)
|
||||
|
||||
{
|
||||
NwGtpv1uRcT rc = NW_GTPV1U_FAILURE;
|
||||
NwGtpv1uMsgHeaderT *msgHdr;
|
||||
NwGtpv1uTunnelEndPointT *pTunnelEndPoint;
|
||||
NwGtpv1uTunnelEndPointT tunnelEndPointKey;
|
||||
|
||||
NW_ENTER(thiz);
|
||||
|
||||
msgHdr = (NwGtpv1uMsgHeaderT *) gpdu;
|
||||
|
||||
tunnelEndPointKey.teid = ntohl(msgHdr->teid);
|
||||
pTunnelEndPoint = RB_FIND(NwGtpv1uTunnelEndPointIdentifierMap,
|
||||
&(thiz->teidMap), &tunnelEndPointKey);
|
||||
|
||||
if(pTunnelEndPoint) {
|
||||
NwGtpv1uMsgHandleT hMsg;
|
||||
|
||||
rc = nwGtpv1uMsgFromBufferNew( (NwGtpv1uStackHandleT)thiz,
|
||||
(NwU8T *)gpdu,
|
||||
gdpuLen,
|
||||
&hMsg);
|
||||
|
||||
if(NW_GTPV1U_OK == rc) {
|
||||
NwGtpv1uMsgT *pMsg = (NwGtpv1uMsgT *) hMsg;
|
||||
NW_LOG(thiz, NW_LOG_LEVEL_DEBG,
|
||||
"Received T-PDU over tunnel end-point '%x' of size %u from "NW_IPV4_ADDR,
|
||||
ntohl(msgHdr->teid), pMsg->msgLen, NW_IPV4_ADDR_FORMAT((peerIp)));
|
||||
rc = nwGtpSessionSendMsgApiToUlpEntity(pTunnelEndPoint, pMsg);
|
||||
}
|
||||
} else {
|
||||
NW_LOG(thiz, NW_LOG_LEVEL_ERRO,
|
||||
"Received T-PDU over non-existent tunnel end-point '%x' from "NW_IPV4_ADDR,
|
||||
ntohl(msgHdr->teid), NW_IPV4_ADDR_FORMAT((peerIp)));
|
||||
}
|
||||
NW_LEAVE(thiz);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
Handle Echo Request from Peer Entity.
|
||||
|
||||
@param[in] thiz : Stack context
|
||||
@return NW_GTPV1U_OK on success.
|
||||
*/
|
||||
|
||||
static NwGtpv1uRcT
|
||||
nwGtpv1uHandleEchoReq(NW_IN NwGtpv1uStackT *thiz,
|
||||
NW_IN NwU8T *msgBuf,
|
||||
NW_IN NwU32T msgBufLen,
|
||||
NW_IN NwU16T peerPort,
|
||||
NW_IN NwU32T peerIp)
|
||||
{
|
||||
NwGtpv1uRcT rc = NW_GTPV1U_FAILURE;
|
||||
NwU16T seqNum = 0;
|
||||
NwGtpv1uMsgHandleT hMsg = 0;
|
||||
|
||||
seqNum = ntohs(*(NwU16T *) (msgBuf + (((*msgBuf) & 0x02) ? 8 : 4)));
|
||||
|
||||
/* Send Echo Response */
|
||||
|
||||
rc = nwGtpv1uMsgNew( (NwGtpv1uStackHandleT)thiz,
|
||||
NW_TRUE, /* SeqNum flag */
|
||||
NW_FALSE,
|
||||
NW_FALSE,
|
||||
NW_GTP_ECHO_RSP, /* Msg Type */
|
||||
0x00000000U, /* TEID */
|
||||
seqNum, /* Seq Number */
|
||||
0,
|
||||
0,
|
||||
(&hMsg));
|
||||
|
||||
NW_ASSERT(NW_GTPV1U_OK == rc);
|
||||
|
||||
/*
|
||||
* The Restart Counter value in the Recovery information element shall
|
||||
* not be used, i.e. it shall be set to zero by the sender and shall be
|
||||
* ignored by the receiver.
|
||||
*/
|
||||
rc = nwGtpv1uMsgAddIeTV1(hMsg, NW_GTPV1U_IE_RECOVERY, 0x00);
|
||||
|
||||
NW_LOG(thiz, NW_LOG_LEVEL_INFO,
|
||||
"Sending NW_GTP_ECHO_RSP message to %x:%x with seq %u", peerIp, peerPort,
|
||||
seqNum);
|
||||
|
||||
rc = nwGtpv1uCreateAndSendMsg(thiz,
|
||||
peerIp,
|
||||
peerPort,
|
||||
(NwGtpv1uMsgT *) hMsg);
|
||||
|
||||
rc = nwGtpv1uMsgDelete((NwGtpv1uStackHandleT)thiz, hMsg);
|
||||
NW_ASSERT(NW_GTPV1U_OK == rc);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*--------------------------------------------------------------------------*
|
||||
* P U B L I C F U N C T I O N S *
|
||||
*--------------------------------------------------------------------------*/
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
* Constructor
|
||||
*--------------------------------------------------------------------------*/
|
||||
|
||||
NwGtpv1uRcT
|
||||
nwGtpv1uInitialize( NW_INOUT NwGtpv1uStackHandleT *hGtpuStackHandle)
|
||||
{
|
||||
NwGtpv1uRcT rc = NW_GTPV1U_FAILURE;
|
||||
NwGtpv1uStackT *thiz;
|
||||
|
||||
thiz = (NwGtpv1uStackT *) malloc( sizeof(NwGtpv1uStackT));
|
||||
memset(thiz, 0, sizeof(NwGtpv1uStackT));
|
||||
|
||||
if(thiz) {
|
||||
thiz->id = (NwU32T) thiz;
|
||||
thiz->seq = (NwU16T) ((NwU32T)thiz) ;
|
||||
RB_INIT(&(thiz->outstandingTxSeqNumMap));
|
||||
RB_INIT(&(thiz->outstandingRxSeqNumMap));
|
||||
RB_INIT(&(thiz->sessionMap));
|
||||
RB_INIT(&(thiz->teidMap));
|
||||
if (0 == 1) {
|
||||
nwGtpv1uDisplayBanner();
|
||||
}
|
||||
|
||||
rc = NW_GTPV1U_OK;
|
||||
} else {
|
||||
rc = NW_GTPV1U_FAILURE;
|
||||
}
|
||||
|
||||
|
||||
*hGtpuStackHandle = (NwGtpv1uStackHandleT) thiz;
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
* Destructor
|
||||
*--------------------------------------------------------------------------*/
|
||||
|
||||
NwGtpv1uRcT
|
||||
nwGtpv1uFinalize( NW_IN NwGtpv1uStackHandleT hGtpuStackHandle)
|
||||
{
|
||||
NwGtpv1uRcT rc = NW_GTPV1U_FAILURE;
|
||||
if(hGtpuStackHandle) {
|
||||
free((void *)hGtpuStackHandle);
|
||||
rc = NW_GTPV1U_OK;
|
||||
} else {
|
||||
rc = NW_GTPV1U_FAILURE;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
* Configuration Get/Set
|
||||
*--------------------------------------------------------------------------*/
|
||||
|
||||
NwGtpv1uRcT
|
||||
nwGtpv1uSetUlpEntity( NW_IN NwGtpv1uStackHandleT hGtpuStackHandle,
|
||||
NW_IN NwGtpv1uUlpEntityT *pUlpEntity)
|
||||
{
|
||||
NwGtpv1uRcT rc = NW_GTPV1U_FAILURE;
|
||||
NwGtpv1uStackT *thiz = (NwGtpv1uStackT *) hGtpuStackHandle;
|
||||
|
||||
if(pUlpEntity) {
|
||||
thiz->ulp = *(pUlpEntity);
|
||||
rc = NW_GTPV1U_OK;
|
||||
} else {
|
||||
rc = NW_GTPV1U_FAILURE;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
NwGtpv1uRcT
|
||||
nwGtpv1uSetUdpEntity( NW_IN NwGtpv1uStackHandleT hGtpuStackHandle,
|
||||
NW_IN NwGtpv1uUdpEntityT *pUdpEntity)
|
||||
{
|
||||
NwGtpv1uRcT rc = NW_GTPV1U_FAILURE;
|
||||
NwGtpv1uStackT *thiz = (NwGtpv1uStackT *) hGtpuStackHandle;
|
||||
|
||||
if(pUdpEntity) {
|
||||
thiz->udp = *(pUdpEntity);
|
||||
rc = NW_GTPV1U_OK;
|
||||
} else {
|
||||
rc = NW_GTPV1U_FAILURE;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
NwGtpv1uRcT
|
||||
nwGtpv1uSetMemMgrEntity( NW_IN NwGtpv1uStackHandleT hGtpuStackHandle,
|
||||
NW_IN NwGtpv1uMemMgrEntityT *pMemMgrEntity)
|
||||
{
|
||||
NwGtpv1uRcT rc = NW_GTPV1U_FAILURE;
|
||||
NwGtpv1uStackT *thiz = (NwGtpv1uStackT *) hGtpuStackHandle;
|
||||
|
||||
if(pMemMgrEntity) {
|
||||
thiz->memMgr = *(pMemMgrEntity);
|
||||
rc = NW_GTPV1U_OK;
|
||||
} else {
|
||||
rc = NW_GTPV1U_FAILURE;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
NwGtpv1uRcT
|
||||
nwGtpv1uSetTimerMgrEntity( NW_IN NwGtpv1uStackHandleT hGtpuStackHandle,
|
||||
NW_IN NwGtpv1uTimerMgrEntityT *pTmrMgrEntity)
|
||||
{
|
||||
NwGtpv1uRcT rc = NW_GTPV1U_FAILURE;
|
||||
NwGtpv1uStackT *thiz = (NwGtpv1uStackT *) hGtpuStackHandle;
|
||||
|
||||
if(pTmrMgrEntity) {
|
||||
thiz->tmrMgr = *(pTmrMgrEntity);
|
||||
rc = NW_GTPV1U_OK;
|
||||
} else {
|
||||
rc = NW_GTPV1U_FAILURE;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
NwGtpv1uRcT
|
||||
nwGtpv1uSetLogMgrEntity( NW_IN NwGtpv1uStackHandleT hGtpuStackHandle,
|
||||
NW_IN NwGtpv1uLogMgrEntityT *pLogMgrEntity)
|
||||
{
|
||||
NwGtpv1uRcT rc = NW_GTPV1U_FAILURE;
|
||||
NwGtpv1uStackT *thiz = (NwGtpv1uStackT *) hGtpuStackHandle;
|
||||
|
||||
if(pLogMgrEntity) {
|
||||
thiz->logMgr = *(pLogMgrEntity);
|
||||
rc = NW_GTPV1U_OK;
|
||||
} else {
|
||||
rc = NW_GTPV1U_FAILURE;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
NwGtpv1uRcT
|
||||
nwGtpv1uSetLogLevel( NW_IN NwGtpv1uStackHandleT hGtpuStackHandle,
|
||||
NW_IN NwU32T logLevel)
|
||||
{
|
||||
NwGtpv1uStackT *thiz = (NwGtpv1uStackT *) hGtpuStackHandle;
|
||||
thiz->logLevel = logLevel;
|
||||
return NW_GTPV1U_OK;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
* Process Request from Udp Layer
|
||||
*--------------------------------------------------------------------------*/
|
||||
|
||||
NwGtpv1uRcT
|
||||
nwGtpv1uProcessUdpReq( NW_IN NwGtpv1uStackHandleT hGtpuStackHandle,
|
||||
NW_IN NwU8T *udpData,
|
||||
NW_IN NwU32T udpDataLen,
|
||||
NW_IN NwU16T peerPort,
|
||||
NW_IN NwU32T peerIp)
|
||||
{
|
||||
NwGtpv1uRcT ret = NW_GTPV1U_FAILURE;
|
||||
NwGtpv1uStackT *thiz;
|
||||
NwU16T msgType;
|
||||
|
||||
thiz = (NwGtpv1uStackT *) hGtpuStackHandle;
|
||||
|
||||
NW_ASSERT(thiz);
|
||||
|
||||
msgType = *((NwU8T *)(udpData + 1));
|
||||
|
||||
switch(msgType) {
|
||||
case NW_GTP_ECHO_REQ:
|
||||
NW_LOG(thiz, NW_LOG_LEVEL_DEBG, "NW_GTP_ECHO_REQ");
|
||||
ret = nwGtpv1uHandleEchoReq( thiz, udpData, udpDataLen, peerPort, peerIp);
|
||||
break;
|
||||
|
||||
case NW_GTP_ERROR_INDICATION:
|
||||
|
||||
NW_LOG(thiz, NW_LOG_LEVEL_DEBG, "NW_GTP_ERROR_INDICATION");
|
||||
ret = nwGtpv1uSendUlpMessageIndication( thiz,
|
||||
0,
|
||||
NW_GTPV1U_ULP_API_RECV_MSG,
|
||||
msgType,
|
||||
peerIp,
|
||||
peerPort,
|
||||
udpData,
|
||||
udpDataLen);
|
||||
|
||||
NW_ASSERT(ret == NW_GTPV1U_OK);
|
||||
|
||||
break;
|
||||
|
||||
case NW_GTP_ECHO_RSP:
|
||||
NW_LOG(thiz, NW_LOG_LEVEL_DEBG, "NW_GTP_ECHO_RSP");
|
||||
ret = NW_GTPV1U_OK;
|
||||
break;
|
||||
|
||||
case NW_GTP_GPDU:
|
||||
NW_LOG(thiz, NW_LOG_LEVEL_DEBG, "NW_GTP_GPDU");
|
||||
ret = nwGtpv1uProcessGpdu(thiz, udpData, udpDataLen, peerIp);
|
||||
break;
|
||||
|
||||
default:
|
||||
ret = NW_GTPV1U_FAILURE;
|
||||
NW_ASSERT(0);
|
||||
break;
|
||||
}
|
||||
|
||||
NW_LEAVE(thiz);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
* Process Request from Upper Layer
|
||||
*--------------------------------------------------------------------------*/
|
||||
|
||||
NwGtpv1uRcT
|
||||
nwGtpv1uProcessUlpReq( NW_IN NwGtpv1uStackHandleT hGtpuStackHandle,
|
||||
NW_IN NwGtpv1uUlpApiT *pUlpReq)
|
||||
{
|
||||
NwGtpv1uRcT rc = NW_GTPV1U_FAILURE;
|
||||
NwGtpv1uStackT *thiz = (NwGtpv1uStackT *) hGtpuStackHandle;
|
||||
|
||||
NW_ASSERT(thiz);
|
||||
NW_ASSERT(pUlpReq != NULL);
|
||||
|
||||
NW_ENTER(thiz);
|
||||
|
||||
switch(pUlpReq->apiType) {
|
||||
case NW_GTPV1U_ULP_API_CREATE_TUNNEL_ENDPOINT: {
|
||||
NW_LOG(thiz, NW_LOG_LEVEL_DEBG, "Received create session req from ulp");
|
||||
rc = NwGtpv1uCreateTunnelEndPoint(thiz,
|
||||
pUlpReq->apiInfo.createTunnelEndPointInfo.teid,
|
||||
pUlpReq->apiInfo.createTunnelEndPointInfo.hUlpSession,
|
||||
&(pUlpReq->apiInfo.createTunnelEndPointInfo.hStackSession));
|
||||
}
|
||||
break;
|
||||
|
||||
case NW_GTPV1U_ULP_API_DESTROY_TUNNEL_ENDPOINT: {
|
||||
NW_LOG(thiz, NW_LOG_LEVEL_DEBG, "Received destroy session req from ulp");
|
||||
rc = nwGtpv1uDestroyTunnelEndPoint(thiz, pUlpReq);
|
||||
}
|
||||
break;
|
||||
|
||||
case NW_GTPV1U_ULP_API_INITIAL_REQ: {
|
||||
NW_LOG(thiz, NW_LOG_LEVEL_DEBG, "Received initial req from ulp");
|
||||
rc = nwGtpv1uInitialReq(thiz, pUlpReq);
|
||||
}
|
||||
break;
|
||||
|
||||
case NW_GTPV1U_ULP_API_SEND_TPDU: {
|
||||
NW_LOG(thiz, NW_LOG_LEVEL_DEBG, "Received send tpdu req from ulp");
|
||||
rc = nwGtpv1uSendto(thiz, pUlpReq);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
NW_LOG(thiz, NW_LOG_LEVEL_ERRO, "Unsupported API received from ulp");
|
||||
rc = NW_GTPV1U_FAILURE;
|
||||
break;
|
||||
}
|
||||
|
||||
NW_LEAVE(thiz);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
* Process Timer timeout Request from Timer Manager
|
||||
*--------------------------------------------------------------------------*/
|
||||
|
||||
NwGtpv1uRcT
|
||||
nwGtpv1uProcessTimeout(void *timeoutInfo)
|
||||
{
|
||||
NwGtpv1uRcT rc = NW_GTPV1U_FAILURE;
|
||||
NwGtpv1uStackT *thiz;
|
||||
|
||||
NW_ASSERT(timeoutInfo != NULL);
|
||||
|
||||
thiz = (NwGtpv1uStackT *) (((NwGtpv1uTimeoutInfoT *) timeoutInfo)->hStack);
|
||||
|
||||
NW_ASSERT(thiz != NULL);
|
||||
|
||||
NW_ENTER(thiz);
|
||||
NW_LOG(thiz, NW_LOG_LEVEL_DEBG,
|
||||
"Received timeout event from ULP with timeoutInfo %x!",
|
||||
(unsigned int)timeoutInfo);
|
||||
|
||||
rc = (((NwGtpv1uTimeoutInfoT *) timeoutInfo)->timeoutCallbackFunc) (timeoutInfo);
|
||||
|
||||
NW_LEAVE(thiz);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
/*--------------------------------------------------------------------------*
|
||||
* E N D O F F I L E *
|
||||
*--------------------------------------------------------------------------*/
|
||||
|
||||
@@ -0,0 +1,479 @@
|
||||
/*----------------------------------------------------------------------------*
|
||||
* *
|
||||
* n w - g t p v 2 u *
|
||||
* G P R S T u n n e l i n g P r o t o c o l v 2 u S t a c k *
|
||||
* *
|
||||
* *
|
||||
* Copyright (c) 2010-2011 Amit Chawre *
|
||||
* All rights reserved. *
|
||||
* *
|
||||
* Redistribution and use in source and binary forms, with or without *
|
||||
* modification, are permitted provided that the following conditions *
|
||||
* are met: *
|
||||
* *
|
||||
* 1. Redistributions of source code must retain the above copyright *
|
||||
* notice, this list of conditions and the following disclaimer. *
|
||||
* 2. Redistributions in binary form must reproduce the above copyright *
|
||||
* notice, this list of conditions and the following disclaimer in the *
|
||||
* documentation and/or other materials provided with the distribution. *
|
||||
* 3. The name of the author may not be used to endorse or promote products *
|
||||
* derived from this software without specific prior written permission. *
|
||||
* *
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR *
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES *
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. *
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, *
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT *
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, *
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY *
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT *
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF *
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include "NwTypes.h"
|
||||
#include "NwLog.h"
|
||||
#include "NwUtils.h"
|
||||
#include "NwGtpv1uLog.h"
|
||||
#include "NwGtpv1u.h"
|
||||
#include "NwGtpv1uPrivate.h"
|
||||
#include "NwGtpv1uMsg.h"
|
||||
|
||||
#define NW_GTPV1U_EPC_SPECIFIC_HEADER_SIZE (12) /**< Size of GTPv1u EPC specific header */
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
static NwGtpv1uMsgT *gpGtpv1uMsgPool = NULL;
|
||||
|
||||
NwGtpv1uRcT
|
||||
nwGtpv1uMsgNew( NW_IN NwGtpv1uStackHandleT hGtpuStackHandle,
|
||||
NW_IN NwU8T seqNumFlag,
|
||||
NW_IN NwU8T npduNumFlag,
|
||||
NW_IN NwU8T extHdrFlag,
|
||||
NW_IN NwU8T msgType,
|
||||
NW_IN NwU8T teid,
|
||||
NW_IN NwU16T seqNum,
|
||||
NW_IN NwU8T npduNum,
|
||||
NW_IN NwU8T nextExtHeader,
|
||||
NW_OUT NwGtpv1uMsgHandleT *phMsg)
|
||||
{
|
||||
NwGtpv1uStackT *pStack = (NwGtpv1uStackT *) hGtpuStackHandle;
|
||||
NwGtpv1uMsgT *pMsg;
|
||||
|
||||
if(gpGtpv1uMsgPool) {
|
||||
pMsg = gpGtpv1uMsgPool;
|
||||
gpGtpv1uMsgPool = gpGtpv1uMsgPool->next;
|
||||
} else {
|
||||
NW_GTPV1U_MALLOC(pStack, sizeof(NwGtpv1uMsgT), pMsg, NwGtpv1uMsgT *);
|
||||
}
|
||||
|
||||
|
||||
if(pMsg) {
|
||||
pMsg->version = NW_GTPU_VERSION;
|
||||
pMsg->protocolType = NW_GTP_PROTOCOL_TYPE_GTP;
|
||||
pMsg->seqNumFlag = seqNumFlag;
|
||||
pMsg->npduNumFlag = npduNumFlag;
|
||||
pMsg->extHdrFlag = extHdrFlag;
|
||||
pMsg->msgType = msgType;
|
||||
|
||||
if(seqNumFlag) {
|
||||
pMsg->seqNum = seqNum;
|
||||
}
|
||||
if(npduNumFlag) {
|
||||
pMsg->npduNum = npduNum;
|
||||
}
|
||||
if(extHdrFlag) {
|
||||
pMsg->nextExtHdrType = nextExtHeader;
|
||||
}
|
||||
|
||||
pMsg->msgLen = ((pMsg->seqNumFlag || pMsg->npduNumFlag
|
||||
|| pMsg->extHdrFlag) ?
|
||||
NW_GTPV1U_EPC_SPECIFIC_HEADER_SIZE : (NW_GTPV1U_EPC_SPECIFIC_HEADER_SIZE - 4));
|
||||
|
||||
*phMsg = (NwGtpv1uMsgHandleT) pMsg;
|
||||
return NW_GTPV1U_OK;
|
||||
}
|
||||
|
||||
return NW_GTPV1U_FAILURE;
|
||||
}
|
||||
|
||||
NwGtpv1uRcT
|
||||
nwGtpv1uGpduMsgNew( NW_IN NwGtpv1uStackHandleT hGtpuStackHandle,
|
||||
NW_IN NwU32T teid,
|
||||
NW_IN NwU8T seqNumFlag,
|
||||
NW_IN NwU16T seqNum,
|
||||
NW_IN NwU8T *tpdu,
|
||||
NW_IN NwU16T tpduLength,
|
||||
NW_OUT NwGtpv1uMsgHandleT *phMsg)
|
||||
{
|
||||
NwGtpv1uStackT *pStack = (NwGtpv1uStackT *) hGtpuStackHandle;
|
||||
NwGtpv1uMsgT *pMsg;
|
||||
|
||||
if(gpGtpv1uMsgPool) {
|
||||
pMsg = gpGtpv1uMsgPool;
|
||||
gpGtpv1uMsgPool = gpGtpv1uMsgPool->next;
|
||||
} else {
|
||||
NW_GTPV1U_MALLOC(pStack, sizeof(NwGtpv1uMsgT), pMsg, NwGtpv1uMsgT *);
|
||||
}
|
||||
|
||||
if(pMsg) {
|
||||
pMsg->version = NW_GTPU_VERSION;
|
||||
pMsg->protocolType = NW_GTP_PROTOCOL_TYPE_GTP;
|
||||
pMsg->extHdrFlag = NW_FALSE;
|
||||
pMsg->seqNumFlag = (seqNumFlag? NW_TRUE : NW_FALSE);
|
||||
pMsg->npduNumFlag = NW_FALSE;
|
||||
pMsg->msgType = NW_GTP_GPDU;
|
||||
pMsg->teid = teid;
|
||||
pMsg->seqNum = seqNum;
|
||||
pMsg->npduNum = 0x00;
|
||||
pMsg->nextExtHdrType= 0x00;
|
||||
pMsg->msgLen = ((pMsg->seqNumFlag || pMsg->npduNumFlag
|
||||
|| pMsg->extHdrFlag ) ?
|
||||
NW_GTPV1U_EPC_SPECIFIC_HEADER_SIZE : (NW_GTPV1U_EPC_SPECIFIC_HEADER_SIZE - 4));
|
||||
|
||||
memcpy(pMsg->msgBuf + pMsg->msgLen, tpdu, tpduLength);
|
||||
pMsg->msgLen += tpduLength;
|
||||
|
||||
*phMsg = (NwGtpv1uMsgHandleT) pMsg;
|
||||
return NW_GTPV1U_OK;
|
||||
}
|
||||
|
||||
return NW_GTPV1U_FAILURE;
|
||||
}
|
||||
|
||||
NwGtpv1uRcT
|
||||
nwGtpv1uMsgFromMsgNew( NW_IN NwGtpv1uStackHandleT hGtpuStackHandle,
|
||||
NW_IN NwGtpv1uMsgHandleT hMsg,
|
||||
NW_OUT NwGtpv1uMsgHandleT *phMsg)
|
||||
{
|
||||
NwGtpv1uStackT *pStack = (NwGtpv1uStackT *) hGtpuStackHandle;
|
||||
NwGtpv1uMsgT *pMsg;
|
||||
|
||||
if(gpGtpv1uMsgPool) {
|
||||
pMsg = gpGtpv1uMsgPool;
|
||||
gpGtpv1uMsgPool = gpGtpv1uMsgPool->next;
|
||||
} else {
|
||||
NW_GTPV1U_MALLOC(pStack, sizeof(NwGtpv1uMsgT), pMsg, NwGtpv1uMsgT *);
|
||||
}
|
||||
|
||||
|
||||
if(pMsg) {
|
||||
memcpy(pMsg, (NwGtpv1uMsgT *)hMsg, sizeof(NwGtpv1uMsgT));
|
||||
*phMsg = (NwGtpv1uMsgHandleT) pMsg;
|
||||
return NW_GTPV1U_OK;
|
||||
}
|
||||
return NW_GTPV1U_FAILURE;
|
||||
}
|
||||
|
||||
NwGtpv1uRcT
|
||||
nwGtpv1uMsgFromBufferNew( NW_IN NwGtpv1uStackHandleT hGtpuStackHandle,
|
||||
NW_IN NwU8T *pBuf,
|
||||
NW_IN NwU32T bufLen,
|
||||
NW_OUT NwGtpv1uMsgHandleT *phMsg)
|
||||
{
|
||||
NwGtpv1uStackT *pStack = (NwGtpv1uStackT *) hGtpuStackHandle;
|
||||
NwGtpv1uMsgT *pMsg;
|
||||
|
||||
if(gpGtpv1uMsgPool) {
|
||||
pMsg = gpGtpv1uMsgPool;
|
||||
gpGtpv1uMsgPool = gpGtpv1uMsgPool->next;
|
||||
} else {
|
||||
NW_GTPV1U_MALLOC(pStack, sizeof(NwGtpv1uMsgT), pMsg, NwGtpv1uMsgT *);
|
||||
}
|
||||
|
||||
|
||||
if(pMsg) {
|
||||
memcpy(pMsg->msgBuf, pBuf, bufLen);
|
||||
pMsg->msgLen = bufLen;
|
||||
|
||||
pMsg->version = ((*pBuf) & 0xE0) >> 5;
|
||||
pMsg->protocolType = ((*pBuf) & 0x10) >> 4;
|
||||
pMsg->extHdrFlag = ((*pBuf) & 0x04) >> 2;
|
||||
pMsg->seqNumFlag = ((*pBuf) & 0x02) >> 1;
|
||||
pMsg->npduNumFlag = ((*pBuf) & 0x01);
|
||||
pBuf++;
|
||||
|
||||
pMsg->msgType = *(pBuf);
|
||||
pBuf++;
|
||||
|
||||
pBuf += 2;
|
||||
|
||||
pMsg->teid = ntohl(*((NwU32T *)pBuf));
|
||||
pBuf += 4;
|
||||
|
||||
if(pMsg->extHdrFlag || pMsg->seqNumFlag || pMsg->npduNumFlag) {
|
||||
pMsg->seqNum = ntohs(*(((NwU16T *)pBuf)));
|
||||
pBuf += 2;
|
||||
pMsg->npduNum = *(pBuf++);
|
||||
pMsg->nextExtHdrType = *(pBuf++);
|
||||
}
|
||||
*phMsg = (NwGtpv1uMsgHandleT) pMsg;
|
||||
return NW_GTPV1U_OK;
|
||||
}
|
||||
return NW_GTPV1U_FAILURE;
|
||||
}
|
||||
|
||||
NwGtpv1uRcT
|
||||
nwGtpv1uMsgDelete( NW_IN NwGtpv1uStackHandleT hGtpuStackHandle,
|
||||
NW_IN NwGtpv1uMsgHandleT hMsg)
|
||||
{
|
||||
((NwGtpv1uMsgT *)hMsg)->next = gpGtpv1uMsgPool;
|
||||
gpGtpv1uMsgPool = (NwGtpv1uMsgT *) hMsg;
|
||||
return NW_GTPV1U_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set TEID for gtpv1u message.
|
||||
*
|
||||
* @param[in] hMsg : Message handle.
|
||||
* @param[in] teid: TEID value.
|
||||
*/
|
||||
|
||||
NwGtpv1uRcT
|
||||
nwGtpv1uMsgSetTeid(NW_IN NwGtpv1uMsgHandleT hMsg, NwU32T teid)
|
||||
{
|
||||
NwGtpv1uMsgT *thiz = (NwGtpv1uMsgT *) hMsg;
|
||||
thiz->teid = teid;
|
||||
printf("nwGtpv1uMsgSetTeid() teid %u", teid);
|
||||
return NW_GTPV1U_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set sequence for gtpv1u message.
|
||||
*
|
||||
* @param[in] hMsg : Message handle.
|
||||
* @param[in] seqNum: Flag boolean value.
|
||||
*/
|
||||
|
||||
NwGtpv1uRcT
|
||||
nwGtpv1uMsgSetSeqNumber(NW_IN NwGtpv1uMsgHandleT hMsg, NwU32T seqNum)
|
||||
{
|
||||
NwGtpv1uMsgT *thiz = (NwGtpv1uMsgT *) hMsg;
|
||||
thiz->seqNum = seqNum;
|
||||
return NW_GTPV1U_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get TEID present for gtpv1u message.
|
||||
*
|
||||
* @param[in] hMsg : Message handle.
|
||||
*/
|
||||
|
||||
NwU32T
|
||||
nwGtpv1uMsgGetTeid(NW_IN NwGtpv1uMsgHandleT hMsg)
|
||||
{
|
||||
NwGtpv1uMsgT *thiz = (NwGtpv1uMsgT *) hMsg;
|
||||
return (thiz->teid);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get sequence number for gtpv1u message.
|
||||
*
|
||||
* @param[in] hMsg : Message handle.
|
||||
*/
|
||||
|
||||
NwU32T
|
||||
nwGtpv1uMsgGetSeqNumber(NW_IN NwGtpv1uMsgHandleT hMsg)
|
||||
{
|
||||
NwGtpv1uMsgT *thiz = (NwGtpv1uMsgT *) hMsg;
|
||||
return (thiz->seqNum);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get msg type for gtpv1u message.
|
||||
*
|
||||
* @param[in] hMsg : Message handle.
|
||||
*/
|
||||
|
||||
NwU32T
|
||||
nwGtpv1uMsgGetMsgType(NW_IN NwGtpv1uMsgHandleT hMsg)
|
||||
{
|
||||
NwGtpv1uMsgT *thiz = (NwGtpv1uMsgT *) hMsg;
|
||||
return (thiz->msgType);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get tpdu for gtpv1u message.
|
||||
*
|
||||
* @param[in] hMsg : Message handle.
|
||||
*/
|
||||
|
||||
NwGtpv1uRcT
|
||||
nwGtpv1uMsgGetTpdu(NW_IN NwGtpv1uMsgHandleT hMsg, NwU8T *pTpduBuf,
|
||||
NwU32T *pTpduLength)
|
||||
{
|
||||
NwGtpv1uMsgT *thiz = (NwGtpv1uMsgT *) hMsg;
|
||||
NwU8T headerLength = ((thiz->seqNumFlag || thiz->extHdrFlag
|
||||
|| thiz->npduNumFlag) ? 12 : 8);
|
||||
|
||||
*pTpduLength = thiz->msgLen - headerLength;
|
||||
memcpy(pTpduBuf, thiz->msgBuf + headerLength, *pTpduLength);
|
||||
return NW_GTPV1U_OK;
|
||||
}
|
||||
|
||||
NwU8T *
|
||||
nwGtpv1uMsgGetTpduHandle(NW_IN NwGtpv1uMsgHandleT hMsg)
|
||||
{
|
||||
NwGtpv1uMsgT *thiz = (NwGtpv1uMsgT *) hMsg;
|
||||
return (thiz->msgBuf + ((thiz->seqNumFlag || thiz->extHdrFlag
|
||||
|| thiz->npduNumFlag) ? 12 : 8));
|
||||
}
|
||||
|
||||
NwU32T
|
||||
nwGtpv1uMsgGetTpduLength(NW_IN NwGtpv1uMsgHandleT hMsg)
|
||||
{
|
||||
NwGtpv1uMsgT *thiz = (NwGtpv1uMsgT *) hMsg;
|
||||
return (thiz->msgLen - ((thiz->seqNumFlag || thiz->extHdrFlag
|
||||
|| thiz->npduNumFlag) ? 12 : 8));
|
||||
}
|
||||
|
||||
NwGtpv1uRcT
|
||||
nwGtpv1uMsgAddIeTV1(NW_IN NwGtpv1uMsgHandleT hMsg,
|
||||
NW_IN NwU8T type,
|
||||
NW_IN NwU8T value)
|
||||
{
|
||||
NwGtpv1uMsgT *pMsg = (NwGtpv1uMsgT *) hMsg;
|
||||
NwGtpv1uIeTv1T *pIe;
|
||||
|
||||
pIe = (NwGtpv1uIeTv1T *) (pMsg->msgBuf + pMsg->msgLen);
|
||||
|
||||
pIe->t = type;
|
||||
pIe->v = value;
|
||||
|
||||
pMsg->msgLen += sizeof(NwGtpv1uIeTv1T);
|
||||
|
||||
return NW_GTPV1U_OK;
|
||||
}
|
||||
|
||||
NwGtpv1uRcT
|
||||
nwGtpv1uMsgAddIeTV2(NW_IN NwGtpv1uMsgHandleT hMsg,
|
||||
NW_IN NwU8T type,
|
||||
NW_IN NwU16T length,
|
||||
NW_IN NwU16T value)
|
||||
{
|
||||
NwGtpv1uMsgT *pMsg = (NwGtpv1uMsgT *) hMsg;
|
||||
NwGtpv1uIeTv2T *pIe;
|
||||
|
||||
pIe = (NwGtpv1uIeTv2T *) (pMsg->msgBuf + pMsg->msgLen);
|
||||
|
||||
pIe->t = type;
|
||||
pIe->v = htons(value);
|
||||
|
||||
pMsg->msgLen += sizeof(NwGtpv1uIeTv2T);
|
||||
|
||||
return NW_GTPV1U_OK;
|
||||
}
|
||||
|
||||
NwGtpv1uRcT
|
||||
nwGtpv1uMsgAddIeTV4(NW_IN NwGtpv1uMsgHandleT hMsg,
|
||||
NW_IN NwU8T type,
|
||||
NW_IN NwU16T length,
|
||||
NW_IN NwU32T value)
|
||||
{
|
||||
NwGtpv1uMsgT *pMsg = (NwGtpv1uMsgT *) hMsg;
|
||||
NwGtpv1uIeTv4T *pIe;
|
||||
|
||||
pIe = (NwGtpv1uIeTv4T *) (pMsg->msgBuf + pMsg->msgLen);
|
||||
|
||||
pIe->t = type;
|
||||
pIe->v = htonl(value);
|
||||
|
||||
pMsg->msgLen += sizeof(NwGtpv1uIeTv4T);
|
||||
|
||||
return NW_GTPV1U_OK;
|
||||
}
|
||||
|
||||
NwGtpv1uRcT
|
||||
nwGtpv1uMsgAddIe(NW_IN NwGtpv1uMsgHandleT hMsg,
|
||||
NW_IN NwU8T type,
|
||||
NW_IN NwU16T length,
|
||||
NW_IN NwU8T *pVal)
|
||||
{
|
||||
NwGtpv1uMsgT *pMsg = (NwGtpv1uMsgT *) hMsg;
|
||||
NwGtpv1uIeTlvT *pIe;
|
||||
|
||||
pIe = (NwGtpv1uIeTlvT *) (pMsg->msgBuf + pMsg->msgLen);
|
||||
|
||||
pIe->t = type;
|
||||
pIe->l = htons(length);
|
||||
|
||||
memcpy(pIe + 4, pVal, length);
|
||||
pMsg->msgLen += (4 + length);
|
||||
|
||||
return NW_GTPV1U_OK;
|
||||
}
|
||||
|
||||
NwGtpv1uRcT
|
||||
nwGtpv1uMsgHexDump(NwGtpv1uMsgHandleT hMsg, FILE *fp)
|
||||
{
|
||||
|
||||
NwGtpv1uMsgT *pMsg = (NwGtpv1uMsgT *) hMsg;
|
||||
NwU8T *data = pMsg->msgBuf;
|
||||
NwU32T size = pMsg->msgLen;
|
||||
|
||||
unsigned char *p = (unsigned char *)data;
|
||||
unsigned char c;
|
||||
int n;
|
||||
char bytestr[4] = {0};
|
||||
char addrstr[10] = {0};
|
||||
char hexstr[ 16*3 + 5] = {0};
|
||||
char charstr[16*1 + 5] = {0};
|
||||
fprintf((FILE *)fp, "\n");
|
||||
for(n=1; n<=size; n++) {
|
||||
if (n%16 == 1) {
|
||||
/* store address for this line */
|
||||
snprintf(addrstr, sizeof(addrstr), "%.4x",
|
||||
((unsigned int)p-(unsigned int)data) );
|
||||
}
|
||||
|
||||
c = *p;
|
||||
if (isalnum(c) == 0) {
|
||||
c = '.';
|
||||
}
|
||||
|
||||
/* store hex str (for left side) */
|
||||
snprintf(bytestr, sizeof(bytestr), "%02X ", *p);
|
||||
strncat(hexstr, bytestr, sizeof(hexstr)-strlen(hexstr)-1);
|
||||
|
||||
/* store char str (for right side) */
|
||||
snprintf(bytestr, sizeof(bytestr), "%c", c);
|
||||
strncat(charstr, bytestr, sizeof(charstr)-strlen(charstr)-1);
|
||||
if(n%16 == 0) {
|
||||
/* line completed */
|
||||
fprintf((FILE *)fp, "[%4.4s] %-50.50s %s\n", addrstr, hexstr, charstr);
|
||||
hexstr[0] = 0;
|
||||
charstr[0] = 0;
|
||||
} else if(n%8 == 0) {
|
||||
/* half line: add whitespaces */
|
||||
strncat(hexstr, " ", sizeof(hexstr)-strlen(hexstr)-1);
|
||||
strncat(charstr, " ", sizeof(charstr)-strlen(charstr)-1);
|
||||
}
|
||||
p++; /* next byte */
|
||||
}
|
||||
|
||||
if (strlen(hexstr) > 0) {
|
||||
/* print rest of buffer if not empty */
|
||||
fprintf((FILE *)fp, "[%4.4s] %-50.50s %s\n", addrstr, hexstr, charstr);
|
||||
|
||||
}
|
||||
fprintf((FILE *)fp, "\n");
|
||||
|
||||
return NW_GTPV1U_OK;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/*--------------------------------------------------------------------------*
|
||||
* E N D O F F I L E *
|
||||
*--------------------------------------------------------------------------*/
|
||||
@@ -0,0 +1,391 @@
|
||||
/*----------------------------------------------------------------------------*
|
||||
* *
|
||||
* n w - g t p v 2 u *
|
||||
* G P R S T u n n e l i n g P r o t o c o l v 2 u S t a c k *
|
||||
* *
|
||||
* *
|
||||
* Copyright (c) 2010-2011 Amit Chawre *
|
||||
* All rights reserved. *
|
||||
* *
|
||||
* Redistribution and use in source and binary forms, with or without *
|
||||
* modification, are permitted provided that the following conditions *
|
||||
* are met: *
|
||||
* *
|
||||
* 1. Redistributions of source code must retain the above copyright *
|
||||
* notice, this list of conditions and the following disclaimer. *
|
||||
* 2. Redistributions in binary form must reproduce the above copyright *
|
||||
* notice, this list of conditions and the following disclaimer in the *
|
||||
* documentation and/or other materials provided with the distribution. *
|
||||
* 3. The name of the author may not be used to endorse or promote products *
|
||||
* derived from this software without specific prior written permission. *
|
||||
* *
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR *
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES *
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. *
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, *
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT *
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, *
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY *
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT *
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF *
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include "NwTypes.h"
|
||||
#include "NwLog.h"
|
||||
#include "NwUtils.h"
|
||||
#include "NwGtpv1uLog.h"
|
||||
#include "NwGtpv1u.h"
|
||||
#include "NwGtpv1uPrivate.h"
|
||||
#include "NwGtpv1uTrxn.h"
|
||||
|
||||
/*--------------------------------------------------------------------------*
|
||||
* P R I V A T E D E C L A R A T I O N S *
|
||||
*--------------------------------------------------------------------------*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
static NwGtpv1uTrxnT *gpGtpv1uTrxnPool = NULL;
|
||||
|
||||
/*--------------------------------------------------------------------------*
|
||||
* P R I V A T E F U N C T I O N S *
|
||||
*--------------------------------------------------------------------------*/
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
* Send msg retransmission to peer via data request to UDP Entity
|
||||
*--------------------------------------------------------------------------*/
|
||||
|
||||
static NwGtpv1uRcT
|
||||
nwGtpv1uTrxnSendMsgRetransmission(NwGtpv1uTrxnT *thiz)
|
||||
{
|
||||
NwGtpv1uRcT rc;
|
||||
|
||||
NW_ASSERT(thiz);
|
||||
NW_ASSERT(thiz->pMsg);
|
||||
|
||||
rc = thiz->pStack->udp.udpDataReqCallback(thiz->pStack->udp.hUdp,
|
||||
thiz->pMsg->msgBuf,
|
||||
thiz->pMsg->msgLen,
|
||||
thiz->peerIp,
|
||||
thiz->peerPort);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static NwGtpv1uRcT
|
||||
nwGtpv1uTrxnPeerRspTimeout(void *arg)
|
||||
{
|
||||
NwGtpv1uRcT rc = NW_GTPV1U_OK;
|
||||
NwGtpv1uTrxnT *thiz;
|
||||
NwGtpv1uStackT *pStack;
|
||||
NwGtpv1uTimeoutInfoT *timeoutInfo = arg;
|
||||
|
||||
thiz = ((NwGtpv1uTrxnT *)timeoutInfo->timeoutArg);
|
||||
pStack = thiz->pStack;
|
||||
|
||||
NW_ASSERT(pStack);
|
||||
|
||||
NW_LOG(pStack, NW_LOG_LEVEL_WARN, "T3 timer expired for transaction 0x%x",
|
||||
(unsigned int)thiz);
|
||||
|
||||
rc = nwGtpv1uTrxnSendMsgRetransmission(thiz);
|
||||
|
||||
if(thiz->maxRetries) {
|
||||
rc = pStack->tmrMgr.tmrStartCallback(pStack->tmrMgr.tmrMgrHandle,
|
||||
thiz->t3Timer, 0, NW_GTPV1U_TMR_TYPE_ONE_SHOT, (void *)timeoutInfo,
|
||||
&thiz->hRspTmr);
|
||||
thiz->maxRetries--;
|
||||
} else {
|
||||
NwGtpv1uUlpApiT ulpApi;
|
||||
ulpApi.apiType = NW_GTPV1U_ULP_API_RSP_FAILURE;
|
||||
ulpApi.apiInfo.recvMsgInfo.msgType = nwGtpv1uMsgGetMsgType((
|
||||
NwGtpv1uMsgHandleT)thiz->pMsg);
|
||||
ulpApi.apiInfo.recvMsgInfo.hUlpTrxn = thiz->hUlpTrxn;
|
||||
ulpApi.apiInfo.recvMsgInfo.peerIp = thiz->peerIp;
|
||||
ulpApi.apiInfo.recvMsgInfo.peerPort = thiz->peerPort;
|
||||
thiz->hRspTmr = 0;
|
||||
|
||||
rc = nwGtpv1uTrxnDelete(&thiz);
|
||||
NW_ASSERT(rc == NW_GTPV1U_OK);
|
||||
|
||||
rc = pStack->ulp.ulpReqCallback(pStack->ulp.hUlp, &ulpApi);
|
||||
NW_ASSERT(rc == NW_GTPV1U_OK);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
Send timer start request to TmrMgr Entity.
|
||||
|
||||
@param[in] thiz : Pointer to transaction
|
||||
@param[in] timeoutCallbackFunc : Timeout handler callback function.
|
||||
@return NW_GTPV1U_OK on success.
|
||||
*/
|
||||
|
||||
static NwGtpv1uRcT
|
||||
nwGtpv1uTrxnStartPeerRspTimer(NwGtpv1uTrxnT *thiz,
|
||||
NwGtpv1uRcT (*timeoutCallbackFunc)(void *))
|
||||
{
|
||||
NwGtpv1uRcT rc;
|
||||
NwGtpv1uTimeoutInfoT *timeoutInfo;
|
||||
|
||||
NW_ASSERT(thiz->pStack->tmrMgr.tmrStartCallback != NULL);
|
||||
|
||||
timeoutInfo = &thiz->peerRspTimeoutInfo;
|
||||
timeoutInfo->timeoutArg = thiz;
|
||||
timeoutInfo->timeoutCallbackFunc = timeoutCallbackFunc;
|
||||
timeoutInfo->hStack = (NwGtpv1uStackHandleT)thiz->pStack;
|
||||
|
||||
rc = thiz->pStack->tmrMgr.tmrStartCallback(thiz->pStack->tmrMgr.tmrMgrHandle,
|
||||
thiz->t3Timer, 0, NW_GTPV1U_TMR_TYPE_ONE_SHOT, (void *)timeoutInfo,
|
||||
&thiz->hRspTmr);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
Send timer stop request to TmrMgr Entity.
|
||||
|
||||
@param[in] thiz : Pointer to transaction
|
||||
@return NW_GTPV1U_OK on success.
|
||||
*/
|
||||
|
||||
static NwGtpv1uRcT
|
||||
nwGtpv1uTrxnStopPeerRspTimer(NwGtpv1uTrxnT *thiz)
|
||||
{
|
||||
NwGtpv1uRcT rc;
|
||||
|
||||
NW_ASSERT(thiz->pStack->tmrMgr.tmrStopCallback != NULL);
|
||||
|
||||
rc = thiz->pStack->tmrMgr.tmrStopCallback(thiz->pStack->tmrMgr.tmrMgrHandle,
|
||||
thiz->hRspTmr);
|
||||
|
||||
thiz->hRspTmr = 0;
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*--------------------------------------------------------------------------*
|
||||
* P U B L I C F U N C T I O N S *
|
||||
*--------------------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param[in] thiz : Pointer to stack
|
||||
* @param[out] ppTrxn : Pointer to pointer to Trxn object.
|
||||
* @return NW_GTPV1U_OK on success.
|
||||
*/
|
||||
NwGtpv1uRcT
|
||||
nwGtpv1uTrxnNew( NW_IN NwGtpv1uStackT *thiz,
|
||||
NW_OUT NwGtpv1uTrxnT **ppTrxn)
|
||||
{
|
||||
NwGtpv1uRcT rc = NW_GTPV1U_OK;
|
||||
NwGtpv1uTrxnT *pTrxn;
|
||||
|
||||
if(gpGtpv1uTrxnPool) {
|
||||
pTrxn = gpGtpv1uTrxnPool;
|
||||
gpGtpv1uTrxnPool = gpGtpv1uTrxnPool->next;
|
||||
} else {
|
||||
NW_GTPV1U_MALLOC(thiz, sizeof(NwGtpv1uTrxnT), pTrxn, NwGtpv1uTrxnT *);
|
||||
}
|
||||
|
||||
if (pTrxn) {
|
||||
pTrxn->maxRetries = 2;
|
||||
pTrxn->pStack = thiz;
|
||||
pTrxn->t3Timer = 2;
|
||||
pTrxn->seqNum = thiz->seq;
|
||||
|
||||
/* Increment sequence number */
|
||||
thiz->seq++;
|
||||
if(thiz->seq == 0x800000) {
|
||||
thiz->seq = 0;
|
||||
}
|
||||
|
||||
} else {
|
||||
rc = NW_GTPV1U_FAILURE;
|
||||
}
|
||||
|
||||
NW_LOG(thiz, NW_LOG_LEVEL_DEBG, "Created transaction 0x%X", (unsigned int)pTrxn);
|
||||
|
||||
*ppTrxn = pTrxn;
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
* Overloaded Constructor
|
||||
*
|
||||
* @param[in] thiz : Pointer to stack.
|
||||
* @param[in] seqNum : Sequence number for this transaction.
|
||||
* @param[out] ppTrxn : Pointer to pointer to Trxn object.
|
||||
* @return NW_GTPV1U_OK on success.
|
||||
*/
|
||||
NwGtpv1uRcT
|
||||
nwGtpv1uTrxnWithSeqNew( NW_IN NwGtpv1uStackT *thiz,
|
||||
NW_IN NwU32T seqNum,
|
||||
NW_OUT NwGtpv1uTrxnT **ppTrxn)
|
||||
{
|
||||
NwGtpv1uRcT rc = NW_GTPV1U_OK;
|
||||
NwGtpv1uTrxnT *pTrxn;
|
||||
|
||||
if(gpGtpv1uTrxnPool) {
|
||||
pTrxn = gpGtpv1uTrxnPool;
|
||||
gpGtpv1uTrxnPool = gpGtpv1uTrxnPool->next;
|
||||
} else {
|
||||
NW_GTPV1U_MALLOC(thiz, sizeof(NwGtpv1uTrxnT), pTrxn, NwGtpv1uTrxnT *);
|
||||
}
|
||||
|
||||
|
||||
if (pTrxn) {
|
||||
pTrxn->maxRetries = 2;
|
||||
pTrxn->pStack = thiz;
|
||||
pTrxn->t3Timer = 2;
|
||||
pTrxn->seqNum = seqNum;
|
||||
pTrxn->pMsg = NULL;
|
||||
} else {
|
||||
rc = NW_GTPV1U_FAILURE;
|
||||
}
|
||||
|
||||
NW_LOG(thiz, NW_LOG_LEVEL_DEBG, "Created transaction 0x%X", (unsigned int)pTrxn);
|
||||
|
||||
*ppTrxn = pTrxn;
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*
|
||||
* @param[out] pthiz : Pointer to pointer to Trxn object.
|
||||
* @return NW_GTPV1U_OK on success.
|
||||
*/
|
||||
NwGtpv1uRcT
|
||||
nwGtpv1uTrxnDelete( NW_INOUT NwGtpv1uTrxnT **pthiz)
|
||||
{
|
||||
NwGtpv1uRcT rc = NW_GTPV1U_OK;
|
||||
NwGtpv1uStackT *pStack;
|
||||
NwGtpv1uTrxnT *thiz = *pthiz;
|
||||
|
||||
pStack = thiz->pStack;
|
||||
|
||||
if(thiz->hRspTmr) {
|
||||
rc = nwGtpv1uTrxnStopPeerRspTimer(thiz);
|
||||
NW_ASSERT(rc == NW_GTPV1U_OK);
|
||||
}
|
||||
|
||||
if(thiz->pMsg) {
|
||||
rc = nwGtpv1uMsgDelete((NwGtpv1uStackHandleT)pStack,
|
||||
(NwGtpv1uMsgHandleT)thiz->pMsg);
|
||||
NW_ASSERT(rc == NW_GTPV1U_OK);
|
||||
}
|
||||
|
||||
thiz->next = gpGtpv1uTrxnPool;
|
||||
gpGtpv1uTrxnPool = thiz;
|
||||
|
||||
NW_LOG(pStack, NW_LOG_LEVEL_DEBG, "Purged transaction 0x%X", (unsigned int)thiz);
|
||||
|
||||
*pthiz = NULL;
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
#if 1
|
||||
/**
|
||||
* Send msg to peer via data request to UDP Entity
|
||||
*
|
||||
* @param[in] thiz : Pointer to stack.
|
||||
* @param[in] pTrxn : Pointer to Trxn object.
|
||||
* @param[in] peerIp : Peer Ip address.
|
||||
* @param[in] peerPort : Peer Ip port.
|
||||
* @param[in] pMsg : Message to be sent.
|
||||
* @return NW_GTPV1U_OK on success.
|
||||
*/
|
||||
NwGtpv1uRcT
|
||||
nwGtpv1uTrxnCreateAndSendMsg( NW_IN NwGtpv1uStackT *thiz,
|
||||
NW_IN NwGtpv1uTrxnT *pTrxn,
|
||||
NW_IN NwU32T peerIp,
|
||||
NW_IN NwU32T peerPort,
|
||||
NW_IN NwGtpv1uMsgT *pMsg)
|
||||
{
|
||||
NwGtpv1uRcT rc;
|
||||
NwU8T *msgHdr;
|
||||
|
||||
NW_ASSERT(thiz);
|
||||
NW_ASSERT(pMsg);
|
||||
|
||||
msgHdr = pMsg->msgBuf;
|
||||
NW_ASSERT(msgHdr != NULL);
|
||||
|
||||
*(msgHdr++) = (pMsg->version << 5) |
|
||||
(pMsg->protocolType << 4) |
|
||||
(pMsg->extHdrFlag << 2) |
|
||||
(pMsg->seqNumFlag << 1) |
|
||||
(pMsg->npduNumFlag);
|
||||
|
||||
*(msgHdr++) = (pMsg->msgType);
|
||||
*((NwU16T *) msgHdr) = htons(pMsg->msgLen);
|
||||
msgHdr += 2;
|
||||
|
||||
*((NwU32T *) msgHdr) = htonl(pMsg->teid);
|
||||
msgHdr += 4;
|
||||
|
||||
if(pMsg->seqNumFlag | pMsg->extHdrFlag | pMsg->npduNumFlag) {
|
||||
if(pMsg->seqNumFlag) {
|
||||
*((NwU16T *) msgHdr) = htons((pTrxn ? pTrxn->seqNum : pMsg->seqNum));
|
||||
} else {
|
||||
*((NwU16T *) msgHdr) = 0x0000;
|
||||
}
|
||||
msgHdr += 2;
|
||||
|
||||
if(pMsg->npduNumFlag) {
|
||||
*((NwU8T *) msgHdr) = pMsg->npduNumFlag;
|
||||
} else {
|
||||
*((NwU8T *) msgHdr) = 0x00;
|
||||
}
|
||||
msgHdr++;
|
||||
|
||||
if(pMsg->extHdrFlag) {
|
||||
*((NwU8T *) msgHdr) = pMsg->extHdrFlag;
|
||||
} else {
|
||||
*((NwU8T *) msgHdr) = 0x00;
|
||||
}
|
||||
msgHdr++;
|
||||
}
|
||||
|
||||
NW_ASSERT(thiz->udp.udpDataReqCallback != NULL);
|
||||
|
||||
rc = thiz->udp.udpDataReqCallback(thiz->udp.hUdp,
|
||||
pMsg->msgBuf,
|
||||
pMsg->msgLen,
|
||||
peerIp,
|
||||
peerPort);
|
||||
|
||||
/* Save the message for retransmission */
|
||||
if(rc == NW_GTPV1U_OK && pTrxn) {
|
||||
pTrxn->pMsg = pMsg;
|
||||
pTrxn->peerIp = peerIp;
|
||||
pTrxn->peerPort = peerPort;
|
||||
|
||||
rc = nwGtpv1uTrxnStartPeerRspTimer(pTrxn, nwGtpv1uTrxnPeerRspTimeout);
|
||||
NW_ASSERT(rc == NW_GTPV1U_OK);
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
/*--------------------------------------------------------------------------*
|
||||
* E N D O F F I L E *
|
||||
*--------------------------------------------------------------------------*/
|
||||
@@ -0,0 +1,134 @@
|
||||
/*----------------------------------------------------------------------------*
|
||||
* *
|
||||
* n w - g t p v 2 u *
|
||||
* G P R S T u n n e l i n g P r o t o c o l v 2 u S t a c k *
|
||||
* *
|
||||
* *
|
||||
* Copyright (c) 2010-2011 Amit Chawre *
|
||||
* All rights reserved. *
|
||||
* *
|
||||
* Redistribution and use in source and binary forms, with or without *
|
||||
* modification, are permitted provided that the following conditions *
|
||||
* are met: *
|
||||
* *
|
||||
* 1. Redistributions of source code must retain the above copyright *
|
||||
* notice, this list of conditions and the following disclaimer. *
|
||||
* 2. Redistributions in binary form must reproduce the above copyright *
|
||||
* notice, this list of conditions and the following disclaimer in the *
|
||||
* documentation and/or other materials provided with the distribution. *
|
||||
* 3. The name of the author may not be used to endorse or promote products *
|
||||
* derived from this software without specific prior written permission. *
|
||||
* *
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR *
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES *
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. *
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, *
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT *
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, *
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY *
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT *
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF *
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "NwTypes.h"
|
||||
#include "NwUtils.h"
|
||||
#include "NwGtpv1uError.h"
|
||||
#include "NwGtpv1uPrivate.h"
|
||||
#include "NwGtpv1uMsg.h"
|
||||
#include "NwGtpv1uTunnelEndPoint.h"
|
||||
#include "NwGtpv1u.h"
|
||||
#include "NwGtpv1uLog.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*--------------------------------------------------------------------------*
|
||||
* P R I V A T E D E C L A R A T I O N S *
|
||||
*--------------------------------------------------------------------------*/
|
||||
|
||||
static NwGtpv1uTunnelEndPointT *gpTunnelEndPointPool = NULL;
|
||||
|
||||
/*--------------------------------------------------------------------------*
|
||||
* P U B L I C F U N C T I O N S *
|
||||
*--------------------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
Constructor
|
||||
|
||||
@param[in] msid: MSID
|
||||
@param[in] peerAddr: Address of the peer.
|
||||
@return Pointer to Session on success, NULL on failure.
|
||||
*/
|
||||
|
||||
|
||||
NwGtpv1uTunnelEndPointT *
|
||||
nwGtpTunnelEndPointNew(struct NwGtpv1uStack *pStack)
|
||||
{
|
||||
NwGtpv1uTunnelEndPointT *thiz;
|
||||
if(gpTunnelEndPointPool) {
|
||||
thiz = gpTunnelEndPointPool;
|
||||
gpTunnelEndPointPool = gpTunnelEndPointPool->next;
|
||||
} else {
|
||||
NW_GTPV1U_MALLOC(pStack, sizeof(NwGtpv1uTunnelEndPointT), thiz,
|
||||
NwGtpv1uTunnelEndPointT *);
|
||||
}
|
||||
|
||||
return thiz;
|
||||
}
|
||||
|
||||
/**
|
||||
Destructor
|
||||
|
||||
@param[in] thiz: Pointer to session
|
||||
@return NW_GTPV1U_OK on success.
|
||||
*/
|
||||
|
||||
NwGtpv1uRcT
|
||||
nwGtpTunnelEndPointDestroy(struct NwGtpv1uStack *pStack,
|
||||
NwGtpv1uTunnelEndPointT *thiz)
|
||||
{
|
||||
thiz->next = gpTunnelEndPointPool;
|
||||
gpTunnelEndPointPool = thiz;
|
||||
return NW_GTPV1U_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
Purge a Transaction for a Session.
|
||||
|
||||
@param[in] thiz: Pointer to session
|
||||
@param[in,out] pTrxn: Pointer to the trxn.
|
||||
@return NW_GTPV1U_OK on success.
|
||||
*/
|
||||
|
||||
NwGtpv1uRcT
|
||||
nwGtpSessionSendMsgApiToUlpEntity(NwGtpv1uTunnelEndPointT *thiz,
|
||||
NwGtpv1uMsgT *pMsg)
|
||||
{
|
||||
NwGtpv1uRcT rc = NW_GTPV1U_OK;
|
||||
NwGtpv1uUlpApiT api;
|
||||
|
||||
api.apiType = NW_GTPV1U_ULP_API_RECV_TPDU;
|
||||
api.apiInfo.recvMsgInfo.hUlpSession = thiz->hUlpSession;
|
||||
api.apiInfo.recvMsgInfo.teid = thiz->teid;
|
||||
api.apiInfo.recvMsgInfo.hMsg = (NwGtpv1uMsgHandleT)pMsg;
|
||||
|
||||
NW_ASSERT(thiz->pStack->ulp.ulpReqCallback != NULL);
|
||||
|
||||
thiz->pStack->ulp.ulpReqCallback(thiz->pStack->ulp.hUlp, &api);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
/*--------------------------------------------------------------------------*
|
||||
* E N D O F F I L E *
|
||||
*--------------------------------------------------------------------------*/
|
||||
@@ -0,0 +1,5 @@
|
||||
# this is example-file: Makefile.am
|
||||
|
||||
# the subdirectories of the project to go into
|
||||
SUBDIRS = \
|
||||
nw-helloworld
|
||||
@@ -0,0 +1,461 @@
|
||||
# Makefile.in generated by automake 1.10.1 from Makefile.am.
|
||||
# @configure_input@
|
||||
|
||||
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
|
||||
# 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
|
||||
# This Makefile.in is free software; the Free Software Foundation
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
# with or without modifications, as long as this notice is preserved.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
|
||||
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
# PARTICULAR PURPOSE.
|
||||
|
||||
@SET_MAKE@
|
||||
|
||||
# this is example-file: Makefile.am
|
||||
VPATH = @srcdir@
|
||||
pkgdatadir = $(datadir)/@PACKAGE@
|
||||
pkglibdir = $(libdir)/@PACKAGE@
|
||||
pkgincludedir = $(includedir)/@PACKAGE@
|
||||
am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
|
||||
install_sh_DATA = $(install_sh) -c -m 644
|
||||
install_sh_PROGRAM = $(install_sh) -c
|
||||
install_sh_SCRIPT = $(install_sh) -c
|
||||
INSTALL_HEADER = $(INSTALL_DATA)
|
||||
transform = $(program_transform_name)
|
||||
NORMAL_INSTALL = :
|
||||
PRE_INSTALL = :
|
||||
POST_INSTALL = :
|
||||
NORMAL_UNINSTALL = :
|
||||
PRE_UNINSTALL = :
|
||||
POST_UNINSTALL = :
|
||||
subdir = nw-gtpv1u/test-app
|
||||
DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
|
||||
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
|
||||
am__aclocal_m4_deps = $(top_srcdir)/configure.ac
|
||||
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
|
||||
$(ACLOCAL_M4)
|
||||
mkinstalldirs = $(install_sh) -d
|
||||
CONFIG_CLEAN_FILES =
|
||||
SOURCES =
|
||||
DIST_SOURCES =
|
||||
RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \
|
||||
html-recursive info-recursive install-data-recursive \
|
||||
install-dvi-recursive install-exec-recursive \
|
||||
install-html-recursive install-info-recursive \
|
||||
install-pdf-recursive install-ps-recursive install-recursive \
|
||||
installcheck-recursive installdirs-recursive pdf-recursive \
|
||||
ps-recursive uninstall-recursive
|
||||
RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \
|
||||
distclean-recursive maintainer-clean-recursive
|
||||
ETAGS = etags
|
||||
CTAGS = ctags
|
||||
DIST_SUBDIRS = $(SUBDIRS)
|
||||
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
|
||||
ACLOCAL = @ACLOCAL@
|
||||
AMTAR = @AMTAR@
|
||||
AM_CFLAGS = @AM_CFLAGS@
|
||||
AM_LDFLAGS = @AM_LDFLAGS@
|
||||
AUTOCONF = @AUTOCONF@
|
||||
AUTOHEADER = @AUTOHEADER@
|
||||
AUTOMAKE = @AUTOMAKE@
|
||||
AWK = @AWK@
|
||||
CC = @CC@
|
||||
CCDEPMODE = @CCDEPMODE@
|
||||
CFLAGS = @CFLAGS@
|
||||
CPP = @CPP@
|
||||
CPPFLAGS = @CPPFLAGS@
|
||||
CXX = @CXX@
|
||||
CXXCPP = @CXXCPP@
|
||||
CXXDEPMODE = @CXXDEPMODE@
|
||||
CXXFLAGS = @CXXFLAGS@
|
||||
CYGPATH_W = @CYGPATH_W@
|
||||
DEFS = @DEFS@
|
||||
DEPDIR = @DEPDIR@
|
||||
ECHO_C = @ECHO_C@
|
||||
ECHO_N = @ECHO_N@
|
||||
ECHO_T = @ECHO_T@
|
||||
EGREP = @EGREP@
|
||||
EXEEXT = @EXEEXT@
|
||||
GREP = @GREP@
|
||||
INSTALL = @INSTALL@
|
||||
INSTALL_DATA = @INSTALL_DATA@
|
||||
INSTALL_PROGRAM = @INSTALL_PROGRAM@
|
||||
INSTALL_SCRIPT = @INSTALL_SCRIPT@
|
||||
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
|
||||
LDFLAGS = @LDFLAGS@
|
||||
LIBOBJS = @LIBOBJS@
|
||||
LIBS = @LIBS@
|
||||
LTLIBOBJS = @LTLIBOBJS@
|
||||
MAKEINFO = @MAKEINFO@
|
||||
MKDIR_P = @MKDIR_P@
|
||||
OBJEXT = @OBJEXT@
|
||||
PACKAGE = @PACKAGE@
|
||||
PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
|
||||
PACKAGE_NAME = @PACKAGE_NAME@
|
||||
PACKAGE_STRING = @PACKAGE_STRING@
|
||||
PACKAGE_TARNAME = @PACKAGE_TARNAME@
|
||||
PACKAGE_VERSION = @PACKAGE_VERSION@
|
||||
PATH_SEPARATOR = @PATH_SEPARATOR@
|
||||
RANLIB = @RANLIB@
|
||||
SET_MAKE = @SET_MAKE@
|
||||
SHELL = @SHELL@
|
||||
STRIP = @STRIP@
|
||||
VERSION = @VERSION@
|
||||
abs_builddir = @abs_builddir@
|
||||
abs_srcdir = @abs_srcdir@
|
||||
abs_top_builddir = @abs_top_builddir@
|
||||
abs_top_srcdir = @abs_top_srcdir@
|
||||
ac_ct_CC = @ac_ct_CC@
|
||||
ac_ct_CXX = @ac_ct_CXX@
|
||||
am__include = @am__include@
|
||||
am__leading_dot = @am__leading_dot@
|
||||
am__quote = @am__quote@
|
||||
am__tar = @am__tar@
|
||||
am__untar = @am__untar@
|
||||
bindir = @bindir@
|
||||
build_alias = @build_alias@
|
||||
builddir = @builddir@
|
||||
datadir = @datadir@
|
||||
datarootdir = @datarootdir@
|
||||
docdir = @docdir@
|
||||
dvidir = @dvidir@
|
||||
exec_prefix = @exec_prefix@
|
||||
host_alias = @host_alias@
|
||||
htmldir = @htmldir@
|
||||
includedir = @includedir@
|
||||
infodir = @infodir@
|
||||
install_sh = @install_sh@
|
||||
libdir = @libdir@
|
||||
libexecdir = @libexecdir@
|
||||
localedir = @localedir@
|
||||
localstatedir = @localstatedir@
|
||||
mandir = @mandir@
|
||||
mkdir_p = @mkdir_p@
|
||||
oldincludedir = @oldincludedir@
|
||||
pdfdir = @pdfdir@
|
||||
prefix = @prefix@
|
||||
program_transform_name = @program_transform_name@
|
||||
psdir = @psdir@
|
||||
sbindir = @sbindir@
|
||||
sharedstatedir = @sharedstatedir@
|
||||
srcdir = @srcdir@
|
||||
sysconfdir = @sysconfdir@
|
||||
target_alias = @target_alias@
|
||||
top_builddir = @top_builddir@
|
||||
top_srcdir = @top_srcdir@
|
||||
|
||||
# the subdirectories of the project to go into
|
||||
SUBDIRS = \
|
||||
nw-helloworld
|
||||
|
||||
all: all-recursive
|
||||
|
||||
.SUFFIXES:
|
||||
$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
|
||||
@for dep in $?; do \
|
||||
case '$(am__configure_deps)' in \
|
||||
*$$dep*) \
|
||||
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \
|
||||
&& exit 0; \
|
||||
exit 1;; \
|
||||
esac; \
|
||||
done; \
|
||||
echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu nw-gtpv1u/test-app/Makefile'; \
|
||||
cd $(top_srcdir) && \
|
||||
$(AUTOMAKE) --gnu nw-gtpv1u/test-app/Makefile
|
||||
.PRECIOUS: Makefile
|
||||
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
|
||||
@case '$?' in \
|
||||
*config.status*) \
|
||||
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
|
||||
*) \
|
||||
echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
|
||||
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
|
||||
esac;
|
||||
|
||||
$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
|
||||
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
|
||||
|
||||
$(top_srcdir)/configure: $(am__configure_deps)
|
||||
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
|
||||
$(ACLOCAL_M4): $(am__aclocal_m4_deps)
|
||||
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
|
||||
|
||||
# This directory's subdirectories are mostly independent; you can cd
|
||||
# into them and run `make' without going through this Makefile.
|
||||
# To change the values of `make' variables: instead of editing Makefiles,
|
||||
# (1) if the variable is set in `config.status', edit `config.status'
|
||||
# (which will cause the Makefiles to be regenerated when you run `make');
|
||||
# (2) otherwise, pass the desired values on the `make' command line.
|
||||
$(RECURSIVE_TARGETS):
|
||||
@failcom='exit 1'; \
|
||||
for f in x $$MAKEFLAGS; do \
|
||||
case $$f in \
|
||||
*=* | --[!k]*);; \
|
||||
*k*) failcom='fail=yes';; \
|
||||
esac; \
|
||||
done; \
|
||||
dot_seen=no; \
|
||||
target=`echo $@ | sed s/-recursive//`; \
|
||||
list='$(SUBDIRS)'; for subdir in $$list; do \
|
||||
echo "Making $$target in $$subdir"; \
|
||||
if test "$$subdir" = "."; then \
|
||||
dot_seen=yes; \
|
||||
local_target="$$target-am"; \
|
||||
else \
|
||||
local_target="$$target"; \
|
||||
fi; \
|
||||
(cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
|
||||
|| eval $$failcom; \
|
||||
done; \
|
||||
if test "$$dot_seen" = "no"; then \
|
||||
$(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \
|
||||
fi; test -z "$$fail"
|
||||
|
||||
$(RECURSIVE_CLEAN_TARGETS):
|
||||
@failcom='exit 1'; \
|
||||
for f in x $$MAKEFLAGS; do \
|
||||
case $$f in \
|
||||
*=* | --[!k]*);; \
|
||||
*k*) failcom='fail=yes';; \
|
||||
esac; \
|
||||
done; \
|
||||
dot_seen=no; \
|
||||
case "$@" in \
|
||||
distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \
|
||||
*) list='$(SUBDIRS)' ;; \
|
||||
esac; \
|
||||
rev=''; for subdir in $$list; do \
|
||||
if test "$$subdir" = "."; then :; else \
|
||||
rev="$$subdir $$rev"; \
|
||||
fi; \
|
||||
done; \
|
||||
rev="$$rev ."; \
|
||||
target=`echo $@ | sed s/-recursive//`; \
|
||||
for subdir in $$rev; do \
|
||||
echo "Making $$target in $$subdir"; \
|
||||
if test "$$subdir" = "."; then \
|
||||
local_target="$$target-am"; \
|
||||
else \
|
||||
local_target="$$target"; \
|
||||
fi; \
|
||||
(cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
|
||||
|| eval $$failcom; \
|
||||
done && test -z "$$fail"
|
||||
tags-recursive:
|
||||
list='$(SUBDIRS)'; for subdir in $$list; do \
|
||||
test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \
|
||||
done
|
||||
ctags-recursive:
|
||||
list='$(SUBDIRS)'; for subdir in $$list; do \
|
||||
test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \
|
||||
done
|
||||
|
||||
ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
|
||||
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
|
||||
unique=`for i in $$list; do \
|
||||
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
|
||||
done | \
|
||||
$(AWK) '{ files[$$0] = 1; nonemtpy = 1; } \
|
||||
END { if (nonempty) { for (i in files) print i; }; }'`; \
|
||||
mkid -fID $$unique
|
||||
tags: TAGS
|
||||
|
||||
TAGS: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
|
||||
$(TAGS_FILES) $(LISP)
|
||||
tags=; \
|
||||
here=`pwd`; \
|
||||
if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \
|
||||
include_option=--etags-include; \
|
||||
empty_fix=.; \
|
||||
else \
|
||||
include_option=--include; \
|
||||
empty_fix=; \
|
||||
fi; \
|
||||
list='$(SUBDIRS)'; for subdir in $$list; do \
|
||||
if test "$$subdir" = .; then :; else \
|
||||
test ! -f $$subdir/TAGS || \
|
||||
tags="$$tags $$include_option=$$here/$$subdir/TAGS"; \
|
||||
fi; \
|
||||
done; \
|
||||
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
|
||||
unique=`for i in $$list; do \
|
||||
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
|
||||
done | \
|
||||
$(AWK) '{ files[$$0] = 1; nonempty = 1; } \
|
||||
END { if (nonempty) { for (i in files) print i; }; }'`; \
|
||||
if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
|
||||
test -n "$$unique" || unique=$$empty_fix; \
|
||||
$(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
|
||||
$$tags $$unique; \
|
||||
fi
|
||||
ctags: CTAGS
|
||||
CTAGS: ctags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
|
||||
$(TAGS_FILES) $(LISP)
|
||||
tags=; \
|
||||
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
|
||||
unique=`for i in $$list; do \
|
||||
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
|
||||
done | \
|
||||
$(AWK) '{ files[$$0] = 1; nonempty = 1; } \
|
||||
END { if (nonempty) { for (i in files) print i; }; }'`; \
|
||||
test -z "$(CTAGS_ARGS)$$tags$$unique" \
|
||||
|| $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
|
||||
$$tags $$unique
|
||||
|
||||
GTAGS:
|
||||
here=`$(am__cd) $(top_builddir) && pwd` \
|
||||
&& cd $(top_srcdir) \
|
||||
&& gtags -i $(GTAGS_ARGS) $$here
|
||||
|
||||
distclean-tags:
|
||||
-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
|
||||
|
||||
distdir: $(DISTFILES)
|
||||
@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
|
||||
topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
|
||||
list='$(DISTFILES)'; \
|
||||
dist_files=`for file in $$list; do echo $$file; done | \
|
||||
sed -e "s|^$$srcdirstrip/||;t" \
|
||||
-e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
|
||||
case $$dist_files in \
|
||||
*/*) $(MKDIR_P) `echo "$$dist_files" | \
|
||||
sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
|
||||
sort -u` ;; \
|
||||
esac; \
|
||||
for file in $$dist_files; do \
|
||||
if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
|
||||
if test -d $$d/$$file; then \
|
||||
dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
|
||||
if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
|
||||
cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
|
||||
fi; \
|
||||
cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
|
||||
else \
|
||||
test -f $(distdir)/$$file \
|
||||
|| cp -p $$d/$$file $(distdir)/$$file \
|
||||
|| exit 1; \
|
||||
fi; \
|
||||
done
|
||||
list='$(DIST_SUBDIRS)'; for subdir in $$list; do \
|
||||
if test "$$subdir" = .; then :; else \
|
||||
test -d "$(distdir)/$$subdir" \
|
||||
|| $(MKDIR_P) "$(distdir)/$$subdir" \
|
||||
|| exit 1; \
|
||||
distdir=`$(am__cd) $(distdir) && pwd`; \
|
||||
top_distdir=`$(am__cd) $(top_distdir) && pwd`; \
|
||||
(cd $$subdir && \
|
||||
$(MAKE) $(AM_MAKEFLAGS) \
|
||||
top_distdir="$$top_distdir" \
|
||||
distdir="$$distdir/$$subdir" \
|
||||
am__remove_distdir=: \
|
||||
am__skip_length_check=: \
|
||||
distdir) \
|
||||
|| exit 1; \
|
||||
fi; \
|
||||
done
|
||||
check-am: all-am
|
||||
check: check-recursive
|
||||
all-am: Makefile
|
||||
installdirs: installdirs-recursive
|
||||
installdirs-am:
|
||||
install: install-recursive
|
||||
install-exec: install-exec-recursive
|
||||
install-data: install-data-recursive
|
||||
uninstall: uninstall-recursive
|
||||
|
||||
install-am: all-am
|
||||
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
|
||||
|
||||
installcheck: installcheck-recursive
|
||||
install-strip:
|
||||
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
|
||||
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
|
||||
`test -z '$(STRIP)' || \
|
||||
echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
|
||||
mostlyclean-generic:
|
||||
|
||||
clean-generic:
|
||||
|
||||
distclean-generic:
|
||||
-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
|
||||
|
||||
maintainer-clean-generic:
|
||||
@echo "This command is intended for maintainers to use"
|
||||
@echo "it deletes files that may require special tools to rebuild."
|
||||
clean: clean-recursive
|
||||
|
||||
clean-am: clean-generic mostlyclean-am
|
||||
|
||||
distclean: distclean-recursive
|
||||
-rm -f Makefile
|
||||
distclean-am: clean-am distclean-generic distclean-tags
|
||||
|
||||
dvi: dvi-recursive
|
||||
|
||||
dvi-am:
|
||||
|
||||
html: html-recursive
|
||||
|
||||
info: info-recursive
|
||||
|
||||
info-am:
|
||||
|
||||
install-data-am:
|
||||
|
||||
install-dvi: install-dvi-recursive
|
||||
|
||||
install-exec-am:
|
||||
|
||||
install-html: install-html-recursive
|
||||
|
||||
install-info: install-info-recursive
|
||||
|
||||
install-man:
|
||||
|
||||
install-pdf: install-pdf-recursive
|
||||
|
||||
install-ps: install-ps-recursive
|
||||
|
||||
installcheck-am:
|
||||
|
||||
maintainer-clean: maintainer-clean-recursive
|
||||
-rm -f Makefile
|
||||
maintainer-clean-am: distclean-am maintainer-clean-generic
|
||||
|
||||
mostlyclean: mostlyclean-recursive
|
||||
|
||||
mostlyclean-am: mostlyclean-generic
|
||||
|
||||
pdf: pdf-recursive
|
||||
|
||||
pdf-am:
|
||||
|
||||
ps: ps-recursive
|
||||
|
||||
ps-am:
|
||||
|
||||
uninstall-am:
|
||||
|
||||
.MAKE: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) install-am \
|
||||
install-strip
|
||||
|
||||
.PHONY: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) CTAGS GTAGS \
|
||||
all all-am check check-am clean clean-generic ctags \
|
||||
ctags-recursive distclean distclean-generic distclean-tags \
|
||||
distdir dvi dvi-am html html-am info info-am install \
|
||||
install-am install-data install-data-am install-dvi \
|
||||
install-dvi-am install-exec install-exec-am install-html \
|
||||
install-html-am install-info install-info-am install-man \
|
||||
install-pdf install-pdf-am install-ps install-ps-am \
|
||||
install-strip installcheck installcheck-am installdirs \
|
||||
installdirs-am maintainer-clean maintainer-clean-generic \
|
||||
mostlyclean mostlyclean-generic pdf pdf-am ps ps-am tags \
|
||||
tags-recursive uninstall uninstall-am
|
||||
|
||||
# Tell versions [3.59,3.63) of GNU make to not export all variables.
|
||||
# Otherwise a system limit (for SysV at least) may be exceeded.
|
||||
.NOEXPORT:
|
||||
@@ -0,0 +1,17 @@
|
||||
bin_PROGRAMS = helloworld
|
||||
|
||||
AM_CFLAGS = -D__WITH_LIBEVENT__ -I../../shared -I../../include -I../../test-app/nw-udp -I../../test-app/nw-log @AM_CFLAGS@
|
||||
|
||||
helloworld_SOURCES = \
|
||||
NwEvt.h\
|
||||
NwMiniLogMgrEntity.h\
|
||||
NwMiniTmrMgrEntity.h\
|
||||
NwMiniUlpEntity.h\
|
||||
NwMiniUdpEntity.h\
|
||||
NwMiniLogMgrEntity.c\
|
||||
NwMiniTmrMgrEntity.c\
|
||||
NwMiniUlpEntity.c\
|
||||
NwMiniUdpEntity.c\
|
||||
helloworld.c
|
||||
|
||||
helloworld_LDADD = ../../src/libNwGtpv1u.a -levent $(AM_LDFLAGS)
|
||||
@@ -0,0 +1,433 @@
|
||||
# Makefile.in generated by automake 1.10.1 from Makefile.am.
|
||||
# @configure_input@
|
||||
|
||||
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
|
||||
# 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
|
||||
# This Makefile.in is free software; the Free Software Foundation
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
# with or without modifications, as long as this notice is preserved.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
|
||||
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
# PARTICULAR PURPOSE.
|
||||
|
||||
@SET_MAKE@
|
||||
|
||||
VPATH = @srcdir@
|
||||
pkgdatadir = $(datadir)/@PACKAGE@
|
||||
pkglibdir = $(libdir)/@PACKAGE@
|
||||
pkgincludedir = $(includedir)/@PACKAGE@
|
||||
am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
|
||||
install_sh_DATA = $(install_sh) -c -m 644
|
||||
install_sh_PROGRAM = $(install_sh) -c
|
||||
install_sh_SCRIPT = $(install_sh) -c
|
||||
INSTALL_HEADER = $(INSTALL_DATA)
|
||||
transform = $(program_transform_name)
|
||||
NORMAL_INSTALL = :
|
||||
PRE_INSTALL = :
|
||||
POST_INSTALL = :
|
||||
NORMAL_UNINSTALL = :
|
||||
PRE_UNINSTALL = :
|
||||
POST_UNINSTALL = :
|
||||
bin_PROGRAMS = helloworld$(EXEEXT)
|
||||
subdir = nw-gtpv1u/test-app/nw-helloworld
|
||||
DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
|
||||
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
|
||||
am__aclocal_m4_deps = $(top_srcdir)/configure.ac
|
||||
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
|
||||
$(ACLOCAL_M4)
|
||||
mkinstalldirs = $(install_sh) -d
|
||||
CONFIG_CLEAN_FILES =
|
||||
am__installdirs = "$(DESTDIR)$(bindir)"
|
||||
binPROGRAMS_INSTALL = $(INSTALL_PROGRAM)
|
||||
PROGRAMS = $(bin_PROGRAMS)
|
||||
am_helloworld_OBJECTS = NwMiniLogMgrEntity.$(OBJEXT) \
|
||||
NwMiniTmrMgrEntity.$(OBJEXT) NwMiniUlpEntity.$(OBJEXT) \
|
||||
NwMiniUdpEntity.$(OBJEXT) helloworld.$(OBJEXT)
|
||||
helloworld_OBJECTS = $(am_helloworld_OBJECTS)
|
||||
am__DEPENDENCIES_1 =
|
||||
helloworld_DEPENDENCIES = ../../src/libNwGtpv1u.a \
|
||||
$(am__DEPENDENCIES_1)
|
||||
DEFAULT_INCLUDES = -I.@am__isrc@
|
||||
depcomp = $(SHELL) $(top_srcdir)/depcomp
|
||||
am__depfiles_maybe = depfiles
|
||||
COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
|
||||
$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
|
||||
CCLD = $(CC)
|
||||
LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
|
||||
SOURCES = $(helloworld_SOURCES)
|
||||
DIST_SOURCES = $(helloworld_SOURCES)
|
||||
ETAGS = etags
|
||||
CTAGS = ctags
|
||||
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
|
||||
ACLOCAL = @ACLOCAL@
|
||||
AMTAR = @AMTAR@
|
||||
AM_CFLAGS = -D__WITH_LIBEVENT__ -I../../shared -I../../include -I../../test-app/nw-udp -I../../test-app/nw-log @AM_CFLAGS@
|
||||
AM_LDFLAGS = @AM_LDFLAGS@
|
||||
AUTOCONF = @AUTOCONF@
|
||||
AUTOHEADER = @AUTOHEADER@
|
||||
AUTOMAKE = @AUTOMAKE@
|
||||
AWK = @AWK@
|
||||
CC = @CC@
|
||||
CCDEPMODE = @CCDEPMODE@
|
||||
CFLAGS = @CFLAGS@
|
||||
CPP = @CPP@
|
||||
CPPFLAGS = @CPPFLAGS@
|
||||
CXX = @CXX@
|
||||
CXXCPP = @CXXCPP@
|
||||
CXXDEPMODE = @CXXDEPMODE@
|
||||
CXXFLAGS = @CXXFLAGS@
|
||||
CYGPATH_W = @CYGPATH_W@
|
||||
DEFS = @DEFS@
|
||||
DEPDIR = @DEPDIR@
|
||||
ECHO_C = @ECHO_C@
|
||||
ECHO_N = @ECHO_N@
|
||||
ECHO_T = @ECHO_T@
|
||||
EGREP = @EGREP@
|
||||
EXEEXT = @EXEEXT@
|
||||
GREP = @GREP@
|
||||
INSTALL = @INSTALL@
|
||||
INSTALL_DATA = @INSTALL_DATA@
|
||||
INSTALL_PROGRAM = @INSTALL_PROGRAM@
|
||||
INSTALL_SCRIPT = @INSTALL_SCRIPT@
|
||||
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
|
||||
LDFLAGS = @LDFLAGS@
|
||||
LIBOBJS = @LIBOBJS@
|
||||
LIBS = @LIBS@
|
||||
LTLIBOBJS = @LTLIBOBJS@
|
||||
MAKEINFO = @MAKEINFO@
|
||||
MKDIR_P = @MKDIR_P@
|
||||
OBJEXT = @OBJEXT@
|
||||
PACKAGE = @PACKAGE@
|
||||
PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
|
||||
PACKAGE_NAME = @PACKAGE_NAME@
|
||||
PACKAGE_STRING = @PACKAGE_STRING@
|
||||
PACKAGE_TARNAME = @PACKAGE_TARNAME@
|
||||
PACKAGE_VERSION = @PACKAGE_VERSION@
|
||||
PATH_SEPARATOR = @PATH_SEPARATOR@
|
||||
RANLIB = @RANLIB@
|
||||
SET_MAKE = @SET_MAKE@
|
||||
SHELL = @SHELL@
|
||||
STRIP = @STRIP@
|
||||
VERSION = @VERSION@
|
||||
abs_builddir = @abs_builddir@
|
||||
abs_srcdir = @abs_srcdir@
|
||||
abs_top_builddir = @abs_top_builddir@
|
||||
abs_top_srcdir = @abs_top_srcdir@
|
||||
ac_ct_CC = @ac_ct_CC@
|
||||
ac_ct_CXX = @ac_ct_CXX@
|
||||
am__include = @am__include@
|
||||
am__leading_dot = @am__leading_dot@
|
||||
am__quote = @am__quote@
|
||||
am__tar = @am__tar@
|
||||
am__untar = @am__untar@
|
||||
bindir = @bindir@
|
||||
build_alias = @build_alias@
|
||||
builddir = @builddir@
|
||||
datadir = @datadir@
|
||||
datarootdir = @datarootdir@
|
||||
docdir = @docdir@
|
||||
dvidir = @dvidir@
|
||||
exec_prefix = @exec_prefix@
|
||||
host_alias = @host_alias@
|
||||
htmldir = @htmldir@
|
||||
includedir = @includedir@
|
||||
infodir = @infodir@
|
||||
install_sh = @install_sh@
|
||||
libdir = @libdir@
|
||||
libexecdir = @libexecdir@
|
||||
localedir = @localedir@
|
||||
localstatedir = @localstatedir@
|
||||
mandir = @mandir@
|
||||
mkdir_p = @mkdir_p@
|
||||
oldincludedir = @oldincludedir@
|
||||
pdfdir = @pdfdir@
|
||||
prefix = @prefix@
|
||||
program_transform_name = @program_transform_name@
|
||||
psdir = @psdir@
|
||||
sbindir = @sbindir@
|
||||
sharedstatedir = @sharedstatedir@
|
||||
srcdir = @srcdir@
|
||||
sysconfdir = @sysconfdir@
|
||||
target_alias = @target_alias@
|
||||
top_builddir = @top_builddir@
|
||||
top_srcdir = @top_srcdir@
|
||||
helloworld_SOURCES = \
|
||||
NwEvt.h\
|
||||
NwMiniLogMgrEntity.h\
|
||||
NwMiniTmrMgrEntity.h\
|
||||
NwMiniUlpEntity.h\
|
||||
NwMiniUdpEntity.h\
|
||||
NwMiniLogMgrEntity.c\
|
||||
NwMiniTmrMgrEntity.c\
|
||||
NwMiniUlpEntity.c\
|
||||
NwMiniUdpEntity.c\
|
||||
helloworld.c
|
||||
|
||||
helloworld_LDADD = ../../src/libNwGtpv1u.a -levent $(AM_LDFLAGS)
|
||||
all: all-am
|
||||
|
||||
.SUFFIXES:
|
||||
.SUFFIXES: .c .o .obj
|
||||
$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
|
||||
@for dep in $?; do \
|
||||
case '$(am__configure_deps)' in \
|
||||
*$$dep*) \
|
||||
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \
|
||||
&& exit 0; \
|
||||
exit 1;; \
|
||||
esac; \
|
||||
done; \
|
||||
echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu nw-gtpv1u/test-app/nw-helloworld/Makefile'; \
|
||||
cd $(top_srcdir) && \
|
||||
$(AUTOMAKE) --gnu nw-gtpv1u/test-app/nw-helloworld/Makefile
|
||||
.PRECIOUS: Makefile
|
||||
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
|
||||
@case '$?' in \
|
||||
*config.status*) \
|
||||
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
|
||||
*) \
|
||||
echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
|
||||
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
|
||||
esac;
|
||||
|
||||
$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
|
||||
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
|
||||
|
||||
$(top_srcdir)/configure: $(am__configure_deps)
|
||||
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
|
||||
$(ACLOCAL_M4): $(am__aclocal_m4_deps)
|
||||
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
|
||||
install-binPROGRAMS: $(bin_PROGRAMS)
|
||||
@$(NORMAL_INSTALL)
|
||||
test -z "$(bindir)" || $(MKDIR_P) "$(DESTDIR)$(bindir)"
|
||||
@list='$(bin_PROGRAMS)'; for p in $$list; do \
|
||||
p1=`echo $$p|sed 's/$(EXEEXT)$$//'`; \
|
||||
if test -f $$p \
|
||||
; then \
|
||||
f=`echo "$$p1" | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'`; \
|
||||
echo " $(INSTALL_PROGRAM_ENV) $(binPROGRAMS_INSTALL) '$$p' '$(DESTDIR)$(bindir)/$$f'"; \
|
||||
$(INSTALL_PROGRAM_ENV) $(binPROGRAMS_INSTALL) "$$p" "$(DESTDIR)$(bindir)/$$f" || exit 1; \
|
||||
else :; fi; \
|
||||
done
|
||||
|
||||
uninstall-binPROGRAMS:
|
||||
@$(NORMAL_UNINSTALL)
|
||||
@list='$(bin_PROGRAMS)'; for p in $$list; do \
|
||||
f=`echo "$$p" | sed 's,^.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/'`; \
|
||||
echo " rm -f '$(DESTDIR)$(bindir)/$$f'"; \
|
||||
rm -f "$(DESTDIR)$(bindir)/$$f"; \
|
||||
done
|
||||
|
||||
clean-binPROGRAMS:
|
||||
-test -z "$(bin_PROGRAMS)" || rm -f $(bin_PROGRAMS)
|
||||
helloworld$(EXEEXT): $(helloworld_OBJECTS) $(helloworld_DEPENDENCIES)
|
||||
@rm -f helloworld$(EXEEXT)
|
||||
$(LINK) $(helloworld_OBJECTS) $(helloworld_LDADD) $(LIBS)
|
||||
|
||||
mostlyclean-compile:
|
||||
-rm -f *.$(OBJEXT)
|
||||
|
||||
distclean-compile:
|
||||
-rm -f *.tab.c
|
||||
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/NwMiniLogMgrEntity.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/NwMiniTmrMgrEntity.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/NwMiniUdpEntity.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/NwMiniUlpEntity.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/helloworld.Po@am__quote@
|
||||
|
||||
.c.o:
|
||||
@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
|
||||
@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCC_FALSE@ $(COMPILE) -c $<
|
||||
|
||||
.c.obj:
|
||||
@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
|
||||
@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
|
||||
|
||||
ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
|
||||
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
|
||||
unique=`for i in $$list; do \
|
||||
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
|
||||
done | \
|
||||
$(AWK) '{ files[$$0] = 1; nonemtpy = 1; } \
|
||||
END { if (nonempty) { for (i in files) print i; }; }'`; \
|
||||
mkid -fID $$unique
|
||||
tags: TAGS
|
||||
|
||||
TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
|
||||
$(TAGS_FILES) $(LISP)
|
||||
tags=; \
|
||||
here=`pwd`; \
|
||||
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
|
||||
unique=`for i in $$list; do \
|
||||
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
|
||||
done | \
|
||||
$(AWK) '{ files[$$0] = 1; nonempty = 1; } \
|
||||
END { if (nonempty) { for (i in files) print i; }; }'`; \
|
||||
if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
|
||||
test -n "$$unique" || unique=$$empty_fix; \
|
||||
$(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
|
||||
$$tags $$unique; \
|
||||
fi
|
||||
ctags: CTAGS
|
||||
CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
|
||||
$(TAGS_FILES) $(LISP)
|
||||
tags=; \
|
||||
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
|
||||
unique=`for i in $$list; do \
|
||||
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
|
||||
done | \
|
||||
$(AWK) '{ files[$$0] = 1; nonempty = 1; } \
|
||||
END { if (nonempty) { for (i in files) print i; }; }'`; \
|
||||
test -z "$(CTAGS_ARGS)$$tags$$unique" \
|
||||
|| $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
|
||||
$$tags $$unique
|
||||
|
||||
GTAGS:
|
||||
here=`$(am__cd) $(top_builddir) && pwd` \
|
||||
&& cd $(top_srcdir) \
|
||||
&& gtags -i $(GTAGS_ARGS) $$here
|
||||
|
||||
distclean-tags:
|
||||
-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
|
||||
|
||||
distdir: $(DISTFILES)
|
||||
@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
|
||||
topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
|
||||
list='$(DISTFILES)'; \
|
||||
dist_files=`for file in $$list; do echo $$file; done | \
|
||||
sed -e "s|^$$srcdirstrip/||;t" \
|
||||
-e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
|
||||
case $$dist_files in \
|
||||
*/*) $(MKDIR_P) `echo "$$dist_files" | \
|
||||
sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
|
||||
sort -u` ;; \
|
||||
esac; \
|
||||
for file in $$dist_files; do \
|
||||
if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
|
||||
if test -d $$d/$$file; then \
|
||||
dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
|
||||
if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
|
||||
cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
|
||||
fi; \
|
||||
cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
|
||||
else \
|
||||
test -f $(distdir)/$$file \
|
||||
|| cp -p $$d/$$file $(distdir)/$$file \
|
||||
|| exit 1; \
|
||||
fi; \
|
||||
done
|
||||
check-am: all-am
|
||||
check: check-am
|
||||
all-am: Makefile $(PROGRAMS)
|
||||
installdirs:
|
||||
for dir in "$(DESTDIR)$(bindir)"; do \
|
||||
test -z "$$dir" || $(MKDIR_P) "$$dir"; \
|
||||
done
|
||||
install: install-am
|
||||
install-exec: install-exec-am
|
||||
install-data: install-data-am
|
||||
uninstall: uninstall-am
|
||||
|
||||
install-am: all-am
|
||||
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
|
||||
|
||||
installcheck: installcheck-am
|
||||
install-strip:
|
||||
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
|
||||
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
|
||||
`test -z '$(STRIP)' || \
|
||||
echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
|
||||
mostlyclean-generic:
|
||||
|
||||
clean-generic:
|
||||
|
||||
distclean-generic:
|
||||
-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
|
||||
|
||||
maintainer-clean-generic:
|
||||
@echo "This command is intended for maintainers to use"
|
||||
@echo "it deletes files that may require special tools to rebuild."
|
||||
clean: clean-am
|
||||
|
||||
clean-am: clean-binPROGRAMS clean-generic mostlyclean-am
|
||||
|
||||
distclean: distclean-am
|
||||
-rm -rf ./$(DEPDIR)
|
||||
-rm -f Makefile
|
||||
distclean-am: clean-am distclean-compile distclean-generic \
|
||||
distclean-tags
|
||||
|
||||
dvi: dvi-am
|
||||
|
||||
dvi-am:
|
||||
|
||||
html: html-am
|
||||
|
||||
info: info-am
|
||||
|
||||
info-am:
|
||||
|
||||
install-data-am:
|
||||
|
||||
install-dvi: install-dvi-am
|
||||
|
||||
install-exec-am: install-binPROGRAMS
|
||||
|
||||
install-html: install-html-am
|
||||
|
||||
install-info: install-info-am
|
||||
|
||||
install-man:
|
||||
|
||||
install-pdf: install-pdf-am
|
||||
|
||||
install-ps: install-ps-am
|
||||
|
||||
installcheck-am:
|
||||
|
||||
maintainer-clean: maintainer-clean-am
|
||||
-rm -rf ./$(DEPDIR)
|
||||
-rm -f Makefile
|
||||
maintainer-clean-am: distclean-am maintainer-clean-generic
|
||||
|
||||
mostlyclean: mostlyclean-am
|
||||
|
||||
mostlyclean-am: mostlyclean-compile mostlyclean-generic
|
||||
|
||||
pdf: pdf-am
|
||||
|
||||
pdf-am:
|
||||
|
||||
ps: ps-am
|
||||
|
||||
ps-am:
|
||||
|
||||
uninstall-am: uninstall-binPROGRAMS
|
||||
|
||||
.MAKE: install-am install-strip
|
||||
|
||||
.PHONY: CTAGS GTAGS all all-am check check-am clean clean-binPROGRAMS \
|
||||
clean-generic ctags distclean distclean-compile \
|
||||
distclean-generic distclean-tags distdir dvi dvi-am html \
|
||||
html-am info info-am install install-am install-binPROGRAMS \
|
||||
install-data install-data-am install-dvi install-dvi-am \
|
||||
install-exec install-exec-am install-html install-html-am \
|
||||
install-info install-info-am install-man install-pdf \
|
||||
install-pdf-am install-ps install-ps-am install-strip \
|
||||
installcheck installcheck-am installdirs maintainer-clean \
|
||||
maintainer-clean-generic mostlyclean mostlyclean-compile \
|
||||
mostlyclean-generic pdf pdf-am ps ps-am tags uninstall \
|
||||
uninstall-am uninstall-binPROGRAMS
|
||||
|
||||
# Tell versions [3.59,3.63) of GNU make to not export all variables.
|
||||
# Otherwise a system limit (for SysV at least) may be exceeded.
|
||||
.NOEXPORT:
|
||||
@@ -0,0 +1,81 @@
|
||||
/*----------------------------------------------------------------------------*
|
||||
* *
|
||||
* Copyright (c) 2010-2011 Amit Chawre *
|
||||
* All rights reserved. *
|
||||
* *
|
||||
* Redistribution and use in source and binary forms, with or without *
|
||||
* modification, are permitted provided that the following conditions *
|
||||
* are met: *
|
||||
* *
|
||||
* 1. Redistributions of source code must retain the above copyright *
|
||||
* notice, this list of conditions and the following disclaimer. *
|
||||
* 2. Redistributions in binary form must reproduce the above copyright *
|
||||
* notice, this list of conditions and the following disclaimer in the *
|
||||
* documentation and/or other materials provided with the distribution. *
|
||||
* 3. The name of the author may not be used to endorse or promote products *
|
||||
* derived from this software without specific prior written permission. *
|
||||
* *
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR *
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES *
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. *
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, *
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT *
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, *
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY *
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT *
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF *
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef __NW_EVT_H__
|
||||
#define __NW_EVT_H__
|
||||
/**
|
||||
* @file NwEvt.h
|
||||
* @brief
|
||||
*/
|
||||
|
||||
#ifdef __WITH_LIBEVENT__
|
||||
|
||||
#include <event.h>
|
||||
|
||||
typedef struct event NwEventT;
|
||||
|
||||
#define NW_EVT_READ (EV_READ)
|
||||
#define NW_EVT_PERSIST (EV_PERSIST)
|
||||
#define NW_EVT_CALLBACK(__cbFunc) __cbFunc(int fd, short event, void *arg)
|
||||
#define NW_TMR_CALLBACK(__cbFunc) __cbFunc(int fd, short event, void *arg)
|
||||
|
||||
#define NW_EVT_INIT event_init
|
||||
#define NW_EVT_LOOP event_dispatch
|
||||
|
||||
#define NW_EVENT_ADD(__ev, __evSelObj, __evCallback, __evCallbackArg, __evFlags) \
|
||||
do { \
|
||||
event_set(&(__ev), __evSelObj, __evFlags, __evCallback, __evCallbackArg); \
|
||||
event_add(&(__ev), NULL); \
|
||||
} while(0)
|
||||
|
||||
#else
|
||||
|
||||
#warning "Event library not defined!"
|
||||
|
||||
/* HACK : Defining dummy values for compilation!*/
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int __tbd;
|
||||
} NwEventT;
|
||||
|
||||
#define NW_EVT_READ (0)
|
||||
#define NW_EVT_PERSIST (1)
|
||||
#define NW_EVT_CALLBACK(__cbFunc) __cbFunc(void *arg)
|
||||
#define NW_TMR_CALLBACK(__cbFunc) __cbFunc(void *arg)
|
||||
|
||||
|
||||
#define NW_EVT_INIT() do { printf("error: Event library not defined!\n"); exit (0); } while(0)
|
||||
#define NW_EVT_LOOP() do { printf("error: Event library not defined!\n"); exit (0); } while(0)
|
||||
#define NW_EVENT_ADD(...) do { printf("error: Event library not defined!\n"); exit (0); } while(0)
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* __NW_EVT_H__ */
|
||||
@@ -0,0 +1,60 @@
|
||||
/*----------------------------------------------------------------------------*
|
||||
* *
|
||||
* M I N I M A L I S T I C L O G M G R E N T I T Y *
|
||||
* *
|
||||
* Copyright (C) 2010 Amit Chawre. *
|
||||
* *
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @file hello-world.c
|
||||
* @brief This file contains example of a minimalistic log manager entity.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
#include "NwLog.h"
|
||||
#include "NwEvt.h"
|
||||
#include "NwGtpv1u.h"
|
||||
|
||||
#include "NwMiniLogMgrEntity.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
NwU32T g_log_level = NW_LOG_LEVEL_INFO;
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
* Public functions
|
||||
*--------------------------------------------------------------------------*/
|
||||
|
||||
NwGtpv1uRcT nwMiniLogMgrInit(NwMiniLogMgrT *thiz, NwU32T logLevel )
|
||||
{
|
||||
thiz->logLevel = logLevel;
|
||||
return NW_GTPV1U_OK;
|
||||
}
|
||||
|
||||
NwGtpv1uRcT nwMiniLogMgrSetLogLevel(NwMiniLogMgrT *thiz, NwU32T logLevel)
|
||||
{
|
||||
thiz->logLevel = logLevel;
|
||||
}
|
||||
|
||||
NwGtpv1uRcT nwMiniLogMgrLogRequest (NwGtpv1uLogMgrHandleT hLogMgr,
|
||||
NwU32T logLevel,
|
||||
NwCharT *file,
|
||||
NwU32T line,
|
||||
NwCharT *logStr)
|
||||
{
|
||||
NwMiniLogMgrT *thiz = (NwMiniLogMgrT *) hLogMgr;
|
||||
if(thiz->logLevel >= logLevel) {
|
||||
printf("NWGTPv2U-STK %s - %s <%s,%u>\n", gLogLevelStr[logLevel], logStr,
|
||||
basename(file), line);
|
||||
}
|
||||
return NW_GTPV1U_OK;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
/*----------------------------------------------------------------------------*
|
||||
* *
|
||||
* M I N I M A L I S T I C L O G M G R E N T I T Y *
|
||||
* *
|
||||
* Copyright (C) 2010 Amit Chawre. *
|
||||
* *
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @file hello-world.c
|
||||
* @brief This file contains example of a minimalistic log manager entity.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
#include "NwEvt.h"
|
||||
#include "NwLog.h"
|
||||
|
||||
#ifndef NW_ASSERT
|
||||
#define NW_ASSERT assert
|
||||
#endif
|
||||
|
||||
#ifndef __NW_MINI_LOG_MGR_H__
|
||||
#define __NW_MINI_LOG_MGR_H__
|
||||
|
||||
extern NwU32T g_log_level;
|
||||
|
||||
|
||||
#define NW_LOG( _logLevel, ...) \
|
||||
do { \
|
||||
if(g_log_level >= _logLevel) \
|
||||
{ \
|
||||
char _logStr[1024]; \
|
||||
snprintf(_logStr, 1024, __VA_ARGS__); \
|
||||
printf("NWGTPv2U-APP %s - %s <%s,%u>\n", gLogLevelStr[_logLevel], _logStr, basename(__FILE__), __LINE__);\
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
typedef struct
|
||||
{
|
||||
NwU8T logLevel;
|
||||
} NwMiniLogMgrT;
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
NwGtpv1uRcT nwMiniLogMgrLogRequest (NwGtpv1uLogMgrHandleT logMgrHandle,
|
||||
NwU32T logLevel,
|
||||
NwCharT* file,
|
||||
NwU32T line,
|
||||
NwCharT* logStr);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,101 @@
|
||||
/*----------------------------------------------------------------------------*
|
||||
* *
|
||||
* M I N I M A L I S T I C T M R M G R E N T I T Y *
|
||||
* *
|
||||
* Copyright (C) 2010 Amit Chawre. *
|
||||
* *
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @file NwMiniTmrMgrEntity.c
|
||||
* @brief This file ontains example of a minimalistic timer manager entity.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
#include "NwEvt.h"
|
||||
#include "NwGtpv1u.h"
|
||||
#include "NwMiniLogMgrEntity.h"
|
||||
#include "NwMiniTmrMgrEntity.h"
|
||||
|
||||
#ifndef NW_ASSERT
|
||||
#define NW_ASSERT assert
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
* Private functions
|
||||
*--------------------------------------------------------------------------*/
|
||||
|
||||
static void
|
||||
NW_TMR_CALLBACK(nwMiniTmrMgrHandleTimeout)
|
||||
{
|
||||
NwGtpv1uRcT rc;
|
||||
NwMiniTmrMgrEntityT *pTmr = (NwMiniTmrMgrEntityT *) arg;
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
* Send Timeout Request to GTPv1u Stack Instance
|
||||
*--------------------------------------------------------------------------*/
|
||||
|
||||
rc = nwGtpv1uProcessTimeout(pTmr->timeoutArg);
|
||||
NW_ASSERT( rc == NW_GTPV1U_OK );
|
||||
|
||||
free(pTmr);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
* Public functions
|
||||
*--------------------------------------------------------------------------*/
|
||||
|
||||
NwGtpv1uRcT nwTimerStart( NwGtpv1uTimerMgrHandleT tmrMgrHandle,
|
||||
NwU32T timeoutSec,
|
||||
NwU32T timeoutUsec,
|
||||
NwU32T tmrType,
|
||||
void *timeoutArg,
|
||||
NwGtpv1uTimerHandleT *hTmr)
|
||||
{
|
||||
NwGtpv1uRcT rc = NW_GTPV1U_OK;
|
||||
NwMiniTmrMgrEntityT *pTmr;
|
||||
struct timeval tv;
|
||||
|
||||
NW_LOG(NW_LOG_LEVEL_INFO,
|
||||
"Received start timer request from stack with timer type %u, arg %x, for %u sec and %u usec",
|
||||
tmrType, timeoutArg, timeoutSec, timeoutUsec);
|
||||
|
||||
pTmr = (NwMiniTmrMgrEntityT *) malloc (sizeof(NwMiniTmrMgrEntityT));
|
||||
|
||||
/* set the timevalues*/
|
||||
timerclear(&tv);
|
||||
tv.tv_sec = timeoutSec;
|
||||
tv.tv_usec = timeoutUsec;
|
||||
|
||||
pTmr->timeoutArg = timeoutArg;
|
||||
evtimer_set(&pTmr->ev, nwMiniTmrMgrHandleTimeout, pTmr);
|
||||
|
||||
/*add event*/
|
||||
|
||||
event_add(&(pTmr->ev), &tv);
|
||||
|
||||
*hTmr = (NwGtpv1uTimerHandleT)pTmr;
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
NwGtpv1uRcT nwTimerStop( NwGtpv1uTimerMgrHandleT tmrMgrHandle,
|
||||
NwGtpv1uTimerHandleT hTmr)
|
||||
{
|
||||
NW_LOG(NW_LOG_LEVEL_INFO,
|
||||
"Received stop timer request from stack for timer handle %u", hTmr);
|
||||
evtimer_del(&(((NwMiniTmrMgrEntityT *)hTmr)->ev));
|
||||
free((void *)hTmr);
|
||||
return NW_GTPV1U_OK;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,54 @@
|
||||
/*----------------------------------------------------------------------------*
|
||||
* *
|
||||
* M I N I M A L I S T I C T M R M G R E N T I T Y *
|
||||
* *
|
||||
* Copyright (C) 2010 Amit Chawre. *
|
||||
* *
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
/**
|
||||
* @file NwMiniTmrMgrEntity.c
|
||||
* @brief This file ontains example of a minimalistic timer manager entity.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
#include "NwEvt.h"
|
||||
#include "NwLog.h"
|
||||
|
||||
#ifndef NW_ASSERT
|
||||
#define NW_ASSERT assert
|
||||
#endif
|
||||
|
||||
#ifndef __NW_MINI_TMR_MGR_H__
|
||||
#define __NW_MINI_TMR_MGR_H__
|
||||
|
||||
typedef struct
|
||||
{
|
||||
NwEventT ev;
|
||||
void* timeoutArg;
|
||||
} NwMiniTmrMgrEntityT;
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
NwGtpv1uRcT nwTimerStart( NwGtpv1uTimerMgrHandleT tmrMgrHandle,
|
||||
NwU32T timeoutSec,
|
||||
NwU32T timeoutUsec,
|
||||
NwU32T tmrType,
|
||||
void* timeoutArg,
|
||||
NwGtpv1uTimerHandleT* hTmr);
|
||||
|
||||
|
||||
NwGtpv1uRcT nwTimerStop( NwGtpv1uTimerMgrHandleT tmrMgrHandle,
|
||||
NwGtpv1uTimerHandleT hTmr);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,155 @@
|
||||
/*----------------------------------------------------------------------------*
|
||||
* *
|
||||
* M I N I M A L I S T I C U D P E N T I T Y *
|
||||
* *
|
||||
* Copyright (C) 2010 Amit Chawre. *
|
||||
* *
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
/**
|
||||
* @file NwMiniUdpEntity.c
|
||||
* @brief This file contains example of a minimalistic ULP entity.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <sys/socket.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#include "NwEvt.h"
|
||||
#include "NwGtpv1u.h"
|
||||
#include "NwMiniLogMgrEntity.h"
|
||||
#include "NwMiniUdpEntity.h"
|
||||
|
||||
#ifndef NW_ASSERT
|
||||
#define NW_ASSERT assert
|
||||
#endif
|
||||
|
||||
#define MAX_UDP_PAYLOAD_LEN (4096)
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
* Private functions
|
||||
*--------------------------------------------------------------------------*/
|
||||
|
||||
static
|
||||
void NW_TMR_CALLBACK(nwUdpDataIndicationCallbackData)
|
||||
{
|
||||
NwGtpv1uRcT rc;
|
||||
NwU8T udpBuf[MAX_UDP_PAYLOAD_LEN];
|
||||
NwS32T bytesRead;
|
||||
NwU32T peerLen;
|
||||
struct sockaddr_in peer;
|
||||
NwMiniUdpEntityT *thiz = (NwMiniUdpEntityT *) arg;
|
||||
|
||||
peerLen = sizeof(peer);
|
||||
|
||||
bytesRead = recvfrom(thiz->hSocket, udpBuf, MAX_UDP_PAYLOAD_LEN , 0,
|
||||
(struct sockaddr *) &peer,(socklen_t *) &peerLen);
|
||||
if(bytesRead) {
|
||||
NW_LOG(NW_LOG_LEVEL_DEBG, "Received UDP message of length %u from %X:%u",
|
||||
bytesRead, ntohl(peer.sin_addr.s_addr), ntohs(peer.sin_port));
|
||||
rc = nwGtpv1uProcessUdpReq(thiz->hGtpv1uStack, udpBuf, bytesRead,
|
||||
peer.sin_port, peer.sin_addr.s_addr);
|
||||
} else {
|
||||
NW_LOG(NW_LOG_LEVEL_ERRO, "%s", strerror(errno));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
* Public functions
|
||||
*--------------------------------------------------------------------------*/
|
||||
|
||||
NwGtpv1uRcT nwMiniUdpInit(NwMiniUdpEntityT *thiz,
|
||||
NwGtpv1uStackHandleT hGtpv1uStack, NwU8T *ipAddr)
|
||||
{
|
||||
int sd;
|
||||
struct sockaddr_in addr;
|
||||
|
||||
sd = socket(AF_INET, SOCK_DGRAM, 0);
|
||||
|
||||
if (sd < 0) {
|
||||
NW_LOG(NW_LOG_LEVEL_ERRO, "%s", strerror(errno));
|
||||
NW_ASSERT(0);
|
||||
}
|
||||
|
||||
addr.sin_family = AF_INET;
|
||||
addr.sin_port = htons(2152);
|
||||
addr.sin_addr.s_addr = inet_addr(ipAddr);
|
||||
memset(addr.sin_zero, '\0', sizeof (addr.sin_zero));
|
||||
|
||||
if(bind(sd, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
|
||||
NW_LOG(NW_LOG_LEVEL_ERRO, "%s", strerror(errno));
|
||||
NW_ASSERT(0);
|
||||
}
|
||||
|
||||
event_set(&(thiz->ev), sd, EV_READ|EV_PERSIST, nwUdpDataIndicationCallbackData,
|
||||
thiz);
|
||||
event_add(&(thiz->ev), NULL);
|
||||
|
||||
thiz->hSocket = sd;
|
||||
thiz->hGtpv1uStack = hGtpv1uStack;
|
||||
|
||||
return NW_GTPV1U_OK;
|
||||
}
|
||||
|
||||
NwGtpv1uRcT nwMiniUdpDestroy(NwMiniUdpEntityT *thiz)
|
||||
{
|
||||
close(thiz->hSocket);
|
||||
}
|
||||
|
||||
NwGtpv1uRcT nwMiniUdpDataReq(NwGtpv1uUdpHandleT udpHandle,
|
||||
NwU8T *dataBuf,
|
||||
NwU32T dataSize,
|
||||
NwU32T peerIpAddr,
|
||||
NwU32T peerPort)
|
||||
{
|
||||
struct sockaddr_in peerAddr;
|
||||
NwS32T bytesSent;
|
||||
NwMiniUdpEntityT *thiz = (NwMiniUdpEntityT *) udpHandle;
|
||||
|
||||
peerAddr.sin_family = AF_INET;
|
||||
peerAddr.sin_port = htons(peerPort);
|
||||
peerAddr.sin_addr.s_addr = (peerIpAddr);
|
||||
memset(peerAddr.sin_zero, '\0', sizeof (peerAddr.sin_zero));
|
||||
|
||||
NW_LOG(NW_LOG_LEVEL_DEBG,
|
||||
"Sending %u bytes on handle 0x%x to peer %u.%u.%u.%u:%u", dataSize, udpHandle,
|
||||
(peerIpAddr & 0x000000ff),
|
||||
(peerIpAddr & 0x0000ff00) >> 8,
|
||||
(peerIpAddr & 0x00ff0000) >> 16,
|
||||
(peerIpAddr & 0xff000000) >> 24,
|
||||
peerPort);
|
||||
|
||||
bytesSent = sendto (thiz->hSocket, dataBuf, dataSize, 0,
|
||||
(struct sockaddr *) &peerAddr, sizeof(peerAddr));
|
||||
|
||||
if(bytesSent < 0) {
|
||||
NW_LOG(NW_LOG_LEVEL_ERRO, "%s", strerror(errno));
|
||||
} else {
|
||||
NW_LOG(NW_LOG_LEVEL_DEBG, "Sent %u bytes on handle 0x%x to peer %u.%u.%u.%u",
|
||||
dataSize, udpHandle,
|
||||
(peerIpAddr & 0x000000ff),
|
||||
(peerIpAddr & 0x0000ff00) >> 8,
|
||||
(peerIpAddr & 0x00ff0000) >> 16,
|
||||
(peerIpAddr & 0xff000000) >> 24);
|
||||
|
||||
}
|
||||
return NW_GTPV1U_OK;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
/*----------------------------------------------------------------------------*
|
||||
* *
|
||||
* M I N I M A L I S T I C U D P E N T I T Y *
|
||||
* *
|
||||
* Copyright (C) 2010 Amit Chawre. *
|
||||
* *
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
/**
|
||||
* @file NwMiniUdpEntity.h
|
||||
* @brief This file contains example of a minimalistic ULP entity.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
#include "NwEvt.h"
|
||||
#include "NwLog.h"
|
||||
|
||||
#ifndef NW_ASSERT
|
||||
#define NW_ASSERT assert
|
||||
#endif
|
||||
|
||||
#ifndef __NW_MINI_UDP_ENTITY_H__
|
||||
#define __NW_MINI_UDP_ENTITY_H__
|
||||
|
||||
typedef struct
|
||||
{
|
||||
NwU32T hSocket;
|
||||
NwEventT ev;
|
||||
NwGtpv1uStackHandleT hGtpv1uStack;
|
||||
} NwMiniUdpEntityT;
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
NwGtpv1uRcT nwMiniUdpInit(NwMiniUdpEntityT* thiz, NwGtpv1uStackHandleT hGtpv1uStack, NwU8T* ipAddr);
|
||||
|
||||
NwGtpv1uRcT nwMiniUdpDestroy(NwMiniUdpEntityT* thiz);
|
||||
|
||||
NwGtpv1uRcT nwMiniUdpDataReq(NwGtpv1uUdpHandleT udpHandle,
|
||||
NwU8T* dataBuf,
|
||||
NwU32T dataSize,
|
||||
NwU32T peerAddr,
|
||||
NwU32T peerPort);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,306 @@
|
||||
/*----------------------------------------------------------------------------*
|
||||
* *
|
||||
* M I N I M A L I S T I C U L P E N T I T Y *
|
||||
* *
|
||||
* Copyright (C) 2010 Amit Chawre. *
|
||||
* *
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @file NwMiniUlpEntity.c
|
||||
* @brief This file contains example of a minimalistic ULP entity.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <assert.h>
|
||||
#include "NwEvt.h"
|
||||
#include "NwGtpv1u.h"
|
||||
#include "NwGtpv1uIe.h"
|
||||
#include "NwMiniLogMgrEntity.h"
|
||||
#include "NwMiniUlpEntity.h"
|
||||
|
||||
#ifndef NW_ASSERT
|
||||
#define NW_ASSERT assert
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
* Private Functions
|
||||
*--------------------------------------------------------------------------*/
|
||||
|
||||
#define MAX_UDP_PAYLOAD_LEN (4096)
|
||||
|
||||
NwGtpv1uRcT
|
||||
nwMiniUlpSendEchoRequestToPeer(NwMiniUlpEntityT *thiz, NwU32T peerIp)
|
||||
{
|
||||
NwGtpv1uRcT rc;
|
||||
NwGtpv1uUlpApiT ulpReq;
|
||||
|
||||
/*
|
||||
* Send Message Request to Gtpv1u Stack Instance
|
||||
*/
|
||||
|
||||
ulpReq.apiType = NW_GTPV1U_ULP_API_INITIAL_REQ;
|
||||
|
||||
ulpReq.apiInfo.initialReqInfo.hUlpTrxn = (NwGtpv1uUlpTrxnHandleT)thiz;
|
||||
ulpReq.apiInfo.initialReqInfo.teid = 0x00;
|
||||
ulpReq.apiInfo.initialReqInfo.peerIp = (peerIp);
|
||||
ulpReq.apiInfo.initialReqInfo.peerPort = 2152;
|
||||
|
||||
/* Send Echo Request*/
|
||||
|
||||
rc = nwGtpv1uMsgNew( thiz->hGtpv1uStack,
|
||||
NW_TRUE, /* SeqNum flag */
|
||||
NW_FALSE,
|
||||
NW_FALSE,
|
||||
NW_GTP_ECHO_REQ, /* Msg Type */
|
||||
0x00000000UL, /* TEID */
|
||||
0x5678, /* Seq Number */
|
||||
0,
|
||||
0,
|
||||
(&ulpReq.hMsg));
|
||||
|
||||
NW_ASSERT( rc == NW_GTPV1U_OK );
|
||||
|
||||
rc = nwGtpv1uMsgAddIeTV1((ulpReq.hMsg), NW_GTPV1U_IE_RECOVERY,
|
||||
thiz->restartCounter);
|
||||
NW_ASSERT( rc == NW_GTPV1U_OK );
|
||||
|
||||
rc = nwGtpv1uProcessUlpReq(thiz->hGtpv1uStack, &ulpReq);
|
||||
NW_ASSERT( rc == NW_GTPV1U_OK );
|
||||
|
||||
return NW_GTPV1U_OK;
|
||||
}
|
||||
|
||||
static
|
||||
void NW_EVT_CALLBACK(nwMiniUlpDataIndicationCallbackData)
|
||||
{
|
||||
NwMiniUlpEntityT *thiz = (NwMiniUlpEntityT *) arg;
|
||||
NwGtpv1uRcT rc;
|
||||
NwU8T udpBuf[MAX_UDP_PAYLOAD_LEN];
|
||||
NwS32T bytesRead;
|
||||
NwU32T peerLen;
|
||||
struct sockaddr_in peer;
|
||||
|
||||
peerLen = sizeof(peer);
|
||||
|
||||
bytesRead = recvfrom(thiz->hSocket, udpBuf, MAX_UDP_PAYLOAD_LEN , 0,
|
||||
(struct sockaddr *) &peer,(socklen_t *) &peerLen);
|
||||
if(bytesRead) {
|
||||
NW_LOG(NW_LOG_LEVEL_DEBG, "Received UDP message of length %u from %X:%u",
|
||||
bytesRead, ntohl(peer.sin_addr.s_addr), ntohs(peer.sin_port));
|
||||
rc = nwMiniUlpTpduSend(thiz, udpBuf, bytesRead, thiz->localPort[fd]);
|
||||
} else {
|
||||
NW_LOG(NW_LOG_LEVEL_ERRO, "%s", strerror(errno));
|
||||
}
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
* Public Functions
|
||||
*--------------------------------------------------------------------------*/
|
||||
|
||||
NwGtpv1uRcT
|
||||
nwMiniUlpInit(NwMiniUlpEntityT *thiz, NwGtpv1uStackHandleT hGtpv1uStack)
|
||||
{
|
||||
NwGtpv1uRcT rc;
|
||||
thiz->hGtpv1uStack = hGtpv1uStack;
|
||||
|
||||
return NW_GTPV1U_OK;
|
||||
}
|
||||
|
||||
NwGtpv1uRcT
|
||||
nwMiniUlpDestroy(NwMiniUlpEntityT *thiz)
|
||||
{
|
||||
NW_ASSERT(thiz);
|
||||
memset(thiz, 0, sizeof(NwMiniUlpEntityT));
|
||||
return NW_GTPV1U_OK;
|
||||
}
|
||||
|
||||
NwGtpv1uRcT
|
||||
nwMiniUlpCreateConn(NwMiniUlpEntityT *thiz, char *localIpStr, NwU16T localport,
|
||||
char *peerIpStr)
|
||||
{
|
||||
NwGtpv1uRcT rc;
|
||||
int sd;
|
||||
struct sockaddr_in addr;
|
||||
NwGtpv1uUlpApiT ulpReq;
|
||||
|
||||
strcpy(thiz->peerIpStr, peerIpStr);
|
||||
|
||||
/*
|
||||
* Create local tunnel endpoint
|
||||
*/
|
||||
|
||||
NW_LOG(NW_LOG_LEVEL_NOTI, "Creating tunnel endpoint with teid %d", localport);
|
||||
ulpReq.apiType =
|
||||
NW_GTPV1U_ULP_API_CREATE_TUNNEL_ENDPOINT;
|
||||
ulpReq.apiInfo.createTunnelEndPointInfo.teid = localport;
|
||||
ulpReq.apiInfo.createTunnelEndPointInfo.hUlpSession =
|
||||
(NwGtpv1uUlpSessionHandleT)thiz;
|
||||
|
||||
rc = nwGtpv1uProcessUlpReq(thiz->hGtpv1uStack, &ulpReq);
|
||||
NW_ASSERT( rc == NW_GTPV1U_OK );
|
||||
|
||||
thiz->hGtpv1uConn = ulpReq.apiInfo.createTunnelEndPointInfo.hStackSession;
|
||||
|
||||
/*
|
||||
* Create local udp listening endpoint
|
||||
*/
|
||||
|
||||
sd = socket(AF_INET, SOCK_DGRAM, 0);
|
||||
|
||||
if (sd < 0) {
|
||||
NW_LOG(NW_LOG_LEVEL_ERRO, "%s", strerror(errno));
|
||||
NW_ASSERT(0);
|
||||
}
|
||||
|
||||
addr.sin_family = AF_INET;
|
||||
addr.sin_port = htons(localport);
|
||||
addr.sin_addr.s_addr = inet_addr(localIpStr);
|
||||
memset(addr.sin_zero, '\0', sizeof (addr.sin_zero));
|
||||
|
||||
if(bind(sd, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
|
||||
NW_LOG(NW_LOG_LEVEL_ERRO, "%s", strerror(errno));
|
||||
NW_ASSERT(0);
|
||||
}
|
||||
|
||||
event_set(&(thiz->ev[sd]), sd, EV_READ|EV_PERSIST,
|
||||
nwMiniUlpDataIndicationCallbackData, thiz);
|
||||
event_add(&(thiz->ev[sd]), NULL);
|
||||
|
||||
thiz->localPort[sd] = localport;
|
||||
|
||||
/*
|
||||
* Create local udp for sendign data
|
||||
*/
|
||||
|
||||
sd = socket(AF_INET, SOCK_DGRAM, 0);
|
||||
|
||||
if (sd < 0) {
|
||||
NW_LOG(NW_LOG_LEVEL_ERRO, "%s", strerror(errno));
|
||||
NW_ASSERT(0);
|
||||
}
|
||||
|
||||
|
||||
thiz->hSocket = sd;
|
||||
return NW_GTPV1U_OK;
|
||||
}
|
||||
|
||||
NwGtpv1uRcT
|
||||
nwMiniUlpDestroyConn(NwMiniUlpEntityT *thiz)
|
||||
{
|
||||
NwGtpv1uRcT rc;
|
||||
NwGtpv1uUlpApiT ulpReq;
|
||||
/*---------------------------------------------------------------------------
|
||||
* Send Destroy Session Request to GTPv1u Stack Instance
|
||||
*--------------------------------------------------------------------------*/
|
||||
|
||||
ulpReq.apiType = NW_GTPV1U_ULP_API_DESTROY_TUNNEL_ENDPOINT;
|
||||
ulpReq.apiInfo.destroyTunnelEndPointInfo.hStackSessionHandle = thiz->hGtpv1uConn;
|
||||
|
||||
rc = nwGtpv1uProcessUlpReq(thiz->hGtpv1uStack, &ulpReq);
|
||||
NW_ASSERT( rc == NW_GTPV1U_OK );
|
||||
|
||||
thiz->hGtpv1uConn = 0;
|
||||
|
||||
return NW_GTPV1U_OK;
|
||||
}
|
||||
|
||||
|
||||
NwGtpv1uRcT
|
||||
nwMiniUlpTpduSend(NwMiniUlpEntityT *thiz, NwU8T *tpduBuf, NwU32T tpduLen ,
|
||||
NwU16T fromPort)
|
||||
{
|
||||
NwGtpv1uRcT rc;
|
||||
NwGtpv1uUlpApiT ulpReq;
|
||||
|
||||
/*
|
||||
* Send Message Request to GTPv1u Stack Instance
|
||||
*/
|
||||
|
||||
ulpReq.apiType = NW_GTPV1U_ULP_API_SEND_TPDU;
|
||||
ulpReq.apiInfo.sendtoInfo.teid = fromPort;
|
||||
ulpReq.apiInfo.sendtoInfo.ipAddr = inet_addr(thiz->peerIpStr);
|
||||
|
||||
rc = nwGtpv1uGpduMsgNew( thiz->hGtpv1uStack,
|
||||
fromPort,
|
||||
NW_FALSE,
|
||||
thiz->seqNum++,
|
||||
tpduBuf,
|
||||
tpduLen,
|
||||
&(ulpReq.apiInfo.sendtoInfo.hMsg));
|
||||
|
||||
NW_ASSERT( rc == NW_GTPV1U_OK );
|
||||
|
||||
rc = nwGtpv1uProcessUlpReq(thiz->hGtpv1uStack, &ulpReq);
|
||||
NW_ASSERT( rc == NW_GTPV1U_OK );
|
||||
|
||||
rc = nwGtpv1uMsgDelete(thiz->hGtpv1uStack, (ulpReq.apiInfo.sendtoInfo.hMsg));
|
||||
NW_ASSERT( rc == NW_GTPV1U_OK );
|
||||
|
||||
return NW_GTPV1U_OK;
|
||||
}
|
||||
|
||||
NwGtpv1uRcT
|
||||
nwMiniUlpProcessStackReqCallback (NwGtpv1uUlpHandleT hUlp,
|
||||
NwGtpv1uUlpApiT *pUlpApi)
|
||||
{
|
||||
NwMiniUlpEntityT *thiz;
|
||||
NW_ASSERT(pUlpApi != NULL);
|
||||
|
||||
thiz = (NwMiniUlpEntityT *) hUlp;
|
||||
|
||||
switch(pUlpApi->apiType) {
|
||||
case NW_GTPV1U_ULP_API_RECV_TPDU: {
|
||||
struct sockaddr_in peerAddr;
|
||||
NwS32T bytesSent;
|
||||
NwU8T dataBuf[4096];
|
||||
NwU32T dataSize;
|
||||
NwU32T peerIpAddr = (inet_addr(thiz->peerIpStr));
|
||||
|
||||
NW_ASSERT( NW_GTPV1U_OK == nwGtpv1uMsgGetTpdu(pUlpApi->apiInfo.recvMsgInfo.hMsg,
|
||||
dataBuf, &dataSize) );
|
||||
|
||||
NW_LOG(NW_LOG_LEVEL_DEBG, "Received TPDU from gtpv1u stack %u!",
|
||||
pUlpApi->apiInfo.recvMsgInfo.teid);
|
||||
|
||||
peerAddr.sin_family = AF_INET;
|
||||
peerAddr.sin_port = htons(pUlpApi->apiInfo.recvMsgInfo.teid);
|
||||
peerAddr.sin_addr.s_addr = (peerIpAddr);
|
||||
memset(peerAddr.sin_zero, '\0', sizeof (peerAddr.sin_zero));
|
||||
|
||||
bytesSent = sendto (thiz->hSocket, dataBuf, dataSize, 0,
|
||||
(struct sockaddr *) &peerAddr, sizeof(peerAddr));
|
||||
|
||||
if(bytesSent < 0) {
|
||||
NW_LOG(NW_LOG_LEVEL_ERRO, "%s", strerror(errno));
|
||||
NW_ASSERT(0);
|
||||
} else {
|
||||
NW_LOG(NW_LOG_LEVEL_DEBG, "Sent %u bytes to peer %u.%u.%u.%u", dataSize,
|
||||
(peerIpAddr & 0x000000ff),
|
||||
(peerIpAddr & 0x0000ff00) >> 8,
|
||||
(peerIpAddr & 0x00ff0000) >> 16,
|
||||
(peerIpAddr & 0xff000000) >> 24);
|
||||
}
|
||||
|
||||
NW_ASSERT(nwGtpv1uMsgDelete(thiz->hGtpv1uStack,
|
||||
(pUlpApi->apiInfo.recvMsgInfo.hMsg)) == NW_GTPV1U_OK);
|
||||
|
||||
}
|
||||
break;
|
||||
default:
|
||||
NW_LOG(NW_LOG_LEVEL_WARN, "Received undefined UlpApi (%d) from gtpv1u stack!",
|
||||
pUlpApi->apiType);
|
||||
}
|
||||
return NW_GTPV1U_OK;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
/*----------------------------------------------------------------------------*
|
||||
* *
|
||||
* M I N I M A L I S T I C U L P E N T I T Y *
|
||||
* *
|
||||
* Copyright (C) 2010 Amit Chawre. *
|
||||
* *
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @file NwMiniUlpEntity.h
|
||||
* @brief This file contains example of a minimalistic ULP entity.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
#include "NwEvt.h"
|
||||
#include "NwLog.h"
|
||||
|
||||
#ifndef __NW_MINI_ULP_H__
|
||||
#define __NW_MINI_ULP_H__
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int hSocket;
|
||||
NwU16T seqNum;
|
||||
NwU8T restartCounter;
|
||||
NwU8T localIpStr[16];
|
||||
NwU8T peerIpStr[16];
|
||||
NwU32T localPort[1025];
|
||||
NwEventT ev[1025];
|
||||
NwGtpv1uStackHandleT hGtpv1uStack;
|
||||
NwGtpv1uStackSessionHandleT hGtpv1uConn;
|
||||
} NwMiniUlpEntityT;
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
NwGtpv1uRcT
|
||||
nwMiniUlpInit(NwMiniUlpEntityT* thiz, NwGtpv1uStackHandleT hGtpv1uStack);
|
||||
|
||||
NwGtpv1uRcT
|
||||
nwMiniUlpDestroy(NwMiniUlpEntityT* thiz);
|
||||
|
||||
NwGtpv1uRcT
|
||||
nwMiniUlpCreateConn(NwMiniUlpEntityT* thiz, char* localIpStr, NwU16T localPort, char* peerIpStr);
|
||||
|
||||
NwGtpv1uRcT
|
||||
nwMiniUlpDestroyConn(NwMiniUlpEntityT* thiz);
|
||||
|
||||
NwGtpv1uRcT
|
||||
nwMiniUlpSendMsg(NwMiniUlpEntityT* thiz);
|
||||
|
||||
NwGtpv1uRcT
|
||||
nwMiniUlpTpduSend(NwMiniUlpEntityT* thiz, NwU8T* tpduBuf, NwU32T tpduLen , NwU16T fromPort);
|
||||
|
||||
NwGtpv1uRcT
|
||||
nwMiniUlpProcessStackReqCallback (NwGtpv1uUlpHandleT hUlp,
|
||||
NwGtpv1uUlpApiT *pUlpApi);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,207 @@
|
||||
/*----------------------------------------------------------------------------*
|
||||
* *
|
||||
* n w - g t p v 2 u *
|
||||
* G P R S T u n n e l i n g P r o t o c o l v 2 u S t a c k *
|
||||
* *
|
||||
* M I N I M A L I S T I C D E M O N S T R A T I O N *
|
||||
* *
|
||||
* Copyright (C) 2010 Amit Chawre. *
|
||||
* *
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
/**
|
||||
* @file hello-world.c
|
||||
* @brief This is a test program demostrating usage of nw-gtpv2 library.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
#include "NwEvt.h"
|
||||
#include "NwGtpv1u.h"
|
||||
|
||||
#include "NwMiniLogMgrEntity.h"
|
||||
#include "NwMiniTmrMgrEntity.h"
|
||||
#include "NwMiniUdpEntity.h"
|
||||
#include "NwMiniUlpEntity.h"
|
||||
|
||||
#ifndef NW_ASSERT
|
||||
#define NW_ASSERT assert
|
||||
#endif
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
* T H E M A I N F U N C T I O N
|
||||
*--------------------------------------------------------------------------*/
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
NwGtpv1uRcT rc;
|
||||
char *logLevelStr;
|
||||
NwU32T logLevel;
|
||||
NwU32T num_of_connections;
|
||||
|
||||
NwGtpv1uStackHandleT hGtpv1uStack = 0;
|
||||
NwMiniUlpEntityT ulpObj;
|
||||
NwMiniUdpEntityT udpObj;
|
||||
NwMiniLogMgrT logObj;
|
||||
NwGtpv1uUlpEntityT ulp;
|
||||
NwGtpv1uUdpEntityT udp;
|
||||
NwGtpv1uTimerMgrEntityT tmrMgr;
|
||||
NwGtpv1uLogMgrEntityT logMgr;
|
||||
|
||||
if(argc != 4) {
|
||||
printf("Usage: %s <num-of-connections> <local-ip> <peer-ip>\n", argv[0]);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
|
||||
logLevelStr = getenv ("NW_LOG_LEVEL");
|
||||
|
||||
if(logLevelStr == NULL) {
|
||||
logLevel = NW_LOG_LEVEL_INFO;
|
||||
} else {
|
||||
if(strncmp(logLevelStr, "EMER",4) == 0) {
|
||||
logLevel = NW_LOG_LEVEL_EMER;
|
||||
} else if(strncmp(logLevelStr, "ALER",4) == 0) {
|
||||
logLevel = NW_LOG_LEVEL_ALER;
|
||||
} else if(strncmp(logLevelStr, "CRIT",4) == 0) {
|
||||
logLevel = NW_LOG_LEVEL_CRIT;
|
||||
} else if(strncmp(logLevelStr, "ERRO",4) == 0) {
|
||||
logLevel = NW_LOG_LEVEL_ERRO ;
|
||||
} else if(strncmp(logLevelStr, "WARN",4) == 0) {
|
||||
logLevel = NW_LOG_LEVEL_WARN;
|
||||
} else if(strncmp(logLevelStr, "NOTI",4) == 0) {
|
||||
logLevel = NW_LOG_LEVEL_NOTI;
|
||||
} else if(strncmp(logLevelStr, "INFO",4) == 0) {
|
||||
logLevel = NW_LOG_LEVEL_INFO;
|
||||
} else if(strncmp(logLevelStr, "DEBG",4) == 0) {
|
||||
logLevel = NW_LOG_LEVEL_DEBG;
|
||||
}
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
* Initialize event library
|
||||
*--------------------------------------------------------------------------*/
|
||||
|
||||
NW_EVT_INIT();
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
* Initialize Log Manager
|
||||
*--------------------------------------------------------------------------*/
|
||||
|
||||
nwMiniLogMgrInit(&logObj, logLevel);
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
* Create GTPv1u Stack Instance
|
||||
*--------------------------------------------------------------------------*/
|
||||
|
||||
rc = nwGtpv1uInitialize(&hGtpv1uStack);
|
||||
|
||||
if(rc != NW_GTPV1U_OK) {
|
||||
NW_LOG(NW_LOG_LEVEL_ERRO,
|
||||
"Failed to create gtpv1u stack instance. Error '%u' occured", rc);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
NW_LOG(NW_LOG_LEVEL_INFO, "Gtpv1u Stack Handle '%X' Creation Successful!",
|
||||
hGtpv1uStack);
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
* Set up Ulp Entity
|
||||
*--------------------------------------------------------------------------*/
|
||||
|
||||
rc = nwMiniUlpInit(&ulpObj, hGtpv1uStack);
|
||||
NW_ASSERT( rc == NW_GTPV1U_OK );
|
||||
|
||||
ulp.hUlp = (NwGtpv1uUlpHandleT) &ulpObj;
|
||||
ulp.ulpReqCallback = nwMiniUlpProcessStackReqCallback;
|
||||
|
||||
rc = nwGtpv1uSetUlpEntity(hGtpv1uStack, &ulp);
|
||||
NW_ASSERT( rc == NW_GTPV1U_OK );
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
* Set up Udp Entity
|
||||
*--------------------------------------------------------------------------*/
|
||||
|
||||
rc = nwMiniUdpInit(&udpObj, hGtpv1uStack, (argv[2]));
|
||||
NW_ASSERT( rc == NW_GTPV1U_OK );
|
||||
|
||||
udp.hUdp = (NwGtpv1uUdpHandleT) &udpObj;
|
||||
udp.udpDataReqCallback = nwMiniUdpDataReq;
|
||||
|
||||
rc = nwGtpv1uSetUdpEntity(hGtpv1uStack, &udp);
|
||||
NW_ASSERT( rc == NW_GTPV1U_OK );
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
* Set up Log Entity
|
||||
*--------------------------------------------------------------------------*/
|
||||
|
||||
tmrMgr.tmrMgrHandle = 0;
|
||||
tmrMgr.tmrStartCallback = nwTimerStart;
|
||||
tmrMgr.tmrStopCallback = nwTimerStop;
|
||||
|
||||
rc = nwGtpv1uSetTimerMgrEntity(hGtpv1uStack, &tmrMgr);
|
||||
NW_ASSERT( rc == NW_GTPV1U_OK );
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
* Set up Log Entity
|
||||
*--------------------------------------------------------------------------*/
|
||||
|
||||
logMgr.logMgrHandle = (NwGtpv1uLogMgrHandleT) &logObj;
|
||||
logMgr.logReqCallback = nwMiniLogMgrLogRequest;
|
||||
|
||||
rc = nwGtpv1uSetLogMgrEntity(hGtpv1uStack, &logMgr);
|
||||
NW_ASSERT( rc == NW_GTPV1U_OK );
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
* Set GTPv1u log level
|
||||
*--------------------------------------------------------------------------*/
|
||||
|
||||
rc = nwGtpv1uSetLogLevel(hGtpv1uStack, logLevel);
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
* Send Create Session Request to GTPv1u Stack Instance
|
||||
*--------------------------------------------------------------------------*/
|
||||
|
||||
num_of_connections = atoi(argv[1]);
|
||||
|
||||
while ( num_of_connections-- ) {
|
||||
//rc = nwMiniUlpCreateConn(&ulpObj, argv[2], 1234 + num_of_connections, argv[3]);
|
||||
rc = nwMiniUlpSendEchoRequestToPeer(&ulpObj, inet_addr(argv[3]));
|
||||
NW_ASSERT( rc == NW_GTPV1U_OK );
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
* Event loop
|
||||
*--------------------------------------------------------------------------*/
|
||||
|
||||
NW_EVT_LOOP();
|
||||
|
||||
NW_LOG(NW_LOG_LEVEL_ERRO, "Exit from eventloop, no events to process!");
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
* Send Destroy Session Request to GTPv1u Stack Instance
|
||||
*--------------------------------------------------------------------------*/
|
||||
|
||||
rc = nwMiniUlpDestroyConn(&ulpObj);
|
||||
NW_ASSERT( rc == NW_GTPV1U_OK );
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
* Destroy GTPv1u Stack Instance
|
||||
*--------------------------------------------------------------------------*/
|
||||
|
||||
rc = nwGtpv1uFinalize(hGtpv1uStack);
|
||||
|
||||
if(rc != NW_GTPV1U_OK) {
|
||||
NW_LOG(NW_LOG_LEVEL_ERRO,
|
||||
"Failed to finalize gtpv1u stack instance. Error '%u' occured", rc);
|
||||
} else {
|
||||
NW_LOG(NW_LOG_LEVEL_INFO, "Gtpv1u Stack Handle '%X' Finalize Successful!",
|
||||
hGtpv1uStack);
|
||||
}
|
||||
|
||||
|
||||
return rc;
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
SUBDIRS = nwgtpv2c-0.11/
|
||||
@@ -0,0 +1 @@
|
||||
Amit Chawre
|
||||
@@ -0,0 +1,26 @@
|
||||
Copyright (c) 2010-2011 Amit Chawre <http://www.amitchawre.net/contact.html>
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
3. The name of the author may not be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
@@ -0,0 +1,370 @@
|
||||
Installation Instructions
|
||||
*************************
|
||||
|
||||
Copyright (C) 1994-1996, 1999-2002, 2004-2011 Free Software Foundation,
|
||||
Inc.
|
||||
|
||||
Copying and distribution of this file, with or without modification,
|
||||
are permitted in any medium without royalty provided the copyright
|
||||
notice and this notice are preserved. This file is offered as-is,
|
||||
without warranty of any kind.
|
||||
|
||||
Basic Installation
|
||||
==================
|
||||
|
||||
Briefly, the shell commands `./configure; make; make install' should
|
||||
configure, build, and install this package. The following
|
||||
more-detailed instructions are generic; see the `README' file for
|
||||
instructions specific to this package. Some packages provide this
|
||||
`INSTALL' file but do not implement all of the features documented
|
||||
below. The lack of an optional feature in a given package is not
|
||||
necessarily a bug. More recommendations for GNU packages can be found
|
||||
in *note Makefile Conventions: (standards)Makefile Conventions.
|
||||
|
||||
The `configure' shell script attempts to guess correct values for
|
||||
various system-dependent variables used during compilation. It uses
|
||||
those values to create a `Makefile' in each directory of the package.
|
||||
It may also create one or more `.h' files containing system-dependent
|
||||
definitions. Finally, it creates a shell script `config.status' that
|
||||
you can run in the future to recreate the current configuration, and a
|
||||
file `config.log' containing compiler output (useful mainly for
|
||||
debugging `configure').
|
||||
|
||||
It can also use an optional file (typically called `config.cache'
|
||||
and enabled with `--cache-file=config.cache' or simply `-C') that saves
|
||||
the results of its tests to speed up reconfiguring. Caching is
|
||||
disabled by default to prevent problems with accidental use of stale
|
||||
cache files.
|
||||
|
||||
If you need to do unusual things to compile the package, please try
|
||||
to figure out how `configure' could check whether to do them, and mail
|
||||
diffs or instructions to the address given in the `README' so they can
|
||||
be considered for the next release. If you are using the cache, and at
|
||||
some point `config.cache' contains results you don't want to keep, you
|
||||
may remove or edit it.
|
||||
|
||||
The file `configure.ac' (or `configure.in') is used to create
|
||||
`configure' by a program called `autoconf'. You need `configure.ac' if
|
||||
you want to change it or regenerate `configure' using a newer version
|
||||
of `autoconf'.
|
||||
|
||||
The simplest way to compile this package is:
|
||||
|
||||
1. `cd' to the directory containing the package's source code and type
|
||||
`./configure' to configure the package for your system.
|
||||
|
||||
Running `configure' might take a while. While running, it prints
|
||||
some messages telling which features it is checking for.
|
||||
|
||||
2. Type `make' to compile the package.
|
||||
|
||||
3. Optionally, type `make check' to run any self-tests that come with
|
||||
the package, generally using the just-built uninstalled binaries.
|
||||
|
||||
4. Type `make install' to install the programs and any data files and
|
||||
documentation. When installing into a prefix owned by root, it is
|
||||
recommended that the package be configured and built as a regular
|
||||
user, and only the `make install' phase executed with root
|
||||
privileges.
|
||||
|
||||
5. Optionally, type `make installcheck' to repeat any self-tests, but
|
||||
this time using the binaries in their final installed location.
|
||||
This target does not install anything. Running this target as a
|
||||
regular user, particularly if the prior `make install' required
|
||||
root privileges, verifies that the installation completed
|
||||
correctly.
|
||||
|
||||
6. You can remove the program binaries and object files from the
|
||||
source code directory by typing `make clean'. To also remove the
|
||||
files that `configure' created (so you can compile the package for
|
||||
a different kind of computer), type `make distclean'. There is
|
||||
also a `make maintainer-clean' target, but that is intended mainly
|
||||
for the package's developers. If you use it, you may have to get
|
||||
all sorts of other programs in order to regenerate files that came
|
||||
with the distribution.
|
||||
|
||||
7. Often, you can also type `make uninstall' to remove the installed
|
||||
files again. In practice, not all packages have tested that
|
||||
uninstallation works correctly, even though it is required by the
|
||||
GNU Coding Standards.
|
||||
|
||||
8. Some packages, particularly those that use Automake, provide `make
|
||||
distcheck', which can by used by developers to test that all other
|
||||
targets like `make install' and `make uninstall' work correctly.
|
||||
This target is generally not run by end users.
|
||||
|
||||
Compilers and Options
|
||||
=====================
|
||||
|
||||
Some systems require unusual options for compilation or linking that
|
||||
the `configure' script does not know about. Run `./configure --help'
|
||||
for details on some of the pertinent environment variables.
|
||||
|
||||
You can give `configure' initial values for configuration parameters
|
||||
by setting variables in the command line or in the environment. Here
|
||||
is an example:
|
||||
|
||||
./configure CC=c99 CFLAGS=-g LIBS=-lposix
|
||||
|
||||
*Note Defining Variables::, for more details.
|
||||
|
||||
Compiling For Multiple Architectures
|
||||
====================================
|
||||
|
||||
You can compile the package for more than one kind of computer at the
|
||||
same time, by placing the object files for each architecture in their
|
||||
own directory. To do this, you can use GNU `make'. `cd' to the
|
||||
directory where you want the object files and executables to go and run
|
||||
the `configure' script. `configure' automatically checks for the
|
||||
source code in the directory that `configure' is in and in `..'. This
|
||||
is known as a "VPATH" build.
|
||||
|
||||
With a non-GNU `make', it is safer to compile the package for one
|
||||
architecture at a time in the source code directory. After you have
|
||||
installed the package for one architecture, use `make distclean' before
|
||||
reconfiguring for another architecture.
|
||||
|
||||
On MacOS X 10.5 and later systems, you can create libraries and
|
||||
executables that work on multiple system types--known as "fat" or
|
||||
"universal" binaries--by specifying multiple `-arch' options to the
|
||||
compiler but only a single `-arch' option to the preprocessor. Like
|
||||
this:
|
||||
|
||||
./configure CC="gcc -arch i386 -arch x86_64 -arch ppc -arch ppc64" \
|
||||
CXX="g++ -arch i386 -arch x86_64 -arch ppc -arch ppc64" \
|
||||
CPP="gcc -E" CXXCPP="g++ -E"
|
||||
|
||||
This is not guaranteed to produce working output in all cases, you
|
||||
may have to build one architecture at a time and combine the results
|
||||
using the `lipo' tool if you have problems.
|
||||
|
||||
Installation Names
|
||||
==================
|
||||
|
||||
By default, `make install' installs the package's commands under
|
||||
`/usr/local/bin', include files under `/usr/local/include', etc. You
|
||||
can specify an installation prefix other than `/usr/local' by giving
|
||||
`configure' the option `--prefix=PREFIX', where PREFIX must be an
|
||||
absolute file name.
|
||||
|
||||
You can specify separate installation prefixes for
|
||||
architecture-specific files and architecture-independent files. If you
|
||||
pass the option `--exec-prefix=PREFIX' to `configure', the package uses
|
||||
PREFIX as the prefix for installing programs and libraries.
|
||||
Documentation and other data files still use the regular prefix.
|
||||
|
||||
In addition, if you use an unusual directory layout you can give
|
||||
options like `--bindir=DIR' to specify different values for particular
|
||||
kinds of files. Run `configure --help' for a list of the directories
|
||||
you can set and what kinds of files go in them. In general, the
|
||||
default for these options is expressed in terms of `${prefix}', so that
|
||||
specifying just `--prefix' will affect all of the other directory
|
||||
specifications that were not explicitly provided.
|
||||
|
||||
The most portable way to affect installation locations is to pass the
|
||||
correct locations to `configure'; however, many packages provide one or
|
||||
both of the following shortcuts of passing variable assignments to the
|
||||
`make install' command line to change installation locations without
|
||||
having to reconfigure or recompile.
|
||||
|
||||
The first method involves providing an override variable for each
|
||||
affected directory. For example, `make install
|
||||
prefix=/alternate/directory' will choose an alternate location for all
|
||||
directory configuration variables that were expressed in terms of
|
||||
`${prefix}'. Any directories that were specified during `configure',
|
||||
but not in terms of `${prefix}', must each be overridden at install
|
||||
time for the entire installation to be relocated. The approach of
|
||||
makefile variable overrides for each directory variable is required by
|
||||
the GNU Coding Standards, and ideally causes no recompilation.
|
||||
However, some platforms have known limitations with the semantics of
|
||||
shared libraries that end up requiring recompilation when using this
|
||||
method, particularly noticeable in packages that use GNU Libtool.
|
||||
|
||||
The second method involves providing the `DESTDIR' variable. For
|
||||
example, `make install DESTDIR=/alternate/directory' will prepend
|
||||
`/alternate/directory' before all installation names. The approach of
|
||||
`DESTDIR' overrides is not required by the GNU Coding Standards, and
|
||||
does not work on platforms that have drive letters. On the other hand,
|
||||
it does better at avoiding recompilation issues, and works well even
|
||||
when some directory options were not specified in terms of `${prefix}'
|
||||
at `configure' time.
|
||||
|
||||
Optional Features
|
||||
=================
|
||||
|
||||
If the package supports it, you can cause programs to be installed
|
||||
with an extra prefix or suffix on their names by giving `configure' the
|
||||
option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'.
|
||||
|
||||
Some packages pay attention to `--enable-FEATURE' options to
|
||||
`configure', where FEATURE indicates an optional part of the package.
|
||||
They may also pay attention to `--with-PACKAGE' options, where PACKAGE
|
||||
is something like `gnu-as' or `x' (for the X Window System). The
|
||||
`README' should mention any `--enable-' and `--with-' options that the
|
||||
package recognizes.
|
||||
|
||||
For packages that use the X Window System, `configure' can usually
|
||||
find the X include and library files automatically, but if it doesn't,
|
||||
you can use the `configure' options `--x-includes=DIR' and
|
||||
`--x-libraries=DIR' to specify their locations.
|
||||
|
||||
Some packages offer the ability to configure how verbose the
|
||||
execution of `make' will be. For these packages, running `./configure
|
||||
--enable-silent-rules' sets the default to minimal output, which can be
|
||||
overridden with `make V=1'; while running `./configure
|
||||
--disable-silent-rules' sets the default to verbose, which can be
|
||||
overridden with `make V=0'.
|
||||
|
||||
Particular systems
|
||||
==================
|
||||
|
||||
On HP-UX, the default C compiler is not ANSI C compatible. If GNU
|
||||
CC is not installed, it is recommended to use the following options in
|
||||
order to use an ANSI C compiler:
|
||||
|
||||
./configure CC="cc -Ae -D_XOPEN_SOURCE=500"
|
||||
|
||||
and if that doesn't work, install pre-built binaries of GCC for HP-UX.
|
||||
|
||||
HP-UX `make' updates targets which have the same time stamps as
|
||||
their prerequisites, which makes it generally unusable when shipped
|
||||
generated files such as `configure' are involved. Use GNU `make'
|
||||
instead.
|
||||
|
||||
On OSF/1 a.k.a. Tru64, some versions of the default C compiler cannot
|
||||
parse its `<wchar.h>' header file. The option `-nodtk' can be used as
|
||||
a workaround. If GNU CC is not installed, it is therefore recommended
|
||||
to try
|
||||
|
||||
./configure CC="cc"
|
||||
|
||||
and if that doesn't work, try
|
||||
|
||||
./configure CC="cc -nodtk"
|
||||
|
||||
On Solaris, don't put `/usr/ucb' early in your `PATH'. This
|
||||
directory contains several dysfunctional programs; working variants of
|
||||
these programs are available in `/usr/bin'. So, if you need `/usr/ucb'
|
||||
in your `PATH', put it _after_ `/usr/bin'.
|
||||
|
||||
On Haiku, software installed for all users goes in `/boot/common',
|
||||
not `/usr/local'. It is recommended to use the following options:
|
||||
|
||||
./configure --prefix=/boot/common
|
||||
|
||||
Specifying the System Type
|
||||
==========================
|
||||
|
||||
There may be some features `configure' cannot figure out
|
||||
automatically, but needs to determine by the type of machine the package
|
||||
will run on. Usually, assuming the package is built to be run on the
|
||||
_same_ architectures, `configure' can figure that out, but if it prints
|
||||
a message saying it cannot guess the machine type, give it the
|
||||
`--build=TYPE' option. TYPE can either be a short name for the system
|
||||
type, such as `sun4', or a canonical name which has the form:
|
||||
|
||||
CPU-COMPANY-SYSTEM
|
||||
|
||||
where SYSTEM can have one of these forms:
|
||||
|
||||
OS
|
||||
KERNEL-OS
|
||||
|
||||
See the file `config.sub' for the possible values of each field. If
|
||||
`config.sub' isn't included in this package, then this package doesn't
|
||||
need to know the machine type.
|
||||
|
||||
If you are _building_ compiler tools for cross-compiling, you should
|
||||
use the option `--target=TYPE' to select the type of system they will
|
||||
produce code for.
|
||||
|
||||
If you want to _use_ a cross compiler, that generates code for a
|
||||
platform different from the build platform, you should specify the
|
||||
"host" platform (i.e., that on which the generated programs will
|
||||
eventually be run) with `--host=TYPE'.
|
||||
|
||||
Sharing Defaults
|
||||
================
|
||||
|
||||
If you want to set default values for `configure' scripts to share,
|
||||
you can create a site shell script called `config.site' that gives
|
||||
default values for variables like `CC', `cache_file', and `prefix'.
|
||||
`configure' looks for `PREFIX/share/config.site' if it exists, then
|
||||
`PREFIX/etc/config.site' if it exists. Or, you can set the
|
||||
`CONFIG_SITE' environment variable to the location of the site script.
|
||||
A warning: not all `configure' scripts look for a site script.
|
||||
|
||||
Defining Variables
|
||||
==================
|
||||
|
||||
Variables not defined in a site shell script can be set in the
|
||||
environment passed to `configure'. However, some packages may run
|
||||
configure again during the build, and the customized values of these
|
||||
variables may be lost. In order to avoid this problem, you should set
|
||||
them in the `configure' command line, using `VAR=value'. For example:
|
||||
|
||||
./configure CC=/usr/local2/bin/gcc
|
||||
|
||||
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 bug. Until the bug is fixed you can use this workaround:
|
||||
|
||||
CONFIG_SHELL=/bin/bash /bin/bash ./configure CONFIG_SHELL=/bin/bash
|
||||
|
||||
`configure' Invocation
|
||||
======================
|
||||
|
||||
`configure' recognizes the following options to control how it
|
||||
operates.
|
||||
|
||||
`--help'
|
||||
`-h'
|
||||
Print a summary of all of the options to `configure', and exit.
|
||||
|
||||
`--help=short'
|
||||
`--help=recursive'
|
||||
Print a summary of the options unique to this package's
|
||||
`configure', and exit. The `short' variant lists options used
|
||||
only in the top level, while the `recursive' variant lists options
|
||||
also present in any nested packages.
|
||||
|
||||
`--version'
|
||||
`-V'
|
||||
Print the version of Autoconf used to generate the `configure'
|
||||
script, and exit.
|
||||
|
||||
`--cache-file=FILE'
|
||||
Enable the cache: use and save the results of the tests in FILE,
|
||||
traditionally `config.cache'. FILE defaults to `/dev/null' to
|
||||
disable caching.
|
||||
|
||||
`--config-cache'
|
||||
`-C'
|
||||
Alias for `--cache-file=config.cache'.
|
||||
|
||||
`--quiet'
|
||||
`--silent'
|
||||
`-q'
|
||||
Do not print messages saying which checks are being made. To
|
||||
suppress all normal output, redirect it to `/dev/null' (any error
|
||||
messages will still be shown).
|
||||
|
||||
`--srcdir=DIR'
|
||||
Look for the package's source code in directory DIR. Usually
|
||||
`configure' can determine that directory automatically.
|
||||
|
||||
`--prefix=DIR'
|
||||
Use DIR as the installation prefix. *note Installation Names::
|
||||
for more details, including other options available for fine-tuning
|
||||
the installation locations.
|
||||
|
||||
`--no-create'
|
||||
`-n'
|
||||
Run the configure checks, but stop before creating any output
|
||||
files.
|
||||
|
||||
`configure' also accepts some other, not widely useful, options. Run
|
||||
`configure --help' for more details.
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
# this is example-file: Makefile.am
|
||||
|
||||
# the subdirectories of the project to go into
|
||||
SUBDIRS = \
|
||||
src\
|
||||
test-app
|
||||
@@ -0,0 +1,168 @@
|
||||
|
||||
INTRODUCTION
|
||||
------------
|
||||
|
||||
nwGtpv2c library is a free and open source implementation of GPRS Tunneling
|
||||
Protocol v2, also known as eGTP-C, as per 3GPP TS-29274.
|
||||
|
||||
The stack library supports transaction management, message creation and parsing,
|
||||
message validation, echo response and retransmission management. Other than
|
||||
this, timer and memory management functions are also built into the stack.
|
||||
|
||||
The library is published under BSD three clause license.
|
||||
|
||||
|
||||
DESIGN PHILOSPHY
|
||||
----------------
|
||||
|
||||
The stack is designed for high portability not only for the hardware and OS
|
||||
it will run on but also for the application software that uses it. The stack
|
||||
doesn't mandate conditions on the user application architecture or design.
|
||||
The stack relies on the user application for infrastructure utilities such
|
||||
as I/O, timers, logs and multithreading. This realized by using callback
|
||||
mechanisms and enables the stack library to seamlessly integrate without or
|
||||
very little changes to the existing application framework.
|
||||
|
||||
The stack is fully-asynchronous in design for compatibility with event loop
|
||||
mechanisms such as select, poll, etc. and can also be used for multi-threaded
|
||||
applications. It should compile on Linux, BSD, Mac OS X, Solaris and Windows
|
||||
(cygwin).
|
||||
|
||||
The stack architecture builds upon following mentioned entities that are
|
||||
external to it:
|
||||
|
||||
+-------------+ +---------+ +---------+
|
||||
| ULP ENTITY | | TMR MGR | | LOG MGR |
|
||||
+------+------+ +----+----+ +----+----+
|
||||
| | |
|
||||
+------+------------------+------------------+----+
|
||||
| |
|
||||
| NWGTPv2 STACK |
|
||||
| |
|
||||
+-------------------------+-----------------------+
|
||||
|
|
||||
+------+------+
|
||||
| UDP ENTITY |
|
||||
+-------------+
|
||||
|
||||
|
||||
- User Layer Protocol (ULP) Entity:
|
||||
This entity is the one which decides behaviour of the GTP user application.
|
||||
This layer implements the intelligent logic for the GTP application and sits
|
||||
on top of the GTP stack. This layer may also execute functions other than GTP
|
||||
procedures for example authetication.
|
||||
|
||||
- UDP Entity:
|
||||
This is the layer below the GTP stack and is responsible for UDP I/O between
|
||||
the stack and network. This layer shall manage the socket interface. This entity
|
||||
abstracts the stack library's view of the network. This may be useful in a
|
||||
multiprocess load balancing application wherein the GTP messages are received
|
||||
by a GTP load distribution entity and relayed to multiple GTP stacks over
|
||||
internal messaging. It may or may not be housed with/in ULP.
|
||||
|
||||
- Timer Manager Entity:
|
||||
Timer Manager Entity provides the GTP stack library with infrastructure for
|
||||
timer CRUD operations. It may or may not be housed with/in ULP.
|
||||
|
||||
- Log Manager Entity:
|
||||
Log Manager Entity provides the GTP stack library with callbacks for logging
|
||||
operations. It may or may not be housed with/in ULP.
|
||||
|
||||
|
||||
Optionally, there may be a user level "Stack Management Entity" which shall be
|
||||
resposible for creating and configuring the stack library, though the stack
|
||||
library is not aware of any such entity.
|
||||
|
||||
The application may implement all above entities as a single or multiple object.
|
||||
The external entities need to register callbacks with GTP stack library for
|
||||
receiving APIs from the stack library and stack library exposes API for the same.
|
||||
|
||||
The GTP stack library doesn't implement any execution threads of its own. It is
|
||||
up-to user application if it want to call the library APIs via multiple threads.
|
||||
The stack library, though, currently DOES NOT protect its critical section and
|
||||
hence, is NOT threadsafe.
|
||||
|
||||
|
||||
FEATURES
|
||||
--------
|
||||
|
||||
- TS 29.274 (Release 9) compliance target for gtp-c
|
||||
- Message Encoding
|
||||
- Reliable Message Delivery
|
||||
- Message Parser
|
||||
- Message Integrity and Error Checking
|
||||
- Support for S11, S5 and S8 SAE/EPC interfaces
|
||||
- Easy Application Integration
|
||||
|
||||
|
||||
APPLICATIONS
|
||||
------------
|
||||
|
||||
In general, the GTP stack library may be used to write any GTP version 2 based
|
||||
application.
|
||||
The GTP stack library can also be used by applications implementing LTE MME, SGW
|
||||
or PDN Gateways and simulators/emulators for either of them. Please see the test
|
||||
applications involving basic GTP procedures.
|
||||
|
||||
The test applications use libevent-1.4 library for I/O and timer infrastructure,
|
||||
(http://www.monkey.org/~provos/libevent-1.4.14b-stable.tar.gz).
|
||||
Following is a brief description of the test applications:
|
||||
|
||||
- nw-helloworld
|
||||
This is minimalistic program demostrating usage of nw-gtpv2 library. It
|
||||
demostrates ulp, udp, tmrmgr and logmgr entities as well as stack construction
|
||||
and destruction. The gtpv2c test application creates a transaction and sends
|
||||
a initial request messages over it.
|
||||
|
||||
- nw-egpting
|
||||
egtping is a utility for pinging a GPRS Tunneling Protocol (GTP) version 2,
|
||||
or Evolved GTP (eGTP) using Echo Request/Response.
|
||||
|
||||
- nw-epc
|
||||
The nw-epc software package is a free and open source framework implementation
|
||||
of SGW and PGW built upon nw-gtpv2.
|
||||
|
||||
|
||||
LICENSE
|
||||
-------
|
||||
|
||||
Copyright (c) 2010-2011 Amit Chawre <http://www.amitchawre.net/contact.html>
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
3. The name of the author may not be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
|
||||
DISCLAIMER
|
||||
----------
|
||||
|
||||
THIS INFORMATION IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
THIS INFORMATION, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
+986
@@ -0,0 +1,986 @@
|
||||
# generated automatically by aclocal 1.12 -*- Autoconf -*-
|
||||
|
||||
# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
|
||||
# 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation,
|
||||
# Inc.
|
||||
# This file is free software; the Free Software Foundation
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
# with or without modifications, as long as this notice is preserved.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
|
||||
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
# PARTICULAR PURPOSE.
|
||||
|
||||
m4_ifndef([AC_AUTOCONF_VERSION],
|
||||
[m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl
|
||||
m4_if(m4_defn([AC_AUTOCONF_VERSION]), [2.69],,
|
||||
[m4_warning([this file was generated for autoconf 2.69.
|
||||
You have another version of autoconf. It may work, but is not guaranteed to.
|
||||
If you have problems, you may need to regenerate the build system entirely.
|
||||
To do so, use the procedure documented by the package, typically 'autoreconf'.])])
|
||||
|
||||
# Copyright (C) 2002-2012 Free Software Foundation, Inc.
|
||||
#
|
||||
# This file is free software; the Free Software Foundation
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
# with or without modifications, as long as this notice is preserved.
|
||||
|
||||
# serial 8
|
||||
|
||||
# AM_AUTOMAKE_VERSION(VERSION)
|
||||
# ----------------------------
|
||||
# Automake X.Y traces this macro to ensure aclocal.m4 has been
|
||||
# generated from the m4 files accompanying Automake X.Y.
|
||||
# (This private macro should not be called outside this file.)
|
||||
AC_DEFUN([AM_AUTOMAKE_VERSION],
|
||||
[am__api_version='1.12'
|
||||
dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to
|
||||
dnl require some minimum version. Point them to the right macro.
|
||||
m4_if([$1], [1.12], [],
|
||||
[AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl
|
||||
])
|
||||
|
||||
# _AM_AUTOCONF_VERSION(VERSION)
|
||||
# -----------------------------
|
||||
# aclocal traces this macro to find the Autoconf version.
|
||||
# This is a private macro too. Using m4_define simplifies
|
||||
# the logic in aclocal, which can simply ignore this definition.
|
||||
m4_define([_AM_AUTOCONF_VERSION], [])
|
||||
|
||||
# AM_SET_CURRENT_AUTOMAKE_VERSION
|
||||
# -------------------------------
|
||||
# Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced.
|
||||
# This function is AC_REQUIREd by AM_INIT_AUTOMAKE.
|
||||
AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION],
|
||||
[AM_AUTOMAKE_VERSION([1.12])dnl
|
||||
m4_ifndef([AC_AUTOCONF_VERSION],
|
||||
[m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl
|
||||
_AM_AUTOCONF_VERSION(m4_defn([AC_AUTOCONF_VERSION]))])
|
||||
|
||||
# AM_AUX_DIR_EXPAND -*- Autoconf -*-
|
||||
|
||||
# Copyright (C) 2001-2012 Free Software Foundation, Inc.
|
||||
#
|
||||
# This file is free software; the Free Software Foundation
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
# with or without modifications, as long as this notice is preserved.
|
||||
|
||||
# serial 2
|
||||
|
||||
# For projects using AC_CONFIG_AUX_DIR([foo]), Autoconf sets
|
||||
# $ac_aux_dir to '$srcdir/foo'. In other projects, it is set to
|
||||
# '$srcdir', '$srcdir/..', or '$srcdir/../..'.
|
||||
#
|
||||
# Of course, Automake must honor this variable whenever it calls a
|
||||
# tool from the auxiliary directory. The problem is that $srcdir (and
|
||||
# therefore $ac_aux_dir as well) can be either absolute or relative,
|
||||
# depending on how configure is run. This is pretty annoying, since
|
||||
# it makes $ac_aux_dir quite unusable in subdirectories: in the top
|
||||
# source directory, any form will work fine, but in subdirectories a
|
||||
# relative path needs to be adjusted first.
|
||||
#
|
||||
# $ac_aux_dir/missing
|
||||
# fails when called from a subdirectory if $ac_aux_dir is relative
|
||||
# $top_srcdir/$ac_aux_dir/missing
|
||||
# fails if $ac_aux_dir is absolute,
|
||||
# fails when called from a subdirectory in a VPATH build with
|
||||
# a relative $ac_aux_dir
|
||||
#
|
||||
# The reason of the latter failure is that $top_srcdir and $ac_aux_dir
|
||||
# are both prefixed by $srcdir. In an in-source build this is usually
|
||||
# harmless because $srcdir is '.', but things will broke when you
|
||||
# start a VPATH build or use an absolute $srcdir.
|
||||
#
|
||||
# So we could use something similar to $top_srcdir/$ac_aux_dir/missing,
|
||||
# iff we strip the leading $srcdir from $ac_aux_dir. That would be:
|
||||
# am_aux_dir='\$(top_srcdir)/'`expr "$ac_aux_dir" : "$srcdir//*\(.*\)"`
|
||||
# and then we would define $MISSING as
|
||||
# MISSING="\${SHELL} $am_aux_dir/missing"
|
||||
# This will work as long as MISSING is not called from configure, because
|
||||
# unfortunately $(top_srcdir) has no meaning in configure.
|
||||
# However there are other variables, like CC, which are often used in
|
||||
# configure, and could therefore not use this "fixed" $ac_aux_dir.
|
||||
#
|
||||
# Another solution, used here, is to always expand $ac_aux_dir to an
|
||||
# absolute PATH. The drawback is that using absolute paths prevent a
|
||||
# configured tree to be moved without reconfiguration.
|
||||
|
||||
AC_DEFUN([AM_AUX_DIR_EXPAND],
|
||||
[dnl Rely on autoconf to set up CDPATH properly.
|
||||
AC_PREREQ([2.50])dnl
|
||||
# expand $ac_aux_dir to an absolute path
|
||||
am_aux_dir=`cd $ac_aux_dir && pwd`
|
||||
])
|
||||
|
||||
# AM_CONDITIONAL -*- Autoconf -*-
|
||||
|
||||
# Copyright (C) 1997-2012 Free Software Foundation, Inc.
|
||||
#
|
||||
# This file is free software; the Free Software Foundation
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
# with or without modifications, as long as this notice is preserved.
|
||||
|
||||
# serial 10
|
||||
|
||||
# AM_CONDITIONAL(NAME, SHELL-CONDITION)
|
||||
# -------------------------------------
|
||||
# Define a conditional.
|
||||
AC_DEFUN([AM_CONDITIONAL],
|
||||
[AC_PREREQ([2.52])dnl
|
||||
m4_if([$1], [TRUE], [AC_FATAL([$0: invalid condition: $1])],
|
||||
[$1], [FALSE], [AC_FATAL([$0: invalid condition: $1])])dnl
|
||||
AC_SUBST([$1_TRUE])dnl
|
||||
AC_SUBST([$1_FALSE])dnl
|
||||
_AM_SUBST_NOTMAKE([$1_TRUE])dnl
|
||||
_AM_SUBST_NOTMAKE([$1_FALSE])dnl
|
||||
m4_define([_AM_COND_VALUE_$1], [$2])dnl
|
||||
if $2; then
|
||||
$1_TRUE=
|
||||
$1_FALSE='#'
|
||||
else
|
||||
$1_TRUE='#'
|
||||
$1_FALSE=
|
||||
fi
|
||||
AC_CONFIG_COMMANDS_PRE(
|
||||
[if test -z "${$1_TRUE}" && test -z "${$1_FALSE}"; then
|
||||
AC_MSG_ERROR([[conditional "$1" was never defined.
|
||||
Usually this means the macro was only invoked conditionally.]])
|
||||
fi])])
|
||||
|
||||
# Copyright (C) 1999-2012 Free Software Foundation, Inc.
|
||||
#
|
||||
# This file is free software; the Free Software Foundation
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
# with or without modifications, as long as this notice is preserved.
|
||||
|
||||
# serial 16
|
||||
|
||||
# There are a few dirty hacks below to avoid letting 'AC_PROG_CC' be
|
||||
# written in clear, in which case automake, when reading aclocal.m4,
|
||||
# will think it sees a *use*, and therefore will trigger all it's
|
||||
# C support machinery. Also note that it means that autoscan, seeing
|
||||
# CC etc. in the Makefile, will ask for an AC_PROG_CC use...
|
||||
|
||||
|
||||
# _AM_DEPENDENCIES(NAME)
|
||||
# ----------------------
|
||||
# See how the compiler implements dependency checking.
|
||||
# NAME is "CC", "CXX", "GCJ", or "OBJC".
|
||||
# We try a few techniques and use that to set a single cache variable.
|
||||
#
|
||||
# We don't AC_REQUIRE the corresponding AC_PROG_CC since the latter was
|
||||
# modified to invoke _AM_DEPENDENCIES(CC); we would have a circular
|
||||
# dependency, and given that the user is not expected to run this macro,
|
||||
# just rely on AC_PROG_CC.
|
||||
AC_DEFUN([_AM_DEPENDENCIES],
|
||||
[AC_REQUIRE([AM_SET_DEPDIR])dnl
|
||||
AC_REQUIRE([AM_OUTPUT_DEPENDENCY_COMMANDS])dnl
|
||||
AC_REQUIRE([AM_MAKE_INCLUDE])dnl
|
||||
AC_REQUIRE([AM_DEP_TRACK])dnl
|
||||
|
||||
m4_if([$1], [CC], [depcc="$CC" am_compiler_list=],
|
||||
[$1], [CXX], [depcc="$CXX" am_compiler_list=],
|
||||
[$1], [OBJC], [depcc="$OBJC" am_compiler_list='gcc3 gcc'],
|
||||
[$1], [UPC], [depcc="$UPC" am_compiler_list=],
|
||||
[$1], [GCJ], [depcc="$GCJ" am_compiler_list='gcc3 gcc'],
|
||||
[depcc="$$1" am_compiler_list=])
|
||||
|
||||
AC_CACHE_CHECK([dependency style of $depcc],
|
||||
[am_cv_$1_dependencies_compiler_type],
|
||||
[if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then
|
||||
# We make a subdir and do the tests there. Otherwise we can end up
|
||||
# making bogus files that we don't know about and never remove. For
|
||||
# instance it was reported that on HP-UX the gcc test will end up
|
||||
# making a dummy file named 'D' -- because '-MD' means "put the output
|
||||
# in D".
|
||||
rm -rf conftest.dir
|
||||
mkdir conftest.dir
|
||||
# Copy depcomp to subdir because otherwise we won't find it if we're
|
||||
# using a relative directory.
|
||||
cp "$am_depcomp" conftest.dir
|
||||
cd conftest.dir
|
||||
# We will build objects and dependencies in a subdirectory because
|
||||
# it helps to detect inapplicable dependency modes. For instance
|
||||
# both Tru64's cc and ICC support -MD to output dependencies as a
|
||||
# side effect of compilation, but ICC will put the dependencies in
|
||||
# the current directory while Tru64 will put them in the object
|
||||
# directory.
|
||||
mkdir sub
|
||||
|
||||
am_cv_$1_dependencies_compiler_type=none
|
||||
if test "$am_compiler_list" = ""; then
|
||||
am_compiler_list=`sed -n ['s/^#*\([a-zA-Z0-9]*\))$/\1/p'] < ./depcomp`
|
||||
fi
|
||||
am__universal=false
|
||||
m4_case([$1], [CC],
|
||||
[case " $depcc " in #(
|
||||
*\ -arch\ *\ -arch\ *) am__universal=true ;;
|
||||
esac],
|
||||
[CXX],
|
||||
[case " $depcc " in #(
|
||||
*\ -arch\ *\ -arch\ *) am__universal=true ;;
|
||||
esac])
|
||||
|
||||
for depmode in $am_compiler_list; do
|
||||
# Setup a source with many dependencies, because some compilers
|
||||
# like to wrap large dependency lists on column 80 (with \), and
|
||||
# we should not choose a depcomp mode which is confused by this.
|
||||
#
|
||||
# We need to recreate these files for each test, as the compiler may
|
||||
# overwrite some of them when testing with obscure command lines.
|
||||
# This happens at least with the AIX C compiler.
|
||||
: > sub/conftest.c
|
||||
for i in 1 2 3 4 5 6; do
|
||||
echo '#include "conftst'$i'.h"' >> sub/conftest.c
|
||||
# Using ": > sub/conftst$i.h" creates only sub/conftst1.h with
|
||||
# Solaris 10 /bin/sh.
|
||||
echo '/* dummy */' > sub/conftst$i.h
|
||||
done
|
||||
echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf
|
||||
|
||||
# We check with '-c' and '-o' for the sake of the "dashmstdout"
|
||||
# mode. It turns out that the SunPro C++ compiler does not properly
|
||||
# handle '-M -o', and we need to detect this. Also, some Intel
|
||||
# versions had trouble with output in subdirs.
|
||||
am__obj=sub/conftest.${OBJEXT-o}
|
||||
am__minus_obj="-o $am__obj"
|
||||
case $depmode in
|
||||
gcc)
|
||||
# This depmode causes a compiler race in universal mode.
|
||||
test "$am__universal" = false || continue
|
||||
;;
|
||||
nosideeffect)
|
||||
# After this tag, mechanisms are not by side-effect, so they'll
|
||||
# only be used when explicitly requested.
|
||||
if test "x$enable_dependency_tracking" = xyes; then
|
||||
continue
|
||||
else
|
||||
break
|
||||
fi
|
||||
;;
|
||||
msvc7 | msvc7msys | msvisualcpp | msvcmsys)
|
||||
# This compiler won't grok '-c -o', but also, the minuso test has
|
||||
# not run yet. These depmodes are late enough in the game, and
|
||||
# so weak that their functioning should not be impacted.
|
||||
am__obj=conftest.${OBJEXT-o}
|
||||
am__minus_obj=
|
||||
;;
|
||||
none) break ;;
|
||||
esac
|
||||
if depmode=$depmode \
|
||||
source=sub/conftest.c object=$am__obj \
|
||||
depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \
|
||||
$SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \
|
||||
>/dev/null 2>conftest.err &&
|
||||
grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 &&
|
||||
grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 &&
|
||||
grep $am__obj sub/conftest.Po > /dev/null 2>&1 &&
|
||||
${MAKE-make} -s -f confmf > /dev/null 2>&1; then
|
||||
# icc doesn't choke on unknown options, it will just issue warnings
|
||||
# or remarks (even with -Werror). So we grep stderr for any message
|
||||
# that says an option was ignored or not supported.
|
||||
# When given -MP, icc 7.0 and 7.1 complain thusly:
|
||||
# icc: Command line warning: ignoring option '-M'; no argument required
|
||||
# The diagnosis changed in icc 8.0:
|
||||
# icc: Command line remark: option '-MP' not supported
|
||||
if (grep 'ignoring option' conftest.err ||
|
||||
grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else
|
||||
am_cv_$1_dependencies_compiler_type=$depmode
|
||||
break
|
||||
fi
|
||||
fi
|
||||
done
|
||||
|
||||
cd ..
|
||||
rm -rf conftest.dir
|
||||
else
|
||||
am_cv_$1_dependencies_compiler_type=none
|
||||
fi
|
||||
])
|
||||
AC_SUBST([$1DEPMODE], [depmode=$am_cv_$1_dependencies_compiler_type])
|
||||
AM_CONDITIONAL([am__fastdep$1], [
|
||||
test "x$enable_dependency_tracking" != xno \
|
||||
&& test "$am_cv_$1_dependencies_compiler_type" = gcc3])
|
||||
])
|
||||
|
||||
|
||||
# AM_SET_DEPDIR
|
||||
# -------------
|
||||
# Choose a directory name for dependency files.
|
||||
# This macro is AC_REQUIREd in _AM_DEPENDENCIES.
|
||||
AC_DEFUN([AM_SET_DEPDIR],
|
||||
[AC_REQUIRE([AM_SET_LEADING_DOT])dnl
|
||||
AC_SUBST([DEPDIR], ["${am__leading_dot}deps"])dnl
|
||||
])
|
||||
|
||||
|
||||
# AM_DEP_TRACK
|
||||
# ------------
|
||||
AC_DEFUN([AM_DEP_TRACK],
|
||||
[AC_ARG_ENABLE([dependency-tracking], [dnl
|
||||
AS_HELP_STRING(
|
||||
[--enable-dependency-tracking],
|
||||
[do not reject slow dependency extractors])
|
||||
AS_HELP_STRING(
|
||||
[--disable-dependency-tracking],
|
||||
[speeds up one-time build])])
|
||||
if test "x$enable_dependency_tracking" != xno; then
|
||||
am_depcomp="$ac_aux_dir/depcomp"
|
||||
AMDEPBACKSLASH='\'
|
||||
am__nodep='_no'
|
||||
fi
|
||||
AM_CONDITIONAL([AMDEP], [test "x$enable_dependency_tracking" != xno])
|
||||
AC_SUBST([AMDEPBACKSLASH])dnl
|
||||
_AM_SUBST_NOTMAKE([AMDEPBACKSLASH])dnl
|
||||
AC_SUBST([am__nodep])dnl
|
||||
_AM_SUBST_NOTMAKE([am__nodep])dnl
|
||||
])
|
||||
|
||||
# Generate code to set up dependency tracking. -*- Autoconf -*-
|
||||
|
||||
# Copyright (C) 1999-2012 Free Software Foundation, Inc.
|
||||
#
|
||||
# This file is free software; the Free Software Foundation
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
# with or without modifications, as long as this notice is preserved.
|
||||
|
||||
# serial 6
|
||||
|
||||
# _AM_OUTPUT_DEPENDENCY_COMMANDS
|
||||
# ------------------------------
|
||||
AC_DEFUN([_AM_OUTPUT_DEPENDENCY_COMMANDS],
|
||||
[{
|
||||
# Autoconf 2.62 quotes --file arguments for eval, but not when files
|
||||
# are listed without --file. Let's play safe and only enable the eval
|
||||
# if we detect the quoting.
|
||||
case $CONFIG_FILES in
|
||||
*\'*) eval set x "$CONFIG_FILES" ;;
|
||||
*) set x $CONFIG_FILES ;;
|
||||
esac
|
||||
shift
|
||||
for mf
|
||||
do
|
||||
# Strip MF so we end up with the name of the file.
|
||||
mf=`echo "$mf" | sed -e 's/:.*$//'`
|
||||
# Check whether this is an Automake generated Makefile or not.
|
||||
# We used to match only the files named 'Makefile.in', but
|
||||
# some people rename them; so instead we look at the file content.
|
||||
# Grep'ing the first line is not enough: some people post-process
|
||||
# each Makefile.in and add a new line on top of each file to say so.
|
||||
# Grep'ing the whole file is not good either: AIX grep has a line
|
||||
# limit of 2048, but all sed's we know have understand at least 4000.
|
||||
if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then
|
||||
dirpart=`AS_DIRNAME("$mf")`
|
||||
else
|
||||
continue
|
||||
fi
|
||||
# Extract the definition of DEPDIR, am__include, and am__quote
|
||||
# from the Makefile without running 'make'.
|
||||
DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"`
|
||||
test -z "$DEPDIR" && continue
|
||||
am__include=`sed -n 's/^am__include = //p' < "$mf"`
|
||||
test -z "am__include" && continue
|
||||
am__quote=`sed -n 's/^am__quote = //p' < "$mf"`
|
||||
# Find all dependency output files, they are included files with
|
||||
# $(DEPDIR) in their names. We invoke sed twice because it is the
|
||||
# simplest approach to changing $(DEPDIR) to its actual value in the
|
||||
# expansion.
|
||||
for file in `sed -n "
|
||||
s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \
|
||||
sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g'`; do
|
||||
# Make sure the directory exists.
|
||||
test -f "$dirpart/$file" && continue
|
||||
fdir=`AS_DIRNAME(["$file"])`
|
||||
AS_MKDIR_P([$dirpart/$fdir])
|
||||
# echo "creating $dirpart/$file"
|
||||
echo '# dummy' > "$dirpart/$file"
|
||||
done
|
||||
done
|
||||
}
|
||||
])# _AM_OUTPUT_DEPENDENCY_COMMANDS
|
||||
|
||||
|
||||
# AM_OUTPUT_DEPENDENCY_COMMANDS
|
||||
# -----------------------------
|
||||
# This macro should only be invoked once -- use via AC_REQUIRE.
|
||||
#
|
||||
# This code is only required when automatic dependency tracking
|
||||
# is enabled. FIXME. This creates each '.P' file that we will
|
||||
# need in order to bootstrap the dependency handling code.
|
||||
AC_DEFUN([AM_OUTPUT_DEPENDENCY_COMMANDS],
|
||||
[AC_CONFIG_COMMANDS([depfiles],
|
||||
[test x"$AMDEP_TRUE" != x"" || _AM_OUTPUT_DEPENDENCY_COMMANDS],
|
||||
[AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir"])
|
||||
])
|
||||
|
||||
# Do all the work for Automake. -*- Autoconf -*-
|
||||
|
||||
# Copyright (C) 1996-2012 Free Software Foundation, Inc.
|
||||
#
|
||||
# This file is free software; the Free Software Foundation
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
# with or without modifications, as long as this notice is preserved.
|
||||
|
||||
# serial 18
|
||||
|
||||
# This macro actually does too much. Some checks are only needed if
|
||||
# your package does certain things. But this isn't really a big deal.
|
||||
|
||||
# AM_INIT_AUTOMAKE(PACKAGE, VERSION, [NO-DEFINE])
|
||||
# AM_INIT_AUTOMAKE([OPTIONS])
|
||||
# -----------------------------------------------
|
||||
# The call with PACKAGE and VERSION arguments is the old style
|
||||
# call (pre autoconf-2.50), which is being phased out. PACKAGE
|
||||
# and VERSION should now be passed to AC_INIT and removed from
|
||||
# the call to AM_INIT_AUTOMAKE.
|
||||
# We support both call styles for the transition. After
|
||||
# the next Automake release, Autoconf can make the AC_INIT
|
||||
# arguments mandatory, and then we can depend on a new Autoconf
|
||||
# release and drop the old call support.
|
||||
AC_DEFUN([AM_INIT_AUTOMAKE],
|
||||
[AC_PREREQ([2.62])dnl
|
||||
dnl Autoconf wants to disallow AM_ names. We explicitly allow
|
||||
dnl the ones we care about.
|
||||
m4_pattern_allow([^AM_[A-Z]+FLAGS$])dnl
|
||||
AC_REQUIRE([AM_SET_CURRENT_AUTOMAKE_VERSION])dnl
|
||||
AC_REQUIRE([AC_PROG_INSTALL])dnl
|
||||
if test "`cd $srcdir && pwd`" != "`pwd`"; then
|
||||
# Use -I$(srcdir) only when $(srcdir) != ., so that make's output
|
||||
# is not polluted with repeated "-I."
|
||||
AC_SUBST([am__isrc], [' -I$(srcdir)'])_AM_SUBST_NOTMAKE([am__isrc])dnl
|
||||
# test to see if srcdir already configured
|
||||
if test -f $srcdir/config.status; then
|
||||
AC_MSG_ERROR([source directory already configured; run "make distclean" there first])
|
||||
fi
|
||||
fi
|
||||
|
||||
# test whether we have cygpath
|
||||
if test -z "$CYGPATH_W"; then
|
||||
if (cygpath --version) >/dev/null 2>/dev/null; then
|
||||
CYGPATH_W='cygpath -w'
|
||||
else
|
||||
CYGPATH_W=echo
|
||||
fi
|
||||
fi
|
||||
AC_SUBST([CYGPATH_W])
|
||||
|
||||
# Define the identity of the package.
|
||||
dnl Distinguish between old-style and new-style calls.
|
||||
m4_ifval([$2],
|
||||
[m4_ifval([$3], [_AM_SET_OPTION([no-define])])dnl
|
||||
AC_SUBST([PACKAGE], [$1])dnl
|
||||
AC_SUBST([VERSION], [$2])],
|
||||
[_AM_SET_OPTIONS([$1])dnl
|
||||
dnl Diagnose old-style AC_INIT with new-style AM_AUTOMAKE_INIT.
|
||||
m4_if(
|
||||
m4_ifdef([AC_PACKAGE_NAME], [ok]):m4_ifdef([AC_PACKAGE_VERSION], [ok]),
|
||||
[ok:ok],,
|
||||
[m4_fatal([AC_INIT should be called with package and version arguments])])dnl
|
||||
AC_SUBST([PACKAGE], ['AC_PACKAGE_TARNAME'])dnl
|
||||
AC_SUBST([VERSION], ['AC_PACKAGE_VERSION'])])dnl
|
||||
|
||||
_AM_IF_OPTION([no-define],,
|
||||
[AC_DEFINE_UNQUOTED([PACKAGE], ["$PACKAGE"], [Name of package])
|
||||
AC_DEFINE_UNQUOTED([VERSION], ["$VERSION"], [Version number of package])])dnl
|
||||
|
||||
# Some tools Automake needs.
|
||||
AC_REQUIRE([AM_SANITY_CHECK])dnl
|
||||
AC_REQUIRE([AC_ARG_PROGRAM])dnl
|
||||
AM_MISSING_PROG([ACLOCAL], [aclocal-${am__api_version}])
|
||||
AM_MISSING_PROG([AUTOCONF], [autoconf])
|
||||
AM_MISSING_PROG([AUTOMAKE], [automake-${am__api_version}])
|
||||
AM_MISSING_PROG([AUTOHEADER], [autoheader])
|
||||
AM_MISSING_PROG([MAKEINFO], [makeinfo])
|
||||
AC_REQUIRE([AM_PROG_INSTALL_SH])dnl
|
||||
AC_REQUIRE([AM_PROG_INSTALL_STRIP])dnl
|
||||
AC_REQUIRE([AM_PROG_MKDIR_P])dnl
|
||||
# We need awk for the "check" target. The system "awk" is bad on
|
||||
# some platforms.
|
||||
AC_REQUIRE([AC_PROG_AWK])dnl
|
||||
AC_REQUIRE([AC_PROG_MAKE_SET])dnl
|
||||
AC_REQUIRE([AM_SET_LEADING_DOT])dnl
|
||||
_AM_IF_OPTION([tar-ustar], [_AM_PROG_TAR([ustar])],
|
||||
[_AM_IF_OPTION([tar-pax], [_AM_PROG_TAR([pax])],
|
||||
[_AM_PROG_TAR([v7])])])
|
||||
_AM_IF_OPTION([no-dependencies],,
|
||||
[AC_PROVIDE_IFELSE([AC_PROG_CC],
|
||||
[_AM_DEPENDENCIES([CC])],
|
||||
[define([AC_PROG_CC],
|
||||
defn([AC_PROG_CC])[_AM_DEPENDENCIES([CC])])])dnl
|
||||
AC_PROVIDE_IFELSE([AC_PROG_CXX],
|
||||
[_AM_DEPENDENCIES([CXX])],
|
||||
[define([AC_PROG_CXX],
|
||||
defn([AC_PROG_CXX])[_AM_DEPENDENCIES([CXX])])])dnl
|
||||
AC_PROVIDE_IFELSE([AC_PROG_OBJC],
|
||||
[_AM_DEPENDENCIES([OBJC])],
|
||||
[define([AC_PROG_OBJC],
|
||||
defn([AC_PROG_OBJC])[_AM_DEPENDENCIES([OBJC])])])dnl
|
||||
])
|
||||
_AM_IF_OPTION([silent-rules], [AC_REQUIRE([AM_SILENT_RULES])])dnl
|
||||
dnl The 'parallel-tests' driver may need to know about EXEEXT, so add the
|
||||
dnl 'am__EXEEXT' conditional if _AM_COMPILER_EXEEXT was seen. This macro
|
||||
dnl is hooked onto _AC_COMPILER_EXEEXT early, see below.
|
||||
AC_CONFIG_COMMANDS_PRE(dnl
|
||||
[m4_provide_if([_AM_COMPILER_EXEEXT],
|
||||
[AM_CONDITIONAL([am__EXEEXT], [test -n "$EXEEXT"])])])dnl
|
||||
])
|
||||
|
||||
dnl Hook into '_AC_COMPILER_EXEEXT' early to learn its expansion. Do not
|
||||
dnl add the conditional right here, as _AC_COMPILER_EXEEXT may be further
|
||||
dnl mangled by Autoconf and run in a shell conditional statement.
|
||||
m4_define([_AC_COMPILER_EXEEXT],
|
||||
m4_defn([_AC_COMPILER_EXEEXT])[m4_provide([_AM_COMPILER_EXEEXT])])
|
||||
|
||||
|
||||
# When config.status generates a header, we must update the stamp-h file.
|
||||
# This file resides in the same directory as the config header
|
||||
# that is generated. The stamp files are numbered to have different names.
|
||||
|
||||
# Autoconf calls _AC_AM_CONFIG_HEADER_HOOK (when defined) in the
|
||||
# loop where config.status creates the headers, so we can generate
|
||||
# our stamp files there.
|
||||
AC_DEFUN([_AC_AM_CONFIG_HEADER_HOOK],
|
||||
[# Compute $1's index in $config_headers.
|
||||
_am_arg=$1
|
||||
_am_stamp_count=1
|
||||
for _am_header in $config_headers :; do
|
||||
case $_am_header in
|
||||
$_am_arg | $_am_arg:* )
|
||||
break ;;
|
||||
* )
|
||||
_am_stamp_count=`expr $_am_stamp_count + 1` ;;
|
||||
esac
|
||||
done
|
||||
echo "timestamp for $_am_arg" >`AS_DIRNAME(["$_am_arg"])`/stamp-h[]$_am_stamp_count])
|
||||
|
||||
# Copyright (C) 2001-2012 Free Software Foundation, Inc.
|
||||
#
|
||||
# This file is free software; the Free Software Foundation
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
# with or without modifications, as long as this notice is preserved.
|
||||
|
||||
# serial 8
|
||||
|
||||
# AM_PROG_INSTALL_SH
|
||||
# ------------------
|
||||
# Define $install_sh.
|
||||
AC_DEFUN([AM_PROG_INSTALL_SH],
|
||||
[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl
|
||||
if test x"${install_sh}" != xset; then
|
||||
case $am_aux_dir in
|
||||
*\ * | *\ *)
|
||||
install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;;
|
||||
*)
|
||||
install_sh="\${SHELL} $am_aux_dir/install-sh"
|
||||
esac
|
||||
fi
|
||||
AC_SUBST([install_sh])])
|
||||
|
||||
# Copyright (C) 2003-2012 Free Software Foundation, Inc.
|
||||
#
|
||||
# This file is free software; the Free Software Foundation
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
# with or without modifications, as long as this notice is preserved.
|
||||
|
||||
# serial 2
|
||||
|
||||
# Check whether the underlying file-system supports filenames
|
||||
# with a leading dot. For instance MS-DOS doesn't.
|
||||
AC_DEFUN([AM_SET_LEADING_DOT],
|
||||
[rm -rf .tst 2>/dev/null
|
||||
mkdir .tst 2>/dev/null
|
||||
if test -d .tst; then
|
||||
am__leading_dot=.
|
||||
else
|
||||
am__leading_dot=_
|
||||
fi
|
||||
rmdir .tst 2>/dev/null
|
||||
AC_SUBST([am__leading_dot])])
|
||||
|
||||
# Check to see how 'make' treats includes. -*- Autoconf -*-
|
||||
|
||||
# Copyright (C) 2001-2012 Free Software Foundation, Inc.
|
||||
#
|
||||
# This file is free software; the Free Software Foundation
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
# with or without modifications, as long as this notice is preserved.
|
||||
|
||||
# serial 5
|
||||
|
||||
# AM_MAKE_INCLUDE()
|
||||
# -----------------
|
||||
# Check to see how make treats includes.
|
||||
AC_DEFUN([AM_MAKE_INCLUDE],
|
||||
[am_make=${MAKE-make}
|
||||
cat > confinc << 'END'
|
||||
am__doit:
|
||||
@echo this is the am__doit target
|
||||
.PHONY: am__doit
|
||||
END
|
||||
# If we don't find an include directive, just comment out the code.
|
||||
AC_MSG_CHECKING([for style of include used by $am_make])
|
||||
am__include="#"
|
||||
am__quote=
|
||||
_am_result=none
|
||||
# First try GNU make style include.
|
||||
echo "include confinc" > confmf
|
||||
# Ignore all kinds of additional output from 'make'.
|
||||
case `$am_make -s -f confmf 2> /dev/null` in #(
|
||||
*the\ am__doit\ target*)
|
||||
am__include=include
|
||||
am__quote=
|
||||
_am_result=GNU
|
||||
;;
|
||||
esac
|
||||
# Now try BSD make style include.
|
||||
if test "$am__include" = "#"; then
|
||||
echo '.include "confinc"' > confmf
|
||||
case `$am_make -s -f confmf 2> /dev/null` in #(
|
||||
*the\ am__doit\ target*)
|
||||
am__include=.include
|
||||
am__quote="\""
|
||||
_am_result=BSD
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
AC_SUBST([am__include])
|
||||
AC_SUBST([am__quote])
|
||||
AC_MSG_RESULT([$_am_result])
|
||||
rm -f confinc confmf
|
||||
])
|
||||
|
||||
# Fake the existence of programs that GNU maintainers use. -*- Autoconf -*-
|
||||
|
||||
# Copyright (C) 1997-2012 Free Software Foundation, Inc.
|
||||
#
|
||||
# This file is free software; the Free Software Foundation
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
# with or without modifications, as long as this notice is preserved.
|
||||
|
||||
# serial 7
|
||||
|
||||
# AM_MISSING_PROG(NAME, PROGRAM)
|
||||
# ------------------------------
|
||||
AC_DEFUN([AM_MISSING_PROG],
|
||||
[AC_REQUIRE([AM_MISSING_HAS_RUN])
|
||||
$1=${$1-"${am_missing_run}$2"}
|
||||
AC_SUBST($1)])
|
||||
|
||||
|
||||
# AM_MISSING_HAS_RUN
|
||||
# ------------------
|
||||
# Define MISSING if not defined so far and test if it supports --run.
|
||||
# If it does, set am_missing_run to use it, otherwise, to nothing.
|
||||
AC_DEFUN([AM_MISSING_HAS_RUN],
|
||||
[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl
|
||||
AC_REQUIRE_AUX_FILE([missing])dnl
|
||||
if test x"${MISSING+set}" != xset; then
|
||||
case $am_aux_dir in
|
||||
*\ * | *\ *)
|
||||
MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;;
|
||||
*)
|
||||
MISSING="\${SHELL} $am_aux_dir/missing" ;;
|
||||
esac
|
||||
fi
|
||||
# Use eval to expand $SHELL
|
||||
if eval "$MISSING --run true"; then
|
||||
am_missing_run="$MISSING --run "
|
||||
else
|
||||
am_missing_run=
|
||||
AC_MSG_WARN(['missing' script is too old or missing])
|
||||
fi
|
||||
])
|
||||
|
||||
# Copyright (C) 2003-2012 Free Software Foundation, Inc.
|
||||
#
|
||||
# This file is free software; the Free Software Foundation
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
# with or without modifications, as long as this notice is preserved.
|
||||
|
||||
# serial 2
|
||||
|
||||
# AM_PROG_MKDIR_P
|
||||
# ---------------
|
||||
# Check for 'mkdir -p'.
|
||||
AC_DEFUN([AM_PROG_MKDIR_P],
|
||||
[AC_PREREQ([2.60])dnl
|
||||
AC_REQUIRE([AC_PROG_MKDIR_P])dnl
|
||||
dnl Automake 1.8 to 1.9.6 used to define mkdir_p. We now use MKDIR_P,
|
||||
dnl while keeping a definition of mkdir_p for backward compatibility.
|
||||
dnl @MKDIR_P@ is magic: AC_OUTPUT adjusts its value for each Makefile.
|
||||
dnl However we cannot define mkdir_p as $(MKDIR_P) for the sake of
|
||||
dnl Makefile.ins that do not define MKDIR_P, so we do our own
|
||||
dnl adjustment using top_builddir (which is defined more often than
|
||||
dnl MKDIR_P).
|
||||
AC_SUBST([mkdir_p], ["$MKDIR_P"])dnl
|
||||
case $mkdir_p in
|
||||
[[\\/$]]* | ?:[[\\/]]*) ;;
|
||||
*/*) mkdir_p="\$(top_builddir)/$mkdir_p" ;;
|
||||
esac
|
||||
])
|
||||
|
||||
# Helper functions for option handling. -*- Autoconf -*-
|
||||
|
||||
# Copyright (C) 2001-2012 Free Software Foundation, Inc.
|
||||
#
|
||||
# This file is free software; the Free Software Foundation
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
# with or without modifications, as long as this notice is preserved.
|
||||
|
||||
# serial 6
|
||||
|
||||
# _AM_MANGLE_OPTION(NAME)
|
||||
# -----------------------
|
||||
AC_DEFUN([_AM_MANGLE_OPTION],
|
||||
[[_AM_OPTION_]m4_bpatsubst($1, [[^a-zA-Z0-9_]], [_])])
|
||||
|
||||
# _AM_SET_OPTION(NAME)
|
||||
# --------------------
|
||||
# Set option NAME. Presently that only means defining a flag for this option.
|
||||
AC_DEFUN([_AM_SET_OPTION],
|
||||
[m4_define(_AM_MANGLE_OPTION([$1]), [1])])
|
||||
|
||||
# _AM_SET_OPTIONS(OPTIONS)
|
||||
# ------------------------
|
||||
# OPTIONS is a space-separated list of Automake options.
|
||||
AC_DEFUN([_AM_SET_OPTIONS],
|
||||
[m4_foreach_w([_AM_Option], [$1], [_AM_SET_OPTION(_AM_Option)])])
|
||||
|
||||
# _AM_IF_OPTION(OPTION, IF-SET, [IF-NOT-SET])
|
||||
# -------------------------------------------
|
||||
# Execute IF-SET if OPTION is set, IF-NOT-SET otherwise.
|
||||
AC_DEFUN([_AM_IF_OPTION],
|
||||
[m4_ifset(_AM_MANGLE_OPTION([$1]), [$2], [$3])])
|
||||
|
||||
# Check to make sure that the build environment is sane. -*- Autoconf -*-
|
||||
|
||||
# Copyright (C) 1996-2012 Free Software Foundation, Inc.
|
||||
#
|
||||
# This file is free software; the Free Software Foundation
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
# with or without modifications, as long as this notice is preserved.
|
||||
|
||||
# serial 9
|
||||
|
||||
# AM_SANITY_CHECK
|
||||
# ---------------
|
||||
AC_DEFUN([AM_SANITY_CHECK],
|
||||
[AC_MSG_CHECKING([whether build environment is sane])
|
||||
# Reject unsafe characters in $srcdir or the absolute working directory
|
||||
# name. Accept space and tab only in the latter.
|
||||
am_lf='
|
||||
'
|
||||
case `pwd` in
|
||||
*[[\\\"\#\$\&\'\`$am_lf]]*)
|
||||
AC_MSG_ERROR([unsafe absolute working directory name]);;
|
||||
esac
|
||||
case $srcdir in
|
||||
*[[\\\"\#\$\&\'\`$am_lf\ \ ]]*)
|
||||
AC_MSG_ERROR([unsafe srcdir value: '$srcdir']);;
|
||||
esac
|
||||
|
||||
# Do 'set' in a subshell so we don't clobber the current shell's
|
||||
# arguments. Must try -L first in case configure is actually a
|
||||
# symlink; some systems play weird games with the mod time of symlinks
|
||||
# (eg FreeBSD returns the mod time of the symlink's containing
|
||||
# directory).
|
||||
if (
|
||||
am_has_slept=no
|
||||
for am_try in 1 2; do
|
||||
echo "timestamp, slept: $am_has_slept" > conftest.file
|
||||
set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null`
|
||||
if test "$[*]" = "X"; then
|
||||
# -L didn't work.
|
||||
set X `ls -t "$srcdir/configure" conftest.file`
|
||||
fi
|
||||
if test "$[*]" != "X $srcdir/configure conftest.file" \
|
||||
&& test "$[*]" != "X conftest.file $srcdir/configure"; then
|
||||
|
||||
# If neither matched, then we have a broken ls. This can happen
|
||||
# if, for instance, CONFIG_SHELL is bash and it inherits a
|
||||
# broken ls alias from the environment. This has actually
|
||||
# happened. Such a system could not be considered "sane".
|
||||
AC_MSG_ERROR([ls -t appears to fail. Make sure there is not a broken
|
||||
alias in your environment])
|
||||
fi
|
||||
if test "$[2]" = conftest.file || test $am_try -eq 2; then
|
||||
break
|
||||
fi
|
||||
# Just in case.
|
||||
sleep 1
|
||||
am_has_slept=yes
|
||||
done
|
||||
test "$[2]" = conftest.file
|
||||
)
|
||||
then
|
||||
# Ok.
|
||||
:
|
||||
else
|
||||
AC_MSG_ERROR([newly created file is older than distributed files!
|
||||
Check your system clock])
|
||||
fi
|
||||
AC_MSG_RESULT([yes])
|
||||
# If we didn't sleep, we still need to ensure time stamps of config.status and
|
||||
# generated files are strictly newer.
|
||||
am_sleep_pid=
|
||||
if grep 'slept: no' conftest.file >/dev/null 2>&1; then
|
||||
( sleep 1 ) &
|
||||
am_sleep_pid=$!
|
||||
fi
|
||||
AC_CONFIG_COMMANDS_PRE(
|
||||
[AC_MSG_CHECKING([that generated files are newer than configure])
|
||||
if test -n "$am_sleep_pid"; then
|
||||
# Hide warnings about reused PIDs.
|
||||
wait $am_sleep_pid 2>/dev/null
|
||||
fi
|
||||
AC_MSG_RESULT([done])])
|
||||
rm -f conftest.file
|
||||
])
|
||||
|
||||
# Copyright (C) 2001-2012 Free Software Foundation, Inc.
|
||||
#
|
||||
# This file is free software; the Free Software Foundation
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
# with or without modifications, as long as this notice is preserved.
|
||||
|
||||
# serial 2
|
||||
|
||||
# AM_PROG_INSTALL_STRIP
|
||||
# ---------------------
|
||||
# One issue with vendor 'install' (even GNU) is that you can't
|
||||
# specify the program used to strip binaries. This is especially
|
||||
# annoying in cross-compiling environments, where the build's strip
|
||||
# is unlikely to handle the host's binaries.
|
||||
# Fortunately install-sh will honor a STRIPPROG variable, so we
|
||||
# always use install-sh in "make install-strip", and initialize
|
||||
# STRIPPROG with the value of the STRIP variable (set by the user).
|
||||
AC_DEFUN([AM_PROG_INSTALL_STRIP],
|
||||
[AC_REQUIRE([AM_PROG_INSTALL_SH])dnl
|
||||
# Installed binaries are usually stripped using 'strip' when the user
|
||||
# run "make install-strip". However 'strip' might not be the right
|
||||
# tool to use in cross-compilation environments, therefore Automake
|
||||
# will honor the 'STRIP' environment variable to overrule this program.
|
||||
dnl Don't test for $cross_compiling = yes, because it might be 'maybe'.
|
||||
if test "$cross_compiling" != no; then
|
||||
AC_CHECK_TOOL([STRIP], [strip], :)
|
||||
fi
|
||||
INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s"
|
||||
AC_SUBST([INSTALL_STRIP_PROGRAM])])
|
||||
|
||||
# Copyright (C) 2006-2012 Free Software Foundation, Inc.
|
||||
#
|
||||
# This file is free software; the Free Software Foundation
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
# with or without modifications, as long as this notice is preserved.
|
||||
|
||||
# serial 3
|
||||
|
||||
# _AM_SUBST_NOTMAKE(VARIABLE)
|
||||
# ---------------------------
|
||||
# Prevent Automake from outputting VARIABLE = @VARIABLE@ in Makefile.in.
|
||||
# This macro is traced by Automake.
|
||||
AC_DEFUN([_AM_SUBST_NOTMAKE])
|
||||
|
||||
# AM_SUBST_NOTMAKE(VARIABLE)
|
||||
# --------------------------
|
||||
# Public sister of _AM_SUBST_NOTMAKE.
|
||||
AC_DEFUN([AM_SUBST_NOTMAKE], [_AM_SUBST_NOTMAKE($@)])
|
||||
|
||||
# Check how to create a tarball. -*- Autoconf -*-
|
||||
|
||||
# Copyright (C) 2004-2012 Free Software Foundation, Inc.
|
||||
#
|
||||
# This file is free software; the Free Software Foundation
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
# with or without modifications, as long as this notice is preserved.
|
||||
|
||||
# serial 3
|
||||
|
||||
# _AM_PROG_TAR(FORMAT)
|
||||
# --------------------
|
||||
# Check how to create a tarball in format FORMAT.
|
||||
# FORMAT should be one of 'v7', 'ustar', or 'pax'.
|
||||
#
|
||||
# Substitute a variable $(am__tar) that is a command
|
||||
# writing to stdout a FORMAT-tarball containing the directory
|
||||
# $tardir.
|
||||
# tardir=directory && $(am__tar) > result.tar
|
||||
#
|
||||
# Substitute a variable $(am__untar) that extract such
|
||||
# a tarball read from stdin.
|
||||
# $(am__untar) < result.tar
|
||||
AC_DEFUN([_AM_PROG_TAR],
|
||||
[# Always define AMTAR for backward compatibility. Yes, it's still used
|
||||
# in the wild :-( We should find a proper way to deprecate it ...
|
||||
AC_SUBST([AMTAR], ['$${TAR-tar}'])
|
||||
m4_if([$1], [v7],
|
||||
[am__tar='$${TAR-tar} chof - "$$tardir"' am__untar='$${TAR-tar} xf -'],
|
||||
[m4_case([$1], [ustar],, [pax],,
|
||||
[m4_fatal([Unknown tar format])])
|
||||
AC_MSG_CHECKING([how to create a $1 tar archive])
|
||||
# Loop over all known methods to create a tar archive until one works.
|
||||
_am_tools='gnutar m4_if([$1], [ustar], [plaintar]) pax cpio none'
|
||||
_am_tools=${am_cv_prog_tar_$1-$_am_tools}
|
||||
# Do not fold the above two line into one, because Tru64 sh and
|
||||
# Solaris sh will not grok spaces in the rhs of '-'.
|
||||
for _am_tool in $_am_tools
|
||||
do
|
||||
case $_am_tool in
|
||||
gnutar)
|
||||
for _am_tar in tar gnutar gtar;
|
||||
do
|
||||
AM_RUN_LOG([$_am_tar --version]) && break
|
||||
done
|
||||
am__tar="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$$tardir"'
|
||||
am__tar_="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$tardir"'
|
||||
am__untar="$_am_tar -xf -"
|
||||
;;
|
||||
plaintar)
|
||||
# Must skip GNU tar: if it does not support --format= it doesn't create
|
||||
# ustar tarball either.
|
||||
(tar --version) >/dev/null 2>&1 && continue
|
||||
am__tar='tar chf - "$$tardir"'
|
||||
am__tar_='tar chf - "$tardir"'
|
||||
am__untar='tar xf -'
|
||||
;;
|
||||
pax)
|
||||
am__tar='pax -L -x $1 -w "$$tardir"'
|
||||
am__tar_='pax -L -x $1 -w "$tardir"'
|
||||
am__untar='pax -r'
|
||||
;;
|
||||
cpio)
|
||||
am__tar='find "$$tardir" -print | cpio -o -H $1 -L'
|
||||
am__tar_='find "$tardir" -print | cpio -o -H $1 -L'
|
||||
am__untar='cpio -i -H $1 -d'
|
||||
;;
|
||||
none)
|
||||
am__tar=false
|
||||
am__tar_=false
|
||||
am__untar=false
|
||||
;;
|
||||
esac
|
||||
|
||||
# If the value was cached, stop now. We just wanted to have am__tar
|
||||
# and am__untar set.
|
||||
test -n "${am_cv_prog_tar_$1}" && break
|
||||
|
||||
# tar/untar a dummy directory, and stop if the command works
|
||||
rm -rf conftest.dir
|
||||
mkdir conftest.dir
|
||||
echo GrepMe > conftest.dir/file
|
||||
AM_RUN_LOG([tardir=conftest.dir && eval $am__tar_ >conftest.tar])
|
||||
rm -rf conftest.dir
|
||||
if test -s conftest.tar; then
|
||||
AM_RUN_LOG([$am__untar <conftest.tar])
|
||||
grep GrepMe conftest.dir/file >/dev/null 2>&1 && break
|
||||
fi
|
||||
done
|
||||
rm -rf conftest.dir
|
||||
|
||||
AC_CACHE_VAL([am_cv_prog_tar_$1], [am_cv_prog_tar_$1=$_am_tool])
|
||||
AC_MSG_RESULT([$am_cv_prog_tar_$1])])
|
||||
AC_SUBST([am__tar])
|
||||
AC_SUBST([am__untar])
|
||||
]) # _AM_PROG_TAR
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
# this is example-file: configure.ac
|
||||
|
||||
# initial information about the project
|
||||
AC_INIT([NwGtpv2c],[0.11],[])
|
||||
|
||||
# check if the source folder is correct
|
||||
AC_CONFIG_SRCDIR([src/NwGtpv2c.c])
|
||||
|
||||
# Checks for programs
|
||||
|
||||
# check for C++ preprocessor and compiler and the library compiler
|
||||
AC_PROG_CXXCPP
|
||||
AC_PROG_CXX
|
||||
AC_PROG_RANLIB
|
||||
|
||||
# automake initialisation and check for minimal automake API version 1.9
|
||||
AM_INIT_AUTOMAKE([1.9])
|
||||
|
||||
# use the C compiler for the following checks
|
||||
AC_LANG([C])
|
||||
AC_C_INLINE
|
||||
|
||||
# Checks for header files.
|
||||
AC_HEADER_STDC
|
||||
AC_CHECK_HEADERS([fcntl.h])
|
||||
AC_CHECK_HEADERS([string])
|
||||
AC_CHECK_HEADERS([iostream])
|
||||
AC_CHECK_HEADERS([arpa/inet.h])
|
||||
AC_CHECK_HEADERS([sys/time.h])
|
||||
AC_CHECK_HEADERS([sys/socket.h])
|
||||
|
||||
AC_CHECK_FUNCS([strerror])
|
||||
AC_CHECK_FUNCS([socket])
|
||||
AC_CHECK_FUNCS([memset])
|
||||
AC_CHECK_FUNCS([gettimeofday])
|
||||
AC_FUNC_MALLOC
|
||||
AC_PROG_LN_S
|
||||
|
||||
AC_CHECK_LIB([event], [event_init])
|
||||
AM_CONDITIONAL([ENABLE_TESTS_APP], [test x$HAVE_LIBEVENT == xyes])
|
||||
|
||||
# Checks for typedefs, structures, and compiler characteristics.
|
||||
AC_TYPE_SIZE_T
|
||||
|
||||
# distribute additional compiler and linker flags
|
||||
# --> set these variables instead of CXXFLAGS or LDFLAGS
|
||||
AC_SUBST([AM_CFLAGS])
|
||||
AC_SUBST([AM_LDFLAGS])
|
||||
|
||||
# files to generate via autotools (.am or .in source files)
|
||||
AC_CONFIG_FILES([Makefile])
|
||||
AC_CONFIG_FILES([src/Makefile])
|
||||
AC_CONFIG_FILES([test-app/Makefile])
|
||||
AC_CONFIG_FILES([test-app/nw-helloworld/Makefile])
|
||||
AC_CONFIG_FILES([test-app/nw-egtping/Makefile])
|
||||
|
||||
# generate the final Makefile etc.
|
||||
AC_OUTPUT
|
||||
@@ -0,0 +1,83 @@
|
||||
/*----------------------------------------------------------------------------*
|
||||
* *
|
||||
* n w - g t p v 2 c *
|
||||
* G P R S T u n n e l i n g P r o t o c o l v 2 c S t a c k *
|
||||
* *
|
||||
* *
|
||||
* Copyright (c) 2010-2011 Amit Chawre *
|
||||
* All rights reserved. *
|
||||
* *
|
||||
* Redistribution and use in source and binary forms, with or without *
|
||||
* modification, are permitted provided that the following conditions *
|
||||
* are met: *
|
||||
* *
|
||||
* 1. Redistributions of source code must retain the above copyright *
|
||||
* notice, this list of conditions and the following disclaimer. *
|
||||
* 2. Redistributions in binary form must reproduce the above copyright *
|
||||
* notice, this list of conditions and the following disclaimer in the *
|
||||
* documentation and/or other materials provided with the distribution. *
|
||||
* 3. The name of the author may not be used to endorse or promote products *
|
||||
* derived from this software without specific prior written permission. *
|
||||
* *
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR *
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES *
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. *
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, *
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT *
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, *
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY *
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT *
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF *
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef __NW_GTPV2C_LOG_H__
|
||||
#define __NW_GTPV2C_LOG_H__
|
||||
|
||||
#include <stdio.h>
|
||||
#include "NwLog.h"
|
||||
|
||||
/**
|
||||
* @file NwGtpv2cLog.h
|
||||
* @brief This header contains logging related definitions.
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
* Log Macro Definition
|
||||
*--------------------------------------------------------------------------*/
|
||||
|
||||
#define NW_LOG(_gtpv2cHandle, _logLevel, ...) \
|
||||
do { \
|
||||
if(((NwGtpv2cStackT*)(_gtpv2cHandle))->logLevel >= _logLevel) \
|
||||
{ \
|
||||
char _logBuf[1024]; \
|
||||
snprintf(_logBuf, 1024, __VA_ARGS__); \
|
||||
((NwGtpv2cStackT*)(_gtpv2cHandle))->logMgr.logReqCallback(((NwGtpv2cStackT*)_gtpv2cHandle)->logMgr.logMgrHandle, _logLevel, __FILE__, __LINE__, _logBuf);\
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
#define NW_ENTER(_gtpv2cHandle) \
|
||||
do { \
|
||||
NW_LOG(_gtpv2cHandle, NW_LOG_LEVEL_DEBG, "Entering '%s'", __func__);\
|
||||
} while(0)
|
||||
|
||||
#define NW_LEAVE(_gtpv2cHandle) \
|
||||
do { \
|
||||
NW_LOG(_gtpv2cHandle, NW_LOG_LEVEL_DEBG, "Leaving '%s'", __func__);\
|
||||
} while(0)
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __NW_TYPES_H__ */
|
||||
|
||||
|
||||
/*--------------------------------------------------------------------------*
|
||||
* E N D O F F I L E *
|
||||
*--------------------------------------------------------------------------*/
|
||||
|
||||
@@ -0,0 +1,97 @@
|
||||
/*----------------------------------------------------------------------------*
|
||||
* *
|
||||
* n w - g t p v 2 c *
|
||||
* G P R S T u n n e l i n g P r o t o c o l v 2 c S t a c k *
|
||||
* *
|
||||
* *
|
||||
* Copyright (c) 2010-2011 Amit Chawre *
|
||||
* All rights reserved. *
|
||||
* *
|
||||
* Redistribution and use in source and binary forms, with or without *
|
||||
* modification, are permitted provided that the following conditions *
|
||||
* are met: *
|
||||
* *
|
||||
* 1. Redistributions of source code must retain the above copyright *
|
||||
* notice, this list of conditions and the following disclaimer. *
|
||||
* 2. Redistributions in binary form must reproduce the above copyright *
|
||||
* notice, this list of conditions and the following disclaimer in the *
|
||||
* documentation and/or other materials provided with the distribution. *
|
||||
* 3. The name of the author may not be used to endorse or promote products *
|
||||
* derived from this software without specific prior written permission. *
|
||||
* *
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR *
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES *
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. *
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, *
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT *
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, *
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY *
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT *
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF *
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef __NW_GTPV2C_MSG_PARSE_INFO_H__
|
||||
#define __NW_GTPV2C_MSG_PARSE_INFO_H__
|
||||
|
||||
#include "NwTypes.h"
|
||||
#include "NwGtpv2c.h"
|
||||
|
||||
/**
|
||||
* @file NwGtpv2cMsgParseInfo.h
|
||||
* @brief This file defines APIs for to parse incoming messages.
|
||||
*/
|
||||
|
||||
typedef struct
|
||||
{
|
||||
NwU8T groupedIeType;
|
||||
NwU16T mandatoryIeCount;
|
||||
NwGtpv2cStackHandleT hStack;
|
||||
|
||||
struct {
|
||||
NwU8T ieMinLength;
|
||||
NwU8T iePresence;
|
||||
} ieParseInfo[NW_GTPV2C_IE_TYPE_MAXIMUM][NW_GTPV2C_IE_INSTANCE_MAXIMUM];
|
||||
|
||||
} NwGtpv2cGroupedIeParseInfoT;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
NwU16T msgType;
|
||||
NwU16T mandatoryIeCount;
|
||||
NwGtpv2cStackHandleT hStack;
|
||||
|
||||
struct {
|
||||
NwU8T ieMinLength;
|
||||
NwU8T iePresence;
|
||||
NwGtpv2cGroupedIeParseInfoT* pGroupedIeInfo;
|
||||
} ieParseInfo[NW_GTPV2C_IE_TYPE_MAXIMUM][NW_GTPV2C_IE_INSTANCE_MAXIMUM];
|
||||
|
||||
} NwGtpv2cMsgIeParseInfoT;
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
NwGtpv2cMsgIeParseInfoT*
|
||||
nwGtpv2cMsgIeParseInfoNew(NwGtpv2cStackHandleT hStack, NwU8T msgType);
|
||||
|
||||
NwRcT
|
||||
nwGtpv2cMsgIeParseInfoDelete(NwGtpv2cMsgIeParseInfoT* thiz);
|
||||
|
||||
NwRcT
|
||||
nwGtpv2cMsgIeParse(NW_IN NwGtpv2cMsgIeParseInfoT* thiz,
|
||||
NW_IN NwGtpv2cMsgHandleT hMsg,
|
||||
NW_INOUT NwGtpv2cErrorT *pError);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __NW_GTPV2C_MSG_PARSE_INFO_H__ */
|
||||
|
||||
|
||||
/*--------------------------------------------------------------------------*
|
||||
* E N D O F F I L E *
|
||||
*--------------------------------------------------------------------------*/
|
||||
|
||||
@@ -0,0 +1,242 @@
|
||||
/*----------------------------------------------------------------------------*
|
||||
* *
|
||||
* n w - g t p v 2 c *
|
||||
* G P R S T u n n e l i n g P r o t o c o l v 2 c S t a c k *
|
||||
* *
|
||||
* *
|
||||
* Copyright (c) 2010-2011 Amit Chawre *
|
||||
* All rights reserved. *
|
||||
* *
|
||||
* Redistribution and use in source and binary forms, with or without *
|
||||
* modification, are permitted provided that the following conditions *
|
||||
* are met: *
|
||||
* *
|
||||
* 1. Redistributions of source code must retain the above copyright *
|
||||
* notice, this list of conditions and the following disclaimer. *
|
||||
* 2. Redistributions in binary form must reproduce the above copyright *
|
||||
* notice, this list of conditions and the following disclaimer in the *
|
||||
* documentation and/or other materials provided with the distribution. *
|
||||
* 3. The name of the author may not be used to endorse or promote products *
|
||||
* derived from this software without specific prior written permission. *
|
||||
* *
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR *
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES *
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. *
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, *
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT *
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, *
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY *
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT *
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF *
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef __NW_GTPV2C_PRIVATE_H__
|
||||
#define __NW_GTPV2C_PRIVATE_H__
|
||||
|
||||
#include <sys/time.h>
|
||||
|
||||
#include "tree.h"
|
||||
#include "queue.h"
|
||||
|
||||
#include "NwTypes.h"
|
||||
#include "NwError.h"
|
||||
#include "NwGtpv2c.h"
|
||||
#include "NwGtpv2cIe.h"
|
||||
#include "NwGtpv2cMsg.h"
|
||||
#include "NwGtpv2cMsgIeParseInfo.h"
|
||||
#include "NwGtpv2cTunnel.h"
|
||||
|
||||
/**
|
||||
* @file NwGtpv2cPrivate.h
|
||||
* @brief This header file contains nw-gtpv2c private definitions not to be
|
||||
* exposed to user application.
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define NW_GTPV2C_MALLOC(_stack, _size, _mem, _type) \
|
||||
do { \
|
||||
if(((NwGtpv2cStackT*)(_stack))->memMgr.memAlloc && ((NwGtpv2cStackT*)(_stack))->memMgr.memFree )\
|
||||
{ \
|
||||
_mem = (_type) ((NwGtpv2cStackT*) (_stack))->memMgr.memAlloc(((NwGtpv2cStackT*) (_stack))->memMgr.hMemMgr, _size, __FILE__, __LINE__);\
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
_mem = (_type) malloc (_size); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define NW_GTPV2C_FREE(_stack, _mem) \
|
||||
do { \
|
||||
if(((NwGtpv2cStackT*)(_stack))->memMgr.memAlloc && ((NwGtpv2cStackT*)(_stack))->memMgr.memFree )\
|
||||
{ \
|
||||
((NwGtpv2cStackT*)(_stack))->memMgr.memFree(((NwGtpv2cStackT*) (_stack))->memMgr.hMemMgr, _mem, __FILE__, __LINE__);\
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
free ((void*)_mem); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
/*--------------------------------------------------------------------------*
|
||||
* G T P V 2 C S T A C K O B J E C T T Y P E D E F I N I T I O N *
|
||||
*--------------------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* gtpv2c stack class definition
|
||||
*/
|
||||
|
||||
typedef struct NwGtpv2cStack
|
||||
{
|
||||
NwU32T id;
|
||||
NwGtpv2cUlpEntityT ulp;
|
||||
NwGtpv2cUdpEntityT udp;
|
||||
NwGtpv2cMemMgrEntityT memMgr;
|
||||
NwGtpv2cTimerMgrEntityT tmrMgr;
|
||||
NwGtpv2cLogMgrEntityT logMgr;
|
||||
|
||||
NwU32T seqNum;
|
||||
NwU32T logLevel;
|
||||
NwU32T restartCounter;
|
||||
|
||||
NwGtpv2cMsgIeParseInfoT *pGtpv2cMsgIeParseInfo[NW_GTP_MSG_END];
|
||||
struct NwGtpv2cTimeoutInfo *activeTimerInfo;
|
||||
|
||||
RB_HEAD( NwGtpv2cTunnelMap, NwGtpv2cTunnel ) tunnelMap;
|
||||
RB_HEAD( NwGtpv2cOutstandingTxSeqNumTrxnMap, NwGtpv2cTrxn ) outstandingTxSeqNumMap;
|
||||
RB_HEAD( NwGtpv2cOutstandingRxSeqNumTrxnMap, NwGtpv2cTrxn ) outstandingRxSeqNumMap;
|
||||
RB_HEAD( NwGtpv2cActiveTimerList, NwGtpv2cTimeoutInfo ) activeTimerList;
|
||||
NwHandleT hTmrMinHeap;
|
||||
} NwGtpv2cStackT;
|
||||
|
||||
|
||||
/*--------------------------------------------------------------------------*
|
||||
* Timeout Info Type Definition
|
||||
*--------------------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* gtpv2c timeout info
|
||||
*/
|
||||
|
||||
typedef struct NwGtpv2cTimeoutInfo
|
||||
{
|
||||
NwGtpv2cStackHandleT hStack;
|
||||
struct timeval tvTimeout;
|
||||
NwU32T tmrType;
|
||||
void* timeoutArg;
|
||||
NwRcT (*timeoutCallbackFunc)(void*);
|
||||
NwGtpv2cTimerHandleT hTimer;
|
||||
RB_ENTRY (NwGtpv2cTimeoutInfo) activeTimerListRbtNode; /**< RB Tree Data Structure Node */
|
||||
NwU32T timerMinHeapIndex;
|
||||
struct NwGtpv2cTimeoutInfo *next;
|
||||
} NwGtpv2cTimeoutInfoT;
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
* GTPv2c Message Container Definition
|
||||
*--------------------------------------------------------------------------*/
|
||||
|
||||
#define NW_GTPV2C_MAX_MSG_LEN (1024) /**< Maximum supported gtpv2c packet length including header */
|
||||
|
||||
/**
|
||||
* NwGtpv2cMsgT holds gtpv2c messages to/from the peer.
|
||||
*/
|
||||
typedef struct NwGtpv2cMsgS
|
||||
{
|
||||
NwU8T version;
|
||||
NwU8T teidPresent;
|
||||
NwU8T msgType;
|
||||
NwU16T msgLen;
|
||||
NwU32T teid;
|
||||
NwU32T seqNum;
|
||||
NwU8T* pMsgStart;
|
||||
|
||||
#define NW_GTPV2C_MAX_GROUPED_IE_DEPTH (2)
|
||||
struct {
|
||||
NwGtpv2cIeTlvT *pIe[NW_GTPV2C_MAX_GROUPED_IE_DEPTH];
|
||||
NwU8T top;
|
||||
} groupedIeEncodeStack;
|
||||
|
||||
NwBoolT isIeValid[NW_GTPV2C_IE_TYPE_MAXIMUM][NW_GTPV2C_IE_INSTANCE_MAXIMUM];
|
||||
NwU8T *pIe[NW_GTPV2C_IE_TYPE_MAXIMUM][NW_GTPV2C_IE_INSTANCE_MAXIMUM];
|
||||
NwU8T msgBuf[NW_GTPV2C_MAX_MSG_LEN];
|
||||
NwGtpv2cStackHandleT hStack;
|
||||
struct NwGtpv2cMsgS* next;
|
||||
} NwGtpv2cMsgT;
|
||||
|
||||
/**
|
||||
* Transaction structure
|
||||
*/
|
||||
|
||||
typedef struct NwGtpv2cTrxn
|
||||
{
|
||||
NwU32T seqNum;
|
||||
NwU32T peerIp;
|
||||
NwU32T peerPort;
|
||||
NwU8T t3Timer;
|
||||
NwU8T maxRetries;
|
||||
NwGtpv2cMsgT* pMsg;
|
||||
NwGtpv2cStackT* pStack;
|
||||
NwGtpv2cTimerHandleT hRspTmr; /**< Handle to reponse timer */
|
||||
NwGtpv2cTunnelHandleT hTunnel; /**< Handle to local tunnel context */
|
||||
NwGtpv2cUlpTrxnHandleT hUlpTrxn; /**< Handle to ULP tunnel context */
|
||||
RB_ENTRY (NwGtpv2cTrxn) outstandingTxSeqNumMapRbtNode; /**< RB Tree Data Structure Node */
|
||||
RB_ENTRY (NwGtpv2cTrxn) outstandingRxSeqNumMapRbtNode; /**< RB Tree Data Structure Node */
|
||||
struct NwGtpv2cTrxn* next;
|
||||
} NwGtpv2cTrxnT;
|
||||
|
||||
/**
|
||||
* GTPv2c Path Context
|
||||
*/
|
||||
|
||||
typedef struct NwGtpv2cPathS
|
||||
{
|
||||
NwU32T hUlpPath; /**< Handle to ULP path contect */
|
||||
NwU32T ipv4Address;
|
||||
NwU32T restartCounter;
|
||||
NwU16T t3ResponseTimout;
|
||||
NwU16T n3RequestCount;
|
||||
NwGtpv2cTimerHandleT hKeepAliveTmr; /**< Handle to path keep alive echo timer */
|
||||
RB_ENTRY (NwGtpv2cPathS) pathMapRbtNode;
|
||||
} NwGtpv2cPathT;
|
||||
|
||||
|
||||
RB_PROTOTYPE(NwGtpv2cTunnelMap, NwGtpv2cTunnel, tunnelMapRbtNode, nwGtpv2cCompareTunnel)
|
||||
RB_PROTOTYPE(NwGtpv2cOutstandingTxSeqNumTrxnMap, NwGtpv2cTrxn, outstandingTxSeqNumMapRbtNode, nwGtpv2cCompareSeqNum)
|
||||
RB_PROTOTYPE(NwGtpv2cOutstandingRxSeqNumTrxnMap, NwGtpv2cTrxn, outstandingRxSeqNumMapRbtNode, nwGtpv2cCompareSeqNum)
|
||||
RB_PROTOTYPE(NwGtpv2cActiveTimerList, NwGtpv2cTimeoutInfo, activeTimerListRbtNode, nwGtpv2cCompareOutstandingTxRexmitTime)
|
||||
|
||||
/**
|
||||
* Start Timer with ULP Timer Manager
|
||||
*/
|
||||
|
||||
NwRcT
|
||||
nwGtpv2cStartTimer(NwGtpv2cStackT* thiz,
|
||||
NwU32T timeoutSec,
|
||||
NwU32T timeoutUsec,
|
||||
NwU32T tmrType,
|
||||
NwRcT (*timeoutCallbackFunc)(void*),
|
||||
void* timeoutCallbackArg,
|
||||
NwGtpv2cTimerHandleT *phTimer);
|
||||
|
||||
|
||||
/**
|
||||
* Stop Timer with ULP Timer Manager
|
||||
*/
|
||||
|
||||
NwRcT
|
||||
nwGtpv2cStopTimer(NwGtpv2cStackT* thiz,
|
||||
NwGtpv2cTimerHandleT hTimer);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __NW_GTPV2C_PRIVATE_H__ */
|
||||
/*--------------------------------------------------------------------------*
|
||||
* E N D O F F I L E *
|
||||
*--------------------------------------------------------------------------*/
|
||||
|
||||
@@ -0,0 +1,117 @@
|
||||
/*----------------------------------------------------------------------------*
|
||||
* *
|
||||
* n w - g t p v 2 c *
|
||||
* G P R S T u n n e l i n g P r o t o c o l v 2 c S t a c k *
|
||||
* *
|
||||
* *
|
||||
* Copyright (c) 2010-2011 Amit Chawre *
|
||||
* All rights reserved. *
|
||||
* *
|
||||
* Redistribution and use in source and binary forms, with or without *
|
||||
* modification, are permitted provided that the following conditions *
|
||||
* are met: *
|
||||
* *
|
||||
* 1. Redistributions of source code must retain the above copyright *
|
||||
* notice, this list of conditions and the following disclaimer. *
|
||||
* 2. Redistributions in binary form must reproduce the above copyright *
|
||||
* notice, this list of conditions and the following disclaimer in the *
|
||||
* documentation and/or other materials provided with the distribution. *
|
||||
* 3. The name of the author may not be used to endorse or promote products *
|
||||
* derived from this software without specific prior written permission. *
|
||||
* *
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR *
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES *
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. *
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, *
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT *
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, *
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY *
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT *
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF *
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @file NwGtpv2cTrxn.h
|
||||
* @author Amit Chawre
|
||||
* @brief
|
||||
*
|
||||
* This header file contains required definitions and functions
|
||||
* prototypes used by gtpv2c transactions.
|
||||
*
|
||||
**/
|
||||
|
||||
|
||||
#ifndef __NW_GTPV2C_TRXN_H__
|
||||
#define __NW_GTPV2C_TRXN_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Constructotr
|
||||
*/
|
||||
NwGtpv2cTrxnT*
|
||||
nwGtpv2cTrxnNew( NW_IN NwGtpv2cStackT* pStack);
|
||||
|
||||
/**
|
||||
* Overloaded Constructotr
|
||||
*/
|
||||
NwGtpv2cTrxnT*
|
||||
nwGtpv2cTrxnWithSeqNumNew( NW_IN NwGtpv2cStackT* pStack,
|
||||
NW_IN NwU32T seqNum);
|
||||
|
||||
/**
|
||||
* Another overloaded constructor. Create transaction as outstanding
|
||||
* RX transaction for detecting duplicated requests.
|
||||
*
|
||||
* @param[in] thiz : Pointer to stack.
|
||||
* @param[in] teidLocal : Trxn teid.
|
||||
* @param[in] peerIp : Peer Ip address.
|
||||
* @param[in] peerPort : Peer Ip port.
|
||||
* @param[in] seqNum : Seq Number.
|
||||
* @return NW_OK on success.
|
||||
*/
|
||||
|
||||
NwGtpv2cTrxnT*
|
||||
nwGtpv2cTrxnOutstandingRxNew( NW_IN NwGtpv2cStackT* pStack,
|
||||
NW_IN NwU32T teidLocal,
|
||||
NW_IN NwU32T peerIp,
|
||||
NW_IN NwU32T peerPort,
|
||||
NW_IN NwU32T seqNum);
|
||||
|
||||
NwRcT
|
||||
nwGtpv2cTrxnDelete( NW_INOUT NwGtpv2cTrxnT **ppTrxn);
|
||||
|
||||
/**
|
||||
* Start timer to wait before pruginf a req tran for which response has been sent
|
||||
*
|
||||
* @param[in] thiz : Pointer to transaction
|
||||
* @return NW_OK on success.
|
||||
*/
|
||||
|
||||
NwRcT
|
||||
nwGtpv2cTrxnStartDulpicateRequestWaitTimer(NwGtpv2cTrxnT* thiz);
|
||||
|
||||
/**
|
||||
* Start timer to wait for rsp of a req message
|
||||
*
|
||||
* @param[in] thiz : Pointer to transaction
|
||||
* @param[in] timeoutCallbackFunc : Timeout handler callback function.
|
||||
* @return NW_OK on success.
|
||||
*/
|
||||
|
||||
NwRcT
|
||||
nwGtpv2cTrxnStartPeerRspWaitTimer(NwGtpv2cTrxnT* thiz);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __NW_GTPV2C_TRXN_H__ */
|
||||
|
||||
/*--------------------------------------------------------------------------*
|
||||
* E N D O F F I L E *
|
||||
*--------------------------------------------------------------------------*/
|
||||
|
||||
@@ -0,0 +1,80 @@
|
||||
/*----------------------------------------------------------------------------*
|
||||
* *
|
||||
* n w - g t p v 2 c *
|
||||
* G P R S T u n n e l i n g P r o t o c o l v 2 c S t a c k *
|
||||
* *
|
||||
* *
|
||||
* Copyright (c) 2010-2011 Amit Chawre *
|
||||
* All rights reserved. *
|
||||
* *
|
||||
* Redistribution and use in source and binary forms, with or without *
|
||||
* modification, are permitted provided that the following conditions *
|
||||
* are met: *
|
||||
* *
|
||||
* 1. Redistributions of source code must retain the above copyright *
|
||||
* notice, this list of conditions and the following disclaimer. *
|
||||
* 2. Redistributions in binary form must reproduce the above copyright *
|
||||
* notice, this list of conditions and the following disclaimer in the *
|
||||
* documentation and/or other materials provided with the distribution. *
|
||||
* 3. The name of the author may not be used to endorse or promote products *
|
||||
* derived from this software without specific prior written permission. *
|
||||
* *
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR *
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES *
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. *
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, *
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT *
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, *
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY *
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT *
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF *
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef __NW_GTPV2C_TUNNEL_H__
|
||||
#define __NW_GTPV2C_TUNNEL_H__
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "tree.h"
|
||||
#include "NwTypes.h"
|
||||
#include "NwUtils.h"
|
||||
#include "NwError.h"
|
||||
#include "NwGtpv2c.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct NwGtpv2cStack;
|
||||
|
||||
typedef struct NwGtpv2cTunnel
|
||||
{
|
||||
NwU32T teid;
|
||||
NwU32T ipv4AddrRemote;
|
||||
NwGtpv2cUlpTunnelHandleT hUlpTunnel;
|
||||
RB_ENTRY (NwGtpv2cTunnel) tunnelMapRbtNode; /**< RB Tree Data Structure Node */
|
||||
struct NwGtpv2cTunnel* next;
|
||||
} NwGtpv2cTunnelT;
|
||||
|
||||
NwGtpv2cTunnelT*
|
||||
nwGtpv2cTunnelNew(struct NwGtpv2cStack *hStack, NwU32T teid, NwU32T peerIpv4Addr, NwGtpv2cUlpTunnelHandleT hUlpTunnel);
|
||||
|
||||
NwRcT
|
||||
nwGtpv2cTunnelDelete(struct NwGtpv2cStack *pStack, NwGtpv2cTunnelT* thiz);
|
||||
|
||||
NwRcT
|
||||
nwGtpv2cTunnelGetUlpTunnelHandle( NwGtpv2cTunnelT* thiz, NwGtpv2cUlpTunnelHandleT* phUlpTunnel);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
/*--------------------------------------------------------------------------*
|
||||
* E N D O F F I L E *
|
||||
*--------------------------------------------------------------------------*/
|
||||
|
||||
@@ -0,0 +1,566 @@
|
||||
/*
|
||||
* Copyright (c) 1991, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)queue.h 8.5 (Berkeley) 8/20/94
|
||||
* $FreeBSD: src/sys/sys/queue.h,v 1.32.2.6 2001/12/18 10:09:02 ru Exp $
|
||||
*/
|
||||
|
||||
#ifndef _SYS_QUEUE_H_
|
||||
#define _SYS_QUEUE_H_
|
||||
|
||||
|
||||
/*
|
||||
* This file defines five types of data structures: singly-linked lists,
|
||||
* singly-linked tail queues, lists, tail queues, and circular queues.
|
||||
*
|
||||
* A singly-linked list is headed by a single forward pointer. The elements
|
||||
* are singly linked for minimum space and pointer manipulation overhead at
|
||||
* the expense of O(n) removal for arbitrary elements. New elements can be
|
||||
* added to the list after an existing element or at the head of the list.
|
||||
* Elements being removed from the head of the list should use the explicit
|
||||
* macro for this purpose for tmpimum efficiency. A singly-linked list may
|
||||
* only be traversed in the forward direction. Singly-linked lists are ideal
|
||||
* for applications with large datasets and few or no removals or for
|
||||
* implementing a LIFO queue.
|
||||
*
|
||||
* A singly-linked tail queue is headed by a pair of pointers, one to the
|
||||
* head of the list and the other to the tail of the list. The elements are
|
||||
* singly linked for minimum space and pointer manipulation overhead at the
|
||||
* expense of O(n) removal for arbitrary elements. New elements can be added
|
||||
* to the list after an existing element, at the head of the list, or at the
|
||||
* end of the list. Elements being removed from the head of the tail queue
|
||||
* should use the explicit macro for this purpose for tmpimum efficiency.
|
||||
* A singly-linked tail queue may only be traversed in the forward direction.
|
||||
* Singly-linked tail queues are ideal for applications with large datasets
|
||||
* and few or no removals or for implementing a FIFO queue.
|
||||
*
|
||||
* A list is headed by a single forward pointer (or an array of forward
|
||||
* pointers for a hash table header). The elements are doubly linked
|
||||
* so that an arbitrary element can be removed without a need to
|
||||
* traverse the list. New elements can be added to the list before
|
||||
* or after an existing element or at the head of the list. A list
|
||||
* may only be traversed in the forward direction.
|
||||
*
|
||||
* A tail queue is headed by a pair of pointers, one to the head of the
|
||||
* list and the other to the tail of the list. The elements are doubly
|
||||
* linked so that an arbitrary element can be removed without a need to
|
||||
* traverse the list. New elements can be added to the list before or
|
||||
* after an existing element, at the head of the list, or at the end of
|
||||
* the list. A tail queue may be traversed in either direction.
|
||||
*
|
||||
* A circle queue is headed by a pair of pointers, one to the head of the
|
||||
* list and the other to the tail of the list. The elements are doubly
|
||||
* linked so that an arbitrary element can be removed without a need to
|
||||
* traverse the list. New elements can be added to the list before or after
|
||||
* an existing element, at the head of the list, or at the end of the list.
|
||||
* A circle queue may be traversed in either direction, but has a more
|
||||
* complex end of list detection.
|
||||
*
|
||||
* For details on the use of these macros, see the queue(3) manual page.
|
||||
*
|
||||
*
|
||||
* SLIST LIST STAILQ TAILQ CIRCLEQ
|
||||
* _HEAD + + + + +
|
||||
* _HEAD_INITIALIZER + + + + +
|
||||
* _ENTRY + + + + +
|
||||
* _INIT + + + + +
|
||||
* _EMPTY + + + + +
|
||||
* _FIRST + + + + +
|
||||
* _NEXT + + + + +
|
||||
* _PREV - - - + +
|
||||
* _LAST - - + + +
|
||||
* _FOREACH + + + + +
|
||||
* _FOREACH_REVERSE - - - + +
|
||||
* _INSERT_HEAD + + + + +
|
||||
* _INSERT_BEFORE - + - + +
|
||||
* _INSERT_AFTER + + + + +
|
||||
* _INSERT_TAIL - - + + +
|
||||
* _REMOVE_HEAD + - + - -
|
||||
* _REMOVE + + + + +
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Singly-linked List declarations.
|
||||
*/
|
||||
#define SLIST_HEAD(name, type) \
|
||||
struct name { \
|
||||
struct type *slh_first; /* first element */ \
|
||||
}
|
||||
|
||||
#define SLIST_HEAD_INITIALIZER(head) \
|
||||
{ NULL }
|
||||
|
||||
#define SLIST_ENTRY(type) \
|
||||
struct { \
|
||||
struct type *sle_next; /* next element */ \
|
||||
}
|
||||
|
||||
/*
|
||||
* Singly-linked List functions.
|
||||
*/
|
||||
#define SLIST_EMPTY(head) ((head)->slh_first == NULL)
|
||||
|
||||
#define SLIST_FIRST(head) ((head)->slh_first)
|
||||
|
||||
#define SLIST_FOREACH(var, head, field) \
|
||||
for ((var) = SLIST_FIRST((head)); \
|
||||
(var); \
|
||||
(var) = SLIST_NEXT((var), field))
|
||||
|
||||
#define SLIST_INIT(head) do { \
|
||||
SLIST_FIRST((head)) = NULL; \
|
||||
} while (0)
|
||||
|
||||
#define SLIST_INSERT_AFTER(slistelm, elm, field) do { \
|
||||
SLIST_NEXT((elm), field) = SLIST_NEXT((slistelm), field); \
|
||||
SLIST_NEXT((slistelm), field) = (elm); \
|
||||
} while (0)
|
||||
|
||||
#define SLIST_INSERT_HEAD(head, elm, field) do { \
|
||||
SLIST_NEXT((elm), field) = SLIST_FIRST((head)); \
|
||||
SLIST_FIRST((head)) = (elm); \
|
||||
} while (0)
|
||||
|
||||
#define SLIST_NEXT(elm, field) ((elm)->field.sle_next)
|
||||
|
||||
#define SLIST_REMOVE(head, elm, type, field) do { \
|
||||
if (SLIST_FIRST((head)) == (elm)) { \
|
||||
SLIST_REMOVE_HEAD((head), field); \
|
||||
} \
|
||||
else { \
|
||||
struct type *curelm = SLIST_FIRST((head)); \
|
||||
while (SLIST_NEXT(curelm, field) != (elm)) \
|
||||
curelm = SLIST_NEXT(curelm, field); \
|
||||
SLIST_NEXT(curelm, field) = \
|
||||
SLIST_NEXT(SLIST_NEXT(curelm, field), field); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define SLIST_REMOVE_HEAD(head, field) do { \
|
||||
SLIST_FIRST((head)) = SLIST_NEXT(SLIST_FIRST((head)), field); \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* Singly-linked Tail queue declarations.
|
||||
*/
|
||||
#define STAILQ_HEAD(name, type) \
|
||||
struct name { \
|
||||
struct type *stqh_first;/* first element */ \
|
||||
struct type **stqh_last;/* addr of last next element */ \
|
||||
}
|
||||
|
||||
#define STAILQ_HEAD_INITIALIZER(head) \
|
||||
{ NULL, &(head).stqh_first }
|
||||
|
||||
#define STAILQ_HEAD_INIT(head) do{ \
|
||||
(head).stqh_first = NULL; \
|
||||
(head).stqh_last = &(head).stqh_first; \
|
||||
}while(0)
|
||||
|
||||
#define STAILQ_ENTRY(type) \
|
||||
struct { \
|
||||
struct type *stqe_next; /* next element */ \
|
||||
}
|
||||
|
||||
/*
|
||||
* Singly-linked Tail queue functions.
|
||||
*/
|
||||
#define STAILQ_EMPTY(head) ((head)->stqh_first == NULL)
|
||||
|
||||
#define STAILQ_FIRST(head) ((head)->stqh_first)
|
||||
|
||||
#define STAILQ_FOREACH(var, head, field) \
|
||||
for((var) = STAILQ_FIRST((head)); \
|
||||
(var); \
|
||||
(var) = STAILQ_NEXT((var), field))
|
||||
|
||||
#define STAILQ_INIT(head) do { \
|
||||
STAILQ_FIRST((head)) = NULL; \
|
||||
(head)->stqh_last = &STAILQ_FIRST((head)); \
|
||||
} while (0)
|
||||
|
||||
#define STAILQ_INSERT_AFTER(head, tqelm, elm, field) do { \
|
||||
if ((STAILQ_NEXT((elm), field) = STAILQ_NEXT((tqelm), field)) == NULL)\
|
||||
(head)->stqh_last = &STAILQ_NEXT((elm), field); \
|
||||
STAILQ_NEXT((tqelm), field) = (elm); \
|
||||
} while (0)
|
||||
|
||||
#define STAILQ_INSERT_HEAD(head, elm, field) do { \
|
||||
if ((STAILQ_NEXT((elm), field) = STAILQ_FIRST((head))) == NULL) \
|
||||
(head)->stqh_last = &STAILQ_NEXT((elm), field); \
|
||||
STAILQ_FIRST((head)) = (elm); \
|
||||
} while (0)
|
||||
|
||||
#define STAILQ_INSERT_TAIL(head, elm, field) do { \
|
||||
STAILQ_NEXT((elm), field) = NULL; \
|
||||
*(head)->stqh_last = (elm); \
|
||||
(head)->stqh_last = &STAILQ_NEXT((elm), field); \
|
||||
} while (0)
|
||||
|
||||
#define STAILQ_LAST(head, type, field) \
|
||||
(STAILQ_EMPTY(head) ? \
|
||||
NULL : \
|
||||
((struct type *) \
|
||||
((char *)((head)->stqh_last) - __offsetof(struct type, field))))
|
||||
|
||||
#define STAILQ_NEXT(elm, field) ((elm)->field.stqe_next)
|
||||
|
||||
#define STAILQ_REMOVE(head, elm, type, field) do { \
|
||||
if (STAILQ_FIRST((head)) == (elm)) { \
|
||||
STAILQ_REMOVE_HEAD(head, field); \
|
||||
} \
|
||||
else { \
|
||||
struct type *curelm = STAILQ_FIRST((head)); \
|
||||
while (STAILQ_NEXT(curelm, field) != (elm)) \
|
||||
curelm = STAILQ_NEXT(curelm, field); \
|
||||
if ((STAILQ_NEXT(curelm, field) = \
|
||||
STAILQ_NEXT(STAILQ_NEXT(curelm, field), field)) == NULL)\
|
||||
(head)->stqh_last = &STAILQ_NEXT((curelm), field);\
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define STAILQ_REMOVE_HEAD(head, field) do { \
|
||||
if ((STAILQ_FIRST((head)) = \
|
||||
STAILQ_NEXT(STAILQ_FIRST((head)), field)) == NULL) \
|
||||
(head)->stqh_last = &STAILQ_FIRST((head)); \
|
||||
} while (0)
|
||||
|
||||
#define STAILQ_REMOVE_HEAD_UNTIL(head, elm, field) do { \
|
||||
if ((STAILQ_FIRST((head)) = STAILQ_NEXT((elm), field)) == NULL) \
|
||||
(head)->stqh_last = &STAILQ_FIRST((head)); \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* List declarations.
|
||||
*/
|
||||
#define LIST_HEAD(name, type) \
|
||||
struct name { \
|
||||
struct type *lh_first; /* first element */ \
|
||||
}
|
||||
|
||||
#define LIST_HEAD_INITIALIZER(head) \
|
||||
{ NULL }
|
||||
|
||||
#define LIST_ENTRY(type) \
|
||||
struct { \
|
||||
struct type *le_next; /* next element */ \
|
||||
struct type **le_prev; /* address of previous next element */ \
|
||||
}
|
||||
|
||||
/*
|
||||
* List functions.
|
||||
*/
|
||||
|
||||
#define LIST_EMPTY(head) ((head)->lh_first == NULL)
|
||||
|
||||
#define LIST_FIRST(head) ((head)->lh_first)
|
||||
|
||||
#define LIST_FOREACH(var, head, field) \
|
||||
for ((var) = LIST_FIRST((head)); \
|
||||
(var); \
|
||||
(var) = LIST_NEXT((var), field))
|
||||
|
||||
#define LIST_INIT(head) do { \
|
||||
LIST_FIRST((head)) = NULL; \
|
||||
} while (0)
|
||||
|
||||
#define LIST_INSERT_AFTER(listelm, elm, field) do { \
|
||||
if ((LIST_NEXT((elm), field) = LIST_NEXT((listelm), field)) != NULL)\
|
||||
LIST_NEXT((listelm), field)->field.le_prev = \
|
||||
&LIST_NEXT((elm), field); \
|
||||
LIST_NEXT((listelm), field) = (elm); \
|
||||
(elm)->field.le_prev = &LIST_NEXT((listelm), field); \
|
||||
} while (0)
|
||||
|
||||
#define LIST_INSERT_BEFORE(listelm, elm, field) do { \
|
||||
(elm)->field.le_prev = (listelm)->field.le_prev; \
|
||||
LIST_NEXT((elm), field) = (listelm); \
|
||||
*(listelm)->field.le_prev = (elm); \
|
||||
(listelm)->field.le_prev = &LIST_NEXT((elm), field); \
|
||||
} while (0)
|
||||
|
||||
#define LIST_INSERT_HEAD(head, elm, field) do { \
|
||||
if ((LIST_NEXT((elm), field) = LIST_FIRST((head))) != NULL) \
|
||||
LIST_FIRST((head))->field.le_prev = &LIST_NEXT((elm), field);\
|
||||
LIST_FIRST((head)) = (elm); \
|
||||
(elm)->field.le_prev = &LIST_FIRST((head)); \
|
||||
} while (0)
|
||||
|
||||
#define LIST_NEXT(elm, field) ((elm)->field.le_next)
|
||||
|
||||
#define LIST_REMOVE(elm, field) do { \
|
||||
if (LIST_NEXT((elm), field) != NULL) \
|
||||
LIST_NEXT((elm), field)->field.le_prev = \
|
||||
(elm)->field.le_prev; \
|
||||
*(elm)->field.le_prev = LIST_NEXT((elm), field); \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* Tail queue declarations.
|
||||
*/
|
||||
#define TAILQ_HEAD(name, type) \
|
||||
struct name { \
|
||||
struct type *tqh_first; /* first element */ \
|
||||
struct type **tqh_last; /* addr of last next element */ \
|
||||
}
|
||||
|
||||
#define TAILQ_HEAD_INITIALIZER(head) \
|
||||
{ NULL, &(head).tqh_first }
|
||||
|
||||
#define TAILQ_ENTRY(type) \
|
||||
struct { \
|
||||
struct type *tqe_next; /* next element */ \
|
||||
struct type **tqe_prev; /* address of previous next element */ \
|
||||
}
|
||||
|
||||
/*
|
||||
* Tail queue functions.
|
||||
*/
|
||||
#define TAILQ_EMPTY(head) ((head)->tqh_first == NULL)
|
||||
|
||||
#define TAILQ_FIRST(head) ((head)->tqh_first)
|
||||
|
||||
#define TAILQ_FOREACH(var, head, field) \
|
||||
for ((var) = TAILQ_FIRST((head)); \
|
||||
(var); \
|
||||
(var) = TAILQ_NEXT((var), field))
|
||||
|
||||
#define TAILQ_FOREACH_REVERSE(var, head, headname, field) \
|
||||
for ((var) = TAILQ_LAST((head), headname); \
|
||||
(var); \
|
||||
(var) = TAILQ_PREV((var), headname, field))
|
||||
|
||||
#define TAILQ_INIT(head) do { \
|
||||
TAILQ_FIRST((head)) = NULL; \
|
||||
(head)->tqh_last = &TAILQ_FIRST((head)); \
|
||||
} while (0)
|
||||
|
||||
#define TAILQ_INSERT_AFTER(head, listelm, elm, field) do { \
|
||||
if ((TAILQ_NEXT((elm), field) = TAILQ_NEXT((listelm), field)) != NULL)\
|
||||
TAILQ_NEXT((elm), field)->field.tqe_prev = \
|
||||
&TAILQ_NEXT((elm), field); \
|
||||
else \
|
||||
(head)->tqh_last = &TAILQ_NEXT((elm), field); \
|
||||
TAILQ_NEXT((listelm), field) = (elm); \
|
||||
(elm)->field.tqe_prev = &TAILQ_NEXT((listelm), field); \
|
||||
} while (0)
|
||||
|
||||
#define TAILQ_INSERT_BEFORE(listelm, elm, field) do { \
|
||||
(elm)->field.tqe_prev = (listelm)->field.tqe_prev; \
|
||||
TAILQ_NEXT((elm), field) = (listelm); \
|
||||
*(listelm)->field.tqe_prev = (elm); \
|
||||
(listelm)->field.tqe_prev = &TAILQ_NEXT((elm), field); \
|
||||
} while (0)
|
||||
|
||||
#define TAILQ_INSERT_HEAD(head, elm, field) do { \
|
||||
if ((TAILQ_NEXT((elm), field) = TAILQ_FIRST((head))) != NULL) \
|
||||
TAILQ_FIRST((head))->field.tqe_prev = \
|
||||
&TAILQ_NEXT((elm), field); \
|
||||
else \
|
||||
(head)->tqh_last = &TAILQ_NEXT((elm), field); \
|
||||
TAILQ_FIRST((head)) = (elm); \
|
||||
(elm)->field.tqe_prev = &TAILQ_FIRST((head)); \
|
||||
} while (0)
|
||||
|
||||
#define TAILQ_INSERT_TAIL(head, elm, field) do { \
|
||||
TAILQ_NEXT((elm), field) = NULL; \
|
||||
(elm)->field.tqe_prev = (head)->tqh_last; \
|
||||
*(head)->tqh_last = (elm); \
|
||||
(head)->tqh_last = &TAILQ_NEXT((elm), field); \
|
||||
} while (0)
|
||||
|
||||
#define TAILQ_LAST(head, headname) \
|
||||
(*(((struct headname *)((head)->tqh_last))->tqh_last))
|
||||
|
||||
#define TAILQ_NEXT(elm, field) ((elm)->field.tqe_next)
|
||||
|
||||
#define TAILQ_PREV(elm, headname, field) \
|
||||
(*(((struct headname *)((elm)->field.tqe_prev))->tqh_last))
|
||||
|
||||
#define TAILQ_REMOVE(head, elm, field) do { \
|
||||
if ((TAILQ_NEXT((elm), field)) != NULL) \
|
||||
TAILQ_NEXT((elm), field)->field.tqe_prev = \
|
||||
(elm)->field.tqe_prev; \
|
||||
else \
|
||||
(head)->tqh_last = (elm)->field.tqe_prev; \
|
||||
*(elm)->field.tqe_prev = TAILQ_NEXT((elm), field); \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* Circular queue declarations.
|
||||
*/
|
||||
#define CIRCLEQ_HEAD(name, type) \
|
||||
struct name { \
|
||||
struct type *cqh_first; /* first element */ \
|
||||
struct type *cqh_last; /* last element */ \
|
||||
}
|
||||
|
||||
#define CIRCLEQ_HEAD_INITIALIZER(head) \
|
||||
{ (void *)&(head), (void *)&(head) }
|
||||
|
||||
#define CIRCLEQ_ENTRY(type) \
|
||||
struct { \
|
||||
struct type *cqe_next; /* next element */ \
|
||||
struct type *cqe_prev; /* previous element */ \
|
||||
}
|
||||
|
||||
/*
|
||||
* Circular queue functions.
|
||||
*/
|
||||
#define CIRCLEQ_EMPTY(head) ((head)->cqh_first == (void *)(head))
|
||||
|
||||
#define CIRCLEQ_FIRST(head) ((head)->cqh_first)
|
||||
|
||||
#define CIRCLEQ_FOREACH(var, head, field) \
|
||||
for ((var) = CIRCLEQ_FIRST((head)); \
|
||||
(var) != (void *)(head); \
|
||||
(var) = CIRCLEQ_NEXT((var), field))
|
||||
|
||||
#define CIRCLEQ_FOREACH_REVERSE(var, head, field) \
|
||||
for ((var) = CIRCLEQ_LAST((head)); \
|
||||
(var) != (void *)(head); \
|
||||
(var) = CIRCLEQ_PREV((var), field))
|
||||
|
||||
#define CIRCLEQ_INIT(head) do { \
|
||||
CIRCLEQ_FIRST((head)) = (void *)(head); \
|
||||
CIRCLEQ_LAST((head)) = (void *)(head); \
|
||||
} while (0)
|
||||
|
||||
#define CIRCLEQ_INSERT_AFTER(head, listelm, elm, field) do { \
|
||||
CIRCLEQ_NEXT((elm), field) = CIRCLEQ_NEXT((listelm), field); \
|
||||
CIRCLEQ_PREV((elm), field) = (listelm); \
|
||||
if (CIRCLEQ_NEXT((listelm), field) == (void *)(head)) \
|
||||
CIRCLEQ_LAST((head)) = (elm); \
|
||||
else \
|
||||
CIRCLEQ_PREV(CIRCLEQ_NEXT((listelm), field), field) = (elm);\
|
||||
CIRCLEQ_NEXT((listelm), field) = (elm); \
|
||||
} while (0)
|
||||
|
||||
#define CIRCLEQ_INSERT_BEFORE(head, listelm, elm, field) do { \
|
||||
CIRCLEQ_NEXT((elm), field) = (listelm); \
|
||||
CIRCLEQ_PREV((elm), field) = CIRCLEQ_PREV((listelm), field); \
|
||||
if (CIRCLEQ_PREV((listelm), field) == (void *)(head)) \
|
||||
CIRCLEQ_FIRST((head)) = (elm); \
|
||||
else \
|
||||
CIRCLEQ_NEXT(CIRCLEQ_PREV((listelm), field), field) = (elm);\
|
||||
CIRCLEQ_PREV((listelm), field) = (elm); \
|
||||
} while (0)
|
||||
|
||||
#define CIRCLEQ_INSERT_HEAD(head, elm, field) do { \
|
||||
CIRCLEQ_NEXT((elm), field) = CIRCLEQ_FIRST((head)); \
|
||||
CIRCLEQ_PREV((elm), field) = (void *)(head); \
|
||||
if (CIRCLEQ_LAST((head)) == (void *)(head)) \
|
||||
CIRCLEQ_LAST((head)) = (elm); \
|
||||
else \
|
||||
CIRCLEQ_PREV(CIRCLEQ_FIRST((head)), field) = (elm); \
|
||||
CIRCLEQ_FIRST((head)) = (elm); \
|
||||
} while (0)
|
||||
|
||||
#define CIRCLEQ_INSERT_TAIL(head, elm, field) do { \
|
||||
CIRCLEQ_NEXT((elm), field) = (void *)(head); \
|
||||
CIRCLEQ_PREV((elm), field) = CIRCLEQ_LAST((head)); \
|
||||
if (CIRCLEQ_FIRST((head)) == (void *)(head)) \
|
||||
CIRCLEQ_FIRST((head)) = (elm); \
|
||||
else \
|
||||
CIRCLEQ_NEXT(CIRCLEQ_LAST((head)), field) = (elm); \
|
||||
CIRCLEQ_LAST((head)) = (elm); \
|
||||
} while (0)
|
||||
|
||||
#define CIRCLEQ_LAST(head) ((head)->cqh_last)
|
||||
|
||||
#define CIRCLEQ_NEXT(elm,field) ((elm)->field.cqe_next)
|
||||
|
||||
#define CIRCLEQ_PREV(elm,field) ((elm)->field.cqe_prev)
|
||||
|
||||
#define CIRCLEQ_REMOVE(head, elm, field) do { \
|
||||
if (CIRCLEQ_NEXT((elm), field) == (void *)(head)) \
|
||||
CIRCLEQ_LAST((head)) = CIRCLEQ_PREV((elm), field); \
|
||||
else \
|
||||
CIRCLEQ_PREV(CIRCLEQ_NEXT((elm), field), field) = \
|
||||
CIRCLEQ_PREV((elm), field); \
|
||||
if (CIRCLEQ_PREV((elm), field) == (void *)(head)) \
|
||||
CIRCLEQ_FIRST((head)) = CIRCLEQ_NEXT((elm), field); \
|
||||
else \
|
||||
CIRCLEQ_NEXT(CIRCLEQ_PREV((elm), field), field) = \
|
||||
CIRCLEQ_NEXT((elm), field); \
|
||||
} while (0)
|
||||
|
||||
#ifdef _KERNEL
|
||||
|
||||
/*
|
||||
* XXX insque() and remque() are an old way of handling certain queues.
|
||||
* They bogusly assumes that all queue heads look alike.
|
||||
*/
|
||||
|
||||
struct quehead {
|
||||
struct quehead *qh_link;
|
||||
struct quehead *qh_rlink;
|
||||
};
|
||||
|
||||
#ifdef __GNUC__
|
||||
|
||||
static __inline void
|
||||
insque(void *a, void *b)
|
||||
{
|
||||
struct quehead *element = (struct quehead *)a,
|
||||
*head = (struct quehead *)b;
|
||||
|
||||
element->qh_link = head->qh_link;
|
||||
element->qh_rlink = head;
|
||||
head->qh_link = element;
|
||||
element->qh_link->qh_rlink = element;
|
||||
}
|
||||
|
||||
static __inline void
|
||||
remque(void *a)
|
||||
{
|
||||
struct quehead *element = (struct quehead *)a;
|
||||
|
||||
element->qh_link->qh_rlink = element->qh_rlink;
|
||||
element->qh_rlink->qh_link = element->qh_link;
|
||||
element->qh_rlink = 0;
|
||||
}
|
||||
|
||||
#else /* !__GNUC__ */
|
||||
|
||||
void insque __P((void *a, void *b));
|
||||
void remque __P((void *a));
|
||||
|
||||
#endif /* __GNUC__ */
|
||||
|
||||
#endif /* _KERNEL */
|
||||
|
||||
#endif /* !_SYS_QUEUE_H_ */
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,678 @@
|
||||
/*
|
||||
* Copyright 2002 Niels Provos <provos@citi.umich.edu>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _SYS_TREE_H_
|
||||
#define _SYS_TREE_H_
|
||||
|
||||
/*
|
||||
* This file defines data structures for different types of trees:
|
||||
* splay trees and red-black trees.
|
||||
*
|
||||
* A splay tree is a self-organizing data structure. Every operation
|
||||
* on the tree causes a splay to happen. The splay moves the requested
|
||||
* node to the root of the tree and partly rebalances it.
|
||||
*
|
||||
* This has the benefit that request locality causes faster lookups as
|
||||
* the requested nodes move to the top of the tree. On the other hand,
|
||||
* every lookup causes memory writes.
|
||||
*
|
||||
* The Balance Theorem bounds the total access time for m operations
|
||||
* and n inserts on an initially empty tree as O((m + n)lg n). The
|
||||
* amortized cost for a sequence of m accesses to a splay tree is O(lg n);
|
||||
*
|
||||
* A red-black tree is a binary search tree with the node color as an
|
||||
* extra attribute. It fulfills a set of conditions:
|
||||
* - every search path from the root to a leaf consists of the
|
||||
* same number of black nodes,
|
||||
* - each red node (except for the root) has a black parent,
|
||||
* - each leaf node is black.
|
||||
*
|
||||
* Every operation on a red-black tree is bounded as O(lg n).
|
||||
* The maximum height of a red-black tree is 2lg (n+1).
|
||||
*/
|
||||
|
||||
#define SPLAY_HEAD(name, type) \
|
||||
struct name { \
|
||||
struct type *sph_root; /* root of the tree */ \
|
||||
}
|
||||
|
||||
#define SPLAY_INITIALIZER(root) \
|
||||
{ NULL }
|
||||
|
||||
#define SPLAY_INIT(root) do { \
|
||||
(root)->sph_root = NULL; \
|
||||
} while (0)
|
||||
|
||||
#define SPLAY_ENTRY(type) \
|
||||
struct { \
|
||||
struct type *spe_left; /* left element */ \
|
||||
struct type *spe_right; /* right element */ \
|
||||
}
|
||||
|
||||
#define SPLAY_LEFT(elm, field) (elm)->field.spe_left
|
||||
#define SPLAY_RIGHT(elm, field) (elm)->field.spe_right
|
||||
#define SPLAY_ROOT(head) (head)->sph_root
|
||||
#define SPLAY_EMPTY(head) (SPLAY_ROOT(head) == NULL)
|
||||
|
||||
/* SPLAY_ROTATE_{LEFT,RIGHT} expect that tmp hold SPLAY_{RIGHT,LEFT} */
|
||||
#define SPLAY_ROTATE_RIGHT(head, tmp, field) do { \
|
||||
SPLAY_LEFT((head)->sph_root, field) = SPLAY_RIGHT(tmp, field); \
|
||||
SPLAY_RIGHT(tmp, field) = (head)->sph_root; \
|
||||
(head)->sph_root = tmp; \
|
||||
} while (0)
|
||||
|
||||
#define SPLAY_ROTATE_LEFT(head, tmp, field) do { \
|
||||
SPLAY_RIGHT((head)->sph_root, field) = SPLAY_LEFT(tmp, field); \
|
||||
SPLAY_LEFT(tmp, field) = (head)->sph_root; \
|
||||
(head)->sph_root = tmp; \
|
||||
} while (0)
|
||||
|
||||
#define SPLAY_LINKLEFT(head, tmp, field) do { \
|
||||
SPLAY_LEFT(tmp, field) = (head)->sph_root; \
|
||||
tmp = (head)->sph_root; \
|
||||
(head)->sph_root = SPLAY_LEFT((head)->sph_root, field); \
|
||||
} while (0)
|
||||
|
||||
#define SPLAY_LINKRIGHT(head, tmp, field) do { \
|
||||
SPLAY_RIGHT(tmp, field) = (head)->sph_root; \
|
||||
tmp = (head)->sph_root; \
|
||||
(head)->sph_root = SPLAY_RIGHT((head)->sph_root, field); \
|
||||
} while (0)
|
||||
|
||||
#define SPLAY_ASSEMBLE(head, node, left, right, field) do { \
|
||||
SPLAY_RIGHT(left, field) = SPLAY_LEFT((head)->sph_root, field); \
|
||||
SPLAY_LEFT(right, field) = SPLAY_RIGHT((head)->sph_root, field);\
|
||||
SPLAY_LEFT((head)->sph_root, field) = SPLAY_RIGHT(node, field); \
|
||||
SPLAY_RIGHT((head)->sph_root, field) = SPLAY_LEFT(node, field); \
|
||||
} while (0)
|
||||
|
||||
/* Generates prototypes and inline functions */
|
||||
|
||||
#define SPLAY_PROTOTYPE(name, type, field, cmp) \
|
||||
void name##_SPLAY(struct name *, struct type *); \
|
||||
void name##_SPLAY_MINMAX(struct name *, int); \
|
||||
struct type *name##_SPLAY_INSERT(struct name *, struct type *); \
|
||||
struct type *name##_SPLAY_REMOVE(struct name *, struct type *); \
|
||||
\
|
||||
/* Finds the node with the same key as elm */ \
|
||||
static __inline struct type * \
|
||||
name##_SPLAY_FIND(struct name *head, struct type *elm) \
|
||||
{ \
|
||||
if (SPLAY_EMPTY(head)) \
|
||||
return(NULL); \
|
||||
name##_SPLAY(head, elm); \
|
||||
if ((cmp)(elm, (head)->sph_root) == 0) \
|
||||
return (head->sph_root); \
|
||||
return (NULL); \
|
||||
} \
|
||||
\
|
||||
static __inline struct type * \
|
||||
name##_SPLAY_NEXT(struct name *head, struct type *elm) \
|
||||
{ \
|
||||
name##_SPLAY(head, elm); \
|
||||
if (SPLAY_RIGHT(elm, field) != NULL) { \
|
||||
elm = SPLAY_RIGHT(elm, field); \
|
||||
while (SPLAY_LEFT(elm, field) != NULL) { \
|
||||
elm = SPLAY_LEFT(elm, field); \
|
||||
} \
|
||||
} else \
|
||||
elm = NULL; \
|
||||
return (elm); \
|
||||
} \
|
||||
\
|
||||
static __inline struct type * \
|
||||
name##_SPLAY_MIN_MAX(struct name *head, int val) \
|
||||
{ \
|
||||
name##_SPLAY_MINMAX(head, val); \
|
||||
return (SPLAY_ROOT(head)); \
|
||||
}
|
||||
|
||||
/* Main splay operation.
|
||||
* Moves node close to the key of elm to top
|
||||
*/
|
||||
#define SPLAY_GENERATE(name, type, field, cmp) \
|
||||
struct type * \
|
||||
name##_SPLAY_INSERT(struct name *head, struct type *elm) \
|
||||
{ \
|
||||
if (SPLAY_EMPTY(head)) { \
|
||||
SPLAY_LEFT(elm, field) = SPLAY_RIGHT(elm, field) = NULL; \
|
||||
} else { \
|
||||
int __comp; \
|
||||
name##_SPLAY(head, elm); \
|
||||
__comp = (cmp)(elm, (head)->sph_root); \
|
||||
if(__comp < 0) { \
|
||||
SPLAY_LEFT(elm, field) = SPLAY_LEFT((head)->sph_root, field);\
|
||||
SPLAY_RIGHT(elm, field) = (head)->sph_root; \
|
||||
SPLAY_LEFT((head)->sph_root, field) = NULL; \
|
||||
} else if (__comp > 0) { \
|
||||
SPLAY_RIGHT(elm, field) = SPLAY_RIGHT((head)->sph_root, field);\
|
||||
SPLAY_LEFT(elm, field) = (head)->sph_root; \
|
||||
SPLAY_RIGHT((head)->sph_root, field) = NULL; \
|
||||
} else \
|
||||
return ((head)->sph_root); \
|
||||
} \
|
||||
(head)->sph_root = (elm); \
|
||||
return (NULL); \
|
||||
} \
|
||||
\
|
||||
struct type * \
|
||||
name##_SPLAY_REMOVE(struct name *head, struct type *elm) \
|
||||
{ \
|
||||
struct type *__tmp; \
|
||||
if (SPLAY_EMPTY(head)) \
|
||||
return (NULL); \
|
||||
name##_SPLAY(head, elm); \
|
||||
if ((cmp)(elm, (head)->sph_root) == 0) { \
|
||||
if (SPLAY_LEFT((head)->sph_root, field) == NULL) { \
|
||||
(head)->sph_root = SPLAY_RIGHT((head)->sph_root, field);\
|
||||
} else { \
|
||||
__tmp = SPLAY_RIGHT((head)->sph_root, field); \
|
||||
(head)->sph_root = SPLAY_LEFT((head)->sph_root, field);\
|
||||
name##_SPLAY(head, elm); \
|
||||
SPLAY_RIGHT((head)->sph_root, field) = __tmp; \
|
||||
} \
|
||||
return (elm); \
|
||||
} \
|
||||
return (NULL); \
|
||||
} \
|
||||
\
|
||||
void \
|
||||
name##_SPLAY(struct name *head, struct type *elm) \
|
||||
{ \
|
||||
struct type __node, *__left, *__right, *__tmp; \
|
||||
int __comp; \
|
||||
\
|
||||
SPLAY_LEFT(&__node, field) = SPLAY_RIGHT(&__node, field) = NULL;\
|
||||
__left = __right = &__node; \
|
||||
\
|
||||
while ((__comp = (cmp)(elm, (head)->sph_root))) { \
|
||||
if (__comp < 0) { \
|
||||
__tmp = SPLAY_LEFT((head)->sph_root, field); \
|
||||
if (__tmp == NULL) \
|
||||
break; \
|
||||
if ((cmp)(elm, __tmp) < 0){ \
|
||||
SPLAY_ROTATE_RIGHT(head, __tmp, field); \
|
||||
if (SPLAY_LEFT((head)->sph_root, field) == NULL)\
|
||||
break; \
|
||||
} \
|
||||
SPLAY_LINKLEFT(head, __right, field); \
|
||||
} else if (__comp > 0) { \
|
||||
__tmp = SPLAY_RIGHT((head)->sph_root, field); \
|
||||
if (__tmp == NULL) \
|
||||
break; \
|
||||
if ((cmp)(elm, __tmp) > 0){ \
|
||||
SPLAY_ROTATE_LEFT(head, __tmp, field); \
|
||||
if (SPLAY_RIGHT((head)->sph_root, field) == NULL)\
|
||||
break; \
|
||||
} \
|
||||
SPLAY_LINKRIGHT(head, __left, field); \
|
||||
} \
|
||||
} \
|
||||
SPLAY_ASSEMBLE(head, &__node, __left, __right, field); \
|
||||
} \
|
||||
\
|
||||
/* Splay with either the minimum or the maximum element \
|
||||
* Used to find minimum or maximum element in tree. \
|
||||
*/ \
|
||||
void name##_SPLAY_MINMAX(struct name *head, int __comp) \
|
||||
{ \
|
||||
struct type __node, *__left, *__right, *__tmp; \
|
||||
\
|
||||
SPLAY_LEFT(&__node, field) = SPLAY_RIGHT(&__node, field) = NULL;\
|
||||
__left = __right = &__node; \
|
||||
\
|
||||
while (1) { \
|
||||
if (__comp < 0) { \
|
||||
__tmp = SPLAY_LEFT((head)->sph_root, field); \
|
||||
if (__tmp == NULL) \
|
||||
break; \
|
||||
if (__comp < 0){ \
|
||||
SPLAY_ROTATE_RIGHT(head, __tmp, field); \
|
||||
if (SPLAY_LEFT((head)->sph_root, field) == NULL)\
|
||||
break; \
|
||||
} \
|
||||
SPLAY_LINKLEFT(head, __right, field); \
|
||||
} else if (__comp > 0) { \
|
||||
__tmp = SPLAY_RIGHT((head)->sph_root, field); \
|
||||
if (__tmp == NULL) \
|
||||
break; \
|
||||
if (__comp > 0) { \
|
||||
SPLAY_ROTATE_LEFT(head, __tmp, field); \
|
||||
if (SPLAY_RIGHT((head)->sph_root, field) == NULL)\
|
||||
break; \
|
||||
} \
|
||||
SPLAY_LINKRIGHT(head, __left, field); \
|
||||
} \
|
||||
} \
|
||||
SPLAY_ASSEMBLE(head, &__node, __left, __right, field); \
|
||||
}
|
||||
|
||||
#define SPLAY_NEGINF -1
|
||||
#define SPLAY_INF 1
|
||||
|
||||
#define SPLAY_INSERT(name, x, y) name##_SPLAY_INSERT(x, y)
|
||||
#define SPLAY_REMOVE(name, x, y) name##_SPLAY_REMOVE(x, y)
|
||||
#define SPLAY_FIND(name, x, y) name##_SPLAY_FIND(x, y)
|
||||
#define SPLAY_NEXT(name, x, y) name##_SPLAY_NEXT(x, y)
|
||||
#define SPLAY_MIN(name, x) (SPLAY_EMPTY(x) ? NULL \
|
||||
: name##_SPLAY_MIN_MAX(x, SPLAY_NEGINF))
|
||||
#define SPLAY_MAX(name, x) (SPLAY_EMPTY(x) ? NULL \
|
||||
: name##_SPLAY_MIN_MAX(x, SPLAY_INF))
|
||||
|
||||
#define SPLAY_FOREACH(x, name, head) \
|
||||
for ((x) = SPLAY_MIN(name, head); \
|
||||
(x) != NULL; \
|
||||
(x) = SPLAY_NEXT(name, head, x))
|
||||
|
||||
/* Macros that define a red-back tree */
|
||||
#define RB_HEAD(name, type) \
|
||||
struct name { \
|
||||
struct type *rbh_root; /* root of the tree */ \
|
||||
}
|
||||
|
||||
#define RB_INITIALIZER(root) \
|
||||
{ NULL }
|
||||
|
||||
#define RB_INIT(root) do { \
|
||||
(root)->rbh_root = NULL; \
|
||||
} while (0)
|
||||
|
||||
#define RB_BLACK 0
|
||||
#define RB_RED 1
|
||||
#define RB_ENTRY(type) \
|
||||
struct { \
|
||||
struct type *rbe_left; /* left element */ \
|
||||
struct type *rbe_right; /* right element */ \
|
||||
struct type *rbe_parent; /* parent element */ \
|
||||
int rbe_color; /* node color */ \
|
||||
}
|
||||
|
||||
#define RB_LEFT(elm, field) (elm)->field.rbe_left
|
||||
#define RB_RIGHT(elm, field) (elm)->field.rbe_right
|
||||
#define RB_PARENT(elm, field) (elm)->field.rbe_parent
|
||||
#define RB_COLOR(elm, field) (elm)->field.rbe_color
|
||||
#define RB_ROOT(head) (head)->rbh_root
|
||||
#define RB_EMPTY(head) (RB_ROOT(head) == NULL)
|
||||
|
||||
#define RB_SET(elm, parent, field) do { \
|
||||
RB_PARENT(elm, field) = parent; \
|
||||
RB_LEFT(elm, field) = RB_RIGHT(elm, field) = NULL; \
|
||||
RB_COLOR(elm, field) = RB_RED; \
|
||||
} while (0)
|
||||
|
||||
#define RB_SET_BLACKRED(black, red, field) do { \
|
||||
RB_COLOR(black, field) = RB_BLACK; \
|
||||
RB_COLOR(red, field) = RB_RED; \
|
||||
} while (0)
|
||||
|
||||
#ifndef RB_AUGMENT
|
||||
#define RB_AUGMENT(x)
|
||||
#endif
|
||||
|
||||
#define RB_ROTATE_LEFT(head, elm, tmp, field) do { \
|
||||
(tmp) = RB_RIGHT(elm, field); \
|
||||
if ((RB_RIGHT(elm, field) = RB_LEFT(tmp, field))) { \
|
||||
RB_PARENT(RB_LEFT(tmp, field), field) = (elm); \
|
||||
} \
|
||||
RB_AUGMENT(elm); \
|
||||
if ((RB_PARENT(tmp, field) = RB_PARENT(elm, field))) { \
|
||||
if ((elm) == RB_LEFT(RB_PARENT(elm, field), field)) \
|
||||
RB_LEFT(RB_PARENT(elm, field), field) = (tmp); \
|
||||
else \
|
||||
RB_RIGHT(RB_PARENT(elm, field), field) = (tmp); \
|
||||
} else \
|
||||
(head)->rbh_root = (tmp); \
|
||||
RB_LEFT(tmp, field) = (elm); \
|
||||
RB_PARENT(elm, field) = (tmp); \
|
||||
RB_AUGMENT(tmp); \
|
||||
if ((RB_PARENT(tmp, field))) \
|
||||
RB_AUGMENT(RB_PARENT(tmp, field)); \
|
||||
} while (0)
|
||||
|
||||
#define RB_ROTATE_RIGHT(head, elm, tmp, field) do { \
|
||||
(tmp) = RB_LEFT(elm, field); \
|
||||
if ((RB_LEFT(elm, field) = RB_RIGHT(tmp, field))) { \
|
||||
RB_PARENT(RB_RIGHT(tmp, field), field) = (elm); \
|
||||
} \
|
||||
RB_AUGMENT(elm); \
|
||||
if ((RB_PARENT(tmp, field) = RB_PARENT(elm, field))) { \
|
||||
if ((elm) == RB_LEFT(RB_PARENT(elm, field), field)) \
|
||||
RB_LEFT(RB_PARENT(elm, field), field) = (tmp); \
|
||||
else \
|
||||
RB_RIGHT(RB_PARENT(elm, field), field) = (tmp); \
|
||||
} else \
|
||||
(head)->rbh_root = (tmp); \
|
||||
RB_RIGHT(tmp, field) = (elm); \
|
||||
RB_PARENT(elm, field) = (tmp); \
|
||||
RB_AUGMENT(tmp); \
|
||||
if ((RB_PARENT(tmp, field))) \
|
||||
RB_AUGMENT(RB_PARENT(tmp, field)); \
|
||||
} while (0)
|
||||
|
||||
/* Generates prototypes and inline functions */
|
||||
#define RB_PROTOTYPE(name, type, field, cmp) \
|
||||
void name##_RB_INSERT_COLOR(struct name *, struct type *); \
|
||||
void name##_RB_REMOVE_COLOR(struct name *, struct type *, struct type *);\
|
||||
struct type *name##_RB_REMOVE(struct name *, struct type *); \
|
||||
struct type *name##_RB_INSERT(struct name *, struct type *); \
|
||||
struct type *name##_RB_FIND(struct name *, struct type *); \
|
||||
struct type *name##_RB_NEXT(struct type *); \
|
||||
struct type *name##_RB_MINMAX(struct name *, int); \
|
||||
\
|
||||
|
||||
/* Main rb operation.
|
||||
* Moves node close to the key of elm to top
|
||||
*/
|
||||
#define RB_GENERATE(name, type, field, cmp) \
|
||||
void \
|
||||
name##_RB_INSERT_COLOR(struct name *head, struct type *elm) \
|
||||
{ \
|
||||
struct type *parent, *gparent, *tmp; \
|
||||
while ((parent = RB_PARENT(elm, field)) && \
|
||||
RB_COLOR(parent, field) == RB_RED) { \
|
||||
gparent = RB_PARENT(parent, field); \
|
||||
if (parent == RB_LEFT(gparent, field)) { \
|
||||
tmp = RB_RIGHT(gparent, field); \
|
||||
if (tmp && RB_COLOR(tmp, field) == RB_RED) { \
|
||||
RB_COLOR(tmp, field) = RB_BLACK; \
|
||||
RB_SET_BLACKRED(parent, gparent, field);\
|
||||
elm = gparent; \
|
||||
continue; \
|
||||
} \
|
||||
if (RB_RIGHT(parent, field) == elm) { \
|
||||
RB_ROTATE_LEFT(head, parent, tmp, field);\
|
||||
tmp = parent; \
|
||||
parent = elm; \
|
||||
elm = tmp; \
|
||||
} \
|
||||
RB_SET_BLACKRED(parent, gparent, field); \
|
||||
RB_ROTATE_RIGHT(head, gparent, tmp, field); \
|
||||
} else { \
|
||||
tmp = RB_LEFT(gparent, field); \
|
||||
if (tmp && RB_COLOR(tmp, field) == RB_RED) { \
|
||||
RB_COLOR(tmp, field) = RB_BLACK; \
|
||||
RB_SET_BLACKRED(parent, gparent, field);\
|
||||
elm = gparent; \
|
||||
continue; \
|
||||
} \
|
||||
if (RB_LEFT(parent, field) == elm) { \
|
||||
RB_ROTATE_RIGHT(head, parent, tmp, field);\
|
||||
tmp = parent; \
|
||||
parent = elm; \
|
||||
elm = tmp; \
|
||||
} \
|
||||
RB_SET_BLACKRED(parent, gparent, field); \
|
||||
RB_ROTATE_LEFT(head, gparent, tmp, field); \
|
||||
} \
|
||||
} \
|
||||
RB_COLOR(head->rbh_root, field) = RB_BLACK; \
|
||||
} \
|
||||
\
|
||||
void \
|
||||
name##_RB_REMOVE_COLOR(struct name *head, struct type *parent, struct type *elm) \
|
||||
{ \
|
||||
struct type *tmp; \
|
||||
while ((elm == NULL || RB_COLOR(elm, field) == RB_BLACK) && \
|
||||
elm != RB_ROOT(head)) { \
|
||||
if (RB_LEFT(parent, field) == elm) { \
|
||||
tmp = RB_RIGHT(parent, field); \
|
||||
if (RB_COLOR(tmp, field) == RB_RED) { \
|
||||
RB_SET_BLACKRED(tmp, parent, field); \
|
||||
RB_ROTATE_LEFT(head, parent, tmp, field);\
|
||||
tmp = RB_RIGHT(parent, field); \
|
||||
} \
|
||||
if ((RB_LEFT(tmp, field) == NULL || \
|
||||
RB_COLOR(RB_LEFT(tmp, field), field) == RB_BLACK) &&\
|
||||
(RB_RIGHT(tmp, field) == NULL || \
|
||||
RB_COLOR(RB_RIGHT(tmp, field), field) == RB_BLACK)) {\
|
||||
RB_COLOR(tmp, field) = RB_RED; \
|
||||
elm = parent; \
|
||||
parent = RB_PARENT(elm, field); \
|
||||
} else { \
|
||||
if (RB_RIGHT(tmp, field) == NULL || \
|
||||
RB_COLOR(RB_RIGHT(tmp, field), field) == RB_BLACK) {\
|
||||
struct type *oleft; \
|
||||
if ((oleft = RB_LEFT(tmp, field)))\
|
||||
RB_COLOR(oleft, field) = RB_BLACK;\
|
||||
RB_COLOR(tmp, field) = RB_RED; \
|
||||
RB_ROTATE_RIGHT(head, tmp, oleft, field);\
|
||||
tmp = RB_RIGHT(parent, field); \
|
||||
} \
|
||||
RB_COLOR(tmp, field) = RB_COLOR(parent, field);\
|
||||
RB_COLOR(parent, field) = RB_BLACK; \
|
||||
if (RB_RIGHT(tmp, field)) \
|
||||
RB_COLOR(RB_RIGHT(tmp, field), field) = RB_BLACK;\
|
||||
RB_ROTATE_LEFT(head, parent, tmp, field);\
|
||||
elm = RB_ROOT(head); \
|
||||
break; \
|
||||
} \
|
||||
} else { \
|
||||
tmp = RB_LEFT(parent, field); \
|
||||
if (RB_COLOR(tmp, field) == RB_RED) { \
|
||||
RB_SET_BLACKRED(tmp, parent, field); \
|
||||
RB_ROTATE_RIGHT(head, parent, tmp, field);\
|
||||
tmp = RB_LEFT(parent, field); \
|
||||
} \
|
||||
if ((RB_LEFT(tmp, field) == NULL || \
|
||||
RB_COLOR(RB_LEFT(tmp, field), field) == RB_BLACK) &&\
|
||||
(RB_RIGHT(tmp, field) == NULL || \
|
||||
RB_COLOR(RB_RIGHT(tmp, field), field) == RB_BLACK)) {\
|
||||
RB_COLOR(tmp, field) = RB_RED; \
|
||||
elm = parent; \
|
||||
parent = RB_PARENT(elm, field); \
|
||||
} else { \
|
||||
if (RB_LEFT(tmp, field) == NULL || \
|
||||
RB_COLOR(RB_LEFT(tmp, field), field) == RB_BLACK) {\
|
||||
struct type *oright; \
|
||||
if ((oright = RB_RIGHT(tmp, field)))\
|
||||
RB_COLOR(oright, field) = RB_BLACK;\
|
||||
RB_COLOR(tmp, field) = RB_RED; \
|
||||
RB_ROTATE_LEFT(head, tmp, oright, field);\
|
||||
tmp = RB_LEFT(parent, field); \
|
||||
} \
|
||||
RB_COLOR(tmp, field) = RB_COLOR(parent, field);\
|
||||
RB_COLOR(parent, field) = RB_BLACK; \
|
||||
if (RB_LEFT(tmp, field)) \
|
||||
RB_COLOR(RB_LEFT(tmp, field), field) = RB_BLACK;\
|
||||
RB_ROTATE_RIGHT(head, parent, tmp, field);\
|
||||
elm = RB_ROOT(head); \
|
||||
break; \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
if (elm) \
|
||||
RB_COLOR(elm, field) = RB_BLACK; \
|
||||
} \
|
||||
\
|
||||
struct type * \
|
||||
name##_RB_REMOVE(struct name *head, struct type *elm) \
|
||||
{ \
|
||||
struct type *child, *parent, *old = elm; \
|
||||
int color; \
|
||||
if (RB_LEFT(elm, field) == NULL) \
|
||||
child = RB_RIGHT(elm, field); \
|
||||
else if (RB_RIGHT(elm, field) == NULL) \
|
||||
child = RB_LEFT(elm, field); \
|
||||
else { \
|
||||
struct type *left; \
|
||||
elm = RB_RIGHT(elm, field); \
|
||||
while ((left = RB_LEFT(elm, field))) \
|
||||
elm = left; \
|
||||
child = RB_RIGHT(elm, field); \
|
||||
parent = RB_PARENT(elm, field); \
|
||||
color = RB_COLOR(elm, field); \
|
||||
if (child) \
|
||||
RB_PARENT(child, field) = parent; \
|
||||
if (parent) { \
|
||||
if (RB_LEFT(parent, field) == elm) \
|
||||
RB_LEFT(parent, field) = child; \
|
||||
else \
|
||||
RB_RIGHT(parent, field) = child; \
|
||||
RB_AUGMENT(parent); \
|
||||
} else \
|
||||
RB_ROOT(head) = child; \
|
||||
if (RB_PARENT(elm, field) == old) \
|
||||
parent = elm; \
|
||||
(elm)->field = (old)->field; \
|
||||
if (RB_PARENT(old, field)) { \
|
||||
if (RB_LEFT(RB_PARENT(old, field), field) == old)\
|
||||
RB_LEFT(RB_PARENT(old, field), field) = elm;\
|
||||
else \
|
||||
RB_RIGHT(RB_PARENT(old, field), field) = elm;\
|
||||
RB_AUGMENT(RB_PARENT(old, field)); \
|
||||
} else \
|
||||
RB_ROOT(head) = elm; \
|
||||
RB_PARENT(RB_LEFT(old, field), field) = elm; \
|
||||
if (RB_RIGHT(old, field)) \
|
||||
RB_PARENT(RB_RIGHT(old, field), field) = elm; \
|
||||
if (parent) { \
|
||||
left = parent; \
|
||||
do { \
|
||||
RB_AUGMENT(left); \
|
||||
} while ((left = RB_PARENT(left, field))); \
|
||||
} \
|
||||
goto color; \
|
||||
} \
|
||||
parent = RB_PARENT(elm, field); \
|
||||
color = RB_COLOR(elm, field); \
|
||||
if (child) \
|
||||
RB_PARENT(child, field) = parent; \
|
||||
if (parent) { \
|
||||
if (RB_LEFT(parent, field) == elm) \
|
||||
RB_LEFT(parent, field) = child; \
|
||||
else \
|
||||
RB_RIGHT(parent, field) = child; \
|
||||
RB_AUGMENT(parent); \
|
||||
} else \
|
||||
RB_ROOT(head) = child; \
|
||||
color: \
|
||||
if (color == RB_BLACK) \
|
||||
name##_RB_REMOVE_COLOR(head, parent, child); \
|
||||
return (old); \
|
||||
} \
|
||||
\
|
||||
/* Inserts a node into the RB tree */ \
|
||||
struct type * \
|
||||
name##_RB_INSERT(struct name *head, struct type *elm) \
|
||||
{ \
|
||||
struct type *tmp; \
|
||||
struct type *parent = NULL; \
|
||||
int comp = 0; \
|
||||
tmp = RB_ROOT(head); \
|
||||
while (tmp) { \
|
||||
parent = tmp; \
|
||||
comp = (cmp)(elm, parent); \
|
||||
if (comp < 0) \
|
||||
tmp = RB_LEFT(tmp, field); \
|
||||
else if (comp > 0) \
|
||||
tmp = RB_RIGHT(tmp, field); \
|
||||
else \
|
||||
return (tmp); \
|
||||
} \
|
||||
RB_SET(elm, parent, field); \
|
||||
if (parent != NULL) { \
|
||||
if (comp < 0) \
|
||||
RB_LEFT(parent, field) = elm; \
|
||||
else \
|
||||
RB_RIGHT(parent, field) = elm; \
|
||||
RB_AUGMENT(parent); \
|
||||
} else \
|
||||
{ \
|
||||
RB_ROOT(head) = elm; \
|
||||
} \
|
||||
name##_RB_INSERT_COLOR(head, elm); \
|
||||
return (NULL); \
|
||||
} \
|
||||
\
|
||||
/* Finds the node with the same key as elm */ \
|
||||
struct type * \
|
||||
name##_RB_FIND(struct name *head, struct type *elm) \
|
||||
{ \
|
||||
struct type *tmp = RB_ROOT(head); \
|
||||
int comp; \
|
||||
while (tmp) { \
|
||||
comp = cmp(elm, tmp); \
|
||||
if (comp < 0) \
|
||||
tmp = RB_LEFT(tmp, field); \
|
||||
else if (comp > 0) \
|
||||
tmp = RB_RIGHT(tmp, field); \
|
||||
else \
|
||||
return (tmp); \
|
||||
} \
|
||||
return (NULL); \
|
||||
} \
|
||||
\
|
||||
struct type * \
|
||||
name##_RB_NEXT(struct type *elm) \
|
||||
{ \
|
||||
if (RB_RIGHT(elm, field)) { \
|
||||
elm = RB_RIGHT(elm, field); \
|
||||
while (RB_LEFT(elm, field)) \
|
||||
elm = RB_LEFT(elm, field); \
|
||||
} else { \
|
||||
if (RB_PARENT(elm, field) && \
|
||||
(elm == RB_LEFT(RB_PARENT(elm, field), field))) \
|
||||
elm = RB_PARENT(elm, field); \
|
||||
else { \
|
||||
while (RB_PARENT(elm, field) && \
|
||||
(elm == RB_RIGHT(RB_PARENT(elm, field), field)))\
|
||||
elm = RB_PARENT(elm, field); \
|
||||
elm = RB_PARENT(elm, field); \
|
||||
} \
|
||||
} \
|
||||
return (elm); \
|
||||
} \
|
||||
\
|
||||
struct type * \
|
||||
name##_RB_MINMAX(struct name *head, int val) \
|
||||
{ \
|
||||
struct type *tmp = RB_ROOT(head); \
|
||||
struct type *parent = NULL; \
|
||||
while (tmp) { \
|
||||
parent = tmp; \
|
||||
if (val < 0) \
|
||||
tmp = RB_LEFT(tmp, field); \
|
||||
else \
|
||||
tmp = RB_RIGHT(tmp, field); \
|
||||
} \
|
||||
return (parent); \
|
||||
}
|
||||
|
||||
#define RB_NEGINF -1
|
||||
#define RB_INF 1
|
||||
|
||||
#define RB_INSERT(name, x, y) name##_RB_INSERT(x, y)
|
||||
#define RB_REMOVE(name, x, y) name##_RB_REMOVE(x, y)
|
||||
#define RB_FIND(name, x, y) name##_RB_FIND(x, y)
|
||||
#define RB_NEXT(name, x, y) name##_RB_NEXT(y)
|
||||
#define RB_MIN(name, x) name##_RB_MINMAX(x, RB_NEGINF)
|
||||
#define RB_MAX(name, x) name##_RB_MINMAX(x, RB_INF)
|
||||
|
||||
#define RB_FOREACH(x, name, head) \
|
||||
for ((x) = RB_MIN(name, head); \
|
||||
(x) != NULL; \
|
||||
(x) = name##_RB_NEXT(x))
|
||||
|
||||
#endif /* _SYS_TREE_H_ */
|
||||
@@ -0,0 +1,65 @@
|
||||
/*----------------------------------------------------------------------------*
|
||||
* *
|
||||
* n w - g t p v 2 c *
|
||||
* G P R S T u n n e l i n g P r o t o c o l v 2 c S t a c k *
|
||||
* *
|
||||
* *
|
||||
* Copyright (c) 2010-2011 Amit Chawre *
|
||||
* All rights reserved. *
|
||||
* *
|
||||
* Redistribution and use in source and binary forms, with or without *
|
||||
* modification, are permitted provided that the following conditions *
|
||||
* are met: *
|
||||
* *
|
||||
* 1. Redistributions of source code must retain the above copyright *
|
||||
* notice, this list of conditions and the following disclaimer. *
|
||||
* 2. Redistributions in binary form must reproduce the above copyright *
|
||||
* notice, this list of conditions and the following disclaimer in the *
|
||||
* documentation and/or other materials provided with the distribution. *
|
||||
* 3. The name of the author may not be used to endorse or promote products *
|
||||
* derived from this software without specific prior written permission. *
|
||||
* *
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR *
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES *
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. *
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, *
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT *
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, *
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY *
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT *
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF *
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
#ifndef __NW_ERROR_H__
|
||||
#define __NW_ERROR_H__
|
||||
|
||||
/**
|
||||
* @file NwError.h
|
||||
* @brief This header file contains return error code type definitions.
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef enum {
|
||||
|
||||
NW_OK = 0x00000000,
|
||||
NW_GTPV2C_IE_MISSING,
|
||||
NW_GTPV2C_IE_INCORRECT,
|
||||
NW_GTPV2C_MANDATORY_IE_DUPLICATE,
|
||||
NW_GTPV2C_CONDITIONAL_IE_MISSING,
|
||||
NW_GTPV2C_MANDATORY_IE_MISSING,
|
||||
NW_GTPV2C_MSG_MALFORMED,
|
||||
NW_FAILURE = 0xFFFFFFFE
|
||||
} NwRcT;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __NW_ERROR_CODE_H__ */
|
||||
|
||||
|
||||
@@ -0,0 +1,595 @@
|
||||
/*----------------------------------------------------------------------------*
|
||||
* *
|
||||
* n w - g t p v 2 c *
|
||||
* G P R S T u n n e l i n g P r o t o c o l v 2 c S t a c k *
|
||||
* *
|
||||
* *
|
||||
* Copyright (c) 2010-2011 Amit Chawre *
|
||||
* All rights reserved. *
|
||||
* *
|
||||
* Redistribution and use in source and binary forms, with or without *
|
||||
* modification, are permitted provided that the following conditions *
|
||||
* are met: *
|
||||
* *
|
||||
* 1. Redistributions of source code must retain the above copyright *
|
||||
* notice, this list of conditions and the following disclaimer. *
|
||||
* 2. Redistributions in binary form must reproduce the above copyright *
|
||||
* notice, this list of conditions and the following disclaimer in the *
|
||||
* documentation and/or other materials provided with the distribution. *
|
||||
* 3. The name of the author may not be used to endorse or promote products *
|
||||
* derived from this software without specific prior written permission. *
|
||||
* *
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR *
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES *
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. *
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, *
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT *
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, *
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY *
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT *
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF *
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef __NW_GTPV2C_H__
|
||||
#define __NW_GTPV2C_H__
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <arpa/inet.h>
|
||||
#include "NwTypes.h"
|
||||
#include "NwError.h"
|
||||
|
||||
/** @mainpage
|
||||
|
||||
@section intro Introduction
|
||||
|
||||
nw-gtpv2c library is a free and open source control plane implementation of GPRS
|
||||
Tunneling protocol v2 also known as eGTPc as per 3GPP TS29274-930.
|
||||
The library is published under BSD three clause license.
|
||||
|
||||
@section scope Scope
|
||||
|
||||
The stack library also does basic tasks like packet/header validation,
|
||||
retransmission and message parsing.
|
||||
|
||||
@section design Design Philosophy
|
||||
|
||||
The stack is fully-asynchronous in design for compatibility with event loop
|
||||
mechanisms such as select, poll, etc. and can also be used for multi-threaded
|
||||
applications. It should compile on Linux, *BSD, Mac OS X, Solaris and Windows
|
||||
(cygwin).
|
||||
|
||||
The stack is designed for high portability not only for the hardware and OS it will
|
||||
run on but also for the application software that uses it. The stack doesn't mandate
|
||||
conditions on the user application architecture or design. The stack relies on
|
||||
the user application for infrastructure utilities such as I/O, timers,
|
||||
logs and multithreading. This realized by using callback mechanisms and enables the
|
||||
stack library to seamlessly integrate without or very little changes to the existing
|
||||
application framework.
|
||||
|
||||
The stack architecture builds upon following mentioned entities that are external to it.
|
||||
|
||||
User Layer Protocol (ULP) Entity:
|
||||
This layer implements the intelligent logic for the application and sits on top of the
|
||||
stack.
|
||||
|
||||
UDP Entity:
|
||||
This is the layer below the stack and is responsible for UDP I/O with the stack and network.
|
||||
It may or may not be housed in ULP.
|
||||
|
||||
Timer Manager Entity:
|
||||
Timer Manager Entity provides the stack with infrastructure for timer CRUD operations.
|
||||
|
||||
Log Manager Entity:
|
||||
Log Manager Entity provides the stack with callbacks for logging operations. It may
|
||||
or may not be housed in ULP.
|
||||
|
||||
The application may implement all above entities as a single or multiple object.
|
||||
|
||||
@section applications Applications and Usage
|
||||
|
||||
Please refer sample applications under 'test-app' directory for usage examples.
|
||||
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file NwGtpv2c.h
|
||||
* @author Amit Chawre
|
||||
* @brief
|
||||
*
|
||||
* This header file contains all required definitions and functions
|
||||
* prototypes for using nw-gtpv2c library.
|
||||
*
|
||||
**/
|
||||
|
||||
/*--------------------------------------------------------------------------*
|
||||
* S T A C K H A N D L E D E F I N I T I O N S *
|
||||
*--------------------------------------------------------------------------*/
|
||||
|
||||
typedef NwPtrT NwGtpv2cStackHandleT; /**< Gtpv2c Stack Handle */
|
||||
typedef NwPtrT NwGtpv2cUlpHandleT; /**< Gtpv2c Stack Ulp Entity Handle */
|
||||
typedef NwPtrT NwGtpv2cUdpHandleT; /**< Gtpv2c Stack Udp Entity Handle */
|
||||
typedef NwPtrT NwGtpv2cTimerMgrHandleT; /**< Gtpv2c Stack Timer Manager Handle */
|
||||
typedef NwPtrT NwGtpv2cMemMgrHandleT; /**< Gtpv2c Stack Memory Manager Handle */
|
||||
typedef NwPtrT NwGtpv2cLogMgrHandleT; /**< Gtpv2c Stack Log Manager Handle */
|
||||
typedef NwPtrT NwGtpv2cTimerHandleT; /**< Gtpv2c Stack Timer Handle */
|
||||
typedef NwPtrT NwGtpv2cMsgHandleT; /**< Gtpv2c Msg Handle */
|
||||
typedef NwPtrT NwGtpv2cTrxnHandleT; /**< Gtpv2c Transaction Handle */
|
||||
typedef NwPtrT NwGtpv2cTunnelHandleT; /**< Gtpv2c Ulp Tunnel Handle */
|
||||
typedef NwPtrT NwGtpv2cUlpTrxnHandleT; /**< Gtpv2c Ulp Transaction Handle */
|
||||
typedef NwPtrT NwGtpv2cUlpTunnelHandleT; /**< Gtpv2c Ulp Tunnel Handle */
|
||||
|
||||
typedef NwU8T NwGtpv2cMsgTypeT; /**< Gtpv2c Msg Type */
|
||||
|
||||
typedef struct NwGtpv2cStackConfigS
|
||||
{
|
||||
NwU16T __tbd;
|
||||
} NwGtpv2cStackConfigT;
|
||||
|
||||
/*--------------------------------------------------------------------------*
|
||||
* S T A C K A P I D E F I N I T I O N S *
|
||||
*--------------------------------------------------------------------------*/
|
||||
|
||||
#define NW_GTPV2C_ULP_API_FLAG_NONE (0x00 << 24)
|
||||
#define NW_GTPV2C_ULP_API_FLAG_CREATE_LOCAL_TUNNEL (0x01 << 24)
|
||||
#define NW_GTPV2C_ULP_API_FLAG_DELETE_LOCAL_TUNNEL (0x02 << 24)
|
||||
#define NW_GTPV2C_ULP_API_FLAG_IS_COMMAND_MESSAGE (0x03 << 24)
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
* Gtpv2c Stack ULP API type definitions
|
||||
*--------------------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* APIs types between ULP and Stack
|
||||
*/
|
||||
|
||||
typedef enum
|
||||
{
|
||||
/* APIs from ULP to stack */
|
||||
|
||||
NW_GTPV2C_ULP_API_INITIAL_REQ = 0x00000000, /**< Send a initial message */
|
||||
NW_GTPV2C_ULP_API_TRIGGERED_REQ, /**< Send a triggered req message */
|
||||
NW_GTPV2C_ULP_API_TRIGGERED_RSP, /**< Send a triggered rsp message */
|
||||
|
||||
/* APIs from stack to ULP */
|
||||
|
||||
NW_GTPV2C_ULP_API_INITIAL_REQ_IND, /**< Receive a initial message from stack */
|
||||
NW_GTPV2C_ULP_API_TRIGGERED_RSP_IND, /**< Recieve a triggered rsp message from stack */
|
||||
NW_GTPV2C_ULP_API_TRIGGERED_REQ_IND, /**< Recieve a triggered req message from stack */
|
||||
NW_GTPV2C_ULP_API_RSP_FAILURE_IND, /**< Rsp failure for gtpv2 message from stack */
|
||||
|
||||
/* Local tunnel management APIs from ULP to stack */
|
||||
|
||||
NW_GTPV2C_ULP_CREATE_LOCAL_TUNNEL, /**< Create a local tunnel */
|
||||
NW_GTPV2C_ULP_DELETE_LOCAL_TUNNEL, /**< Delete a local tunnel */
|
||||
|
||||
/* Do not add below this */
|
||||
NW_GTPV2C_ULP_API_END = 0xFFFFFFFF,
|
||||
|
||||
} NwGtpv2cUlpApiTypeT;
|
||||
|
||||
/**
|
||||
* Error information of incoming GTP messages
|
||||
*/
|
||||
|
||||
typedef struct NwGtpv2cErrorS
|
||||
{
|
||||
NW_IN NwU8T cause;
|
||||
NW_IN NwU8T flags;
|
||||
struct {
|
||||
NW_IN NwU8T type;
|
||||
NW_IN NwU8T instance;
|
||||
} offendingIe;
|
||||
} NwGtpv2cErrorT;
|
||||
|
||||
/**
|
||||
* API information elements between ULP and Stack for
|
||||
* sending a Gtpv2c initial message.
|
||||
*/
|
||||
|
||||
typedef struct
|
||||
{
|
||||
NW_INOUT NwGtpv2cTunnelHandleT hTunnel; /**< Tunnel handle over which the mesasge is to be sent.*/
|
||||
NW_IN NwU16T t3Timer;
|
||||
NW_IN NwU16T maxRetries;
|
||||
NW_IN NwGtpv2cUlpTrxnHandleT hUlpTrxn; /**< Optional handle to be returned in rsp of this msg. */
|
||||
|
||||
NW_IN NwU32T peerIp; /**< Required only in case when hTunnel == 0 */
|
||||
NW_IN NwU32T teidLocal; /**< Required only in case when hTunnel == 0 */
|
||||
NW_IN NwGtpv2cUlpTunnelHandleT hUlpTunnel; /**< Required only in case when hTunnel == 0 */
|
||||
} NwGtpv2cInitialReqInfoT;
|
||||
|
||||
/**
|
||||
* API information elements between ULP and Stack for
|
||||
* sending a Gtpv2c triggered request message.
|
||||
*/
|
||||
|
||||
typedef struct
|
||||
{
|
||||
NW_IN NwGtpv2cTunnelHandleT hTunnel; /**< Tunnel handle over which the mesasge is to be sent */
|
||||
NW_IN NwGtpv2cTrxnHandleT hTrxn; /**< Request Trxn handle which to which triggered req is being sent */
|
||||
NW_IN NwU16T t3Timer;
|
||||
NW_IN NwU16T maxRetries;
|
||||
NW_IN NwGtpv2cUlpTrxnHandleT hUlpTrxn; /**< Optional handle to be returned in rsp of this msg. */
|
||||
NW_IN NwU32T peerIp; /**< Required only in case when hTunnel == 0 */
|
||||
NW_IN NwU32T teidLocal; /**< Required only in case when hTunnel == 0 */
|
||||
NW_IN NwGtpv2cUlpTunnelHandleT hUlpTunnel; /**< Required only in case when hTunnel == 0 */
|
||||
|
||||
} NwGtpv2cTriggeredReqInfoT;
|
||||
|
||||
/**
|
||||
* API information elements between ULP and Stack for
|
||||
* sending a Gtpv2c triggered response message.
|
||||
*/
|
||||
|
||||
typedef struct
|
||||
{
|
||||
NW_IN NwGtpv2cTrxnHandleT hTrxn; /**< Request Trxn handle which to which triggered rsp is being sent */
|
||||
NW_IN NwU32T teidLocal; /**< Required only if NW_GTPV2C_ULP_API_FLAG_CREATE_LOCAL_TUNNEL is set to flags. */
|
||||
NW_IN NwGtpv2cUlpTunnelHandleT hUlpTunnel; /**< Required only if NW_GTPV2C_ULP_API_FLAG_CREATE_LOCAL_TUNNEL is set to flags. */
|
||||
|
||||
NW_OUT NwGtpv2cTunnelHandleT hTunnel; /**< Returned only in case flags is set to
|
||||
NW_GTPV2C_ULP_API_FLAG_CREATE_LOCAL_TUNNEL */
|
||||
} NwGtpv2cTriggeredRspInfoT;
|
||||
|
||||
/**
|
||||
* API information elements between ULP and Stack for
|
||||
* sending a Gtpv2c initial message.
|
||||
*/
|
||||
|
||||
typedef struct
|
||||
{
|
||||
NW_IN NwGtpv2cErrorT error;
|
||||
NW_IN NwGtpv2cTrxnHandleT hTrxn;
|
||||
NW_IN NwGtpv2cUlpTrxnHandleT hUlpTrxn;
|
||||
NW_IN NwGtpv2cMsgTypeT msgType;
|
||||
NW_IN NwU32T peerIp;
|
||||
NW_IN NwU32T peerPort;
|
||||
NW_IN NwGtpv2cUlpTunnelHandleT hUlpTunnel;
|
||||
NW_INOUT NwGtpv2cTunnelHandleT hTunnel;
|
||||
} NwGtpv2cInitialReqIndInfoT;
|
||||
|
||||
/**
|
||||
* API information elements between ULP and Stack for
|
||||
* sending a Gtpv2c triggered request message.
|
||||
*/
|
||||
|
||||
typedef struct
|
||||
{
|
||||
NW_IN NwGtpv2cErrorT error;
|
||||
NW_IN NwGtpv2cTrxnHandleT hTrxn;
|
||||
NW_IN NwGtpv2cUlpTrxnHandleT hUlpTrxn;
|
||||
NW_IN NwGtpv2cMsgTypeT msgType;
|
||||
NW_IN NwU32T seqNum;
|
||||
NW_IN NwU32T teidLocal;
|
||||
NW_IN NwU32T teidRemote;
|
||||
NW_IN NwGtpv2cUlpTunnelHandleT hUlpTunnel;
|
||||
} NwGtpv2cTriggeredReqIndInfoT;
|
||||
|
||||
/**
|
||||
* API information elements between ULP and Stack for
|
||||
* sending a Gtpv2c triggered response message.
|
||||
*/
|
||||
|
||||
typedef struct
|
||||
{
|
||||
NW_IN NwGtpv2cErrorT error;
|
||||
NW_IN NwGtpv2cUlpTrxnHandleT hUlpTrxn;
|
||||
NW_IN NwGtpv2cUlpTunnelHandleT hUlpTunnel;
|
||||
NW_IN NwGtpv2cMsgTypeT msgType;
|
||||
} NwGtpv2cTriggeredRspIndInfoT;
|
||||
|
||||
/**
|
||||
* API information elements between ULP and Stack for
|
||||
* receving a path failure indication from stack.
|
||||
*/
|
||||
|
||||
typedef struct
|
||||
{
|
||||
NW_IN NwGtpv2cUlpTrxnHandleT hUlpTrxn;
|
||||
NW_IN NwGtpv2cUlpTunnelHandleT hUlpTunnel;
|
||||
} NwGtpv2cRspFailureIndInfoT;
|
||||
|
||||
/**
|
||||
* API information elements between ULP and Stack for
|
||||
* creating local tunnel.
|
||||
*/
|
||||
|
||||
typedef struct
|
||||
{
|
||||
NW_OUT NwGtpv2cTunnelHandleT hTunnel;
|
||||
NW_IN NwGtpv2cUlpTunnelHandleT hUlpTunnel;
|
||||
NW_IN NwU32T teidLocal;
|
||||
NW_IN NwU32T peerIp;
|
||||
} NwGtpv2cCreateLocalTunnelInfoT;
|
||||
|
||||
|
||||
/**
|
||||
* API information elements between ULP and Stack for
|
||||
* deleting a local tunnel.
|
||||
*/
|
||||
|
||||
typedef struct
|
||||
{
|
||||
NW_IN NwGtpv2cTunnelHandleT hTunnel;
|
||||
} NwGtpv2cDeleteLocalTunnelInfoT;
|
||||
|
||||
|
||||
/**
|
||||
* API container structure between ULP and Stack.
|
||||
*/
|
||||
|
||||
typedef struct
|
||||
{
|
||||
NwGtpv2cUlpApiTypeT apiType; /**< First bytes of this field is used as flag holder */
|
||||
NwGtpv2cMsgHandleT hMsg; /**< Handle associated with this API */
|
||||
union
|
||||
{
|
||||
NwGtpv2cInitialReqInfoT initialReqInfo;
|
||||
NwGtpv2cTriggeredRspInfoT triggeredRspInfo;
|
||||
NwGtpv2cTriggeredReqInfoT triggeredReqInfo;
|
||||
NwGtpv2cInitialReqIndInfoT initialReqIndInfo;
|
||||
NwGtpv2cTriggeredRspIndInfoT triggeredRspIndInfo;
|
||||
NwGtpv2cTriggeredReqIndInfoT triggeredReqIndInfo;
|
||||
NwGtpv2cRspFailureIndInfoT rspFailureInfo;
|
||||
NwGtpv2cCreateLocalTunnelInfoT createLocalTunnelInfo;
|
||||
NwGtpv2cDeleteLocalTunnelInfoT deleteLocalTunnelInfo;
|
||||
} apiInfo;
|
||||
} NwGtpv2cUlpApiT;
|
||||
|
||||
|
||||
/*--------------------------------------------------------------------------*
|
||||
* S T A C K E N T I T I E S D E F I N I T I O N S *
|
||||
*--------------------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* Gtpv2c ULP entity definition
|
||||
*/
|
||||
|
||||
typedef struct
|
||||
{
|
||||
NwGtpv2cUlpHandleT hUlp;
|
||||
NwRcT (*ulpReqCallback) ( NW_IN NwGtpv2cUlpHandleT hUlp,
|
||||
NW_IN NwGtpv2cUlpApiT *pUlpApi);
|
||||
} NwGtpv2cUlpEntityT;
|
||||
|
||||
|
||||
/**
|
||||
* Gtpv2c UDP entity definition
|
||||
*/
|
||||
|
||||
typedef struct
|
||||
{
|
||||
NwGtpv2cUdpHandleT hUdp;
|
||||
NwRcT (*udpDataReqCallback) ( NW_IN NwGtpv2cUdpHandleT udpHandle,
|
||||
NW_IN NwU8T* dataBuf,
|
||||
NW_IN NwU32T dataSize,
|
||||
NW_IN NwU32T peerIp,
|
||||
NW_IN NwU32T peerPort);
|
||||
} NwGtpv2cUdpEntityT;
|
||||
|
||||
/**
|
||||
* Gtpv2c Memory Manager entity definition
|
||||
*/
|
||||
|
||||
typedef struct
|
||||
{
|
||||
NwGtpv2cMemMgrHandleT hMemMgr;
|
||||
void* (*memAlloc)( NW_IN NwGtpv2cMemMgrHandleT hMemMgr,
|
||||
NW_IN NwU32T memSize,
|
||||
NW_IN NwCharT* fileName,
|
||||
NW_IN NwU32T lineNumber);
|
||||
|
||||
void (*memFree) ( NW_IN NwGtpv2cMemMgrHandleT hMemMgr,
|
||||
NW_IN void* hMem,
|
||||
NW_IN NwCharT* fileName,
|
||||
NW_IN NwU32T lineNumber);
|
||||
} NwGtpv2cMemMgrEntityT;
|
||||
|
||||
|
||||
#define NW_GTPV2C_TMR_TYPE_ONE_SHOT (0)
|
||||
#define NW_GTPV2C_TMR_TYPE_REPETITIVE (1)
|
||||
/**
|
||||
* Gtpv2c Timer Manager entity definition
|
||||
*/
|
||||
|
||||
typedef struct
|
||||
{
|
||||
NwGtpv2cTimerMgrHandleT tmrMgrHandle;
|
||||
NwRcT (*tmrStartCallback)( NW_IN NwGtpv2cTimerMgrHandleT tmrMgrHandle,
|
||||
NW_IN NwU32T timeoutSec,
|
||||
NW_IN NwU32T timeoutUsec,
|
||||
NW_IN NwU32T tmrType,
|
||||
NW_IN void* tmrArg,
|
||||
NW_OUT NwGtpv2cTimerHandleT* tmrHandle);
|
||||
|
||||
NwRcT (*tmrStopCallback) ( NW_IN NwGtpv2cTimerMgrHandleT tmrMgrHandle,
|
||||
NW_IN NwGtpv2cTimerHandleT tmrHandle);
|
||||
} NwGtpv2cTimerMgrEntityT;
|
||||
|
||||
/**
|
||||
* Gtpv2c Log manager entity definition
|
||||
*/
|
||||
|
||||
typedef struct
|
||||
{
|
||||
NwGtpv2cLogMgrHandleT logMgrHandle;
|
||||
NwRcT (*logReqCallback) (NW_IN NwGtpv2cLogMgrHandleT logMgrHandle,
|
||||
NW_IN NwU32T logLevel,
|
||||
NW_IN NwCharT* filename,
|
||||
NW_IN NwU32T line,
|
||||
NW_IN NwCharT* logStr);
|
||||
} NwGtpv2cLogMgrEntityT;
|
||||
|
||||
|
||||
/*--------------------------------------------------------------------------*
|
||||
* P U B L I C F U N C T I O N S *
|
||||
*--------------------------------------------------------------------------*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
Constructor. Initialize nw-gtpv2c stack instance.
|
||||
|
||||
@param[in,out] phGtpcStackHandle : Pointer to stack instance handle
|
||||
*/
|
||||
|
||||
NwRcT
|
||||
nwGtpv2cInitialize( NW_INOUT NwGtpv2cStackHandleT* phGtpcStackHandle);
|
||||
|
||||
/**
|
||||
Destructor. Destroy nw-gtpv2c stack instance .
|
||||
|
||||
@param[in] hGtpcStackHandle : Stack instance handle
|
||||
*/
|
||||
|
||||
NwRcT
|
||||
nwGtpv2cFinalize( NW_IN NwGtpv2cStackHandleT hGtpcStackHandle);
|
||||
|
||||
/**
|
||||
Set Configuration for the nw-gtpv2c stack.
|
||||
|
||||
@param[in,out] phGtpcStackHandle : Pointer to stack handle
|
||||
*/
|
||||
|
||||
NwRcT
|
||||
nwGtpv2cConfigSet( NW_IN NwGtpv2cStackHandleT* phGtpcStackHandle, NW_IN NwGtpv2cStackConfigT* pConfig);
|
||||
|
||||
/**
|
||||
Get Configuration for the nw-gtpv2c stack.
|
||||
|
||||
@param[in,out] phGtpcStackHandle : Pointer to stack handle
|
||||
*/
|
||||
|
||||
NwRcT
|
||||
nwGtpv2cConfigGet( NW_IN NwGtpv2cStackHandleT* phGtpcStackHandle, NW_OUT NwGtpv2cStackConfigT* pConfig);
|
||||
|
||||
/**
|
||||
Set ULP entity for the stack.
|
||||
|
||||
@param[in] hGtpcStackHandle : Stack handle
|
||||
@param[in] pUlpEntity : Pointer to ULP entity.
|
||||
@return NW_OK on success.
|
||||
*/
|
||||
|
||||
NwRcT
|
||||
nwGtpv2cSetUlpEntity( NW_IN NwGtpv2cStackHandleT hGtpcStackHandle,
|
||||
NW_IN NwGtpv2cUlpEntityT* pUlpEntity);
|
||||
|
||||
/**
|
||||
Set UDP entity for the stack.
|
||||
|
||||
@param[in] hGtpcStackHandle : Stack handle
|
||||
@param[in] pUdpEntity : Pointer to UDP entity.
|
||||
@return NW_OK on success.
|
||||
*/
|
||||
|
||||
NwRcT
|
||||
nwGtpv2cSetUdpEntity( NW_IN NwGtpv2cStackHandleT hGtpcStackHandle,
|
||||
NW_IN NwGtpv2cUdpEntityT* pUdpEntity);
|
||||
|
||||
/**
|
||||
Set MemMgr entity for the stack.
|
||||
|
||||
@param[in] hGtpcStackHandle : Stack handle
|
||||
@param[in] pMemMgr : Pointer to Memory Manager.
|
||||
@return NW_OK on success.
|
||||
*/
|
||||
|
||||
NwRcT
|
||||
nwGtpv2cSetMemMgrEntity( NW_IN NwGtpv2cStackHandleT hGtpcStackHandle,
|
||||
NW_IN NwGtpv2cMemMgrEntityT* pMemMgr);
|
||||
|
||||
|
||||
/**
|
||||
Set TmrMgr entity for the stack.
|
||||
|
||||
@param[in] hGtpcStackHandle : Stack handle
|
||||
@param[in] pTmrMgr : Pointer to Timer Manager.
|
||||
@return NW_OK on success.
|
||||
*/
|
||||
|
||||
NwRcT
|
||||
nwGtpv2cSetTimerMgrEntity( NW_IN NwGtpv2cStackHandleT hGtpcStackHandle,
|
||||
NW_IN NwGtpv2cTimerMgrEntityT* pTmrMgr);
|
||||
|
||||
/**
|
||||
Set LogMgr entity for the stack.
|
||||
|
||||
@param[in] hGtpcStackHandle : Stack handle
|
||||
@param[in] pLogMgr : Pointer to Log Manager.
|
||||
@return NW_OK on success.
|
||||
*/
|
||||
|
||||
NwRcT
|
||||
nwGtpv2cSetLogMgrEntity( NW_IN NwGtpv2cStackHandleT hGtpcStackHandle,
|
||||
NW_IN NwGtpv2cLogMgrEntityT* pLogMgr);
|
||||
|
||||
/**
|
||||
Set log level for the stack.
|
||||
|
||||
@param[in] hGtpcStackHandle : Stack handle
|
||||
@param[in] logLevel : Log Level.
|
||||
@return NW_OK on success.
|
||||
*/
|
||||
|
||||
NwRcT
|
||||
nwGtpv2cSetLogLevel( NW_IN NwGtpv2cStackHandleT hGtpcStackHandle,
|
||||
NW_IN NwU32T logLevel);
|
||||
|
||||
|
||||
/**
|
||||
Process Data Request from UDP entity.
|
||||
|
||||
@param[in] hGtpcStackHandle : Stack handle
|
||||
@param[in] udpData : Pointer to received UDP data.
|
||||
@param[in] udpDataLen : Received data length.
|
||||
@param[in] dstPort : Received on port.
|
||||
@param[in] from : Received from peer information.
|
||||
@return NW_OK on success.
|
||||
*/
|
||||
|
||||
NwRcT
|
||||
nwGtpv2cProcessUdpReq( NW_IN NwGtpv2cStackHandleT hGtpcStackHandle,
|
||||
NW_IN NwU8T* udpData,
|
||||
NW_IN NwU32T udpDataLen,
|
||||
NW_IN NwU16T peerPort,
|
||||
NW_IN NwU32T peerIP);
|
||||
|
||||
/**
|
||||
Process Request from ULP entity.
|
||||
|
||||
@param[in] hGtpcStackHandle : Stack handle
|
||||
@param[in] pLogMgr : Pointer to Ulp Req.
|
||||
@return NW_OK on success.
|
||||
*/
|
||||
|
||||
NwRcT
|
||||
nwGtpv2cProcessUlpReq( NW_IN NwGtpv2cStackHandleT hGtpcStackHandle,
|
||||
NW_IN NwGtpv2cUlpApiT *ulpReq);
|
||||
|
||||
|
||||
/**
|
||||
Process Timer timeout Request from Timer Manager
|
||||
|
||||
@param[in] pLogMgr : Pointer timeout arguments.
|
||||
@return NW_OK on success.
|
||||
*/
|
||||
|
||||
NwRcT
|
||||
nwGtpv2cProcessTimeout( NW_IN void* timeoutArg);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __NW_GTPV2C_H__ */
|
||||
|
||||
/*--------------------------------------------------------------------------*
|
||||
* E N D O F F I L E *
|
||||
*--------------------------------------------------------------------------*/
|
||||
|
||||
@@ -0,0 +1,159 @@
|
||||
/*----------------------------------------------------------------------------*
|
||||
* *
|
||||
* n w - g t p v 2 c *
|
||||
* G P R S T u n n e l i n g P r o t o c o l v 2 c S t a c k *
|
||||
* *
|
||||
* *
|
||||
* Copyright (c) 2010-2011 Amit Chawre *
|
||||
* All rights reserved. *
|
||||
* *
|
||||
* Redistribution and use in source and binary forms, with or without *
|
||||
* modification, are permitted provided that the following conditions *
|
||||
* are met: *
|
||||
* *
|
||||
* 1. Redistributions of source code must retain the above copyright *
|
||||
* notice, this list of conditions and the following disclaimer. *
|
||||
* 2. Redistributions in binary form must reproduce the above copyright *
|
||||
* notice, this list of conditions and the following disclaimer in the *
|
||||
* documentation and/or other materials provided with the distribution. *
|
||||
* 3. The name of the author may not be used to endorse or promote products *
|
||||
* derived from this software without specific prior written permission. *
|
||||
* *
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR *
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES *
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. *
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, *
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT *
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, *
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY *
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT *
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF *
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @file NwGtpv2cIe.h
|
||||
* @brief This header file contains Information Element definitions for GTPv2c
|
||||
* as per 3GPP TS 29274-930.
|
||||
*/
|
||||
|
||||
#ifndef __NW_GTPV2C_IE_H__
|
||||
#define __NW_GTPV2C_IE_H__
|
||||
|
||||
/*--------------------------------------------------------------------------*
|
||||
* G T P V 2 C I E T Y P E M A C R O D E F I N I T I O N S *
|
||||
*--------------------------------------------------------------------------*/
|
||||
|
||||
#define NW_GTPV2C_IE_RESERVED (0)
|
||||
#define NW_GTPV2C_IE_IMSI (1)
|
||||
#define NW_GTPV2C_IE_CAUSE (2)
|
||||
#define NW_GTPV2C_IE_RECOVERY (3)
|
||||
#define NW_GTPV2C_IE_APN (71)
|
||||
#define NW_GTPV2C_IE_AMBR (72)
|
||||
#define NW_GTPV2C_IE_EBI (73)
|
||||
#define NW_GTPV2C_IE_IP_ADDRESS (74)
|
||||
#define NW_GTPV2C_IE_MEI (75)
|
||||
#define NW_GTPV2C_IE_MSISDN (76)
|
||||
#define NW_GTPV2C_IE_INDICATION (77)
|
||||
#define NW_GTPV2C_IE_PCO (78)
|
||||
#define NW_GTPV2C_IE_PAA (79)
|
||||
#define NW_GTPV2C_IE_BEARER_LEVEL_QOS (80)
|
||||
#define NW_GTPV2C_IE_FLOW_QOS (81)
|
||||
#define NW_GTPV2C_IE_RAT_TYPE (82)
|
||||
#define NW_GTPV2C_IE_SERVING_NETWORK (83)
|
||||
#define NW_GTPV2C_IE_BEARER_TFT (84)
|
||||
#define NW_GTPV2C_IE_TAD (85)
|
||||
#define NW_GTPV2C_IE_ULI (86)
|
||||
#define NW_GTPV2C_IE_FTEID (87)
|
||||
#define NW_GTPV2C_IE_TMSI (88)
|
||||
#define NW_GTPV2C_IE_GLOBAL_CN_ID (89)
|
||||
#define NW_GTPV2C_IE_S103PDF (90)
|
||||
#define NW_GTPV2C_IE_S1UDF (91)
|
||||
#define NW_GTPV2C_IE_DELAY_VALUE (92)
|
||||
#define NW_GTPV2C_IE_BEARER_CONTEXT (93)
|
||||
#define NW_GTPV2C_IE_CHARGING_ID (94)
|
||||
#define NW_GTPV2C_IE_CHARGING_CHARACTERISTICS (95)
|
||||
#define NW_GTPV2C_IE_TRACE_INFORMATION (96)
|
||||
#define NW_GTPV2C_IE_BEARER_FLAGS (97)
|
||||
#define NW_GTPV2C_IE_PDN_TYPE (99)
|
||||
#define NW_GTPV2C_IE_PROCEDURE_TRANSACTION_ID (100)
|
||||
#define NW_GTPV2C_IE_DRX_PARAMETER (101)
|
||||
#define NW_GTPV2C_IE_UE_NETWORK_CAPABILITY (102)
|
||||
#define NW_GTPV2C_IE_MM_CONTEXT (103)
|
||||
#define NW_GTPV2C_IE_PDN_CONNECTION (109)
|
||||
#define NW_GTPV2C_IE_PDU_NUMBERS (110)
|
||||
#define NW_GTPV2C_IE_PTMSI (111)
|
||||
#define NW_GTPV2C_IE_PTMSI_SIGNATURE (112)
|
||||
#define NW_GTPV2C_IE_HOP_COUNTER (113)
|
||||
#define NW_GTPV2C_IE_UE_TIME_ZONE (114)
|
||||
#define NW_GTPV2C_IE_TRACE_REFERENCE (115)
|
||||
#define NW_GTPV2C_IE_COMPLETE_REQUEST_MESSAGE (116)
|
||||
#define NW_GTPV2C_IE_GUTI (117)
|
||||
#define NW_GTPV2C_IE_F_CONTAINER (118)
|
||||
#define NW_GTPV2C_IE_F_CAUSE (119)
|
||||
#define NW_GTPV2C_IE_SELECTED_PLMN_ID (120)
|
||||
#define NW_GTPV2C_IE_TARGET_IDENTIFICATION (121)
|
||||
#define NW_GTPV2C_IE_PACKET_FLOW_ID (123)
|
||||
#define NW_GTPV2C_IE_RAB_CONTEXT (124)
|
||||
#define NW_GTPV2C_IE_SOURCE_RNC_PDCP_CONTEXT_INFO (125)
|
||||
#define NW_GTPV2C_IE_UDP_SOURCE_PORT_NUMBER (126)
|
||||
#define NW_GTPV2C_IE_APN_RESTRICTION (127)
|
||||
#define NW_GTPV2C_IE_SELECTION_MODE (128)
|
||||
#define NW_GTPV2C_IE_SOURCE_IDENTIFICATION (129)
|
||||
#define NW_GTPV2C_IE_CHANGE_REPORTING_ACTION (131)
|
||||
#define NW_GTPV2C_IE_FQ_CSID (132)
|
||||
#define NW_GTPV2C_IE_CHANNEL_NEEDED (133)
|
||||
#define NW_GTPV2C_IE_EMLPP_PRIORITY (134)
|
||||
#define NW_GTPV2C_IE_NODE_TYPE (135)
|
||||
#define NW_GTPV2C_IE_FQDN (136)
|
||||
#define NW_GTPV2C_IE_TI (137)
|
||||
#define NW_GTPV2C_IE_MBMS_SESSION_DURATION (138)
|
||||
#define NW_GTPV2C_IE_MBMS_SERIVCE_AREA (139)
|
||||
#define NW_GTPV2C_IE_MBMS_SESSION_IDENTIFIER (140)
|
||||
#define NW_GTPV2C_IE_MBMS_FLOW_IDENTIFIER (141)
|
||||
#define NW_GTPV2C_IE_MBMS_IP_MULTICAST_DISTRIBUTION (142)
|
||||
#define NW_GTPV2C_IE_MBMS_IP_DISTRIBUTION_ACK (143)
|
||||
#define NW_GTPV2C_IE_RFSP_INDEX (144)
|
||||
#define NW_GTPV2C_IE_UCI (145)
|
||||
#define NW_GTPV2C_IE_CSG_INFORMATION_REPORTING_ACTION (146)
|
||||
#define NW_GTPV2C_IE_CSG_ID (147)
|
||||
#define NW_GTPV2C_IE_CSG_MEMBERSHIP_INDICATION (148)
|
||||
#define NW_GTPV2C_IE_SERVICE_INDICATOR (149)
|
||||
#define NW_GTPV2C_IE_LDN (151)
|
||||
#define NW_GTPV2C_IE_ADDITIONAL_MM_CTXT_FOR_SRVCC (159)
|
||||
#define NW_GTPV2C_IE_ADDITIONAL_FLAGS_FOR_SRVCC (160)
|
||||
#define NW_GTPV2C_IE_PRIVATE_EXTENSION (255)
|
||||
#define NW_GTPV2C_IE_TYPE_MAXIMUM (256)
|
||||
|
||||
|
||||
/*--------------------------------------------------------------------------*
|
||||
* G T P V 2 C C A U S E V A L U E D E F I N I T I O N S *
|
||||
*--------------------------------------------------------------------------*/
|
||||
|
||||
#define NW_GTPV2C_CAUSE_REQUEST_ACCEPTED (16)
|
||||
#define NW_GTPV2C_CAUSE_INVALID_LENGTH (67)
|
||||
#define NW_GTPV2C_CAUSE_MANDATORY_IE_INCORRECT (69)
|
||||
#define NW_GTPV2C_CAUSE_MANDATORY_IE_MISSING (70)
|
||||
#define NW_GTPV2C_CAUSE_SYSTEM_FAILURE (72)
|
||||
#define NW_GTPV2C_CAUSE_REQUEST_REJECTED (94)
|
||||
#define NW_GTPV2C_CAUSE_REMOTE_PEER_NOT_RESPONDING (100)
|
||||
#define NW_GTPV2C_CAUSE_CONDITIONAL_IE_MISSING (103)
|
||||
|
||||
#define NW_GTPV2C_IE_INSTANCE_ZERO (0)
|
||||
#define NW_GTPV2C_IE_INSTANCE_ONE (1)
|
||||
#define NW_GTPV2C_IE_INSTANCE_TWO (2)
|
||||
#define NW_GTPV2C_IE_INSTANCE_THREE (3)
|
||||
#define NW_GTPV2C_IE_INSTANCE_FOUR (4)
|
||||
#define NW_GTPV2C_IE_INSTANCE_MAXIMUM (NW_GTPV2C_IE_INSTANCE_FOUR)
|
||||
|
||||
#define NW_GTPV2C_IE_PRESENCE_MANDATORY (1)
|
||||
#define NW_GTPV2C_IE_PRESENCE_CONDITIONAL (2)
|
||||
#define NW_GTPV2C_IE_PRESENCE_CONDITIONAL_OPTIONAL (3)
|
||||
#define NW_GTPV2C_IE_PRESENCE_OPTIONAL (4)
|
||||
|
||||
#endif /* __NW_GTPV2C_IE_H__ */
|
||||
|
||||
/*--------------------------------------------------------------------------*
|
||||
* E N D O F F I L E *
|
||||
*--------------------------------------------------------------------------*/
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user