git-svn-id: http://svn.eurecom.fr/openair4G/trunk@4234 818b1a75-f10b-46b9-bf7c-635c3b92a50f

This commit is contained in:
Cedric Roux
2013-10-21 08:08:15 +00:00
parent ff4360527c
commit d7c8c99e2d
860 changed files with 212101 additions and 0 deletions
+1
View File
@@ -0,0 +1 @@
+526
View File
@@ -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__*/
+249
View File
@@ -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__*/
+250
View File
@@ -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_ */
+8
View File
@@ -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_ */
+6
View File
@@ -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
View File
@@ -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_ */
+15
View File
@@ -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"
+24
View File
@@ -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_ */
+3
View File
@@ -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_ */
+16
View File
@@ -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)
+77
View File
@@ -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_ */
+1
View File
@@ -0,0 +1 @@
//WARNING: Do not include this header directly. Use intertask_interface.h instead.
+4
View File
@@ -0,0 +1,4 @@
#ifndef S11_MESSAGES_TYPES_H_
#define S11_MESSAGES_TYPES_H_
#endif /* S11_MESSAGES_TYPES_H_ */
+4
View File
@@ -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)
+51
View File
@@ -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_ */
+5
View File
@@ -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)
+43
View File
@@ -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_ */
+6
View File
@@ -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)
+34
View File
@@ -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_ */
+183
View File
@@ -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_ */
+6
View File
@@ -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)
+209
View File
@@ -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
+25
View File
@@ -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)
+3
View File
@@ -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)
+16
View File
@@ -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_ */
+674
View File
@@ -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>.
+15
View File
@@ -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
+22
View File
@@ -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
File diff suppressed because it is too large Load Diff
Binary file not shown.
+774
View File
@@ -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}
+9
View File
@@ -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
+1
View File
@@ -0,0 +1 @@
SUBDIRS = DOXYGEN
+31
View File
@@ -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
+49
View File
@@ -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)
+51
View File
@@ -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_ */
+520
View File
@@ -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(&gtpv1u_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,
&gtpv1u_data_p->udp_data, data_recv_callback, (void *)gtpv1u_data_p) < 0) {
return -1;
}
/* Initializing GTPv1-U stack */
if ((rc = nwGtpv1uInitialize(&gtpv1u_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) &gtpv1u_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;
}
+86
View File
@@ -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_ */
+78
View File
@@ -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_ */
+553
View File
@@ -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**)&gtpv1u_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**)&gtpv1u_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(&gtpv1u_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(&gtpv1u_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, &gtpv1u_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;
}
+20
View File
@@ -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
}
+1
View File
@@ -0,0 +1 @@
Amit Chawre
+26
View File
@@ -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.
View File
View File
@@ -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__ */
+886
View File
@@ -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;
}
+1
View File
@@ -0,0 +1 @@
SUBDIRS = nwgtpv2c-0.11/
+1
View File
@@ -0,0 +1 @@
Amit Chawre
+26
View File
@@ -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.
+370
View File
@@ -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
+168
View File
@@ -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
View File
@@ -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