astyle --recursive --indent=spaces=2 --style=kr --indent-col1-comments --break-blocks --convert-tabs --max-code-length=200

This is done for better merging branch/LG_PRE_RELEASE_0.3 into trunk (same process is applied on this branch)

git-svn-id: http://svn.eurecom.fr/openair4G/trunk@7073 818b1a75-f10b-46b9-bf7c-635c3b92a50f
This commit is contained in:
Lionel Gauthier
2015-04-09 09:29:12 +00:00
parent f0a8a0b3b5
commit 059a0a3fdc
2044 changed files with 1182666 additions and 1145123 deletions
+5 -5
View File
@@ -1,5 +1,5 @@
/******************************************************************************* /*******************************************************************************
OpenAirInterface OpenAirInterface
Copyright(c) 1999 - 2014 Eurecom Copyright(c) 1999 - 2014 Eurecom
OpenAirInterface is free software: you can redistribute it and/or modify OpenAirInterface is free software: you can redistribute it and/or modify
@@ -14,15 +14,15 @@
GNU General Public License for more details. GNU General Public License for more details.
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with OpenAirInterface.The full GNU General Public License is along with OpenAirInterface.The full GNU General Public License is
included in this distribution in the file called "COPYING". If not, included in this distribution in the file called "COPYING". If not,
see <http://www.gnu.org/licenses/>. see <http://www.gnu.org/licenses/>.
Contact Information Contact Information
OpenAirInterface Admin: openair_admin@eurecom.fr OpenAirInterface Admin: openair_admin@eurecom.fr
OpenAirInterface Tech : openair_tech@eurecom.fr OpenAirInterface Tech : openair_tech@eurecom.fr
OpenAirInterface Dev : openair4g-devel@eurecom.fr OpenAirInterface Dev : openair4g-devel@eurecom.fr
Address : Eurecom, Campus SophiaTech, 450 Route des Chappes, CS 50193 - 06904 Biot Sophia Antipolis cedex, FRANCE Address : Eurecom, Campus SophiaTech, 450 Route des Chappes, CS 50193 - 06904 Biot Sophia Antipolis cedex, FRANCE
*******************************************************************************/ *******************************************************************************/
@@ -30,7 +30,7 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#ifdef CMAKER #ifdef CMAKER
#include <platform_types.h> #include <platform_types.h>
#endif #endif
#if defined(ENB_MODE) #if defined(ENB_MODE)
+16 -16
View File
@@ -1,5 +1,5 @@
/******************************************************************************* /*******************************************************************************
OpenAirInterface OpenAirInterface
Copyright(c) 1999 - 2014 Eurecom Copyright(c) 1999 - 2014 Eurecom
OpenAirInterface is free software: you can redistribute it and/or modify OpenAirInterface is free software: you can redistribute it and/or modify
@@ -14,15 +14,15 @@
GNU General Public License for more details. GNU General Public License for more details.
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with OpenAirInterface.The full GNU General Public License is along with OpenAirInterface.The full GNU General Public License is
included in this distribution in the file called "COPYING". If not, included in this distribution in the file called "COPYING". If not,
see <http://www.gnu.org/licenses/>. see <http://www.gnu.org/licenses/>.
Contact Information Contact Information
OpenAirInterface Admin: openair_admin@eurecom.fr OpenAirInterface Admin: openair_admin@eurecom.fr
OpenAirInterface Tech : openair_tech@eurecom.fr OpenAirInterface Tech : openair_tech@eurecom.fr
OpenAirInterface Dev : openair4g-devel@eurecom.fr OpenAirInterface Dev : openair4g-devel@eurecom.fr
Address : Eurecom, Campus SophiaTech, 450 Route des Chappes, CS 50193 - 06904 Biot Sophia Antipolis cedex, FRANCE Address : Eurecom, Campus SophiaTech, 450 Route des Chappes, CS 50193 - 06904 Biot Sophia Antipolis cedex, FRANCE
*******************************************************************************/ *******************************************************************************/
@@ -41,24 +41,24 @@
/* Obtain a backtrace and print it to stdout. */ /* Obtain a backtrace and print it to stdout. */
void display_backtrace(void) void display_backtrace(void)
{ {
void *array[10]; void *array[10];
size_t size; size_t size;
char **strings; char **strings;
size_t i; size_t i;
size = backtrace(array, 10); size = backtrace(array, 10);
strings = backtrace_symbols(array, size); strings = backtrace_symbols(array, size);
printf("Obtained %zd stack frames.\n", size); printf("Obtained %zd stack frames.\n", size);
for (i = 0; i < size; i++) for (i = 0; i < size; i++)
printf("%s\n", strings[i]); printf("%s\n", strings[i]);
free(strings); free(strings);
} }
void backtrace_handle_signal(siginfo_t *info) void backtrace_handle_signal(siginfo_t *info)
{ {
display_backtrace(); display_backtrace();
//exit(EXIT_FAILURE); //exit(EXIT_FAILURE);
} }
+4 -4
View File
@@ -1,5 +1,5 @@
/******************************************************************************* /*******************************************************************************
OpenAirInterface OpenAirInterface
Copyright(c) 1999 - 2014 Eurecom Copyright(c) 1999 - 2014 Eurecom
OpenAirInterface is free software: you can redistribute it and/or modify OpenAirInterface is free software: you can redistribute it and/or modify
@@ -14,15 +14,15 @@
GNU General Public License for more details. GNU General Public License for more details.
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with OpenAirInterface.The full GNU General Public License is along with OpenAirInterface.The full GNU General Public License is
included in this distribution in the file called "COPYING". If not, included in this distribution in the file called "COPYING". If not,
see <http://www.gnu.org/licenses/>. see <http://www.gnu.org/licenses/>.
Contact Information Contact Information
OpenAirInterface Admin: openair_admin@eurecom.fr OpenAirInterface Admin: openair_admin@eurecom.fr
OpenAirInterface Tech : openair_tech@eurecom.fr OpenAirInterface Tech : openair_tech@eurecom.fr
OpenAirInterface Dev : openair4g-devel@eurecom.fr OpenAirInterface Dev : openair4g-devel@eurecom.fr
Address : Eurecom, Campus SophiaTech, 450 Route des Chappes, CS 50193 - 06904 Biot Sophia Antipolis cedex, FRANCE Address : Eurecom, Campus SophiaTech, 450 Route des Chappes, CS 50193 - 06904 Biot Sophia Antipolis cedex, FRANCE
*******************************************************************************/ *******************************************************************************/
File diff suppressed because it is too large Load Diff
+35 -35
View File
@@ -1,5 +1,5 @@
/******************************************************************************* /*******************************************************************************
OpenAirInterface OpenAirInterface
Copyright(c) 1999 - 2014 Eurecom Copyright(c) 1999 - 2014 Eurecom
OpenAirInterface is free software: you can redistribute it and/or modify OpenAirInterface is free software: you can redistribute it and/or modify
@@ -14,15 +14,15 @@
GNU General Public License for more details. GNU General Public License for more details.
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with OpenAirInterface.The full GNU General Public License is along with OpenAirInterface.The full GNU General Public License is
included in this distribution in the file called "COPYING". If not, included in this distribution in the file called "COPYING". If not,
see <http://www.gnu.org/licenses/>. see <http://www.gnu.org/licenses/>.
Contact Information Contact Information
OpenAirInterface Admin: openair_admin@eurecom.fr OpenAirInterface Admin: openair_admin@eurecom.fr
OpenAirInterface Tech : openair_tech@eurecom.fr OpenAirInterface Tech : openair_tech@eurecom.fr
OpenAirInterface Dev : openair4g-devel@eurecom.fr OpenAirInterface Dev : openair4g-devel@eurecom.fr
Address : Eurecom, Campus SophiaTech, 450 Route des Chappes, CS 50193 - 06904 Biot Sophia Antipolis cedex, FRANCE Address : Eurecom, Campus SophiaTech, 450 Route des Chappes, CS 50193 - 06904 Biot Sophia Antipolis cedex, FRANCE
*******************************************************************************/ *******************************************************************************/
@@ -62,41 +62,41 @@ typedef unsigned long message_number_t;
#define MESSAGE_NUMBER_SIZE (sizeof(unsigned long)) #define MESSAGE_NUMBER_SIZE (sizeof(unsigned long))
typedef enum message_priorities_e { typedef enum message_priorities_e {
MESSAGE_PRIORITY_MAX = 100, MESSAGE_PRIORITY_MAX = 100,
MESSAGE_PRIORITY_MAX_LEAST = 85, MESSAGE_PRIORITY_MAX_LEAST = 85,
MESSAGE_PRIORITY_MED_PLUS = 70, MESSAGE_PRIORITY_MED_PLUS = 70,
MESSAGE_PRIORITY_MED = 55, MESSAGE_PRIORITY_MED = 55,
MESSAGE_PRIORITY_MED_LEAST = 40, MESSAGE_PRIORITY_MED_LEAST = 40,
MESSAGE_PRIORITY_MIN_PLUS = 25, MESSAGE_PRIORITY_MIN_PLUS = 25,
MESSAGE_PRIORITY_MIN = 10, MESSAGE_PRIORITY_MIN = 10,
} message_priorities_t; } message_priorities_t;
typedef struct message_info_s { typedef struct message_info_s {
task_id_t id; task_id_t id;
message_priorities_t priority; message_priorities_t priority;
/* Message payload size */ /* Message payload size */
MessageHeaderSize size; MessageHeaderSize size;
/* Printable name */ /* Printable name */
const char * const name; const char * const name;
} message_info_t; } message_info_t;
typedef enum task_priorities_e { typedef enum task_priorities_e {
TASK_PRIORITY_MAX = 100, TASK_PRIORITY_MAX = 100,
TASK_PRIORITY_MAX_LEAST = 85, TASK_PRIORITY_MAX_LEAST = 85,
TASK_PRIORITY_MED_PLUS = 70, TASK_PRIORITY_MED_PLUS = 70,
TASK_PRIORITY_MED = 55, TASK_PRIORITY_MED = 55,
TASK_PRIORITY_MED_LEAST = 40, TASK_PRIORITY_MED_LEAST = 40,
TASK_PRIORITY_MIN_PLUS = 25, TASK_PRIORITY_MIN_PLUS = 25,
TASK_PRIORITY_MIN = 10, TASK_PRIORITY_MIN = 10,
} task_priorities_t; } task_priorities_t;
typedef struct task_info_s { typedef struct task_info_s {
thread_id_t thread; thread_id_t thread;
task_id_t parent_task; task_id_t parent_task;
task_priorities_t priority; task_priorities_t priority;
unsigned int queue_size; unsigned int queue_size;
/* Printable name */ /* Printable name */
const char * const name; const char * const name;
} task_info_t; } task_info_t;
/** \brief Update the itti LTE time reference for messages /** \brief Update the itti LTE time reference for messages
@@ -205,8 +205,8 @@ const char *itti_get_task_name(task_id_t task_id);
* @returns NULL in case of failure or newly allocated mesage ref * @returns NULL in case of failure or newly allocated mesage ref
**/ **/
MessageDef *itti_alloc_new_message( MessageDef *itti_alloc_new_message(
task_id_t origin_task_id, task_id_t origin_task_id,
MessagesIds message_id); MessagesIds message_id);
/** \brief Alloc and memset(0) a new itti message. /** \brief Alloc and memset(0) a new itti message.
* \param origin_task_id Task ID of the sending task * \param origin_task_id Task ID of the sending task
@@ -215,9 +215,9 @@ MessageDef *itti_alloc_new_message(
* @returns NULL in case of failure or newly allocated mesage ref * @returns NULL in case of failure or newly allocated mesage ref
**/ **/
MessageDef *itti_alloc_new_message_sized( MessageDef *itti_alloc_new_message_sized(
task_id_t origin_task_id, task_id_t origin_task_id,
MessagesIds message_id, MessagesIds message_id,
MessageHeaderSize size); MessageHeaderSize size);
/** \brief handle signals and wait for all threads to join when the process complete. /** \brief handle signals and wait for all threads to join when the process complete.
* This function should be called from the main thread after having created all ITTI tasks. * This function should be called from the main thread after having created all ITTI tasks.
File diff suppressed because it is too large Load Diff
+4 -4
View File
@@ -1,5 +1,5 @@
/******************************************************************************* /*******************************************************************************
OpenAirInterface OpenAirInterface
Copyright(c) 1999 - 2014 Eurecom Copyright(c) 1999 - 2014 Eurecom
OpenAirInterface is free software: you can redistribute it and/or modify OpenAirInterface is free software: you can redistribute it and/or modify
@@ -14,15 +14,15 @@
GNU General Public License for more details. GNU General Public License for more details.
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with OpenAirInterface.The full GNU General Public License is along with OpenAirInterface.The full GNU General Public License is
included in this distribution in the file called "COPYING". If not, included in this distribution in the file called "COPYING". If not,
see <http://www.gnu.org/licenses/>. see <http://www.gnu.org/licenses/>.
Contact Information Contact Information
OpenAirInterface Admin: openair_admin@eurecom.fr OpenAirInterface Admin: openair_admin@eurecom.fr
OpenAirInterface Tech : openair_tech@eurecom.fr OpenAirInterface Tech : openair_tech@eurecom.fr
OpenAirInterface Dev : openair4g-devel@eurecom.fr OpenAirInterface Dev : openair4g-devel@eurecom.fr
Address : Eurecom, Campus SophiaTech, 450 Route des Chappes, CS 50193 - 06904 Biot Sophia Antipolis cedex, FRANCE Address : Eurecom, Campus SophiaTech, 450 Route des Chappes, CS 50193 - 06904 Biot Sophia Antipolis cedex, FRANCE
*******************************************************************************/ *******************************************************************************/
+5 -5
View File
@@ -1,5 +1,5 @@
/******************************************************************************* /*******************************************************************************
OpenAirInterface OpenAirInterface
Copyright(c) 1999 - 2014 Eurecom Copyright(c) 1999 - 2014 Eurecom
OpenAirInterface is free software: you can redistribute it and/or modify OpenAirInterface is free software: you can redistribute it and/or modify
@@ -14,15 +14,15 @@
GNU General Public License for more details. GNU General Public License for more details.
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with OpenAirInterface.The full GNU General Public License is along with OpenAirInterface.The full GNU General Public License is
included in this distribution in the file called "COPYING". If not, included in this distribution in the file called "COPYING". If not,
see <http://www.gnu.org/licenses/>. see <http://www.gnu.org/licenses/>.
Contact Information Contact Information
OpenAirInterface Admin: openair_admin@eurecom.fr OpenAirInterface Admin: openair_admin@eurecom.fr
OpenAirInterface Tech : openair_tech@eurecom.fr OpenAirInterface Tech : openair_tech@eurecom.fr
OpenAirInterface Dev : openair4g-devel@eurecom.fr OpenAirInterface Dev : openair4g-devel@eurecom.fr
Address : Eurecom, Campus SophiaTech, 450 Route des Chappes, CS 50193 - 06904 Biot Sophia Antipolis cedex, FRANCE Address : Eurecom, Campus SophiaTech, 450 Route des Chappes, CS 50193 - 06904 Biot Sophia Antipolis cedex, FRANCE
*******************************************************************************/ *******************************************************************************/
@@ -55,7 +55,7 @@ const char * const messages_definition_xml = {
/* Map task id to printable name. */ /* Map task id to printable name. */
const task_info_t tasks_info[] = { const task_info_t tasks_info[] = {
{0, TASK_UNKNOWN, 0, 0, "TASK_UNKNOWN"}, {0, TASK_UNKNOWN, 0, 0, "TASK_UNKNOWN"},
#define TASK_DEF(tHREADiD, pRIO, qUEUEsIZE) { tHREADiD##_THREAD, TASK_UNKNOWN, pRIO, qUEUEsIZE, #tHREADiD }, #define TASK_DEF(tHREADiD, pRIO, qUEUEsIZE) { tHREADiD##_THREAD, TASK_UNKNOWN, pRIO, qUEUEsIZE, #tHREADiD },
#define SUB_TASK_DEF(tHREADiD, sUBtASKiD, qUEUEsIZE) { sUBtASKiD##_THREAD, tHREADiD##_THREAD, 0, qUEUEsIZE, #sUBtASKiD }, #define SUB_TASK_DEF(tHREADiD, sUBtASKiD, qUEUEsIZE) { sUBtASKiD##_THREAD, tHREADiD##_THREAD, 0, qUEUEsIZE, #sUBtASKiD },
#include <tasks_def.h> #include <tasks_def.h>
+29 -37
View File
@@ -1,5 +1,5 @@
/******************************************************************************* /*******************************************************************************
OpenAirInterface OpenAirInterface
Copyright(c) 1999 - 2014 Eurecom Copyright(c) 1999 - 2014 Eurecom
OpenAirInterface is free software: you can redistribute it and/or modify OpenAirInterface is free software: you can redistribute it and/or modify
@@ -14,15 +14,15 @@
GNU General Public License for more details. GNU General Public License for more details.
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with OpenAirInterface.The full GNU General Public License is along with OpenAirInterface.The full GNU General Public License is
included in this distribution in the file called "COPYING". If not, included in this distribution in the file called "COPYING". If not,
see <http://www.gnu.org/licenses/>. see <http://www.gnu.org/licenses/>.
Contact Information Contact Information
OpenAirInterface Admin: openair_admin@eurecom.fr OpenAirInterface Admin: openair_admin@eurecom.fr
OpenAirInterface Tech : openair_tech@eurecom.fr OpenAirInterface Tech : openair_tech@eurecom.fr
OpenAirInterface Dev : openair4g-devel@eurecom.fr OpenAirInterface Dev : openair4g-devel@eurecom.fr
Address : Eurecom, Campus SophiaTech, 450 Route des Chappes, CS 50193 - 06904 Biot Sophia Antipolis cedex, FRANCE Address : Eurecom, Campus SophiaTech, 450 Route des Chappes, CS 50193 - 06904 Biot Sophia Antipolis cedex, FRANCE
*******************************************************************************/ *******************************************************************************/
@@ -63,19 +63,17 @@
#include <messages_types.h> #include <messages_types.h>
/* This enum defines messages ids. Each one is unique. */ /* This enum defines messages ids. Each one is unique. */
typedef enum typedef enum {
{
#define MESSAGE_DEF(iD, pRIO, sTRUCT, fIELDnAME) iD, #define MESSAGE_DEF(iD, pRIO, sTRUCT, fIELDnAME) iD,
#include <messages_def.h> #include <messages_def.h>
#undef MESSAGE_DEF #undef MESSAGE_DEF
MESSAGES_ID_MAX, MESSAGES_ID_MAX,
} MessagesIds; } MessagesIds;
//! Thread id of each task //! Thread id of each task
typedef enum typedef enum {
{ THREAD_NULL = 0,
THREAD_NULL = 0,
#define TASK_DEF(tHREADiD, pRIO, qUEUEsIZE) THREAD_##tHREADiD, #define TASK_DEF(tHREADiD, pRIO, qUEUEsIZE) THREAD_##tHREADiD,
#define SUB_TASK_DEF(tHREADiD, sUBtASKiD, qUEUEsIZE) #define SUB_TASK_DEF(tHREADiD, sUBtASKiD, qUEUEsIZE)
@@ -83,13 +81,12 @@ typedef enum
#undef SUB_TASK_DEF #undef SUB_TASK_DEF
#undef TASK_DEF #undef TASK_DEF
THREAD_MAX, THREAD_MAX,
THREAD_FIRST = 1, THREAD_FIRST = 1,
} thread_id_t; } thread_id_t;
//! Sub-tasks id, to defined offset form thread id //! Sub-tasks id, to defined offset form thread id
typedef enum typedef enum {
{
#define TASK_DEF(tHREADiD, pRIO, qUEUEsIZE) tHREADiD##_THREAD = THREAD_##tHREADiD, #define TASK_DEF(tHREADiD, pRIO, qUEUEsIZE) tHREADiD##_THREAD = THREAD_##tHREADiD,
#define SUB_TASK_DEF(tHREADiD, sUBtASKiD, qUEUEsIZE) sUBtASKiD##_THREAD = THREAD_##tHREADiD, #define SUB_TASK_DEF(tHREADiD, sUBtASKiD, qUEUEsIZE) sUBtASKiD##_THREAD = THREAD_##tHREADiD,
#include <tasks_def.h> #include <tasks_def.h>
@@ -98,9 +95,8 @@ typedef enum
} task_thread_id_t; } task_thread_id_t;
//! Tasks id of each task //! Tasks id of each task
typedef enum typedef enum {
{ TASK_UNKNOWN = 0,
TASK_UNKNOWN = 0,
#define TASK_DEF(tHREADiD, pRIO, qUEUEsIZE) tHREADiD, #define TASK_DEF(tHREADiD, pRIO, qUEUEsIZE) tHREADiD,
#define SUB_TASK_DEF(tHREADiD, sUBtASKiD, qUEUEsIZE) sUBtASKiD, #define SUB_TASK_DEF(tHREADiD, sUBtASKiD, qUEUEsIZE) sUBtASKiD,
@@ -108,12 +104,11 @@ typedef enum
#undef SUB_TASK_DEF #undef SUB_TASK_DEF
#undef TASK_DEF #undef TASK_DEF
TASK_MAX, TASK_MAX,
TASK_FIRST = 1, TASK_FIRST = 1,
} task_id_t; } task_id_t;
typedef union msg_s typedef union msg_s {
{
#define MESSAGE_DEF(iD, pRIO, sTRUCT, fIELDnAME) sTRUCT fIELDnAME; #define MESSAGE_DEF(iD, pRIO, sTRUCT, fIELDnAME) sTRUCT fIELDnAME;
#include <messages_def.h> #include <messages_def.h>
#undef MESSAGE_DEF #undef MESSAGE_DEF
@@ -121,26 +116,24 @@ typedef union msg_s
typedef uint16_t MessageHeaderSize; typedef uint16_t MessageHeaderSize;
typedef struct itti_lte_time_s typedef struct itti_lte_time_s {
{ uint32_t frame;
uint32_t frame; uint8_t slot;
uint8_t slot;
} itti_lte_time_t; } itti_lte_time_t;
/** @struct MessageHeader /** @struct MessageHeader
* @brief Message Header structure for inter-task communication. * @brief Message Header structure for inter-task communication.
*/ */
typedef struct MessageHeader_s typedef struct MessageHeader_s {
{ MessagesIds messageId; /**< Unique message id as referenced in enum MessagesIds */
MessagesIds messageId; /**< Unique message id as referenced in enum MessagesIds */
task_id_t originTaskId; /**< ID of the sender task */ task_id_t originTaskId; /**< ID of the sender task */
task_id_t destinationTaskId; /**< ID of the destination task */ task_id_t destinationTaskId; /**< ID of the destination task */
instance_t instance; /**< Task instance for virtualization */ instance_t instance; /**< Task instance for virtualization */
MessageHeaderSize ittiMsgSize; /**< Message size (not including header size) */ MessageHeaderSize ittiMsgSize; /**< Message size (not including header size) */
itti_lte_time_t lte_time; /**< Reference LTE time */ itti_lte_time_t lte_time; /**< Reference LTE time */
} MessageHeader; } MessageHeader;
/** @struct MessageDef /** @struct MessageDef
@@ -148,10 +141,9 @@ typedef struct MessageHeader_s
* \internal * \internal
* The attached attribute \c __packed__ is neccessary, because the memory allocation code expects \ref ittiMsg directly following \ref ittiMsgHeader. * The attached attribute \c __packed__ is neccessary, because the memory allocation code expects \ref ittiMsg directly following \ref ittiMsgHeader.
*/ */
typedef struct __attribute__ ((__packed__)) MessageDef_s typedef struct __attribute__ ((__packed__)) MessageDef_s {
{ MessageHeader ittiMsgHeader; /**< Message header */
MessageHeader ittiMsgHeader; /**< Message header */ msg_t ittiMsg; /**< Union of payloads as defined in x_messages_def.h headers */
msg_t ittiMsg; /**< Union of payloads as defined in x_messages_def.h headers */
} MessageDef; } MessageDef;
#endif /* INTERTASK_INTERFACE_TYPES_H_ */ #endif /* INTERTASK_INTERFACE_TYPES_H_ */
+4 -4
View File
@@ -1,5 +1,5 @@
/******************************************************************************* /*******************************************************************************
OpenAirInterface OpenAirInterface
Copyright(c) 1999 - 2014 Eurecom Copyright(c) 1999 - 2014 Eurecom
OpenAirInterface is free software: you can redistribute it and/or modify OpenAirInterface is free software: you can redistribute it and/or modify
@@ -14,15 +14,15 @@
GNU General Public License for more details. GNU General Public License for more details.
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with OpenAirInterface.The full GNU General Public License is along with OpenAirInterface.The full GNU General Public License is
included in this distribution in the file called "COPYING". If not, included in this distribution in the file called "COPYING". If not,
see <http://www.gnu.org/licenses/>. see <http://www.gnu.org/licenses/>.
Contact Information Contact Information
OpenAirInterface Admin: openair_admin@eurecom.fr OpenAirInterface Admin: openair_admin@eurecom.fr
OpenAirInterface Tech : openair_tech@eurecom.fr OpenAirInterface Tech : openair_tech@eurecom.fr
OpenAirInterface Dev : openair4g-devel@eurecom.fr OpenAirInterface Dev : openair4g-devel@eurecom.fr
Address : Eurecom, Campus SophiaTech, 450 Route des Chappes, CS 50193 - 06904 Biot Sophia Antipolis cedex, FRANCE Address : Eurecom, Campus SophiaTech, 450 Route des Chappes, CS 50193 - 06904 Biot Sophia Antipolis cedex, FRANCE
*******************************************************************************/ *******************************************************************************/
+8 -10
View File
@@ -1,5 +1,5 @@
/******************************************************************************* /*******************************************************************************
OpenAirInterface OpenAirInterface
Copyright(c) 1999 - 2014 Eurecom Copyright(c) 1999 - 2014 Eurecom
OpenAirInterface is free software: you can redistribute it and/or modify OpenAirInterface is free software: you can redistribute it and/or modify
@@ -14,15 +14,15 @@
GNU General Public License for more details. GNU General Public License for more details.
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with OpenAirInterface.The full GNU General Public License is along with OpenAirInterface.The full GNU General Public License is
included in this distribution in the file called "COPYING". If not, included in this distribution in the file called "COPYING". If not,
see <http://www.gnu.org/licenses/>. see <http://www.gnu.org/licenses/>.
Contact Information Contact Information
OpenAirInterface Admin: openair_admin@eurecom.fr OpenAirInterface Admin: openair_admin@eurecom.fr
OpenAirInterface Tech : openair_tech@eurecom.fr OpenAirInterface Tech : openair_tech@eurecom.fr
OpenAirInterface Dev : openair4g-devel@eurecom.fr OpenAirInterface Dev : openair4g-devel@eurecom.fr
Address : Eurecom, Campus SophiaTech, 450 Route des Chappes, CS 50193 - 06904 Biot Sophia Antipolis cedex, FRANCE Address : Eurecom, Campus SophiaTech, 450 Route des Chappes, CS 50193 - 06904 Biot Sophia Antipolis cedex, FRANCE
*******************************************************************************/ *******************************************************************************/
@@ -38,14 +38,12 @@
#ifndef INTERTASK_MESSAGES_TYPES_H_ #ifndef INTERTASK_MESSAGES_TYPES_H_
#define INTERTASK_MESSAGES_TYPES_H_ #define INTERTASK_MESSAGES_TYPES_H_
typedef struct IttiMsgEmpty_s typedef struct IttiMsgEmpty_s {
{
} IttiMsgEmpty; } IttiMsgEmpty;
typedef struct IttiMsgText_s typedef struct IttiMsgText_s {
{ uint32_t size;
uint32_t size; char text[];
char text[];
} IttiMsgText; } IttiMsgText;
#endif /* INTERTASK_MESSAGES_TYPES_H_ */ #endif /* INTERTASK_MESSAGES_TYPES_H_ */
+17 -18
View File
@@ -1,5 +1,5 @@
/******************************************************************************* /*******************************************************************************
OpenAirInterface OpenAirInterface
Copyright(c) 1999 - 2014 Eurecom Copyright(c) 1999 - 2014 Eurecom
OpenAirInterface is free software: you can redistribute it and/or modify OpenAirInterface is free software: you can redistribute it and/or modify
@@ -14,15 +14,15 @@
GNU General Public License for more details. GNU General Public License for more details.
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with OpenAirInterface.The full GNU General Public License is along with OpenAirInterface.The full GNU General Public License is
included in this distribution in the file called "COPYING". If not, included in this distribution in the file called "COPYING". If not,
see <http://www.gnu.org/licenses/>. see <http://www.gnu.org/licenses/>.
Contact Information Contact Information
OpenAirInterface Admin: openair_admin@eurecom.fr OpenAirInterface Admin: openair_admin@eurecom.fr
OpenAirInterface Tech : openair_tech@eurecom.fr OpenAirInterface Tech : openair_tech@eurecom.fr
OpenAirInterface Dev : openair4g-devel@eurecom.fr OpenAirInterface Dev : openair4g-devel@eurecom.fr
Address : Eurecom, Campus SophiaTech, 450 Route des Chappes, CS 50193 - 06904 Biot Sophia Antipolis cedex, FRANCE Address : Eurecom, Campus SophiaTech, 450 Route des Chappes, CS 50193 - 06904 Biot Sophia Antipolis cedex, FRANCE
*******************************************************************************/ *******************************************************************************/
@@ -42,19 +42,18 @@
#define MESSAGE_NUMBER_CHAR_FORMAT "%11u" #define MESSAGE_NUMBER_CHAR_FORMAT "%11u"
/* Intertask message types */ /* Intertask message types */
enum itti_message_types_e enum itti_message_types_e {
{ ITTI_DUMP_XML_DEFINITION = CHARS_TO_UINT32 ('\n', 'I', 'x', 'd'),
ITTI_DUMP_XML_DEFINITION = CHARS_TO_UINT32 ('\n', 'I', 'x', 'd'), ITTI_DUMP_XML_DEFINITION_END = CHARS_TO_UINT32 ('i', 'X', 'D', '\n'),
ITTI_DUMP_XML_DEFINITION_END = CHARS_TO_UINT32 ('i', 'X', 'D', '\n'),
ITTI_DUMP_MESSAGE_TYPE = CHARS_TO_UINT32 ('\n', 'I', 'm', 's'), ITTI_DUMP_MESSAGE_TYPE = CHARS_TO_UINT32 ('\n', 'I', 'm', 's'),
ITTI_DUMP_MESSAGE_TYPE_END = CHARS_TO_UINT32 ('i', 'M', 'S', '\n'), ITTI_DUMP_MESSAGE_TYPE_END = CHARS_TO_UINT32 ('i', 'M', 'S', '\n'),
ITTI_STATISTIC_MESSAGE_TYPE = CHARS_TO_UINT32 ('\n', 'I', 's', 't'), ITTI_STATISTIC_MESSAGE_TYPE = CHARS_TO_UINT32 ('\n', 'I', 's', 't'),
ITTI_STATISTIC_MESSAGE_TYPE_END = CHARS_TO_UINT32 ('i', 'S', 'T', '\n'), ITTI_STATISTIC_MESSAGE_TYPE_END = CHARS_TO_UINT32 ('i', 'S', 'T', '\n'),
/* This signal is not meant to be used by remote analyzer */ /* This signal is not meant to be used by remote analyzer */
ITTI_DUMP_EXIT_SIGNAL = CHARS_TO_UINT32 ('e', 'X', 'I', 'T'), ITTI_DUMP_EXIT_SIGNAL = CHARS_TO_UINT32 ('e', 'X', 'I', 'T'),
}; };
typedef uint32_t itti_message_types_t; typedef uint32_t itti_message_types_t;
@@ -63,13 +62,13 @@ typedef uint32_t itti_message_types_t;
* remote process and this one. * remote process and this one.
*/ */
typedef struct { typedef struct {
/* The size of this structure */ /* The size of this structure */
uint32_t message_size; uint32_t message_size;
itti_message_types_t message_type; itti_message_types_t message_type;
} itti_socket_header_t; } itti_socket_header_t;
typedef struct { typedef struct {
char message_number_char[12]; /* 9 chars are needed to store an unsigned 32 bits value in decimal, but must be a multiple of 32 bits to avoid alignment issues */ char message_number_char[12]; /* 9 chars are needed to store an unsigned 32 bits value in decimal, but must be a multiple of 32 bits to avoid alignment issues */
} itti_signal_header_t; } itti_signal_header_t;
+345 -360
View File
@@ -1,5 +1,5 @@
/******************************************************************************* /*******************************************************************************
OpenAirInterface OpenAirInterface
Copyright(c) 1999 - 2014 Eurecom Copyright(c) 1999 - 2014 Eurecom
OpenAirInterface is free software: you can redistribute it and/or modify OpenAirInterface is free software: you can redistribute it and/or modify
@@ -14,15 +14,15 @@
GNU General Public License for more details. GNU General Public License for more details.
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with OpenAirInterface.The full GNU General Public License is along with OpenAirInterface.The full GNU General Public License is
included in this distribution in the file called "COPYING". If not, included in this distribution in the file called "COPYING". If not,
see <http://www.gnu.org/licenses/>. see <http://www.gnu.org/licenses/>.
Contact Information Contact Information
OpenAirInterface Admin: openair_admin@eurecom.fr OpenAirInterface Admin: openair_admin@eurecom.fr
OpenAirInterface Tech : openair_tech@eurecom.fr OpenAirInterface Tech : openair_tech@eurecom.fr
OpenAirInterface Dev : openair4g-devel@eurecom.fr OpenAirInterface Dev : openair4g-devel@eurecom.fr
Address : Eurecom, Campus SophiaTech, 450 Route des Chappes, CS 50193 - 06904 Biot Sophia Antipolis cedex, FRANCE Address : Eurecom, Campus SophiaTech, 450 Route des Chappes, CS 50193 - 06904 Biot Sophia Antipolis cedex, FRANCE
*******************************************************************************/ *******************************************************************************/
@@ -63,18 +63,18 @@ typedef int32_t items_group_position_t;
typedef int32_t items_group_index_t; typedef int32_t items_group_index_t;
typedef union items_group_positions_u { typedef union items_group_positions_u {
uint64_t all; uint64_t all;
struct { struct {
items_group_position_t put; items_group_position_t put;
items_group_position_t get; items_group_position_t get;
} ind; } ind;
} items_group_positions_t; } items_group_positions_t;
typedef struct items_group_s { typedef struct items_group_s {
items_group_position_t number_plus_one; items_group_position_t number_plus_one;
volatile uint32_t minimum; volatile uint32_t minimum;
volatile items_group_positions_t positions; volatile items_group_positions_t positions;
volatile items_group_index_t *indexes; volatile items_group_index_t *indexes;
} items_group_t; } items_group_t;
/*------------------------------------------------------------------------------*/ /*------------------------------------------------------------------------------*/
@@ -95,40 +95,40 @@ typedef uint8_t pool_id_t;
typedef uint8_t item_status_t; typedef uint8_t item_status_t;
typedef struct memory_pool_item_start_s { typedef struct memory_pool_item_start_s {
pool_item_start_mark_t start_mark; pool_item_start_mark_t start_mark;
pool_id_t pool_id; pool_id_t pool_id;
item_status_t item_status; item_status_t item_status;
uint16_t info[MEMORY_POOL_ITEM_INFO_NUMBER]; uint16_t info[MEMORY_POOL_ITEM_INFO_NUMBER];
} memory_pool_item_start_t; } memory_pool_item_start_t;
typedef struct memory_pool_item_end_s { typedef struct memory_pool_item_end_s {
pool_item_end_mark_t end_mark; pool_item_end_mark_t end_mark;
} memory_pool_item_end_t; } memory_pool_item_end_t;
typedef struct memory_pool_item_s { typedef struct memory_pool_item_s {
memory_pool_item_start_t start; memory_pool_item_start_t start;
memory_pool_data_t data[0]; memory_pool_data_t data[0];
memory_pool_item_end_t end; memory_pool_item_end_t end;
} memory_pool_item_t; } memory_pool_item_t;
typedef struct memory_pool_s { typedef struct memory_pool_s {
pool_start_mark_t start_mark; pool_start_mark_t start_mark;
pool_id_t pool_id; pool_id_t pool_id;
uint32_t item_data_number; uint32_t item_data_number;
uint32_t pool_item_size; uint32_t pool_item_size;
items_group_t items_group_free; items_group_t items_group_free;
memory_pool_item_t *items; memory_pool_item_t *items;
} memory_pool_t; } memory_pool_t;
typedef struct memory_pools_s { typedef struct memory_pools_s {
pools_start_mark_t start_mark; pools_start_mark_t start_mark;
uint32_t pools_number; uint32_t pools_number;
uint32_t pools_defined; uint32_t pools_defined;
memory_pool_t *pools; memory_pool_t *pools;
} memory_pools_t; } memory_pools_t;
/*------------------------------------------------------------------------------*/ /*------------------------------------------------------------------------------*/
@@ -149,370 +149,421 @@ static const pools_start_mark_t POOLS_START_MARK = CHARS_TO_UINT32 ('P'
/*------------------------------------------------------------------------------*/ /*------------------------------------------------------------------------------*/
static inline uint32_t items_group_number_items (items_group_t *items_group) static inline uint32_t items_group_number_items (items_group_t *items_group)
{ {
return items_group->number_plus_one - 1; return items_group->number_plus_one - 1;
} }
static inline uint32_t items_group_free_items (items_group_t *items_group) static inline uint32_t items_group_free_items (items_group_t *items_group)
{ {
items_group_positions_t positions; items_group_positions_t positions;
uint32_t free_items; uint32_t free_items;
positions.all = items_group->positions.all; positions.all = items_group->positions.all;
free_items = items_group->number_plus_one + positions.ind.put - positions.ind.get; free_items = items_group->number_plus_one + positions.ind.put - positions.ind.get;
free_items %= items_group->number_plus_one; free_items %= items_group->number_plus_one;
return free_items; return free_items;
} }
static inline items_group_index_t items_group_get_free_item (items_group_t *items_group) static inline items_group_index_t items_group_get_free_item (items_group_t *items_group)
{ {
items_group_position_t get_raw; items_group_position_t get_raw;
items_group_position_t put; items_group_position_t put;
items_group_position_t get; items_group_position_t get;
items_group_position_t free_items; items_group_position_t free_items;
items_group_index_t index = ITEMS_GROUP_INDEX_INVALID; items_group_index_t index = ITEMS_GROUP_INDEX_INVALID;
/* Get current put position */ /* Get current put position */
put = items_group->positions.ind.put % items_group->number_plus_one; put = items_group->positions.ind.put % items_group->number_plus_one;
/* Get current get position and increase it */ /* Get current get position and increase it */
get_raw = __sync_fetch_and_add (&items_group->positions.ind.get, 1); get_raw = __sync_fetch_and_add (&items_group->positions.ind.get, 1);
get = get_raw % items_group->number_plus_one; get = get_raw % items_group->number_plus_one;
if(put == get)
{ if(put == get) {
/* No more item free, restore previous position */ /* No more item free, restore previous position */
__sync_fetch_and_sub (&items_group->positions.ind.get, 1); __sync_fetch_and_sub (&items_group->positions.ind.get, 1);
} else {
/* Get index at current get position */
index = items_group->indexes[get];
if (index <= ITEMS_GROUP_INDEX_INVALID) {
/* Index has not yet been completely freed, restore previous get position */
__sync_fetch_and_sub (&items_group->positions.ind.get, 1);
} else {
if (get_raw == items_group->number_plus_one) {
/* Wrap get position */
__sync_fetch_and_sub (&items_group->positions.ind.get, items_group->number_plus_one);
}
free_items = items_group_free_items(items_group);
/* Updates minimum free items if needed */
while (items_group->minimum > free_items) {
items_group->minimum = free_items;
}
/* Clear index at current get position to indicate that item is free */
items_group->indexes[get] = ITEMS_GROUP_INDEX_INVALID;
} }
else }
{
/* Get index at current get position */
index = items_group->indexes[get];
if (index <= ITEMS_GROUP_INDEX_INVALID)
{
/* Index has not yet been completely freed, restore previous get position */
__sync_fetch_and_sub (&items_group->positions.ind.get, 1);
}
else
{
if (get_raw == items_group->number_plus_one)
{
/* Wrap get position */
__sync_fetch_and_sub (&items_group->positions.ind.get, items_group->number_plus_one);
}
free_items = items_group_free_items(items_group); return (index);
/* Updates minimum free items if needed */
while (items_group->minimum > free_items)
{
items_group->minimum = free_items;
}
/* Clear index at current get position to indicate that item is free */
items_group->indexes[get] = ITEMS_GROUP_INDEX_INVALID;
}
}
return (index);
} }
static inline int items_group_put_free_item (items_group_t *items_group, items_group_index_t index) static inline int items_group_put_free_item (items_group_t *items_group, items_group_index_t index)
{ {
items_group_position_t put_raw; items_group_position_t put_raw;
items_group_position_t put; items_group_position_t put;
/* Get current put position and increase it */ /* Get current put position and increase it */
put_raw = __sync_fetch_and_add (&items_group->positions.ind.put, 1); put_raw = __sync_fetch_and_add (&items_group->positions.ind.put, 1);
put = put_raw % items_group->number_plus_one; put = put_raw % items_group->number_plus_one;
if (put_raw == items_group->number_plus_one) if (put_raw == items_group->number_plus_one) {
{ /* Wrap position */
/* Wrap position */ __sync_fetch_and_sub (&items_group->positions.ind.put, items_group->number_plus_one);
__sync_fetch_and_sub (&items_group->positions.ind.put, items_group->number_plus_one); }
}
AssertError (items_group->indexes[put] <= ITEMS_GROUP_INDEX_INVALID, return (EXIT_FAILURE), AssertError (items_group->indexes[put] <= ITEMS_GROUP_INDEX_INVALID, return (EXIT_FAILURE),
"Index at current put position (%d) is not marked as free (%d)!\n", put, items_group->number_plus_one); "Index at current put position (%d) is not marked as free (%d)!\n", put, items_group->number_plus_one);
/* Save freed item index at current put position */ /* Save freed item index at current put position */
items_group->indexes[put] = index; items_group->indexes[put] = index;
return (EXIT_SUCCESS); return (EXIT_SUCCESS);
} }
/*------------------------------------------------------------------------------*/ /*------------------------------------------------------------------------------*/
static inline memory_pools_t *memory_pools_from_handler (memory_pools_handle_t memory_pools_handle) static inline memory_pools_t *memory_pools_from_handler (memory_pools_handle_t memory_pools_handle)
{ {
memory_pools_t *memory_pools; memory_pools_t *memory_pools;
/* Recover memory_pools */ /* Recover memory_pools */
memory_pools = (memory_pools_t *) memory_pools_handle; memory_pools = (memory_pools_t *) memory_pools_handle;
/* Sanity check on passed handle */ /* Sanity check on passed handle */
AssertError (memory_pools->start_mark == POOLS_START_MARK, memory_pools = NULL, AssertError (memory_pools->start_mark == POOLS_START_MARK, memory_pools = NULL,
"Handle %p is not a valid memory pools handle, start mark is missing!\n", memory_pools_handle); "Handle %p is not a valid memory pools handle, start mark is missing!\n", memory_pools_handle);
return (memory_pools); return (memory_pools);
} }
static inline memory_pool_item_t *memory_pool_item_from_handler (memory_pool_item_handle_t memory_pool_item_handle) static inline memory_pool_item_t *memory_pool_item_from_handler (memory_pool_item_handle_t memory_pool_item_handle)
{ {
void *address; void *address;
memory_pool_item_t *memory_pool_item; memory_pool_item_t *memory_pool_item;
/* Recover memory_pools */ /* Recover memory_pools */
address = memory_pool_item_handle - sizeof(memory_pool_item_start_t); address = memory_pool_item_handle - sizeof(memory_pool_item_start_t);
memory_pool_item = (memory_pool_item_t *) address; memory_pool_item = (memory_pool_item_t *) address;
/* Sanity check on passed handle */ /* Sanity check on passed handle */
AssertError (memory_pool_item->start.start_mark == POOL_ITEM_START_MARK, memory_pool_item = NULL, AssertError (memory_pool_item->start.start_mark == POOL_ITEM_START_MARK, memory_pool_item = NULL,
"Handle %p is not a valid memory pool item handle, start mark is missing!\n", memory_pool_item); "Handle %p is not a valid memory pool item handle, start mark is missing!\n", memory_pool_item);
return (memory_pool_item); return (memory_pool_item);
} }
static inline memory_pool_item_t *memory_pool_item_from_index (memory_pool_t *memory_pool, items_group_index_t index) static inline memory_pool_item_t *memory_pool_item_from_index (memory_pool_t *memory_pool, items_group_index_t index)
{ {
void *address; void *address;
address = (void *) memory_pool->items; address = (void *) memory_pool->items;
address += index * memory_pool->pool_item_size; address += index * memory_pool->pool_item_size;
return (address); return (address);
} }
/*------------------------------------------------------------------------------*/ /*------------------------------------------------------------------------------*/
memory_pools_handle_t memory_pools_create (uint32_t pools_number) memory_pools_handle_t memory_pools_create (uint32_t pools_number)
{ {
memory_pools_t *memory_pools; memory_pools_t *memory_pools;
pool_id_t pool; pool_id_t pool;
AssertFatal (pools_number <= MAX_POOLS_NUMBER, "Too many memory pools requested (%d/%d)!\n", pools_number, MAX_POOLS_NUMBER); /* Limit to a reasonable number of pools */ AssertFatal (pools_number <= MAX_POOLS_NUMBER, "Too many memory pools requested (%d/%d)!\n", pools_number, MAX_POOLS_NUMBER); /* Limit to a reasonable number of pools */
/* Allocate memory_pools */ /* Allocate memory_pools */
memory_pools = malloc (sizeof(memory_pools_t)); memory_pools = malloc (sizeof(memory_pools_t));
AssertFatal (memory_pools != NULL, "Memory pools structure allocation failed!\n"); AssertFatal (memory_pools != NULL, "Memory pools structure allocation failed!\n");
/* Initialize memory_pools */ /* Initialize memory_pools */
{ {
memory_pools->start_mark = POOLS_START_MARK; memory_pools->start_mark = POOLS_START_MARK;
memory_pools->pools_number = pools_number; memory_pools->pools_number = pools_number;
memory_pools->pools_defined = 0; memory_pools->pools_defined = 0;
/* Allocate pools */ /* Allocate pools */
memory_pools->pools = calloc (pools_number, sizeof(memory_pool_t)); memory_pools->pools = calloc (pools_number, sizeof(memory_pool_t));
AssertFatal (memory_pools->pools != NULL, "Memory pools allocation failed!\n"); AssertFatal (memory_pools->pools != NULL, "Memory pools allocation failed!\n");
/* Initialize pools */ /* Initialize pools */
for (pool = 0; pool < pools_number; pool++) for (pool = 0; pool < pools_number; pool++) {
{ memory_pools->pools[pool].start_mark = POOL_START_MARK;
memory_pools->pools[pool].start_mark = POOL_START_MARK;
}
} }
}
return ((memory_pools_handle_t) memory_pools); return ((memory_pools_handle_t) memory_pools);
} }
char *memory_pools_statistics(memory_pools_handle_t memory_pools_handle) char *memory_pools_statistics(memory_pools_handle_t memory_pools_handle)
{ {
memory_pools_t *memory_pools; memory_pools_t *memory_pools;
pool_id_t pool; pool_id_t pool;
char *statistics; char *statistics;
int printed_chars; int printed_chars;
uint32_t allocated_pool_memory; uint32_t allocated_pool_memory;
uint32_t allocated_pools_memory = 0; uint32_t allocated_pools_memory = 0;
items_group_t *items_group; items_group_t *items_group;
uint32_t pool_items_size; uint32_t pool_items_size;
/* Recover memory_pools */ /* Recover memory_pools */
memory_pools = memory_pools_from_handler (memory_pools_handle); memory_pools = memory_pools_from_handler (memory_pools_handle);
AssertFatal (memory_pools != NULL, "Failed to retrieve memory pool for handle %p!\n", memory_pools_handle); AssertFatal (memory_pools != NULL, "Failed to retrieve memory pool for handle %p!\n", memory_pools_handle);
statistics = malloc(memory_pools->pools_defined * 200); statistics = malloc(memory_pools->pools_defined * 200);
printed_chars = sprintf (&statistics[0], "Pool: size, number, minimum, free, address space and memory used in Kbytes\n"); printed_chars = sprintf (&statistics[0], "Pool: size, number, minimum, free, address space and memory used in Kbytes\n");
for (pool = 0; pool < memory_pools->pools_defined; pool++)
{
items_group = &memory_pools->pools[pool].items_group_free;
allocated_pool_memory = items_group_number_items (items_group) * memory_pools->pools[pool].pool_item_size;
allocated_pools_memory += allocated_pool_memory;
pool_items_size = memory_pools->pools[pool].item_data_number * sizeof(memory_pool_data_t);
printed_chars += sprintf (&statistics[printed_chars], " %2u: %6u, %6u, %6u, %6u, [%p-%p] %6u\n",
pool, pool_items_size,
items_group_number_items (items_group),
items_group->minimum,
items_group_free_items (items_group),
memory_pools->pools[pool].items,
((void *) memory_pools->pools[pool].items) + allocated_pool_memory,
allocated_pool_memory / (1024));
}
printed_chars = sprintf (&statistics[printed_chars], "Pools memory %u Kbytes\n", allocated_pools_memory / (1024));
return (statistics); for (pool = 0; pool < memory_pools->pools_defined; pool++) {
items_group = &memory_pools->pools[pool].items_group_free;
allocated_pool_memory = items_group_number_items (items_group) * memory_pools->pools[pool].pool_item_size;
allocated_pools_memory += allocated_pool_memory;
pool_items_size = memory_pools->pools[pool].item_data_number * sizeof(memory_pool_data_t);
printed_chars += sprintf (&statistics[printed_chars], " %2u: %6u, %6u, %6u, %6u, [%p-%p] %6u\n",
pool, pool_items_size,
items_group_number_items (items_group),
items_group->minimum,
items_group_free_items (items_group),
memory_pools->pools[pool].items,
((void *) memory_pools->pools[pool].items) + allocated_pool_memory,
allocated_pool_memory / (1024));
}
printed_chars = sprintf (&statistics[printed_chars], "Pools memory %u Kbytes\n", allocated_pools_memory / (1024));
return (statistics);
} }
int memory_pools_add_pool (memory_pools_handle_t memory_pools_handle, uint32_t pool_items_number, uint32_t pool_item_size) int memory_pools_add_pool (memory_pools_handle_t memory_pools_handle, uint32_t pool_items_number, uint32_t pool_item_size)
{ {
memory_pools_t *memory_pools; memory_pools_t *memory_pools;
memory_pool_t *memory_pool; memory_pool_t *memory_pool;
pool_id_t pool; pool_id_t pool;
items_group_index_t item_index; items_group_index_t item_index;
memory_pool_item_t *memory_pool_item; memory_pool_item_t *memory_pool_item;
AssertFatal (pool_items_number <= MAX_POOL_ITEMS_NUMBER, "Too many items for a memory pool (%u/%d)!\n", pool_items_number, MAX_POOL_ITEMS_NUMBER); /* Limit to a reasonable number of items */ AssertFatal (pool_items_number <= MAX_POOL_ITEMS_NUMBER, "Too many items for a memory pool (%u/%d)!\n", pool_items_number, MAX_POOL_ITEMS_NUMBER); /* Limit to a reasonable number of items */
AssertFatal (pool_item_size <= MAX_POOL_ITEM_SIZE, "Item size is too big for memory pool items (%u/%d)!\n", pool_item_size, MAX_POOL_ITEM_SIZE); /* Limit to a reasonable item size */ AssertFatal (pool_item_size <= MAX_POOL_ITEM_SIZE, "Item size is too big for memory pool items (%u/%d)!\n", pool_item_size, MAX_POOL_ITEM_SIZE); /* Limit to a reasonable item size */
/* Recover memory_pools */ /* Recover memory_pools */
memory_pools = memory_pools_from_handler (memory_pools_handle); memory_pools = memory_pools_from_handler (memory_pools_handle);
AssertFatal (memory_pools != NULL, "Failed to retrieve memory pool for handle %p!\n", memory_pools_handle); AssertFatal (memory_pools != NULL, "Failed to retrieve memory pool for handle %p!\n", memory_pools_handle);
/* Check number of already created pools */ /* Check number of already created pools */
AssertFatal (memory_pools->pools_defined < memory_pools->pools_number, "Can not allocate more memory pool (%d)!\n", memory_pools->pools_number); AssertFatal (memory_pools->pools_defined < memory_pools->pools_number, "Can not allocate more memory pool (%d)!\n", memory_pools->pools_number);
/* Select pool */ /* Select pool */
pool = memory_pools->pools_defined; pool = memory_pools->pools_defined;
memory_pool = &memory_pools->pools[pool]; memory_pool = &memory_pools->pools[pool];
/* Initialize pool */ /* Initialize pool */
{ {
memory_pool->pool_id = pool; memory_pool->pool_id = pool;
/* Item size in memory_pool_data_t items by excess */ /* Item size in memory_pool_data_t items by excess */
memory_pool->item_data_number = (pool_item_size + sizeof(memory_pool_data_t) - 1) / sizeof(memory_pool_data_t); memory_pool->item_data_number = (pool_item_size + sizeof(memory_pool_data_t) - 1) / sizeof(memory_pool_data_t);
memory_pool->pool_item_size = (memory_pool->item_data_number * sizeof(memory_pool_data_t)) + sizeof(memory_pool_item_t); memory_pool->pool_item_size = (memory_pool->item_data_number * sizeof(memory_pool_data_t)) + sizeof(memory_pool_item_t);
memory_pool->items_group_free.number_plus_one = pool_items_number + 1; memory_pool->items_group_free.number_plus_one = pool_items_number + 1;
memory_pool->items_group_free.minimum = pool_items_number; memory_pool->items_group_free.minimum = pool_items_number;
memory_pool->items_group_free.positions.ind.put = pool_items_number; memory_pool->items_group_free.positions.ind.put = pool_items_number;
memory_pool->items_group_free.positions.ind.get = 0; memory_pool->items_group_free.positions.ind.get = 0;
/* Allocate free indexes */ /* Allocate free indexes */
memory_pool->items_group_free.indexes = malloc(memory_pool->items_group_free.number_plus_one * sizeof(items_group_index_t)); memory_pool->items_group_free.indexes = malloc(memory_pool->items_group_free.number_plus_one * sizeof(items_group_index_t));
AssertFatal (memory_pool->items_group_free.indexes != NULL, "Memory pool indexes allocation failed!\n"); AssertFatal (memory_pool->items_group_free.indexes != NULL, "Memory pool indexes allocation failed!\n");
/* Initialize free indexes */ /* Initialize free indexes */
for (item_index = 0; item_index < pool_items_number; item_index++) for (item_index = 0; item_index < pool_items_number; item_index++) {
{ memory_pool->items_group_free.indexes[item_index] = item_index;
memory_pool->items_group_free.indexes[item_index] = item_index;
}
/* Last index is not allocated */
memory_pool->items_group_free.indexes[item_index] = ITEMS_GROUP_INDEX_INVALID;
/* Allocate items */
memory_pool->items = calloc (pool_items_number, memory_pool->pool_item_size);
AssertFatal (memory_pool->items != NULL, "Memory pool items allocation failed!\n");
/* Initialize items */
for (item_index = 0; item_index < pool_items_number; item_index++)
{
memory_pool_item = memory_pool_item_from_index (memory_pool, item_index);
memory_pool_item->start.start_mark = POOL_ITEM_START_MARK;
memory_pool_item->start.pool_id = pool;
memory_pool_item->start.item_status = ITEM_STATUS_FREE;
memory_pool_item->data[memory_pool->item_data_number] = POOL_ITEM_END_MARK;
}
} }
memory_pools->pools_defined ++; /* Last index is not allocated */
memory_pool->items_group_free.indexes[item_index] = ITEMS_GROUP_INDEX_INVALID;
return (0); /* Allocate items */
memory_pool->items = calloc (pool_items_number, memory_pool->pool_item_size);
AssertFatal (memory_pool->items != NULL, "Memory pool items allocation failed!\n");
/* Initialize items */
for (item_index = 0; item_index < pool_items_number; item_index++) {
memory_pool_item = memory_pool_item_from_index (memory_pool, item_index);
memory_pool_item->start.start_mark = POOL_ITEM_START_MARK;
memory_pool_item->start.pool_id = pool;
memory_pool_item->start.item_status = ITEM_STATUS_FREE;
memory_pool_item->data[memory_pool->item_data_number] = POOL_ITEM_END_MARK;
}
}
memory_pools->pools_defined ++;
return (0);
} }
memory_pool_item_handle_t memory_pools_allocate (memory_pools_handle_t memory_pools_handle, uint32_t item_size, uint16_t info_0, uint16_t info_1) memory_pool_item_handle_t memory_pools_allocate (memory_pools_handle_t memory_pools_handle, uint32_t item_size, uint16_t info_0, uint16_t info_1)
{ {
memory_pools_t *memory_pools; memory_pools_t *memory_pools;
memory_pool_item_t *memory_pool_item; memory_pool_item_t *memory_pool_item;
memory_pool_item_handle_t memory_pool_item_handle = NULL; memory_pool_item_handle_t memory_pool_item_handle = NULL;
pool_id_t pool; pool_id_t pool;
items_group_index_t item_index = ITEMS_GROUP_INDEX_INVALID; items_group_index_t item_index = ITEMS_GROUP_INDEX_INVALID;
#if defined(OAI_EMU) || defined(RTAI) #if defined(OAI_EMU) || defined(RTAI)
vcd_signal_dumper_dump_variable_by_name(VCD_SIGNAL_DUMPER_VARIABLE_MP_ALLOC, vcd_signal_dumper_dump_variable_by_name(VCD_SIGNAL_DUMPER_VARIABLE_MP_ALLOC,
__sync_or_and_fetch (&vcd_mp_alloc, 1L << info_0)); __sync_or_and_fetch (&vcd_mp_alloc, 1L << info_0));
#endif #endif
/* Recover memory_pools */ /* Recover memory_pools */
memory_pools = memory_pools_from_handler (memory_pools_handle); memory_pools = memory_pools_from_handler (memory_pools_handle);
AssertError (memory_pools != NULL, {}, "Failed to retrieve memory pool for handle %p!\n", memory_pools_handle); AssertError (memory_pools != NULL, {}, "Failed to retrieve memory pool for handle %p!\n", memory_pools_handle);
for (pool = 0; pool < memory_pools->pools_defined; pool++) for (pool = 0; pool < memory_pools->pools_defined; pool++) {
{ if ((memory_pools->pools[pool].item_data_number * sizeof(memory_pool_data_t)) < item_size) {
if ((memory_pools->pools[pool].item_data_number * sizeof(memory_pool_data_t)) < item_size) /* This memory pool has too small items, skip it */
{ continue;
/* This memory pool has too small items, skip it */
continue;
}
item_index = items_group_get_free_item(&memory_pools->pools[pool].items_group_free);
if (item_index <= ITEMS_GROUP_INDEX_INVALID)
{
/* Allocation failed, skip this pool */
continue;
}
else
{
/* Allocation succeed, exit searching loop */
break;
}
} }
if (item_index > ITEMS_GROUP_INDEX_INVALID) item_index = items_group_get_free_item(&memory_pools->pools[pool].items_group_free);
{
/* Convert item index into memory_pool_item address */
memory_pool_item = memory_pool_item_from_index (&memory_pools->pools[pool], item_index);
/* Sanity check on item status, must be free */
AssertFatal (memory_pool_item->start.item_status == ITEM_STATUS_FREE, "Item status is not set to free (%d) in pool %u, item %d!\n",
memory_pool_item->start.item_status, pool, item_index);
memory_pool_item->start.item_status = ITEM_STATUS_ALLOCATED; if (item_index <= ITEMS_GROUP_INDEX_INVALID) {
memory_pool_item->start.info[0] = info_0; /* Allocation failed, skip this pool */
memory_pool_item->start.info[1] = info_1; continue;
memory_pool_item_handle = memory_pool_item->data; } else {
/* Allocation succeed, exit searching loop */
break;
}
}
MP_DEBUG(" Alloc [%2u][%6d]{%6d}, %3u %3u, %6u, %p, %p, %p\n", if (item_index > ITEMS_GROUP_INDEX_INVALID) {
pool, item_index, /* Convert item index into memory_pool_item address */
items_group_free_items (&memory_pools->pools[pool].items_group_free), memory_pool_item = memory_pool_item_from_index (&memory_pools->pools[pool], item_index);
info_0, info_1, /* Sanity check on item status, must be free */
item_size, AssertFatal (memory_pool_item->start.item_status == ITEM_STATUS_FREE, "Item status is not set to free (%d) in pool %u, item %d!\n",
memory_pools->pools[pool].items, memory_pool_item->start.item_status, pool, item_index);
memory_pool_item,
memory_pool_item_handle); memory_pool_item->start.item_status = ITEM_STATUS_ALLOCATED;
} memory_pool_item->start.info[0] = info_0;
else memory_pool_item->start.info[1] = info_1;
{ memory_pool_item_handle = memory_pool_item->data;
MP_DEBUG(" Alloc [--][------]{------}, %3u %3u, %6u, failed!\n", info_0, info_1, item_size);
} MP_DEBUG(" Alloc [%2u][%6d]{%6d}, %3u %3u, %6u, %p, %p, %p\n",
pool, item_index,
items_group_free_items (&memory_pools->pools[pool].items_group_free),
info_0, info_1,
item_size,
memory_pools->pools[pool].items,
memory_pool_item,
memory_pool_item_handle);
} else {
MP_DEBUG(" Alloc [--][------]{------}, %3u %3u, %6u, failed!\n", info_0, info_1, item_size);
}
#if defined(OAI_EMU) || defined(RTAI) #if defined(OAI_EMU) || defined(RTAI)
vcd_signal_dumper_dump_variable_by_name(VCD_SIGNAL_DUMPER_VARIABLE_MP_ALLOC, vcd_signal_dumper_dump_variable_by_name(VCD_SIGNAL_DUMPER_VARIABLE_MP_ALLOC,
__sync_and_and_fetch (&vcd_mp_alloc, ~(1L << info_0))); __sync_and_and_fetch (&vcd_mp_alloc, ~(1L << info_0)));
#endif #endif
return memory_pool_item_handle; return memory_pool_item_handle;
} }
int memory_pools_free (memory_pools_handle_t memory_pools_handle, memory_pool_item_handle_t memory_pool_item_handle, uint16_t info_0) int memory_pools_free (memory_pools_handle_t memory_pools_handle, memory_pool_item_handle_t memory_pool_item_handle, uint16_t info_0)
{ {
memory_pools_t *memory_pools; memory_pools_t *memory_pools;
memory_pool_item_t *memory_pool_item; memory_pool_item_t *memory_pool_item;
pool_id_t pool; pool_id_t pool;
items_group_index_t item_index; items_group_index_t item_index;
uint32_t item_size; uint32_t item_size;
uint32_t pool_item_size; uint32_t pool_item_size;
uint16_t info_1; uint16_t info_1;
int result; int result;
/* Recover memory_pools */ /* Recover memory_pools */
memory_pools = memory_pools_from_handler (memory_pools_handle); memory_pools = memory_pools_from_handler (memory_pools_handle);
AssertError (memory_pools != NULL, return (EXIT_FAILURE), "Failed to retrieve memory pools for handle %p!\n", memory_pools_handle); AssertError (memory_pools != NULL, return (EXIT_FAILURE), "Failed to retrieve memory pools for handle %p!\n", memory_pools_handle);
/* Recover memory pool item */ /* Recover memory pool item */
memory_pool_item = memory_pool_item_from_handler (memory_pool_item_handle); memory_pool_item = memory_pool_item_from_handler (memory_pool_item_handle);
AssertError (memory_pool_item != NULL, return (EXIT_FAILURE), "Failed to retrieve memory pool item for handle %p!\n", memory_pool_item_handle); AssertError (memory_pool_item != NULL, return (EXIT_FAILURE), "Failed to retrieve memory pool item for handle %p!\n", memory_pool_item_handle);
info_1 = memory_pool_item->start.info[1]; info_1 = memory_pool_item->start.info[1];
#if defined(OAI_EMU) || defined(RTAI) #if defined(OAI_EMU) || defined(RTAI)
vcd_signal_dumper_dump_variable_by_name(VCD_SIGNAL_DUMPER_VARIABLE_MP_FREE, vcd_signal_dumper_dump_variable_by_name(VCD_SIGNAL_DUMPER_VARIABLE_MP_FREE,
__sync_or_and_fetch (&vcd_mp_free, 1L << info_1)); __sync_or_and_fetch (&vcd_mp_free, 1L << info_1));
#endif #endif
/* Recover pool index */
pool = memory_pool_item->start.pool_id;
AssertFatal (pool < memory_pools->pools_defined, "Pool index is invalid (%u/%u)!\n", pool, memory_pools->pools_defined);
item_size = memory_pools->pools[pool].item_data_number;
pool_item_size = memory_pools->pools[pool].pool_item_size;
item_index = (((void *) memory_pool_item) - ((void *) memory_pools->pools[pool].items)) / pool_item_size;
MP_DEBUG(" Free [%2u][%6d]{%6d}, %3u %3u, %p, %p, %p, %u\n",
pool, item_index,
items_group_free_items (&memory_pools->pools[pool].items_group_free),
memory_pool_item->start.info[0], info_1,
memory_pool_item_handle, memory_pool_item,
memory_pools->pools[pool].items, ((uint32_t) (item_size * sizeof(memory_pool_data_t))));
/* Sanity check on calculated item index */
AssertFatal (memory_pool_item == memory_pool_item_from_index(&memory_pools->pools[pool], item_index),
"Incorrect memory pool item address (%p, %p) for pool %u, item %d!\n",
memory_pool_item, memory_pool_item_from_index(&memory_pools->pools[pool], item_index), pool, item_index);
/* Sanity check on end marker, must still be present (no write overflow) */
AssertFatal (memory_pool_item->data[item_size] == POOL_ITEM_END_MARK,
"Memory pool item is corrupted, end mark is not present for pool %u, item %d!\n", pool, item_index);
/* Sanity check on item status, must be allocated */
AssertFatal (memory_pool_item->start.item_status == ITEM_STATUS_ALLOCATED,
"Trying to free a non allocated (%x) memory pool item (pool %u, item %d)!\n",
memory_pool_item->start.item_status, pool, item_index);
memory_pool_item->start.item_status = ITEM_STATUS_FREE;
result = items_group_put_free_item(&memory_pools->pools[pool].items_group_free, item_index);
AssertError (result == EXIT_SUCCESS, {}, "Failed to free memory pool item (pool %u, item %d)!\n", pool, item_index);
#if defined(OAI_EMU) || defined(RTAI)
vcd_signal_dumper_dump_variable_by_name(VCD_SIGNAL_DUMPER_VARIABLE_MP_FREE,
__sync_and_and_fetch (&vcd_mp_free, ~(1L << info_1)));
#endif
return (result);
}
void memory_pools_set_info (memory_pools_handle_t memory_pools_handle, memory_pool_item_handle_t memory_pool_item_handle, int index, uint16_t info)
{
memory_pools_t *memory_pools;
memory_pool_item_t *memory_pool_item;
pool_id_t pool;
items_group_index_t item_index;
uint32_t item_size;
uint32_t pool_item_size;
AssertFatal (index < MEMORY_POOL_ITEM_INFO_NUMBER, "Incorrect info index (%d/%d)!\n", index, MEMORY_POOL_ITEM_INFO_NUMBER);
/* Recover memory pool item */
memory_pool_item = memory_pool_item_from_handler (memory_pool_item_handle);
AssertFatal (memory_pool_item != NULL, "Failed to retrieve memory pool item for handle %p!\n", memory_pool_item_handle);
/* Set info[1] */
memory_pool_item->start.info[index] = info;
/* Check item validity and log (not mandatory) */
if (1) {
/* Recover memory_pools */
memory_pools = memory_pools_from_handler (memory_pools_handle);
AssertFatal (memory_pools != NULL, "Failed to retrieve memory pool for handle %p!\n", memory_pools_handle);
/* Recover pool index */ /* Recover pool index */
pool = memory_pool_item->start.pool_id; pool = memory_pool_item->start.pool_id;
AssertFatal (pool < memory_pools->pools_defined, "Pool index is invalid (%u/%u)!\n", pool, memory_pools->pools_defined); AssertFatal (pool < memory_pools->pools_defined, "Pool index is invalid (%u/%u)!\n", pool, memory_pools->pools_defined);
@@ -521,10 +572,10 @@ int memory_pools_free (memory_pools_handle_t memory_pools_handle, memory_pool_it
pool_item_size = memory_pools->pools[pool].pool_item_size; pool_item_size = memory_pools->pools[pool].pool_item_size;
item_index = (((void *) memory_pool_item) - ((void *) memory_pools->pools[pool].items)) / pool_item_size; item_index = (((void *) memory_pool_item) - ((void *) memory_pools->pools[pool].items)) / pool_item_size;
MP_DEBUG(" Free [%2u][%6d]{%6d}, %3u %3u, %p, %p, %p, %u\n", MP_DEBUG(" Info [%2u][%6d]{%6d}, %3u %3u, %p, %p, %p, %u\n",
pool, item_index, pool, item_index,
items_group_free_items (&memory_pools->pools[pool].items_group_free), items_group_free_items (&memory_pools->pools[pool].items_group_free),
memory_pool_item->start.info[0], info_1, memory_pool_item->start.info[0], memory_pool_item->start.info[1],
memory_pool_item_handle, memory_pool_item, memory_pool_item_handle, memory_pool_item,
memory_pools->pools[pool].items, ((uint32_t) (item_size * sizeof(memory_pool_data_t)))); memory_pools->pools[pool].items, ((uint32_t) (item_size * sizeof(memory_pool_data_t))));
@@ -537,73 +588,7 @@ int memory_pools_free (memory_pools_handle_t memory_pools_handle, memory_pool_it
"Memory pool item is corrupted, end mark is not present for pool %u, item %d!\n", pool, item_index); "Memory pool item is corrupted, end mark is not present for pool %u, item %d!\n", pool, item_index);
/* Sanity check on item status, must be allocated */ /* Sanity check on item status, must be allocated */
AssertFatal (memory_pool_item->start.item_status == ITEM_STATUS_ALLOCATED, AssertFatal (memory_pool_item->start.item_status == ITEM_STATUS_ALLOCATED,
"Trying to free a non allocated (%x) memory pool item (pool %u, item %d)!\n", "Trying to free a non allocated (%x) memory pool item (pool %u, item %d)\n",
memory_pool_item->start.item_status, pool, item_index); memory_pool_item->start.item_status, pool, item_index);
}
memory_pool_item->start.item_status = ITEM_STATUS_FREE;
result = items_group_put_free_item(&memory_pools->pools[pool].items_group_free, item_index);
AssertError (result == EXIT_SUCCESS, {}, "Failed to free memory pool item (pool %u, item %d)!\n", pool, item_index);
#if defined(OAI_EMU) || defined(RTAI)
vcd_signal_dumper_dump_variable_by_name(VCD_SIGNAL_DUMPER_VARIABLE_MP_FREE,
__sync_and_and_fetch (&vcd_mp_free, ~(1L << info_1)));
#endif
return (result);
}
void memory_pools_set_info (memory_pools_handle_t memory_pools_handle, memory_pool_item_handle_t memory_pool_item_handle, int index, uint16_t info)
{
memory_pools_t *memory_pools;
memory_pool_item_t *memory_pool_item;
pool_id_t pool;
items_group_index_t item_index;
uint32_t item_size;
uint32_t pool_item_size;
AssertFatal (index < MEMORY_POOL_ITEM_INFO_NUMBER, "Incorrect info index (%d/%d)!\n", index, MEMORY_POOL_ITEM_INFO_NUMBER);
/* Recover memory pool item */
memory_pool_item = memory_pool_item_from_handler (memory_pool_item_handle);
AssertFatal (memory_pool_item != NULL, "Failed to retrieve memory pool item for handle %p!\n", memory_pool_item_handle);
/* Set info[1] */
memory_pool_item->start.info[index] = info;
/* Check item validity and log (not mandatory) */
if (1)
{
/* Recover memory_pools */
memory_pools = memory_pools_from_handler (memory_pools_handle);
AssertFatal (memory_pools != NULL, "Failed to retrieve memory pool for handle %p!\n", memory_pools_handle);
/* Recover pool index */
pool = memory_pool_item->start.pool_id;
AssertFatal (pool < memory_pools->pools_defined, "Pool index is invalid (%u/%u)!\n", pool, memory_pools->pools_defined);
item_size = memory_pools->pools[pool].item_data_number;
pool_item_size = memory_pools->pools[pool].pool_item_size;
item_index = (((void *) memory_pool_item) - ((void *) memory_pools->pools[pool].items)) / pool_item_size;
MP_DEBUG(" Info [%2u][%6d]{%6d}, %3u %3u, %p, %p, %p, %u\n",
pool, item_index,
items_group_free_items (&memory_pools->pools[pool].items_group_free),
memory_pool_item->start.info[0], memory_pool_item->start.info[1],
memory_pool_item_handle, memory_pool_item,
memory_pools->pools[pool].items, ((uint32_t) (item_size * sizeof(memory_pool_data_t))));
/* Sanity check on calculated item index */
AssertFatal (memory_pool_item == memory_pool_item_from_index(&memory_pools->pools[pool], item_index),
"Incorrect memory pool item address (%p, %p) for pool %u, item %d!\n",
memory_pool_item, memory_pool_item_from_index(&memory_pools->pools[pool], item_index), pool, item_index);
/* Sanity check on end marker, must still be present (no write overflow) */
AssertFatal (memory_pool_item->data[item_size] == POOL_ITEM_END_MARK,
"Memory pool item is corrupted, end mark is not present for pool %u, item %d!\n", pool, item_index);
/* Sanity check on item status, must be allocated */
AssertFatal (memory_pool_item->start.item_status == ITEM_STATUS_ALLOCATED,
"Trying to free a non allocated (%x) memory pool item (pool %u, item %d)\n",
memory_pool_item->start.item_status, pool, item_index);
}
} }
+4 -4
View File
@@ -1,5 +1,5 @@
/******************************************************************************* /*******************************************************************************
OpenAirInterface OpenAirInterface
Copyright(c) 1999 - 2014 Eurecom Copyright(c) 1999 - 2014 Eurecom
OpenAirInterface is free software: you can redistribute it and/or modify OpenAirInterface is free software: you can redistribute it and/or modify
@@ -14,15 +14,15 @@
GNU General Public License for more details. GNU General Public License for more details.
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with OpenAirInterface.The full GNU General Public License is along with OpenAirInterface.The full GNU General Public License is
included in this distribution in the file called "COPYING". If not, included in this distribution in the file called "COPYING". If not,
see <http://www.gnu.org/licenses/>. see <http://www.gnu.org/licenses/>.
Contact Information Contact Information
OpenAirInterface Admin: openair_admin@eurecom.fr OpenAirInterface Admin: openair_admin@eurecom.fr
OpenAirInterface Tech : openair_tech@eurecom.fr OpenAirInterface Tech : openair_tech@eurecom.fr
OpenAirInterface Dev : openair4g-devel@eurecom.fr OpenAirInterface Dev : openair4g-devel@eurecom.fr
Address : Eurecom, Campus SophiaTech, 450 Route des Chappes, CS 50193 - 06904 Biot Sophia Antipolis cedex, FRANCE Address : Eurecom, Campus SophiaTech, 450 Route des Chappes, CS 50193 - 06904 Biot Sophia Antipolis cedex, FRANCE
*******************************************************************************/ *******************************************************************************/
+4 -4
View File
@@ -1,5 +1,5 @@
/******************************************************************************* /*******************************************************************************
OpenAirInterface OpenAirInterface
Copyright(c) 1999 - 2014 Eurecom Copyright(c) 1999 - 2014 Eurecom
OpenAirInterface is free software: you can redistribute it and/or modify OpenAirInterface is free software: you can redistribute it and/or modify
@@ -14,15 +14,15 @@
GNU General Public License for more details. GNU General Public License for more details.
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with OpenAirInterface.The full GNU General Public License is along with OpenAirInterface.The full GNU General Public License is
included in this distribution in the file called "COPYING". If not, included in this distribution in the file called "COPYING". If not,
see <http://www.gnu.org/licenses/>. see <http://www.gnu.org/licenses/>.
Contact Information Contact Information
OpenAirInterface Admin: openair_admin@eurecom.fr OpenAirInterface Admin: openair_admin@eurecom.fr
OpenAirInterface Tech : openair_tech@eurecom.fr OpenAirInterface Tech : openair_tech@eurecom.fr
OpenAirInterface Dev : openair4g-devel@eurecom.fr OpenAirInterface Dev : openair4g-devel@eurecom.fr
Address : Eurecom, Campus SophiaTech, 450 Route des Chappes, CS 50193 - 06904 Biot Sophia Antipolis cedex, FRANCE Address : Eurecom, Campus SophiaTech, 450 Route des Chappes, CS 50193 - 06904 Biot Sophia Antipolis cedex, FRANCE
*******************************************************************************/ *******************************************************************************/
+4 -4
View File
@@ -1,5 +1,5 @@
/******************************************************************************* /*******************************************************************************
OpenAirInterface OpenAirInterface
Copyright(c) 1999 - 2014 Eurecom Copyright(c) 1999 - 2014 Eurecom
OpenAirInterface is free software: you can redistribute it and/or modify OpenAirInterface is free software: you can redistribute it and/or modify
@@ -14,15 +14,15 @@
GNU General Public License for more details. GNU General Public License for more details.
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with OpenAirInterface.The full GNU General Public License is along with OpenAirInterface.The full GNU General Public License is
included in this distribution in the file called "COPYING". If not, included in this distribution in the file called "COPYING". If not,
see <http://www.gnu.org/licenses/>. see <http://www.gnu.org/licenses/>.
Contact Information Contact Information
OpenAirInterface Admin: openair_admin@eurecom.fr OpenAirInterface Admin: openair_admin@eurecom.fr
OpenAirInterface Tech : openair_tech@eurecom.fr OpenAirInterface Tech : openair_tech@eurecom.fr
OpenAirInterface Dev : openair4g-devel@eurecom.fr OpenAirInterface Dev : openair4g-devel@eurecom.fr
Address : Eurecom, Campus SophiaTech, 450 Route des Chappes, CS 50193 - 06904 Biot Sophia Antipolis cedex, FRANCE Address : Eurecom, Campus SophiaTech, 450 Route des Chappes, CS 50193 - 06904 Biot Sophia Antipolis cedex, FRANCE
*******************************************************************************/ *******************************************************************************/
+73 -73
View File
@@ -1,5 +1,5 @@
/******************************************************************************* /*******************************************************************************
OpenAirInterface OpenAirInterface
Copyright(c) 1999 - 2014 Eurecom Copyright(c) 1999 - 2014 Eurecom
OpenAirInterface is free software: you can redistribute it and/or modify OpenAirInterface is free software: you can redistribute it and/or modify
@@ -14,15 +14,15 @@
GNU General Public License for more details. GNU General Public License for more details.
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with OpenAirInterface.The full GNU General Public License is along with OpenAirInterface.The full GNU General Public License is
included in this distribution in the file called "COPYING". If not, included in this distribution in the file called "COPYING". If not,
see <http://www.gnu.org/licenses/>. see <http://www.gnu.org/licenses/>.
Contact Information Contact Information
OpenAirInterface Admin: openair_admin@eurecom.fr OpenAirInterface Admin: openair_admin@eurecom.fr
OpenAirInterface Tech : openair_tech@eurecom.fr OpenAirInterface Tech : openair_tech@eurecom.fr
OpenAirInterface Dev : openair4g-devel@eurecom.fr OpenAirInterface Dev : openair4g-devel@eurecom.fr
Address : Eurecom, Campus SophiaTech, 450 Route des Chappes, CS 50193 - 06904 Biot Sophia Antipolis cedex, FRANCE Address : Eurecom, Campus SophiaTech, 450 Route des Chappes, CS 50193 - 06904 Biot Sophia Antipolis cedex, FRANCE
*******************************************************************************/ *******************************************************************************/
@@ -65,85 +65,85 @@ static sigset_t set;
int signal_mask(void) int signal_mask(void)
{ {
/* We set the signal mask to avoid threads other than the main thread /* We set the signal mask to avoid threads other than the main thread
* to receive the timer signal. Note that threads created will inherit this * to receive the timer signal. Note that threads created will inherit this
* configuration. * configuration.
*/ */
sigemptyset(&set); sigemptyset(&set);
sigaddset (&set, SIGTIMER); sigaddset (&set, SIGTIMER);
sigaddset (&set, SIGUSR1); sigaddset (&set, SIGUSR1);
sigaddset (&set, SIGABRT); sigaddset (&set, SIGABRT);
sigaddset (&set, SIGSEGV); sigaddset (&set, SIGSEGV);
sigaddset (&set, SIGINT); sigaddset (&set, SIGINT);
if (sigprocmask(SIG_BLOCK, &set, NULL) < 0) { if (sigprocmask(SIG_BLOCK, &set, NULL) < 0) {
perror ("sigprocmask"); perror ("sigprocmask");
return -1; return -1;
} }
return 0; return 0;
} }
int signal_handle(int *end) int signal_handle(int *end)
{ {
int ret; int ret;
siginfo_t info; siginfo_t info;
sigemptyset(&set); sigemptyset(&set);
sigaddset (&set, SIGTIMER); sigaddset (&set, SIGTIMER);
sigaddset (&set, SIGUSR1); sigaddset (&set, SIGUSR1);
sigaddset (&set, SIGABRT); sigaddset (&set, SIGABRT);
sigaddset (&set, SIGSEGV); sigaddset (&set, SIGSEGV);
sigaddset (&set, SIGINT); sigaddset (&set, SIGINT);
if (sigprocmask(SIG_BLOCK, &set, NULL) < 0) { if (sigprocmask(SIG_BLOCK, &set, NULL) < 0) {
perror ("sigprocmask"); perror ("sigprocmask");
return -1; return -1;
}
/* Block till a signal is received.
* NOTE: The signals defined by set are required to be blocked at the time
* of the call to sigwait() otherwise sigwait() is not successful.
*/
if ((ret = sigwaitinfo(&set, &info)) == -1) {
perror ("sigwait");
return ret;
}
printf("Received signal %d\n", info.si_signo);
/* Real-time signals are non constant and are therefore not suitable for
* use in switch.
*/
if (info.si_signo == SIGTIMER) {
timer_handle_signal(&info);
} else {
/* Dispatch the signal to sub-handlers */
switch(info.si_signo) {
case SIGUSR1:
SIG_DEBUG("Received SIGUSR1\n");
*end = 1;
break;
case SIGSEGV: /* Fall through */
case SIGABRT:
SIG_DEBUG("Received SIGABORT\n");
backtrace_handle_signal(&info);
break;
case SIGINT:
printf("Received SIGINT\n");
itti_send_terminate_message(TASK_UNKNOWN);
*end = 1;
break;
default:
SIG_ERROR("Received unknown signal %d\n", info.si_signo);
break;
} }
}
/* Block till a signal is received. return 0;
* NOTE: The signals defined by set are required to be blocked at the time
* of the call to sigwait() otherwise sigwait() is not successful.
*/
if ((ret = sigwaitinfo(&set, &info)) == -1) {
perror ("sigwait");
return ret;
}
printf("Received signal %d\n", info.si_signo);
/* Real-time signals are non constant and are therefore not suitable for
* use in switch.
*/
if (info.si_signo == SIGTIMER) {
timer_handle_signal(&info);
} else {
/* Dispatch the signal to sub-handlers */
switch(info.si_signo) {
case SIGUSR1:
SIG_DEBUG("Received SIGUSR1\n");
*end = 1;
break;
case SIGSEGV: /* Fall through */
case SIGABRT:
SIG_DEBUG("Received SIGABORT\n");
backtrace_handle_signal(&info);
break;
case SIGINT:
printf("Received SIGINT\n");
itti_send_terminate_message(TASK_UNKNOWN);
*end = 1;
break;
default:
SIG_ERROR("Received unknown signal %d\n", info.si_signo);
break;
}
}
return 0;
} }
+4 -4
View File
@@ -1,5 +1,5 @@
/******************************************************************************* /*******************************************************************************
OpenAirInterface OpenAirInterface
Copyright(c) 1999 - 2014 Eurecom Copyright(c) 1999 - 2014 Eurecom
OpenAirInterface is free software: you can redistribute it and/or modify OpenAirInterface is free software: you can redistribute it and/or modify
@@ -14,15 +14,15 @@
GNU General Public License for more details. GNU General Public License for more details.
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with OpenAirInterface.The full GNU General Public License is along with OpenAirInterface.The full GNU General Public License is
included in this distribution in the file called "COPYING". If not, included in this distribution in the file called "COPYING". If not,
see <http://www.gnu.org/licenses/>. see <http://www.gnu.org/licenses/>.
Contact Information Contact Information
OpenAirInterface Admin: openair_admin@eurecom.fr OpenAirInterface Admin: openair_admin@eurecom.fr
OpenAirInterface Tech : openair_tech@eurecom.fr OpenAirInterface Tech : openair_tech@eurecom.fr
OpenAirInterface Dev : openair4g-devel@eurecom.fr OpenAirInterface Dev : openair4g-devel@eurecom.fr
Address : Eurecom, Campus SophiaTech, 450 Route des Chappes, CS 50193 - 06904 Biot Sophia Antipolis cedex, FRANCE Address : Eurecom, Campus SophiaTech, 450 Route des Chappes, CS 50193 - 06904 Biot Sophia Antipolis cedex, FRANCE
*******************************************************************************/ *******************************************************************************/
+4 -4
View File
@@ -1,5 +1,5 @@
/******************************************************************************* /*******************************************************************************
OpenAirInterface OpenAirInterface
Copyright(c) 1999 - 2014 Eurecom Copyright(c) 1999 - 2014 Eurecom
OpenAirInterface is free software: you can redistribute it and/or modify OpenAirInterface is free software: you can redistribute it and/or modify
@@ -14,15 +14,15 @@
GNU General Public License for more details. GNU General Public License for more details.
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with OpenAirInterface.The full GNU General Public License is along with OpenAirInterface.The full GNU General Public License is
included in this distribution in the file called "COPYING". If not, included in this distribution in the file called "COPYING". If not,
see <http://www.gnu.org/licenses/>. see <http://www.gnu.org/licenses/>.
Contact Information Contact Information
OpenAirInterface Admin: openair_admin@eurecom.fr OpenAirInterface Admin: openair_admin@eurecom.fr
OpenAirInterface Tech : openair_tech@eurecom.fr OpenAirInterface Tech : openair_tech@eurecom.fr
OpenAirInterface Dev : openair4g-devel@eurecom.fr OpenAirInterface Dev : openair4g-devel@eurecom.fr
Address : Eurecom, Campus SophiaTech, 450 Route des Chappes, CS 50193 - 06904 Biot Sophia Antipolis cedex, FRANCE Address : Eurecom, Campus SophiaTech, 450 Route des Chappes, CS 50193 - 06904 Biot Sophia Antipolis cedex, FRANCE
*******************************************************************************/ *******************************************************************************/
+146 -140
View File
@@ -1,5 +1,5 @@
/******************************************************************************* /*******************************************************************************
OpenAirInterface OpenAirInterface
Copyright(c) 1999 - 2014 Eurecom Copyright(c) 1999 - 2014 Eurecom
OpenAirInterface is free software: you can redistribute it and/or modify OpenAirInterface is free software: you can redistribute it and/or modify
@@ -14,15 +14,15 @@
GNU General Public License for more details. GNU General Public License for more details.
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with OpenAirInterface.The full GNU General Public License is along with OpenAirInterface.The full GNU General Public License is
included in this distribution in the file called "COPYING". If not, included in this distribution in the file called "COPYING". If not,
see <http://www.gnu.org/licenses/>. see <http://www.gnu.org/licenses/>.
Contact Information Contact Information
OpenAirInterface Admin: openair_admin@eurecom.fr OpenAirInterface Admin: openair_admin@eurecom.fr
OpenAirInterface Tech : openair_tech@eurecom.fr OpenAirInterface Tech : openair_tech@eurecom.fr
OpenAirInterface Dev : openair4g-devel@eurecom.fr OpenAirInterface Dev : openair4g-devel@eurecom.fr
Address : Eurecom, Campus SophiaTech, 450 Route des Chappes, CS 50193 - 06904 Biot Sophia Antipolis cedex, FRANCE Address : Eurecom, Campus SophiaTech, 450 Route des Chappes, CS 50193 - 06904 Biot Sophia Antipolis cedex, FRANCE
*******************************************************************************/ *******************************************************************************/
@@ -58,18 +58,18 @@
int timer_handle_signal(siginfo_t *info); int timer_handle_signal(siginfo_t *info);
struct timer_elm_s { struct timer_elm_s {
task_id_t task_id; ///< Task ID which has requested the timer task_id_t task_id; ///< Task ID which has requested the timer
int32_t instance; ///< Instance of the task which has requested the timer int32_t instance; ///< Instance of the task which has requested the timer
timer_t timer; ///< Unique timer id timer_t timer; ///< Unique timer id
timer_type_t type; ///< Timer type timer_type_t type; ///< Timer type
void *timer_arg; ///< Optional argument that will be passed when timer expires void *timer_arg; ///< Optional argument that will be passed when timer expires
STAILQ_ENTRY(timer_elm_s) entries; ///< Pointer to next element STAILQ_ENTRY(timer_elm_s) entries; ///< Pointer to next element
}; };
typedef struct timer_desc_s { typedef struct timer_desc_s {
STAILQ_HEAD(timer_list_head, timer_elm_s) timer_queue; STAILQ_HEAD(timer_list_head, timer_elm_s) timer_queue;
pthread_mutex_t timer_list_mutex; pthread_mutex_t timer_list_mutex;
struct timespec timeout; struct timespec timeout;
} timer_desc_t; } timer_desc_t;
static timer_desc_t timer_desc; static timer_desc_t timer_desc;
@@ -84,169 +84,175 @@ do { \
int timer_handle_signal(siginfo_t *info) int timer_handle_signal(siginfo_t *info)
{ {
struct timer_elm_s *timer_p; struct timer_elm_s *timer_p;
MessageDef *message_p; MessageDef *message_p;
timer_has_expired_t *timer_expired_p; timer_has_expired_t *timer_expired_p;
task_id_t task_id; task_id_t task_id;
int32_t instance; int32_t instance;
/* Get back pointer to timer list element */ /* Get back pointer to timer list element */
timer_p = (struct timer_elm_s *)info->si_ptr; timer_p = (struct timer_elm_s *)info->si_ptr;
TMR_DEBUG("Timer with id 0x%lx has expired\n", (long)timer_p->timer); TMR_DEBUG("Timer with id 0x%lx has expired\n", (long)timer_p->timer);
task_id = timer_p->task_id; task_id = timer_p->task_id;
instance = timer_p->instance; instance = timer_p->instance;
message_p = itti_alloc_new_message(TASK_TIMER, TIMER_HAS_EXPIRED); message_p = itti_alloc_new_message(TASK_TIMER, TIMER_HAS_EXPIRED);
timer_expired_p = &message_p->ittiMsg.timer_has_expired; timer_expired_p = &message_p->ittiMsg.timer_has_expired;
timer_expired_p->timer_id = (long)timer_p->timer; timer_expired_p->timer_id = (long)timer_p->timer;
timer_expired_p->arg = timer_p->timer_arg; timer_expired_p->arg = timer_p->timer_arg;
/* Timer is a one shot timer, remove it */ /* Timer is a one shot timer, remove it */
if (timer_p->type == TIMER_ONE_SHOT) { if (timer_p->type == TIMER_ONE_SHOT) {
// if (timer_delete(timer_p->timer) < 0) { // if (timer_delete(timer_p->timer) < 0) {
// TMR_DEBUG("Failed to delete timer 0x%lx\n", (long)timer_p->timer); // TMR_DEBUG("Failed to delete timer 0x%lx\n", (long)timer_p->timer);
// } // }
// TMR_DEBUG("Removed timer 0x%lx\n", (long)timer_p->timer); // TMR_DEBUG("Removed timer 0x%lx\n", (long)timer_p->timer);
// pthread_mutex_lock(&timer_desc.timer_list_mutex); // pthread_mutex_lock(&timer_desc.timer_list_mutex);
// STAILQ_REMOVE(&timer_desc.timer_queue, timer_p, timer_elm_s, entries); // STAILQ_REMOVE(&timer_desc.timer_queue, timer_p, timer_elm_s, entries);
// pthread_mutex_unlock(&timer_desc.timer_list_mutex); // pthread_mutex_unlock(&timer_desc.timer_list_mutex);
// free(timer_p); // free(timer_p);
// timer_p = NULL; // timer_p = NULL;
if (timer_remove((long)timer_p->timer) != 0) { if (timer_remove((long)timer_p->timer) != 0) {
TMR_DEBUG("Failed to delete timer 0x%lx\n", (long)timer_p->timer); TMR_DEBUG("Failed to delete timer 0x%lx\n", (long)timer_p->timer);
}
}
/* Notify task of timer expiry */
if (itti_send_msg_to_task(task_id, instance, message_p) < 0) {
TMR_DEBUG("Failed to send msg TIMER_HAS_EXPIRED to task %u\n", task_id);
free(message_p);
return -1;
} }
}
return 0; /* Notify task of timer expiry */
if (itti_send_msg_to_task(task_id, instance, message_p) < 0) {
TMR_DEBUG("Failed to send msg TIMER_HAS_EXPIRED to task %u\n", task_id);
free(message_p);
return -1;
}
return 0;
} }
int timer_setup( int timer_setup(
uint32_t interval_sec, uint32_t interval_sec,
uint32_t interval_us, uint32_t interval_us,
task_id_t task_id, task_id_t task_id,
int32_t instance, int32_t instance,
timer_type_t type, timer_type_t type,
void *timer_arg, void *timer_arg,
long *timer_id) long *timer_id)
{ {
struct sigevent se; struct sigevent se;
struct itimerspec its; struct itimerspec its;
struct timer_elm_s *timer_p; struct timer_elm_s *timer_p;
timer_t timer; timer_t timer;
if (timer_id == NULL) { if (timer_id == NULL) {
return -1; return -1;
} }
AssertFatal (type < TIMER_TYPE_MAX, "Invalid timer type (%d/%d)!\n", type, TIMER_TYPE_MAX);
/* Allocate new timer list element */ AssertFatal (type < TIMER_TYPE_MAX, "Invalid timer type (%d/%d)!\n", type, TIMER_TYPE_MAX);
timer_p = malloc(sizeof(struct timer_elm_s));
if (timer_p == NULL) {
TMR_ERROR("Failed to create new timer element\n");
return -1;
}
memset(&timer, 0, sizeof(timer_t)); /* Allocate new timer list element */
memset(&se, 0, sizeof(struct sigevent)); timer_p = malloc(sizeof(struct timer_elm_s));
timer_p->task_id = task_id; if (timer_p == NULL) {
timer_p->instance = instance; TMR_ERROR("Failed to create new timer element\n");
timer_p->type = type; return -1;
timer_p->timer_arg = timer_arg; }
/* Setting up alarm */ memset(&timer, 0, sizeof(timer_t));
/* Set and enable alarm */ memset(&se, 0, sizeof(struct sigevent));
se.sigev_notify = SIGEV_SIGNAL;
se.sigev_signo = SIGTIMER;
se.sigev_value.sival_ptr = timer_p;
/* At the timer creation, the timer structure will be filled in with timer_id,
* which is unique for this process. This id is allocated by kernel and the
* value might be used to distinguish timers.
*/
if (timer_create(CLOCK_REALTIME, &se, &timer) < 0) {
TMR_ERROR("Failed to create timer: (%s:%d)\n", strerror(errno), errno);
free(timer_p);
return -1;
}
/* Fill in the first expiration value. */ timer_p->task_id = task_id;
its.it_value.tv_sec = interval_sec; timer_p->instance = instance;
its.it_value.tv_nsec = interval_us * 1000; timer_p->type = type;
timer_p->timer_arg = timer_arg;
if (type == TIMER_PERIODIC) { /* Setting up alarm */
/* Asked for periodic timer. We set the interval time */ /* Set and enable alarm */
its.it_interval.tv_sec = interval_sec; se.sigev_notify = SIGEV_SIGNAL;
its.it_interval.tv_nsec = interval_us * 1000; se.sigev_signo = SIGTIMER;
} else { se.sigev_value.sival_ptr = timer_p;
/* Asked for one-shot timer. Do not set the interval field */
its.it_interval.tv_sec = 0;
its.it_interval.tv_nsec = 0;
}
timer_settime(timer, 0, &its, NULL);
/* Simply set the timer_id argument. so it can be used by caller */
*timer_id = (long)timer;
TMR_DEBUG("Requesting new %s timer with id 0x%lx that expires within "
"%d sec and %d usec\n",
type == TIMER_PERIODIC ? "periodic" : "single shot",
*timer_id, interval_sec, interval_us);
timer_p->timer = timer; /* At the timer creation, the timer structure will be filled in with timer_id,
* which is unique for this process. This id is allocated by kernel and the
* value might be used to distinguish timers.
*/
if (timer_create(CLOCK_REALTIME, &se, &timer) < 0) {
TMR_ERROR("Failed to create timer: (%s:%d)\n", strerror(errno), errno);
free(timer_p);
return -1;
}
/* Lock the queue and insert the timer at the tail */ /* Fill in the first expiration value. */
pthread_mutex_lock(&timer_desc.timer_list_mutex); its.it_value.tv_sec = interval_sec;
STAILQ_INSERT_TAIL(&timer_desc.timer_queue, timer_p, entries); its.it_value.tv_nsec = interval_us * 1000;
pthread_mutex_unlock(&timer_desc.timer_list_mutex);
return 0; if (type == TIMER_PERIODIC) {
/* Asked for periodic timer. We set the interval time */
its.it_interval.tv_sec = interval_sec;
its.it_interval.tv_nsec = interval_us * 1000;
} else {
/* Asked for one-shot timer. Do not set the interval field */
its.it_interval.tv_sec = 0;
its.it_interval.tv_nsec = 0;
}
timer_settime(timer, 0, &its, NULL);
/* Simply set the timer_id argument. so it can be used by caller */
*timer_id = (long)timer;
TMR_DEBUG("Requesting new %s timer with id 0x%lx that expires within "
"%d sec and %d usec\n",
type == TIMER_PERIODIC ? "periodic" : "single shot",
*timer_id, interval_sec, interval_us);
timer_p->timer = timer;
/* Lock the queue and insert the timer at the tail */
pthread_mutex_lock(&timer_desc.timer_list_mutex);
STAILQ_INSERT_TAIL(&timer_desc.timer_queue, timer_p, entries);
pthread_mutex_unlock(&timer_desc.timer_list_mutex);
return 0;
} }
int timer_remove(long timer_id) int timer_remove(long timer_id)
{ {
int rc = 0; int rc = 0;
struct timer_elm_s *timer_p; struct timer_elm_s *timer_p;
TMR_DEBUG("Removing timer 0x%lx\n", timer_id); TMR_DEBUG("Removing timer 0x%lx\n", timer_id);
pthread_mutex_lock(&timer_desc.timer_list_mutex); pthread_mutex_lock(&timer_desc.timer_list_mutex);
TIMER_SEARCH(timer_p, timer, ((timer_t)timer_id), &timer_desc.timer_queue); TIMER_SEARCH(timer_p, timer, ((timer_t)timer_id), &timer_desc.timer_queue);
/* We didn't find the timer in list */ /* We didn't find the timer in list */
if (timer_p == NULL) { if (timer_p == NULL) {
pthread_mutex_unlock(&timer_desc.timer_list_mutex);
TMR_ERROR("Didn't find timer 0x%lx in list\n", timer_id);
return -1;
}
STAILQ_REMOVE(&timer_desc.timer_queue, timer_p, timer_elm_s, entries);
pthread_mutex_unlock(&timer_desc.timer_list_mutex); pthread_mutex_unlock(&timer_desc.timer_list_mutex);
TMR_ERROR("Didn't find timer 0x%lx in list\n", timer_id);
return -1;
}
if (timer_delete(timer_p->timer) < 0) { STAILQ_REMOVE(&timer_desc.timer_queue, timer_p, timer_elm_s, entries);
TMR_ERROR("Failed to delete timer 0x%lx\n", (long)timer_p->timer); pthread_mutex_unlock(&timer_desc.timer_list_mutex);
rc = -1;
} if (timer_delete(timer_p->timer) < 0) {
free(timer_p); TMR_ERROR("Failed to delete timer 0x%lx\n", (long)timer_p->timer);
timer_p = NULL; rc = -1;
return rc; }
free(timer_p);
timer_p = NULL;
return rc;
} }
int timer_init(void) int timer_init(void)
{ {
TMR_DEBUG("Initializing TIMER task interface\n"); TMR_DEBUG("Initializing TIMER task interface\n");
memset(&timer_desc, 0, sizeof(timer_desc_t)); memset(&timer_desc, 0, sizeof(timer_desc_t));
STAILQ_INIT(&timer_desc.timer_queue); STAILQ_INIT(&timer_desc.timer_queue);
pthread_mutex_init(&timer_desc.timer_list_mutex, NULL); pthread_mutex_init(&timer_desc.timer_list_mutex, NULL);
TMR_DEBUG("Initializing TIMER task interface: DONE\n"); TMR_DEBUG("Initializing TIMER task interface: DONE\n");
return 0; return 0;
} }
+14 -14
View File
@@ -1,5 +1,5 @@
/******************************************************************************* /*******************************************************************************
OpenAirInterface OpenAirInterface
Copyright(c) 1999 - 2014 Eurecom Copyright(c) 1999 - 2014 Eurecom
OpenAirInterface is free software: you can redistribute it and/or modify OpenAirInterface is free software: you can redistribute it and/or modify
@@ -14,15 +14,15 @@
GNU General Public License for more details. GNU General Public License for more details.
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with OpenAirInterface.The full GNU General Public License is along with OpenAirInterface.The full GNU General Public License is
included in this distribution in the file called "COPYING". If not, included in this distribution in the file called "COPYING". If not,
see <http://www.gnu.org/licenses/>. see <http://www.gnu.org/licenses/>.
Contact Information Contact Information
OpenAirInterface Admin: openair_admin@eurecom.fr OpenAirInterface Admin: openair_admin@eurecom.fr
OpenAirInterface Tech : openair_tech@eurecom.fr OpenAirInterface Tech : openair_tech@eurecom.fr
OpenAirInterface Dev : openair4g-devel@eurecom.fr OpenAirInterface Dev : openair4g-devel@eurecom.fr
Address : Eurecom, Campus SophiaTech, 450 Route des Chappes, CS 50193 - 06904 Biot Sophia Antipolis cedex, FRANCE Address : Eurecom, Campus SophiaTech, 450 Route des Chappes, CS 50193 - 06904 Biot Sophia Antipolis cedex, FRANCE
*******************************************************************************/ *******************************************************************************/
@@ -35,9 +35,9 @@
#define SIGTIMER SIGRTMIN #define SIGTIMER SIGRTMIN
typedef enum timer_type_s { typedef enum timer_type_s {
TIMER_PERIODIC, TIMER_PERIODIC,
TIMER_ONE_SHOT, TIMER_ONE_SHOT,
TIMER_TYPE_MAX, TIMER_TYPE_MAX,
} timer_type_t; } timer_type_t;
int timer_handle_signal(siginfo_t *info); int timer_handle_signal(siginfo_t *info);
@@ -52,13 +52,13 @@ int timer_handle_signal(siginfo_t *info);
* @returns -1 on failure, 0 otherwise * @returns -1 on failure, 0 otherwise
**/ **/
int timer_setup( int timer_setup(
uint32_t interval_sec, uint32_t interval_sec,
uint32_t interval_us, uint32_t interval_us,
task_id_t task_id, task_id_t task_id,
int32_t instance, int32_t instance,
timer_type_t type, timer_type_t type,
void *timer_arg, void *timer_arg,
long *timer_id); long *timer_id);
/** \brief Remove the timer from list /** \brief Remove the timer from list
* \param timer_id unique timer id * \param timer_id unique timer id
+4 -4
View File
@@ -1,5 +1,5 @@
/******************************************************************************* /*******************************************************************************
OpenAirInterface OpenAirInterface
Copyright(c) 1999 - 2014 Eurecom Copyright(c) 1999 - 2014 Eurecom
OpenAirInterface is free software: you can redistribute it and/or modify OpenAirInterface is free software: you can redistribute it and/or modify
@@ -14,15 +14,15 @@
GNU General Public License for more details. GNU General Public License for more details.
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with OpenAirInterface.The full GNU General Public License is along with OpenAirInterface.The full GNU General Public License is
included in this distribution in the file called "COPYING". If not, included in this distribution in the file called "COPYING". If not,
see <http://www.gnu.org/licenses/>. see <http://www.gnu.org/licenses/>.
Contact Information Contact Information
OpenAirInterface Admin: openair_admin@eurecom.fr OpenAirInterface Admin: openair_admin@eurecom.fr
OpenAirInterface Tech : openair_tech@eurecom.fr OpenAirInterface Tech : openair_tech@eurecom.fr
OpenAirInterface Dev : openair4g-devel@eurecom.fr OpenAirInterface Dev : openair4g-devel@eurecom.fr
Address : Eurecom, Campus SophiaTech, 450 Route des Chappes, CS 50193 - 06904 Biot Sophia Antipolis cedex, FRANCE Address : Eurecom, Campus SophiaTech, 450 Route des Chappes, CS 50193 - 06904 Biot Sophia Antipolis cedex, FRANCE
*******************************************************************************/ *******************************************************************************/
+6 -6
View File
@@ -1,5 +1,5 @@
/******************************************************************************* /*******************************************************************************
OpenAirInterface OpenAirInterface
Copyright(c) 1999 - 2014 Eurecom Copyright(c) 1999 - 2014 Eurecom
OpenAirInterface is free software: you can redistribute it and/or modify OpenAirInterface is free software: you can redistribute it and/or modify
@@ -14,15 +14,15 @@
GNU General Public License for more details. GNU General Public License for more details.
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with OpenAirInterface.The full GNU General Public License is along with OpenAirInterface.The full GNU General Public License is
included in this distribution in the file called "COPYING". If not, included in this distribution in the file called "COPYING". If not,
see <http://www.gnu.org/licenses/>. see <http://www.gnu.org/licenses/>.
Contact Information Contact Information
OpenAirInterface Admin: openair_admin@eurecom.fr OpenAirInterface Admin: openair_admin@eurecom.fr
OpenAirInterface Tech : openair_tech@eurecom.fr OpenAirInterface Tech : openair_tech@eurecom.fr
OpenAirInterface Dev : openair4g-devel@eurecom.fr OpenAirInterface Dev : openair4g-devel@eurecom.fr
Address : Eurecom, Campus SophiaTech, 450 Route des Chappes, CS 50193 - 06904 Biot Sophia Antipolis cedex, FRANCE Address : Eurecom, Campus SophiaTech, 450 Route des Chappes, CS 50193 - 06904 Biot Sophia Antipolis cedex, FRANCE
*******************************************************************************/ *******************************************************************************/
@@ -36,8 +36,8 @@
//-------------------------------------------------------------------------------------------// //-------------------------------------------------------------------------------------------//
typedef struct { typedef struct {
void *arg; void *arg;
long timer_id; long timer_id;
} timer_has_expired_t; } timer_has_expired_t;
#endif /* TIMER_MESSAGES_TYPES_H_ */ #endif /* TIMER_MESSAGES_TYPES_H_ */
+110 -110
View File
@@ -48,32 +48,32 @@
#define MAX_APN_PER_UE (5) #define MAX_APN_PER_UE (5)
typedef enum { typedef enum {
RAT_WLAN = 0, RAT_WLAN = 0,
RAT_VIRTUAL = 1, RAT_VIRTUAL = 1,
RAT_UTRAN = 1000, RAT_UTRAN = 1000,
RAT_GERAN = 1001, RAT_GERAN = 1001,
RAT_GAN = 1002, RAT_GAN = 1002,
RAT_HSPA_EVOLUTION = 1003, RAT_HSPA_EVOLUTION = 1003,
RAT_EUTRAN = 1004, RAT_EUTRAN = 1004,
RAT_CDMA2000_1X = 2000, RAT_CDMA2000_1X = 2000,
RAT_HRPD = 2001, RAT_HRPD = 2001,
RAT_UMB = 2002, RAT_UMB = 2002,
RAT_EHRPD = 2003, RAT_EHRPD = 2003,
} rat_type_t; } rat_type_t;
#define NUMBER_OF_RAT_TYPE 11 #define NUMBER_OF_RAT_TYPE 11
typedef enum { typedef enum {
SS_SERVICE_GRANTED = 0, SS_SERVICE_GRANTED = 0,
SS_OPERATOR_DETERMINED_BARRING = 1, SS_OPERATOR_DETERMINED_BARRING = 1,
SS_MAX, SS_MAX,
} subscriber_status_t; } subscriber_status_t;
typedef enum { typedef enum {
NAM_PACKET_AND_CIRCUIT = 0, NAM_PACKET_AND_CIRCUIT = 0,
NAM_RESERVED = 1, NAM_RESERVED = 1,
NAM_ONLY_PACKET = 2, NAM_ONLY_PACKET = 2,
NAM_MAX, NAM_MAX,
} network_access_mode_t; } network_access_mode_t;
typedef uint64_t bitrate_t; typedef uint64_t bitrate_t;
@@ -100,154 +100,154 @@ typedef uint32_t ard_t;
#define ARD_MAX (1U << 6) #define ARD_MAX (1U << 6)
typedef struct { typedef struct {
plmn_t plmn; plmn_t plmn;
unsigned cell_identity:28; unsigned cell_identity:28;
} cgi_t; } cgi_t;
typedef union { typedef union {
struct { struct {
uint8_t imei[13]; uint8_t imei[13];
uint8_t sotfware_version[2]; uint8_t sotfware_version[2];
} id; } id;
uint8_t imeisv[15]; uint8_t imeisv[15];
} me_identity_t; } me_identity_t;
typedef struct { typedef struct {
bitrate_t br_ul; bitrate_t br_ul;
bitrate_t br_dl; bitrate_t br_dl;
} ambr_t; } ambr_t;
typedef enum { typedef enum {
IPv4 = 0, IPv4 = 0,
IPv6 = 1, IPv6 = 1,
IPv4_AND_v6 = 2, IPv4_AND_v6 = 2,
IPv4_OR_v6 = 3, IPv4_OR_v6 = 3,
IP_MAX, IP_MAX,
} pdn_type_t; } pdn_type_t;
typedef struct { typedef struct {
pdn_type_t pdn_type; pdn_type_t pdn_type;
struct { struct {
uint8_t ipv4_address[4]; uint8_t ipv4_address[4];
uint8_t ipv6_address[16]; uint8_t ipv6_address[16];
} address; } address;
} ip_address_t; } ip_address_t;
typedef enum { typedef enum {
QCI_1 = 1, QCI_1 = 1,
QCI_2 = 2, QCI_2 = 2,
QCI_3 = 3, QCI_3 = 3,
QCI_4 = 4, QCI_4 = 4,
QCI_5 = 5, QCI_5 = 5,
QCI_6 = 6, QCI_6 = 6,
QCI_7 = 7, QCI_7 = 7,
QCI_8 = 8, QCI_8 = 8,
QCI_9 = 9, QCI_9 = 9,
/* Values from 128 to 254 are operator specific. /* Values from 128 to 254 are operator specific.
* Other are reserved. * Other are reserved.
*/ */
QCI_MAX, QCI_MAX,
} qci_t; } qci_t;
typedef enum { typedef enum {
PRE_EMPTION_CAPABILITY_ENABLED = 0, PRE_EMPTION_CAPABILITY_ENABLED = 0,
PRE_EMPTION_CAPABILITY_DISABLED = 1, PRE_EMPTION_CAPABILITY_DISABLED = 1,
PRE_EMPTION_CAPABILITY_MAX, PRE_EMPTION_CAPABILITY_MAX,
} pre_emp_capability_t; } pre_emp_capability_t;
typedef enum { typedef enum {
PRE_EMPTION_VULNERABILITY_ENABLED = 0, PRE_EMPTION_VULNERABILITY_ENABLED = 0,
PRE_EMPTION_VULNERABILITY_DISABLED = 1, PRE_EMPTION_VULNERABILITY_DISABLED = 1,
PRE_EMPTION_VULNERABILITY_MAX, PRE_EMPTION_VULNERABILITY_MAX,
} pre_emp_vulnerability_t; } pre_emp_vulnerability_t;
typedef struct { typedef struct {
priority_level_t priority_level; priority_level_t priority_level;
pre_emp_vulnerability_t pre_emp_vulnerability; pre_emp_vulnerability_t pre_emp_vulnerability;
pre_emp_capability_t pre_emp_capability; pre_emp_capability_t pre_emp_capability;
} allocation_retention_priority_t; } allocation_retention_priority_t;
typedef struct eps_subscribed_qos_profile_s { typedef struct eps_subscribed_qos_profile_s {
qci_t qci; qci_t qci;
allocation_retention_priority_t allocation_retention_priority; allocation_retention_priority_t allocation_retention_priority;
} eps_subscribed_qos_profile_t; } eps_subscribed_qos_profile_t;
typedef struct apn_configuration_s { typedef struct apn_configuration_s {
context_identifier_t context_identifier; context_identifier_t context_identifier;
/* Each APN configuration can have 0, 1, or 2 ip address: /* Each APN configuration can have 0, 1, or 2 ip address:
* - 0 means subscribed is dynamically allocated by P-GW depending on the * - 0 means subscribed is dynamically allocated by P-GW depending on the
* pdn_type * pdn_type
* - 1 Only one type of IP address is returned by HSS * - 1 Only one type of IP address is returned by HSS
* - 2 IPv4 and IPv6 address are returned by HSS and are statically * - 2 IPv4 and IPv6 address are returned by HSS and are statically
* allocated * allocated
*/ */
uint8_t nb_ip_address; uint8_t nb_ip_address;
ip_address_t ip_address[2]; ip_address_t ip_address[2];
pdn_type_t pdn_type; pdn_type_t pdn_type;
char service_selection[APN_MAX_LENGTH]; char service_selection[APN_MAX_LENGTH];
int service_selection_length; int service_selection_length;
eps_subscribed_qos_profile_t subscribed_qos; eps_subscribed_qos_profile_t subscribed_qos;
ambr_t ambr; ambr_t ambr;
} apn_configuration_t; } apn_configuration_t;
typedef enum { typedef enum {
ALL_APN_CONFIGURATIONS_INCLUDED = 0, ALL_APN_CONFIGURATIONS_INCLUDED = 0,
MODIFIED_ADDED_APN_CONFIGURATIONS_INCLUDED = 1, MODIFIED_ADDED_APN_CONFIGURATIONS_INCLUDED = 1,
ALL_APN_MAX, ALL_APN_MAX,
} all_apn_conf_ind_t; } all_apn_conf_ind_t;
typedef struct { typedef struct {
context_identifier_t context_identifier; context_identifier_t context_identifier;
all_apn_conf_ind_t all_apn_conf_ind; all_apn_conf_ind_t all_apn_conf_ind;
/* Number of APNs provided */ /* Number of APNs provided */
uint8_t nb_apns; uint8_t nb_apns;
/* List of APNs configuration 1 to n elements */ /* List of APNs configuration 1 to n elements */
struct apn_configuration_s apn_configuration[MAX_APN_PER_UE]; struct apn_configuration_s apn_configuration[MAX_APN_PER_UE];
} apn_config_profile_t; } apn_config_profile_t;
typedef struct { typedef struct {
subscriber_status_t subscriber_status; subscriber_status_t subscriber_status;
char msisdn[MSISDN_LENGTH + 1]; char msisdn[MSISDN_LENGTH + 1];
uint8_t msisdn_length; uint8_t msisdn_length;
network_access_mode_t access_mode; network_access_mode_t access_mode;
access_restriction_t access_restriction; access_restriction_t access_restriction;
ambr_t subscribed_ambr; ambr_t subscribed_ambr;
apn_config_profile_t apn_config_profile; apn_config_profile_t apn_config_profile;
rau_tau_timer_t rau_tau_timer; rau_tau_timer_t rau_tau_timer;
} subscription_data_t; } subscription_data_t;
typedef struct authentication_info_s { typedef struct authentication_info_s {
uint8_t nb_of_vectors; uint8_t nb_of_vectors;
eutran_vector_t eutran_vector; eutran_vector_t eutran_vector;
} authentication_info_t; } authentication_info_t;
typedef enum { typedef enum {
DIAMETER_AUTHENTICATION_DATA_UNAVAILABLE = 4181, DIAMETER_AUTHENTICATION_DATA_UNAVAILABLE = 4181,
DIAMETER_ERROR_USER_UNKNOWN = 5001, DIAMETER_ERROR_USER_UNKNOWN = 5001,
DIAMETER_ERROR_ROAMING_NOT_ALLOWED = 5004, DIAMETER_ERROR_ROAMING_NOT_ALLOWED = 5004,
DIAMETER_ERROR_UNKNOWN_EPS_SUBSCRIPTION = 5420, DIAMETER_ERROR_UNKNOWN_EPS_SUBSCRIPTION = 5420,
DIAMETER_ERROR_RAT_NOT_ALLOWED = 5421, DIAMETER_ERROR_RAT_NOT_ALLOWED = 5421,
DIAMETER_ERROR_EQUIPMENT_UNKNOWN = 5422, DIAMETER_ERROR_EQUIPMENT_UNKNOWN = 5422,
DIAMETER_ERROR_UNKOWN_SERVING_NODE = 5423, DIAMETER_ERROR_UNKOWN_SERVING_NODE = 5423,
} s6a_experimental_result_t; } s6a_experimental_result_t;
typedef enum { typedef enum {
DIAMETER_SUCCESS = 2001, DIAMETER_SUCCESS = 2001,
} s6a_base_result_t; } s6a_base_result_t;
typedef struct { typedef struct {
#define S6A_RESULT_BASE 0x0 #define S6A_RESULT_BASE 0x0
#define S6A_RESULT_EXPERIMENTAL 0x1 #define S6A_RESULT_EXPERIMENTAL 0x1
unsigned present:1; unsigned present:1;
union { union {
/* Experimental result as defined in 3GPP TS 29.272 */ /* Experimental result as defined in 3GPP TS 29.272 */
s6a_experimental_result_t experimental; s6a_experimental_result_t experimental;
/* Diameter basics results as defined in RFC 3588 */ /* Diameter basics results as defined in RFC 3588 */
s6a_base_result_t base; s6a_base_result_t base;
} choice; } choice;
} s6a_result_t; } s6a_result_t;
#endif /* COMMON_TYPES_H_ */ #endif /* COMMON_TYPES_H_ */
+30 -30
View File
@@ -32,57 +32,57 @@
#include "../SGW-LITE/sgw_lite_ie_defs.h" #include "../SGW-LITE/sgw_lite_ie_defs.h"
typedef struct { typedef struct {
Teid_t context_teid; ///< Tunnel Endpoint Identifier Teid_t context_teid; ///< Tunnel Endpoint Identifier
ebi_t eps_bearer_id; ebi_t eps_bearer_id;
} Gtpv1uCreateTunnelReq; } Gtpv1uCreateTunnelReq;
typedef struct { typedef struct {
uint8_t status; ///< Status of S1U endpoint creation (Failed = 0xFF or Success = 0x0) 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 context_teid; ///< local SGW S11 Tunnel Endpoint Identifier
Teid_t S1u_teid; ///< Tunnel Endpoint Identifier Teid_t S1u_teid; ///< Tunnel Endpoint Identifier
ebi_t eps_bearer_id; ebi_t eps_bearer_id;
} Gtpv1uCreateTunnelResp; } Gtpv1uCreateTunnelResp;
typedef struct { typedef struct {
Teid_t context_teid; ///< S11 Tunnel Endpoint Identifier Teid_t context_teid; ///< S11 Tunnel Endpoint Identifier
Teid_t sgw_S1u_teid; ///< SGW S1U local Tunnel Endpoint Identifier Teid_t sgw_S1u_teid; ///< SGW S1U local Tunnel Endpoint Identifier
Teid_t enb_S1u_teid; ///< eNB S1U Tunnel Endpoint Identifier Teid_t enb_S1u_teid; ///< eNB S1U Tunnel Endpoint Identifier
ip_address_t enb_ip_address_for_S1u; ip_address_t enb_ip_address_for_S1u;
ebi_t eps_bearer_id; ebi_t eps_bearer_id;
} Gtpv1uUpdateTunnelReq; } Gtpv1uUpdateTunnelReq;
typedef struct { typedef struct {
uint8_t status; ///< Status (Failed = 0xFF or Success = 0x0) uint8_t status; ///< Status (Failed = 0xFF or Success = 0x0)
Teid_t context_teid; ///< S11 Tunnel Endpoint Identifier Teid_t context_teid; ///< S11 Tunnel Endpoint Identifier
Teid_t sgw_S1u_teid; ///< SGW S1U local Tunnel Endpoint Identifier Teid_t sgw_S1u_teid; ///< SGW S1U local Tunnel Endpoint Identifier
Teid_t enb_S1u_teid; ///< eNB S1U Tunnel Endpoint Identifier Teid_t enb_S1u_teid; ///< eNB S1U Tunnel Endpoint Identifier
ebi_t eps_bearer_id; ebi_t eps_bearer_id;
} Gtpv1uUpdateTunnelResp; } Gtpv1uUpdateTunnelResp;
typedef struct { typedef struct {
Teid_t context_teid; ///< local SGW S11 Tunnel Endpoint Identifier Teid_t context_teid; ///< local SGW S11 Tunnel Endpoint Identifier
Teid_t S1u_teid; ///< local S1U Tunnel Endpoint Identifier to be deleted Teid_t S1u_teid; ///< local S1U Tunnel Endpoint Identifier to be deleted
} Gtpv1uDeleteTunnelReq; } Gtpv1uDeleteTunnelReq;
typedef struct { typedef struct {
uint8_t status; ///< Status of S1U endpoint deleteion (Failed = 0xFF or Success = 0x0) 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 context_teid; ///< local SGW S11 Tunnel Endpoint Identifier
Teid_t S1u_teid; ///< local S1U Tunnel Endpoint Identifier to be deleted Teid_t S1u_teid; ///< local S1U Tunnel Endpoint Identifier to be deleted
} Gtpv1uDeleteTunnelResp; } Gtpv1uDeleteTunnelResp;
typedef struct { typedef struct {
uint8_t *buffer; uint8_t *buffer;
uint32_t length; uint32_t length;
uint32_t offset; ///< start of message offset in buffer uint32_t offset; ///< start of message offset in buffer
Teid_t local_S1u_teid; ///< Tunnel Endpoint Identifier Teid_t local_S1u_teid; ///< Tunnel Endpoint Identifier
} Gtpv1uTunnelDataInd; } Gtpv1uTunnelDataInd;
typedef struct { typedef struct {
uint8_t *buffer; uint8_t *buffer;
uint32_t length; uint32_t length;
uint32_t offset; ///< start of message offset in buffer uint32_t offset; ///< start of message offset in buffer
Teid_t local_S1u_teid; ///< Tunnel Endpoint Identifier Teid_t local_S1u_teid; ///< Tunnel Endpoint Identifier
Teid_t S1u_enb_teid; ///< Tunnel Endpoint Identifier Teid_t S1u_enb_teid; ///< Tunnel Endpoint Identifier
} Gtpv1uTunnelDataReq; } Gtpv1uTunnelDataReq;
#endif /* GTPV1_U_MESSAGES_TYPES_H_ */ #endif /* GTPV1_U_MESSAGES_TYPES_H_ */
+40 -40
View File
@@ -30,66 +30,66 @@
#define SGI_FORWARD_MESSAGES_TYPES_H_ #define SGI_FORWARD_MESSAGES_TYPES_H_
typedef enum SGIStatus_e { typedef enum SGIStatus_e {
SGI_STATUS_OK = 0, SGI_STATUS_OK = 0,
SGI_STATUS_ERROR_CONTEXT_ALREADY_EXIST = 50, SGI_STATUS_ERROR_CONTEXT_ALREADY_EXIST = 50,
SGI_STATUS_ERROR_CONTEXT_NOT_FOUND = 51, SGI_STATUS_ERROR_CONTEXT_NOT_FOUND = 51,
SGI_STATUS_ERROR_INVALID_MESSAGE_FORMAT = 52, SGI_STATUS_ERROR_INVALID_MESSAGE_FORMAT = 52,
SGI_STATUS_ERROR_SERVICE_NOT_SUPPORTED = 53, SGI_STATUS_ERROR_SERVICE_NOT_SUPPORTED = 53,
SGI_STATUS_ERROR_SYSTEM_FAILURE = 54, SGI_STATUS_ERROR_SYSTEM_FAILURE = 54,
SGI_STATUS_ERROR_NO_RESOURCES_AVAILABLE = 55, SGI_STATUS_ERROR_NO_RESOURCES_AVAILABLE = 55,
SGI_STATUS_ERROR_NO_MEMORY_AVAILABLE = 56, SGI_STATUS_ERROR_NO_MEMORY_AVAILABLE = 56,
SGI_STATUS_MAX, SGI_STATUS_MAX,
} SGIStatus_t; } SGIStatus_t;
typedef struct { typedef struct {
Teid_t context_teid; ///< Tunnel Endpoint Identifier S11 Teid_t context_teid; ///< Tunnel Endpoint Identifier S11
Teid_t sgw_S1u_teid; ///< Tunnel Endpoint Identifier S1-U Teid_t sgw_S1u_teid; ///< Tunnel Endpoint Identifier S1-U
ebi_t eps_bearer_id; ///< EPS bearer identifier ebi_t eps_bearer_id; ///< EPS bearer identifier
pdn_type_t pdn_type; ///< PDN Type pdn_type_t pdn_type; ///< PDN Type
PAA_t paa; ///< PDN Address Allocation PAA_t paa; ///< PDN Address Allocation
} SGICreateEndpointReq; } SGICreateEndpointReq;
typedef struct { typedef struct {
SGIStatus_t status; ///< Status of endpoint creation (Failed = 0xFF or Success = 0x0) SGIStatus_t status; ///< Status of endpoint creation (Failed = 0xFF or Success = 0x0)
Teid_t context_teid; ///< Tunnel Endpoint Identifier S11 Teid_t context_teid; ///< Tunnel Endpoint Identifier S11
Teid_t sgw_S1u_teid; ///< Tunnel Endpoint Identifier S1-U Teid_t sgw_S1u_teid; ///< Tunnel Endpoint Identifier S1-U
ebi_t eps_bearer_id; ///< EPS bearer identifier ebi_t eps_bearer_id; ///< EPS bearer identifier
pdn_type_t pdn_type; ///< PDN Type pdn_type_t pdn_type; ///< PDN Type
PAA_t paa; ///< PDN Address Allocation PAA_t paa; ///< PDN Address Allocation
} SGICreateEndpointResp; } SGICreateEndpointResp;
typedef struct { typedef struct {
Teid_t context_teid; ///< Tunnel Endpoint Identifier S11 Teid_t context_teid; ///< Tunnel Endpoint Identifier S11
Teid_t sgw_S1u_teid; ///< Tunnel Endpoint Identifier S1-U Teid_t sgw_S1u_teid; ///< Tunnel Endpoint Identifier S1-U
Teid_t enb_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 ebi_t eps_bearer_id; ///< EPS bearer identifier
} SGIUpdateEndpointReq; } SGIUpdateEndpointReq;
typedef struct { typedef struct {
SGIStatus_t status; ///< Status of endpoint creation (Failed = 0xFF or Success = 0x0) SGIStatus_t status; ///< Status of endpoint creation (Failed = 0xFF or Success = 0x0)
Teid_t context_teid; ///< Tunnel Endpoint Identifier S11 Teid_t context_teid; ///< Tunnel Endpoint Identifier S11
Teid_t sgw_S1u_teid; ///< Tunnel Endpoint Identifier S1-U Teid_t sgw_S1u_teid; ///< Tunnel Endpoint Identifier S1-U
Teid_t enb_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 ebi_t eps_bearer_id; ///< EPS bearer identifier
} SGIUpdateEndpointResp; } SGIUpdateEndpointResp;
typedef struct { typedef struct {
Teid_t context_teid; ///< Tunnel Endpoint Identifier S11 Teid_t context_teid; ///< Tunnel Endpoint Identifier S11
Teid_t sgw_S1u_teid; ///< Tunnel Endpoint Identifier S1-U Teid_t sgw_S1u_teid; ///< Tunnel Endpoint Identifier S1-U
ebi_t eps_bearer_id; ///< EPS bearer identifier ebi_t eps_bearer_id; ///< EPS bearer identifier
pdn_type_t pdn_type; ///< PDN Type pdn_type_t pdn_type; ///< PDN Type
PAA_t paa; ///< PDN Address Allocation PAA_t paa; ///< PDN Address Allocation
} SGIDeleteEndpointReq; } SGIDeleteEndpointReq;
typedef struct { typedef struct {
SGIStatus_t status; ///< Status of endpoint deletion (Failed = 0xFF or Success = 0x0) SGIStatus_t status; ///< Status of endpoint deletion (Failed = 0xFF or Success = 0x0)
Teid_t context_teid; ///< Tunnel Endpoint Identifier S11 Teid_t context_teid; ///< Tunnel Endpoint Identifier S11
Teid_t sgw_S1u_teid; ///< Tunnel Endpoint Identifier S1-U Teid_t sgw_S1u_teid; ///< Tunnel Endpoint Identifier S1-U
ebi_t eps_bearer_id; ///< EPS bearer identifier ebi_t eps_bearer_id; ///< EPS bearer identifier
pdn_type_t pdn_type; ///< PDN Type pdn_type_t pdn_type; ///< PDN Type
PAA_t paa; ///< PDN Address Allocation PAA_t paa; ///< PDN Address Allocation
} SGIDeleteEndpointResp; } SGIDeleteEndpointResp;
#endif /* SGI_FORWARD_MESSAGES_TYPES_H_ */ #endif /* SGI_FORWARD_MESSAGES_TYPES_H_ */
+21 -21
View File
@@ -35,37 +35,37 @@
#define MME_APP_INITIAL_CONTEXT_SETUP_RSP(mSGpTR) (mSGpTR)->ittiMsg.mme_app_initial_context_setup_rsp #define MME_APP_INITIAL_CONTEXT_SETUP_RSP(mSGpTR) (mSGpTR)->ittiMsg.mme_app_initial_context_setup_rsp
typedef struct mme_app_connection_establishment_ind_s { typedef struct mme_app_connection_establishment_ind_s {
uint32_t mme_ue_s1ap_id; uint32_t mme_ue_s1ap_id;
nas_establish_ind_t nas; nas_establish_ind_t nas;
/* Transparent message from s1ap to be forwarded to MME_APP or /* Transparent message from s1ap to be forwarded to MME_APP or
* to S1AP if connection establishment is rejected by NAS. * to S1AP if connection establishment is rejected by NAS.
*/ */
s1ap_initial_ue_message_t transparent; s1ap_initial_ue_message_t transparent;
} mme_app_connection_establishment_ind_t; } mme_app_connection_establishment_ind_t;
typedef struct mme_app_connection_establishment_cnf_s { typedef struct mme_app_connection_establishment_cnf_s {
ebi_t eps_bearer_id; ebi_t eps_bearer_id;
FTeid_t bearer_s1u_sgw_fteid; FTeid_t bearer_s1u_sgw_fteid;
qci_t bearer_qos_qci; qci_t bearer_qos_qci;
priority_level_t bearer_qos_prio_level; priority_level_t bearer_qos_prio_level;
pre_emp_vulnerability_t bearer_qos_pre_emp_vulnerability; pre_emp_vulnerability_t bearer_qos_pre_emp_vulnerability;
pre_emp_capability_t bearer_qos_pre_emp_capability; pre_emp_capability_t bearer_qos_pre_emp_capability;
ambr_t ambr; ambr_t ambr;
/* Key eNB */ /* Key eNB */
uint8_t keNB[32]; uint8_t keNB[32];
uint16_t security_capabilities_encryption_algorithms; uint16_t security_capabilities_encryption_algorithms;
uint16_t security_capabilities_integrity_algorithms; uint16_t security_capabilities_integrity_algorithms;
nas_conn_est_cnf_t nas_conn_est_cnf; nas_conn_est_cnf_t nas_conn_est_cnf;
} mme_app_connection_establishment_cnf_t; } mme_app_connection_establishment_cnf_t;
typedef struct mme_app_initial_context_setup_rsp_s { typedef struct mme_app_initial_context_setup_rsp_s {
uint32_t mme_ue_s1ap_id; uint32_t mme_ue_s1ap_id;
ebi_t eps_bearer_id; ebi_t eps_bearer_id;
FTeid_t bearer_s1u_enb_fteid; FTeid_t bearer_s1u_enb_fteid;
} mme_app_initial_context_setup_rsp_t; } mme_app_initial_context_setup_rsp_t;
+140 -140
View File
@@ -67,101 +67,101 @@
typedef enum { typedef enum {
EMM_MSG_HEADER = 1, EMM_MSG_HEADER = 1,
EMM_MSG_ATTACH_REQUEST, EMM_MSG_ATTACH_REQUEST,
EMM_MSG_ATTACH_ACCEPT, EMM_MSG_ATTACH_ACCEPT,
EMM_MSG_ATTACH_COMPLETE, EMM_MSG_ATTACH_COMPLETE,
EMM_MSG_ATTACH_REJECT, EMM_MSG_ATTACH_REJECT,
EMM_MSG_DETACH_REQUEST, EMM_MSG_DETACH_REQUEST,
EMM_MSG_DETACH_ACCEPT, EMM_MSG_DETACH_ACCEPT,
EMM_MSG_TRACKING_AREA_UPDATE_REQUEST, EMM_MSG_TRACKING_AREA_UPDATE_REQUEST,
EMM_MSG_TRACKING_AREA_UPDATE_ACCEPT, EMM_MSG_TRACKING_AREA_UPDATE_ACCEPT,
EMM_MSG_TRACKING_AREA_UPDATE_COMPLETE, EMM_MSG_TRACKING_AREA_UPDATE_COMPLETE,
EMM_MSG_TRACKING_AREA_UPDATE_REJECT, EMM_MSG_TRACKING_AREA_UPDATE_REJECT,
EMM_MSG_EXTENDED_SERVICE_REQUEST, EMM_MSG_EXTENDED_SERVICE_REQUEST,
EMM_MSG_SERVICE_REQUEST, EMM_MSG_SERVICE_REQUEST,
EMM_MSG_SERVICE_REJECT, EMM_MSG_SERVICE_REJECT,
EMM_MSG_GUTI_REALLOCATION_COMMAND, EMM_MSG_GUTI_REALLOCATION_COMMAND,
EMM_MSG_GUTI_REALLOCATION_COMPLETE, EMM_MSG_GUTI_REALLOCATION_COMPLETE,
EMM_MSG_AUTHENTICATION_REQUEST, EMM_MSG_AUTHENTICATION_REQUEST,
EMM_MSG_AUTHENTICATION_RESPONSE, EMM_MSG_AUTHENTICATION_RESPONSE,
EMM_MSG_AUTHENTICATION_REJECT, EMM_MSG_AUTHENTICATION_REJECT,
EMM_MSG_AUTHENTICATION_FAILURE, EMM_MSG_AUTHENTICATION_FAILURE,
EMM_MSG_IDENTITY_REQUEST, EMM_MSG_IDENTITY_REQUEST,
EMM_MSG_IDENTITY_RESPONSE, EMM_MSG_IDENTITY_RESPONSE,
EMM_MSG_SECURITY_MODE_COMMAND, EMM_MSG_SECURITY_MODE_COMMAND,
EMM_MSG_SECURITY_MODE_COMPLETE, EMM_MSG_SECURITY_MODE_COMPLETE,
EMM_MSG_SECURITY_MODE_REJECT, EMM_MSG_SECURITY_MODE_REJECT,
EMM_MSG_EMM_STATUS, EMM_MSG_EMM_STATUS,
EMM_MSG_EMM_INFORMATION, EMM_MSG_EMM_INFORMATION,
EMM_MSG_DOWNLINK_NAS_TRANSPORT, EMM_MSG_DOWNLINK_NAS_TRANSPORT,
EMM_MSG_UPLINK_NAS_TRANSPORT, EMM_MSG_UPLINK_NAS_TRANSPORT,
EMM_MSG_CS_SERVICE_NOTIFICATION, EMM_MSG_CS_SERVICE_NOTIFICATION,
} emm_message_ids_t; } emm_message_ids_t;
typedef enum { typedef enum {
ESM_MSG_HEADER = 1, ESM_MSG_HEADER = 1,
ESM_MSG_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REQUEST, ESM_MSG_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REQUEST,
ESM_MSG_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_ACCEPT, ESM_MSG_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_ACCEPT,
ESM_MSG_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REJECT, ESM_MSG_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REJECT,
ESM_MSG_ACTIVATE_DEDICATED_EPS_BEARER_CONTEXT_REQUEST, ESM_MSG_ACTIVATE_DEDICATED_EPS_BEARER_CONTEXT_REQUEST,
ESM_MSG_ACTIVATE_DEDICATED_EPS_BEARER_CONTEXT_ACCEPT, ESM_MSG_ACTIVATE_DEDICATED_EPS_BEARER_CONTEXT_ACCEPT,
ESM_MSG_ACTIVATE_DEDICATED_EPS_BEARER_CONTEXT_REJECT, ESM_MSG_ACTIVATE_DEDICATED_EPS_BEARER_CONTEXT_REJECT,
ESM_MSG_MODIFY_EPS_BEARER_CONTEXT_REQUEST, ESM_MSG_MODIFY_EPS_BEARER_CONTEXT_REQUEST,
ESM_MSG_MODIFY_EPS_BEARER_CONTEXT_ACCEPT, ESM_MSG_MODIFY_EPS_BEARER_CONTEXT_ACCEPT,
ESM_MSG_MODIFY_EPS_BEARER_CONTEXT_REJECT, ESM_MSG_MODIFY_EPS_BEARER_CONTEXT_REJECT,
ESM_MSG_DEACTIVATE_EPS_BEARER_CONTEXT_REQUEST, ESM_MSG_DEACTIVATE_EPS_BEARER_CONTEXT_REQUEST,
ESM_MSG_DEACTIVATE_EPS_BEARER_CONTEXT_ACCEPT, ESM_MSG_DEACTIVATE_EPS_BEARER_CONTEXT_ACCEPT,
ESM_MSG_PDN_CONNECTIVITY_REQUEST, ESM_MSG_PDN_CONNECTIVITY_REQUEST,
ESM_MSG_PDN_CONNECTIVITY_REJECT, ESM_MSG_PDN_CONNECTIVITY_REJECT,
ESM_MSG_PDN_DISCONNECT_REQUEST, ESM_MSG_PDN_DISCONNECT_REQUEST,
ESM_MSG_PDN_DISCONNECT_REJECT, ESM_MSG_PDN_DISCONNECT_REJECT,
ESM_MSG_BEARER_RESOURCE_ALLOCATION_REQUEST, ESM_MSG_BEARER_RESOURCE_ALLOCATION_REQUEST,
ESM_MSG_BEARER_RESOURCE_ALLOCATION_REJECT, ESM_MSG_BEARER_RESOURCE_ALLOCATION_REJECT,
ESM_MSG_BEARER_RESOURCE_MODIFICATION_REQUEST, ESM_MSG_BEARER_RESOURCE_MODIFICATION_REQUEST,
ESM_MSG_BEARER_RESOURCE_MODIFICATION_REJECT, ESM_MSG_BEARER_RESOURCE_MODIFICATION_REJECT,
ESM_MSG_ESM_INFORMATION_REQUEST, ESM_MSG_ESM_INFORMATION_REQUEST,
ESM_MSG_ESM_INFORMATION_RESPONSE, ESM_MSG_ESM_INFORMATION_RESPONSE,
ESM_MSG_ESM_STATUS, ESM_MSG_ESM_STATUS,
} esm_message_ids_t; } esm_message_ids_t;
typedef struct nas_raw_msg_s { typedef struct nas_raw_msg_s {
uint32_t lenght; uint32_t lenght;
uint8_t data[NAS_DATA_LENGHT_MAX]; uint8_t data[NAS_DATA_LENGHT_MAX];
} nas_raw_msg_t; } nas_raw_msg_t;
typedef struct nas_emm_plain_msg_s { typedef struct nas_emm_plain_msg_s {
emm_message_ids_t present; emm_message_ids_t present;
EMM_msg choice; EMM_msg choice;
} nas_emm_plain_msg_t; } nas_emm_plain_msg_t;
typedef struct nas_emm_protected_msg_s { typedef struct nas_emm_protected_msg_s {
nas_message_security_header_t header; nas_message_security_header_t header;
emm_message_ids_t present; emm_message_ids_t present;
EMM_msg choice; EMM_msg choice;
} nas_emm_protected_msg_t; } nas_emm_protected_msg_t;
typedef struct nas_esm_plain_msg_s { typedef struct nas_esm_plain_msg_s {
esm_message_ids_t present; esm_message_ids_t present;
ESM_msg choice; ESM_msg choice;
} nas_esm_plain_msg_t; } nas_esm_plain_msg_t;
typedef struct nas_esm_protected_msg_s { typedef struct nas_esm_protected_msg_s {
nas_message_security_header_t header; nas_message_security_header_t header;
esm_message_ids_t present; esm_message_ids_t present;
ESM_msg choice; ESM_msg choice;
} nas_esm_protected_msg_t; } nas_esm_protected_msg_t;
@@ -171,66 +171,66 @@ typedef struct nas_paging_ind_s {
typedef struct nas_pdn_connectivity_req_s { typedef struct nas_pdn_connectivity_req_s {
int pti; // nas ref Identity of the procedure transaction executed to activate the PDN connection entry int pti; // nas ref Identity of the procedure transaction executed to activate the PDN connection entry
unsigned ue_id; // nas ref unsigned ue_id; // nas ref
char imsi[16]; char imsi[16];
uint8_t imsi_length; uint8_t imsi_length;
network_qos_t qos; network_qos_t qos;
OctetString apn; OctetString apn;
OctetString pdn_addr; OctetString pdn_addr;
int pdn_type; int pdn_type;
void *proc_data; void *proc_data;
int request_type; int request_type;
} nas_pdn_connectivity_req_t; } nas_pdn_connectivity_req_t;
typedef struct nas_pdn_connectivity_rsp_s { typedef struct nas_pdn_connectivity_rsp_s {
int pti; // nas ref Identity of the procedure transaction executed to activate the PDN connection entry int pti; // nas ref Identity of the procedure transaction executed to activate the PDN connection entry
unsigned ue_id; // nas ref unsigned ue_id; // nas ref
network_qos_t qos; network_qos_t qos;
OctetString apn; OctetString apn;
OctetString pdn_addr; OctetString pdn_addr;
int pdn_type; int pdn_type;
void *proc_data; void *proc_data;
int request_type; int request_type;
unsigned eNB_ue_s1ap_id:24; unsigned eNB_ue_s1ap_id:24;
uint32_t mme_ue_s1ap_id; uint32_t mme_ue_s1ap_id;
/* Key eNB */ /* Key eNB */
//uint8_t keNB[32]; //uint8_t keNB[32];
ambr_t ambr; ambr_t ambr;
ambr_t apn_ambr; ambr_t apn_ambr;
/* EPS bearer ID */ /* EPS bearer ID */
unsigned ebi:4; unsigned ebi:4;
/* QoS */ /* QoS */
qci_t qci; qci_t qci;
priority_level_t prio_level; priority_level_t prio_level;
pre_emp_vulnerability_t pre_emp_vulnerability; pre_emp_vulnerability_t pre_emp_vulnerability;
pre_emp_capability_t pre_emp_capability; pre_emp_capability_t pre_emp_capability;
/* S-GW TEID for user-plane */ /* S-GW TEID for user-plane */
Teid_t sgw_s1u_teid; Teid_t sgw_s1u_teid;
/* S-GW IP address for User-Plane */ /* S-GW IP address for User-Plane */
ip_address_t sgw_s1u_address; ip_address_t sgw_s1u_address;
} nas_pdn_connectivity_rsp_t; } nas_pdn_connectivity_rsp_t;
typedef struct nas_pdn_connectivity_fail_s { typedef struct nas_pdn_connectivity_fail_s {
unsigned ue_id; // nas ref unsigned ue_id; // nas ref
} nas_pdn_connectivity_fail_t; } nas_pdn_connectivity_fail_t;
typedef struct nas_conn_est_ind_s { typedef struct nas_conn_est_ind_s {
nas_establish_ind_t nas; nas_establish_ind_t nas;
/* Transparent message from s1ap to be forwarded to MME_APP or /* Transparent message from s1ap to be forwarded to MME_APP or
* to S1AP if connection establishment is rejected by NAS. * to S1AP if connection establishment is rejected by NAS.
*/ */
s1ap_initial_ue_message_t transparent; s1ap_initial_ue_message_t transparent;
} nas_conn_est_ind_t; } nas_conn_est_ind_t;
@@ -239,11 +239,11 @@ typedef nas_establish_rsp_t nas_conn_est_rej_t;
#if defined(DISABLE_USE_NAS) #if defined(DISABLE_USE_NAS)
typedef struct nas_conn_est_cnf_s { typedef struct nas_conn_est_cnf_s {
uint32_t ue_id; uint32_t ue_id;
nas_establish_cnf_t nas_establish_cnf; nas_establish_cnf_t nas_establish_cnf;
/* Transparent message from MME_APP to S1AP */ /* Transparent message from MME_APP to S1AP */
s1ap_initial_ctxt_setup_req_t transparent; s1ap_initial_ctxt_setup_req_t transparent;
} nas_conn_est_cnf_t; } nas_conn_est_cnf_t;
#else #else
typedef nas_establish_cnf_t nas_conn_est_cnf_t; typedef nas_establish_cnf_t nas_conn_est_cnf_t;
@@ -279,69 +279,69 @@ typedef struct nas_rab_rel_req_s {
typedef struct nas_attach_req_s { typedef struct nas_attach_req_s {
/* TODO: Set the correct size */ /* TODO: Set the correct size */
char apn[100]; char apn[100];
char imsi[16]; char imsi[16];
#define INITIAL_REQUEST (0x1) #define INITIAL_REQUEST (0x1)
unsigned initial:1; unsigned initial:1;
s1ap_initial_ue_message_t transparent; s1ap_initial_ue_message_t transparent;
} nas_attach_req_t; } nas_attach_req_t;
typedef struct nas_auth_req_s { typedef struct nas_auth_req_s {
/* UE imsi */ /* UE imsi */
char imsi[16]; char imsi[16];
#define NAS_FAILURE_OK 0x0 #define NAS_FAILURE_OK 0x0
#define NAS_FAILURE_IND 0x1 #define NAS_FAILURE_IND 0x1
unsigned failure:1; unsigned failure:1;
int cause; int cause;
} nas_auth_req_t; } nas_auth_req_t;
typedef struct nas_auth_resp_s { typedef struct nas_auth_resp_s {
char imsi[16]; char imsi[16];
} nas_auth_resp_t; } nas_auth_resp_t;
typedef struct nas_auth_param_req_s { typedef struct nas_auth_param_req_s {
/* UE identifier */ /* UE identifier */
uint32_t ue_id; uint32_t ue_id;
/* Imsi of the UE (In case of initial request) */ /* Imsi of the UE (In case of initial request) */
char imsi[16]; char imsi[16];
uint8_t imsi_length; uint8_t imsi_length;
/* Indicates whether the procedure corresponds to a new connection or not */ /* Indicates whether the procedure corresponds to a new connection or not */
uint8_t initial_req:1; uint8_t initial_req:1;
uint8_t re_synchronization:1; uint8_t re_synchronization:1;
uint8_t auts[14]; uint8_t auts[14];
} nas_auth_param_req_t; } nas_auth_param_req_t;
typedef struct nas_auth_param_rsp_s { typedef struct nas_auth_param_rsp_s {
/* UE identifier */ /* UE identifier */
uint32_t ue_id; uint32_t ue_id;
/* For future use: nb of vectors provided */ /* For future use: nb of vectors provided */
uint8_t nb_vectors; uint8_t nb_vectors;
/* Consider only one E-UTRAN vector for the moment... */ /* Consider only one E-UTRAN vector for the moment... */
eutran_vector_t vector; eutran_vector_t vector;
} nas_auth_param_rsp_t; } nas_auth_param_rsp_t;
typedef struct nas_auth_param_fail_s { typedef struct nas_auth_param_fail_s {
/* UE identifier */ /* UE identifier */
uint32_t ue_id; uint32_t ue_id;
/* S6A mapped to NAS cause */ /* S6A mapped to NAS cause */
nas_cause_t cause; nas_cause_t cause;
} nas_auth_param_fail_t; } nas_auth_param_fail_t;
#if defined(DISABLE_USE_NAS) #if defined(DISABLE_USE_NAS)
typedef struct nas_attach_accept_s { typedef struct nas_attach_accept_s {
s1ap_initial_ctxt_setup_req_t transparent; s1ap_initial_ctxt_setup_req_t transparent;
} nas_attach_accept_t; } nas_attach_accept_t;
#endif #endif
+27 -27
View File
@@ -33,51 +33,51 @@
#define S1AP_DEREGISTER_UE_REQ(mSGpTR) (mSGpTR)->ittiMsg.s1ap_deregister_ue_req #define S1AP_DEREGISTER_UE_REQ(mSGpTR) (mSGpTR)->ittiMsg.s1ap_deregister_ue_req
typedef struct s1ap_initial_ue_message_s { typedef struct s1ap_initial_ue_message_s {
unsigned eNB_ue_s1ap_id:24; unsigned eNB_ue_s1ap_id:24;
uint32_t mme_ue_s1ap_id; uint32_t mme_ue_s1ap_id;
cgi_t e_utran_cgi; cgi_t e_utran_cgi;
} s1ap_initial_ue_message_t; } s1ap_initial_ue_message_t;
typedef struct s1ap_initial_ctxt_setup_req_s { typedef struct s1ap_initial_ctxt_setup_req_s {
unsigned eNB_ue_s1ap_id:24; unsigned eNB_ue_s1ap_id:24;
uint32_t mme_ue_s1ap_id; uint32_t mme_ue_s1ap_id;
/* Key eNB */ /* Key eNB */
uint8_t keNB[32]; uint8_t keNB[32];
ambr_t ambr; ambr_t ambr;
ambr_t apn_ambr; ambr_t apn_ambr;
/* EPS bearer ID */ /* EPS bearer ID */
unsigned ebi:4; unsigned ebi:4;
/* QoS */ /* QoS */
qci_t qci; qci_t qci;
priority_level_t prio_level; priority_level_t prio_level;
pre_emp_vulnerability_t pre_emp_vulnerability; pre_emp_vulnerability_t pre_emp_vulnerability;
pre_emp_capability_t pre_emp_capability; pre_emp_capability_t pre_emp_capability;
/* S-GW TEID for user-plane */ /* S-GW TEID for user-plane */
Teid_t teid; Teid_t teid;
/* S-GW IP address for User-Plane */ /* S-GW IP address for User-Plane */
ip_address_t s_gw_address; ip_address_t s_gw_address;
} s1ap_initial_ctxt_setup_req_t; } s1ap_initial_ctxt_setup_req_t;
typedef struct s1ap_ue_cap_ind_s { typedef struct s1ap_ue_cap_ind_s {
unsigned eNB_ue_s1ap_id:24; unsigned eNB_ue_s1ap_id:24;
uint32_t mme_ue_s1ap_id; uint32_t mme_ue_s1ap_id;
uint8_t radio_capabilities[100]; uint8_t radio_capabilities[100];
uint32_t radio_capabilities_length; uint32_t radio_capabilities_length;
} s1ap_ue_cap_ind_t; } s1ap_ue_cap_ind_t;
#define S1AP_ITTI_UE_PER_DEREGISTER_MESSAGE 20 #define S1AP_ITTI_UE_PER_DEREGISTER_MESSAGE 20
typedef struct s1ap_eNB_deregistered_ind_s { typedef struct s1ap_eNB_deregistered_ind_s {
uint8_t nb_ue_to_deregister; uint8_t nb_ue_to_deregister;
uint32_t mme_ue_s1ap_id[S1AP_ITTI_UE_PER_DEREGISTER_MESSAGE]; uint32_t mme_ue_s1ap_id[S1AP_ITTI_UE_PER_DEREGISTER_MESSAGE];
} s1ap_eNB_deregistered_ind_t; } s1ap_eNB_deregistered_ind_t;
typedef struct s1ap_deregister_ue_req_s { typedef struct s1ap_deregister_ue_req_s {
uint32_t mme_ue_s1ap_id; uint32_t mme_ue_s1ap_id;
} s1ap_deregister_ue_req_t; } s1ap_deregister_ue_req_t;
#endif /* S1AP_MESSAGES_TYPES_H_ */ #endif /* S1AP_MESSAGES_TYPES_H_ */
+37 -37
View File
@@ -33,62 +33,62 @@
typedef struct s6a_update_location_req_s { typedef struct s6a_update_location_req_s {
#define SKIP_SUBSCRIBER_DATA (0x1) #define SKIP_SUBSCRIBER_DATA (0x1)
unsigned skip_subscriber_data:1; unsigned skip_subscriber_data:1;
#define INITIAL_ATTACH (0x1) #define INITIAL_ATTACH (0x1)
unsigned initial_attach:1; unsigned initial_attach:1;
char imsi[IMSI_DIGITS_MAX + 1]; // username char imsi[IMSI_DIGITS_MAX + 1]; // username
uint8_t imsi_length; // username uint8_t imsi_length; // username
plmn_t visited_plmn; // visited plmn id plmn_t visited_plmn; // visited plmn id
rat_type_t rat_type; // rat type rat_type_t rat_type; // rat type
// missing // origin host // missing // origin host
// missing // origin realm // missing // origin realm
// missing // destination host // missing // destination host
// missing // destination realm // missing // destination realm
} s6a_update_location_req_t; } s6a_update_location_req_t;
typedef struct s6a_update_location_ans_s { typedef struct s6a_update_location_ans_s {
s6a_result_t result; // Result of the update location request procedure s6a_result_t result; // Result of the update location request procedure
subscription_data_t subscription_data; // subscriber status, subscription_data_t subscription_data; // subscriber status,
// Maximum Requested Bandwidth Uplink, downlink // Maximum Requested Bandwidth Uplink, downlink
// access restriction data // access restriction data
// msisdn // msisdn
apn_config_profile_t apn_config_profile;// APN configuration profile apn_config_profile_t apn_config_profile;// APN configuration profile
network_access_mode_t access_mode; network_access_mode_t access_mode;
rau_tau_timer_t rau_tau_timer; rau_tau_timer_t rau_tau_timer;
char imsi[IMSI_DIGITS_MAX + 1]; char imsi[IMSI_DIGITS_MAX + 1];
uint8_t imsi_length; uint8_t imsi_length;
} s6a_update_location_ans_t; } s6a_update_location_ans_t;
typedef struct s6a_auth_info_req_s { typedef struct s6a_auth_info_req_s {
char imsi[IMSI_DIGITS_MAX + 1]; char imsi[IMSI_DIGITS_MAX + 1];
uint8_t imsi_length; uint8_t imsi_length;
plmn_t visited_plmn; plmn_t visited_plmn;
/* Number of vectors to retrieve from HSS, should be equal to one */ /* Number of vectors to retrieve from HSS, should be equal to one */
uint8_t nb_of_vectors; uint8_t nb_of_vectors;
/* Bit to indicate that USIM has requested a re-synchronization of SQN */ /* Bit to indicate that USIM has requested a re-synchronization of SQN */
unsigned re_synchronization:1; unsigned re_synchronization:1;
/* AUTS to provide to AUC. /* AUTS to provide to AUC.
* Only present and interpreted if re_synchronization == 1. * Only present and interpreted if re_synchronization == 1.
*/ */
uint8_t auts[AUTS_LENGTH]; uint8_t auts[AUTS_LENGTH];
} s6a_auth_info_req_t; } s6a_auth_info_req_t;
typedef struct s6a_auth_info_ans_s { typedef struct s6a_auth_info_ans_s {
char imsi[IMSI_DIGITS_MAX + 1]; char imsi[IMSI_DIGITS_MAX + 1];
uint8_t imsi_length; uint8_t imsi_length;
/* Result of the authentication information procedure */ /* Result of the authentication information procedure */
s6a_result_t result; s6a_result_t result;
/* Authentication info containing the vector(s) */ /* Authentication info containing the vector(s) */
authentication_info_t auth_info; authentication_info_t auth_info;
} s6a_auth_info_ans_t; } s6a_auth_info_ans_t;
#endif /* S6A_MESSAGES_TYPES_H_ */ #endif /* S6A_MESSAGES_TYPES_H_ */
+24 -24
View File
@@ -35,42 +35,42 @@
#define SCTP_CLOSE_ASSOCIATION(mSGpTR) (mSGpTR)->ittiMsg.sctp_close_association #define SCTP_CLOSE_ASSOCIATION(mSGpTR) (mSGpTR)->ittiMsg.sctp_close_association
typedef struct sctp_data_req_s { typedef struct sctp_data_req_s {
uint8_t *buffer; uint8_t *buffer;
uint32_t bufLen; uint32_t bufLen;
uint32_t assocId; uint32_t assocId;
uint16_t stream; uint16_t stream;
} sctp_data_req_t; } sctp_data_req_t;
typedef struct sctp_data_ind_s { typedef struct sctp_data_ind_s {
uint8_t *buffer; ///< SCTP buffer uint8_t *buffer; ///< SCTP buffer
uint32_t buf_length; ///< SCTP buffer length uint32_t buf_length; ///< SCTP buffer length
int32_t assoc_id; ///< SCTP physical association ID int32_t assoc_id; ///< SCTP physical association ID
uint8_t stream; ///< Stream number on which data had been received 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 instreams; ///< Number of input streams for the SCTP connection between peers
uint16_t outstreams; ///< Number of output streams for the SCTP connection between peers uint16_t outstreams; ///< Number of output streams for the SCTP connection between peers
} sctp_data_ind_t; } sctp_data_ind_t;
typedef struct sctp_init_s { typedef struct sctp_init_s {
/* Request usage of ipv4 */ /* Request usage of ipv4 */
unsigned ipv4:1; unsigned ipv4:1;
/* Request usage of ipv6 */ /* Request usage of ipv6 */
unsigned ipv6:1; unsigned ipv6:1;
uint8_t nb_ipv4_addr; uint8_t nb_ipv4_addr;
uint32_t ipv4_address[10]; uint32_t ipv4_address[10];
uint8_t nb_ipv6_addr; uint8_t nb_ipv6_addr;
char *ipv6_address[10]; char *ipv6_address[10];
uint16_t port; uint16_t port;
uint32_t ppid; uint32_t ppid;
} SctpInit; } SctpInit;
typedef struct sctp_close_association_s { typedef struct sctp_close_association_s {
uint32_t assoc_id; uint32_t assoc_id;
} sctp_close_association_t; } sctp_close_association_t;
typedef struct sctp_new_peer_s { typedef struct sctp_new_peer_s {
uint32_t instreams; uint32_t instreams;
uint32_t outstreams; uint32_t outstreams;
uint32_t assoc_id; uint32_t assoc_id;
} sctp_new_peer_t; } sctp_new_peer_t;
#endif /* SCTP_MESSAGES_TYPES_H_ */ #endif /* SCTP_MESSAGES_TYPES_H_ */
+14 -14
View File
@@ -92,8 +92,8 @@ do { \
/* RES amd XRES can have a variable length of 4-16 octets */ /* RES amd XRES can have a variable length of 4-16 octets */
typedef struct { typedef struct {
uint8_t size; uint8_t size;
uint8_t data[XRES_LENGTH_MAX]; uint8_t data[XRES_LENGTH_MAX];
} res_t; } res_t;
#define FORMAT_128BITS "%02x,%02x,%02x,%02x,%02x,%02x,%02x,%02x,%02x,%02x,%02x,%02x,%02x,%02x,%02x,%02x" #define FORMAT_128BITS "%02x,%02x,%02x,%02x,%02x,%02x,%02x,%02x,%02x,%02x,%02x,%02x,%02x,%02x,%02x,%02x"
@@ -116,14 +116,14 @@ bUFFER[24], bUFFER[25], bUFFER[26], bUFFER[27], bUFFER[28], bUFFER[29], bUFFER[3
/* Holds an E-UTRAN authentication vector */ /* Holds an E-UTRAN authentication vector */
typedef struct eutran_vector_s { typedef struct eutran_vector_s {
uint8_t rand[RAND_LENGTH_OCTETS]; uint8_t rand[RAND_LENGTH_OCTETS];
res_t xres; res_t xres;
uint8_t autn[AUTN_LENGTH_OCTETS]; uint8_t autn[AUTN_LENGTH_OCTETS];
uint8_t kasme[KASME_LENGTH_OCTETS]; uint8_t kasme[KASME_LENGTH_OCTETS];
/* one UE can have multiple vectors so use STAILQ lists for easy management */ /* one UE can have multiple vectors so use STAILQ lists for easy management */
#if 0 #if 0
STAILQ_ENTRY(eutran_vector_s) entries; STAILQ_ENTRY(eutran_vector_s) entries;
#endif #endif
} eutran_vector_t; } eutran_vector_t;
@@ -143,12 +143,12 @@ typedef struct eutran_vector_s {
#define FC_KASME_TO_CK (0x16) #define FC_KASME_TO_CK (0x16)
typedef enum { typedef enum {
NAS_ENC_ALG = 0x01, NAS_ENC_ALG = 0x01,
NAS_INT_ALG = 0x02, NAS_INT_ALG = 0x02,
RRC_ENC_ALG = 0x03, RRC_ENC_ALG = 0x03,
RRC_INT_ALG = 0x04, RRC_INT_ALG = 0x04,
UP_ENC_ALG = 0x05, UP_ENC_ALG = 0x05,
UP_INT_ALG = 0x06 UP_INT_ALG = 0x06
} algorithm_type_dist_t; } algorithm_type_dist_t;
#endif /* SECURITY_TYPES_H_ */ #endif /* SECURITY_TYPES_H_ */
File diff suppressed because it is too large Load Diff
+11 -11
View File
@@ -32,23 +32,23 @@
#define UDP_INIT(mSGpTR) (mSGpTR)->ittiMsg.udp_init #define UDP_INIT(mSGpTR) (mSGpTR)->ittiMsg.udp_init
typedef struct { typedef struct {
uint32_t port; uint32_t port;
char *address; char *address;
} udp_init_t; } udp_init_t;
typedef struct { typedef struct {
uint8_t *buffer; uint8_t *buffer;
uint32_t buffer_length; uint32_t buffer_length;
uint32_t buffer_offset; uint32_t buffer_offset;
uint32_t peer_address; uint32_t peer_address;
uint32_t peer_port; uint32_t peer_port;
} udp_data_req_t; } udp_data_req_t;
typedef struct { typedef struct {
uint8_t *buffer; uint8_t *buffer;
uint32_t buffer_length; uint32_t buffer_length;
uint32_t peer_address; uint32_t peer_address;
uint32_t peer_port; uint32_t peer_port;
} udp_data_ind_t; } udp_data_ind_t;
#endif /* UDP_MESSAGES_TYPES_H_ */ #endif /* UDP_MESSAGES_TYPES_H_ */
+184 -184
View File
@@ -33,7 +33,7 @@
#define XT_GTPUAH_VERSION IPTABLES_VERSION_STRING #define XT_GTPUAH_VERSION IPTABLES_VERSION_STRING
#define gtpuah_strtoui(s,v,m,M) !string_to_number(s,m,M,v) #define gtpuah_strtoui(s,v,m,M) !string_to_number(s,m,M,v)
#define gtpuah_exit_error exit_error #define gtpuah_exit_error exit_error
#elif (IPTVERSION > 135) && (IPTVERSION <= 141) #elif (IPTVERSION > 135) && (IPTVERSION <= 141)
#define GTPUAH_PARAM_BAD_VALUE P_BAD_VALUE #define GTPUAH_PARAM_BAD_VALUE P_BAD_VALUE
#define GTPUAH_PARAM_ONLY_ONCE P_ONLY_ONCE #define GTPUAH_PARAM_ONLY_ONCE P_ONLY_ONCE
#define XT_GTPUAH_VERSION XTABLES_VERSION #define XT_GTPUAH_VERSION XTABLES_VERSION
@@ -50,246 +50,246 @@
#endif #endif
enum { enum {
PARAM_LADDR = 1 << 0, PARAM_LADDR = 1 << 0,
PARAM_LTUN = 1 << 1, PARAM_LTUN = 1 << 1,
PARAM_RADDR = 1 << 2, PARAM_RADDR = 1 << 2,
PARAM_RTUN = 1 << 3, PARAM_RTUN = 1 << 3,
PARAM_ACTION = 1 << 4, PARAM_ACTION = 1 << 4,
}; };
static void GTPUAH_help(void) static void GTPUAH_help(void)
{ {
printf( printf(
"GTPUAH target options\n" "GTPUAH target options\n"
" --action value Set action <value: add>\n" " --action value Set action <value: add>\n"
" --own-ip value Set own IP address\n" " --own-ip value Set own IP address\n"
" --own-tun value Set own tunnel id <value: 1-2^31>\n" " --own-tun value Set own tunnel id <value: 1-2^31>\n"
" --peer-ip value Set peer IP address\n" " --peer-ip value Set peer IP address\n"
" --peer-tun value Set peer tunnel id <value: 1-2^31>\n"); " --peer-tun value Set peer tunnel id <value: 1-2^31>\n");
} }
#if (IPTVERSION <= 135) #if (IPTVERSION <= 135)
/* Stolen from iptables v1.4.7 code */ /* Stolen from iptables v1.4.7 code */
void gtpuah_param_act(unsigned int status, const char *p1, ...) void gtpuah_param_act(unsigned int status, const char *p1, ...)
{ {
const char *p2, *p3; const char *p2, *p3;
va_list args; va_list args;
int b; int b;
va_start(args, p1); va_start(args, p1);
switch (status) { switch (status) {
case GTPUAH_PARAM_ONLY_ONCE: case GTPUAH_PARAM_ONLY_ONCE:
p2 = va_arg(args, const char *); p2 = va_arg(args, const char *);
b = va_arg(args, unsigned int); b = va_arg(args, unsigned int);
if (!b)
return;
exit_error(PARAMETER_PROBLEM,
"%s: \"%s\" option may only be specified once",
p1, p2);
break;
case GTPUAH_PARAM_BAD_VALUE:
p2 = va_arg(args, const char *);
p3 = va_arg(args, const char *);
exit_error(PARAMETER_PROBLEM,
"%s: Bad value for \"%s\" option: \"%s\"",
p1, p2, p3);
break;
default:
exit_error(status, "%s", "Unknown error");
break;
}
va_end(args); if (!b)
return;
exit_error(PARAMETER_PROBLEM,
"%s: \"%s\" option may only be specified once",
p1, p2);
break;
case GTPUAH_PARAM_BAD_VALUE:
p2 = va_arg(args, const char *);
p3 = va_arg(args, const char *);
exit_error(PARAMETER_PROBLEM,
"%s: Bad value for \"%s\" option: \"%s\"",
p1, p2, p3);
break;
default:
exit_error(status, "%s", "Unknown error");
break;
}
va_end(args);
} }
#endif #endif
static void parse_gtpuah_addr(const char *s, struct xt_gtpuah_target_info *info, int flag) static void parse_gtpuah_addr(const char *s, struct xt_gtpuah_target_info *info, int flag)
{ {
in_addr_t addr; in_addr_t addr;
if ((addr = inet_addr(s)) == -1) if ((addr = inet_addr(s)) == -1) {
{ switch (flag) {
switch (flag) case PARAM_LADDR:
{ gtpuah_param_act(GTPUAH_PARAM_BAD_VALUE, "GTPUAH", "--own-ip", s);
case PARAM_LADDR: break;
gtpuah_param_act(GTPUAH_PARAM_BAD_VALUE, "GTPUAH", "--own-ip", s);
break; case PARAM_RADDR:
case PARAM_RADDR: gtpuah_param_act(GTPUAH_PARAM_BAD_VALUE, "GTPUAH", "--peer-ip", s);
gtpuah_param_act(GTPUAH_PARAM_BAD_VALUE, "GTPUAH", "--peer-ip", s); break;
break;
}
}
switch (flag)
{
case PARAM_LADDR:
info->laddr = addr;
break;
case PARAM_RADDR:
info->raddr = addr;
break;
} }
}
switch (flag) {
case PARAM_LADDR:
info->laddr = addr;
break;
case PARAM_RADDR:
info->raddr = addr;
break;
}
} }
static void parse_gtpuah_tunid(char *s, struct xt_gtpuah_target_info *info, int flag) static void parse_gtpuah_tunid(char *s, struct xt_gtpuah_target_info *info, int flag)
{ {
unsigned int value; unsigned int value;
if (!gtpuah_strtoui(s, &value, 0, UINT32_MAX)) if (!gtpuah_strtoui(s, &value, 0, UINT32_MAX)) {
{ switch (flag) {
switch (flag) case PARAM_LTUN:
{ gtpuah_param_act(GTPUAH_PARAM_BAD_VALUE, "GTPUAH", "--own-tun", s);
case PARAM_LTUN: break;
gtpuah_param_act(GTPUAH_PARAM_BAD_VALUE, "GTPUAH", "--own-tun", s);
break;
case PARAM_RTUN:
gtpuah_param_act(GTPUAH_PARAM_BAD_VALUE, "GTPUAH", "--peer-tun", s);
break;
}
}
switch (flag) case PARAM_RTUN:
{ gtpuah_param_act(GTPUAH_PARAM_BAD_VALUE, "GTPUAH", "--peer-tun", s);
case PARAM_LTUN: break;
info->ltun = value;
break;
case PARAM_RTUN:
info->rtun = value;
break;
} }
}
switch (flag) {
case PARAM_LTUN:
info->ltun = value;
break;
case PARAM_RTUN:
info->rtun = value;
break;
}
} }
static void parse_gtpuah_action(char *s, struct xt_gtpuah_target_info *info, unsigned int *flags) static void parse_gtpuah_action(char *s, struct xt_gtpuah_target_info *info, unsigned int *flags)
{ {
if (!strcmp(s, "add")) if (!strcmp(s, "add")) {
{ info->action = PARAM_GTPUAH_ACTION_ADD;
info->action = PARAM_GTPUAH_ACTION_ADD; *flags |= PARAM_GTPUAH_ACTION_ADD;
*flags |= PARAM_GTPUAH_ACTION_ADD; } else {
} gtpuah_param_act(GTPUAH_PARAM_BAD_VALUE, "GTPUAH", "--action", s);
else }
{
gtpuah_param_act(GTPUAH_PARAM_BAD_VALUE, "GTPUAH", "--action", s);
}
} }
#if (IPTVERSION <= 135) #if (IPTVERSION <= 135)
static int static int
GTPUAH_parse(int c, char **argv, int invert, unsigned int *flags, GTPUAH_parse(int c, char **argv, int invert, unsigned int *flags,
const struct ipt_entry *entry, const struct ipt_entry *entry,
struct ipt_entry_target **target) struct ipt_entry_target **target)
#else #else
static int static int
GTPUAH_parse(int c, char **argv, int invert, unsigned int *flags, GTPUAH_parse(int c, char **argv, int invert, unsigned int *flags,
const void *entry, struct xt_entry_target **target) const void *entry, struct xt_entry_target **target)
#endif #endif
{ {
struct xt_gtpuah_target_info *info = (struct xt_gtpuah_target_info *) (*target)->data; struct xt_gtpuah_target_info *info = (struct xt_gtpuah_target_info *) (*target)->data;
switch (c)
{
case '1':
gtpuah_param_act(GTPUAH_PARAM_ONLY_ONCE, "GTPUAH", "--own-ip", *flags & PARAM_LADDR);
parse_gtpuah_addr(optarg, info, PARAM_LADDR);
*flags |= PARAM_LADDR;
return 1;
case '2':
gtpuah_param_act(GTPUAH_PARAM_ONLY_ONCE, "GTPUAH", "--own-tun", *flags & PARAM_LTUN);
parse_gtpuah_tunid(optarg, info, PARAM_LTUN);
*flags |= PARAM_LTUN;
return 1;
case '3':
gtpuah_param_act(GTPUAH_PARAM_ONLY_ONCE, "GTPUAH", "--peer-ip", *flags & PARAM_RADDR);
parse_gtpuah_addr(optarg, info, PARAM_RADDR);
*flags |= PARAM_RADDR;
return 1;
case '4':
gtpuah_param_act(GTPUAH_PARAM_ONLY_ONCE, "GTPUAH", "--peer-tun", *flags & PARAM_RTUN);
parse_gtpuah_tunid(optarg, info, PARAM_RTUN);
*flags |= PARAM_RTUN;
return 1;
case '5':
gtpuah_param_act(GTPUAH_PARAM_ONLY_ONCE, "GTPUAH", "--action", *flags & PARAM_ACTION);
parse_gtpuah_action(optarg, info, flags);
*flags |= PARAM_ACTION;
return 1;
}
switch (c) {
case '1':
gtpuah_param_act(GTPUAH_PARAM_ONLY_ONCE, "GTPUAH", "--own-ip", *flags & PARAM_LADDR);
parse_gtpuah_addr(optarg, info, PARAM_LADDR);
*flags |= PARAM_LADDR;
return 1; return 1;
case '2':
gtpuah_param_act(GTPUAH_PARAM_ONLY_ONCE, "GTPUAH", "--own-tun", *flags & PARAM_LTUN);
parse_gtpuah_tunid(optarg, info, PARAM_LTUN);
*flags |= PARAM_LTUN;
return 1;
case '3':
gtpuah_param_act(GTPUAH_PARAM_ONLY_ONCE, "GTPUAH", "--peer-ip", *flags & PARAM_RADDR);
parse_gtpuah_addr(optarg, info, PARAM_RADDR);
*flags |= PARAM_RADDR;
return 1;
case '4':
gtpuah_param_act(GTPUAH_PARAM_ONLY_ONCE, "GTPUAH", "--peer-tun", *flags & PARAM_RTUN);
parse_gtpuah_tunid(optarg, info, PARAM_RTUN);
*flags |= PARAM_RTUN;
return 1;
case '5':
gtpuah_param_act(GTPUAH_PARAM_ONLY_ONCE, "GTPUAH", "--action", *flags & PARAM_ACTION);
parse_gtpuah_action(optarg, info, flags);
*flags |= PARAM_ACTION;
return 1;
}
return 1;
} }
static void GTPUAH_check(unsigned int flags) static void GTPUAH_check(unsigned int flags)
{ {
if (!(flags & PARAM_ACTION)) if (!(flags & PARAM_ACTION)) {
{ gtpuah_exit_error(PARAMETER_PROBLEM, "GTPUAH: You must specify action");
gtpuah_exit_error(PARAMETER_PROBLEM, "GTPUAH: You must specify action"); }
}
if (!(flags & PARAM_LADDR)) {
if (!(flags & PARAM_LADDR)) gtpuah_exit_error(PARAMETER_PROBLEM, "GTPUAH: You must specify local addr");
{ }
gtpuah_exit_error(PARAMETER_PROBLEM, "GTPUAH: You must specify local addr");
} if (!(flags & PARAM_LTUN)) {
if (!(flags & PARAM_LTUN)) gtpuah_exit_error(PARAMETER_PROBLEM, "GTPUAH: You must specify local tunnel id");
{ }
gtpuah_exit_error(PARAMETER_PROBLEM, "GTPUAH: You must specify local tunnel id");
} if (!(flags & PARAM_RADDR)) {
if (!(flags & PARAM_RADDR)) gtpuah_exit_error(PARAMETER_PROBLEM, "GTPUAH: You must specify remote addr");
{ }
gtpuah_exit_error(PARAMETER_PROBLEM, "GTPUAH: You must specify remote addr");
} if (!(flags & PARAM_RTUN)) {
if (!(flags & PARAM_RTUN)) gtpuah_exit_error(PARAMETER_PROBLEM, "GTPUAH: You must specify remote tunnel id");
{ }
gtpuah_exit_error(PARAMETER_PROBLEM, "GTPUAH: You must specify remote tunnel id");
}
} }
static void convert_action_to_string(int action, char *actionstr) static void convert_action_to_string(int action, char *actionstr)
{ {
switch(action) switch(action) {
{ case PARAM_GTPUAH_ACTION_ADD:
case PARAM_GTPUAH_ACTION_ADD: sprintf (actionstr, "add");
sprintf (actionstr, "add"); break;
break;
default : default :
sprintf (actionstr, "unspecified!!!"); sprintf (actionstr, "unspecified!!!");
break; break;
} }
} }
#if (IPTVERSION <= 135) #if (IPTVERSION <= 135)
static void static void
GTPUAH_print(const struct ipt_ip *ip, GTPUAH_print(const struct ipt_ip *ip,
const struct ipt_entry_target *target, const struct ipt_entry_target *target,
int numeric) int numeric)
#else #else
static void static void
GTPUAH_print(const void *ip, GTPUAH_print(const void *ip,
const struct xt_entry_target *target, const struct xt_entry_target *target,
int numeric) int numeric)
#endif #endif
{ {
const struct xt_gtpuah_target_info *info = const struct xt_gtpuah_target_info *info =
(struct xt_gtpuah_target_info *) target->data; (struct xt_gtpuah_target_info *) target->data;
char laddr[64], raddr[64], actionstr[32]; char laddr[64], raddr[64], actionstr[32];
convert_action_to_string(info->action, actionstr); convert_action_to_string(info->action, actionstr);
sprintf (laddr, "%s", inet_ntoa(*(struct in_addr*)&info->laddr)); sprintf (laddr, "%s", inet_ntoa(*(struct in_addr*)&info->laddr));
sprintf (raddr, "%s", inet_ntoa(*(struct in_addr*)&info->raddr)); sprintf (raddr, "%s", inet_ntoa(*(struct in_addr*)&info->raddr));
printf("GTPUAH self: %s tunnel: 0x%x / peer: %s tunnel: 0x%x / action: %s", printf("GTPUAH self: %s tunnel: 0x%x / peer: %s tunnel: 0x%x / action: %s",
laddr, info->ltun, raddr, info->rtun, actionstr); laddr, info->ltun, raddr, info->rtun, actionstr);
} }
static struct option GTPUAH_opts[] = { static struct option GTPUAH_opts[] = {
{ "own-ip", 1, NULL, '1' }, { "own-ip", 1, NULL, '1' },
{ "own-tun", 1, NULL, '2' }, { "own-tun", 1, NULL, '2' },
{ "peer-ip", 1, NULL, '3' }, { "peer-ip", 1, NULL, '3' },
{ "peer-tun", 1, NULL, '4' }, { "peer-tun", 1, NULL, '4' },
{ "action", 1, NULL, '5' }, { "action", 1, NULL, '5' },
{ .name = NULL } { .name = NULL }
}; };
#if (IPTVERSION <= 135) #if (IPTVERSION <= 135)
@@ -297,26 +297,26 @@ static struct iptables_target gtpuah_tg_reg = {
#else #else
static struct xtables_target gtpuah_tg_reg = { static struct xtables_target gtpuah_tg_reg = {
#endif #endif
.name = "GTPUAH", .name = "GTPUAH",
.version = XT_GTPUAH_VERSION, .version = XT_GTPUAH_VERSION,
#if (IPTVERSION > 135) #if (IPTVERSION > 135)
.family = NFPROTO_IPV4, .family = NFPROTO_IPV4,
#endif #endif
.size = XT_ALIGN(sizeof(struct xt_gtpuah_target_info)), .size = XT_ALIGN(sizeof(struct xt_gtpuah_target_info)),
.userspacesize = XT_ALIGN(sizeof(struct xt_gtpuah_target_info)), .userspacesize = XT_ALIGN(sizeof(struct xt_gtpuah_target_info)),
.help = GTPUAH_help, .help = GTPUAH_help,
.parse = GTPUAH_parse, .parse = GTPUAH_parse,
.final_check = GTPUAH_check, .final_check = GTPUAH_check,
.print = GTPUAH_print, .print = GTPUAH_print,
.extra_opts = GTPUAH_opts, .extra_opts = GTPUAH_opts,
}; };
void _init(void) void _init(void)
{ {
#if (IPTVERSION <= 135) #if (IPTVERSION <= 135)
register_target(&gtpuah_tg_reg); register_target(&gtpuah_tg_reg);
#else #else
xtables_register_target(&gtpuah_tg_reg); xtables_register_target(&gtpuah_tg_reg);
#endif #endif
} }
+316 -264
View File
@@ -16,13 +16,13 @@
#include <linux/skbuff.h> #include <linux/skbuff.h>
#include <linux/ip.h> #include <linux/ip.h>
#include <linux/if_ether.h> #include <linux/if_ether.h>
#include <linux/route.h> #include <linux/route.h>
#include <linux/time.h> #include <linux/time.h>
#include <net/checksum.h> #include <net/checksum.h>
#include <net/ip.h> #include <net/ip.h>
#include <net/udp.h> #include <net/udp.h>
#include <net/inet_sock.h> #include <net/inet_sock.h>
#include <net/route.h> #include <net/route.h>
#include <net/addrconf.h> #include <net/addrconf.h>
#include <net/ip6_checksum.h> #include <net/ip6_checksum.h>
#include <net/ip6_route.h> #include <net/ip6_route.h>
@@ -57,37 +57,37 @@ static int __init gtpuah_tg_init(void);
static void __exit gtpuah_tg_exit(void); static void __exit gtpuah_tg_exit(void);
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
static struct xt_target gtpuah_tg_reg[] __read_mostly = { static struct xt_target gtpuah_tg_reg[] __read_mostly = {
{ {
.name = "GTPUAH", .name = "GTPUAH",
.revision = 0, .revision = 0,
.family = NFPROTO_IPV4, .family = NFPROTO_IPV4,
.hooks = (1 << NF_INET_POST_ROUTING) | .hooks = (1 << NF_INET_POST_ROUTING) |
(1 << NF_INET_LOCAL_IN), (1 << NF_INET_LOCAL_IN),
.table = "mangle", .table = "mangle",
.target = gtpuah_tg4, .target = gtpuah_tg4,
.targetsize = sizeof(struct xt_gtpuah_target_info), .targetsize = sizeof(struct xt_gtpuah_target_info),
.me = THIS_MODULE, .me = THIS_MODULE,
}, },
#ifdef WITH_IPV6 #ifdef WITH_IPV6
{ {
.name = "GTPUAH", .name = "GTPUAH",
.revision = 0, .revision = 0,
.family = NFPROTO_IPV6, .family = NFPROTO_IPV6,
.hooks = (1 << NF_INET_POST_ROUTING) | .hooks = (1 << NF_INET_POST_ROUTING) |
(1 << NF_INET_LOCAL_IN), (1 << NF_INET_LOCAL_IN),
.table = "mangle", .table = "mangle",
.target = gtpuah_tg6, .target = gtpuah_tg6,
.targetsize = sizeof(struct xt_gtpuah_target_info), .targetsize = sizeof(struct xt_gtpuah_target_info),
.me = THIS_MODULE, .me = THIS_MODULE,
}, },
#endif #endif
}; };
struct gtpuhdr { struct gtpuhdr {
char flags; char flags;
char msgtype; char msgtype;
u_int16_t length; u_int16_t length;
u_int32_t tunid; u_int32_t tunid;
}; };
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@@ -116,21 +116,39 @@ INT_MODULE_PARM(mtu, 1564);
MODULE_PARM_DESC(mtu, "MTU of the S1U IP interface"); MODULE_PARM_DESC(mtu, "MTU of the S1U IP interface");
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
static char* static char*
_gtpuah_nf_inet_hook_2_string(int nf_inet_hookP) { _gtpuah_nf_inet_hook_2_string(int nf_inet_hookP)
//----------------------------------------------------------------------------- {
switch (nf_inet_hookP) { //-----------------------------------------------------------------------------
case NF_INET_PRE_ROUTING: return "NF_INET_PRE_ROUTING";break; switch (nf_inet_hookP) {
case NF_INET_LOCAL_IN: return "NF_INET_LOCAL_IN";break; case NF_INET_PRE_ROUTING:
case NF_INET_FORWARD: return "NF_INET_FORWARD";break; return "NF_INET_PRE_ROUTING";
case NF_INET_LOCAL_OUT: return "NF_INET_LOCAL_OUT";break; break;
case NF_INET_POST_ROUTING: return "NF_INET_POST_ROUTING";break;
default: return "NF_INET_UNKNOWN"; case NF_INET_LOCAL_IN:
} return "NF_INET_LOCAL_IN";
break;
case NF_INET_FORWARD:
return "NF_INET_FORWARD";
break;
case NF_INET_LOCAL_OUT:
return "NF_INET_LOCAL_OUT";
break;
case NF_INET_POST_ROUTING:
return "NF_INET_POST_ROUTING";
break;
default:
return "NF_INET_UNKNOWN";
}
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void void
_gtpuah_print_hex_octets(unsigned char* data_pP, unsigned short sizeP) { _gtpuah_print_hex_octets(unsigned char* data_pP, unsigned short sizeP)
//----------------------------------------------------------------------------- {
//-----------------------------------------------------------------------------
unsigned long octet_index = 0; unsigned long octet_index = 0;
unsigned long buffer_marker = 0; unsigned long buffer_marker = 0;
@@ -142,8 +160,9 @@ _gtpuah_print_hex_octets(unsigned char* data_pP, unsigned short sizeP) {
if (data_pP == NULL) { if (data_pP == NULL) {
return; return;
} }
if (sizeP > 2000) { if (sizeP > 2000) {
return; return;
} }
do_gettimeofday(&tv); do_gettimeofday(&tv);
@@ -155,15 +174,20 @@ _gtpuah_print_hex_octets(unsigned char* data_pP, unsigned short sizeP) {
buffer_marker+=snprintf(&_gtpuah_print_buffer[buffer_marker], GTPUAH_2_PRINT_BUFFER_LEN - buffer_marker,"%s------+-------------------------------------------------+\n",timeofday); buffer_marker+=snprintf(&_gtpuah_print_buffer[buffer_marker], GTPUAH_2_PRINT_BUFFER_LEN - buffer_marker,"%s------+-------------------------------------------------+\n",timeofday);
buffer_marker+=snprintf(&_gtpuah_print_buffer[buffer_marker], GTPUAH_2_PRINT_BUFFER_LEN - buffer_marker,"%s | 0 1 2 3 4 5 6 7 8 9 a b c d e f |\n",timeofday); buffer_marker+=snprintf(&_gtpuah_print_buffer[buffer_marker], GTPUAH_2_PRINT_BUFFER_LEN - buffer_marker,"%s | 0 1 2 3 4 5 6 7 8 9 a b c d e f |\n",timeofday);
buffer_marker+=snprintf(&_gtpuah_print_buffer[buffer_marker], GTPUAH_2_PRINT_BUFFER_LEN - buffer_marker,"%s------+-------------------------------------------------+\n",timeofday); buffer_marker+=snprintf(&_gtpuah_print_buffer[buffer_marker], GTPUAH_2_PRINT_BUFFER_LEN - buffer_marker,"%s------+-------------------------------------------------+\n",timeofday);
pr_info("%s",_gtpuah_print_buffer);buffer_marker = 0; pr_info("%s",_gtpuah_print_buffer);
buffer_marker = 0;
for (octet_index = 0; octet_index < sizeP; octet_index++) { for (octet_index = 0; octet_index < sizeP; octet_index++) {
if ((octet_index % 16) == 0){ if ((octet_index % 16) == 0) {
if (octet_index != 0) { if (octet_index != 0) {
buffer_marker+=snprintf(&_gtpuah_print_buffer[buffer_marker], GTPUAH_2_PRINT_BUFFER_LEN - buffer_marker, " |\n"); buffer_marker+=snprintf(&_gtpuah_print_buffer[buffer_marker], GTPUAH_2_PRINT_BUFFER_LEN - buffer_marker, " |\n");
pr_info("%s",_gtpuah_print_buffer);buffer_marker = 0; pr_info("%s",_gtpuah_print_buffer);
buffer_marker = 0;
} }
buffer_marker+=snprintf(&_gtpuah_print_buffer[buffer_marker], GTPUAH_2_PRINT_BUFFER_LEN - buffer_marker, "%s %04ld |",timeofday, octet_index); buffer_marker+=snprintf(&_gtpuah_print_buffer[buffer_marker], GTPUAH_2_PRINT_BUFFER_LEN - buffer_marker, "%s %04ld |",timeofday, octet_index);
} }
/* /*
* Print every single octet in hexadecimal form * Print every single octet in hexadecimal form
*/ */
@@ -178,7 +202,8 @@ _gtpuah_print_hex_octets(unsigned char* data_pP, unsigned short sizeP) {
*/ */
for (aindex = octet_index; aindex < 16; ++aindex) for (aindex = octet_index; aindex < 16; ++aindex)
buffer_marker+=snprintf(&_gtpuah_print_buffer[buffer_marker], GTPUAH_2_PRINT_BUFFER_LEN - buffer_marker, " "); buffer_marker+=snprintf(&_gtpuah_print_buffer[buffer_marker], GTPUAH_2_PRINT_BUFFER_LEN - buffer_marker, " ");
//SGI_IF_DEBUG(" ");
//SGI_IF_DEBUG(" ");
buffer_marker+=snprintf(&_gtpuah_print_buffer[buffer_marker], GTPUAH_2_PRINT_BUFFER_LEN - buffer_marker, " |\n"); buffer_marker+=snprintf(&_gtpuah_print_buffer[buffer_marker], GTPUAH_2_PRINT_BUFFER_LEN - buffer_marker, " |\n");
pr_info("%s",_gtpuah_print_buffer); pr_info("%s",_gtpuah_print_buffer);
} }
@@ -186,275 +211,302 @@ _gtpuah_print_hex_octets(unsigned char* data_pP, unsigned short sizeP) {
#ifdef WITH_IPV6 #ifdef WITH_IPV6
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
static void static void
_gtpuah_tg6_add(struct sk_buff *old_skb_pP, const struct xt_action_param *par_pP) { _gtpuah_tg6_add(struct sk_buff *old_skb_pP, const struct xt_action_param *par_pP)
//----------------------------------------------------------------------------- {
//-----------------------------------------------------------------------------
} }
#endif #endif
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
static void static void
_gtpuah_tg4_add(struct sk_buff *old_skb_pP, const struct xt_action_param *par_pP) { _gtpuah_tg4_add(struct sk_buff *old_skb_pP, const struct xt_action_param *par_pP)
//----------------------------------------------------------------------------- {
struct rtable *rt = NULL; //-----------------------------------------------------------------------------
struct ethhdr *ethhdr_p = NULL; struct rtable *rt = NULL;
struct iphdr *old_iph_p = ip_hdr(old_skb_pP); struct ethhdr *ethhdr_p = NULL;
struct iphdr *new_iph_p = NULL; struct iphdr *old_iph_p = ip_hdr(old_skb_pP);
struct iphdr *tmp_iph_p = NULL; struct iphdr *new_iph_p = NULL;
struct udphdr *udph_p = NULL; struct iphdr *tmp_iph_p = NULL;
struct gtpuhdr *gtpuh_p = NULL; struct udphdr *udph_p = NULL;
struct sk_buff *new_skb_p = NULL; struct gtpuhdr *gtpuh_p = NULL;
const uint16_t headroom_reqd = ETH_HLEN + sizeof(struct iphdr) + sizeof(struct udphdr) + sizeof(struct gtpuhdr); struct sk_buff *new_skb_p = NULL;
uint16_t orig_iplen = 0, udp_len = 0, ip_len = 0; const uint16_t headroom_reqd = ETH_HLEN + sizeof(struct iphdr) + sizeof(struct udphdr) + sizeof(struct gtpuhdr);
int flags = 0, offset = 0; uint16_t orig_iplen = 0, udp_len = 0, ip_len = 0;
unsigned int addr_type = RTN_UNSPEC; int flags = 0, offset = 0;
unsigned int addr_type = RTN_UNSPEC;
if (ip_is_fragment(ip_hdr(old_skb_pP))) { if (ip_is_fragment(ip_hdr(old_skb_pP))) {
pr_info("GTPUAH: IP fragment, dropped\n"); pr_info("GTPUAH: IP fragment, dropped\n");
return; return;
}
if (skb_linearize(old_skb_pP) < 0) {
pr_info("GTPUAH: skb no linearize\n");
return;
}
if (old_skb_pP->mark == 0) {
pr_info("GTPUAH: _gtpuah_target_add force info_pP mark %u to skb_pP mark %u\n",
old_skb_pP->mark,
((const struct xt_gtpuah_target_info *)(par_pP->targinfo))->rtun);
old_skb_pP->mark = ((const struct xt_gtpuah_target_info *)(par_pP->targinfo))->rtun;
}
/* Keep the length of the source IP packet */
orig_iplen = ntohs(old_iph_p->tot_len);
offset = ntohs(old_iph_p->frag_off);
flags = offset & ~IP_OFFSET;
/* Create a new copy of the original skb...can't avoid :-( */
if ((orig_iplen + headroom_reqd) <= mtu) {
new_skb_p = alloc_skb(headroom_reqd + orig_iplen, GFP_ATOMIC);
if (new_skb_p == NULL) {
pr_info("GTPUAH: alloc_skb returned NULL\n");
return;
} }
if (skb_linearize(old_skb_pP) < 0) {
pr_info("GTPUAH: skb no linearize\n"); if (skb_linearize(new_skb_p) < 0) {
return; pr_info("GTPUAH: skb no linearize\n");
goto free_new_skb;
} }
if (old_skb_pP->mark == 0) {
pr_info("GTPUAH: _gtpuah_target_add force info_pP mark %u to skb_pP mark %u\n",
old_skb_pP->mark,
((const struct xt_gtpuah_target_info *)(par_pP->targinfo))->rtun);
old_skb_pP->mark = ((const struct xt_gtpuah_target_info *)(par_pP->targinfo))->rtun;
}
/* Keep the length of the source IP packet */
orig_iplen = ntohs(old_iph_p->tot_len);
offset = ntohs(old_iph_p->frag_off);
flags = offset & ~IP_OFFSET;
skb_reserve(new_skb_p, headroom_reqd + orig_iplen);
tmp_iph_p = (void *)skb_push(new_skb_p, orig_iplen);
memcpy(tmp_iph_p, old_iph_p, orig_iplen);
/* Create a new copy of the original skb...can't avoid :-( */ /* Add GTPu header */
if ((orig_iplen + headroom_reqd) <= mtu) { gtpuh_p = (struct gtpuhdr*)skb_push(new_skb_p, sizeof(struct gtpuhdr));
gtpuh_p->flags = 0x30; /* v1 and Protocol-type=GTP */
gtpuh_p->msgtype = 0xff; /* T-PDU */
gtpuh_p->length = htons(orig_iplen);
gtpuh_p->tunid = htonl(old_skb_pP->mark);
new_skb_p = alloc_skb(headroom_reqd + orig_iplen, GFP_ATOMIC); /* Add UDP header */
if (new_skb_p == NULL) { udp_len = sizeof(struct udphdr) + sizeof(struct gtpuhdr) + orig_iplen;
pr_info("GTPUAH: alloc_skb returned NULL\n"); udph_p = (struct udphdr*)skb_push(new_skb_p, sizeof(struct udphdr));
return; udph_p->source = htons(gtpu_port);
} udph_p->dest = htons(gtpu_port);
if (skb_linearize(new_skb_p) < 0) { udph_p->len = htons(udp_len);
pr_info("GTPUAH: skb no linearize\n"); udph_p->check = 0;
goto free_new_skb; udph_p->check = csum_tcpudp_magic(((const struct xt_gtpuah_target_info *)(par_pP->targinfo))->laddr,
} ((const struct xt_gtpuah_target_info *)(par_pP->targinfo))->raddr,
skb_reserve(new_skb_p, headroom_reqd + orig_iplen); udp_len,
tmp_iph_p = (void *)skb_push(new_skb_p, orig_iplen); IPPROTO_UDP,
memcpy(tmp_iph_p, old_iph_p, orig_iplen); csum_partial((char*)udph_p, udp_len, 0));
skb_set_transport_header(new_skb_p, 0);
/* Add GTPu header */ /* Add IP header */
gtpuh_p = (struct gtpuhdr*)skb_push(new_skb_p, sizeof(struct gtpuhdr)); ip_len = sizeof(struct iphdr) + sizeof(struct udphdr) + sizeof(struct gtpuhdr) + orig_iplen;
gtpuh_p->flags = 0x30; /* v1 and Protocol-type=GTP */ new_iph_p = (struct iphdr*)skb_push(new_skb_p, sizeof(struct iphdr));
gtpuh_p->msgtype = 0xff; /* T-PDU */ new_iph_p->ihl = 5;
gtpuh_p->length = htons(orig_iplen); new_iph_p->version = 4;
gtpuh_p->tunid = htonl(old_skb_pP->mark); new_iph_p->tos = 0;
new_iph_p->tot_len = htons(ip_len);
new_iph_p->id = (uint16_t)(((uint64_t)new_skb_p) >> 8);
new_iph_p->frag_off = 0;
new_iph_p->ttl = 64;
new_iph_p->protocol = IPPROTO_UDP;
new_iph_p->saddr = ((const struct xt_gtpuah_target_info *)(par_pP->targinfo))->laddr;
// !!!!!!!! LG TEST !!!!!!!!!!
//new_iph_p->saddr = old_iph_p->saddr;
new_iph_p->daddr = ((const struct xt_gtpuah_target_info *)(par_pP->targinfo))->raddr;
new_iph_p->check = 0;
new_iph_p->check = ip_fast_csum((unsigned char *)new_iph_p, new_iph_p->ihl);
skb_set_network_header(new_skb_p, 0);
/* Add UDP header */ skb_set_inner_network_header(new_skb_p, -ETH_HLEN);
udp_len = sizeof(struct udphdr) + sizeof(struct gtpuhdr) + orig_iplen; skb_set_inner_transport_header(new_skb_p, -ETH_HLEN);
udph_p = (struct udphdr*)skb_push(new_skb_p, sizeof(struct udphdr));
udph_p->source = htons(gtpu_port);
udph_p->dest = htons(gtpu_port);
udph_p->len = htons(udp_len);
udph_p->check = 0;
udph_p->check = csum_tcpudp_magic(((const struct xt_gtpuah_target_info *)(par_pP->targinfo))->laddr,
((const struct xt_gtpuah_target_info *)(par_pP->targinfo))->raddr,
udp_len,
IPPROTO_UDP,
csum_partial((char*)udph_p, udp_len, 0));
skb_set_transport_header(new_skb_p, 0);
/* Add IP header */
ip_len = sizeof(struct iphdr) + sizeof(struct udphdr) + sizeof(struct gtpuhdr) + orig_iplen;
new_iph_p = (struct iphdr*)skb_push(new_skb_p, sizeof(struct iphdr));
new_iph_p->ihl = 5;
new_iph_p->version = 4;
new_iph_p->tos = 0;
new_iph_p->tot_len = htons(ip_len);
new_iph_p->id = (uint16_t)(((uint64_t)new_skb_p) >> 8);
new_iph_p->frag_off = 0;
new_iph_p->ttl = 64;
new_iph_p->protocol = IPPROTO_UDP;
new_iph_p->saddr = ((const struct xt_gtpuah_target_info *)(par_pP->targinfo))->laddr;
// !!!!!!!! LG TEST !!!!!!!!!!
//new_iph_p->saddr = old_iph_p->saddr;
new_iph_p->daddr = ((const struct xt_gtpuah_target_info *)(par_pP->targinfo))->raddr;
new_iph_p->check = 0;
new_iph_p->check = ip_fast_csum((unsigned char *)new_iph_p, new_iph_p->ihl);
skb_set_network_header(new_skb_p, 0);
skb_set_inner_network_header(new_skb_p, -ETH_HLEN);
skb_set_inner_transport_header(new_skb_p, -ETH_HLEN);
// CHECKSUM_NONE, CHECKSUM_UNNECESSARY, CHECKSUM_COMPLETE, CHECKSUM_PARTIAL // CHECKSUM_NONE, CHECKSUM_UNNECESSARY, CHECKSUM_COMPLETE, CHECKSUM_PARTIAL
new_skb_p->ip_summed = CHECKSUM_NONE; new_skb_p->ip_summed = CHECKSUM_NONE;
new_skb_p->mark = old_skb_pP->mark; new_skb_p->mark = old_skb_pP->mark;
switch (par_pP->hooknum) { switch (par_pP->hooknum) {
case NF_INET_POST_ROUTING: { case NF_INET_POST_ROUTING: {
new_skb_p->pkt_type = PACKET_OTHERHOST; // PACKET_OUTGOING new_skb_p->pkt_type = PACKET_OTHERHOST; // PACKET_OUTGOING
#ifdef CONFIG_BRIDGE_NETFILTER #ifdef CONFIG_BRIDGE_NETFILTER
if (new_skb_p->nf_bridge != NULL && new_skb_p->nf_bridge->mask & BRNF_BRIDGED) {
addr_type = RTN_LOCAL; if (new_skb_p->nf_bridge != NULL && new_skb_p->nf_bridge->mask & BRNF_BRIDGED) {
new_skb_p->pkt_type =PACKET_HOST; addr_type = RTN_LOCAL;
} new_skb_p->pkt_type =PACKET_HOST;
}
#endif #endif
if (tunnel_local == 0) {
struct flowi fl = {
.u = {
.ip4 = {
.daddr = new_iph_p->daddr,
.flowi4_tos = RT_TOS(new_iph_p->tos),
.flowi4_scope = RT_SCOPE_UNIVERSE,
}
}
};
if (tunnel_local == 0) {
rt = ip_route_output_key(&init_net, &fl.u.ip4); struct flowi fl = {
if (rt == NULL) { .u = {
pr_info("GTPURH: Failed to route packet to dst 0x%x.\n", fl.u.ip4.daddr); .ip4 = {
goto free_new_skb; .daddr = new_iph_p->daddr,
} .flowi4_tos = RT_TOS(new_iph_p->tos),
new_skb_p->priority = rt_tos2priority(new_iph_p->tos); .flowi4_scope = RT_SCOPE_UNIVERSE,
skb_dst_drop(new_skb_p);
if (rt->dst.dev) {
pr_info("GTPUAH: dst dev name %s\n", rt->dst.dev->name);
skb_dst_set(new_skb_p, dst_clone(&rt->dst));
new_skb_p->dev = skb_dst(new_skb_p)->dev;
if (new_skb_p->len > dst_mtu(skb_dst(new_skb_p))) {
goto free_new_skb;
}
nf_ct_attach(new_skb_p, old_skb_pP);
pr_info("GTPUAH: PACKET -> NF_HOOK NF_INET_POST_ROUTING/%s mark %u encap src: %u.%u.%u.%u dst: %u.%u.%u.%u in src: %u.%u.%u.%u dst: %u.%u.%u.%u\n",
gtpuah_tg_reg[0].table,
new_skb_p->mark,
NIPADDR(old_iph_p->saddr),
NIPADDR(old_iph_p->daddr),
NIPADDR(new_iph_p->saddr),
NIPADDR(new_iph_p->daddr));
_gtpuah_print_hex_octets(
ip_hdr(new_skb_p),
headroom_reqd);
ip_local_out(new_skb_p);
return;
} else {
pr_info("GTPURH: rt->dst.dev == NULL\n");
goto free_new_skb;
}
} else { // (tunnel_local)
new_skb_p->pkt_type = PACKET_HOST;
new_skb_p->priority = rt_tos2priority(new_iph_p->tos);
new_skb_p->protocol = htons(ETH_P_IP);
// fake mac header
ethhdr_p = (struct ethhdr*)skb_push(new_skb_p, ETH_HLEN);
skb_set_mac_header(new_skb_p, 0);
memset(ethhdr_p, 0, ETH_HLEN);
ethhdr_p->h_proto = ntohs(ETH_P_IP);
//_gtpuah_print_hex_octets(new_iph_p, ip_len);
//ip_local_deliver_fn_ptr(new_skb_p);
new_skb_p->ip_summed = CHECKSUM_NONE;
skb_dst_drop(new_skb_p);
nf_reset(new_skb_p);
/*pr_info("GTPUAH(tun): PACKET -> NF_HOOK NF_INET_POST_ROUTING/%s encapsulated src: %u.%u.%u.%u dst: %u.%u.%u.%u\n",
gtpuah_tg_reg[0].table,
NIPADDR(old_iph_p->saddr),
NIPADDR(old_iph_p->daddr));*/
if ( dev_forward_skb(old_skb_pP->dev, new_skb_p) != NET_RX_SUCCESS) {
pr_info("GTPUAH(tun): dev_forward_skb failed!!!\n");
}
return;
}
} }
break; }
};
default:
pr_info("GTPUAH: NF_HOOK %u not processed\n", par_pP->hooknum); rt = ip_route_output_key(&init_net, &fl.u.ip4);
goto free_new_skb;
if (rt == NULL) {
pr_info("GTPURH: Failed to route packet to dst 0x%x.\n", fl.u.ip4.daddr);
goto free_new_skb;
} }
new_skb_p->priority = rt_tos2priority(new_iph_p->tos);
skb_dst_drop(new_skb_p);
if (rt->dst.dev) {
pr_info("GTPUAH: dst dev name %s\n", rt->dst.dev->name);
skb_dst_set(new_skb_p, dst_clone(&rt->dst));
new_skb_p->dev = skb_dst(new_skb_p)->dev;
if (new_skb_p->len > dst_mtu(skb_dst(new_skb_p))) {
goto free_new_skb;
}
nf_ct_attach(new_skb_p, old_skb_pP);
pr_info("GTPUAH: PACKET -> NF_HOOK NF_INET_POST_ROUTING/%s mark %u encap src: %u.%u.%u.%u dst: %u.%u.%u.%u in src: %u.%u.%u.%u dst: %u.%u.%u.%u\n",
gtpuah_tg_reg[0].table,
new_skb_p->mark,
NIPADDR(old_iph_p->saddr),
NIPADDR(old_iph_p->daddr),
NIPADDR(new_iph_p->saddr),
NIPADDR(new_iph_p->daddr));
_gtpuah_print_hex_octets(
ip_hdr(new_skb_p),
headroom_reqd);
ip_local_out(new_skb_p);
return;
} else {
pr_info("GTPURH: rt->dst.dev == NULL\n");
goto free_new_skb;
}
} else { // (tunnel_local)
new_skb_p->pkt_type = PACKET_HOST;
new_skb_p->priority = rt_tos2priority(new_iph_p->tos);
new_skb_p->protocol = htons(ETH_P_IP);
// fake mac header
ethhdr_p = (struct ethhdr*)skb_push(new_skb_p, ETH_HLEN);
skb_set_mac_header(new_skb_p, 0);
memset(ethhdr_p, 0, ETH_HLEN);
ethhdr_p->h_proto = ntohs(ETH_P_IP);
//_gtpuah_print_hex_octets(new_iph_p, ip_len);
//ip_local_deliver_fn_ptr(new_skb_p);
new_skb_p->ip_summed = CHECKSUM_NONE;
skb_dst_drop(new_skb_p);
nf_reset(new_skb_p);
/*pr_info("GTPUAH(tun): PACKET -> NF_HOOK NF_INET_POST_ROUTING/%s encapsulated src: %u.%u.%u.%u dst: %u.%u.%u.%u\n",
gtpuah_tg_reg[0].table,
NIPADDR(old_iph_p->saddr),
NIPADDR(old_iph_p->daddr));*/
if ( dev_forward_skb(old_skb_pP->dev, new_skb_p) != NET_RX_SUCCESS) {
pr_info("GTPUAH(tun): dev_forward_skb failed!!!\n");
}
return; return;
} else { }
pr_info("GTPUAH: PACKET DROPPED because of mtu %u < (%u + %u)\n",
mtu, orig_iplen, headroom_reqd);
} }
break;
default:
pr_info("GTPUAH: NF_HOOK %u not processed\n", par_pP->hooknum);
goto free_new_skb;
}
return;
} else {
pr_info("GTPUAH: PACKET DROPPED because of mtu %u < (%u + %u)\n",
mtu, orig_iplen, headroom_reqd);
}
free_new_skb: free_new_skb:
pr_info("GTPUAH: PACKET DROPPED\n"); pr_info("GTPUAH: PACKET DROPPED\n");
kfree_skb(new_skb_p); kfree_skb(new_skb_p);
return ; return ;
} }
#ifdef WITH_IPV6 #ifdef WITH_IPV6
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
static unsigned int static unsigned int
gtpuah_tg6(struct sk_buff *skb_pP, const struct xt_action_param *par_pP) { gtpuah_tg6(struct sk_buff *skb_pP, const struct xt_action_param *par_pP)
//----------------------------------------------------------------------------- {
//-----------------------------------------------------------------------------
const struct xt_gtpuah_target_info *tgi_p = par_pP->targinfo; const struct xt_gtpuah_target_info *tgi_p = par_pP->targinfo;
if (tgi_p == NULL) { if (tgi_p == NULL) {
return NF_ACCEPT;
}
if (tgi_p->action == PARAM_GTPUAH_ACTION_ADD) {
_gtpuah_tg6_add(skb_pP, par_pP);
return NF_DROP; // TODO
}
return NF_ACCEPT; return NF_ACCEPT;
}
if (tgi_p->action == PARAM_GTPUAH_ACTION_ADD) {
_gtpuah_tg6_add(skb_pP, par_pP);
return NF_DROP; // TODO
}
return NF_ACCEPT;
} }
#endif #endif
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
static unsigned int static unsigned int
gtpuah_tg4(struct sk_buff *skb_pP, const struct xt_action_param *par_pP) { gtpuah_tg4(struct sk_buff *skb_pP, const struct xt_action_param *par_pP)
//----------------------------------------------------------------------------- {
const struct iphdr *iph_p = ip_hdr(skb_pP); //-----------------------------------------------------------------------------
const struct xt_gtpuah_target_info *tgi_p = par_pP->targinfo; const struct iphdr *iph_p = ip_hdr(skb_pP);
if (tgi_p == NULL) { const struct xt_gtpuah_target_info *tgi_p = par_pP->targinfo;
return NF_ACCEPT;
}
if (tgi_p->action == PARAM_GTPUAH_ACTION_ADD) { if (tgi_p == NULL) {
_gtpuah_tg4_add(skb_pP, par_pP);
return NF_DROP;
}
return NF_ACCEPT; return NF_ACCEPT;
}
if (tgi_p->action == PARAM_GTPUAH_ACTION_ADD) {
_gtpuah_tg4_add(skb_pP, par_pP);
return NF_DROP;
}
return NF_ACCEPT;
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
static int static int
__init gtpuah_tg_init(void) { __init gtpuah_tg_init(void)
//----------------------------------------------------------------------------- {
pr_info("GTPUAH: Initializing module (KVersion: %d)\n", KVERSION); //-----------------------------------------------------------------------------
pr_info("GTPUAH: Copyright Polaris Networks 2010-2011\n"); pr_info("GTPUAH: Initializing module (KVersion: %d)\n", KVERSION);
pr_info("GTPUAH: Modified by EURECOM Lionel GAUTHIER 2014\n"); pr_info("GTPUAH: Copyright Polaris Networks 2010-2011\n");
#ifndef CMAKER pr_info("GTPUAH: Modified by EURECOM Lionel GAUTHIER 2014\n");
pr_info("GTPUAH: Compiled %s at time %s\n",__DATE__,__TIME__); #ifndef CMAKER
#endif pr_info("GTPUAH: Compiled %s at time %s\n",__DATE__,__TIME__);
#if defined(WITH_IPV6)
pr_info("GTPURH: IPv4/IPv6 enabled\n");
#else
pr_info("GTPURH: IPv4 only enabled\n");
#endif #endif
return xt_register_targets(gtpuah_tg_reg, ARRAY_SIZE(gtpuah_tg_reg)); #if defined(WITH_IPV6)
pr_info("GTPURH: IPv4/IPv6 enabled\n");
#else
pr_info("GTPURH: IPv4 only enabled\n");
#endif
return xt_register_targets(gtpuah_tg_reg, ARRAY_SIZE(gtpuah_tg_reg));
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
static void static void
__exit gtpuah_tg_exit(void) { __exit gtpuah_tg_exit(void)
//----------------------------------------------------------------------------- {
xt_unregister_targets(gtpuah_tg_reg, ARRAY_SIZE(gtpuah_tg_reg)); //-----------------------------------------------------------------------------
pr_info("GTPUAH: Unloading module\n"); xt_unregister_targets(gtpuah_tg_reg, ARRAY_SIZE(gtpuah_tg_reg));
pr_info("GTPUAH: Unloading module\n");
} }
+8 -10
View File
@@ -9,17 +9,15 @@
* *
*/ */
enum xt_gtpuah_mode_ enum xt_gtpuah_mode_ {
{ PARAM_GTPUAH_ACTION_ADD = 1 << 8,
PARAM_GTPUAH_ACTION_ADD = 1 << 8,
}; };
struct xt_gtpuah_target_info struct xt_gtpuah_target_info {
{ u_int32_t laddr __attribute__((aligned(8)));
u_int32_t laddr __attribute__((aligned(8))); u_int32_t raddr __attribute__((aligned(8)));
u_int32_t raddr __attribute__((aligned(8))); u_int32_t ltun __attribute__((aligned(8)));
u_int32_t ltun __attribute__((aligned(8))); u_int32_t rtun __attribute__((aligned(8)));
u_int32_t rtun __attribute__((aligned(8))); u_int32_t action __attribute__((aligned(8)));
u_int32_t action __attribute__((aligned(8)));
}; };
+183 -174
View File
@@ -33,7 +33,7 @@
#define XT_GTPURH_VERSION IPTABLES_VERSION_STRING #define XT_GTPURH_VERSION IPTABLES_VERSION_STRING
#define gtpurh_strtoui(s,v,m,M) !string_to_number(s,m,M,v) #define gtpurh_strtoui(s,v,m,M) !string_to_number(s,m,M,v)
#define gtpurh_exit_error exit_error #define gtpurh_exit_error exit_error
#elif (IPTVERSION > 135) && (IPTVERSION <= 141) #elif (IPTVERSION > 135) && (IPTVERSION <= 141)
#define GTPURH_PARAM_BAD_VALUE P_BAD_VALUE #define GTPURH_PARAM_BAD_VALUE P_BAD_VALUE
#define GTPURH_PARAM_ONLY_ONCE P_ONLY_ONCE #define GTPURH_PARAM_ONLY_ONCE P_ONLY_ONCE
#define XT_GTPURH_VERSION XTABLES_VERSION #define XT_GTPURH_VERSION XTABLES_VERSION
@@ -50,238 +50,247 @@
#endif #endif
enum { enum {
PARAM_LADDR = 1 << 0, PARAM_LADDR = 1 << 0,
PARAM_LTUN = 1 << 1, PARAM_LTUN = 1 << 1,
PARAM_RADDR = 1 << 2, PARAM_RADDR = 1 << 2,
PARAM_RTUN = 1 << 3, PARAM_RTUN = 1 << 3,
PARAM_ACTION = 1 << 4, PARAM_ACTION = 1 << 4,
}; };
static void GTPURH_help(void) static void GTPURH_help(void)
{ {
printf( printf(
"GTPUAH target options\n" "GTPUAH target options\n"
" --action value Set action <value: remove>\n" " --action value Set action <value: remove>\n"
" --own-ip value Set own IP address\n" " --own-ip value Set own IP address\n"
" --own-tun value Set own tunnel id <value: 1-2^31>\n" " --own-tun value Set own tunnel id <value: 1-2^31>\n"
" --peer-ip value Set peer IP address\n" " --peer-ip value Set peer IP address\n"
" --peer-tun value Set peer tunnel id <value: 1-2^31>\n"); " --peer-tun value Set peer tunnel id <value: 1-2^31>\n");
} }
#if (IPTVERSION <= 135) #if (IPTVERSION <= 135)
/* Stolen from iptables v1.4.7 code */ /* Stolen from iptables v1.4.7 code */
void gtpurh_param_act(unsigned int status, const char *p1, ...) void gtpurh_param_act(unsigned int status, const char *p1, ...)
{ {
const char *p2, *p3; const char *p2, *p3;
va_list args; va_list args;
int b; int b;
va_start(args, p1); va_start(args, p1);
switch (status) { switch (status) {
case GTPURH_PARAM_ONLY_ONCE: case GTPURH_PARAM_ONLY_ONCE:
p2 = va_arg(args, const char *); p2 = va_arg(args, const char *);
b = va_arg(args, unsigned int); b = va_arg(args, unsigned int);
if (!b)
return;
exit_error(PARAMETER_PROBLEM,
"%s: \"%s\" option may only be specified once",
p1, p2);
break;
case GTPURH_PARAM_BAD_VALUE:
p2 = va_arg(args, const char *);
p3 = va_arg(args, const char *);
exit_error(PARAMETER_PROBLEM,
"%s: Bad value for \"%s\" option: \"%s\"",
p1, p2, p3);
break;
default:
exit_error(status, "%s", "Unknown error");
break;
}
va_end(args); if (!b)
return;
exit_error(PARAMETER_PROBLEM,
"%s: \"%s\" option may only be specified once",
p1, p2);
break;
case GTPURH_PARAM_BAD_VALUE:
p2 = va_arg(args, const char *);
p3 = va_arg(args, const char *);
exit_error(PARAMETER_PROBLEM,
"%s: Bad value for \"%s\" option: \"%s\"",
p1, p2, p3);
break;
default:
exit_error(status, "%s", "Unknown error");
break;
}
va_end(args);
} }
#endif #endif
static void parse_gtpurh_addr(const char *s, struct xt_gtpurh_target_info *info, int flag) static void parse_gtpurh_addr(const char *s, struct xt_gtpurh_target_info *info, int flag)
{ {
in_addr_t addr; in_addr_t addr;
if ((addr = inet_addr(s)) == -1) {
switch (flag) {
case PARAM_LADDR:
gtpurh_param_act(GTPURH_PARAM_BAD_VALUE, "GTPURH", "--own-ip", s);
break;
case PARAM_RADDR:
gtpurh_param_act(GTPURH_PARAM_BAD_VALUE, "GTPURH", "--peer-ip", s);
break;
}
}
if ((addr = inet_addr(s)) == -1) {
switch (flag) { switch (flag) {
case PARAM_LADDR: case PARAM_LADDR:
info->laddr = addr; gtpurh_param_act(GTPURH_PARAM_BAD_VALUE, "GTPURH", "--own-ip", s);
break; break;
case PARAM_RADDR:
info->raddr = addr; case PARAM_RADDR:
break; gtpurh_param_act(GTPURH_PARAM_BAD_VALUE, "GTPURH", "--peer-ip", s);
break;
} }
}
switch (flag) {
case PARAM_LADDR:
info->laddr = addr;
break;
case PARAM_RADDR:
info->raddr = addr;
break;
}
} }
static void parse_gtpurh_tunid(char *s, struct xt_gtpurh_target_info *info, int flag) static void parse_gtpurh_tunid(char *s, struct xt_gtpurh_target_info *info, int flag)
{ {
unsigned int value; unsigned int value;
if (!gtpurh_strtoui(s, &value, 0, UINT32_MAX)) {
switch (flag) {
case PARAM_LTUN:
gtpurh_param_act(GTPURH_PARAM_BAD_VALUE, "GTPURH", "--own-tun", s);
break;
case PARAM_RTUN:
gtpurh_param_act(GTPURH_PARAM_BAD_VALUE, "GTPURH", "--peer-tun", s);
break;
}
}
if (!gtpurh_strtoui(s, &value, 0, UINT32_MAX)) {
switch (flag) { switch (flag) {
case PARAM_LTUN: case PARAM_LTUN:
info->ltun = value; gtpurh_param_act(GTPURH_PARAM_BAD_VALUE, "GTPURH", "--own-tun", s);
break; break;
case PARAM_RTUN:
info->rtun = value; case PARAM_RTUN:
break; gtpurh_param_act(GTPURH_PARAM_BAD_VALUE, "GTPURH", "--peer-tun", s);
break;
} }
}
switch (flag) {
case PARAM_LTUN:
info->ltun = value;
break;
case PARAM_RTUN:
info->rtun = value;
break;
}
} }
static void parse_gtpurh_action(char *s, struct xt_gtpurh_target_info *info, unsigned int *flags) static void parse_gtpurh_action(char *s, struct xt_gtpurh_target_info *info, unsigned int *flags)
{ {
if (!strcmp(s, "remove")) { if (!strcmp(s, "remove")) {
info->action = PARAM_GTPURH_ACTION_REM; info->action = PARAM_GTPURH_ACTION_REM;
*flags |= PARAM_GTPURH_ACTION_REM; *flags |= PARAM_GTPURH_ACTION_REM;
} else { } else {
gtpurh_param_act(GTPURH_PARAM_BAD_VALUE, "GTPURH", "--action", s); gtpurh_param_act(GTPURH_PARAM_BAD_VALUE, "GTPURH", "--action", s);
} }
} }
#if (IPTVERSION <= 135) #if (IPTVERSION <= 135)
static int static int
GTPURH_parse(int c, char **argv, int invert, unsigned int *flags, GTPURH_parse(int c, char **argv, int invert, unsigned int *flags,
const struct ipt_entry *entry, const struct ipt_entry *entry,
struct ipt_entry_target **target) struct ipt_entry_target **target)
#else #else
static int static int
GTPURH_parse(int c, char **argv, int invert, unsigned int *flags, GTPURH_parse(int c, char **argv, int invert, unsigned int *flags,
const void *entry, struct xt_entry_target **target) const void *entry, struct xt_entry_target **target)
#endif #endif
{ {
struct xt_gtpurh_target_info *info = (struct xt_gtpurh_target_info *) (*target)->data; struct xt_gtpurh_target_info *info = (struct xt_gtpurh_target_info *) (*target)->data;
switch (c)
{
case '1':
gtpurh_param_act(GTPURH_PARAM_ONLY_ONCE, "GTPURH", "--own-ip", *flags & PARAM_LADDR);
parse_gtpurh_addr(optarg, info, PARAM_LADDR);
*flags |= PARAM_LADDR;
return 1;
case '2':
gtpurh_param_act(GTPURH_PARAM_ONLY_ONCE, "GTPURH", "--own-tun", *flags & PARAM_LTUN);
parse_gtpurh_tunid(optarg, info, PARAM_LTUN);
*flags |= PARAM_LTUN;
return 1;
case '3':
gtpurh_param_act(GTPURH_PARAM_ONLY_ONCE, "GTPURH", "--peer-ip", *flags & PARAM_RADDR);
parse_gtpurh_addr(optarg, info, PARAM_RADDR);
*flags |= PARAM_RADDR;
return 1;
case '4':
gtpurh_param_act(GTPURH_PARAM_ONLY_ONCE, "GTPURH", "--peer-tun", *flags & PARAM_RTUN);
parse_gtpurh_tunid(optarg, info, PARAM_RTUN);
*flags |= PARAM_RTUN;
return 1;
case '5':
gtpurh_param_act(GTPURH_PARAM_ONLY_ONCE, "GTPURH", "--action", *flags & PARAM_ACTION);
parse_gtpurh_action(optarg, info, flags);
*flags |= PARAM_ACTION;
return 1;
}
switch (c) {
case '1':
gtpurh_param_act(GTPURH_PARAM_ONLY_ONCE, "GTPURH", "--own-ip", *flags & PARAM_LADDR);
parse_gtpurh_addr(optarg, info, PARAM_LADDR);
*flags |= PARAM_LADDR;
return 1; return 1;
case '2':
gtpurh_param_act(GTPURH_PARAM_ONLY_ONCE, "GTPURH", "--own-tun", *flags & PARAM_LTUN);
parse_gtpurh_tunid(optarg, info, PARAM_LTUN);
*flags |= PARAM_LTUN;
return 1;
case '3':
gtpurh_param_act(GTPURH_PARAM_ONLY_ONCE, "GTPURH", "--peer-ip", *flags & PARAM_RADDR);
parse_gtpurh_addr(optarg, info, PARAM_RADDR);
*flags |= PARAM_RADDR;
return 1;
case '4':
gtpurh_param_act(GTPURH_PARAM_ONLY_ONCE, "GTPURH", "--peer-tun", *flags & PARAM_RTUN);
parse_gtpurh_tunid(optarg, info, PARAM_RTUN);
*flags |= PARAM_RTUN;
return 1;
case '5':
gtpurh_param_act(GTPURH_PARAM_ONLY_ONCE, "GTPURH", "--action", *flags & PARAM_ACTION);
parse_gtpurh_action(optarg, info, flags);
*flags |= PARAM_ACTION;
return 1;
}
return 1;
} }
static void GTPURH_check(unsigned int flags) static void GTPURH_check(unsigned int flags)
{ {
if (!(flags & PARAM_ACTION)) if (!(flags & PARAM_ACTION)) {
{ gtpurh_exit_error(PARAMETER_PROBLEM, "GTPURH: You must specify action");
gtpurh_exit_error(PARAMETER_PROBLEM, "GTPURH: You must specify action"); }
}
if (!(flags & PARAM_LADDR)) if (!(flags & PARAM_LADDR)) {
{ gtpurh_exit_error(PARAMETER_PROBLEM, "GTPURH: You must specify local addr");
gtpurh_exit_error(PARAMETER_PROBLEM, "GTPURH: You must specify local addr"); }
}
if (!(flags & PARAM_LTUN)) if (!(flags & PARAM_LTUN)) {
{ gtpurh_exit_error(PARAMETER_PROBLEM, "GTPURH: You must specify local tunnel id");
gtpurh_exit_error(PARAMETER_PROBLEM, "GTPURH: You must specify local tunnel id"); }
}
if (!(flags & PARAM_RADDR)) if (!(flags & PARAM_RADDR)) {
{ gtpurh_exit_error(PARAMETER_PROBLEM, "GTPURH: You must specify remote addr");
gtpurh_exit_error(PARAMETER_PROBLEM, "GTPURH: You must specify remote addr"); }
}
if (!(flags & PARAM_RTUN)) if (!(flags & PARAM_RTUN)) {
{ gtpurh_exit_error(PARAMETER_PROBLEM, "GTPURH: You must specify remote tunnel id");
gtpurh_exit_error(PARAMETER_PROBLEM, "GTPURH: You must specify remote tunnel id"); }
}
} }
static void convert_action_to_string(int action, char *actionstr) static void convert_action_to_string(int action, char *actionstr)
{ {
switch(action) switch(action) {
{ case PARAM_GTPURH_ACTION_REM:
case PARAM_GTPURH_ACTION_REM: sprintf (actionstr, "remove");
sprintf (actionstr, "remove"); break;
break;
default : default :
sprintf (actionstr, "unspecified!!!"); sprintf (actionstr, "unspecified!!!");
break; break;
} }
} }
#if (IPTVERSION <= 135) #if (IPTVERSION <= 135)
static void static void
GTPURH_print(const struct ipt_ip *ip, GTPURH_print(const struct ipt_ip *ip,
const struct ipt_entry_target *target, const struct ipt_entry_target *target,
int numeric) int numeric)
#else #else
static void static void
GTPURH_print(const void *ip, GTPURH_print(const void *ip,
const struct xt_entry_target *target, const struct xt_entry_target *target,
int numeric) int numeric)
#endif #endif
{ {
const struct xt_gtpurh_target_info *info = const struct xt_gtpurh_target_info *info =
(struct xt_gtpurh_target_info *) target->data; (struct xt_gtpurh_target_info *) target->data;
char laddr[64], raddr[64], actionstr[32]; char laddr[64], raddr[64], actionstr[32];
convert_action_to_string(info->action, actionstr); convert_action_to_string(info->action, actionstr);
if (info->action == PARAM_GTPURH_ACTION_REM) if (info->action == PARAM_GTPURH_ACTION_REM) {
{ printf("GTPURH action: %s", actionstr);
printf("GTPURH action: %s", actionstr); return;
return; }
}
} }
static struct option GTPURH_opts[] = { static struct option GTPURH_opts[] = {
{ "own-ip", 1, NULL, '1' }, { "own-ip", 1, NULL, '1' },
{ "own-tun", 1, NULL, '2' }, { "own-tun", 1, NULL, '2' },
{ "peer-ip", 1, NULL, '3' }, { "peer-ip", 1, NULL, '3' },
{ "peer-tun", 1, NULL, '4' }, { "peer-tun", 1, NULL, '4' },
{ "action", 1, NULL, '5' }, { "action", 1, NULL, '5' },
{ .name = NULL } { .name = NULL }
}; };
#if (IPTVERSION <= 135) #if (IPTVERSION <= 135)
@@ -289,26 +298,26 @@ static struct iptables_target gtpurh_tg_reg = {
#else #else
static struct xtables_target gtpurh_tg_reg = { static struct xtables_target gtpurh_tg_reg = {
#endif #endif
.name = "GTPURH", .name = "GTPURH",
.version = XT_GTPURH_VERSION, .version = XT_GTPURH_VERSION,
#if (IPTVERSION > 135) #if (IPTVERSION > 135)
.family = NFPROTO_IPV4, .family = NFPROTO_IPV4,
#endif #endif
.size = XT_ALIGN(sizeof(struct xt_gtpurh_target_info)), .size = XT_ALIGN(sizeof(struct xt_gtpurh_target_info)),
.userspacesize = XT_ALIGN(sizeof(struct xt_gtpurh_target_info)), .userspacesize = XT_ALIGN(sizeof(struct xt_gtpurh_target_info)),
.help = GTPURH_help, .help = GTPURH_help,
.parse = GTPURH_parse, .parse = GTPURH_parse,
.final_check = GTPURH_check, .final_check = GTPURH_check,
.print = GTPURH_print, .print = GTPURH_print,
.extra_opts = GTPURH_opts, .extra_opts = GTPURH_opts,
}; };
void _init(void) void _init(void)
{ {
#if (IPTVERSION <= 135) #if (IPTVERSION <= 135)
register_target(&gtpurh_tg_reg); register_target(&gtpurh_tg_reg);
#else #else
xtables_register_target(&gtpurh_tg_reg); xtables_register_target(&gtpurh_tg_reg);
#endif #endif
} }
+387 -341
View File
@@ -16,12 +16,12 @@
#include <linux/skbuff.h> #include <linux/skbuff.h>
#include <linux/ip.h> #include <linux/ip.h>
#include <linux/if_ether.h> #include <linux/if_ether.h>
#include <linux/route.h> #include <linux/route.h>
#include <net/checksum.h> #include <net/checksum.h>
#include <net/ip.h> #include <net/ip.h>
#include <net/udp.h> #include <net/udp.h>
#include <net/inet_sock.h> #include <net/inet_sock.h>
#include <net/route.h> #include <net/route.h>
#include <linux/netfilter/x_tables.h> #include <linux/netfilter/x_tables.h>
#include <linux/netfilter_ipv4/ip_tables.h> #include <linux/netfilter_ipv4/ip_tables.h>
#if defined(CONFIG_IP6_NF_IPTABLES) || defined(CONFIG_IP6_NF_IPTABLES_MODULE) #if defined(CONFIG_IP6_NF_IPTABLES) || defined(CONFIG_IP6_NF_IPTABLES_MODULE)
@@ -65,58 +65,75 @@ static unsigned int gtpurh_tg4(struct sk_buff *skb_pP, const struct xt_action_p
static char _gtpurh_print_buffer[GTPURH_2_PRINT_BUFFER_LEN]; static char _gtpurh_print_buffer[GTPURH_2_PRINT_BUFFER_LEN];
static struct xt_target gtpurh_tg_reg[] __read_mostly = { static struct xt_target gtpurh_tg_reg[] __read_mostly = {
{ {
.name = "GTPURH", .name = "GTPURH",
.revision = 0, .revision = 0,
.family = NFPROTO_IPV4, .family = NFPROTO_IPV4,
.hooks = (1 << NF_INET_PRE_ROUTING) | .hooks = (1 << NF_INET_PRE_ROUTING) |
(1 << NF_INET_LOCAL_OUT), (1 << NF_INET_LOCAL_OUT),
.proto = IPPROTO_UDP, .proto = IPPROTO_UDP,
.table = "raw", .table = "raw",
.target = gtpurh_tg4, .target = gtpurh_tg4,
.targetsize = sizeof(struct xt_gtpurh_target_info), .targetsize = sizeof(struct xt_gtpurh_target_info),
.me = THIS_MODULE, .me = THIS_MODULE,
}, },
#if defined(WITH_IPV6) #if defined(WITH_IPV6)
{ {
.name = "GTPURH", .name = "GTPURH",
.revision = 0, .revision = 0,
.family = NFPROTO_IPV6, .family = NFPROTO_IPV6,
.proto = IPPROTO_UDP, .proto = IPPROTO_UDP,
.table = "raw", .table = "raw",
.target = gtpurh_tg6, .target = gtpurh_tg6,
.me = THIS_MODULE, .me = THIS_MODULE,
}, },
#endif #endif
}; };
struct gtpuhdr struct gtpuhdr {
{ char flags;
char flags; char msgtype;
char msgtype; u_int16_t length;
u_int16_t length; u_int32_t tunid;
u_int32_t tunid;
}; };
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
static char* static char*
_gtpurh_nf_inet_hook_2_string(int nf_inet_hookP) { _gtpurh_nf_inet_hook_2_string(int nf_inet_hookP)
//----------------------------------------------------------------------------- {
switch (nf_inet_hookP) { //-----------------------------------------------------------------------------
case NF_INET_PRE_ROUTING: return "NF_INET_PRE_ROUTING";break; switch (nf_inet_hookP) {
case NF_INET_LOCAL_IN: return "NF_INET_LOCAL_IN";break; case NF_INET_PRE_ROUTING:
case NF_INET_FORWARD: return "NF_INET_FORWARD";break; return "NF_INET_PRE_ROUTING";
case NF_INET_LOCAL_OUT: return "NF_INET_LOCAL_OUT";break; break;
case NF_INET_POST_ROUTING: return "NF_INET_POST_ROUTING";break;
default: return "NF_INET_UNKNOWN"; case NF_INET_LOCAL_IN:
} return "NF_INET_LOCAL_IN";
break;
case NF_INET_FORWARD:
return "NF_INET_FORWARD";
break;
case NF_INET_LOCAL_OUT:
return "NF_INET_LOCAL_OUT";
break;
case NF_INET_POST_ROUTING:
return "NF_INET_POST_ROUTING";
break;
default:
return "NF_INET_UNKNOWN";
}
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
static inline bool static inline bool
_gtpurh_ip_is_fragment(const struct iphdr *iph_p) { _gtpurh_ip_is_fragment(const struct iphdr *iph_p)
//----------------------------------------------------------------------------- {
return (iph_p->frag_off & htons(IP_MF | IP_OFFSET)) != 0; //-----------------------------------------------------------------------------
return (iph_p->frag_off & htons(IP_MF | IP_OFFSET)) != 0;
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@@ -133,8 +150,9 @@ void _gtpurh_print_hex_octets(unsigned char* data_pP, unsigned short sizeP)
if (data_pP == NULL) { if (data_pP == NULL) {
return; return;
} }
if (sizeP > 2000) { if (sizeP > 2000) {
return; return;
} }
do_gettimeofday(&tv); do_gettimeofday(&tv);
@@ -146,15 +164,20 @@ void _gtpurh_print_hex_octets(unsigned char* data_pP, unsigned short sizeP)
buffer_marker+=snprintf(&_gtpurh_print_buffer[buffer_marker], GTPURH_2_PRINT_BUFFER_LEN - buffer_marker,"%s------+-------------------------------------------------+\n",timeofday); buffer_marker+=snprintf(&_gtpurh_print_buffer[buffer_marker], GTPURH_2_PRINT_BUFFER_LEN - buffer_marker,"%s------+-------------------------------------------------+\n",timeofday);
buffer_marker+=snprintf(&_gtpurh_print_buffer[buffer_marker], GTPURH_2_PRINT_BUFFER_LEN - buffer_marker,"%s | 0 1 2 3 4 5 6 7 8 9 a b c d e f |\n",timeofday); buffer_marker+=snprintf(&_gtpurh_print_buffer[buffer_marker], GTPURH_2_PRINT_BUFFER_LEN - buffer_marker,"%s | 0 1 2 3 4 5 6 7 8 9 a b c d e f |\n",timeofday);
buffer_marker+=snprintf(&_gtpurh_print_buffer[buffer_marker], GTPURH_2_PRINT_BUFFER_LEN - buffer_marker,"%s------+-------------------------------------------------+\n",timeofday); buffer_marker+=snprintf(&_gtpurh_print_buffer[buffer_marker], GTPURH_2_PRINT_BUFFER_LEN - buffer_marker,"%s------+-------------------------------------------------+\n",timeofday);
pr_info("%s",_gtpurh_print_buffer);buffer_marker = 0; pr_info("%s",_gtpurh_print_buffer);
buffer_marker = 0;
for (octet_index = 0; octet_index < sizeP; octet_index++) { for (octet_index = 0; octet_index < sizeP; octet_index++) {
if ((octet_index % 16) == 0){ if ((octet_index % 16) == 0) {
if (octet_index != 0) { if (octet_index != 0) {
buffer_marker+=snprintf(&_gtpurh_print_buffer[buffer_marker], GTPURH_2_PRINT_BUFFER_LEN - buffer_marker, " |\n"); buffer_marker+=snprintf(&_gtpurh_print_buffer[buffer_marker], GTPURH_2_PRINT_BUFFER_LEN - buffer_marker, " |\n");
pr_info("%s",_gtpurh_print_buffer);buffer_marker = 0; pr_info("%s",_gtpurh_print_buffer);
buffer_marker = 0;
} }
buffer_marker+=snprintf(&_gtpurh_print_buffer[buffer_marker], GTPURH_2_PRINT_BUFFER_LEN - buffer_marker, "%s %04ld |",timeofday, octet_index); buffer_marker+=snprintf(&_gtpurh_print_buffer[buffer_marker], GTPURH_2_PRINT_BUFFER_LEN - buffer_marker, "%s %04ld |",timeofday, octet_index);
} }
/* /*
* Print every single octet in hexadecimal form * Print every single octet in hexadecimal form
*/ */
@@ -169,7 +192,8 @@ void _gtpurh_print_hex_octets(unsigned char* data_pP, unsigned short sizeP)
*/ */
for (aindex = octet_index; aindex < 16; ++aindex) for (aindex = octet_index; aindex < 16; ++aindex)
buffer_marker+=snprintf(&_gtpurh_print_buffer[buffer_marker], GTPURH_2_PRINT_BUFFER_LEN - buffer_marker, " "); buffer_marker+=snprintf(&_gtpurh_print_buffer[buffer_marker], GTPURH_2_PRINT_BUFFER_LEN - buffer_marker, " ");
//SGI_IF_DEBUG(" ");
//SGI_IF_DEBUG(" ");
buffer_marker+=snprintf(&_gtpurh_print_buffer[buffer_marker], GTPURH_2_PRINT_BUFFER_LEN - buffer_marker, " |\n"); buffer_marker+=snprintf(&_gtpurh_print_buffer[buffer_marker], GTPURH_2_PRINT_BUFFER_LEN - buffer_marker, " |\n");
pr_info("%s",_gtpurh_print_buffer); pr_info("%s",_gtpurh_print_buffer);
} }
@@ -180,284 +204,302 @@ void _gtpurh_print_hex_octets(unsigned char* data_pP, unsigned short sizeP)
static bool _gtpurh_route_packet(struct sk_buff *skb_pP, const struct xt_gtpurh_target_info *info_pP) static bool _gtpurh_route_packet(struct sk_buff *skb_pP, const struct xt_gtpurh_target_info *info_pP)
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
{ {
int err = 0; int err = 0;
struct rtable *rt = NULL; struct rtable *rt = NULL;
struct iphdr *iph_p = ip_hdr(skb_pP); struct iphdr *iph_p = ip_hdr(skb_pP);
int daddr = iph_p->daddr; int daddr = iph_p->daddr;
struct flowi fl = { struct flowi fl = {
.u = { .u = {
.ip4 = { .ip4 = {
.daddr = daddr, .daddr = daddr,
.flowi4_tos = RT_TOS(iph_p->tos), .flowi4_tos = RT_TOS(iph_p->tos),
.flowi4_scope = RT_SCOPE_UNIVERSE, .flowi4_scope = RT_SCOPE_UNIVERSE,
} }
} }
}; };
//skb_pP->pkt_type = PACKET_OTHERHOST; //skb_pP->pkt_type = PACKET_OTHERHOST;
skb_pP->pkt_type = PACKET_OUTGOING; skb_pP->pkt_type = PACKET_OUTGOING;
#if 0 #if 0
pr_info("GTPURH(%d): Routing packet: %d.%d.%d.%d --> %d.%d.%d.%d Proto: %d, Len: %d Mark: %u Packet type: %u\n", pr_info("GTPURH(%d): Routing packet: %d.%d.%d.%d --> %d.%d.%d.%d Proto: %d, Len: %d Mark: %u Packet type: %u\n",
info_pP->action, info_pP->action,
iph_p->saddr & 0xFF, iph_p->saddr & 0xFF,
(iph_p->saddr & 0x0000FF00) >> 8, (iph_p->saddr & 0x0000FF00) >> 8,
(iph_p->saddr & 0x00FF0000) >> 16, (iph_p->saddr & 0x00FF0000) >> 16,
iph_p->saddr >> 24, iph_p->saddr >> 24,
iph_p->daddr & 0xFF, iph_p->daddr & 0xFF,
(iph_p->daddr & 0x0000FF00) >> 8, (iph_p->daddr & 0x0000FF00) >> 8,
(iph_p->daddr & 0x00FF0000) >> 16, (iph_p->daddr & 0x00FF0000) >> 16,
iph_p->daddr >> 24, iph_p->daddr >> 24,
iph_p->protocol, iph_p->protocol,
ntohs(iph_p->tot_len), ntohs(iph_p->tot_len),
skb_pP->mark, skb_pP->mark,
skb_pP->pkt_type); skb_pP->pkt_type);
#endif #endif
rt = ip_route_output_key(&init_net, &fl.u.ip4); rt = ip_route_output_key(&init_net, &fl.u.ip4);
if (rt == null) {
pr_info("GTPURH: Failed to route packet to dst 0x%x. Error: (%d)\n", fl.u.ip4.daddr, err); if (rt == null) {
return GTPURH_FAILURE; pr_info("GTPURH: Failed to route packet to dst 0x%x. Error: (%d)\n", fl.u.ip4.daddr, err);
} return GTPURH_FAILURE;
}
#if 0 #if 0
if (rt->dst.dev) {
pr_info("GTPURH: dst dev name %s\n", rt->dst.dev->name); if (rt->dst.dev) {
} else { pr_info("GTPURH: dst dev name %s\n", rt->dst.dev->name);
pr_info("GTPURH: dst dev NULL\n"); } else {
} pr_info("GTPURH: dst dev NULL\n");
}
#endif #endif
skb_pP->priority = rt_tos2priority(iph_p->tos); skb_pP->priority = rt_tos2priority(iph_p->tos);
skb_dst_drop(skb_pP); skb_dst_drop(skb_pP);
skb_dst_set(skb_pP, &rt->dst); skb_dst_set(skb_pP, &rt->dst);
skb_pP->dev = skb_dst(skb_pP)->dev; skb_pP->dev = skb_dst(skb_pP)->dev;
// Send the GTPu message out // Send the GTPu message out
ip_local_out(skb_pP); ip_local_out(skb_pP);
if (err == 0) { if (err == 0) {
return GTPURH_SUCCESS; return GTPURH_SUCCESS;
} else { } else {
return GTPURH_FAILURE; return GTPURH_FAILURE;
} }
} }
#endif #endif
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
static unsigned int static unsigned int
_gtpurh_tg4_rem(struct sk_buff *orig_skb_pP, const struct xt_action_param *par_pP) { _gtpurh_tg4_rem(struct sk_buff *orig_skb_pP, const struct xt_action_param *par_pP)
//----------------------------------------------------------------------------- {
//-----------------------------------------------------------------------------
struct iphdr *iph_p = ip_hdr(orig_skb_pP); struct iphdr *iph_p = ip_hdr(orig_skb_pP);
struct iphdr *iph2_p = NULL; struct iphdr *iph2_p = NULL;
struct udphdr *udph_p = NULL; struct udphdr *udph_p = NULL;
struct gtpuhdr *gtpuh_p = NULL; struct gtpuhdr *gtpuh_p = NULL;
struct sk_buff *skb_p = NULL; struct sk_buff *skb_p = NULL;
#if defined(NEW_SKB) #if defined(NEW_SKB)
struct sk_buff *new_skb_p = NULL; struct sk_buff *new_skb_p = NULL;
struct iphdr *new_ip_p = NULL; struct iphdr *new_ip_p = NULL;
#endif #endif
uint16_t gtp_payload_size = 0; uint16_t gtp_payload_size = 0;
/* Create a new copy of the original skb_p...can't avoid :-( LG: WHY???*/ /* Create a new copy of the original skb_p...can't avoid :-( LG: WHY???*/
#if defined(ROUTE_PACKET) #if defined(ROUTE_PACKET)
skb_p = skb_copy(orig_skb_pP, GFP_ATOMIC); skb_p = skb_copy(orig_skb_pP, GFP_ATOMIC);
if (skb_p == NULL) {
return NF_ACCEPT; if (skb_p == NULL) {
} return NF_ACCEPT;
skb_p->skb_iif = orig_skb_pP->skb_iif; }
pr_info("GTPURH: skb protocol %04X\n", orig_skb_pP->protocol);
skb_p->protocol = orig_skb_pP->protocol; skb_p->skb_iif = orig_skb_pP->skb_iif;
pr_info("GTPURH: skb protocol %04X\n", orig_skb_pP->protocol);
skb_p->protocol = orig_skb_pP->protocol;
#else #else
skb_p = orig_skb_pP; skb_p = orig_skb_pP;
if (skb_linearize(skb_p) < 0) {
pr_info("GTPURH: skb DROPPED (no linearize)\n");
return NF_DROP;
}
#endif
//---------------------------
// check if is GTPU TUNNEL
if (iph_p->protocol != IPPROTO_UDP) {
pr_info("GTPURH: skb DROPPED Not GTPV1U packet (not UDP)\n");
return NF_ACCEPT;
}
//--------------------------- if (skb_linearize(skb_p) < 0) {
// check if is fragment pr_info("GTPURH: skb DROPPED (no linearize)\n");
// but should not happen since MTU should have been set bigger than 1500 + GTP encap.
// TO DO later segment, but did not succeed in getting in this target all framents of an ip packet!
if (_gtpurh_ip_is_fragment(iph_p)) {
pr_info("GTPURH: ip_is_fragment YES, FLAGS %04X & %04X = %04X\n",
iph_p->frag_off,
htons(IP_MF | IP_OFFSET),
iph_p->frag_off & htons(IP_MF | IP_OFFSET));
return NF_ACCEPT;
}
if (skb_p->len <= sizeof (struct udphdr) + sizeof (struct gtpuhdr) + sizeof (struct iphdr)) {
pr_info("GTPURH: Thought was GTPV1U packet but too short length\n");
return NF_ACCEPT;
}
/* Remove IP header */
udph_p = (struct udphdr*)skb_pull(skb_p, (iph_p->ihl << 2));
if (udph_p->dest != htons(GTPURH_PORT)) {
pr_info("GTPURH: Not GTPV1U packet (bad UDP dest port)\n");
skb_push(skb_p, (iph_p->ihl << 2));
return NF_ACCEPT;
}
/* Remove UDP header */
gtpuh_p = (struct gtpuhdr*)skb_pull(skb_p, sizeof(struct udphdr));
gtp_payload_size = ntohs(gtpuh_p->length);
skb_p->mark = ntohl(gtpuh_p->tunid);
/* Remove GTPu header */
skb_pull(skb_p, sizeof(struct gtpuhdr));
/* If additional fields are present in header, remove them also */
if (gtpuh_p->flags & GTPURH_ANY_EXT_HDR_BIT)
{
pr_info("GTPURH: GTPURH_ANY_EXT_HDR_BIT found\n");
skb_pull(skb_p, sizeof(short) + sizeof(char) + sizeof(char)); /* #Seq, #N-PDU, #ExtHdr Type */
gtp_payload_size = gtp_payload_size - sizeof(short) - sizeof(char) - sizeof(char);
}
skb_set_network_header(skb_p, 0);
iph2_p = ip_hdr(skb_p);
skb_set_transport_header(skb_p, iph2_p->ihl << 2);
if ((iph2_p->version != 4 ) && (iph2_p->version != 6)) {
pr_info("\nGTPURH: Decapsulated packet dropped because not IPvx protocol see all GTPU packet here:\n");
_gtpurh_print_hex_octets((unsigned char*)iph_p, ntohs(iph_p->tot_len));
return NF_DROP;
}
#if 0
if ((skb_p->mark == 0) || (gtp_payload_size != ntohs(iph2_p->tot_len))) {
pr_info("\nGTPURH: Decapsulated packet: %d.%d.%d.%d --> %d.%d.%d.%d Proto: %d, Total Len (IP): %u mark %u Frag offset %u Flags 0x%0x\n",
iph2_p->saddr & 0xFF,
(iph2_p->saddr & 0x0000FF00) >> 8,
(iph2_p->saddr & 0x00FF0000) >> 16,
iph2_p->saddr >> 24,
iph2_p->daddr & 0xFF,
(iph2_p->daddr & 0x0000FF00) >> 8,
(iph2_p->daddr & 0x00FF0000) >> 16,
iph2_p->daddr >> 24,
iph2_p->protocol,
ntohs(iph2_p->tot_len),
skb_p->mark,
ntohs(iph_p->frag_off) & 0x1FFFFFFF,
ntohs(iph_p->frag_off) >> 13);
if (gtp_payload_size != ntohs(iph2_p->tot_len)) {
pr_info("GTPURH: Mismatch in lengths GTPU length: %u -> %u, IP length %u\n",
ntohs(gtpuh_p->length),
gtp_payload_size,
ntohs(iph2_p->tot_len));
_gtpurh_print_hex_octets((unsigned char*)iph_p, ntohs(iph_p->tot_len));
return NF_DROP;
}
}
#endif
/* Route the packet */
#if defined(ROUTE_PACKET)
_gtpurh_route_packet(skb_p, tgi_pP);
return NF_DROP; return NF_DROP;
#else }
{
int err = 0;
struct rtable *rt = NULL;
int daddr = iph2_p->daddr;
struct flowi fl = {
.u = {
.ip4 = {
.daddr = daddr,
.flowi4_tos = RT_TOS(iph2_p->tos),
.flowi4_scope = RT_SCOPE_UNIVERSE,
}
}
};
rt = ip_route_output_key(&init_net, &fl.u.ip4);
if (rt == NULL) {
pr_info("GTPURH: Failed to route packet to dst 0x%x. Error: (%d)\n", fl.u.ip4.daddr, err);
return NF_DROP;
}
#if 0
if (rt->dst.dev) {
pr_info("GTPURH: dst dev name %s\n", rt->dst.dev->name);
} else {
pr_info("GTPURH: dst dev NULL\n");
return NF_DROP;
}
#endif #endif
skb_p->priority = rt_tos2priority(iph2_p->tos);
skb_p->pkt_type = PACKET_OTHERHOST; //---------------------------
skb_dst_drop(skb_p); // check if is GTPU TUNNEL
skb_dst_set(skb_p, dst_clone(&rt->dst)); if (iph_p->protocol != IPPROTO_UDP) {
skb_p->dev = skb_dst(skb_p)->dev; pr_info("GTPURH: skb DROPPED Not GTPV1U packet (not UDP)\n");
return NF_ACCEPT;
}
//---------------------------
// check if is fragment
// but should not happen since MTU should have been set bigger than 1500 + GTP encap.
// TO DO later segment, but did not succeed in getting in this target all framents of an ip packet!
if (_gtpurh_ip_is_fragment(iph_p)) {
pr_info("GTPURH: ip_is_fragment YES, FLAGS %04X & %04X = %04X\n",
iph_p->frag_off,
htons(IP_MF | IP_OFFSET),
iph_p->frag_off & htons(IP_MF | IP_OFFSET));
return NF_ACCEPT;
}
if (skb_p->len <= sizeof (struct udphdr) + sizeof (struct gtpuhdr) + sizeof (struct iphdr)) {
pr_info("GTPURH: Thought was GTPV1U packet but too short length\n");
return NF_ACCEPT;
}
/* Remove IP header */
udph_p = (struct udphdr*)skb_pull(skb_p, (iph_p->ihl << 2));
if (udph_p->dest != htons(GTPURH_PORT)) {
pr_info("GTPURH: Not GTPV1U packet (bad UDP dest port)\n");
skb_push(skb_p, (iph_p->ihl << 2));
return NF_ACCEPT;
}
/* Remove UDP header */
gtpuh_p = (struct gtpuhdr*)skb_pull(skb_p, sizeof(struct udphdr));
gtp_payload_size = ntohs(gtpuh_p->length);
skb_p->mark = ntohl(gtpuh_p->tunid);
/* Remove GTPu header */
skb_pull(skb_p, sizeof(struct gtpuhdr));
/* If additional fields are present in header, remove them also */
if (gtpuh_p->flags & GTPURH_ANY_EXT_HDR_BIT) {
pr_info("GTPURH: GTPURH_ANY_EXT_HDR_BIT found\n");
skb_pull(skb_p, sizeof(short) + sizeof(char) + sizeof(char)); /* #Seq, #N-PDU, #ExtHdr Type */
gtp_payload_size = gtp_payload_size - sizeof(short) - sizeof(char) - sizeof(char);
}
skb_set_network_header(skb_p, 0);
iph2_p = ip_hdr(skb_p);
skb_set_transport_header(skb_p, iph2_p->ihl << 2);
if ((iph2_p->version != 4 ) && (iph2_p->version != 6)) {
pr_info("\nGTPURH: Decapsulated packet dropped because not IPvx protocol see all GTPU packet here:\n");
_gtpurh_print_hex_octets((unsigned char*)iph_p, ntohs(iph_p->tot_len));
return NF_DROP;
}
#if 0
if ((skb_p->mark == 0) || (gtp_payload_size != ntohs(iph2_p->tot_len))) {
pr_info("\nGTPURH: Decapsulated packet: %d.%d.%d.%d --> %d.%d.%d.%d Proto: %d, Total Len (IP): %u mark %u Frag offset %u Flags 0x%0x\n",
iph2_p->saddr & 0xFF,
(iph2_p->saddr & 0x0000FF00) >> 8,
(iph2_p->saddr & 0x00FF0000) >> 16,
iph2_p->saddr >> 24,
iph2_p->daddr & 0xFF,
(iph2_p->daddr & 0x0000FF00) >> 8,
(iph2_p->daddr & 0x00FF0000) >> 16,
iph2_p->daddr >> 24,
iph2_p->protocol,
ntohs(iph2_p->tot_len),
skb_p->mark,
ntohs(iph_p->frag_off) & 0x1FFFFFFF,
ntohs(iph_p->frag_off) >> 13);
if (gtp_payload_size != ntohs(iph2_p->tot_len)) {
pr_info("GTPURH: Mismatch in lengths GTPU length: %u -> %u, IP length %u\n",
ntohs(gtpuh_p->length),
gtp_payload_size,
ntohs(iph2_p->tot_len));
_gtpurh_print_hex_octets((unsigned char*)iph_p, ntohs(iph_p->tot_len));
return NF_DROP;
}
}
#endif
/* Route the packet */
#if defined(ROUTE_PACKET)
_gtpurh_route_packet(skb_p, tgi_pP);
return NF_DROP;
#else
{
int err = 0;
struct rtable *rt = NULL;
int daddr = iph2_p->daddr;
struct flowi fl = {
.u = {
.ip4 = {
.daddr = daddr,
.flowi4_tos = RT_TOS(iph2_p->tos),
.flowi4_scope = RT_SCOPE_UNIVERSE,
}
}
};
rt = ip_route_output_key(&init_net, &fl.u.ip4);
if (rt == NULL) {
pr_info("GTPURH: Failed to route packet to dst 0x%x. Error: (%d)\n", fl.u.ip4.daddr, err);
return NF_DROP;
}
#if 0
if (rt->dst.dev) {
pr_info("GTPURH: dst dev name %s\n", rt->dst.dev->name);
} else {
pr_info("GTPURH: dst dev NULL\n");
return NF_DROP;
}
#endif
skb_p->priority = rt_tos2priority(iph2_p->tos);
skb_p->pkt_type = PACKET_OTHERHOST;
skb_dst_drop(skb_p);
skb_dst_set(skb_p, dst_clone(&rt->dst));
skb_p->dev = skb_dst(skb_p)->dev;
#if defined(NEW_SKB) #if defined(NEW_SKB)
new_skb_p = alloc_skb(LL_MAX_HEADER + ntohs(iph2_p->tot_len), GFP_ATOMIC); new_skb_p = alloc_skb(LL_MAX_HEADER + ntohs(iph2_p->tot_len), GFP_ATOMIC);
if (new_skb_p == NULL) {
return NF_DROP; if (new_skb_p == NULL) {
} return NF_DROP;
}
skb_reserve(new_skb_p, LL_MAX_HEADER + ntohs(iph2_p->tot_len)); skb_reserve(new_skb_p, LL_MAX_HEADER + ntohs(iph2_p->tot_len));
new_skb_p->protocol = skb_p->protocol; new_skb_p->protocol = skb_p->protocol;
new_ip_p = (void *)skb_push(new_skb_p, ntohs(iph2_p->tot_len) - (iph2_p->ihl << 2)); new_ip_p = (void *)skb_push(new_skb_p, ntohs(iph2_p->tot_len) - (iph2_p->ihl << 2));
skb_reset_transport_header(new_skb_p); skb_reset_transport_header(new_skb_p);
new_ip_p = (void *)skb_push(new_skb_p, iph2_p->ihl << 2); new_ip_p = (void *)skb_push(new_skb_p, iph2_p->ihl << 2);
memcpy(new_ip_p, iph2_p, ntohs(iph2_p->tot_len)); memcpy(new_ip_p, iph2_p, ntohs(iph2_p->tot_len));
skb_reset_network_header(new_skb_p); skb_reset_network_header(new_skb_p);
skb_reset_inner_network_header(new_skb_p); skb_reset_inner_network_header(new_skb_p);
skb_reset_inner_transport_header(new_skb_p); skb_reset_inner_transport_header(new_skb_p);
new_skb_p->mark = ntohl(gtpuh_p->tunid); new_skb_p->mark = ntohl(gtpuh_p->tunid);
//new_skb_p->mark = skb_p->mark; //new_skb_p->mark = skb_p->mark;
/* ip_route_me_harder expects skb->dst to be set */ /* ip_route_me_harder expects skb->dst to be set */
skb_dst_set(new_skb_p, dst_clone(skb_dst(skb_p))); skb_dst_set(new_skb_p, dst_clone(skb_dst(skb_p)));
/*if (ip_route_me_harder(new_skb_p, RTN_UNSPEC) < 0) { /*if (ip_route_me_harder(new_skb_p, RTN_UNSPEC) < 0) {
pr_info("GTPURH: cannot route harder dest 0x%x\n", daddr); pr_info("GTPURH: cannot route harder dest 0x%x\n", daddr);
goto free_skb; goto free_skb;
}*/ }*/
new_ip_p->ttl = new_ip_p->ttl -1; // ip4_dst_hoplimit(skb_dst(new_skb_p)); new_ip_p->ttl = new_ip_p->ttl -1; // ip4_dst_hoplimit(skb_dst(new_skb_p));
new_skb_p->ip_summed = CHECKSUM_NONE; new_skb_p->ip_summed = CHECKSUM_NONE;
if (new_skb_p->len > dst_mtu(skb_dst(new_skb_p))) { if (new_skb_p->len > dst_mtu(skb_dst(new_skb_p))) {
pr_info("GTPURH: bad length\n"); pr_info("GTPURH: bad length\n");
goto free_skb; goto free_skb;
} }
nf_ct_attach(new_skb_p, skb_p); nf_ct_attach(new_skb_p, skb_p);
/*pr_info("GTPURH: ip_local_out %s/%s dev %s src %u.%u.%u.%u dst %u.%u.%u.%u\n", /*pr_info("GTPURH: ip_local_out %s/%s dev %s src %u.%u.%u.%u dst %u.%u.%u.%u\n",
_gtpurh_nf_inet_hook_2_string(par_pP->hooknum), _gtpurh_nf_inet_hook_2_string(par_pP->hooknum),
gtpurh_tg_reg[0].table, gtpurh_tg_reg[0].table,
(new_skb_p->dev == NULL) ? "NULL" : new_skb_p->dev->name, (new_skb_p->dev == NULL) ? "NULL" : new_skb_p->dev->name,
NIPADDR(new_ip_p->saddr), NIPADDR(new_ip_p->saddr),
NIPADDR(new_ip_p->daddr));*/ NIPADDR(new_ip_p->daddr));*/
ip_local_out(new_skb_p); ip_local_out(new_skb_p);
return NF_DROP; return NF_DROP;
free_skb: free_skb:
pr_info("GTPURH: Dropped skb ip_local_out %s/%s\n", pr_info("GTPURH: Dropped skb ip_local_out %s/%s\n",
_gtpurh_nf_inet_hook_2_string(par_pP->hooknum), _gtpurh_nf_inet_hook_2_string(par_pP->hooknum),
gtpurh_tg_reg[0].table); gtpurh_tg_reg[0].table);
kfree_skb(new_skb_p); kfree_skb(new_skb_p);
return NF_DROP; return NF_DROP;
#else #else
return NF_ACCEPT; return NF_ACCEPT;
free_skb: free_skb:
pr_info("GTPURH: Dropped skb\n"); pr_info("GTPURH: Dropped skb\n");
kfree_skb(skb_p); kfree_skb(skb_p);
return NF_DROP; return NF_DROP;
#endif #endif
} }
#endif #endif
} }
@@ -468,17 +510,18 @@ static unsigned int
gtpurh_tg6(struct sk_buff *skb_pP, const struct xt_action_param *par_pP) gtpurh_tg6(struct sk_buff *skb_pP, const struct xt_action_param *par_pP)
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
{ {
const struct xt_gtpurh_target_info *tgi_p = par_pP->targinfo; const struct xt_gtpurh_target_info *tgi_p = par_pP->targinfo;
int result = NF_DROP; int result = NF_DROP;
if (tgi_p == NULL) { if (tgi_p == NULL) {
return result;
}
if (tgi_p->action == PARAM_GTPURH_ACTION_REM) {
result = NF_DROP; // TO DO
}
return result; return result;
}
if (tgi_p->action == PARAM_GTPURH_ACTION_REM) {
result = NF_DROP; // TO DO
}
return result;
} }
#endif #endif
@@ -487,67 +530,70 @@ static unsigned int
gtpurh_tg4(struct sk_buff *skb_pP, const struct xt_action_param *par_pP) gtpurh_tg4(struct sk_buff *skb_pP, const struct xt_action_param *par_pP)
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
{ {
const struct iphdr *iph_p = ip_hdr(skb_pP); const struct iphdr *iph_p = ip_hdr(skb_pP);
const struct rtable *rt_p = skb_rtable(skb_pP); const struct rtable *rt_p = skb_rtable(skb_pP);
const struct xt_gtpurh_target_info *tgi_p = par_pP->targinfo; const struct xt_gtpurh_target_info *tgi_p = par_pP->targinfo;
if (tgi_p == NULL) { if (tgi_p == NULL) {
return NF_ACCEPT; return NF_ACCEPT;
} }
if ((tgi_p->raddr != iph_p->saddr) || (tgi_p->laddr != iph_p->daddr)) { if ((tgi_p->raddr != iph_p->saddr) || (tgi_p->laddr != iph_p->daddr)) {
pr_info("GTPURH: Not processed because of not matching saddr %d.%d.%d.%d raddr %d.%d.%d.%d laddr %d.%d.%d.%d daddr %d.%d.%d.%d\n", pr_info("GTPURH: Not processed because of not matching saddr %d.%d.%d.%d raddr %d.%d.%d.%d laddr %d.%d.%d.%d daddr %d.%d.%d.%d\n",
NIPADDR(tgi_p->raddr), NIPADDR(tgi_p->raddr),
NIPADDR(iph_p->saddr), NIPADDR(iph_p->saddr),
NIPADDR(tgi_p->laddr), NIPADDR(tgi_p->laddr),
NIPADDR(iph_p->daddr)); NIPADDR(iph_p->daddr));
return NF_ACCEPT; return NF_ACCEPT;
} }
if (ip_hdrlen(skb_pP) != sizeof(struct iphdr)) { if (ip_hdrlen(skb_pP) != sizeof(struct iphdr)) {
pr_info("GTPURH: Dropped because IP options\n"); pr_info("GTPURH: Dropped because IP options\n");
return NF_DROP;
}
// Drop fragments
if (iph_p->frag_off & htons(IP_OFFSET)) {
pr_info("GTPURH: Dropped because is fragment\n");
return NF_DROP;
}
if (tgi_p->action == PARAM_GTPURH_ACTION_REM) {
return _gtpurh_tg4_rem(skb_pP, par_pP);
}
return NF_DROP; return NF_DROP;
}
// Drop fragments
if (iph_p->frag_off & htons(IP_OFFSET)) {
pr_info("GTPURH: Dropped because is fragment\n");
return NF_DROP;
}
if (tgi_p->action == PARAM_GTPURH_ACTION_REM) {
return _gtpurh_tg4_rem(skb_pP, par_pP);
}
return NF_DROP;
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
static int static int
__init gtpurh_tg_init(void) { __init gtpurh_tg_init(void)
//----------------------------------------------------------------------------- {
//-----------------------------------------------------------------------------
pr_info("GTPURH: Initializing module (KVersion: %d)\n", KVERSION); pr_info("GTPURH: Initializing module (KVersion: %d)\n", KVERSION);
pr_info("GTPURH: Copyright Polaris Networks 2010-2011\n"); pr_info("GTPURH: Copyright Polaris Networks 2010-2011\n");
pr_info("GTPURH: Modified by EURECOM Lionel GAUTHIER 2014\n"); pr_info("GTPURH: Modified by EURECOM Lionel GAUTHIER 2014\n");
#ifndef CMAKER #ifndef CMAKER
pr_info("GTPURH: Compiled %s at time %s\n",__DATE__,__TIME__); pr_info("GTPURH: Compiled %s at time %s\n",__DATE__,__TIME__);
#endif
#if defined(WITH_IPV6)
pr_info("GTPURH: IPv4/IPv6 enabled\n");
#else
pr_info("GTPURH: IPv4 only enabled\n");
#endif #endif
return xt_register_targets(gtpurh_tg_reg, ARRAY_SIZE(gtpurh_tg_reg)); #if defined(WITH_IPV6)
pr_info("GTPURH: IPv4/IPv6 enabled\n");
#else
pr_info("GTPURH: IPv4 only enabled\n");
#endif
return xt_register_targets(gtpurh_tg_reg, ARRAY_SIZE(gtpurh_tg_reg));
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
static void static void
__exit gtpurh_tg_exit(void) { __exit gtpurh_tg_exit(void)
//----------------------------------------------------------------------------- {
//-----------------------------------------------------------------------------
xt_unregister_targets(gtpurh_tg_reg, ARRAY_SIZE(gtpurh_tg_reg)); xt_unregister_targets(gtpurh_tg_reg, ARRAY_SIZE(gtpurh_tg_reg));
pr_info("GTPURH: Unloading module\n"); pr_info("GTPURH: Unloading module\n");
} }
module_init(gtpurh_tg_init); module_init(gtpurh_tg_init);
+8 -10
View File
@@ -9,18 +9,16 @@
* *
*/ */
enum xt_gtpurh_mode_ enum xt_gtpurh_mode_ {
{ PARAM_GTPURH_ACTION_REM = 1 << 9,
PARAM_GTPURH_ACTION_REM = 1 << 9,
}; };
struct xt_gtpurh_target_info struct xt_gtpurh_target_info {
{ u_int32_t laddr __attribute__((aligned(8)));
u_int32_t laddr __attribute__((aligned(8))); u_int32_t raddr __attribute__((aligned(8)));
u_int32_t raddr __attribute__((aligned(8))); u_int32_t ltun __attribute__((aligned(8)));
u_int32_t ltun __attribute__((aligned(8))); u_int32_t rtun __attribute__((aligned(8)));
u_int32_t rtun __attribute__((aligned(8))); u_int32_t action __attribute__((aligned(8)));
u_int32_t action __attribute__((aligned(8)));
}; };
File diff suppressed because it is too large Load Diff
+59 -59
View File
@@ -46,93 +46,93 @@
#define GTPV1U_MAX_BEARERS_ID (max_val_DRB_Identity - GTPV1U_BEARER_OFFSET) #define GTPV1U_MAX_BEARERS_ID (max_val_DRB_Identity - GTPV1U_BEARER_OFFSET)
typedef enum { typedef enum {
BEARER_DOWN = 0, BEARER_DOWN = 0,
BEARER_IN_CONFIG, BEARER_IN_CONFIG,
BEARER_UP, BEARER_UP,
BEARER_DL_HANDOVER, BEARER_DL_HANDOVER,
BEARER_UL_HANDOVER, BEARER_UL_HANDOVER,
BEARER_MAX, BEARER_MAX,
} bearer_state_t; } bearer_state_t;
typedef struct gtpv1u_teid_data_s { typedef struct gtpv1u_teid_data_s {
/* UE identifier for oaisim stack */ /* UE identifier for oaisim stack */
module_id_t enb_id; module_id_t enb_id;
module_id_t ue_id; module_id_t ue_id;
ebi_t eps_bearer_id; ebi_t eps_bearer_id;
} gtpv1u_teid_data_t; } gtpv1u_teid_data_t;
typedef struct gtpv1u_bearer_s { typedef struct gtpv1u_bearer_s {
/* TEID used in dl and ul */ /* TEID used in dl and ul */
teid_t teid_eNB; ///< eNB TEID teid_t teid_eNB; ///< eNB TEID
teid_t teid_sgw; ///< Remote TEID teid_t teid_sgw; ///< Remote TEID
in_addr_t sgw_ip_addr; in_addr_t sgw_ip_addr;
struct in6_addr sgw_ip6_addr; struct in6_addr sgw_ip6_addr;
tcp_udp_port_t port; tcp_udp_port_t port;
//NwGtpv1uStackSessionHandleT stack_session; //NwGtpv1uStackSessionHandleT stack_session;
bearer_state_t state; bearer_state_t state;
} gtpv1u_bearer_t; } gtpv1u_bearer_t;
typedef struct gtpv1u_ue_data_s { typedef struct gtpv1u_ue_data_s {
/* UE identifier for oaisim stack */ /* UE identifier for oaisim stack */
module_id_t ue_id; module_id_t ue_id;
/* Unique identifier used between PDCP and GTP-U to distinguish UEs */ /* Unique identifier used between PDCP and GTP-U to distinguish UEs */
uint32_t instance_id; uint32_t instance_id;
int num_bearers; int num_bearers;
/* Bearer related data. /* Bearer related data.
* Note that the first LCID available for data is 3 and we fixed the maximum * Note that the first LCID available for data is 3 and we fixed the maximum
* number of e-rab per UE to be (32 [id range]), max RB is 11. The real rb id will 3 + rab_id (3..32). * number of e-rab per UE to be (32 [id range]), max RB is 11. The real rb id will 3 + rab_id (3..32).
*/ */
gtpv1u_bearer_t bearers[GTPV1U_MAX_BEARERS_ID]; gtpv1u_bearer_t bearers[GTPV1U_MAX_BEARERS_ID];
//RB_ENTRY(gtpv1u_ue_data_s) gtpv1u_ue_node; //RB_ENTRY(gtpv1u_ue_data_s) gtpv1u_ue_node;
} gtpv1u_ue_data_t; } gtpv1u_ue_data_t;
typedef struct gtpv1u_data_s{ typedef struct gtpv1u_data_s {
/* nwgtpv1u stack internal data */ /* nwgtpv1u stack internal data */
NwGtpv1uStackHandleT gtpv1u_stack; NwGtpv1uStackHandleT gtpv1u_stack;
/* RB tree of UEs */ /* RB tree of UEs */
hash_table_t *ue_mapping; // PDCP->GTPV1U hash_table_t *ue_mapping; // PDCP->GTPV1U
hash_table_t *teid_mapping; // GTPV1U -> PDCP hash_table_t *teid_mapping; // GTPV1U -> PDCP
//RB_HEAD(gtpv1u_ue_map, gtpv1u_ue_data_s) gtpv1u_ue_map_head; //RB_HEAD(gtpv1u_ue_map, gtpv1u_ue_data_s) gtpv1u_ue_map_head;
/* Local IP address to use */ /* Local IP address to use */
in_addr_t enb_ip_address_for_S1u_S12_S4_up; in_addr_t enb_ip_address_for_S1u_S12_S4_up;
char *ip_addr; char *ip_addr;
tcp_udp_port_t enb_port_for_S1u_S12_S4_up; tcp_udp_port_t enb_port_for_S1u_S12_S4_up;
/* UDP internal data */ /* UDP internal data */
//udp_data_t udp_data; //udp_data_t udp_data;
uint16_t seq_num; uint16_t seq_num;
uint8_t restart_counter; uint8_t restart_counter;
#ifdef GTPU_IN_KERNEL #ifdef GTPU_IN_KERNEL
char *interface_name; char *interface_name;
int interface_index; int interface_index;
struct iovec *malloc_ring; struct iovec *malloc_ring;
void *sock_mmap_ring[16]; void *sock_mmap_ring[16];
int sock_desc[16]; // indexed by marking int sock_desc[16]; // indexed by marking
#endif #endif
} gtpv1u_data_t; } gtpv1u_data_t;
int int
gtpv1u_new_data_req( gtpv1u_new_data_req(
uint8_t enb_id, uint8_t enb_id,
uint8_t ue_id, uint8_t ue_id,
uint8_t rab_id, uint8_t rab_id,
uint8_t *buffer, uint8_t *buffer,
uint32_t buf_len, uint32_t buf_len,
uint32_t buf_offset); uint32_t buf_offset);
int int
gtpv1u_initial_req( gtpv1u_initial_req(
gtpv1u_data_t *gtpv1u_data_p, gtpv1u_data_t *gtpv1u_data_p,
uint32_t teid, uint32_t teid,
uint16_t port, uint16_t port,
uint32_t address); uint32_t address);
#endif /* GTPV1U_ENB_DEFS_H_ */ #endif /* GTPV1U_ENB_DEFS_H_ */
+5 -5
View File
@@ -38,11 +38,11 @@
int int
gtpv1u_new_data_req( gtpv1u_new_data_req(
uint8_t enb_id, uint8_t enb_id,
uint8_t ue_id, uint8_t ue_id,
uint8_t rab_id, uint8_t rab_id,
uint8_t *buffer, uint8_t *buffer,
uint32_t buf_len); uint32_t buf_len);
void *gtpv1u_eNB_task(void *args); void *gtpv1u_eNB_task(void *args);
#endif /* GTPV1U_ENB_TASK_H_ */ #endif /* GTPV1U_ENB_TASK_H_ */
+22 -22
View File
@@ -40,12 +40,12 @@
#define MAX_BEARERS_PER_UE (11) #define MAX_BEARERS_PER_UE (11)
typedef enum { typedef enum {
BEARER_DOWN = 0, BEARER_DOWN = 0,
BEARER_IN_CONFIG, BEARER_IN_CONFIG,
BEARER_UP, BEARER_UP,
BEARER_DL_HANDOVER, BEARER_DL_HANDOVER,
BEARER_UL_HANDOVER, BEARER_UL_HANDOVER,
BEARER_MAX, BEARER_MAX,
} bearer_state_t; } bearer_state_t;
#define BUFFER_TO_NwU32T(buf, x) \ #define BUFFER_TO_NwU32T(buf, x) \
@@ -59,11 +59,11 @@ do { \
typedef struct gtpv1u_teid2enb_info_s { typedef struct gtpv1u_teid2enb_info_s {
/* TEID used in dl and ul */ /* TEID used in dl and ul */
uint32_t teid_enb; ///< Remote eNB TEID uint32_t teid_enb; ///< Remote eNB TEID
ip_address_t enb_ip_addr; ip_address_t enb_ip_addr;
bearer_state_t state; bearer_state_t state;
uint16_t port; /// LG ??? uint16_t port; /// LG ???
} gtpv1u_teid2enb_info_t; } gtpv1u_teid2enb_info_t;
/*struct gtpv1u_ue_data_s { /*struct gtpv1u_ue_data_s {
@@ -83,18 +83,18 @@ typedef struct gtpv1u_teid2enb_info_s {
};*/ };*/
typedef struct { typedef struct {
/* nwgtpv1u stack internal data */ /* nwgtpv1u stack internal data */
NwGtpv1uStackHandleT gtpv1u_stack; NwGtpv1uStackHandleT gtpv1u_stack;
/* RB tree of UEs */ /* RB tree of UEs */
//RB_HEAD(gtpv1u_ue_map, gtpv1u_ue_data_s) gtpv1u_ue_map_head; //RB_HEAD(gtpv1u_ue_map, gtpv1u_ue_data_s) gtpv1u_ue_map_head;
/* Local IP address to use */ /* Local IP address to use */
uint32_t sgw_ip_address_for_S1u_S12_S4_up; uint32_t sgw_ip_address_for_S1u_S12_S4_up;
char *ip_addr; char *ip_addr;
uint16_t seq_num; uint16_t seq_num;
uint8_t restart_counter; uint8_t restart_counter;
//gtpv1u_teid2enb_info_t* teid2enb_mapping[]; //gtpv1u_teid2enb_info_t* teid2enb_mapping[];
hash_table_t *S1U_mapping; hash_table_t *S1U_mapping;
} gtpv1u_data_t; } gtpv1u_data_t;
+436 -407
View File
@@ -61,23 +61,23 @@ static int gtpv1u_update_s1u_tunnel(Gtpv1uUpdateTunnelReq *reqP);
static void *gtpv1u_thread(void *args); static void *gtpv1u_thread(void *args);
NwGtpv1uRcT gtpv1u_send_udp_msg( NwGtpv1uRcT gtpv1u_send_udp_msg(
NwGtpv1uUdpHandleT udpHandle, NwGtpv1uUdpHandleT udpHandle,
NwU8T *buffer, NwU8T *buffer,
NwU32T buffer_len, NwU32T buffer_len,
NwU32T buffer_offset, NwU32T buffer_offset,
NwU32T peerIpAddr, NwU32T peerIpAddr,
NwU32T peerPort); NwU32T peerPort);
NwGtpv1uRcT gtpv1u_log_request( NwGtpv1uRcT gtpv1u_log_request(
NwGtpv1uLogMgrHandleT hLogMgr, NwGtpv1uLogMgrHandleT hLogMgr,
NwU32T logLevel, NwU32T logLevel,
NwCharT *file, NwCharT *file,
NwU32T line, NwU32T line,
NwCharT *logStr); NwCharT *logStr);
NwGtpv1uRcT gtpv1u_process_stack_req( NwGtpv1uRcT gtpv1u_process_stack_req(
NwGtpv1uUlpHandleT hUlp, NwGtpv1uUlpHandleT hUlp,
NwGtpv1uUlpApiT *pUlpApi); NwGtpv1uUlpApiT *pUlpApi);
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@@ -107,21 +107,25 @@ void gtpu_print_hex_octets(unsigned char* dataP, unsigned long sizeP)
GTPU_DEBUG("%s------+-------------------------------------------------|\n",timeofday); GTPU_DEBUG("%s------+-------------------------------------------------|\n",timeofday);
GTPU_DEBUG("%s | 0 1 2 3 4 5 6 7 8 9 a b c d e f |\n",timeofday); GTPU_DEBUG("%s | 0 1 2 3 4 5 6 7 8 9 a b c d e f |\n",timeofday);
GTPU_DEBUG("%s------+-------------------------------------------------|\n",timeofday); GTPU_DEBUG("%s------+-------------------------------------------------|\n",timeofday);
for (octet_index = 0; octet_index < sizeP; octet_index++) { for (octet_index = 0; octet_index < sizeP; octet_index++) {
if (GTPU_2_PRINT_BUFFER_LEN < (buffer_marker + 32)) { if (GTPU_2_PRINT_BUFFER_LEN < (buffer_marker + 32)) {
buffer_marker+=snprintf(&gtpu_2_print_buffer[buffer_marker], GTPU_2_PRINT_BUFFER_LEN - buffer_marker, buffer_marker+=snprintf(&gtpu_2_print_buffer[buffer_marker], GTPU_2_PRINT_BUFFER_LEN - buffer_marker,
"... (print buffer overflow)"); "... (print buffer overflow)");
GTPU_DEBUG("%s%s",timeofday,gtpu_2_print_buffer); GTPU_DEBUG("%s%s",timeofday,gtpu_2_print_buffer);
return; return;
} }
if ((octet_index % 16) == 0){
if ((octet_index % 16) == 0) {
if (octet_index != 0) { if (octet_index != 0) {
buffer_marker+=snprintf(&gtpu_2_print_buffer[buffer_marker], GTPU_2_PRINT_BUFFER_LEN - buffer_marker, " |\n"); buffer_marker+=snprintf(&gtpu_2_print_buffer[buffer_marker], GTPU_2_PRINT_BUFFER_LEN - buffer_marker, " |\n");
GTPU_DEBUG("%s%s",timeofday, gtpu_2_print_buffer); GTPU_DEBUG("%s%s",timeofday, gtpu_2_print_buffer);
buffer_marker = 0; buffer_marker = 0;
} }
buffer_marker+=snprintf(&gtpu_2_print_buffer[buffer_marker], GTPU_2_PRINT_BUFFER_LEN - buffer_marker, " %04ld |", octet_index); buffer_marker+=snprintf(&gtpu_2_print_buffer[buffer_marker], GTPU_2_PRINT_BUFFER_LEN - buffer_marker, " %04ld |", octet_index);
} }
/* /*
* Print every single octet in hexadecimal form * Print every single octet in hexadecimal form
*/ */
@@ -136,7 +140,8 @@ void gtpu_print_hex_octets(unsigned char* dataP, unsigned long sizeP)
*/ */
for (aindex = octet_index; aindex < 16; ++aindex) for (aindex = octet_index; aindex < 16; ++aindex)
buffer_marker+=snprintf(&gtpu_2_print_buffer[buffer_marker], GTPU_2_PRINT_BUFFER_LEN - buffer_marker, " "); buffer_marker+=snprintf(&gtpu_2_print_buffer[buffer_marker], GTPU_2_PRINT_BUFFER_LEN - buffer_marker, " ");
//GTPU_DEBUG(" ");
//GTPU_DEBUG(" ");
buffer_marker+=snprintf(&gtpu_2_print_buffer[buffer_marker], GTPU_2_PRINT_BUFFER_LEN - buffer_marker, " |\n"); buffer_marker+=snprintf(&gtpu_2_print_buffer[buffer_marker], GTPU_2_PRINT_BUFFER_LEN - buffer_marker, " |\n");
GTPU_DEBUG("%s%s",timeofday,gtpu_2_print_buffer); GTPU_DEBUG("%s%s",timeofday,gtpu_2_print_buffer);
} }
@@ -144,23 +149,24 @@ void gtpu_print_hex_octets(unsigned char* dataP, unsigned long sizeP)
static int gtpv1u_send_init_udp(uint16_t port_number) static int gtpv1u_send_init_udp(uint16_t port_number)
{ {
// Create and alloc new message // Create and alloc new message
MessageDef *message_p; MessageDef *message_p;
struct in_addr addr; struct in_addr addr;
message_p = itti_alloc_new_message(TASK_GTPV1_U, UDP_INIT); message_p = itti_alloc_new_message(TASK_GTPV1_U, UDP_INIT);
if (message_p == NULL) {
return -1;
}
UDP_INIT(message_p).port = port_number; if (message_p == NULL) {
//LG UDP_INIT(message_p).address = "0.0.0.0"; //ANY address return -1;
}
addr.s_addr = gtpv1u_sgw_data.sgw_ip_address_for_S1u_S12_S4_up; UDP_INIT(message_p).port = port_number;
UDP_INIT(message_p).address = inet_ntoa(addr); //LG UDP_INIT(message_p).address = "0.0.0.0"; //ANY address
GTPU_DEBUG("Tx UDP_INIT IP addr %s\n", UDP_INIT(message_p).address);
return itti_send_msg_to_task(TASK_UDP, INSTANCE_DEFAULT, message_p); addr.s_addr = gtpv1u_sgw_data.sgw_ip_address_for_S1u_S12_S4_up;
UDP_INIT(message_p).address = inet_ntoa(addr);
GTPU_DEBUG("Tx UDP_INIT IP addr %s\n", UDP_INIT(message_p).address);
return itti_send_msg_to_task(TASK_UDP, INSTANCE_DEFAULT, message_p);
} }
NwGtpv1uRcT gtpv1u_log_request(NwGtpv1uLogMgrHandleT hLogMgr, NwGtpv1uRcT gtpv1u_log_request(NwGtpv1uLogMgrHandleT hLogMgr,
@@ -169,471 +175,494 @@ NwGtpv1uRcT gtpv1u_log_request(NwGtpv1uLogMgrHandleT hLogMgr,
NwU32T line, NwU32T line,
NwCharT *logStr) NwCharT *logStr)
{ {
GTPU_DEBUG("%s\n", logStr); GTPU_DEBUG("%s\n", logStr);
return NW_GTPV1U_OK; return NW_GTPV1U_OK;
} }
NwGtpv1uRcT gtpv1u_send_udp_msg( NwGtpv1uRcT gtpv1u_send_udp_msg(
NwGtpv1uUdpHandleT udpHandle, NwGtpv1uUdpHandleT udpHandle,
NwU8T *buffer, NwU8T *buffer,
NwU32T buffer_len, NwU32T buffer_len,
NwU32T buffer_offset, NwU32T buffer_offset,
NwU32T peerIpAddr, NwU32T peerIpAddr,
NwU32T peerPort) NwU32T peerPort)
{ {
// Create and alloc new message // Create and alloc new message
MessageDef *message_p; MessageDef *message_p;
udp_data_req_t *udp_data_req_p; udp_data_req_t *udp_data_req_p;
message_p = itti_alloc_new_message(TASK_GTPV1_U, UDP_DATA_REQ); message_p = itti_alloc_new_message(TASK_GTPV1_U, UDP_DATA_REQ);
udp_data_req_p = &message_p->ittiMsg.udp_data_req; udp_data_req_p = &message_p->ittiMsg.udp_data_req;
udp_data_req_p->peer_address = peerIpAddr; udp_data_req_p->peer_address = peerIpAddr;
udp_data_req_p->peer_port = peerPort; udp_data_req_p->peer_port = peerPort;
udp_data_req_p->buffer = buffer; udp_data_req_p->buffer = buffer;
udp_data_req_p->buffer_length = buffer_len; udp_data_req_p->buffer_length = buffer_len;
udp_data_req_p->buffer_offset = buffer_offset; udp_data_req_p->buffer_offset = buffer_offset;
return itti_send_msg_to_task(TASK_UDP, INSTANCE_DEFAULT, message_p); return itti_send_msg_to_task(TASK_UDP, INSTANCE_DEFAULT, message_p);
} }
/* Callback called when a gtpv1u message arrived on UDP interface */ /* Callback called when a gtpv1u message arrived on UDP interface */
NwGtpv1uRcT gtpv1u_process_stack_req( NwGtpv1uRcT gtpv1u_process_stack_req(
NwGtpv1uUlpHandleT hUlp, NwGtpv1uUlpHandleT hUlp,
NwGtpv1uUlpApiT *pUlpApi) NwGtpv1uUlpApiT *pUlpApi)
{ {
switch(pUlpApi->apiType) { switch(pUlpApi->apiType) {
/* Here there are two type of messages handled: /* Here there are two type of messages handled:
* - T-PDU * - T-PDU
* - END-MARKER * - END-MARKER
*/ */
case NW_GTPV1U_ULP_API_RECV_TPDU: { case NW_GTPV1U_ULP_API_RECV_TPDU: {
//uint8_t buffer[4096]; //uint8_t buffer[4096];
//uint32_t buffer_len; //uint32_t buffer_len;
MessageDef *message_p = NULL; MessageDef *message_p = NULL;
Gtpv1uTunnelDataInd *data_ind_p = NULL; Gtpv1uTunnelDataInd *data_ind_p = NULL;
/* Nw-gptv1u stack has processed a PDU. we can forward it to IPV4 /* Nw-gptv1u stack has processed a PDU. we can forward it to IPV4
* task for transmission. * task for transmission.
*/ */
/*if (NW_GTPV1U_OK != nwGtpv1uMsgGetTpdu(pUlpApi->apiInfo.recvMsgInfo.hMsg, /*if (NW_GTPV1U_OK != nwGtpv1uMsgGetTpdu(pUlpApi->apiInfo.recvMsgInfo.hMsg,
buffer, (NwU32T *)&buffer_len)) { buffer, (NwU32T *)&buffer_len)) {
GTPU_ERROR("Error while retrieving T-PDU\n"); GTPU_ERROR("Error while retrieving T-PDU\n");
}*/ }*/
GTPU_DEBUG("Received TPDU from gtpv1u stack %u with size %d\n", GTPU_DEBUG("Received TPDU from gtpv1u stack %u with size %d\n",
pUlpApi->apiInfo.recvMsgInfo.teid, pUlpApi->apiInfo.recvMsgInfo.teid,
((NwGtpv1uMsgT*)pUlpApi->apiInfo.recvMsgInfo.hMsg)->msgBufLen); ((NwGtpv1uMsgT*)pUlpApi->apiInfo.recvMsgInfo.hMsg)->msgBufLen);
message_p = itti_alloc_new_message(TASK_GTPV1_U, GTPV1U_TUNNEL_DATA_IND); message_p = itti_alloc_new_message(TASK_GTPV1_U, GTPV1U_TUNNEL_DATA_IND);
if (message_p == NULL) {
return -1;
}
data_ind_p = &message_p->ittiMsg.gtpv1uTunnelDataInd;
data_ind_p->buffer = ((NwGtpv1uMsgT*)pUlpApi->apiInfo.recvMsgInfo.hMsg)->msgBuf;
data_ind_p->length = ((NwGtpv1uMsgT*)pUlpApi->apiInfo.recvMsgInfo.hMsg)->msgBufLen;
data_ind_p->offset = ((NwGtpv1uMsgT*)pUlpApi->apiInfo.recvMsgInfo.hMsg)->msgBufOffset;
data_ind_p->local_S1u_teid = pUlpApi->apiInfo.recvMsgInfo.teid;
if (data_ind_p->buffer == NULL) {
GTPU_ERROR("Failed to allocate new buffer\n");
itti_free(ITTI_MSG_ORIGIN_ID(message_p), message_p);
message_p = NULL;
} else {
//memcpy(data_ind_p->buffer, buffer, buffer_len);
//data_ind_p->length = buffer_len;
if (itti_send_msg_to_task(TASK_FW_IP, INSTANCE_DEFAULT, message_p) < 0) {
GTPU_ERROR("Failed to send message to task\n");
itti_free(ITTI_MSG_ORIGIN_ID(message_p), message_p);
message_p = NULL;
}
}
}
break;
case NW_GTPV1U_ULP_API_CREATE_TUNNEL_ENDPOINT:{ if (message_p == NULL) {
} return -1;
break;
default: {
GTPU_ERROR("Received undefined UlpApi (%02x) from gtpv1u stack!\n",
pUlpApi->apiType);
}
} }
return NW_GTPV1U_OK;
data_ind_p = &message_p->ittiMsg.gtpv1uTunnelDataInd;
data_ind_p->buffer = ((NwGtpv1uMsgT*)pUlpApi->apiInfo.recvMsgInfo.hMsg)->msgBuf;
data_ind_p->length = ((NwGtpv1uMsgT*)pUlpApi->apiInfo.recvMsgInfo.hMsg)->msgBufLen;
data_ind_p->offset = ((NwGtpv1uMsgT*)pUlpApi->apiInfo.recvMsgInfo.hMsg)->msgBufOffset;
data_ind_p->local_S1u_teid = pUlpApi->apiInfo.recvMsgInfo.teid;
if (data_ind_p->buffer == NULL) {
GTPU_ERROR("Failed to allocate new buffer\n");
itti_free(ITTI_MSG_ORIGIN_ID(message_p), message_p);
message_p = NULL;
} else {
//memcpy(data_ind_p->buffer, buffer, buffer_len);
//data_ind_p->length = buffer_len;
if (itti_send_msg_to_task(TASK_FW_IP, INSTANCE_DEFAULT, message_p) < 0) {
GTPU_ERROR("Failed to send message to task\n");
itti_free(ITTI_MSG_ORIGIN_ID(message_p), message_p);
message_p = NULL;
}
}
}
break;
case NW_GTPV1U_ULP_API_CREATE_TUNNEL_ENDPOINT: {
}
break;
default: {
GTPU_ERROR("Received undefined UlpApi (%02x) from gtpv1u stack!\n",
pUlpApi->apiType);
}
}
return NW_GTPV1U_OK;
} }
static int gtpv1u_create_s1u_tunnel(Gtpv1uCreateTunnelReq *create_tunnel_reqP) static int gtpv1u_create_s1u_tunnel(Gtpv1uCreateTunnelReq *create_tunnel_reqP)
{ {
/* Create a new nw-gtpv1-u stack req using API */ /* Create a new nw-gtpv1-u stack req using API */
NwGtpv1uUlpApiT stack_req; NwGtpv1uUlpApiT stack_req;
NwGtpv1uRcT rc; NwGtpv1uRcT rc;
/* Local tunnel end-point identifier */ /* Local tunnel end-point identifier */
uint32_t s1u_teid = 0; uint32_t s1u_teid = 0;
gtpv1u_teid2enb_info_t *gtpv1u_teid2enb_info = NULL; gtpv1u_teid2enb_info_t *gtpv1u_teid2enb_info = NULL;
MessageDef *message_p = NULL; MessageDef *message_p = NULL;
hashtable_rc_t hash_rc; hashtable_rc_t hash_rc;
GTPU_DEBUG("Rx GTPV1U_CREATE_TUNNEL_REQ Context %d\n", create_tunnel_reqP->context_teid); GTPU_DEBUG("Rx GTPV1U_CREATE_TUNNEL_REQ Context %d\n", create_tunnel_reqP->context_teid);
memset(&stack_req, 0, sizeof(NwGtpv1uUlpApiT)); memset(&stack_req, 0, sizeof(NwGtpv1uUlpApiT));
stack_req.apiType = NW_GTPV1U_ULP_API_CREATE_TUNNEL_ENDPOINT; stack_req.apiType = NW_GTPV1U_ULP_API_CREATE_TUNNEL_ENDPOINT;
do { do {
s1u_teid = gtpv1u_new_teid(); s1u_teid = gtpv1u_new_teid();
GTPU_DEBUG("gtpv1u_create_s1u_tunnel() %u\n", s1u_teid); GTPU_DEBUG("gtpv1u_create_s1u_tunnel() %u\n", s1u_teid);
stack_req.apiInfo.createTunnelEndPointInfo.teid = s1u_teid; stack_req.apiInfo.createTunnelEndPointInfo.teid = s1u_teid;
stack_req.apiInfo.createTunnelEndPointInfo.hUlpSession = 0; stack_req.apiInfo.createTunnelEndPointInfo.hUlpSession = 0;
stack_req.apiInfo.createTunnelEndPointInfo.hStackSession = 0; stack_req.apiInfo.createTunnelEndPointInfo.hStackSession = 0;
rc = nwGtpv1uProcessUlpReq(gtpv1u_sgw_data.gtpv1u_stack, &stack_req); rc = nwGtpv1uProcessUlpReq(gtpv1u_sgw_data.gtpv1u_stack, &stack_req);
GTPU_DEBUG(".\n"); GTPU_DEBUG(".\n");
} while (rc != NW_GTPV1U_OK); } while (rc != NW_GTPV1U_OK);
gtpv1u_teid2enb_info = malloc (sizeof(gtpv1u_teid2enb_info_t)); gtpv1u_teid2enb_info = malloc (sizeof(gtpv1u_teid2enb_info_t));
memset(gtpv1u_teid2enb_info, 0, sizeof(gtpv1u_teid2enb_info_t)); memset(gtpv1u_teid2enb_info, 0, sizeof(gtpv1u_teid2enb_info_t));
gtpv1u_teid2enb_info->state = BEARER_IN_CONFIG; gtpv1u_teid2enb_info->state = BEARER_IN_CONFIG;
//#warning !!! hack because missing modify session request, so force enb address //#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.pdn_type = IPv4;
// gtpv1u_teid2enb_info->enb_ip_addr.address.ipv4_address[0] = 192; // 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[1] = 168;
// gtpv1u_teid2enb_info->enb_ip_addr.address.ipv4_address[2] = 1; // 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->enb_ip_addr.address.ipv4_address[3] = 2;
message_p = itti_alloc_new_message(TASK_GTPV1_U, GTPV1U_CREATE_TUNNEL_RESP); message_p = itti_alloc_new_message(TASK_GTPV1_U, GTPV1U_CREATE_TUNNEL_RESP);
message_p->ittiMsg.gtpv1uCreateTunnelResp.S1u_teid = s1u_teid; message_p->ittiMsg.gtpv1uCreateTunnelResp.S1u_teid = s1u_teid;
message_p->ittiMsg.gtpv1uCreateTunnelResp.context_teid = create_tunnel_reqP->context_teid; message_p->ittiMsg.gtpv1uCreateTunnelResp.context_teid = create_tunnel_reqP->context_teid;
message_p->ittiMsg.gtpv1uCreateTunnelResp.eps_bearer_id = create_tunnel_reqP->eps_bearer_id; message_p->ittiMsg.gtpv1uCreateTunnelResp.eps_bearer_id = create_tunnel_reqP->eps_bearer_id;
hash_rc = hashtable_is_key_exists(gtpv1u_sgw_data.S1U_mapping, s1u_teid); hash_rc = hashtable_is_key_exists(gtpv1u_sgw_data.S1U_mapping, s1u_teid);
if (hash_rc == HASH_TABLE_KEY_NOT_EXISTS) { if (hash_rc == HASH_TABLE_KEY_NOT_EXISTS) {
hash_rc = hashtable_insert(gtpv1u_sgw_data.S1U_mapping, s1u_teid, gtpv1u_teid2enb_info); hash_rc = hashtable_insert(gtpv1u_sgw_data.S1U_mapping, s1u_teid, gtpv1u_teid2enb_info);
message_p->ittiMsg.gtpv1uCreateTunnelResp.status = 0; message_p->ittiMsg.gtpv1uCreateTunnelResp.status = 0;
} else { } else {
message_p->ittiMsg.gtpv1uCreateTunnelResp.status = 0xFF; message_p->ittiMsg.gtpv1uCreateTunnelResp.status = 0xFF;
} }
GTPU_DEBUG("Tx GTPV1U_CREATE_TUNNEL_RESP Context %u teid %u eps bearer id %u status %d\n", GTPU_DEBUG("Tx GTPV1U_CREATE_TUNNEL_RESP Context %u teid %u eps bearer id %u status %d\n",
message_p->ittiMsg.gtpv1uCreateTunnelResp.context_teid, message_p->ittiMsg.gtpv1uCreateTunnelResp.context_teid,
message_p->ittiMsg.gtpv1uCreateTunnelResp.S1u_teid, message_p->ittiMsg.gtpv1uCreateTunnelResp.S1u_teid,
message_p->ittiMsg.gtpv1uCreateTunnelResp.eps_bearer_id, message_p->ittiMsg.gtpv1uCreateTunnelResp.eps_bearer_id,
message_p->ittiMsg.gtpv1uCreateTunnelResp.status); message_p->ittiMsg.gtpv1uCreateTunnelResp.status);
return itti_send_msg_to_task(TASK_SPGW_APP, INSTANCE_DEFAULT, message_p); return itti_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) static int gtpv1u_delete_s1u_tunnel(Teid_t context_teidP, Teid_t S1U_teidP)
{ {
/* Local tunnel end-point identifier */ /* Local tunnel end-point identifier */
MessageDef *message_p; MessageDef *message_p;
GTPU_DEBUG("Rx GTPV1U_DELETE_TUNNEL Context %u S1U teid %u\n", context_teidP, S1U_teidP); GTPU_DEBUG("Rx GTPV1U_DELETE_TUNNEL Context %u S1U teid %u\n", context_teidP, S1U_teidP);
message_p = itti_alloc_new_message(TASK_GTPV1_U, GTPV1U_DELETE_TUNNEL_RESP); message_p = itti_alloc_new_message(TASK_GTPV1_U, GTPV1U_DELETE_TUNNEL_RESP);
message_p->ittiMsg.gtpv1uDeleteTunnelResp.S1u_teid = S1U_teidP; message_p->ittiMsg.gtpv1uDeleteTunnelResp.S1u_teid = S1U_teidP;
message_p->ittiMsg.gtpv1uDeleteTunnelResp.context_teid = context_teidP; message_p->ittiMsg.gtpv1uDeleteTunnelResp.context_teid = context_teidP;
if (hashtable_remove(gtpv1u_sgw_data.S1U_mapping, S1U_teidP) == HASH_TABLE_OK ) { if (hashtable_remove(gtpv1u_sgw_data.S1U_mapping, S1U_teidP) == HASH_TABLE_OK ) {
message_p->ittiMsg.gtpv1uDeleteTunnelResp.status = 0; message_p->ittiMsg.gtpv1uDeleteTunnelResp.status = 0;
} else { } else {
message_p->ittiMsg.gtpv1uDeleteTunnelResp.status = -1; message_p->ittiMsg.gtpv1uDeleteTunnelResp.status = -1;
} }
GTPU_DEBUG("Tx SGW_S1U_ENDPOINT_CREATED Context %u teid %u status %d\n", context_teidP, S1U_teidP, message_p->ittiMsg.gtpv1uDeleteTunnelResp.status);
return itti_send_msg_to_task(TASK_SPGW_APP, INSTANCE_DEFAULT, message_p); GTPU_DEBUG("Tx SGW_S1U_ENDPOINT_CREATED Context %u teid %u status %d\n", context_teidP, S1U_teidP, message_p->ittiMsg.gtpv1uDeleteTunnelResp.status);
return itti_send_msg_to_task(TASK_SPGW_APP, INSTANCE_DEFAULT, message_p);
} }
static int gtpv1u_update_s1u_tunnel(Gtpv1uUpdateTunnelReq *reqP) static int gtpv1u_update_s1u_tunnel(Gtpv1uUpdateTunnelReq *reqP)
{ {
hashtable_rc_t hash_rc; hashtable_rc_t hash_rc;
gtpv1u_teid2enb_info_t *gtpv1u_teid2enb_info; gtpv1u_teid2enb_info_t *gtpv1u_teid2enb_info;
MessageDef *message_p; MessageDef *message_p;
GTPU_DEBUG("Rx GTPV1U_UPDATE_TUNNEL_REQ Context %u, S-GW S1U teid %u, eNB S1U teid %u\n", GTPU_DEBUG("Rx GTPV1U_UPDATE_TUNNEL_REQ Context %u, S-GW S1U teid %u, eNB S1U teid %u\n",
reqP->context_teid, reqP->context_teid,
reqP->sgw_S1u_teid, reqP->sgw_S1u_teid,
reqP->enb_S1u_teid); reqP->enb_S1u_teid);
message_p = itti_alloc_new_message(TASK_GTPV1_U, GTPV1U_UPDATE_TUNNEL_RESP); message_p = itti_alloc_new_message(TASK_GTPV1_U, GTPV1U_UPDATE_TUNNEL_RESP);
hash_rc = hashtable_get(gtpv1u_sgw_data.S1U_mapping, reqP->sgw_S1u_teid, (void**)&gtpv1u_teid2enb_info); hash_rc = hashtable_get(gtpv1u_sgw_data.S1U_mapping, reqP->sgw_S1u_teid, (void**)&gtpv1u_teid2enb_info);
if (hash_rc == HASH_TABLE_OK) { if (hash_rc == HASH_TABLE_OK) {
gtpv1u_teid2enb_info->teid_enb = reqP->enb_S1u_teid; gtpv1u_teid2enb_info->teid_enb = reqP->enb_S1u_teid;
gtpv1u_teid2enb_info->enb_ip_addr = reqP->enb_ip_address_for_S1u; gtpv1u_teid2enb_info->enb_ip_addr = reqP->enb_ip_address_for_S1u;
gtpv1u_teid2enb_info->state = BEARER_UP; gtpv1u_teid2enb_info->state = BEARER_UP;
gtpv1u_teid2enb_info->port = GTPV1U_UDP_PORT; gtpv1u_teid2enb_info->port = GTPV1U_UDP_PORT;
message_p->ittiMsg.gtpv1uUpdateTunnelResp.status = 0; ///< Status (Failed = 0xFF or Success = 0x0) message_p->ittiMsg.gtpv1uUpdateTunnelResp.status = 0; ///< Status (Failed = 0xFF or Success = 0x0)
} else { } else {
GTPU_ERROR("Mapping not found\n"); GTPU_ERROR("Mapping not found\n");
message_p->ittiMsg.gtpv1uUpdateTunnelResp.status = 0xFF; ///< Status (Failed = 0xFF or Success = 0x0) message_p->ittiMsg.gtpv1uUpdateTunnelResp.status = 0xFF; ///< Status (Failed = 0xFF or Success = 0x0)
} }
message_p->ittiMsg.gtpv1uUpdateTunnelResp.context_teid = reqP->context_teid;
message_p->ittiMsg.gtpv1uUpdateTunnelResp.sgw_S1u_teid = reqP->sgw_S1u_teid; message_p->ittiMsg.gtpv1uUpdateTunnelResp.context_teid = reqP->context_teid;
message_p->ittiMsg.gtpv1uUpdateTunnelResp.enb_S1u_teid = reqP->enb_S1u_teid; message_p->ittiMsg.gtpv1uUpdateTunnelResp.sgw_S1u_teid = reqP->sgw_S1u_teid;
message_p->ittiMsg.gtpv1uUpdateTunnelResp.eps_bearer_id = reqP->eps_bearer_id; message_p->ittiMsg.gtpv1uUpdateTunnelResp.enb_S1u_teid = reqP->enb_S1u_teid;
return itti_send_msg_to_task(TASK_SPGW_APP, INSTANCE_DEFAULT, message_p); message_p->ittiMsg.gtpv1uUpdateTunnelResp.eps_bearer_id = reqP->eps_bearer_id;
return itti_send_msg_to_task(TASK_SPGW_APP, INSTANCE_DEFAULT, message_p);
} }
static NwGtpv1uRcT gtpv1u_start_timer_wrapper( static NwGtpv1uRcT gtpv1u_start_timer_wrapper(
NwGtpv1uTimerMgrHandleT tmrMgrHandle, NwGtpv1uTimerMgrHandleT tmrMgrHandle,
NwU32T timeoutSec, NwU32T timeoutSec,
NwU32T timeoutUsec, NwU32T timeoutUsec,
NwU32T tmrType, NwU32T tmrType,
void *timeoutArg, void *timeoutArg,
NwGtpv1uTimerHandleT *hTmr) NwGtpv1uTimerHandleT *hTmr)
{ {
NwGtpv1uRcT rc = NW_GTPV1U_OK; NwGtpv1uRcT rc = NW_GTPV1U_OK;
long timer_id; long timer_id;
if (tmrType == NW_GTPV1U_TMR_TYPE_ONE_SHOT) { if (tmrType == NW_GTPV1U_TMR_TYPE_ONE_SHOT) {
timer_setup(timeoutSec, timer_setup(timeoutSec,
timeoutUsec, timeoutUsec,
TASK_GTPV1_U, TASK_GTPV1_U,
INSTANCE_DEFAULT, INSTANCE_DEFAULT,
TIMER_ONE_SHOT, TIMER_ONE_SHOT,
timeoutArg, timeoutArg,
&timer_id); &timer_id);
} else { } else {
timer_setup(timeoutSec, timer_setup(timeoutSec,
timeoutUsec, timeoutUsec,
TASK_GTPV1_U, TASK_GTPV1_U,
INSTANCE_DEFAULT, INSTANCE_DEFAULT,
TIMER_PERIODIC, TIMER_PERIODIC,
timeoutArg, timeoutArg,
&timer_id); &timer_id);
} }
return rc; return rc;
} }
static NwGtpv1uRcT gtpv1u_stop_timer_wrapper( static NwGtpv1uRcT gtpv1u_stop_timer_wrapper(
NwGtpv1uTimerMgrHandleT tmrMgrHandle, NwGtpv1uTimerMgrHandleT tmrMgrHandle,
NwGtpv1uTimerHandleT hTmr) NwGtpv1uTimerHandleT hTmr)
{ {
NwGtpv1uRcT rc = NW_GTPV1U_OK; NwGtpv1uRcT rc = NW_GTPV1U_OK;
return rc; return rc;
} }
static void *gtpv1u_thread(void *args) static void *gtpv1u_thread(void *args)
{ {
itti_mark_task_ready(TASK_GTPV1_U); itti_mark_task_ready(TASK_GTPV1_U);
while(1) {
/* Trying to fetch a message from the message queue. while(1) {
* If the queue is empty, this function will block till a /* Trying to fetch a message from the message queue.
* message is sent to the task. * If the queue is empty, this function will block till a
*/ * message is sent to the task.
MessageDef *received_message_p = NULL; */
itti_receive_msg(TASK_GTPV1_U, &received_message_p); MessageDef *received_message_p = NULL;
DevAssert(received_message_p != NULL); itti_receive_msg(TASK_GTPV1_U, &received_message_p);
DevAssert(received_message_p != NULL);
#if !defined(ENABLE_USE_GTPU_IN_KERNEL) #if !defined(ENABLE_USE_GTPU_IN_KERNEL)
switch (ITTI_MSG_ID(received_message_p))
{
case GTPV1U_CREATE_TUNNEL_REQ: {
gtpv1u_create_s1u_tunnel(&received_message_p->ittiMsg.gtpv1uCreateTunnelReq);
}
break;
case GTPV1U_DELETE_TUNNEL_REQ: { switch (ITTI_MSG_ID(received_message_p)) {
gtpv1u_delete_s1u_tunnel(received_message_p->ittiMsg.gtpv1uDeleteTunnelReq.context_teid, received_message_p->ittiMsg.gtpv1uDeleteTunnelReq.S1u_teid); case GTPV1U_CREATE_TUNNEL_REQ: {
} gtpv1u_create_s1u_tunnel(&received_message_p->ittiMsg.gtpv1uCreateTunnelReq);
break;
case GTPV1U_UPDATE_TUNNEL_REQ: {
gtpv1u_update_s1u_tunnel(&received_message_p->ittiMsg.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->ittiMsg.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);
//itti_free(ITTI_MSG_ORIGIN_ID(received_message_p), udp_data_ind_p->buffer);
}
break;
// DATA TO BE SENT TO UDP
case GTPV1U_TUNNEL_DATA_REQ: {
Gtpv1uTunnelDataReq *data_req_p = NULL;
NwGtpv1uUlpApiT stack_req;
NwGtpv1uRcT rc;
hashtable_rc_t hash_rc;
gtpv1u_teid2enb_info_t *gtpv1u_teid2enb_info = NULL;
data_req_p = &received_message_p->ittiMsg.gtpv1uTunnelDataReq;
//GTPU_DEBUG("-- GTPV1U_TUNNEL_DATA_REQ -----------------------------------------------------\n%s :\n",
// __FUNCTION__);
//gtpu_print_hex_octets(data_req_p->buffer, data_req_p->length);
memset(&stack_req, 0, sizeof(NwGtpv1uUlpApiT));
hash_rc = hashtable_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;
stack_req.apiInfo.sendtoInfo.teid = gtpv1u_teid2enb_info->teid_enb;
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)*/
GTPU_DEBUG("GTPV1U_TUNNEL_DATA_REQ seq num %d %d bytes\n",
gtpv1u_sgw_data.seq_num,
data_req_p->length);
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,
data_req_p->offset,
&(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 still needed, do not free it */
//itti_free(ITTI_MSG_ORIGIN_ID(received_message_p), data_req_p->buffer);
}
break;
case TERMINATE_MESSAGE: {
itti_exit_task();
} break;
case TIMER_HAS_EXPIRED:
nwGtpv1uProcessTimeout(&received_message_p->ittiMsg.timer_has_expired.arg);
break;
default: {
GTPU_ERROR("Unkwnon message ID %d:%s\n",
ITTI_MSG_ID(received_message_p),
ITTI_MSG_NAME(received_message_p));
}
break;
}
#endif
itti_free(ITTI_MSG_ORIGIN_ID(received_message_p), received_message_p);
received_message_p = NULL;
} }
return NULL; break;
case GTPV1U_DELETE_TUNNEL_REQ: {
gtpv1u_delete_s1u_tunnel(received_message_p->ittiMsg.gtpv1uDeleteTunnelReq.context_teid, received_message_p->ittiMsg.gtpv1uDeleteTunnelReq.S1u_teid);
}
break;
case GTPV1U_UPDATE_TUNNEL_REQ: {
gtpv1u_update_s1u_tunnel(&received_message_p->ittiMsg.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->ittiMsg.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);
//itti_free(ITTI_MSG_ORIGIN_ID(received_message_p), udp_data_ind_p->buffer);
}
break;
// DATA TO BE SENT TO UDP
case GTPV1U_TUNNEL_DATA_REQ: {
Gtpv1uTunnelDataReq *data_req_p = NULL;
NwGtpv1uUlpApiT stack_req;
NwGtpv1uRcT rc;
hashtable_rc_t hash_rc;
gtpv1u_teid2enb_info_t *gtpv1u_teid2enb_info = NULL;
data_req_p = &received_message_p->ittiMsg.gtpv1uTunnelDataReq;
//GTPU_DEBUG("-- GTPV1U_TUNNEL_DATA_REQ -----------------------------------------------------\n%s :\n",
// __FUNCTION__);
//gtpu_print_hex_octets(data_req_p->buffer, data_req_p->length);
memset(&stack_req, 0, sizeof(NwGtpv1uUlpApiT));
hash_rc = hashtable_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;
stack_req.apiInfo.sendtoInfo.teid = gtpv1u_teid2enb_info->teid_enb;
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)*/
GTPU_DEBUG("GTPV1U_TUNNEL_DATA_REQ seq num %d %d bytes\n",
gtpv1u_sgw_data.seq_num,
data_req_p->length);
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,
data_req_p->offset,
&(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 still needed, do not free it */
//itti_free(ITTI_MSG_ORIGIN_ID(received_message_p), data_req_p->buffer);
}
break;
case TERMINATE_MESSAGE: {
itti_exit_task();
}
break;
case TIMER_HAS_EXPIRED:
nwGtpv1uProcessTimeout(&received_message_p->ittiMsg.timer_has_expired.arg);
break;
default: {
GTPU_ERROR("Unkwnon message ID %d:%s\n",
ITTI_MSG_ID(received_message_p),
ITTI_MSG_NAME(received_message_p));
}
break;
}
#endif
itti_free(ITTI_MSG_ORIGIN_ID(received_message_p), received_message_p);
received_message_p = NULL;
}
return NULL;
} }
int gtpv1u_init(const mme_config_t *mme_config_p) int gtpv1u_init(const mme_config_t *mme_config_p)
{ {
int ret = 0; int ret = 0;
NwGtpv1uRcT rc = 0; NwGtpv1uRcT rc = 0;
NwGtpv1uUlpEntityT ulp; NwGtpv1uUlpEntityT ulp;
NwGtpv1uUdpEntityT udp; NwGtpv1uUdpEntityT udp;
NwGtpv1uLogMgrEntityT log; NwGtpv1uLogMgrEntityT log;
NwGtpv1uTimerMgrEntityT tmr; NwGtpv1uTimerMgrEntityT tmr;
GTPU_DEBUG("Initializing GTPV1U interface\n"); GTPU_DEBUG("Initializing GTPV1U interface\n");
memset(&gtpv1u_sgw_data, 0, sizeof(gtpv1u_sgw_data)); memset(&gtpv1u_sgw_data, 0, sizeof(gtpv1u_sgw_data));
gtpv1u_sgw_data.sgw_ip_address_for_S1u_S12_S4_up = mme_config_p->ipv4.sgw_ip_address_for_S1u_S12_S4_up; gtpv1u_sgw_data.sgw_ip_address_for_S1u_S12_S4_up = mme_config_p->ipv4.sgw_ip_address_for_S1u_S12_S4_up;
#if !defined(ENABLE_USE_GTPU_IN_KERNEL) #if !defined(ENABLE_USE_GTPU_IN_KERNEL)
gtpv1u_sgw_data.S1U_mapping = hashtable_create (8192, NULL, NULL); gtpv1u_sgw_data.S1U_mapping = hashtable_create (8192, NULL, NULL);
if (gtpv1u_sgw_data.S1U_mapping == NULL) {
perror("hashtable_create");
GTPU_ERROR("Initializing TASK_GTPV1_U task interface: ERROR\n");
return -1;
}
/* Initializing GTPv1-U stack */ if (gtpv1u_sgw_data.S1U_mapping == NULL) {
if ((rc = nwGtpv1uInitialize(&gtpv1u_sgw_data.gtpv1u_stack)) != NW_GTPV1U_OK) { perror("hashtable_create");
GTPU_ERROR("Failed to setup nwGtpv1u stack %x\n", rc); GTPU_ERROR("Initializing TASK_GTPV1_U task interface: ERROR\n");
return -1; return -1;
} }
if ((rc = nwGtpv1uSetLogLevel(gtpv1u_sgw_data.gtpv1u_stack, /* Initializing GTPv1-U stack */
NW_LOG_LEVEL_DEBG)) != NW_GTPV1U_OK) { if ((rc = nwGtpv1uInitialize(&gtpv1u_sgw_data.gtpv1u_stack)) != NW_GTPV1U_OK) {
GTPU_ERROR("Failed to setup loglevel for stack %x\n", rc); GTPU_ERROR("Failed to setup nwGtpv1u stack %x\n", rc);
return -1; return -1;
} }
/* Set the ULP API callback. Called once message have been processed by the if ((rc = nwGtpv1uSetLogLevel(gtpv1u_sgw_data.gtpv1u_stack,
* nw-gtpv1u stack. NW_LOG_LEVEL_DEBG)) != NW_GTPV1U_OK) {
*/ GTPU_ERROR("Failed to setup loglevel for stack %x\n", rc);
ulp.ulpReqCallback = gtpv1u_process_stack_req; return -1;
}
if ((rc = nwGtpv1uSetUlpEntity(gtpv1u_sgw_data.gtpv1u_stack, &ulp)) != NW_GTPV1U_OK) { /* Set the ULP API callback. Called once message have been processed by the
GTPU_ERROR("nwGtpv1uSetUlpEntity: %x", rc); * nw-gtpv1u stack.
return -1; */
} ulp.ulpReqCallback = gtpv1u_process_stack_req;
/* nw-gtpv1u stack requires an udp callback to send data over UDP. if ((rc = nwGtpv1uSetUlpEntity(gtpv1u_sgw_data.gtpv1u_stack, &ulp)) != NW_GTPV1U_OK) {
* We provide a wrapper to UDP task. GTPU_ERROR("nwGtpv1uSetUlpEntity: %x", rc);
*/ return -1;
udp.udpDataReqCallback = gtpv1u_send_udp_msg; }
if ((rc = nwGtpv1uSetUdpEntity(gtpv1u_sgw_data.gtpv1u_stack, &udp)) != NW_GTPV1U_OK) { /* nw-gtpv1u stack requires an udp callback to send data over UDP.
GTPU_ERROR("nwGtpv1uSetUdpEntity: %x", rc); * We provide a wrapper to UDP task.
return -1; */
} udp.udpDataReqCallback = gtpv1u_send_udp_msg;
log.logReqCallback = gtpv1u_log_request; if ((rc = nwGtpv1uSetUdpEntity(gtpv1u_sgw_data.gtpv1u_stack, &udp)) != NW_GTPV1U_OK) {
GTPU_ERROR("nwGtpv1uSetUdpEntity: %x", rc);
return -1;
}
if ((rc = nwGtpv1uSetLogMgrEntity(gtpv1u_sgw_data.gtpv1u_stack, &log)) != NW_GTPV1U_OK) { log.logReqCallback = gtpv1u_log_request;
GTPU_ERROR("nwGtpv1uSetLogMgrEntity: %x", rc);
return -1;
}
/* Timer interface is more complicated as both wrappers doesn't send a message if ((rc = nwGtpv1uSetLogMgrEntity(gtpv1u_sgw_data.gtpv1u_stack, &log)) != NW_GTPV1U_OK) {
* to the timer task but call the timer API functions start/stop timer. GTPU_ERROR("nwGtpv1uSetLogMgrEntity: %x", rc);
*/ return -1;
tmr.tmrMgrHandle = 0; }
tmr.tmrStartCallback = gtpv1u_start_timer_wrapper;
tmr.tmrStopCallback = gtpv1u_stop_timer_wrapper; /* 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 ((rc = nwGtpv1uSetTimerMgrEntity(gtpv1u_sgw_data.gtpv1u_stack, &tmr)) != NW_GTPV1U_OK) {
GTPU_ERROR("nwGtpv1uSetTimerMgrEntity: %x", rc);
return -1;
}
#endif #endif
if (itti_create_task(TASK_GTPV1_U, &gtpv1u_thread, NULL) < 0) {
GTPU_ERROR("gtpv1u phtread_create: %s", strerror(errno)); if (itti_create_task(TASK_GTPV1_U, &gtpv1u_thread, NULL) < 0) {
return -1; GTPU_ERROR("gtpv1u phtread_create: %s", strerror(errno));
} return -1;
}
#if !defined(ENABLE_USE_GTPU_IN_KERNEL) #if !defined(ENABLE_USE_GTPU_IN_KERNEL)
ret = gtpv1u_send_init_udp(mme_config_p->gtpv1u_config.port_number); ret = gtpv1u_send_init_udp(mme_config_p->gtpv1u_config.port_number);
if (ret < 0) {
return ret;
}
#endif
GTPU_DEBUG("Initializing GTPV1U interface: DONE\n");
if (ret < 0) {
return ret; return ret;
}
#endif
GTPU_DEBUG("Initializing GTPV1U interface: DONE\n");
return ret;
} }
+3 -3
View File
@@ -46,9 +46,9 @@ static uint32_t g_gtpv1u_teid = 0;
uint32_t gtpv1u_new_teid(void) uint32_t gtpv1u_new_teid(void)
{ {
#ifdef GTPV1U_LINEAR_TEID_ALLOCATION #ifdef GTPV1U_LINEAR_TEID_ALLOCATION
g_gtpv1u_teid = g_gtpv1u_teid + 1; g_gtpv1u_teid = g_gtpv1u_teid + 1;
return g_gtpv1u_teid; return g_gtpv1u_teid;
#else #else
return random() + random() % (RAND_MAX - 1) + 1; return random() + random() % (RAND_MAX - 1) + 1;
#endif #endif
} }
@@ -1,6 +1,6 @@
/*----------------------------------------------------------------------------* /*----------------------------------------------------------------------------*
* * * *
* 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 * * 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 *
* * * *
* * * *
@@ -37,8 +37,8 @@
#include <stdio.h> #include <stdio.h>
#include "NwLog.h" #include "NwLog.h"
/** /**
* @file NwGtpv1uLog.h * @file NwGtpv1uLog.h
* @brief This header contains logging related definitions. * @brief This header contains logging related definitions.
*/ */
@@ -1,7 +1,7 @@
/*----------------------------------------------------------------------------* /*----------------------------------------------------------------------------*
* * * *
* n w - g t p v 2 u * * n w - g t p v 2 u *
* 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 * * 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 *
* * * *
* * * *
@@ -44,9 +44,9 @@
#include "NwGtpv1uMsg.h" #include "NwGtpv1uMsg.h"
/** /**
* @file NwGtpv1uPrivate.h * @file NwGtpv1uPrivate.h
* @brief This header file contains nw-gtpv1u private definitions not to be * @brief This header file contains nw-gtpv1u private definitions not to be
* exposed to user application. * exposed to user application.
*/ */
@@ -78,8 +78,7 @@ extern "C" {
* gtpv1u stack class definition * gtpv1u stack class definition
*/ */
typedef struct NwGtpv1uStack typedef struct NwGtpv1uStack {
{
NwU32T id; NwU32T id;
NwU32T seq; NwU32T seq;
NwGtpv1uUlpEntityT ulp; NwGtpv1uUlpEntityT ulp;
@@ -92,14 +91,13 @@ typedef struct NwGtpv1uStack
RB_HEAD( NwGtpv1uOutstandingRxSeqNumTrxnMap, NwGtpv1uTrxn) outstandingRxSeqNumMap; RB_HEAD( NwGtpv1uOutstandingRxSeqNumTrxnMap, NwGtpv1uTrxn) outstandingRxSeqNumMap;
RB_HEAD(NwGtpv1uTunnelEndPointTMap, NwGtpv1uTunnelEndPoint) sessionMap; RB_HEAD(NwGtpv1uTunnelEndPointTMap, NwGtpv1uTunnelEndPoint) sessionMap;
RB_HEAD(NwGtpv1uTunnelEndPointIdentifierMap, NwGtpv1uTunnelEndPoint) teidMap; RB_HEAD(NwGtpv1uTunnelEndPointIdentifierMap, NwGtpv1uTunnelEndPoint) teidMap;
} NwGtpv1uStackT; } NwGtpv1uStackT;
/** /**
* GTP Tunnel End Point class definition * GTP Tunnel End Point class definition
*/ */
typedef struct NwGtpv1uTunnelEndPoint typedef struct NwGtpv1uTunnelEndPoint {
{
NwU32T teid; /**< Gtpu Tunnel End Point Identifier */ NwU32T teid; /**< Gtpu Tunnel End Point Identifier */
NwU32T peerAddr; /**< Peer IP address for the session */ NwU32T peerAddr; /**< Peer IP address for the session */
NwGtpv1uStackT* pStack; /**< Pointer to the parent stack */ NwGtpv1uStackT* pStack; /**< Pointer to the parent stack */
@@ -110,15 +108,14 @@ typedef struct NwGtpv1uTunnelEndPoint
/*--------------------------------------------------------------------------* /*--------------------------------------------------------------------------*
* Timeout Info Type Definition * Timeout Info Type Definition
*--------------------------------------------------------------------------*/ *--------------------------------------------------------------------------*/
/** /**
* gtpv1u timeout info * gtpv1u timeout info
*/ */
typedef struct NwGtpv1uTimeoutInfo typedef struct NwGtpv1uTimeoutInfo {
{
NwGtpv1uStackHandleT hStack; NwGtpv1uStackHandleT hStack;
void* timeoutArg; void* timeoutArg;
NwGtpv1uRcT (*timeoutCallbackFunc)(void*); NwGtpv1uRcT (*timeoutCallbackFunc)(void*);
@@ -129,7 +126,7 @@ typedef struct NwGtpv1uTimeoutInfo
* *
* @param[in] thiz Pointer to stack instance * @param[in] thiz Pointer to stack instance
* @param[in] timeoutArg Arg to timeout function. * @param[in] timeoutArg Arg to timeout function.
* @param[out] phTmr Pointer to timer handle. * @param[out] phTmr Pointer to timer handle.
* @return NW_GTPV1U_OK on success. * @return NW_GTPV1U_OK on success.
*/ */
@@ -140,7 +137,7 @@ nwGtpStartTrxnPeerRspTimer(NwGtpv1uStackT* thiz, NwGtpv1uTimeoutInfoT* timeoutIn
* Stop a transaction response timer * Stop a transaction response timer
* *
* @param[in] thiz Pointer to stack instance * @param[in] thiz Pointer to stack instance
* @param[out] phTmr Pointer to timer handle. * @param[out] phTmr Pointer to timer handle.
* @return NW_GTPV1U_OK on success. * @return NW_GTPV1U_OK on success.
*/ */
@@ -153,8 +150,7 @@ nwGtpStopTrxnPeerRspTimer(NwGtpv1uStackT* thiz, NwGtpv1uTimerHandleT* phTmr);
/** /**
* NwGtpv1uMsgT holds gtpv1u messages to/from the peer. * NwGtpv1uMsgT holds gtpv1u messages to/from the peer.
*/ */
typedef struct NwGtpv1uMsg typedef struct NwGtpv1uMsg {
{
NwU8T version; NwU8T version;
NwU8T protocolType; NwU8T protocolType;
NwU8T extHdrFlag; NwU8T extHdrFlag;
@@ -164,7 +160,7 @@ typedef struct NwGtpv1uMsg
NwU16T msgLen; NwU16T msgLen;
NwU32T teid; NwU32T teid;
NwU16T seqNum; NwU16T seqNum;
NwU8T npduNum; NwU8T npduNum;
NwU8T nextExtHdrType; NwU8T nextExtHdrType;
NwU8T* msgBuf; NwU8T* msgBuf;
NwU32T msgBufLen; NwU32T msgBufLen;
@@ -174,15 +170,14 @@ typedef struct NwGtpv1uMsg
/*--------------------------------------------------------------------------* /*--------------------------------------------------------------------------*
* R6/R4 Transaction Context Type Definition * R6/R4 Transaction Context Type Definition
*--------------------------------------------------------------------------*/ *--------------------------------------------------------------------------*/
/** /**
* Transaction structure * Transaction structure
*/ */
typedef struct NwGtpv1uTrxn typedef struct NwGtpv1uTrxn {
{
NwU32T seqNum; NwU32T seqNum;
NwU32T peerIp; NwU32T peerIp;
NwU32T peerPort; NwU32T peerPort;
@@ -206,8 +201,7 @@ typedef struct NwGtpv1uTrxn
#pragma pack(1) #pragma pack(1)
typedef struct NwGtpv1uMsgHeader typedef struct NwGtpv1uMsgHeader {
{
NwU8T PN:1; NwU8T PN:1;
NwU8T S:1; NwU8T S:1;
NwU8T E:1; NwU8T E:1;
@@ -1,6 +1,6 @@
/*----------------------------------------------------------------------------* /*----------------------------------------------------------------------------*
* * * *
* 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 * * 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 *
* * * *
* * * *
@@ -34,10 +34,10 @@
/** /**
* @file NwGtpv1uTrxn.h * @file NwGtpv1uTrxn.h
* @author Amit Chawre * @author Amit Chawre
* @brief * @brief
* *
* This header file contains required definitions and functions * This header file contains required definitions and functions
* prototypes used by gtpv1u transactions. * prototypes used by gtpv1u transactions.
* *
**/ **/
@@ -1,6 +1,6 @@
/*----------------------------------------------------------------------------* /*----------------------------------------------------------------------------*
* * * *
* 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 * * 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 *
* * * *
* * * *
+113 -131
View File
@@ -1,6 +1,6 @@
/*----------------------------------------------------------------------------* /*----------------------------------------------------------------------------*
* * * *
* 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 * * 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 *
* * * *
* * * *
@@ -44,17 +44,17 @@
/** /**
* @file NwGtpv1u.h * @file NwGtpv1u.h
* @author Amit Chawre * @author Amit Chawre
* @brief * @brief
* *
* This header file contains all required definitions and functions * This header file contains all required definitions and functions
* prototypes for using nw-gtpv1u library. * prototypes for using nw-gtpv1u library.
* *
**/ **/
#define NW_GTPU_VERSION (0x01) #define NW_GTPU_VERSION (0x01)
#define NW_GTP_PROTOCOL_TYPE_GTP (0x01) #define NW_GTP_PROTOCOL_TYPE_GTP (0x01)
#define NW_GTP_PROTOCOL_TYPE_GTP_PRIME (0x00) #define NW_GTP_PROTOCOL_TYPE_GTP_PRIME (0x00)
/*--------------------------------------------------------------------------* /*--------------------------------------------------------------------------*
* S H A R E D A P I M A C R O S * * S H A R E D A P I M A C R O S *
*--------------------------------------------------------------------------*/ *--------------------------------------------------------------------------*/
@@ -71,16 +71,15 @@
*--------------------------------------------------------------------------*/ *--------------------------------------------------------------------------*/
typedef NwPtrT NwGtpv1uStackHandleT; /**< Gtpv2 Stack Handle */ typedef NwPtrT NwGtpv1uStackHandleT; /**< Gtpv2 Stack Handle */
typedef NwPtrT NwGtpv1uUlpHandleT; /**< Gtpv2 Stack Ulp Entity Handle */ typedef NwPtrT NwGtpv1uUlpHandleT; /**< Gtpv2 Stack Ulp Entity Handle */
typedef NwPtrT NwGtpv1uUdpHandleT; /**< Gtpv2 Stack Udp Entity Handle */ typedef NwPtrT NwGtpv1uUdpHandleT; /**< Gtpv2 Stack Udp Entity Handle */
typedef NwPtrT NwGtpv1uMemMgrHandleT; /**< Gtpv2 Stack Mem Manager Handle */ typedef NwPtrT NwGtpv1uMemMgrHandleT; /**< Gtpv2 Stack Mem Manager Handle */
typedef NwPtrT NwGtpv1uTimerMgrHandleT; /**< Gtpv2 Stack Timer Manager Handle */ typedef NwPtrT NwGtpv1uTimerMgrHandleT; /**< Gtpv2 Stack Timer Manager Handle */
typedef NwPtrT NwGtpv1uLogMgrHandleT; /**< Gtpv2 Stack Log Mnagaer Handle */ typedef NwPtrT NwGtpv1uLogMgrHandleT; /**< Gtpv2 Stack Log Mnagaer Handle */
typedef NwPtrT NwGtpv1uTimerHandleT; /**< Gtpv2 Stack Timer Handle */ typedef NwPtrT NwGtpv1uTimerHandleT; /**< Gtpv2 Stack Timer Handle */
typedef NwPtrT NwGtpv1uMsgHandleT; /**< Gtpv2 Msg Handle */ typedef NwPtrT NwGtpv1uMsgHandleT; /**< Gtpv2 Msg Handle */
typedef struct NwGtpv1uStackConfig typedef struct NwGtpv1uStackConfig {
{
NwU16T udpSrcPort; NwU16T udpSrcPort;
} NwGtpv1uStackConfigT; } NwGtpv1uStackConfigT;
@@ -92,12 +91,11 @@ typedef struct NwGtpv1uStackConfig
* Gtpv2 Stack ULP API type definitions * Gtpv2 Stack ULP API type definitions
*--------------------------------------------------------------------------*/ *--------------------------------------------------------------------------*/
/** /**
* APIs types between ULP and Stack * APIs types between ULP and Stack
*/ */
typedef enum typedef enum {
{
/* APIs from ULP to stack */ /* APIs from ULP to stack */
NW_GTPV1U_ULP_API_CREATE_TUNNEL_ENDPOINT = 0x00000000, /**< Create a local teid context on stack */ NW_GTPV1U_ULP_API_CREATE_TUNNEL_ENDPOINT = 0x00000000, /**< Create a local teid context on stack */
@@ -128,35 +126,32 @@ typedef NwU32T NwGtpv1uTrxnHandleT; /**< Gtpv2 Transaction Handle */
typedef NwU32T NwGtpv1uUlpTrxnHandleT; /**< Gtpv2 Ulp Transaction Handle */ typedef NwU32T NwGtpv1uUlpTrxnHandleT; /**< Gtpv2 Ulp Transaction Handle */
typedef NwU32T NwGtpv1uUlpSessionHandleT; /**< Gtpv2 Ulp session Handle */ typedef NwU32T NwGtpv1uUlpSessionHandleT; /**< Gtpv2 Ulp session Handle */
/** /**
* API information elements between ULP and Stack for * API information elements between ULP and Stack for
* creating a session. * creating a session.
*/ */
typedef struct typedef struct {
{ NW_IN NwU32T teid;
NW_IN NwU32T teid; NW_IN NwGtpv1uUlpSessionHandleT hUlpSession;
NW_IN NwGtpv1uUlpSessionHandleT hUlpSession; NW_OUT NwGtpv1uStackSessionHandleT hStackSession;
NW_OUT NwGtpv1uStackSessionHandleT hStackSession;
} NwGtpv1uCreateTunnelEndPointT; } NwGtpv1uCreateTunnelEndPointT;
/** /**
* API information elements between ULP and Stack for * API information elements between ULP and Stack for
* destroying a session. * destroying a session.
*/ */
typedef struct typedef struct {
{ NW_IN NwGtpv1uStackSessionHandleT hStackSessionHandle;
NW_IN NwGtpv1uStackSessionHandleT hStackSessionHandle;
} NwGtpv1uDestroyTunnelEndPointT; } NwGtpv1uDestroyTunnelEndPointT;
/** /**
* API information elements between ULP and Stack for * API information elements between ULP and Stack for
* sending a Gtpv1u initial message. * sending a Gtpv1u initial message.
*/ */
typedef struct typedef struct {
{
NW_IN NwGtpv1uUlpTrxnHandleT hUlpTrxn; NW_IN NwGtpv1uUlpTrxnHandleT hUlpTrxn;
NW_IN NwU32T peerIp; NW_IN NwU32T peerIp;
NW_IN NwU32T peerPort; NW_IN NwU32T peerPort;
@@ -164,13 +159,12 @@ typedef struct
NW_IN NwU32T teid; NW_IN NwU32T teid;
} NwGtpv1uInitialReqInfoT; } NwGtpv1uInitialReqInfoT;
/** /**
* API information elements between ULP and Stack for * API information elements between ULP and Stack for
* sending a Gtpv1u triggered response message. * sending a Gtpv1u triggered response message.
*/ */
typedef struct typedef struct {
{
NW_IN NwGtpv1uUlpTrxnHandleT hUlpTrxn; NW_IN NwGtpv1uUlpTrxnHandleT hUlpTrxn;
NW_IN NwU32T peerIp; NW_IN NwU32T peerIp;
NW_IN NwU32T peerPort; NW_IN NwU32T peerPort;
@@ -180,13 +174,12 @@ typedef struct
NW_IN NwGtpv1uMsgHandleT hMsg; NW_IN NwGtpv1uMsgHandleT hMsg;
} NwGtpv1uTriggeredRspInfoT; } NwGtpv1uTriggeredRspInfoT;
/** /**
* API information elements between ULP and Stack for * API information elements between ULP and Stack for
* sending a Gtpv1u triggered request message. * sending a Gtpv1u triggered request message.
*/ */
typedef struct typedef struct {
{
NW_IN NwGtpv1uUlpTrxnHandleT hUlpTrxn; NW_IN NwGtpv1uUlpTrxnHandleT hUlpTrxn;
NW_IN NwU32T peerIp; NW_IN NwU32T peerIp;
NW_IN NwU32T peerPort; NW_IN NwU32T peerPort;
@@ -197,13 +190,12 @@ typedef struct
} NwGtpv1uTriggeredReqInfoT; } NwGtpv1uTriggeredReqInfoT;
/** /**
* API information elements between ULP and Stack for * API information elements between ULP and Stack for
* sending a Gtpv2 message over a session. * sending a Gtpv2 message over a session.
*/ */
typedef struct typedef struct {
{
NW_IN NwU32T teid; NW_IN NwU32T teid;
NW_IN NwU32T ipAddr; NW_IN NwU32T ipAddr;
NW_IN NwU8T flags; NW_IN NwU8T flags;
@@ -211,14 +203,13 @@ typedef struct
} NwGtpv1uSendtoInfoT; } NwGtpv1uSendtoInfoT;
/** /**
* API information elements between ULP and Stack for * API information elements between ULP and Stack for
* sending a Gtpv2 message over a session. * sending a Gtpv2 message over a session.
*/ */
typedef struct typedef struct {
{ NW_OUT NwGtpv1uStackSessionHandleT hStackSessionHandle;
NW_OUT NwGtpv1uStackSessionHandleT hStackSessionHandle;
NW_INOUT NwGtpv1uTrxnHandleT hTrxn; NW_INOUT NwGtpv1uTrxnHandleT hTrxn;
NW_IN NwGtpv1uUlpTrxnHandleT hUlpTrxn; NW_IN NwGtpv1uUlpTrxnHandleT hUlpTrxn;
NW_IN NwGtpv1uMsgTypeT msgType; NW_IN NwGtpv1uMsgTypeT msgType;
@@ -226,14 +217,13 @@ typedef struct
NW_IN NwGtpv1uMsgHandleT hMsg; NW_IN NwGtpv1uMsgHandleT hMsg;
} NwGtpv1uSendMsgInfoT; } NwGtpv1uSendMsgInfoT;
/** /**
* API information elements between ULP and Stack for * API information elements between ULP and Stack for
* receiving a Gtpv2 message over a session from stack. * receiving a Gtpv2 message over a session from stack.
*/ */
typedef struct typedef struct {
{ NW_IN NwGtpv1uUlpSessionHandleT hUlpSession;
NW_IN NwGtpv1uUlpSessionHandleT hUlpSession;
NW_IN NwGtpv1uUlpTrxnHandleT hUlpTrxn; NW_IN NwGtpv1uUlpTrxnHandleT hUlpTrxn;
NW_IN NwU32T teid; NW_IN NwU32T teid;
NW_IN NwU32T peerIp; NW_IN NwU32T peerIp;
@@ -242,14 +232,13 @@ typedef struct
NW_IN NwGtpv1uMsgHandleT hMsg; /**< Gtp Message handle */ NW_IN NwGtpv1uMsgHandleT hMsg; /**< Gtp Message handle */
} NwGtpv1uRecvMsgInfoT; } NwGtpv1uRecvMsgInfoT;
/** /**
* API information elements between ULP and Stack for * API information elements between ULP and Stack for
* receiving a Gtpv2 message over a session from stack. * receiving a Gtpv2 message over a session from stack.
*/ */
typedef struct typedef struct {
{ NW_IN NwGtpv1uUlpSessionHandleT hUlpSession;
NW_IN NwGtpv1uUlpSessionHandleT hUlpSession;
NW_IN NwGtpv1uTrxnHandleT hTrxn; NW_IN NwGtpv1uTrxnHandleT hTrxn;
} NwGtpv1uNackInfoT; } NwGtpv1uNackInfoT;
@@ -257,16 +246,14 @@ typedef struct
* Gtpv2 Stack API structure definition * Gtpv2 Stack API structure definition
*--------------------------------------------------------------------------*/ *--------------------------------------------------------------------------*/
/** /**
* API structure between ULP and Stack * API structure between ULP and Stack
*/ */
typedef struct typedef struct {
{
NwGtpv1uUlpApiTypeT apiType; NwGtpv1uUlpApiTypeT apiType;
NwGtpv1uMsgHandleT hMsg; NwGtpv1uMsgHandleT hMsg;
union union {
{
NwGtpv1uCreateTunnelEndPointT createTunnelEndPointInfo; NwGtpv1uCreateTunnelEndPointT createTunnelEndPointInfo;
NwGtpv1uDestroyTunnelEndPointT destroyTunnelEndPointInfo; NwGtpv1uDestroyTunnelEndPointT destroyTunnelEndPointInfo;
NwGtpv1uInitialReqInfoT initialReqInfo; NwGtpv1uInitialReqInfoT initialReqInfo;
@@ -292,11 +279,10 @@ typedef struct
* Gtpv2 ULP entity definition * Gtpv2 ULP entity definition
*/ */
typedef struct typedef struct {
{
NwGtpv1uUlpHandleT hUlp; NwGtpv1uUlpHandleT hUlp;
NwGtpv1uRcT (*ulpReqCallback) ( NW_IN NwGtpv1uUlpHandleT hUlp, NwGtpv1uRcT (*ulpReqCallback) ( NW_IN NwGtpv1uUlpHandleT hUlp,
NW_IN NwGtpv1uUlpApiT *pUlpApi); NW_IN NwGtpv1uUlpApiT *pUlpApi);
} NwGtpv1uUlpEntityT; } NwGtpv1uUlpEntityT;
@@ -308,33 +294,31 @@ typedef struct
* Gtpv2 UDP entity definition * Gtpv2 UDP entity definition
*/ */
typedef struct typedef struct {
{
NwGtpv1uUdpHandleT hUdp; NwGtpv1uUdpHandleT hUdp;
NwGtpv1uRcT (*udpDataReqCallback) ( NW_IN NwGtpv1uUdpHandleT udpHandle, NwGtpv1uRcT (*udpDataReqCallback) ( NW_IN NwGtpv1uUdpHandleT udpHandle,
NW_IN NwU8T* dataBuf, NW_IN NwU8T* dataBuf,
NW_IN NwU32T dataSize, NW_IN NwU32T dataSize,
NW_IN NwU32T dataOffset, NW_IN NwU32T dataOffset,
NW_IN NwU32T peerIP, NW_IN NwU32T peerIP,
NW_IN NwU16T peerPort); NW_IN NwU16T peerPort);
} NwGtpv1uUdpEntityT; } NwGtpv1uUdpEntityT;
/** /**
* Gtpv1u Memory Manager entity definition * Gtpv1u Memory Manager entity definition
*/ */
typedef struct typedef struct {
{
NwGtpv1uMemMgrHandleT hMemMgr; NwGtpv1uMemMgrHandleT hMemMgr;
void* (*memAlloc)( NW_IN NwGtpv1uMemMgrHandleT hMemMgr, void* (*memAlloc)( NW_IN NwGtpv1uMemMgrHandleT hMemMgr,
NW_IN NwU32T memSize, NW_IN NwU32T memSize,
NW_IN NwCharT* fileName, NW_IN NwCharT* fileName,
NW_IN NwU32T lineNumber); NW_IN NwU32T lineNumber);
void (*memFree) ( NW_IN NwGtpv1uMemMgrHandleT hMemMgr, void (*memFree) ( NW_IN NwGtpv1uMemMgrHandleT hMemMgr,
NW_IN void* hMem, NW_IN void* hMem,
NW_IN NwCharT* fileName, NW_IN NwCharT* fileName,
NW_IN NwU32T lineNumber); NW_IN NwU32T lineNumber);
} NwGtpv1uMemMgrEntityT; } NwGtpv1uMemMgrEntityT;
@@ -349,18 +333,17 @@ typedef struct
* Gtpv2 Timer Manager entity definition * Gtpv2 Timer Manager entity definition
*/ */
typedef struct typedef struct {
{
NwGtpv1uTimerMgrHandleT tmrMgrHandle; NwGtpv1uTimerMgrHandleT tmrMgrHandle;
NwGtpv1uRcT (*tmrStartCallback)( NW_IN NwGtpv1uTimerMgrHandleT tmrMgrHandle, NwGtpv1uRcT (*tmrStartCallback)( NW_IN NwGtpv1uTimerMgrHandleT tmrMgrHandle,
NW_IN NwU32T timeoutSecs, NW_IN NwU32T timeoutSecs,
NW_IN NwU32T timeoutUsec, NW_IN NwU32T timeoutUsec,
NW_IN NwU32T tmrType, NW_IN NwU32T tmrType,
NW_IN void* tmrArg, NW_IN void* tmrArg,
NW_OUT NwGtpv1uTimerHandleT* tmrHandle); NW_OUT NwGtpv1uTimerHandleT* tmrHandle);
NwGtpv1uRcT (*tmrStopCallback) ( NW_IN NwGtpv1uTimerMgrHandleT tmrMgrHandle, NwGtpv1uRcT (*tmrStopCallback) ( NW_IN NwGtpv1uTimerMgrHandleT tmrMgrHandle,
NW_IN NwGtpv1uTimerHandleT tmrHandle); NW_IN NwGtpv1uTimerHandleT tmrHandle);
} NwGtpv1uTimerMgrEntityT; } NwGtpv1uTimerMgrEntityT;
@@ -372,14 +355,13 @@ typedef struct
* Gtpv2 Log manager entity definition * Gtpv2 Log manager entity definition
*/ */
typedef struct typedef struct {
{
NwGtpv1uLogMgrHandleT logMgrHandle; NwGtpv1uLogMgrHandleT logMgrHandle;
NwGtpv1uRcT (*logReqCallback) (NW_IN NwGtpv1uLogMgrHandleT logMgrHandle, NwGtpv1uRcT (*logReqCallback) (NW_IN NwGtpv1uLogMgrHandleT logMgrHandle,
NW_IN NwU32T logLevel, NW_IN NwU32T logLevel,
NW_IN NwCharT* file, NW_IN NwCharT* file,
NW_IN NwU32T line, NW_IN NwU32T line,
NW_IN NwCharT* logStr); NW_IN NwCharT* logStr);
} NwGtpv1uLogMgrEntityT; } NwGtpv1uLogMgrEntityT;
@@ -390,12 +372,12 @@ typedef struct
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
/*--------------------------------------------------------------------------- /*---------------------------------------------------------------------------
* Constructor * Constructor
*--------------------------------------------------------------------------*/ *--------------------------------------------------------------------------*/
/** /**
Initialize the nw-gtpv1u stack. Initialize the nw-gtpv1u stack.
@param[in,out] phGtpv1uStackHandle : Pointer to stack handle @param[in,out] phGtpv1uStackHandle : Pointer to stack handle
@@ -408,7 +390,7 @@ nwGtpv1uInitialize( NW_INOUT NwGtpv1uStackHandleT* phGtpv1uStackHandle);
* Destructor * Destructor
*--------------------------------------------------------------------------*/ *--------------------------------------------------------------------------*/
/** /**
Destroy the nw-gtpv1u stack. Destroy the nw-gtpv1u stack.
@param[in] hGtpv1uStackHandle : Stack handle @param[in] hGtpv1uStackHandle : Stack handle
@@ -421,7 +403,7 @@ nwGtpv1uFinalize( NW_IN NwGtpv1uStackHandleT hGtpv1uStackHandle);
* Configuration Get/Set Operations * Configuration Get/Set Operations
*--------------------------------------------------------------------------*/ *--------------------------------------------------------------------------*/
/** /**
Set Configuration for the nw-gtpv1u stack. Set Configuration for the nw-gtpv1u stack.
@param[in,out] phGtpv1uStackHandle : Pointer to stack handle @param[in,out] phGtpv1uStackHandle : Pointer to stack handle
@@ -430,7 +412,7 @@ nwGtpv1uFinalize( NW_IN NwGtpv1uStackHandleT hGtpv1uStackHandle);
NwGtpv1uRcT NwGtpv1uRcT
NwGtpv1uConfigSet( NW_IN NwGtpv1uStackHandleT* phGtpv1uStackHandle, NW_IN NwGtpv1uStackConfigT* pConfig); NwGtpv1uConfigSet( NW_IN NwGtpv1uStackHandleT* phGtpv1uStackHandle, NW_IN NwGtpv1uStackConfigT* pConfig);
/** /**
Get Configuration for the nw-gtpv1u stack. Get Configuration for the nw-gtpv1u stack.
@param[in,out] phGtpv1uStackHandle : Pointer to stack handle @param[in,out] phGtpv1uStackHandle : Pointer to stack handle
@@ -439,7 +421,7 @@ NwGtpv1uConfigSet( NW_IN NwGtpv1uStackHandleT* phGtpv1uStackHandle, NW_IN NwGtpv
NwGtpv1uRcT NwGtpv1uRcT
NwGtpv1uConfigGet( NW_IN NwGtpv1uStackHandleT* phGtpv1uStackHandle, NW_OUT NwGtpv1uStackConfigT* pConfig); NwGtpv1uConfigGet( NW_IN NwGtpv1uStackHandleT* phGtpv1uStackHandle, NW_OUT NwGtpv1uStackConfigT* pConfig);
/** /**
Set ULP entity for the stack. Set ULP entity for the stack.
@param[in] hGtpv1uStackHandle : Stack handle @param[in] hGtpv1uStackHandle : Stack handle
@@ -449,9 +431,9 @@ NwGtpv1uConfigGet( NW_IN NwGtpv1uStackHandleT* phGtpv1uStackHandle, NW_OUT NwGtp
NwGtpv1uRcT NwGtpv1uRcT
nwGtpv1uSetUlpEntity( NW_IN NwGtpv1uStackHandleT hGtpv1uStackHandle, nwGtpv1uSetUlpEntity( NW_IN NwGtpv1uStackHandleT hGtpv1uStackHandle,
NW_IN NwGtpv1uUlpEntityT* pUlpEntity); NW_IN NwGtpv1uUlpEntityT* pUlpEntity);
/** /**
Set UDP entity for the stack. Set UDP entity for the stack.
@param[in] hGtpv1uStackHandle : Stack handle @param[in] hGtpv1uStackHandle : Stack handle
@@ -461,9 +443,9 @@ nwGtpv1uSetUlpEntity( NW_IN NwGtpv1uStackHandleT hGtpv1uStackHandle,
NwGtpv1uRcT NwGtpv1uRcT
nwGtpv1uSetUdpEntity( NW_IN NwGtpv1uStackHandleT hGtpv1uStackHandle, nwGtpv1uSetUdpEntity( NW_IN NwGtpv1uStackHandleT hGtpv1uStackHandle,
NW_IN NwGtpv1uUdpEntityT* pUdpEntity); NW_IN NwGtpv1uUdpEntityT* pUdpEntity);
/** /**
Set MemMgr entity for the stack. Set MemMgr entity for the stack.
@param[in] hGtpv1uStackHandle : Stack handle @param[in] hGtpv1uStackHandle : Stack handle
@@ -473,10 +455,10 @@ nwGtpv1uSetUdpEntity( NW_IN NwGtpv1uStackHandleT hGtpv1uStackHandle,
NwGtpv1uRcT NwGtpv1uRcT
nwGtpv1uSetMemMgrEntity( NW_IN NwGtpv1uStackHandleT hGtpv1uStackHandle, nwGtpv1uSetMemMgrEntity( NW_IN NwGtpv1uStackHandleT hGtpv1uStackHandle,
NW_IN NwGtpv1uMemMgrEntityT* pMemMgr); NW_IN NwGtpv1uMemMgrEntityT* pMemMgr);
/** /**
Set TmrMgr entity for the stack. Set TmrMgr entity for the stack.
@param[in] hGtpv1uStackHandle : Stack handle @param[in] hGtpv1uStackHandle : Stack handle
@@ -486,9 +468,9 @@ nwGtpv1uSetMemMgrEntity( NW_IN NwGtpv1uStackHandleT hGtpv1uStackHandle,
NwGtpv1uRcT NwGtpv1uRcT
nwGtpv1uSetTimerMgrEntity( NW_IN NwGtpv1uStackHandleT hGtpv1uStackHandle, nwGtpv1uSetTimerMgrEntity( NW_IN NwGtpv1uStackHandleT hGtpv1uStackHandle,
NW_IN NwGtpv1uTimerMgrEntityT* pTmrMgr); NW_IN NwGtpv1uTimerMgrEntityT* pTmrMgr);
/** /**
Set LogMgr entity for the stack. Set LogMgr entity for the stack.
@param[in] hGtpv1uStackHandle : Stack handle @param[in] hGtpv1uStackHandle : Stack handle
@@ -498,9 +480,9 @@ nwGtpv1uSetTimerMgrEntity( NW_IN NwGtpv1uStackHandleT hGtpv1uStackHandle,
NwGtpv1uRcT NwGtpv1uRcT
nwGtpv1uSetLogMgrEntity( NW_IN NwGtpv1uStackHandleT hGtpv1uStackHandle, nwGtpv1uSetLogMgrEntity( NW_IN NwGtpv1uStackHandleT hGtpv1uStackHandle,
NW_IN NwGtpv1uLogMgrEntityT* pLogMgr); NW_IN NwGtpv1uLogMgrEntityT* pLogMgr);
/** /**
Set log level for the stack. Set log level for the stack.
@param[in] hGtpv1uStackHandle : Stack handle @param[in] hGtpv1uStackHandle : Stack handle
@@ -526,12 +508,12 @@ nwGtpv1uSetLogLevel( NW_IN NwGtpv1uStackHandleT hGtpuStackHandle,
@return NW_GTPV1U_OK on success. @return NW_GTPV1U_OK on success.
*/ */
NwGtpv1uRcT NwGtpv1uRcT
nwGtpv1uProcessUdpReq( NW_IN NwGtpv1uStackHandleT hGtpv1uStackHandle, nwGtpv1uProcessUdpReq( NW_IN NwGtpv1uStackHandleT hGtpv1uStackHandle,
NW_IN NwU8T* udpData, NW_IN NwU8T* udpData,
NW_IN NwU32T udpDataLen, NW_IN NwU32T udpDataLen,
NW_IN NwU16T peerPort, NW_IN NwU16T peerPort,
NW_IN NwU32T peerIP); NW_IN NwU32T peerIP);
/*--------------------------------------------------------------------------- /*---------------------------------------------------------------------------
* Process Request from Upper Layer * Process Request from Upper Layer
@@ -1,6 +1,6 @@
/*----------------------------------------------------------------------------* /*----------------------------------------------------------------------------*
* * * *
* n w - g t p v 2 c * * 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 * * 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 *
* * * *
* * * *
@@ -35,8 +35,8 @@
#ifndef __NW_GTPV1U_ERROR_H__ #ifndef __NW_GTPV1U_ERROR_H__
#define __NW_GTPV1U_ERROR_H__ #define __NW_GTPV1U_ERROR_H__
/** /**
* @file NwGtpv1uError.h * @file NwGtpv1uError.h
* @brief This header file contains return error code type definitions. * @brief This header file contains return error code type definitions.
*/ */
@@ -51,7 +51,8 @@ typedef enum {
NW_GTPV1U_MANDATORY_IE_MISSING, NW_GTPV1U_MANDATORY_IE_MISSING,
NW_GTPV1U_MSG_MALFORMED, NW_GTPV1U_MSG_MALFORMED,
NW_GTPV1U_FAILURE = 0xFFFFFFFE NW_GTPV1U_FAILURE = 0xFFFFFFFE
} NwGtpv1uRcT; }
NwGtpv1uRcT;
#ifdef __cplusplus #ifdef __cplusplus
} }
@@ -1,6 +1,6 @@
/*----------------------------------------------------------------------------* /*----------------------------------------------------------------------------*
* * * *
* 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 * * 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 *
* * * *
* * * *
@@ -31,7 +31,7 @@
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
/** /**
* @file NwGtpv1uIe.h * @file NwGtpv1uIe.h
* @brief This header file contains Information Element definitions for GTPv1u * @brief This header file contains Information Element definitions for GTPv1u
* as per 3GPP TS 29281-930. * as per 3GPP TS 29281-930.
@@ -55,8 +55,8 @@
* 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 * * 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_REQUEST_ACCEPTED (16)
#define NW_GTPV1U_CAUSE_MANDATORY_IE_MISSING (70) #define NW_GTPV1U_CAUSE_MANDATORY_IE_MISSING (70)
#endif /* __NW_GTPV1U_IE_H__ */ #endif /* __NW_GTPV1U_IE_H__ */
+141 -145
View File
@@ -1,6 +1,6 @@
/*----------------------------------------------------------------------------* /*----------------------------------------------------------------------------*
* * * *
* 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 * * 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 *
* * * *
* * * *
@@ -37,7 +37,7 @@
#include "NwTypes.h" #include "NwTypes.h"
#include "NwGtpv1u.h" #include "NwGtpv1u.h"
/** /**
* @file NwGtpv1uMsg.h * @file NwGtpv1uMsg.h
* @brief This file defines APIs for to build new outgoing gtpv1u messages and to parse incoming messages. * @brief This file defines APIs for to build new outgoing gtpv1u messages and to parse incoming messages.
*/ */
@@ -52,26 +52,22 @@ extern "C" {
#pragma pack(1) #pragma pack(1)
typedef struct NwGtpv1uIeTv1 typedef struct NwGtpv1uIeTv1 {
{
NwU8T t; NwU8T t;
NwU8T v; NwU8T v;
} NwGtpv1uIeTv1T; } NwGtpv1uIeTv1T;
typedef struct NwGtpv1uIeTv2 typedef struct NwGtpv1uIeTv2 {
{
NwU8T t; NwU8T t;
NwU8T v; NwU8T v;
} NwGtpv1uIeTv2T; } NwGtpv1uIeTv2T;
typedef struct NwGtpv1uIeTv4 typedef struct NwGtpv1uIeTv4 {
{
NwU8T t; NwU8T t;
NwU32T v; NwU32T v;
} NwGtpv1uIeTv4T; } NwGtpv1uIeTv4T;
typedef struct NwGtpv1uIeTlv typedef struct NwGtpv1uIeTlv {
{
NwU8T t; NwU8T t;
NwU16T l; NwU16T l;
} NwGtpv1uIeTlvT; } NwGtpv1uIeTlvT;
@@ -79,15 +75,15 @@ typedef struct NwGtpv1uIeTlv
#pragma pack() #pragma pack()
/** /**
* Allocate a GPDU gtpv1u message. * Allocate a GPDU gtpv1u message.
* *
* @param[in] hGtpuStackHandle : gtpv1u stack handle. * @param[in] hGtpuStackHandle : gtpv1u stack handle.
* @param[in] teidPresent : TEID is present flag. * @param[in] teidPresent : TEID is present flag.
* @param[in] teid : TEID for this message. * @param[in] teid : TEID for this message.
* @param[in] seqNum : Sequence number for this message. * @param[in] seqNum : Sequence number for this message.
* @param[out] phMsg : Pointer to message handle. * @param[out] phMsg : Pointer to message handle.
*/ */
NwGtpv1uRcT NwGtpv1uRcT
nwGtpv1uMsgNew( NW_IN NwGtpv1uStackHandleT hGtpuStackHandle, nwGtpv1uMsgNew( NW_IN NwGtpv1uStackHandleT hGtpuStackHandle,
@@ -102,130 +98,130 @@ nwGtpv1uMsgNew( NW_IN NwGtpv1uStackHandleT hGtpuStackHandle,
NW_OUT NwGtpv1uMsgHandleT *phMsg); NW_OUT NwGtpv1uMsgHandleT *phMsg);
/** /**
* Allocate a gtpv1u message. * Allocate a gtpv1u message.
* *
* @param[in] hGtpuStackHandle : gtpv1u stack handle. * @param[in] hGtpuStackHandle : gtpv1u stack handle.
* @param[in] teid : TEID for this message. * @param[in] teid : TEID for this message.
* @param[in] seqNumFlag : Sequence number flag for this message. * @param[in] seqNumFlag : Sequence number flag for this message.
* @param[in] seqNum : Sequence number for this message. * @param[in] seqNum : Sequence number for this message.
* @param[in] pTpdu: T-PDU for this message. * @param[in] pTpdu: T-PDU for this message.
* @param[in] tpduLength: T-PDU length for this message. * @param[in] tpduLength: T-PDU length for this message.
* @param[out] phMsg : Pointer to message handle. * @param[out] phMsg : Pointer to message handle.
*/ */
NwGtpv1uRcT NwGtpv1uRcT
nwGtpv1uGpduMsgNew( NW_IN NwGtpv1uStackHandleT hGtpuStackHandle, nwGtpv1uGpduMsgNew( NW_IN NwGtpv1uStackHandleT hGtpuStackHandle,
NW_IN NwU32T teid, NW_IN NwU32T teid,
NW_IN NwU8T seqNumFlag, NW_IN NwU8T seqNumFlag,
NW_IN NwU16T seqNum, NW_IN NwU16T seqNum,
NW_IN NwU8T* tpdu, NW_IN NwU8T* tpdu,
NW_IN NwU16T tpduLength, NW_IN NwU16T tpduLength,
NW_IN NwU32T tpduOffset, NW_IN NwU32T tpduOffset,
NW_OUT NwGtpv1uMsgHandleT *phMsg); NW_OUT NwGtpv1uMsgHandleT *phMsg);
/** /**
* Allocate a gtpv1u message from another gtpv1u message. * Allocate a gtpv1u message from another gtpv1u message.
* *
* @param[in] hGtpuStackHandle : gtpv1u stack handle. * @param[in] hGtpuStackHandle : gtpv1u stack handle.
* @param[out] hMsg : Handle to input message. * @param[out] hMsg : Handle to input message.
* @param[out] phMsg : Pointer to message handle. * @param[out] phMsg : Pointer to message handle.
*/ */
NwGtpv1uRcT NwGtpv1uRcT
nwGtpv1uMsgFromMsgNew( NW_IN NwGtpv1uStackHandleT hGtpuStackHandle, nwGtpv1uMsgFromMsgNew( NW_IN NwGtpv1uStackHandleT hGtpuStackHandle,
NW_IN NwGtpv1uMsgHandleT hMsg, NW_IN NwGtpv1uMsgHandleT hMsg,
NW_OUT NwGtpv1uMsgHandleT *phMsg); NW_OUT NwGtpv1uMsgHandleT *phMsg);
/** /**
* Allocate a gtpv1u message from data buffer. * Allocate a gtpv1u message from data buffer.
* *
* @param[in] hGtpuStackHandle : gtpv1u stack handle. * @param[in] hGtpuStackHandle : gtpv1u stack handle.
* @param[in] pBuf: Buffer to be copied in this message. * @param[in] pBuf: Buffer to be copied in this message.
* @param[in] bufLen: Buffer length to be copied in this message. * @param[in] bufLen: Buffer length to be copied in this message.
* @param[out] phMsg : Pointer to message handle. * @param[out] phMsg : Pointer to message handle.
*/ */
NwGtpv1uRcT NwGtpv1uRcT
nwGtpv1uMsgFromBufferNew( NW_IN NwGtpv1uStackHandleT hGtpuStackHandle, nwGtpv1uMsgFromBufferNew( NW_IN NwGtpv1uStackHandleT hGtpuStackHandle,
NW_IN NwU8T* pBuf, NW_IN NwU8T* pBuf,
NW_IN NwU32T bufLen, NW_IN NwU32T bufLen,
NW_OUT NwGtpv1uMsgHandleT *phMsg); NW_OUT NwGtpv1uMsgHandleT *phMsg);
/** /**
* Free a gtpv1u message. * Free a gtpv1u message.
* *
* @param[in] hGtpuStackHandle : gtpv1u stack handle. * @param[in] hGtpuStackHandle : gtpv1u stack handle.
* @param[in] hMsg : Message handle. * @param[in] hMsg : Message handle.
*/ */
NwGtpv1uRcT NwGtpv1uRcT
nwGtpv1uMsgDelete( NW_IN NwGtpv1uStackHandleT hGtpuStackHandle, nwGtpv1uMsgDelete( NW_IN NwGtpv1uStackHandleT hGtpuStackHandle,
NW_IN NwGtpv1uMsgHandleT hMsg); NW_IN NwGtpv1uMsgHandleT hMsg);
/** /**
* Set TEID for gtpv1u message. * Set TEID for gtpv1u message.
* *
* @param[in] hMsg : Message handle. * @param[in] hMsg : Message handle.
* @param[in] teid: TEID value. * @param[in] teid: TEID value.
*/ */
NwGtpv1uRcT NwGtpv1uRcT
nwGtpv1uMsgSetTeid(NW_IN NwGtpv1uMsgHandleT hMsg, NwU32T teid); nwGtpv1uMsgSetTeid(NW_IN NwGtpv1uMsgHandleT hMsg, NwU32T teid);
/** /**
* Set TEID present flag for gtpv1u message. * Set TEID present flag for gtpv1u message.
* *
* @param[in] hMsg : Message handle. * @param[in] hMsg : Message handle.
* @param[in] teidPesent: Flag boolean value. * @param[in] teidPesent: Flag boolean value.
*/ */
NwGtpv1uRcT NwGtpv1uRcT
nwGtpv1uMsgSetTeidPresent(NW_IN NwGtpv1uMsgHandleT hMsg, NwBoolT teidPresent); nwGtpv1uMsgSetTeidPresent(NW_IN NwGtpv1uMsgHandleT hMsg, NwBoolT teidPresent);
/** /**
* Set sequence for gtpv1u message. * Set sequence for gtpv1u message.
* *
* @param[in] hMsg : Message handle. * @param[in] hMsg : Message handle.
* @param[in] seqNum: Flag boolean value. * @param[in] seqNum: Flag boolean value.
*/ */
NwGtpv1uRcT NwGtpv1uRcT
nwGtpv1uMsgSetSeqNumber(NW_IN NwGtpv1uMsgHandleT hMsg, NwU32T seqNum); nwGtpv1uMsgSetSeqNumber(NW_IN NwGtpv1uMsgHandleT hMsg, NwU32T seqNum);
/** /**
* Get TEID present for gtpv1u message. * Get TEID present for gtpv1u message.
* *
* @param[in] hMsg : Message handle. * @param[in] hMsg : Message handle.
*/ */
NwU32T NwU32T
nwGtpv1uMsgGetTeid(NW_IN NwGtpv1uMsgHandleT hMsg); nwGtpv1uMsgGetTeid(NW_IN NwGtpv1uMsgHandleT hMsg);
/** /**
* Get TEID present for gtpv1u message. * Get TEID present for gtpv1u message.
* *
* @param[in] hMsg : Message handle. * @param[in] hMsg : Message handle.
*/ */
NwBoolT NwBoolT
nwGtpv1uMsgGetTeidPresent(NW_IN NwGtpv1uMsgHandleT hMsg); nwGtpv1uMsgGetTeidPresent(NW_IN NwGtpv1uMsgHandleT hMsg);
/** /**
* Get sequence number for gtpv1u message. * Get sequence number for gtpv1u message.
* *
* @param[in] hMsg : Message handle. * @param[in] hMsg : Message handle.
*/ */
NwU32T NwU32T
nwGtpv1uMsgGetSeqNumber(NW_IN NwGtpv1uMsgHandleT hMsg); nwGtpv1uMsgGetSeqNumber(NW_IN NwGtpv1uMsgHandleT hMsg);
/** /**
* Get tpdu for gtpv1u message. * Get tpdu for gtpv1u message.
* *
* @param[in] hMsg : Message handle. * @param[in] hMsg : Message handle.
* @param[inout] pTpduBuf : Buffer to copy the T-PDU. * @param[inout] pTpduBuf : Buffer to copy the T-PDU.
* @param[out] hMsg : T-PDU length. * @param[out] hMsg : T-PDU length.
*/ */
NwU32T NwU32T
nwGtpv1uMsgGetTpdu(NW_IN NwGtpv1uMsgHandleT hMsg, NwU8T* pTpduBuf, NwU32T* pTpduLength); nwGtpv1uMsgGetTpdu(NW_IN NwGtpv1uMsgHandleT hMsg, NwU8T* pTpduBuf, NwU32T* pTpduLength);
@@ -236,64 +232,64 @@ nwGtpv1uMsgGetTpduHandle(NW_IN NwGtpv1uMsgHandleT hMsg);
NwU32T NwU32T
nwGtpv1uMsgGetTpduLength(NW_IN NwGtpv1uMsgHandleT hMsg); nwGtpv1uMsgGetTpduLength(NW_IN NwGtpv1uMsgHandleT hMsg);
/** /**
* Add a gtpv1u information element of length 1 to gtpv1u mesasge. * Add a gtpv1u information element of length 1 to gtpv1u mesasge.
* *
* @param[in] hMsg : Handle to gtpv1u message. * @param[in] hMsg : Handle to gtpv1u message.
* @param[in] type : IE type. * @param[in] type : IE type.
* @param[in] value : IE value. * @param[in] value : IE value.
*/ */
NwGtpv1uRcT NwGtpv1uRcT
nwGtpv1uMsgAddIeTV1(NW_IN NwGtpv1uMsgHandleT hMsg, nwGtpv1uMsgAddIeTV1(NW_IN NwGtpv1uMsgHandleT hMsg,
NW_IN NwU8T type, NW_IN NwU8T type,
NW_IN NwU8T value); NW_IN NwU8T value);
/** /**
* Add a gtpv1u information element of length 2 to gtpv1u mesasge. * Add a gtpv1u information element of length 2 to gtpv1u mesasge.
* *
* @param[in] hMsg : Handle to gtpv1u message. * @param[in] hMsg : Handle to gtpv1u message.
* @param[in] type : IE type. * @param[in] type : IE type.
* @param[in] value : IE value. * @param[in] value : IE value.
*/ */
NwGtpv1uRcT NwGtpv1uRcT
nwGtpv1uMsgAddIeTV2(NW_IN NwGtpv1uMsgHandleT hMsg, nwGtpv1uMsgAddIeTV2(NW_IN NwGtpv1uMsgHandleT hMsg,
NW_IN NwU8T type, NW_IN NwU8T type,
NW_IN NwU16T length, NW_IN NwU16T length,
NW_IN NwU16T value); NW_IN NwU16T value);
/** /**
* Add a gtpv1u information element of length 4 to gtpv1u mesasge. * Add a gtpv1u information element of length 4 to gtpv1u mesasge.
* *
* @param[in] hMsg : Handle to gtpv1u message. * @param[in] hMsg : Handle to gtpv1u message.
* @param[in] type : IE type. * @param[in] type : IE type.
* @param[in] value : IE value. * @param[in] value : IE value.
*/ */
NwGtpv1uRcT NwGtpv1uRcT
nwGtpv1uMsgAddIeTV4(NW_IN NwGtpv1uMsgHandleT hMsg, nwGtpv1uMsgAddIeTV4(NW_IN NwGtpv1uMsgHandleT hMsg,
NW_IN NwU8T type, NW_IN NwU8T type,
NW_IN NwU16T length, NW_IN NwU16T length,
NW_IN NwU32T value); NW_IN NwU32T value);
/** /**
* Add a gtpv1u information element of variable length to gtpv1u mesasge. * Add a gtpv1u information element of variable length to gtpv1u mesasge.
* *
* @param[in] hMsg : Handle to gtpv1u message. * @param[in] hMsg : Handle to gtpv1u message.
* @param[in] type : IE type. * @param[in] type : IE type.
* @param[in] length : IE length. * @param[in] length : IE length.
* @param[in] value : IE value. * @param[in] value : IE value.
*/ */
NwGtpv1uRcT NwGtpv1uRcT
nwGtpv1uMsgAddIe(NW_IN NwGtpv1uMsgHandleT hMsg, nwGtpv1uMsgAddIe(NW_IN NwGtpv1uMsgHandleT hMsg,
NW_IN NwU8T type, NW_IN NwU8T type,
NW_IN NwU16T length, NW_IN NwU16T length,
NW_IN NwU8T* pVal); NW_IN NwU8T* pVal);
/** /**
* Dump the contents of gtpv1u mesasge. * Dump the contents of gtpv1u mesasge.
+4 -4
View File
@@ -1,6 +1,6 @@
/*----------------------------------------------------------------------------* /*----------------------------------------------------------------------------*
* * * *
* n w - g t p v 2 c * * 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 * * 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 *
* * * *
* * * *
@@ -39,8 +39,8 @@
#include "NwTypes.h" #include "NwTypes.h"
/** /**
* @file NwLog.h * @file NwLog.h
* @brief This header file contains global shared logging definitions. * @brief This header file contains global shared logging definitions.
*/ */
@@ -56,7 +56,7 @@ extern "C" {
#define NW_LOG_LEVEL_ALER (1) /**< action must be taken immediately*/ #define NW_LOG_LEVEL_ALER (1) /**< action must be taken immediately*/
#define NW_LOG_LEVEL_CRIT (2) /**< critical conditions */ #define NW_LOG_LEVEL_CRIT (2) /**< critical conditions */
#define NW_LOG_LEVEL_ERRO (3) /**< error conditions */ #define NW_LOG_LEVEL_ERRO (3) /**< error conditions */
#define NW_LOG_LEVEL_WARN (4) /**< warning conditions */ #define NW_LOG_LEVEL_WARN (4) /**< warning conditions */
#define NW_LOG_LEVEL_NOTI (5) /**< normal but signification condition */ #define NW_LOG_LEVEL_NOTI (5) /**< normal but signification condition */
#define NW_LOG_LEVEL_INFO (6) /**< informational */ #define NW_LOG_LEVEL_INFO (6) /**< informational */
#define NW_LOG_LEVEL_DEBG (7) /**< debug-level messages */ #define NW_LOG_LEVEL_DEBG (7) /**< debug-level messages */
@@ -1,6 +1,6 @@
/*----------------------------------------------------------------------------* /*----------------------------------------------------------------------------*
* * * *
* n w - g t p v 2 c * * 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 * * 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 *
* * * *
* * * *
@@ -38,7 +38,7 @@
#ifndef __NW_TYPES_H__ #ifndef __NW_TYPES_H__
#define __NW_TYPES_H__ #define __NW_TYPES_H__
/** /**
* @file NwTypes.h * @file NwTypes.h
* @brief This header file contains basic type definitions. * @brief This header file contains basic type definitions.
*/ */
@@ -1,6 +1,6 @@
/*----------------------------------------------------------------------------* /*----------------------------------------------------------------------------*
* * * *
* n w - g t p v 2 c * * 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 * * 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 *
* * * *
* * * *
@@ -37,13 +37,13 @@
#define __NW_UTILS_H__ #define __NW_UTILS_H__
/** /**
* @file NwUtils.h * @file NwUtils.h
* @brief This header file contains utility macro and function definitions. * @brief This header file contains utility macro and function definitions.
*/ */
#define NW_ASSERT assert /**< Assertion */ #define NW_ASSERT assert /**< Assertion */
#define NW_CHK_NULL_PTR(_ptr) NW_ASSERT(_ptr != NULL) /**< Null pointer check */ #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_HTONS(x) ( ( ((x) & 0xff00) >> 8 ) | ( ((x) & 0x00ff) << 8 ) )
@@ -56,7 +56,7 @@
( ( ((NwU64T)x) & 0x0000ff0000000000ULL ) >> 24 ) | ( ( ((NwU64T)x) & 0x000000ff00000000ULL ) >> 8 ) | \ ( ( ((NwU64T)x) & 0x0000ff0000000000ULL ) >> 24 ) | ( ( ((NwU64T)x) & 0x000000ff00000000ULL ) >> 8 ) | \
( ( ((NwU64T)x) & 0x000000000000ff00ULL ) << 40 ) | ( ( ((NwU64T)x) & 0x00000000000000ffULL ) << 56 ) | \ ( ( ((NwU64T)x) & 0x000000000000ff00ULL ) << 40 ) | ( ( ((NwU64T)x) & 0x00000000000000ffULL ) << 56 ) | \
( ( ((NwU64T)x) & 0x0000000000ff0000ULL ) << 24 ) | ( ( ((NwU64T)x) & 0x00000000ff000000ULL ) << 8 ) \ ( ( ((NwU64T)x) & 0x0000000000ff0000ULL ) << 24 ) | ( ( ((NwU64T)x) & 0x00000000ff000000ULL ) << 8 ) \
) )
#define NW_NTOHS NW_HTONS #define NW_NTOHS NW_HTONS
#define NW_NTOHL NW_HTONL #define NW_NTOHL NW_HTONL
File diff suppressed because it is too large Load Diff
+274 -264
View File
@@ -70,48 +70,50 @@ nwGtpv1uMsgNew( NW_IN NwGtpv1uStackHandleT hGtpuStackHandle,
NW_IN NwU8T nextExtHeader, NW_IN NwU8T nextExtHeader,
NW_OUT NwGtpv1uMsgHandleT *phMsg) NW_OUT NwGtpv1uMsgHandleT *phMsg)
{ {
NwGtpv1uStackT *pStack = (NwGtpv1uStackT *) hGtpuStackHandle; NwGtpv1uStackT *pStack = (NwGtpv1uStackT *) hGtpuStackHandle;
NwGtpv1uMsgT *pMsg; NwGtpv1uMsgT *pMsg;
if(gpGtpv1uMsgPool) { if(gpGtpv1uMsgPool) {
pMsg = gpGtpv1uMsgPool; pMsg = gpGtpv1uMsgPool;
gpGtpv1uMsgPool = gpGtpv1uMsgPool->next; gpGtpv1uMsgPool = gpGtpv1uMsgPool->next;
} else { } else {
NW_GTPV1U_MALLOC(pStack, sizeof(NwGtpv1uMsgT), pMsg, NwGtpv1uMsgT *); 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) {
if(pMsg) { pMsg->npduNum = npduNum;
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) ?
4 : 0);
//NW_GTPV1U_EPC_SPECIFIC_HEADER_SIZE : (NW_GTPV1U_EPC_SPECIFIC_HEADER_SIZE - 4));
pMsg->msgBuf = NULL;
pMsg->msgBufLen = 0;
pMsg->msgBufOffset = 0;
*phMsg = (NwGtpv1uMsgHandleT) pMsg;
return NW_GTPV1U_OK;
} }
return NW_GTPV1U_FAILURE; if(extHdrFlag) {
pMsg->nextExtHdrType = nextExtHeader;
}
pMsg->msgLen = ((pMsg->seqNumFlag || pMsg->npduNumFlag
|| pMsg->extHdrFlag) ?
4 : 0);
//NW_GTPV1U_EPC_SPECIFIC_HEADER_SIZE : (NW_GTPV1U_EPC_SPECIFIC_HEADER_SIZE - 4));
pMsg->msgBuf = NULL;
pMsg->msgBufLen = 0;
pMsg->msgBufOffset = 0;
*phMsg = (NwGtpv1uMsgHandleT) pMsg;
return NW_GTPV1U_OK;
}
return NW_GTPV1U_FAILURE;
} }
NwGtpv1uRcT NwGtpv1uRcT
@@ -124,87 +126,87 @@ nwGtpv1uGpduMsgNew( NW_IN NwGtpv1uStackHandleT hGtpuStackHandle,
NW_IN NwU32T tpduOffset, NW_IN NwU32T tpduOffset,
NW_OUT NwGtpv1uMsgHandleT *phMsg) NW_OUT NwGtpv1uMsgHandleT *phMsg)
{ {
NwGtpv1uStackT *pStack = (NwGtpv1uStackT *) hGtpuStackHandle; NwGtpv1uStackT *pStack = (NwGtpv1uStackT *) hGtpuStackHandle;
NwGtpv1uMsgT *pMsg; NwGtpv1uMsgT *pMsg;
NwU32T msgExtraLen = 0; NwU32T msgExtraLen = 0;
if(gpGtpv1uMsgPool) { if(gpGtpv1uMsgPool) {
pMsg = gpGtpv1uMsgPool; pMsg = gpGtpv1uMsgPool;
gpGtpv1uMsgPool = gpGtpv1uMsgPool->next; gpGtpv1uMsgPool = gpGtpv1uMsgPool->next;
} else { } else {
NW_GTPV1U_MALLOC(pStack, sizeof(NwGtpv1uMsgT), pMsg, NwGtpv1uMsgT *); NW_GTPV1U_MALLOC(pStack, sizeof(NwGtpv1uMsgT), pMsg, NwGtpv1uMsgT *);
} }
if(pMsg) { if(pMsg) {
msgExtraLen = (((seqNumFlag) || (NW_FALSE) || (NW_FALSE) ) ? msgExtraLen = (((seqNumFlag) || (NW_FALSE) || (NW_FALSE) ) ?
(NW_GTPV1U_EPC_SPECIFIC_HEADER_SIZE - NW_GTPV1U_EPC_MIN_HEADER_SIZE) : 0); (NW_GTPV1U_EPC_SPECIFIC_HEADER_SIZE - NW_GTPV1U_EPC_MIN_HEADER_SIZE) : 0);
AssertFatal((msgExtraLen + NW_GTPV1U_EPC_MIN_HEADER_SIZE) <= tpduOffset, AssertFatal((msgExtraLen + NW_GTPV1U_EPC_MIN_HEADER_SIZE) <= tpduOffset,
"Mismatch GTPU len, msgExtraLen %u tpduOffset %u", "Mismatch GTPU len, msgExtraLen %u tpduOffset %u",
msgExtraLen, msgExtraLen,
tpduOffset); tpduOffset);
pMsg->msgBuf = tpdu; pMsg->msgBuf = tpdu;
pMsg->msgBufLen = tpduLength + msgExtraLen + NW_GTPV1U_EPC_MIN_HEADER_SIZE; pMsg->msgBufLen = tpduLength + msgExtraLen + NW_GTPV1U_EPC_MIN_HEADER_SIZE;
pMsg->msgBufOffset = tpduOffset - (msgExtraLen + NW_GTPV1U_EPC_MIN_HEADER_SIZE); pMsg->msgBufOffset = tpduOffset - (msgExtraLen + NW_GTPV1U_EPC_MIN_HEADER_SIZE);
#if defined(LOG_GTPU) && LOG_GTPU > 0 #if defined(LOG_GTPU) && LOG_GTPU > 0
GTPU_DEBUG("MSG length %u, offset %u -> length %u offset %u\n", GTPU_DEBUG("MSG length %u, offset %u -> length %u offset %u\n",
tpduLength, tpduOffset, tpduLength, tpduOffset,
pMsg->msgBufLen, pMsg->msgBufOffset); pMsg->msgBufLen, pMsg->msgBufOffset);
#endif #endif
// Version field: This field is used to determine the version of the GTP-U protocol. // Version field: This field is used to determine the version of the GTP-U protocol.
// The version number shall be set to '1'. // The version number shall be set to '1'.
pMsg->version = NW_GTPU_VERSION; pMsg->version = NW_GTPU_VERSION;
// Protocol Type (PT): This bit is used as a protocol discriminator between GTP (when PT is '1') // Protocol Type (PT): This bit is used as a protocol discriminator between GTP (when PT is '1')
// and GTP' (when PT is '0'). GTP is described in this document and the GTP' protocol in 3GPP TS 32.295 [8]. // and GTP' (when PT is '0'). GTP is described in this document and the GTP' protocol in 3GPP TS 32.295 [8].
// Note that the interpretation of the header fields may be different in GTP' than in GTP. // Note that the interpretation of the header fields may be different in GTP' than in GTP.
pMsg->protocolType = NW_GTP_PROTOCOL_TYPE_GTP; pMsg->protocolType = NW_GTP_PROTOCOL_TYPE_GTP;
// Extension Header flag (E): This flag indicates the presence of a meaningful value of the Next Extension // Extension Header flag (E): This flag indicates the presence of a meaningful value of the Next Extension
// Header field. When it is set to '0', the Next Extension Header field either is not present or, if present, // Header field. When it is set to '0', the Next Extension Header field either is not present or, if present,
// shall not be interpreted. // shall not be interpreted.
pMsg->extHdrFlag = NW_FALSE; pMsg->extHdrFlag = NW_FALSE;
// Sequence number flag (S): This flag indicates the presence of a meaningful value of the Sequence Number field. // Sequence number flag (S): This flag indicates the presence of a meaningful value of the Sequence Number field.
// When it is set to '0', the Sequence Number field either is not present or, if present, shall not be interpreted. // When it is set to '0', the Sequence Number field either is not present or, if present, shall not be interpreted.
// When it is set to '1', the Sequence Number field is present, and shall be interpreted, as described below in // When it is set to '1', the Sequence Number field is present, and shall be interpreted, as described below in
// this section. // this section.
// For the Echo Request, Echo Response, Error Indication and Supported Extension Headers Notification // For the Echo Request, Echo Response, Error Indication and Supported Extension Headers Notification
// messages, the S flag shall be set to '1'. Since the use of Sequence Numbers is optional for G-PDUs, the PGW, // messages, the S flag shall be set to '1'. Since the use of Sequence Numbers is optional for G-PDUs, the PGW,
// SGW, ePDG and eNodeB should set the flag to '0'. However, when a G-PDU (T-PDU+header) is being relayed // SGW, ePDG and eNodeB should set the flag to '0'. However, when a G-PDU (T-PDU+header) is being relayed
// by the Indirect Data Forwarding for Inter RAT HO procedure, then if the received G-PDU has the S flag set to // by the Indirect Data Forwarding for Inter RAT HO procedure, then if the received G-PDU has the S flag set to
// '1', then the relaying entity shall set S flag to '1' and forward the G-PDU (T-PDU+header). In an End marker // '1', then the relaying entity shall set S flag to '1' and forward the G-PDU (T-PDU+header). In an End marker
// message the S flag shall be set to '0'. // message the S flag shall be set to '0'.
pMsg->seqNumFlag = (seqNumFlag? NW_TRUE : NW_FALSE); pMsg->seqNumFlag = (seqNumFlag? NW_TRUE : NW_FALSE);
pMsg->seqNum = seqNum; pMsg->seqNum = seqNum;
// N-PDU Number flag (PN): This flag indicates the presence of a meaningful value of the N-PDU Number field. // N-PDU Number flag (PN): This flag indicates the presence of a meaningful value of the N-PDU Number field.
// When it is set to '0', the N-PDU Number field either is not present, or, if present, shall not be interpreted. // When it is set to '0', the N-PDU Number field either is not present, or, if present, shall not be interpreted.
// When it is set to '1', the N-PDU Number field is present, and shall be interpreted. // When it is set to '1', the N-PDU Number field is present, and shall be interpreted.
pMsg->npduNumFlag = NW_FALSE; pMsg->npduNumFlag = NW_FALSE;
pMsg->npduNum = 0x00; pMsg->npduNum = 0x00;
// Message Type: This field indicates the type of GTP-U message. // Message Type: This field indicates the type of GTP-U message.
pMsg->msgType = NW_GTP_GPDU; pMsg->msgType = NW_GTP_GPDU;
// Length: This field indicates the length in octets of the payload, i.e. the rest of the packet following the // Length: This field indicates the length in octets of the payload, i.e. the rest of the packet following the
// mandatory part of the GTP header (that is the first 8 octets). // mandatory part of the GTP header (that is the first 8 octets).
// The Sequence Number, the N-PDU Number or any Extension headers shall be considered to be part of the payload, // The Sequence Number, the N-PDU Number or any Extension headers shall be considered to be part of the payload,
// i.e. included in the length count. // i.e. included in the length count.
//header_len = ((pMsg->seqNumFlag || pMsg->npduNumFlag || pMsg->extHdrFlag ) ? //header_len = ((pMsg->seqNumFlag || pMsg->npduNumFlag || pMsg->extHdrFlag ) ?
// NW_GTPV1U_EPC_SPECIFIC_HEADER_SIZE : NW_GTPV1U_EPC_MIN_HEADER_SIZE); // NW_GTPV1U_EPC_SPECIFIC_HEADER_SIZE : NW_GTPV1U_EPC_MIN_HEADER_SIZE);
pMsg->msgLen = msgExtraLen + tpduLength; pMsg->msgLen = msgExtraLen + tpduLength;
// Tunnel Endpoint Identifier (TEID): This field unambiguously identifies a tunnel endpoint in the receiving // Tunnel Endpoint Identifier (TEID): This field unambiguously identifies a tunnel endpoint in the receiving
// GTP-U protocol entity. The receiving end side of a GTP tunnel locally assigns the TEID value the transmitting // GTP-U protocol entity. The receiving end side of a GTP tunnel locally assigns the TEID value the transmitting
// side has to use. The TEID shall be used by the receiving entity to find the PDP context, except for the // side has to use. The TEID shall be used by the receiving entity to find the PDP context, except for the
// following cases: // following cases:
// - The Echo Request/Response and Supported Extension Headers notification messages, where the Tunnel // - The Echo Request/Response and Supported Extension Headers notification messages, where the Tunnel
// Endpoint Identifier shall be set to all zeroes. // Endpoint Identifier shall be set to all zeroes.
// - The Error Indication message where the Tunnel Endpoint Identifier shall be set to all zeros. // - The Error Indication message where the Tunnel Endpoint Identifier shall be set to all zeros.
pMsg->teid = teid; pMsg->teid = teid;
pMsg->nextExtHdrType= 0x00; pMsg->nextExtHdrType= 0x00;
//memcpy(pMsg->msgBuf + header_len, tpdu, tpduLength); //memcpy(pMsg->msgBuf + header_len, tpdu, tpduLength);
*phMsg = (NwGtpv1uMsgHandleT) pMsg; *phMsg = (NwGtpv1uMsgHandleT) pMsg;
return NW_GTPV1U_OK; return NW_GTPV1U_OK;
} }
return NW_GTPV1U_FAILURE; return NW_GTPV1U_FAILURE;
} }
NwGtpv1uRcT NwGtpv1uRcT
@@ -212,23 +214,24 @@ nwGtpv1uMsgFromMsgNew( NW_IN NwGtpv1uStackHandleT hGtpuStackHandle,
NW_IN NwGtpv1uMsgHandleT hMsg, NW_IN NwGtpv1uMsgHandleT hMsg,
NW_OUT NwGtpv1uMsgHandleT *phMsg) NW_OUT NwGtpv1uMsgHandleT *phMsg)
{ {
NwGtpv1uStackT *pStack = (NwGtpv1uStackT *) hGtpuStackHandle; NwGtpv1uStackT *pStack = (NwGtpv1uStackT *) hGtpuStackHandle;
NwGtpv1uMsgT *pMsg; NwGtpv1uMsgT *pMsg;
if(gpGtpv1uMsgPool) { if(gpGtpv1uMsgPool) {
pMsg = gpGtpv1uMsgPool; pMsg = gpGtpv1uMsgPool;
gpGtpv1uMsgPool = gpGtpv1uMsgPool->next; gpGtpv1uMsgPool = gpGtpv1uMsgPool->next;
} else { } else {
NW_GTPV1U_MALLOC(pStack, sizeof(NwGtpv1uMsgT), pMsg, NwGtpv1uMsgT *); NW_GTPV1U_MALLOC(pStack, sizeof(NwGtpv1uMsgT), pMsg, NwGtpv1uMsgT *);
} }
if(pMsg) { if(pMsg) {
memcpy(pMsg, (NwGtpv1uMsgT *)hMsg, sizeof(NwGtpv1uMsgT)); memcpy(pMsg, (NwGtpv1uMsgT *)hMsg, sizeof(NwGtpv1uMsgT));
*phMsg = (NwGtpv1uMsgHandleT) pMsg; *phMsg = (NwGtpv1uMsgHandleT) pMsg;
return NW_GTPV1U_OK; return NW_GTPV1U_OK;
} }
return NW_GTPV1U_FAILURE;
return NW_GTPV1U_FAILURE;
} }
NwGtpv1uRcT NwGtpv1uRcT
@@ -237,61 +240,63 @@ nwGtpv1uMsgFromBufferNew( NW_IN NwGtpv1uStackHandleT hGtpuStackHandle,
NW_IN NwU32T bufLen, NW_IN NwU32T bufLen,
NW_OUT NwGtpv1uMsgHandleT *phMsg) NW_OUT NwGtpv1uMsgHandleT *phMsg)
{ {
NwGtpv1uStackT *pStack = (NwGtpv1uStackT *) hGtpuStackHandle; NwGtpv1uStackT *pStack = (NwGtpv1uStackT *) hGtpuStackHandle;
NwGtpv1uMsgT *pMsg; NwGtpv1uMsgT *pMsg;
if(gpGtpv1uMsgPool) { if(gpGtpv1uMsgPool) {
pMsg = gpGtpv1uMsgPool; pMsg = gpGtpv1uMsgPool;
gpGtpv1uMsgPool = gpGtpv1uMsgPool->next; gpGtpv1uMsgPool = gpGtpv1uMsgPool->next;
} else { } else {
NW_GTPV1U_MALLOC(pStack, sizeof(NwGtpv1uMsgT), pMsg, NwGtpv1uMsgT *); NW_GTPV1U_MALLOC(pStack, sizeof(NwGtpv1uMsgT), pMsg, NwGtpv1uMsgT *);
}
if(pMsg) {
pMsg->msgBuf = pBuf;
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++);
} }
pMsg->msgBufOffset = (NwU32T)(pBuf - pMsg->msgBuf);
if(pMsg) { pMsg->msgBufLen = bufLen - pMsg->msgBufOffset;
pMsg->msgBuf = pBuf; 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++);
}
pMsg->msgBufOffset = (NwU32T)(pBuf - pMsg->msgBuf);
pMsg->msgBufLen = bufLen - pMsg->msgBufOffset;
pMsg->msgLen = bufLen;
#if defined(LOG_GTPU) && LOG_GTPU > 0 #if defined(LOG_GTPU) && LOG_GTPU > 0
GTPU_DEBUG("nwGtpv1uMsgFromBufferNew() msgLen %u msgBufLen %u msgBufOffset %u ", GTPU_DEBUG("nwGtpv1uMsgFromBufferNew() msgLen %u msgBufLen %u msgBufOffset %u ",
pMsg->msgLen, pMsg->msgBufLen, pMsg->msgBufOffset); pMsg->msgLen, pMsg->msgBufLen, pMsg->msgBufOffset);
#endif #endif
*phMsg = (NwGtpv1uMsgHandleT) pMsg; *phMsg = (NwGtpv1uMsgHandleT) pMsg;
return NW_GTPV1U_OK; return NW_GTPV1U_OK;
} }
return NW_GTPV1U_FAILURE;
return NW_GTPV1U_FAILURE;
} }
NwGtpv1uRcT NwGtpv1uRcT
nwGtpv1uMsgDelete( NW_IN NwGtpv1uStackHandleT hGtpuStackHandle, nwGtpv1uMsgDelete( NW_IN NwGtpv1uStackHandleT hGtpuStackHandle,
NW_IN NwGtpv1uMsgHandleT hMsg) NW_IN NwGtpv1uMsgHandleT hMsg)
{ {
((NwGtpv1uMsgT *)hMsg)->next = gpGtpv1uMsgPool; ((NwGtpv1uMsgT *)hMsg)->next = gpGtpv1uMsgPool;
gpGtpv1uMsgPool = (NwGtpv1uMsgT *) hMsg; gpGtpv1uMsgPool = (NwGtpv1uMsgT *) hMsg;
return NW_GTPV1U_OK; return NW_GTPV1U_OK;
} }
/** /**
@@ -304,12 +309,12 @@ nwGtpv1uMsgDelete( NW_IN NwGtpv1uStackHandleT hGtpuStackHandle,
NwGtpv1uRcT NwGtpv1uRcT
nwGtpv1uMsgSetTeid(NW_IN NwGtpv1uMsgHandleT hMsg, NwU32T teid) nwGtpv1uMsgSetTeid(NW_IN NwGtpv1uMsgHandleT hMsg, NwU32T teid)
{ {
NwGtpv1uMsgT *thiz = (NwGtpv1uMsgT *) hMsg; NwGtpv1uMsgT *thiz = (NwGtpv1uMsgT *) hMsg;
thiz->teid = teid; thiz->teid = teid;
#if defined(LOG_GTPU) && LOG_GTPU > 0 #if defined(LOG_GTPU) && LOG_GTPU > 0
GTPU_DEBUG("nwGtpv1uMsgSetTeid() teid %u", teid); GTPU_DEBUG("nwGtpv1uMsgSetTeid() teid %u", teid);
#endif #endif
return NW_GTPV1U_OK; return NW_GTPV1U_OK;
} }
/** /**
@@ -322,9 +327,9 @@ nwGtpv1uMsgSetTeid(NW_IN NwGtpv1uMsgHandleT hMsg, NwU32T teid)
NwGtpv1uRcT NwGtpv1uRcT
nwGtpv1uMsgSetSeqNumber(NW_IN NwGtpv1uMsgHandleT hMsg, NwU32T seqNum) nwGtpv1uMsgSetSeqNumber(NW_IN NwGtpv1uMsgHandleT hMsg, NwU32T seqNum)
{ {
NwGtpv1uMsgT *thiz = (NwGtpv1uMsgT *) hMsg; NwGtpv1uMsgT *thiz = (NwGtpv1uMsgT *) hMsg;
thiz->seqNum = seqNum; thiz->seqNum = seqNum;
return NW_GTPV1U_OK; return NW_GTPV1U_OK;
} }
/** /**
@@ -336,8 +341,8 @@ nwGtpv1uMsgSetSeqNumber(NW_IN NwGtpv1uMsgHandleT hMsg, NwU32T seqNum)
NwU32T NwU32T
nwGtpv1uMsgGetTeid(NW_IN NwGtpv1uMsgHandleT hMsg) nwGtpv1uMsgGetTeid(NW_IN NwGtpv1uMsgHandleT hMsg)
{ {
NwGtpv1uMsgT *thiz = (NwGtpv1uMsgT *) hMsg; NwGtpv1uMsgT *thiz = (NwGtpv1uMsgT *) hMsg;
return (thiz->teid); return (thiz->teid);
} }
@@ -350,8 +355,8 @@ nwGtpv1uMsgGetTeid(NW_IN NwGtpv1uMsgHandleT hMsg)
NwU32T NwU32T
nwGtpv1uMsgGetSeqNumber(NW_IN NwGtpv1uMsgHandleT hMsg) nwGtpv1uMsgGetSeqNumber(NW_IN NwGtpv1uMsgHandleT hMsg)
{ {
NwGtpv1uMsgT *thiz = (NwGtpv1uMsgT *) hMsg; NwGtpv1uMsgT *thiz = (NwGtpv1uMsgT *) hMsg;
return (thiz->seqNum); return (thiz->seqNum);
} }
/** /**
@@ -363,8 +368,8 @@ nwGtpv1uMsgGetSeqNumber(NW_IN NwGtpv1uMsgHandleT hMsg)
NwU32T NwU32T
nwGtpv1uMsgGetMsgType(NW_IN NwGtpv1uMsgHandleT hMsg) nwGtpv1uMsgGetMsgType(NW_IN NwGtpv1uMsgHandleT hMsg)
{ {
NwGtpv1uMsgT *thiz = (NwGtpv1uMsgT *) hMsg; NwGtpv1uMsgT *thiz = (NwGtpv1uMsgT *) hMsg;
return (thiz->msgType); return (thiz->msgType);
} }
/** /**
@@ -377,29 +382,29 @@ NwGtpv1uRcT
nwGtpv1uMsgGetTpdu(NW_IN NwGtpv1uMsgHandleT hMsg, NwU8T *pTpduBuf, nwGtpv1uMsgGetTpdu(NW_IN NwGtpv1uMsgHandleT hMsg, NwU8T *pTpduBuf,
NwU32T *pTpduLength) NwU32T *pTpduLength)
{ {
NwGtpv1uMsgT *thiz = (NwGtpv1uMsgT *) hMsg; NwGtpv1uMsgT *thiz = (NwGtpv1uMsgT *) hMsg;
NwU8T headerLength = ((thiz->seqNumFlag || thiz->extHdrFlag NwU8T headerLength = ((thiz->seqNumFlag || thiz->extHdrFlag
|| thiz->npduNumFlag) ? 12 : 8); || thiz->npduNumFlag) ? 12 : 8);
*pTpduLength = thiz->msgLen - headerLength; *pTpduLength = thiz->msgLen - headerLength;
memcpy(pTpduBuf, thiz->msgBuf + headerLength, *pTpduLength); memcpy(pTpduBuf, thiz->msgBuf + headerLength, *pTpduLength);
return NW_GTPV1U_OK; return NW_GTPV1U_OK;
} }
NwU8T * NwU8T *
nwGtpv1uMsgGetTpduHandle(NW_IN NwGtpv1uMsgHandleT hMsg) nwGtpv1uMsgGetTpduHandle(NW_IN NwGtpv1uMsgHandleT hMsg)
{ {
NwGtpv1uMsgT *thiz = (NwGtpv1uMsgT *) hMsg; NwGtpv1uMsgT *thiz = (NwGtpv1uMsgT *) hMsg;
return (thiz->msgBuf + ((thiz->seqNumFlag || thiz->extHdrFlag return (thiz->msgBuf + ((thiz->seqNumFlag || thiz->extHdrFlag
|| thiz->npduNumFlag) ? 12 : 8)); || thiz->npduNumFlag) ? 12 : 8));
} }
NwU32T NwU32T
nwGtpv1uMsgGetTpduLength(NW_IN NwGtpv1uMsgHandleT hMsg) nwGtpv1uMsgGetTpduLength(NW_IN NwGtpv1uMsgHandleT hMsg)
{ {
NwGtpv1uMsgT *thiz = (NwGtpv1uMsgT *) hMsg; NwGtpv1uMsgT *thiz = (NwGtpv1uMsgT *) hMsg;
return (thiz->msgLen - ((thiz->seqNumFlag || thiz->extHdrFlag return (thiz->msgLen - ((thiz->seqNumFlag || thiz->extHdrFlag
|| thiz->npduNumFlag) ? 12 : 8)); || thiz->npduNumFlag) ? 12 : 8));
} }
NwGtpv1uRcT NwGtpv1uRcT
@@ -407,17 +412,17 @@ nwGtpv1uMsgAddIeTV1(NW_IN NwGtpv1uMsgHandleT hMsg,
NW_IN NwU8T type, NW_IN NwU8T type,
NW_IN NwU8T value) NW_IN NwU8T value)
{ {
NwGtpv1uMsgT *pMsg = (NwGtpv1uMsgT *) hMsg; NwGtpv1uMsgT *pMsg = (NwGtpv1uMsgT *) hMsg;
NwGtpv1uIeTv1T *pIe; NwGtpv1uIeTv1T *pIe;
pIe = (NwGtpv1uIeTv1T *) (pMsg->msgBuf + pMsg->msgLen); pIe = (NwGtpv1uIeTv1T *) (pMsg->msgBuf + pMsg->msgLen);
pIe->t = type; pIe->t = type;
pIe->v = value; pIe->v = value;
pMsg->msgLen += sizeof(NwGtpv1uIeTv1T); pMsg->msgLen += sizeof(NwGtpv1uIeTv1T);
return NW_GTPV1U_OK; return NW_GTPV1U_OK;
} }
NwGtpv1uRcT NwGtpv1uRcT
@@ -426,17 +431,17 @@ nwGtpv1uMsgAddIeTV2(NW_IN NwGtpv1uMsgHandleT hMsg,
NW_IN NwU16T length, NW_IN NwU16T length,
NW_IN NwU16T value) NW_IN NwU16T value)
{ {
NwGtpv1uMsgT *pMsg = (NwGtpv1uMsgT *) hMsg; NwGtpv1uMsgT *pMsg = (NwGtpv1uMsgT *) hMsg;
NwGtpv1uIeTv2T *pIe; NwGtpv1uIeTv2T *pIe;
pIe = (NwGtpv1uIeTv2T *) (pMsg->msgBuf + pMsg->msgLen); pIe = (NwGtpv1uIeTv2T *) (pMsg->msgBuf + pMsg->msgLen);
pIe->t = type; pIe->t = type;
pIe->v = htons(value); pIe->v = htons(value);
pMsg->msgLen += sizeof(NwGtpv1uIeTv2T); pMsg->msgLen += sizeof(NwGtpv1uIeTv2T);
return NW_GTPV1U_OK; return NW_GTPV1U_OK;
} }
NwGtpv1uRcT NwGtpv1uRcT
@@ -445,17 +450,17 @@ nwGtpv1uMsgAddIeTV4(NW_IN NwGtpv1uMsgHandleT hMsg,
NW_IN NwU16T length, NW_IN NwU16T length,
NW_IN NwU32T value) NW_IN NwU32T value)
{ {
NwGtpv1uMsgT *pMsg = (NwGtpv1uMsgT *) hMsg; NwGtpv1uMsgT *pMsg = (NwGtpv1uMsgT *) hMsg;
NwGtpv1uIeTv4T *pIe; NwGtpv1uIeTv4T *pIe;
pIe = (NwGtpv1uIeTv4T *) (pMsg->msgBuf + pMsg->msgLen); pIe = (NwGtpv1uIeTv4T *) (pMsg->msgBuf + pMsg->msgLen);
pIe->t = type; pIe->t = type;
pIe->v = htonl(value); pIe->v = htonl(value);
pMsg->msgLen += sizeof(NwGtpv1uIeTv4T); pMsg->msgLen += sizeof(NwGtpv1uIeTv4T);
return NW_GTPV1U_OK; return NW_GTPV1U_OK;
} }
NwGtpv1uRcT NwGtpv1uRcT
@@ -464,76 +469,81 @@ nwGtpv1uMsgAddIe(NW_IN NwGtpv1uMsgHandleT hMsg,
NW_IN NwU16T length, NW_IN NwU16T length,
NW_IN NwU8T *pVal) NW_IN NwU8T *pVal)
{ {
NwGtpv1uMsgT *pMsg = (NwGtpv1uMsgT *) hMsg; NwGtpv1uMsgT *pMsg = (NwGtpv1uMsgT *) hMsg;
NwGtpv1uIeTlvT *pIe; NwGtpv1uIeTlvT *pIe;
pIe = (NwGtpv1uIeTlvT *) (pMsg->msgBuf + pMsg->msgLen); pIe = (NwGtpv1uIeTlvT *) (pMsg->msgBuf + pMsg->msgLen);
pIe->t = type; pIe->t = type;
pIe->l = htons(length); pIe->l = htons(length);
memcpy(pIe + 4, pVal, length); memcpy(pIe + 4, pVal, length);
pMsg->msgLen += (4 + length); pMsg->msgLen += (4 + length);
return NW_GTPV1U_OK; return NW_GTPV1U_OK;
} }
NwGtpv1uRcT NwGtpv1uRcT
nwGtpv1uMsgHexDump(NwGtpv1uMsgHandleT hMsg, FILE *fp) nwGtpv1uMsgHexDump(NwGtpv1uMsgHandleT hMsg, FILE *fp)
{ {
NwGtpv1uMsgT *pMsg = (NwGtpv1uMsgT *) hMsg; NwGtpv1uMsgT *pMsg = (NwGtpv1uMsgT *) hMsg;
NwU8T *data = pMsg->msgBuf; NwU8T *data = pMsg->msgBuf;
NwU32T size = pMsg->msgLen; NwU32T size = pMsg->msgLen;
unsigned char *p = (unsigned char *)data; unsigned char *p = (unsigned char *)data;
unsigned char c; unsigned char c;
int n; int n;
char bytestr[4] = {0}; char bytestr[4] = {0};
char addrstr[10] = {0}; char addrstr[10] = {0};
char hexstr[ 16*3 + 5] = {0}; char hexstr[ 16*3 + 5] = {0};
char charstr[16*1 + 5] = {0}; char charstr[16*1 + 5] = {0};
fprintf((FILE *)fp, "\n"); fprintf((FILE *)fp, "\n");
for(n=1; n<=size; n++) {
if (n%16 == 1) {
/* store address for this line */
snprintf(addrstr, sizeof(addrstr), "%.4lx",
(p-data) );
}
c = *p; for(n=1; n<=size; n++) {
if (isalnum(c) == 0) { if (n%16 == 1) {
c = '.'; /* store address for this line */
} snprintf(addrstr, sizeof(addrstr), "%.4lx",
(p-data) );
/* 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) { c = *p;
/* print rest of buffer if not empty */
fprintf((FILE *)fp, "[%4.4s] %-50.50s %s\n", addrstr, hexstr, charstr);
if (isalnum(c) == 0) {
c = '.';
} }
fprintf((FILE *)fp, "\n");
return NW_GTPV1U_OK; /* 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 #ifdef __cplusplus
+179 -174
View File
@@ -64,61 +64,62 @@ static NwGtpv1uTrxnT *gpGtpv1uTrxnPool = NULL;
static NwGtpv1uRcT static NwGtpv1uRcT
nwGtpv1uTrxnSendMsgRetransmission(NwGtpv1uTrxnT *thiz) nwGtpv1uTrxnSendMsgRetransmission(NwGtpv1uTrxnT *thiz)
{ {
NwGtpv1uRcT rc; NwGtpv1uRcT rc;
NW_ASSERT(thiz); NW_ASSERT(thiz);
NW_ASSERT(thiz->pMsg); NW_ASSERT(thiz->pMsg);
rc = thiz->pStack->udp.udpDataReqCallback(thiz->pStack->udp.hUdp, rc = thiz->pStack->udp.udpDataReqCallback(thiz->pStack->udp.hUdp,
thiz->pMsg->msgBuf, thiz->pMsg->msgBuf,
thiz->pMsg->msgLen, thiz->pMsg->msgLen,
thiz->pMsg->msgBufOffset, thiz->pMsg->msgBufOffset,
thiz->peerIp, thiz->peerIp,
thiz->peerPort); thiz->peerPort);
return rc; return rc;
} }
static NwGtpv1uRcT static NwGtpv1uRcT
nwGtpv1uTrxnPeerRspTimeout(void *arg) nwGtpv1uTrxnPeerRspTimeout(void *arg)
{ {
NwGtpv1uRcT rc = NW_GTPV1U_OK; NwGtpv1uRcT rc = NW_GTPV1U_OK;
NwGtpv1uTrxnT *thiz; NwGtpv1uTrxnT *thiz;
NwGtpv1uStackT *pStack; NwGtpv1uStackT *pStack;
NwGtpv1uTimeoutInfoT *timeoutInfo = arg; NwGtpv1uTimeoutInfoT *timeoutInfo = arg;
thiz = ((NwGtpv1uTrxnT *)timeoutInfo->timeoutArg); thiz = ((NwGtpv1uTrxnT *)timeoutInfo->timeoutArg);
pStack = thiz->pStack; pStack = thiz->pStack;
NW_ASSERT(pStack); NW_ASSERT(pStack);
NW_LOG(pStack, NW_LOG_LEVEL_WARN, "T3 timer expired for transaction 0x%p", NW_LOG(pStack, NW_LOG_LEVEL_WARN, "T3 timer expired for transaction 0x%p",
thiz); thiz);
rc = nwGtpv1uTrxnSendMsgRetransmission(thiz); rc = nwGtpv1uTrxnSendMsgRetransmission(thiz);
if(thiz->maxRetries) { if(thiz->maxRetries) {
rc = pStack->tmrMgr.tmrStartCallback(pStack->tmrMgr.tmrMgrHandle, rc = pStack->tmrMgr.tmrStartCallback(pStack->tmrMgr.tmrMgrHandle,
thiz->t3Timer, 0, NW_GTPV1U_TMR_TYPE_ONE_SHOT, (void *)timeoutInfo, thiz->t3Timer, 0, NW_GTPV1U_TMR_TYPE_ONE_SHOT, (void *)timeoutInfo,
&thiz->hRspTmr); &thiz->hRspTmr);
thiz->maxRetries--; thiz->maxRetries--;
} else { } else {
NwGtpv1uUlpApiT ulpApi; NwGtpv1uUlpApiT ulpApi;
ulpApi.apiType = NW_GTPV1U_ULP_API_RSP_FAILURE; ulpApi.apiType = NW_GTPV1U_ULP_API_RSP_FAILURE;
ulpApi.apiInfo.recvMsgInfo.msgType = nwGtpv1uMsgGetMsgType(( ulpApi.apiInfo.recvMsgInfo.msgType = nwGtpv1uMsgGetMsgType((
NwGtpv1uMsgHandleT)thiz->pMsg); NwGtpv1uMsgHandleT)thiz->pMsg);
ulpApi.apiInfo.recvMsgInfo.hUlpTrxn = thiz->hUlpTrxn; ulpApi.apiInfo.recvMsgInfo.hUlpTrxn = thiz->hUlpTrxn;
ulpApi.apiInfo.recvMsgInfo.peerIp = thiz->peerIp; ulpApi.apiInfo.recvMsgInfo.peerIp = thiz->peerIp;
ulpApi.apiInfo.recvMsgInfo.peerPort = thiz->peerPort; ulpApi.apiInfo.recvMsgInfo.peerPort = thiz->peerPort;
thiz->hRspTmr = 0; thiz->hRspTmr = 0;
rc = nwGtpv1uTrxnDelete(&thiz); rc = nwGtpv1uTrxnDelete(&thiz);
NW_ASSERT(rc == NW_GTPV1U_OK); NW_ASSERT(rc == NW_GTPV1U_OK);
rc = pStack->ulp.ulpReqCallback(pStack->ulp.hUlp, &ulpApi); rc = pStack->ulp.ulpReqCallback(pStack->ulp.hUlp, &ulpApi);
NW_ASSERT(rc == NW_GTPV1U_OK); NW_ASSERT(rc == NW_GTPV1U_OK);
} }
return rc;
return rc;
} }
/** /**
@@ -133,21 +134,21 @@ static NwGtpv1uRcT
nwGtpv1uTrxnStartPeerRspTimer(NwGtpv1uTrxnT *thiz, nwGtpv1uTrxnStartPeerRspTimer(NwGtpv1uTrxnT *thiz,
NwGtpv1uRcT (*timeoutCallbackFunc)(void *)) NwGtpv1uRcT (*timeoutCallbackFunc)(void *))
{ {
NwGtpv1uRcT rc; NwGtpv1uRcT rc;
NwGtpv1uTimeoutInfoT *timeoutInfo; NwGtpv1uTimeoutInfoT *timeoutInfo;
NW_ASSERT(thiz->pStack->tmrMgr.tmrStartCallback != NULL); NW_ASSERT(thiz->pStack->tmrMgr.tmrStartCallback != NULL);
timeoutInfo = &thiz->peerRspTimeoutInfo; timeoutInfo = &thiz->peerRspTimeoutInfo;
timeoutInfo->timeoutArg = thiz; timeoutInfo->timeoutArg = thiz;
timeoutInfo->timeoutCallbackFunc = timeoutCallbackFunc; timeoutInfo->timeoutCallbackFunc = timeoutCallbackFunc;
timeoutInfo->hStack = (NwGtpv1uStackHandleT)thiz->pStack; timeoutInfo->hStack = (NwGtpv1uStackHandleT)thiz->pStack;
rc = thiz->pStack->tmrMgr.tmrStartCallback(thiz->pStack->tmrMgr.tmrMgrHandle, rc = thiz->pStack->tmrMgr.tmrStartCallback(thiz->pStack->tmrMgr.tmrMgrHandle,
thiz->t3Timer, 0, NW_GTPV1U_TMR_TYPE_ONE_SHOT, (void *)timeoutInfo, thiz->t3Timer, 0, NW_GTPV1U_TMR_TYPE_ONE_SHOT, (void *)timeoutInfo,
&thiz->hRspTmr); &thiz->hRspTmr);
return rc; return rc;
} }
/** /**
@@ -160,16 +161,16 @@ nwGtpv1uTrxnStartPeerRspTimer(NwGtpv1uTrxnT *thiz,
static NwGtpv1uRcT static NwGtpv1uRcT
nwGtpv1uTrxnStopPeerRspTimer(NwGtpv1uTrxnT *thiz) nwGtpv1uTrxnStopPeerRspTimer(NwGtpv1uTrxnT *thiz)
{ {
NwGtpv1uRcT rc; NwGtpv1uRcT rc;
NW_ASSERT(thiz->pStack->tmrMgr.tmrStopCallback != NULL); NW_ASSERT(thiz->pStack->tmrMgr.tmrStopCallback != NULL);
rc = thiz->pStack->tmrMgr.tmrStopCallback(thiz->pStack->tmrMgr.tmrMgrHandle, rc = thiz->pStack->tmrMgr.tmrStopCallback(thiz->pStack->tmrMgr.tmrMgrHandle,
thiz->hRspTmr); thiz->hRspTmr);
thiz->hRspTmr = 0; thiz->hRspTmr = 0;
return rc; return rc;
} }
/*--------------------------------------------------------------------------* /*--------------------------------------------------------------------------*
@@ -187,37 +188,38 @@ NwGtpv1uRcT
nwGtpv1uTrxnNew( NW_IN NwGtpv1uStackT *thiz, nwGtpv1uTrxnNew( NW_IN NwGtpv1uStackT *thiz,
NW_OUT NwGtpv1uTrxnT **ppTrxn) NW_OUT NwGtpv1uTrxnT **ppTrxn)
{ {
NwGtpv1uRcT rc = NW_GTPV1U_OK; NwGtpv1uRcT rc = NW_GTPV1U_OK;
NwGtpv1uTrxnT *pTrxn; NwGtpv1uTrxnT *pTrxn;
if(gpGtpv1uTrxnPool) { if(gpGtpv1uTrxnPool) {
pTrxn = gpGtpv1uTrxnPool; pTrxn = gpGtpv1uTrxnPool;
gpGtpv1uTrxnPool = gpGtpv1uTrxnPool->next; gpGtpv1uTrxnPool = gpGtpv1uTrxnPool->next;
} else { } else {
NW_GTPV1U_MALLOC(thiz, sizeof(NwGtpv1uTrxnT), pTrxn, NwGtpv1uTrxnT *); 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;
} }
if (pTrxn) { } else {
pTrxn->maxRetries = 2; rc = NW_GTPV1U_FAILURE;
pTrxn->pStack = thiz; }
pTrxn->t3Timer = 2;
pTrxn->seqNum = thiz->seq;
/* Increment sequence number */ NW_LOG(thiz, NW_LOG_LEVEL_DEBG, "Created transaction 0x%p", pTrxn);
thiz->seq++;
if(thiz->seq == 0x800000) {
thiz->seq = 0;
}
} else { *ppTrxn = pTrxn;
rc = NW_GTPV1U_FAILURE;
}
NW_LOG(thiz, NW_LOG_LEVEL_DEBG, "Created transaction 0x%p", pTrxn); return rc;
*ppTrxn = pTrxn;
return rc;
} }
/** /**
@@ -233,32 +235,32 @@ nwGtpv1uTrxnWithSeqNew( NW_IN NwGtpv1uStackT *thiz,
NW_IN NwU32T seqNum, NW_IN NwU32T seqNum,
NW_OUT NwGtpv1uTrxnT **ppTrxn) NW_OUT NwGtpv1uTrxnT **ppTrxn)
{ {
NwGtpv1uRcT rc = NW_GTPV1U_OK; NwGtpv1uRcT rc = NW_GTPV1U_OK;
NwGtpv1uTrxnT *pTrxn; NwGtpv1uTrxnT *pTrxn;
if(gpGtpv1uTrxnPool) { if(gpGtpv1uTrxnPool) {
pTrxn = gpGtpv1uTrxnPool; pTrxn = gpGtpv1uTrxnPool;
gpGtpv1uTrxnPool = gpGtpv1uTrxnPool->next; gpGtpv1uTrxnPool = gpGtpv1uTrxnPool->next;
} else { } else {
NW_GTPV1U_MALLOC(thiz, sizeof(NwGtpv1uTrxnT), pTrxn, NwGtpv1uTrxnT *); NW_GTPV1U_MALLOC(thiz, sizeof(NwGtpv1uTrxnT), pTrxn, NwGtpv1uTrxnT *);
} }
if (pTrxn) { if (pTrxn) {
pTrxn->maxRetries = 2; pTrxn->maxRetries = 2;
pTrxn->pStack = thiz; pTrxn->pStack = thiz;
pTrxn->t3Timer = 2; pTrxn->t3Timer = 2;
pTrxn->seqNum = seqNum; pTrxn->seqNum = seqNum;
pTrxn->pMsg = NULL; pTrxn->pMsg = NULL;
} else { } else {
rc = NW_GTPV1U_FAILURE; rc = NW_GTPV1U_FAILURE;
} }
NW_LOG(thiz, NW_LOG_LEVEL_DEBG, "Created transaction 0x%p", pTrxn); NW_LOG(thiz, NW_LOG_LEVEL_DEBG, "Created transaction 0x%p", pTrxn);
*ppTrxn = pTrxn; *ppTrxn = pTrxn;
return rc; return rc;
} }
/** /**
@@ -270,30 +272,30 @@ nwGtpv1uTrxnWithSeqNew( NW_IN NwGtpv1uStackT *thiz,
NwGtpv1uRcT NwGtpv1uRcT
nwGtpv1uTrxnDelete( NW_INOUT NwGtpv1uTrxnT **pthiz) nwGtpv1uTrxnDelete( NW_INOUT NwGtpv1uTrxnT **pthiz)
{ {
NwGtpv1uRcT rc = NW_GTPV1U_OK; NwGtpv1uRcT rc = NW_GTPV1U_OK;
NwGtpv1uStackT *pStack; NwGtpv1uStackT *pStack;
NwGtpv1uTrxnT *thiz = *pthiz; NwGtpv1uTrxnT *thiz = *pthiz;
pStack = thiz->pStack; pStack = thiz->pStack;
if(thiz->hRspTmr) { if(thiz->hRspTmr) {
rc = nwGtpv1uTrxnStopPeerRspTimer(thiz); rc = nwGtpv1uTrxnStopPeerRspTimer(thiz);
NW_ASSERT(rc == NW_GTPV1U_OK); NW_ASSERT(rc == NW_GTPV1U_OK);
} }
if(thiz->pMsg) { if(thiz->pMsg) {
rc = nwGtpv1uMsgDelete((NwGtpv1uStackHandleT)pStack, rc = nwGtpv1uMsgDelete((NwGtpv1uStackHandleT)pStack,
(NwGtpv1uMsgHandleT)thiz->pMsg); (NwGtpv1uMsgHandleT)thiz->pMsg);
NW_ASSERT(rc == NW_GTPV1U_OK); NW_ASSERT(rc == NW_GTPV1U_OK);
} }
thiz->next = gpGtpv1uTrxnPool; thiz->next = gpGtpv1uTrxnPool;
gpGtpv1uTrxnPool = thiz; gpGtpv1uTrxnPool = thiz;
NW_LOG(pStack, NW_LOG_LEVEL_DEBG, "Purged transaction 0x%p", thiz); NW_LOG(pStack, NW_LOG_LEVEL_DEBG, "Purged transaction 0x%p", thiz);
*pthiz = NULL; *pthiz = NULL;
return rc; return rc;
} }
@@ -315,72 +317,75 @@ nwGtpv1uTrxnCreateAndSendMsg( NW_IN NwGtpv1uStackT *thiz,
NW_IN NwU32T peerPort, NW_IN NwU32T peerPort,
NW_IN NwGtpv1uMsgT *pMsg) NW_IN NwGtpv1uMsgT *pMsg)
{ {
NwGtpv1uRcT rc; NwGtpv1uRcT rc;
NwU8T *msgHdr; NwU8T *msgHdr;
NW_ASSERT(thiz); NW_ASSERT(thiz);
NW_ASSERT(pMsg); NW_ASSERT(pMsg);
msgHdr = &pMsg->msgBuf[pMsg->msgBufOffset]; msgHdr = &pMsg->msgBuf[pMsg->msgBufOffset];
NW_ASSERT(msgHdr != NULL); NW_ASSERT(msgHdr != NULL);
*(msgHdr++) = (pMsg->version << 5) | *(msgHdr++) = (pMsg->version << 5) |
(pMsg->protocolType << 4) | (pMsg->protocolType << 4) |
(pMsg->extHdrFlag << 2) | (pMsg->extHdrFlag << 2) |
(pMsg->seqNumFlag << 1) | (pMsg->seqNumFlag << 1) |
(pMsg->npduNumFlag); (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++) = (pMsg->msgType);
*((NwU16T *) msgHdr) = htons(pMsg->msgLen);
msgHdr += 2; msgHdr += 2;
*((NwU32T *) msgHdr) = htonl(pMsg->teid); if(pMsg->npduNumFlag) {
msgHdr += 4; *((NwU8T *) msgHdr) = pMsg->npduNumFlag;
} else {
if(pMsg->seqNumFlag | pMsg->extHdrFlag | pMsg->npduNumFlag) { *((NwU8T *) msgHdr) = 0x00;
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); msgHdr++;
rc = thiz->udp.udpDataReqCallback(thiz->udp.hUdp, if(pMsg->extHdrFlag) {
pMsg->msgBuf, *((NwU8T *) msgHdr) = pMsg->extHdrFlag;
pMsg->msgLen, } else {
pMsg->msgBufOffset, *((NwU8T *) msgHdr) = 0x00;
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; msgHdr++;
}
NW_ASSERT(thiz->udp.udpDataReqCallback != NULL);
rc = thiz->udp.udpDataReqCallback(thiz->udp.hUdp,
pMsg->msgBuf,
pMsg->msgLen,
pMsg->msgBufOffset,
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 #endif
@@ -70,16 +70,17 @@ static NwGtpv1uTunnelEndPointT *gpTunnelEndPointPool = NULL;
NwGtpv1uTunnelEndPointT * NwGtpv1uTunnelEndPointT *
nwGtpTunnelEndPointNew(struct NwGtpv1uStack *pStack) nwGtpTunnelEndPointNew(struct NwGtpv1uStack *pStack)
{ {
NwGtpv1uTunnelEndPointT *thiz; NwGtpv1uTunnelEndPointT *thiz;
if(gpTunnelEndPointPool) {
thiz = gpTunnelEndPointPool;
gpTunnelEndPointPool = gpTunnelEndPointPool->next;
} else {
NW_GTPV1U_MALLOC(pStack, sizeof(NwGtpv1uTunnelEndPointT), thiz,
NwGtpv1uTunnelEndPointT *);
}
return thiz; if(gpTunnelEndPointPool) {
thiz = gpTunnelEndPointPool;
gpTunnelEndPointPool = gpTunnelEndPointPool->next;
} else {
NW_GTPV1U_MALLOC(pStack, sizeof(NwGtpv1uTunnelEndPointT), thiz,
NwGtpv1uTunnelEndPointT *);
}
return thiz;
} }
/** /**
@@ -93,9 +94,9 @@ NwGtpv1uRcT
nwGtpTunnelEndPointDestroy(struct NwGtpv1uStack *pStack, nwGtpTunnelEndPointDestroy(struct NwGtpv1uStack *pStack,
NwGtpv1uTunnelEndPointT *thiz) NwGtpv1uTunnelEndPointT *thiz)
{ {
thiz->next = gpTunnelEndPointPool; thiz->next = gpTunnelEndPointPool;
gpTunnelEndPointPool = thiz; gpTunnelEndPointPool = thiz;
return NW_GTPV1U_OK; return NW_GTPV1U_OK;
} }
/** /**
@@ -110,19 +111,19 @@ NwGtpv1uRcT
nwGtpSessionSendMsgApiToUlpEntity(NwGtpv1uTunnelEndPointT *thiz, nwGtpSessionSendMsgApiToUlpEntity(NwGtpv1uTunnelEndPointT *thiz,
NwGtpv1uMsgT *pMsg) NwGtpv1uMsgT *pMsg)
{ {
NwGtpv1uRcT rc = NW_GTPV1U_OK; NwGtpv1uRcT rc = NW_GTPV1U_OK;
NwGtpv1uUlpApiT api; NwGtpv1uUlpApiT api;
api.apiType = NW_GTPV1U_ULP_API_RECV_TPDU; api.apiType = NW_GTPV1U_ULP_API_RECV_TPDU;
api.apiInfo.recvMsgInfo.hUlpSession = thiz->hUlpSession; api.apiInfo.recvMsgInfo.hUlpSession = thiz->hUlpSession;
api.apiInfo.recvMsgInfo.teid = thiz->teid; api.apiInfo.recvMsgInfo.teid = thiz->teid;
api.apiInfo.recvMsgInfo.hMsg = (NwGtpv1uMsgHandleT)pMsg; api.apiInfo.recvMsgInfo.hMsg = (NwGtpv1uMsgHandleT)pMsg;
NW_ASSERT(thiz->pStack->ulp.ulpReqCallback != NULL); NW_ASSERT(thiz->pStack->ulp.ulpReqCallback != NULL);
thiz->pStack->ulp.ulpReqCallback(thiz->pStack->ulp.hUlp, &api); thiz->pStack->ulp.ulpReqCallback(thiz->pStack->ulp.hUlp, &api);
return rc; return rc;
} }
#ifdef __cplusplus #ifdef __cplusplus
@@ -29,9 +29,9 @@
#ifndef __NW_EVT_H__ #ifndef __NW_EVT_H__
#define __NW_EVT_H__ #define __NW_EVT_H__
/** /**
* @file NwEvt.h * @file NwEvt.h
* @brief * @brief
*/ */
#ifdef __WITH_LIBEVENT__ #ifdef __WITH_LIBEVENT__
@@ -60,9 +60,8 @@ typedef struct event NwEventT;
/* HACK : Defining dummy values for compilation!*/ /* HACK : Defining dummy values for compilation!*/
typedef struct typedef struct {
{ int __tbd;
int __tbd;
} NwEventT; } NwEventT;
#define NW_EVT_READ (0) #define NW_EVT_READ (0)
@@ -71,9 +70,9 @@ typedef struct
#define NW_TMR_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_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_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) #define NW_EVENT_ADD(...) do { printf("error: Event library not defined!\n"); exit (0); } while(0)
#endif #endif
@@ -31,13 +31,13 @@ NwU32T g_log_level = NW_LOG_LEVEL_INFO;
NwGtpv1uRcT nwMiniLogMgrInit(NwMiniLogMgrT *thiz, NwU32T logLevel ) NwGtpv1uRcT nwMiniLogMgrInit(NwMiniLogMgrT *thiz, NwU32T logLevel )
{ {
thiz->logLevel = logLevel; thiz->logLevel = logLevel;
return NW_GTPV1U_OK; return NW_GTPV1U_OK;
} }
NwGtpv1uRcT nwMiniLogMgrSetLogLevel(NwMiniLogMgrT *thiz, NwU32T logLevel) NwGtpv1uRcT nwMiniLogMgrSetLogLevel(NwMiniLogMgrT *thiz, NwU32T logLevel)
{ {
thiz->logLevel = logLevel; thiz->logLevel = logLevel;
} }
NwGtpv1uRcT nwMiniLogMgrLogRequest (NwGtpv1uLogMgrHandleT hLogMgr, NwGtpv1uRcT nwMiniLogMgrLogRequest (NwGtpv1uLogMgrHandleT hLogMgr,
@@ -46,12 +46,14 @@ NwGtpv1uRcT nwMiniLogMgrLogRequest (NwGtpv1uLogMgrHandleT hLogMgr,
NwU32T line, NwU32T line,
NwCharT *logStr) NwCharT *logStr)
{ {
NwMiniLogMgrT *thiz = (NwMiniLogMgrT *) hLogMgr; NwMiniLogMgrT *thiz = (NwMiniLogMgrT *) hLogMgr;
if(thiz->logLevel >= logLevel) {
printf("NWGTPv2U-STK %s - %s <%s,%u>\n", gLogLevelStr[logLevel], logStr, if(thiz->logLevel >= logLevel) {
basename(file), line); printf("NWGTPv2U-STK %s - %s <%s,%u>\n", gLogLevelStr[logLevel], logStr,
} basename(file), line);
return NW_GTPV1U_OK; }
return NW_GTPV1U_OK;
} }
#ifdef __cplusplus #ifdef __cplusplus
@@ -6,7 +6,7 @@
* * * *
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
/** /**
* @file hello-world.c * @file hello-world.c
* @brief This file contains example of a minimalistic log manager entity. * @brief This file contains example of a minimalistic log manager entity.
*/ */
@@ -18,7 +18,7 @@
#ifndef NW_ASSERT #ifndef NW_ASSERT
#define NW_ASSERT assert #define NW_ASSERT assert
#endif #endif
#ifndef __NW_MINI_LOG_MGR_H__ #ifndef __NW_MINI_LOG_MGR_H__
#define __NW_MINI_LOG_MGR_H__ #define __NW_MINI_LOG_MGR_H__
@@ -36,8 +36,7 @@ extern NwU32T g_log_level;
} \ } \
} while(0) } while(0)
typedef struct typedef struct {
{
NwU8T logLevel; NwU8T logLevel;
} NwMiniLogMgrT; } NwMiniLogMgrT;
@@ -46,12 +45,12 @@ extern "C" {
#endif #endif
NwGtpv1uRcT nwMiniLogMgrLogRequest (NwGtpv1uLogMgrHandleT logMgrHandle, NwGtpv1uRcT nwMiniLogMgrLogRequest (NwGtpv1uLogMgrHandleT logMgrHandle,
NwU32T logLevel, NwU32T logLevel,
NwCharT* file, NwCharT* file,
NwU32T line, NwU32T line,
NwCharT* logStr); NwCharT* logStr);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
@@ -33,19 +33,19 @@ extern "C" {
static void static void
NW_TMR_CALLBACK(nwMiniTmrMgrHandleTimeout) NW_TMR_CALLBACK(nwMiniTmrMgrHandleTimeout)
{ {
NwGtpv1uRcT rc; NwGtpv1uRcT rc;
NwMiniTmrMgrEntityT *pTmr = (NwMiniTmrMgrEntityT *) arg; NwMiniTmrMgrEntityT *pTmr = (NwMiniTmrMgrEntityT *) arg;
/*--------------------------------------------------------------------------- /*---------------------------------------------------------------------------
* Send Timeout Request to GTPv1u Stack Instance * Send Timeout Request to GTPv1u Stack Instance
*--------------------------------------------------------------------------*/ *--------------------------------------------------------------------------*/
rc = nwGtpv1uProcessTimeout(pTmr->timeoutArg); rc = nwGtpv1uProcessTimeout(pTmr->timeoutArg);
NW_ASSERT( rc == NW_GTPV1U_OK ); NW_ASSERT( rc == NW_GTPV1U_OK );
free(pTmr); free(pTmr);
return; return;
} }
/*--------------------------------------------------------------------------- /*---------------------------------------------------------------------------
@@ -59,41 +59,41 @@ NwGtpv1uRcT nwTimerStart( NwGtpv1uTimerMgrHandleT tmrMgrHandle,
void *timeoutArg, void *timeoutArg,
NwGtpv1uTimerHandleT *hTmr) NwGtpv1uTimerHandleT *hTmr)
{ {
NwGtpv1uRcT rc = NW_GTPV1U_OK; NwGtpv1uRcT rc = NW_GTPV1U_OK;
NwMiniTmrMgrEntityT *pTmr; NwMiniTmrMgrEntityT *pTmr;
struct timeval tv; struct timeval tv;
NW_LOG(NW_LOG_LEVEL_INFO, NW_LOG(NW_LOG_LEVEL_INFO,
"Received start timer request from stack with timer type %u, arg %x, for %u sec and %u usec", "Received start timer request from stack with timer type %u, arg %x, for %u sec and %u usec",
tmrType, timeoutArg, timeoutSec, timeoutUsec); tmrType, timeoutArg, timeoutSec, timeoutUsec);
pTmr = (NwMiniTmrMgrEntityT *) malloc (sizeof(NwMiniTmrMgrEntityT)); pTmr = (NwMiniTmrMgrEntityT *) malloc (sizeof(NwMiniTmrMgrEntityT));
/* set the timevalues*/ /* set the timevalues*/
timerclear(&tv); timerclear(&tv);
tv.tv_sec = timeoutSec; tv.tv_sec = timeoutSec;
tv.tv_usec = timeoutUsec; tv.tv_usec = timeoutUsec;
pTmr->timeoutArg = timeoutArg; pTmr->timeoutArg = timeoutArg;
evtimer_set(&pTmr->ev, nwMiniTmrMgrHandleTimeout, pTmr); evtimer_set(&pTmr->ev, nwMiniTmrMgrHandleTimeout, pTmr);
/*add event*/ /*add event*/
event_add(&(pTmr->ev), &tv); event_add(&(pTmr->ev), &tv);
*hTmr = (NwGtpv1uTimerHandleT)pTmr; *hTmr = (NwGtpv1uTimerHandleT)pTmr;
return rc; return rc;
} }
NwGtpv1uRcT nwTimerStop( NwGtpv1uTimerMgrHandleT tmrMgrHandle, NwGtpv1uRcT nwTimerStop( NwGtpv1uTimerMgrHandleT tmrMgrHandle,
NwGtpv1uTimerHandleT hTmr) NwGtpv1uTimerHandleT hTmr)
{ {
NW_LOG(NW_LOG_LEVEL_INFO, NW_LOG(NW_LOG_LEVEL_INFO,
"Received stop timer request from stack for timer handle %u", hTmr); "Received stop timer request from stack for timer handle %u", hTmr);
evtimer_del(&(((NwMiniTmrMgrEntityT *)hTmr)->ev)); evtimer_del(&(((NwMiniTmrMgrEntityT *)hTmr)->ev));
free((void *)hTmr); free((void *)hTmr);
return NW_GTPV1U_OK; return NW_GTPV1U_OK;
} }
#ifdef __cplusplus #ifdef __cplusplus
@@ -7,7 +7,7 @@
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
/** /**
* @file NwMiniTmrMgrEntity.c * @file NwMiniTmrMgrEntity.c
* @brief This file ontains example of a minimalistic timer manager entity. * @brief This file ontains example of a minimalistic timer manager entity.
*/ */
@@ -19,13 +19,12 @@
#ifndef NW_ASSERT #ifndef NW_ASSERT
#define NW_ASSERT assert #define NW_ASSERT assert
#endif #endif
#ifndef __NW_MINI_TMR_MGR_H__ #ifndef __NW_MINI_TMR_MGR_H__
#define __NW_MINI_TMR_MGR_H__ #define __NW_MINI_TMR_MGR_H__
typedef struct typedef struct {
{
NwEventT ev; NwEventT ev;
void* timeoutArg; void* timeoutArg;
} NwMiniTmrMgrEntityT; } NwMiniTmrMgrEntityT;
@@ -36,15 +35,15 @@ extern "C" {
#endif #endif
NwGtpv1uRcT nwTimerStart( NwGtpv1uTimerMgrHandleT tmrMgrHandle, NwGtpv1uRcT nwTimerStart( NwGtpv1uTimerMgrHandleT tmrMgrHandle,
NwU32T timeoutSec, NwU32T timeoutSec,
NwU32T timeoutUsec, NwU32T timeoutUsec,
NwU32T tmrType, NwU32T tmrType,
void* timeoutArg, void* timeoutArg,
NwGtpv1uTimerHandleT* hTmr); NwGtpv1uTimerHandleT* hTmr);
NwGtpv1uRcT nwTimerStop( NwGtpv1uTimerMgrHandleT tmrMgrHandle, NwGtpv1uRcT nwTimerStop( NwGtpv1uTimerMgrHandleT tmrMgrHandle,
NwGtpv1uTimerHandleT hTmr); NwGtpv1uTimerHandleT hTmr);
#ifdef __cplusplus #ifdef __cplusplus
@@ -43,25 +43,26 @@ extern "C" {
static static
void NW_TMR_CALLBACK(nwUdpDataIndicationCallbackData) void NW_TMR_CALLBACK(nwUdpDataIndicationCallbackData)
{ {
NwGtpv1uRcT rc; NwGtpv1uRcT rc;
NwU8T udpBuf[MAX_UDP_PAYLOAD_LEN]; NwU8T udpBuf[MAX_UDP_PAYLOAD_LEN];
NwS32T bytesRead; NwS32T bytesRead;
NwU32T peerLen; NwU32T peerLen;
struct sockaddr_in peer; struct sockaddr_in peer;
NwMiniUdpEntityT *thiz = (NwMiniUdpEntityT *) arg; NwMiniUdpEntityT *thiz = (NwMiniUdpEntityT *) arg;
peerLen = sizeof(peer); peerLen = sizeof(peer);
bytesRead = recvfrom(thiz->hSocket, udpBuf, MAX_UDP_PAYLOAD_LEN , 0, bytesRead = recvfrom(thiz->hSocket, udpBuf, MAX_UDP_PAYLOAD_LEN , 0,
(struct sockaddr *) &peer,(socklen_t *) &peerLen); (struct sockaddr *) &peer,(socklen_t *) &peerLen);
if(bytesRead) {
NW_LOG(NW_LOG_LEVEL_DEBG, "Received UDP message of length %u from %X:%u", if(bytesRead) {
bytesRead, ntohl(peer.sin_addr.s_addr), ntohs(peer.sin_port)); NW_LOG(NW_LOG_LEVEL_DEBG, "Received UDP message of length %u from %X:%u",
rc = nwGtpv1uProcessUdpReq(thiz->hGtpv1uStack, udpBuf, bytesRead, bytesRead, ntohl(peer.sin_addr.s_addr), ntohs(peer.sin_port));
peer.sin_port, peer.sin_addr.s_addr); rc = nwGtpv1uProcessUdpReq(thiz->hGtpv1uStack, udpBuf, bytesRead,
} else { peer.sin_port, peer.sin_addr.s_addr);
NW_LOG(NW_LOG_LEVEL_ERRO, "%s", strerror(errno)); } else {
} NW_LOG(NW_LOG_LEVEL_ERRO, "%s", strerror(errno));
}
} }
@@ -72,39 +73,39 @@ void NW_TMR_CALLBACK(nwUdpDataIndicationCallbackData)
NwGtpv1uRcT nwMiniUdpInit(NwMiniUdpEntityT *thiz, NwGtpv1uRcT nwMiniUdpInit(NwMiniUdpEntityT *thiz,
NwGtpv1uStackHandleT hGtpv1uStack, NwU8T *ipAddr) NwGtpv1uStackHandleT hGtpv1uStack, NwU8T *ipAddr)
{ {
int sd; int sd;
struct sockaddr_in addr; struct sockaddr_in addr;
sd = socket(AF_INET, SOCK_DGRAM, 0); sd = socket(AF_INET, SOCK_DGRAM, 0);
if (sd < 0) { if (sd < 0) {
NW_LOG(NW_LOG_LEVEL_ERRO, "%s", strerror(errno)); NW_LOG(NW_LOG_LEVEL_ERRO, "%s", strerror(errno));
NW_ASSERT(0); NW_ASSERT(0);
} }
addr.sin_family = AF_INET; addr.sin_family = AF_INET;
addr.sin_port = htons(2152); addr.sin_port = htons(2152);
addr.sin_addr.s_addr = inet_addr(ipAddr); addr.sin_addr.s_addr = inet_addr(ipAddr);
memset(addr.sin_zero, '\0', sizeof (addr.sin_zero)); memset(addr.sin_zero, '\0', sizeof (addr.sin_zero));
if(bind(sd, (struct sockaddr *)&addr, sizeof(addr)) < 0) { if(bind(sd, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
NW_LOG(NW_LOG_LEVEL_ERRO, "%s", strerror(errno)); NW_LOG(NW_LOG_LEVEL_ERRO, "%s", strerror(errno));
NW_ASSERT(0); NW_ASSERT(0);
} }
event_set(&(thiz->ev), sd, EV_READ|EV_PERSIST, nwUdpDataIndicationCallbackData, event_set(&(thiz->ev), sd, EV_READ|EV_PERSIST, nwUdpDataIndicationCallbackData,
thiz); thiz);
event_add(&(thiz->ev), NULL); event_add(&(thiz->ev), NULL);
thiz->hSocket = sd; thiz->hSocket = sd;
thiz->hGtpv1uStack = hGtpv1uStack; thiz->hGtpv1uStack = hGtpv1uStack;
return NW_GTPV1U_OK; return NW_GTPV1U_OK;
} }
NwGtpv1uRcT nwMiniUdpDestroy(NwMiniUdpEntityT *thiz) NwGtpv1uRcT nwMiniUdpDestroy(NwMiniUdpEntityT *thiz)
{ {
close(thiz->hSocket); close(thiz->hSocket);
} }
NwGtpv1uRcT nwMiniUdpDataReq(NwGtpv1uUdpHandleT udpHandle, NwGtpv1uRcT nwMiniUdpDataReq(NwGtpv1uUdpHandleT udpHandle,
@@ -113,38 +114,39 @@ NwGtpv1uRcT nwMiniUdpDataReq(NwGtpv1uUdpHandleT udpHandle,
NwU32T peerIpAddr, NwU32T peerIpAddr,
NwU32T peerPort) NwU32T peerPort)
{ {
struct sockaddr_in peerAddr; struct sockaddr_in peerAddr;
NwS32T bytesSent; NwS32T bytesSent;
NwMiniUdpEntityT *thiz = (NwMiniUdpEntityT *) udpHandle; NwMiniUdpEntityT *thiz = (NwMiniUdpEntityT *) udpHandle;
peerAddr.sin_family = AF_INET; peerAddr.sin_family = AF_INET;
peerAddr.sin_port = htons(peerPort); peerAddr.sin_port = htons(peerPort);
peerAddr.sin_addr.s_addr = (peerIpAddr); peerAddr.sin_addr.s_addr = (peerIpAddr);
memset(peerAddr.sin_zero, '\0', sizeof (peerAddr.sin_zero)); memset(peerAddr.sin_zero, '\0', sizeof (peerAddr.sin_zero));
NW_LOG(NW_LOG_LEVEL_DEBG, NW_LOG(NW_LOG_LEVEL_DEBG,
"Sending %u bytes on handle 0x%x to peer %u.%u.%u.%u:%u", dataSize, udpHandle, "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 & 0x000000ff),
(peerIpAddr & 0x0000ff00) >> 8, (peerIpAddr & 0x0000ff00) >> 8,
(peerIpAddr & 0x00ff0000) >> 16, (peerIpAddr & 0x00ff0000) >> 16,
(peerIpAddr & 0xff000000) >> 24, (peerIpAddr & 0xff000000) >> 24);
peerPort);
bytesSent = sendto (thiz->hSocket, dataBuf, dataSize, 0, }
(struct sockaddr *) &peerAddr, sizeof(peerAddr));
if(bytesSent < 0) { return NW_GTPV1U_OK;
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;
} }
@@ -7,7 +7,7 @@
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
/** /**
* @file NwMiniUdpEntity.h * @file NwMiniUdpEntity.h
* @brief This file contains example of a minimalistic ULP entity. * @brief This file contains example of a minimalistic ULP entity.
*/ */
@@ -19,13 +19,12 @@
#ifndef NW_ASSERT #ifndef NW_ASSERT
#define NW_ASSERT assert #define NW_ASSERT assert
#endif #endif
#ifndef __NW_MINI_UDP_ENTITY_H__ #ifndef __NW_MINI_UDP_ENTITY_H__
#define __NW_MINI_UDP_ENTITY_H__ #define __NW_MINI_UDP_ENTITY_H__
typedef struct typedef struct {
{
NwU32T hSocket; NwU32T hSocket;
NwEventT ev; NwEventT ev;
NwGtpv1uStackHandleT hGtpv1uStack; NwGtpv1uStackHandleT hGtpv1uStack;
@@ -40,10 +39,10 @@ NwGtpv1uRcT nwMiniUdpInit(NwMiniUdpEntityT* thiz, NwGtpv1uStackHandleT hGtpv1uSt
NwGtpv1uRcT nwMiniUdpDestroy(NwMiniUdpEntityT* thiz); NwGtpv1uRcT nwMiniUdpDestroy(NwMiniUdpEntityT* thiz);
NwGtpv1uRcT nwMiniUdpDataReq(NwGtpv1uUdpHandleT udpHandle, NwGtpv1uRcT nwMiniUdpDataReq(NwGtpv1uUdpHandleT udpHandle,
NwU8T* dataBuf, NwU8T* dataBuf,
NwU32T dataSize, NwU32T dataSize,
NwU32T peerAddr, NwU32T peerAddr,
NwU32T peerPort); NwU32T peerPort);
#ifdef __cplusplus #ifdef __cplusplus
} }
@@ -38,66 +38,67 @@ extern "C" {
NwGtpv1uRcT NwGtpv1uRcT
nwMiniUlpSendEchoRequestToPeer(NwMiniUlpEntityT *thiz, NwU32T peerIp) nwMiniUlpSendEchoRequestToPeer(NwMiniUlpEntityT *thiz, NwU32T peerIp)
{ {
NwGtpv1uRcT rc; NwGtpv1uRcT rc;
NwGtpv1uUlpApiT ulpReq; NwGtpv1uUlpApiT ulpReq;
/* /*
* Send Message Request to Gtpv1u Stack Instance * Send Message Request to Gtpv1u Stack Instance
*/ */
ulpReq.apiType = NW_GTPV1U_ULP_API_INITIAL_REQ; ulpReq.apiType = NW_GTPV1U_ULP_API_INITIAL_REQ;
ulpReq.apiInfo.initialReqInfo.hUlpTrxn = (NwGtpv1uUlpTrxnHandleT)thiz; ulpReq.apiInfo.initialReqInfo.hUlpTrxn = (NwGtpv1uUlpTrxnHandleT)thiz;
ulpReq.apiInfo.initialReqInfo.teid = 0x00; ulpReq.apiInfo.initialReqInfo.teid = 0x00;
ulpReq.apiInfo.initialReqInfo.peerIp = (peerIp); ulpReq.apiInfo.initialReqInfo.peerIp = (peerIp);
ulpReq.apiInfo.initialReqInfo.peerPort = 2152; ulpReq.apiInfo.initialReqInfo.peerPort = 2152;
/* Send Echo Request*/ /* Send Echo Request*/
rc = nwGtpv1uMsgNew( thiz->hGtpv1uStack, rc = nwGtpv1uMsgNew( thiz->hGtpv1uStack,
NW_TRUE, /* SeqNum flag */ NW_TRUE, /* SeqNum flag */
NW_FALSE, NW_FALSE,
NW_FALSE, NW_FALSE,
NW_GTP_ECHO_REQ, /* Msg Type */ NW_GTP_ECHO_REQ, /* Msg Type */
0x00000000UL, /* TEID */ 0x00000000UL, /* TEID */
0x5678, /* Seq Number */ 0x5678, /* Seq Number */
0, 0,
0, 0,
(&ulpReq.hMsg)); (&ulpReq.hMsg));
NW_ASSERT( rc == NW_GTPV1U_OK ); NW_ASSERT( rc == NW_GTPV1U_OK );
rc = nwGtpv1uMsgAddIeTV1((ulpReq.hMsg), NW_GTPV1U_IE_RECOVERY, rc = nwGtpv1uMsgAddIeTV1((ulpReq.hMsg), NW_GTPV1U_IE_RECOVERY,
thiz->restartCounter); thiz->restartCounter);
NW_ASSERT( rc == NW_GTPV1U_OK ); NW_ASSERT( rc == NW_GTPV1U_OK );
rc = nwGtpv1uProcessUlpReq(thiz->hGtpv1uStack, &ulpReq); rc = nwGtpv1uProcessUlpReq(thiz->hGtpv1uStack, &ulpReq);
NW_ASSERT( rc == NW_GTPV1U_OK ); NW_ASSERT( rc == NW_GTPV1U_OK );
return NW_GTPV1U_OK; return NW_GTPV1U_OK;
} }
static static
void NW_EVT_CALLBACK(nwMiniUlpDataIndicationCallbackData) void NW_EVT_CALLBACK(nwMiniUlpDataIndicationCallbackData)
{ {
NwMiniUlpEntityT *thiz = (NwMiniUlpEntityT *) arg; NwMiniUlpEntityT *thiz = (NwMiniUlpEntityT *) arg;
NwGtpv1uRcT rc; NwGtpv1uRcT rc;
NwU8T udpBuf[MAX_UDP_PAYLOAD_LEN]; NwU8T udpBuf[MAX_UDP_PAYLOAD_LEN];
NwS32T bytesRead; NwS32T bytesRead;
NwU32T peerLen; NwU32T peerLen;
struct sockaddr_in peer; struct sockaddr_in peer;
peerLen = sizeof(peer); peerLen = sizeof(peer);
bytesRead = recvfrom(thiz->hSocket, udpBuf, MAX_UDP_PAYLOAD_LEN , 0, bytesRead = recvfrom(thiz->hSocket, udpBuf, MAX_UDP_PAYLOAD_LEN , 0,
(struct sockaddr *) &peer,(socklen_t *) &peerLen); (struct sockaddr *) &peer,(socklen_t *) &peerLen);
if(bytesRead) {
NW_LOG(NW_LOG_LEVEL_DEBG, "Received UDP message of length %u from %X:%u", if(bytesRead) {
bytesRead, ntohl(peer.sin_addr.s_addr), ntohs(peer.sin_port)); NW_LOG(NW_LOG_LEVEL_DEBG, "Received UDP message of length %u from %X:%u",
rc = nwMiniUlpTpduSend(thiz, udpBuf, bytesRead, thiz->localPort[fd]); bytesRead, ntohl(peer.sin_addr.s_addr), ntohs(peer.sin_port));
} else { rc = nwMiniUlpTpduSend(thiz, udpBuf, bytesRead, thiz->localPort[fd]);
NW_LOG(NW_LOG_LEVEL_ERRO, "%s", strerror(errno)); } else {
} NW_LOG(NW_LOG_LEVEL_ERRO, "%s", strerror(errno));
}
} }
/*--------------------------------------------------------------------------- /*---------------------------------------------------------------------------
@@ -107,108 +108,108 @@ void NW_EVT_CALLBACK(nwMiniUlpDataIndicationCallbackData)
NwGtpv1uRcT NwGtpv1uRcT
nwMiniUlpInit(NwMiniUlpEntityT *thiz, NwGtpv1uStackHandleT hGtpv1uStack) nwMiniUlpInit(NwMiniUlpEntityT *thiz, NwGtpv1uStackHandleT hGtpv1uStack)
{ {
NwGtpv1uRcT rc; NwGtpv1uRcT rc;
thiz->hGtpv1uStack = hGtpv1uStack; thiz->hGtpv1uStack = hGtpv1uStack;
return NW_GTPV1U_OK; return NW_GTPV1U_OK;
} }
NwGtpv1uRcT NwGtpv1uRcT
nwMiniUlpDestroy(NwMiniUlpEntityT *thiz) nwMiniUlpDestroy(NwMiniUlpEntityT *thiz)
{ {
NW_ASSERT(thiz); NW_ASSERT(thiz);
memset(thiz, 0, sizeof(NwMiniUlpEntityT)); memset(thiz, 0, sizeof(NwMiniUlpEntityT));
return NW_GTPV1U_OK; return NW_GTPV1U_OK;
} }
NwGtpv1uRcT NwGtpv1uRcT
nwMiniUlpCreateConn(NwMiniUlpEntityT *thiz, char *localIpStr, NwU16T localport, nwMiniUlpCreateConn(NwMiniUlpEntityT *thiz, char *localIpStr, NwU16T localport,
char *peerIpStr) char *peerIpStr)
{ {
NwGtpv1uRcT rc; NwGtpv1uRcT rc;
int sd; int sd;
struct sockaddr_in addr; struct sockaddr_in addr;
NwGtpv1uUlpApiT ulpReq; NwGtpv1uUlpApiT ulpReq;
strcpy(thiz->peerIpStr, peerIpStr); strcpy(thiz->peerIpStr, peerIpStr);
/* /*
* Create local tunnel endpoint * Create local tunnel endpoint
*/ */
NW_LOG(NW_LOG_LEVEL_NOTI, "Creating tunnel endpoint with teid %d", localport); NW_LOG(NW_LOG_LEVEL_NOTI, "Creating tunnel endpoint with teid %d", localport);
ulpReq.apiType = ulpReq.apiType =
NW_GTPV1U_ULP_API_CREATE_TUNNEL_ENDPOINT; NW_GTPV1U_ULP_API_CREATE_TUNNEL_ENDPOINT;
ulpReq.apiInfo.createTunnelEndPointInfo.teid = localport; ulpReq.apiInfo.createTunnelEndPointInfo.teid = localport;
ulpReq.apiInfo.createTunnelEndPointInfo.hUlpSession = ulpReq.apiInfo.createTunnelEndPointInfo.hUlpSession =
(NwGtpv1uUlpSessionHandleT)thiz; (NwGtpv1uUlpSessionHandleT)thiz;
rc = nwGtpv1uProcessUlpReq(thiz->hGtpv1uStack, &ulpReq); rc = nwGtpv1uProcessUlpReq(thiz->hGtpv1uStack, &ulpReq);
NW_ASSERT( rc == NW_GTPV1U_OK ); NW_ASSERT( rc == NW_GTPV1U_OK );
thiz->hGtpv1uConn = ulpReq.apiInfo.createTunnelEndPointInfo.hStackSession; thiz->hGtpv1uConn = ulpReq.apiInfo.createTunnelEndPointInfo.hStackSession;
/* /*
* Create local udp listening endpoint * Create local udp listening endpoint
*/ */
sd = socket(AF_INET, SOCK_DGRAM, 0); sd = socket(AF_INET, SOCK_DGRAM, 0);
if (sd < 0) { if (sd < 0) {
NW_LOG(NW_LOG_LEVEL_ERRO, "%s", strerror(errno)); NW_LOG(NW_LOG_LEVEL_ERRO, "%s", strerror(errno));
NW_ASSERT(0); NW_ASSERT(0);
} }
addr.sin_family = AF_INET; addr.sin_family = AF_INET;
addr.sin_port = htons(localport); addr.sin_port = htons(localport);
addr.sin_addr.s_addr = inet_addr(localIpStr); addr.sin_addr.s_addr = inet_addr(localIpStr);
memset(addr.sin_zero, '\0', sizeof (addr.sin_zero)); memset(addr.sin_zero, '\0', sizeof (addr.sin_zero));
if(bind(sd, (struct sockaddr *)&addr, sizeof(addr)) < 0) { if(bind(sd, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
NW_LOG(NW_LOG_LEVEL_ERRO, "%s", strerror(errno)); NW_LOG(NW_LOG_LEVEL_ERRO, "%s", strerror(errno));
NW_ASSERT(0); NW_ASSERT(0);
} }
event_set(&(thiz->ev[sd]), sd, EV_READ|EV_PERSIST, event_set(&(thiz->ev[sd]), sd, EV_READ|EV_PERSIST,
nwMiniUlpDataIndicationCallbackData, thiz); nwMiniUlpDataIndicationCallbackData, thiz);
event_add(&(thiz->ev[sd]), NULL); event_add(&(thiz->ev[sd]), NULL);
thiz->localPort[sd] = localport; thiz->localPort[sd] = localport;
/* /*
* Create local udp for sendign data * Create local udp for sendign data
*/ */
sd = socket(AF_INET, SOCK_DGRAM, 0); sd = socket(AF_INET, SOCK_DGRAM, 0);
if (sd < 0) { if (sd < 0) {
NW_LOG(NW_LOG_LEVEL_ERRO, "%s", strerror(errno)); NW_LOG(NW_LOG_LEVEL_ERRO, "%s", strerror(errno));
NW_ASSERT(0); NW_ASSERT(0);
} }
thiz->hSocket = sd; thiz->hSocket = sd;
return NW_GTPV1U_OK; return NW_GTPV1U_OK;
} }
NwGtpv1uRcT NwGtpv1uRcT
nwMiniUlpDestroyConn(NwMiniUlpEntityT *thiz) nwMiniUlpDestroyConn(NwMiniUlpEntityT *thiz)
{ {
NwGtpv1uRcT rc; NwGtpv1uRcT rc;
NwGtpv1uUlpApiT ulpReq; NwGtpv1uUlpApiT ulpReq;
/*--------------------------------------------------------------------------- /*---------------------------------------------------------------------------
* Send Destroy Session Request to GTPv1u Stack Instance * Send Destroy Session Request to GTPv1u Stack Instance
*--------------------------------------------------------------------------*/ *--------------------------------------------------------------------------*/
ulpReq.apiType = NW_GTPV1U_ULP_API_DESTROY_TUNNEL_ENDPOINT; ulpReq.apiType = NW_GTPV1U_ULP_API_DESTROY_TUNNEL_ENDPOINT;
ulpReq.apiInfo.destroyTunnelEndPointInfo.hStackSessionHandle = thiz->hGtpv1uConn; ulpReq.apiInfo.destroyTunnelEndPointInfo.hStackSessionHandle = thiz->hGtpv1uConn;
rc = nwGtpv1uProcessUlpReq(thiz->hGtpv1uStack, &ulpReq); rc = nwGtpv1uProcessUlpReq(thiz->hGtpv1uStack, &ulpReq);
NW_ASSERT( rc == NW_GTPV1U_OK ); NW_ASSERT( rc == NW_GTPV1U_OK );
thiz->hGtpv1uConn = 0; thiz->hGtpv1uConn = 0;
return NW_GTPV1U_OK; return NW_GTPV1U_OK;
} }
@@ -216,88 +217,90 @@ NwGtpv1uRcT
nwMiniUlpTpduSend(NwMiniUlpEntityT *thiz, NwU8T *tpduBuf, NwU32T tpduLen , nwMiniUlpTpduSend(NwMiniUlpEntityT *thiz, NwU8T *tpduBuf, NwU32T tpduLen ,
NwU16T fromPort) NwU16T fromPort)
{ {
NwGtpv1uRcT rc; NwGtpv1uRcT rc;
NwGtpv1uUlpApiT ulpReq; NwGtpv1uUlpApiT ulpReq;
/* /*
* Send Message Request to GTPv1u Stack Instance * Send Message Request to GTPv1u Stack Instance
*/ */
ulpReq.apiType = NW_GTPV1U_ULP_API_SEND_TPDU; ulpReq.apiType = NW_GTPV1U_ULP_API_SEND_TPDU;
ulpReq.apiInfo.sendtoInfo.teid = fromPort; ulpReq.apiInfo.sendtoInfo.teid = fromPort;
ulpReq.apiInfo.sendtoInfo.ipAddr = inet_addr(thiz->peerIpStr); ulpReq.apiInfo.sendtoInfo.ipAddr = inet_addr(thiz->peerIpStr);
rc = nwGtpv1uGpduMsgNew( thiz->hGtpv1uStack, rc = nwGtpv1uGpduMsgNew( thiz->hGtpv1uStack,
fromPort, fromPort,
NW_FALSE, NW_FALSE,
thiz->seqNum++, thiz->seqNum++,
tpduBuf, tpduBuf,
tpduLen, tpduLen,
&(ulpReq.apiInfo.sendtoInfo.hMsg)); &(ulpReq.apiInfo.sendtoInfo.hMsg));
NW_ASSERT( rc == NW_GTPV1U_OK ); NW_ASSERT( rc == NW_GTPV1U_OK );
rc = nwGtpv1uProcessUlpReq(thiz->hGtpv1uStack, &ulpReq); rc = nwGtpv1uProcessUlpReq(thiz->hGtpv1uStack, &ulpReq);
NW_ASSERT( rc == NW_GTPV1U_OK ); NW_ASSERT( rc == NW_GTPV1U_OK );
rc = nwGtpv1uMsgDelete(thiz->hGtpv1uStack, (ulpReq.apiInfo.sendtoInfo.hMsg)); rc = nwGtpv1uMsgDelete(thiz->hGtpv1uStack, (ulpReq.apiInfo.sendtoInfo.hMsg));
NW_ASSERT( rc == NW_GTPV1U_OK ); NW_ASSERT( rc == NW_GTPV1U_OK );
return NW_GTPV1U_OK; return NW_GTPV1U_OK;
} }
NwGtpv1uRcT NwGtpv1uRcT
nwMiniUlpProcessStackReqCallback (NwGtpv1uUlpHandleT hUlp, nwMiniUlpProcessStackReqCallback (NwGtpv1uUlpHandleT hUlp,
NwGtpv1uUlpApiT *pUlpApi) NwGtpv1uUlpApiT *pUlpApi)
{ {
NwMiniUlpEntityT *thiz; NwMiniUlpEntityT *thiz;
NW_ASSERT(pUlpApi != NULL); NW_ASSERT(pUlpApi != NULL);
thiz = (NwMiniUlpEntityT *) hUlp; thiz = (NwMiniUlpEntityT *) hUlp;
switch(pUlpApi->apiType) { switch(pUlpApi->apiType) {
case NW_GTPV1U_ULP_API_RECV_TPDU: { case NW_GTPV1U_ULP_API_RECV_TPDU: {
struct sockaddr_in peerAddr; struct sockaddr_in peerAddr;
NwS32T bytesSent; NwS32T bytesSent;
NwU8T dataBuf[4096]; NwU8T dataBuf[4096];
NwU32T dataSize; NwU32T dataSize;
NwU32T peerIpAddr = (inet_addr(thiz->peerIpStr)); NwU32T peerIpAddr = (inet_addr(thiz->peerIpStr));
NW_ASSERT( NW_GTPV1U_OK == nwGtpv1uMsgGetTpdu(pUlpApi->apiInfo.recvMsgInfo.hMsg, NW_ASSERT( NW_GTPV1U_OK == nwGtpv1uMsgGetTpdu(pUlpApi->apiInfo.recvMsgInfo.hMsg,
dataBuf, &dataSize) ); dataBuf, &dataSize) );
NW_LOG(NW_LOG_LEVEL_DEBG, "Received TPDU from gtpv1u stack %u!", NW_LOG(NW_LOG_LEVEL_DEBG, "Received TPDU from gtpv1u stack %u!",
pUlpApi->apiInfo.recvMsgInfo.teid); pUlpApi->apiInfo.recvMsgInfo.teid);
peerAddr.sin_family = AF_INET; peerAddr.sin_family = AF_INET;
peerAddr.sin_port = htons(pUlpApi->apiInfo.recvMsgInfo.teid); peerAddr.sin_port = htons(pUlpApi->apiInfo.recvMsgInfo.teid);
peerAddr.sin_addr.s_addr = (peerIpAddr); peerAddr.sin_addr.s_addr = (peerIpAddr);
memset(peerAddr.sin_zero, '\0', sizeof (peerAddr.sin_zero)); memset(peerAddr.sin_zero, '\0', sizeof (peerAddr.sin_zero));
bytesSent = sendto (thiz->hSocket, dataBuf, dataSize, 0, bytesSent = sendto (thiz->hSocket, dataBuf, dataSize, 0,
(struct sockaddr *) &peerAddr, sizeof(peerAddr)); (struct sockaddr *) &peerAddr, sizeof(peerAddr));
if(bytesSent < 0) { if(bytesSent < 0) {
NW_LOG(NW_LOG_LEVEL_ERRO, "%s", strerror(errno)); NW_LOG(NW_LOG_LEVEL_ERRO, "%s", strerror(errno));
NW_ASSERT(0); NW_ASSERT(0);
} else { } else {
NW_LOG(NW_LOG_LEVEL_DEBG, "Sent %u bytes to peer %u.%u.%u.%u", dataSize, NW_LOG(NW_LOG_LEVEL_DEBG, "Sent %u bytes to peer %u.%u.%u.%u", dataSize,
(peerIpAddr & 0x000000ff), (peerIpAddr & 0x000000ff),
(peerIpAddr & 0x0000ff00) >> 8, (peerIpAddr & 0x0000ff00) >> 8,
(peerIpAddr & 0x00ff0000) >> 16, (peerIpAddr & 0x00ff0000) >> 16,
(peerIpAddr & 0xff000000) >> 24); (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;
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 #ifdef __cplusplus
@@ -6,7 +6,7 @@
* * * *
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
/** /**
* @file NwMiniUlpEntity.h * @file NwMiniUlpEntity.h
* @brief This file contains example of a minimalistic ULP entity. * @brief This file contains example of a minimalistic ULP entity.
*/ */
@@ -16,11 +16,10 @@
#include "NwEvt.h" #include "NwEvt.h"
#include "NwLog.h" #include "NwLog.h"
#ifndef __NW_MINI_ULP_H__ #ifndef __NW_MINI_ULP_H__
#define __NW_MINI_ULP_H__ #define __NW_MINI_ULP_H__
typedef struct typedef struct {
{
int hSocket; int hSocket;
NwU16T seqNum; NwU16T seqNum;
NwU8T restartCounter; NwU8T restartCounter;
@@ -54,9 +53,9 @@ nwMiniUlpSendMsg(NwMiniUlpEntityT* thiz);
NwGtpv1uRcT NwGtpv1uRcT
nwMiniUlpTpduSend(NwMiniUlpEntityT* thiz, NwU8T* tpduBuf, NwU32T tpduLen , NwU16T fromPort); nwMiniUlpTpduSend(NwMiniUlpEntityT* thiz, NwU8T* tpduBuf, NwU32T tpduLen , NwU16T fromPort);
NwGtpv1uRcT NwGtpv1uRcT
nwMiniUlpProcessStackReqCallback (NwGtpv1uUlpHandleT hUlp, nwMiniUlpProcessStackReqCallback (NwGtpv1uUlpHandleT hUlp,
NwGtpv1uUlpApiT *pUlpApi); NwGtpv1uUlpApiT *pUlpApi);
#ifdef __cplusplus #ifdef __cplusplus
} }
@@ -35,173 +35,173 @@
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
NwGtpv1uRcT rc; NwGtpv1uRcT rc;
char *logLevelStr; char *logLevelStr;
NwU32T logLevel; NwU32T logLevel;
NwU32T num_of_connections; NwU32T num_of_connections;
NwGtpv1uStackHandleT hGtpv1uStack = 0; NwGtpv1uStackHandleT hGtpv1uStack = 0;
NwMiniUlpEntityT ulpObj; NwMiniUlpEntityT ulpObj;
NwMiniUdpEntityT udpObj; NwMiniUdpEntityT udpObj;
NwMiniLogMgrT logObj; NwMiniLogMgrT logObj;
NwGtpv1uUlpEntityT ulp; NwGtpv1uUlpEntityT ulp;
NwGtpv1uUdpEntityT udp; NwGtpv1uUdpEntityT udp;
NwGtpv1uTimerMgrEntityT tmrMgr; NwGtpv1uTimerMgrEntityT tmrMgr;
NwGtpv1uLogMgrEntityT logMgr; NwGtpv1uLogMgrEntityT logMgr;
if(argc != 4) { if(argc != 4) {
printf("Usage: %s <num-of-connections> <local-ip> <peer-ip>\n", argv[0]); printf("Usage: %s <num-of-connections> <local-ip> <peer-ip>\n", argv[0]);
exit(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 );
logLevelStr = getenv ("NW_LOG_LEVEL"); /*---------------------------------------------------------------------------
* Set up Udp Entity
*--------------------------------------------------------------------------*/
if(logLevelStr == NULL) { rc = nwMiniUdpInit(&udpObj, hGtpv1uStack, (argv[2]));
logLevel = NW_LOG_LEVEL_INFO; NW_ASSERT( rc == NW_GTPV1U_OK );
} 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;
}
}
/*--------------------------------------------------------------------------- udp.hUdp = (NwGtpv1uUdpHandleT) &udpObj;
* Initialize event library udp.udpDataReqCallback = nwMiniUdpDataReq;
*--------------------------------------------------------------------------*/
NW_EVT_INIT(); rc = nwGtpv1uSetUdpEntity(hGtpv1uStack, &udp);
NW_ASSERT( rc == NW_GTPV1U_OK );
/*--------------------------------------------------------------------------- /*---------------------------------------------------------------------------
* Initialize Log Manager * Set up Log Entity
*--------------------------------------------------------------------------*/ *--------------------------------------------------------------------------*/
nwMiniLogMgrInit(&logObj, logLevel); tmrMgr.tmrMgrHandle = 0;
tmrMgr.tmrStartCallback = nwTimerStart;
tmrMgr.tmrStopCallback = nwTimerStop;
/*--------------------------------------------------------------------------- rc = nwGtpv1uSetTimerMgrEntity(hGtpv1uStack, &tmrMgr);
* Create GTPv1u Stack Instance NW_ASSERT( rc == NW_GTPV1U_OK );
*--------------------------------------------------------------------------*/
rc = nwGtpv1uInitialize(&hGtpv1uStack); /*---------------------------------------------------------------------------
* Set up Log Entity
*--------------------------------------------------------------------------*/
if(rc != NW_GTPV1U_OK) { logMgr.logMgrHandle = (NwGtpv1uLogMgrHandleT) &logObj;
NW_LOG(NW_LOG_LEVEL_ERRO, logMgr.logReqCallback = nwMiniLogMgrLogRequest;
"Failed to create gtpv1u stack instance. Error '%u' occured", rc);
exit(1);
}
NW_LOG(NW_LOG_LEVEL_INFO, "Gtpv1u Stack Handle '%X' Creation Successful!", 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); 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 );
/*--------------------------------------------------------------------------- return rc;
* 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,6 +1,6 @@
/*----------------------------------------------------------------------------* /*----------------------------------------------------------------------------*
* * * *
* n w - g t p v 2 c * * 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 * * 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 *
* * * *
* * * *
@@ -37,8 +37,8 @@
#include <stdio.h> #include <stdio.h>
#include "NwLog.h" #include "NwLog.h"
/** /**
* @file NwGtpv2cLog.h * @file NwGtpv2cLog.h
* @brief This header contains logging related definitions. * @brief This header contains logging related definitions.
*/ */
@@ -1,6 +1,6 @@
/*----------------------------------------------------------------------------* /*----------------------------------------------------------------------------*
* * * *
* n w - g t p v 2 c * * 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 * * 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 *
* * * *
* * * *
@@ -37,13 +37,12 @@
#include "NwTypes.h" #include "NwTypes.h"
#include "NwGtpv2c.h" #include "NwGtpv2c.h"
/** /**
* @file NwGtpv2cMsgParseInfo.h * @file NwGtpv2cMsgParseInfo.h
* @brief This file defines APIs for to parse incoming messages. * @brief This file defines APIs for to parse incoming messages.
*/ */
typedef struct typedef struct {
{
NwU8T groupedIeType; NwU8T groupedIeType;
NwU16T mandatoryIeCount; NwU16T mandatoryIeCount;
NwGtpv2cStackHandleT hStack; NwGtpv2cStackHandleT hStack;
@@ -55,8 +54,7 @@ typedef struct
} NwGtpv2cGroupedIeParseInfoT; } NwGtpv2cGroupedIeParseInfoT;
typedef struct typedef struct {
{
NwU16T msgType; NwU16T msgType;
NwU16T mandatoryIeCount; NwU16T mandatoryIeCount;
NwGtpv2cStackHandleT hStack; NwGtpv2cStackHandleT hStack;
@@ -80,9 +78,9 @@ NwRcT
nwGtpv2cMsgIeParseInfoDelete(NwGtpv2cMsgIeParseInfoT* thiz); nwGtpv2cMsgIeParseInfoDelete(NwGtpv2cMsgIeParseInfoT* thiz);
NwRcT NwRcT
nwGtpv2cMsgIeParse(NW_IN NwGtpv2cMsgIeParseInfoT* thiz, nwGtpv2cMsgIeParse(NW_IN NwGtpv2cMsgIeParseInfoT* thiz,
NW_IN NwGtpv2cMsgHandleT hMsg, NW_IN NwGtpv2cMsgHandleT hMsg,
NW_INOUT NwGtpv2cErrorT *pError); NW_INOUT NwGtpv2cErrorT *pError);
#ifdef __cplusplus #ifdef __cplusplus
} }
@@ -1,6 +1,6 @@
/*----------------------------------------------------------------------------* /*----------------------------------------------------------------------------*
* * * *
* n w - g t p v 2 c * * 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 * * 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 *
* * * *
* * * *
@@ -47,9 +47,9 @@
#include "NwGtpv2cMsgIeParseInfo.h" #include "NwGtpv2cMsgIeParseInfo.h"
#include "NwGtpv2cTunnel.h" #include "NwGtpv2cTunnel.h"
/** /**
* @file NwGtpv2cPrivate.h * @file NwGtpv2cPrivate.h
* @brief This header file contains nw-gtpv2c private definitions not to be * @brief This header file contains nw-gtpv2c private definitions not to be
* exposed to user application. * exposed to user application.
*/ */
@@ -89,8 +89,7 @@ extern "C" {
* gtpv2c stack class definition * gtpv2c stack class definition
*/ */
typedef struct NwGtpv2cStack typedef struct NwGtpv2cStack {
{
NwU32T id; NwU32T id;
NwGtpv2cUlpEntityT ulp; NwGtpv2cUlpEntityT ulp;
NwGtpv2cUdpEntityT udp; NwGtpv2cUdpEntityT udp;
@@ -110,19 +109,18 @@ typedef struct NwGtpv2cStack
RB_HEAD( NwGtpv2cOutstandingRxSeqNumTrxnMap, NwGtpv2cTrxn ) outstandingRxSeqNumMap; RB_HEAD( NwGtpv2cOutstandingRxSeqNumTrxnMap, NwGtpv2cTrxn ) outstandingRxSeqNumMap;
RB_HEAD( NwGtpv2cActiveTimerList, NwGtpv2cTimeoutInfo ) activeTimerList; RB_HEAD( NwGtpv2cActiveTimerList, NwGtpv2cTimeoutInfo ) activeTimerList;
NwHandleT hTmrMinHeap; NwHandleT hTmrMinHeap;
} NwGtpv2cStackT; } NwGtpv2cStackT;
/*--------------------------------------------------------------------------* /*--------------------------------------------------------------------------*
* Timeout Info Type Definition * Timeout Info Type Definition
*--------------------------------------------------------------------------*/ *--------------------------------------------------------------------------*/
/** /**
* gtpv2c timeout info * gtpv2c timeout info
*/ */
typedef struct NwGtpv2cTimeoutInfo typedef struct NwGtpv2cTimeoutInfo {
{
NwGtpv2cStackHandleT hStack; NwGtpv2cStackHandleT hStack;
struct timeval tvTimeout; struct timeval tvTimeout;
NwU32T tmrType; NwU32T tmrType;
@@ -144,8 +142,7 @@ typedef struct NwGtpv2cTimeoutInfo
/** /**
* NwGtpv2cMsgT holds gtpv2c messages to/from the peer. * NwGtpv2cMsgT holds gtpv2c messages to/from the peer.
*/ */
typedef struct NwGtpv2cMsgS typedef struct NwGtpv2cMsgS {
{
NwU8T version; NwU8T version;
NwU8T teidPresent; NwU8T teidPresent;
NwU8T msgType; NwU8T msgType;
@@ -171,8 +168,7 @@ typedef struct NwGtpv2cMsgS
* Transaction structure * Transaction structure
*/ */
typedef struct NwGtpv2cTrxn typedef struct NwGtpv2cTrxn {
{
NwU32T seqNum; NwU32T seqNum;
NwU32T peerIp; NwU32T peerIp;
NwU32T peerPort; NwU32T peerPort;
@@ -192,8 +188,7 @@ typedef struct NwGtpv2cTrxn
* GTPv2c Path Context * GTPv2c Path Context
*/ */
typedef struct NwGtpv2cPathS typedef struct NwGtpv2cPathS {
{
NwU32T hUlpPath; /**< Handle to ULP path contect */ NwU32T hUlpPath; /**< Handle to ULP path contect */
NwU32T ipv4Address; NwU32T ipv4Address;
NwU32T restartCounter; NwU32T restartCounter;
@@ -1,6 +1,6 @@
/*----------------------------------------------------------------------------* /*----------------------------------------------------------------------------*
* * * *
* n w - g t p v 2 c * * 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 * * 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 *
* * * *
* * * *
@@ -34,10 +34,10 @@
/** /**
* @file NwGtpv2cTrxn.h * @file NwGtpv2cTrxn.h
* @author Amit Chawre * @author Amit Chawre
* @brief * @brief
* *
* This header file contains required definitions and functions * This header file contains required definitions and functions
* prototypes used by gtpv2c transactions. * prototypes used by gtpv2c transactions.
* *
**/ **/
@@ -49,24 +49,24 @@
extern "C" { extern "C" {
#endif #endif
/** /**
* Constructotr * Constructotr
*/ */
NwGtpv2cTrxnT* NwGtpv2cTrxnT*
nwGtpv2cTrxnNew( NW_IN NwGtpv2cStackT* pStack); nwGtpv2cTrxnNew( NW_IN NwGtpv2cStackT* pStack);
/** /**
* Overloaded Constructotr * Overloaded Constructotr
*/ */
NwGtpv2cTrxnT* NwGtpv2cTrxnT*
nwGtpv2cTrxnWithSeqNumNew( NW_IN NwGtpv2cStackT* pStack, nwGtpv2cTrxnWithSeqNumNew( NW_IN NwGtpv2cStackT* pStack,
NW_IN NwU32T seqNum); NW_IN NwU32T seqNum);
/** /**
* Another overloaded constructor. Create transaction as outstanding * Another overloaded constructor. Create transaction as outstanding
* RX transaction for detecting duplicated requests. * RX transaction for detecting duplicated requests.
* *
* @param[in] thiz : Pointer to stack. * @param[in] thiz : Pointer to stack.
* @param[in] teidLocal : Trxn teid. * @param[in] teidLocal : Trxn teid.
* @param[in] peerIp : Peer Ip address. * @param[in] peerIp : Peer Ip address.
* @param[in] peerPort : Peer Ip port. * @param[in] peerPort : Peer Ip port.
@@ -76,10 +76,10 @@ nwGtpv2cTrxnWithSeqNumNew( NW_IN NwGtpv2cStackT* pStack,
NwGtpv2cTrxnT* NwGtpv2cTrxnT*
nwGtpv2cTrxnOutstandingRxNew( NW_IN NwGtpv2cStackT* pStack, nwGtpv2cTrxnOutstandingRxNew( NW_IN NwGtpv2cStackT* pStack,
NW_IN NwU32T teidLocal, NW_IN NwU32T teidLocal,
NW_IN NwU32T peerIp, NW_IN NwU32T peerIp,
NW_IN NwU32T peerPort, NW_IN NwU32T peerPort,
NW_IN NwU32T seqNum); NW_IN NwU32T seqNum);
NwRcT NwRcT
nwGtpv2cTrxnDelete( NW_INOUT NwGtpv2cTrxnT **ppTrxn); nwGtpv2cTrxnDelete( NW_INOUT NwGtpv2cTrxnT **ppTrxn);
@@ -96,7 +96,7 @@ nwGtpv2cTrxnStartDulpicateRequestWaitTimer(NwGtpv2cTrxnT* thiz);
/** /**
* Start timer to wait for rsp of a req message * Start timer to wait for rsp of a req message
* *
* @param[in] thiz : Pointer to transaction * @param[in] thiz : Pointer to transaction
* @param[in] timeoutCallbackFunc : Timeout handler callback function. * @param[in] timeoutCallbackFunc : Timeout handler callback function.
* @return NW_OK on success. * @return NW_OK on success.
@@ -1,6 +1,6 @@
/*----------------------------------------------------------------------------* /*----------------------------------------------------------------------------*
* * * *
* n w - g t p v 2 c * * 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 * * 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 *
* * * *
* * * *
@@ -50,8 +50,7 @@ extern "C" {
struct NwGtpv2cStack; struct NwGtpv2cStack;
typedef struct NwGtpv2cTunnel typedef struct NwGtpv2cTunnel {
{
NwU32T teid; NwU32T teid;
NwU32T ipv4AddrRemote; NwU32T ipv4AddrRemote;
NwGtpv2cUlpTunnelHandleT hUlpTunnel; NwGtpv2cUlpTunnelHandleT hUlpTunnel;
+300 -300
View File
@@ -1,6 +1,6 @@
/* /*
* Copyright (c) 1991, 1993 * Copyright (c) 1991, 1993
* The Regents of the University of California. All rights reserved. * The Regents of the University of California. All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions * modification, are permitted provided that the following conditions
@@ -12,8 +12,8 @@
* documentation and/or other materials provided with the distribution. * documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software * 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement: * must display the following acknowledgement:
* This product includes software developed by the University of * This product includes software developed by the University of
* California, Berkeley and its contributors. * California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of 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 * may be used to endorse or promote products derived from this software
* without specific prior written permission. * without specific prior written permission.
@@ -30,12 +30,12 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE. * SUCH DAMAGE.
* *
* @(#)queue.h 8.5 (Berkeley) 8/20/94 * @(#)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 $ * $FreeBSD: src/sys/sys/queue.h,v 1.32.2.6 2001/12/18 10:09:02 ru Exp $
*/ */
#ifndef _SYS_QUEUE_H_ #ifndef _SYS_QUEUE_H_
#define _SYS_QUEUE_H_ #define _SYS_QUEUE_H_
/* /*
@@ -88,431 +88,431 @@
* For details on the use of these macros, see the queue(3) manual page. * For details on the use of these macros, see the queue(3) manual page.
* *
* *
* SLIST LIST STAILQ TAILQ CIRCLEQ * SLIST LIST STAILQ TAILQ CIRCLEQ
* _HEAD + + + + + * _HEAD + + + + +
* _HEAD_INITIALIZER + + + + + * _HEAD_INITIALIZER + + + + +
* _ENTRY + + + + + * _ENTRY + + + + +
* _INIT + + + + + * _INIT + + + + +
* _EMPTY + + + + + * _EMPTY + + + + +
* _FIRST + + + + + * _FIRST + + + + +
* _NEXT + + + + + * _NEXT + + + + +
* _PREV - - - + + * _PREV - - - + +
* _LAST - - + + + * _LAST - - + + +
* _FOREACH + + + + + * _FOREACH + + + + +
* _FOREACH_REVERSE - - - + + * _FOREACH_REVERSE - - - + +
* _INSERT_HEAD + + + + + * _INSERT_HEAD + + + + +
* _INSERT_BEFORE - + - + + * _INSERT_BEFORE - + - + +
* _INSERT_AFTER + + + + + * _INSERT_AFTER + + + + +
* _INSERT_TAIL - - + + + * _INSERT_TAIL - - + + +
* _REMOVE_HEAD + - + - - * _REMOVE_HEAD + - + - -
* _REMOVE + + + + + * _REMOVE + + + + +
* *
*/ */
/* /*
* Singly-linked List declarations. * Singly-linked List declarations.
*/ */
#define SLIST_HEAD(name, type) \ #define SLIST_HEAD(name, type) \
struct name { \ struct name { \
struct type *slh_first; /* first element */ \ struct type *slh_first; /* first element */ \
} }
#define SLIST_HEAD_INITIALIZER(head) \ #define SLIST_HEAD_INITIALIZER(head) \
{ NULL } { NULL }
#define SLIST_ENTRY(type) \ #define SLIST_ENTRY(type) \
struct { \ struct { \
struct type *sle_next; /* next element */ \ struct type *sle_next; /* next element */ \
} }
/* /*
* Singly-linked List functions. * Singly-linked List functions.
*/ */
#define SLIST_EMPTY(head) ((head)->slh_first == NULL) #define SLIST_EMPTY(head) ((head)->slh_first == NULL)
#define SLIST_FIRST(head) ((head)->slh_first) #define SLIST_FIRST(head) ((head)->slh_first)
#define SLIST_FOREACH(var, head, field) \ #define SLIST_FOREACH(var, head, field) \
for ((var) = SLIST_FIRST((head)); \ for ((var) = SLIST_FIRST((head)); \
(var); \ (var); \
(var) = SLIST_NEXT((var), field)) (var) = SLIST_NEXT((var), field))
#define SLIST_INIT(head) do { \ #define SLIST_INIT(head) do { \
SLIST_FIRST((head)) = NULL; \ SLIST_FIRST((head)) = NULL; \
} while (0) } while (0)
#define SLIST_INSERT_AFTER(slistelm, elm, field) do { \ #define SLIST_INSERT_AFTER(slistelm, elm, field) do { \
SLIST_NEXT((elm), field) = SLIST_NEXT((slistelm), field); \ SLIST_NEXT((elm), field) = SLIST_NEXT((slistelm), field); \
SLIST_NEXT((slistelm), field) = (elm); \ SLIST_NEXT((slistelm), field) = (elm); \
} while (0) } while (0)
#define SLIST_INSERT_HEAD(head, elm, field) do { \ #define SLIST_INSERT_HEAD(head, elm, field) do { \
SLIST_NEXT((elm), field) = SLIST_FIRST((head)); \ SLIST_NEXT((elm), field) = SLIST_FIRST((head)); \
SLIST_FIRST((head)) = (elm); \ SLIST_FIRST((head)) = (elm); \
} while (0) } while (0)
#define SLIST_NEXT(elm, field) ((elm)->field.sle_next) #define SLIST_NEXT(elm, field) ((elm)->field.sle_next)
#define SLIST_REMOVE(head, elm, type, field) do { \ #define SLIST_REMOVE(head, elm, type, field) do { \
if (SLIST_FIRST((head)) == (elm)) { \ if (SLIST_FIRST((head)) == (elm)) { \
SLIST_REMOVE_HEAD((head), field); \ SLIST_REMOVE_HEAD((head), field); \
} \ } \
else { \ else { \
struct type *curelm = SLIST_FIRST((head)); \ struct type *curelm = SLIST_FIRST((head)); \
while (SLIST_NEXT(curelm, field) != (elm)) \ while (SLIST_NEXT(curelm, field) != (elm)) \
curelm = SLIST_NEXT(curelm, field); \ curelm = SLIST_NEXT(curelm, field); \
SLIST_NEXT(curelm, field) = \ SLIST_NEXT(curelm, field) = \
SLIST_NEXT(SLIST_NEXT(curelm, field), field); \ SLIST_NEXT(SLIST_NEXT(curelm, field), field); \
} \ } \
} while (0) } while (0)
#define SLIST_REMOVE_HEAD(head, field) do { \ #define SLIST_REMOVE_HEAD(head, field) do { \
SLIST_FIRST((head)) = SLIST_NEXT(SLIST_FIRST((head)), field); \ SLIST_FIRST((head)) = SLIST_NEXT(SLIST_FIRST((head)), field); \
} while (0) } while (0)
/* /*
* Singly-linked Tail queue declarations. * Singly-linked Tail queue declarations.
*/ */
#define STAILQ_HEAD(name, type) \ #define STAILQ_HEAD(name, type) \
struct name { \ struct name { \
struct type *stqh_first;/* first element */ \ struct type *stqh_first;/* first element */ \
struct type **stqh_last;/* addr of last next element */ \ struct type **stqh_last;/* addr of last next element */ \
} }
#define STAILQ_HEAD_INITIALIZER(head) \ #define STAILQ_HEAD_INITIALIZER(head) \
{ NULL, &(head).stqh_first } { NULL, &(head).stqh_first }
#define STAILQ_HEAD_INIT(head) do{ \ #define STAILQ_HEAD_INIT(head) do{ \
(head).stqh_first = NULL; \ (head).stqh_first = NULL; \
(head).stqh_last = &(head).stqh_first; \ (head).stqh_last = &(head).stqh_first; \
}while(0) }while(0)
#define STAILQ_ENTRY(type) \ #define STAILQ_ENTRY(type) \
struct { \ struct { \
struct type *stqe_next; /* next element */ \ struct type *stqe_next; /* next element */ \
} }
/* /*
* Singly-linked Tail queue functions. * Singly-linked Tail queue functions.
*/ */
#define STAILQ_EMPTY(head) ((head)->stqh_first == NULL) #define STAILQ_EMPTY(head) ((head)->stqh_first == NULL)
#define STAILQ_FIRST(head) ((head)->stqh_first) #define STAILQ_FIRST(head) ((head)->stqh_first)
#define STAILQ_FOREACH(var, head, field) \ #define STAILQ_FOREACH(var, head, field) \
for((var) = STAILQ_FIRST((head)); \ for((var) = STAILQ_FIRST((head)); \
(var); \ (var); \
(var) = STAILQ_NEXT((var), field)) (var) = STAILQ_NEXT((var), field))
#define STAILQ_INIT(head) do { \ #define STAILQ_INIT(head) do { \
STAILQ_FIRST((head)) = NULL; \ STAILQ_FIRST((head)) = NULL; \
(head)->stqh_last = &STAILQ_FIRST((head)); \ (head)->stqh_last = &STAILQ_FIRST((head)); \
} while (0) } while (0)
#define STAILQ_INSERT_AFTER(head, tqelm, elm, field) do { \ #define STAILQ_INSERT_AFTER(head, tqelm, elm, field) do { \
if ((STAILQ_NEXT((elm), field) = STAILQ_NEXT((tqelm), field)) == NULL)\ if ((STAILQ_NEXT((elm), field) = STAILQ_NEXT((tqelm), field)) == NULL)\
(head)->stqh_last = &STAILQ_NEXT((elm), field); \ (head)->stqh_last = &STAILQ_NEXT((elm), field); \
STAILQ_NEXT((tqelm), field) = (elm); \ STAILQ_NEXT((tqelm), field) = (elm); \
} while (0) } while (0)
#define STAILQ_INSERT_HEAD(head, elm, field) do { \ #define STAILQ_INSERT_HEAD(head, elm, field) do { \
if ((STAILQ_NEXT((elm), field) = STAILQ_FIRST((head))) == NULL) \ if ((STAILQ_NEXT((elm), field) = STAILQ_FIRST((head))) == NULL) \
(head)->stqh_last = &STAILQ_NEXT((elm), field); \ (head)->stqh_last = &STAILQ_NEXT((elm), field); \
STAILQ_FIRST((head)) = (elm); \ STAILQ_FIRST((head)) = (elm); \
} while (0) } while (0)
#define STAILQ_INSERT_TAIL(head, elm, field) do { \ #define STAILQ_INSERT_TAIL(head, elm, field) do { \
STAILQ_NEXT((elm), field) = NULL; \ STAILQ_NEXT((elm), field) = NULL; \
*(head)->stqh_last = (elm); \ *(head)->stqh_last = (elm); \
(head)->stqh_last = &STAILQ_NEXT((elm), field); \ (head)->stqh_last = &STAILQ_NEXT((elm), field); \
} while (0) } while (0)
#define STAILQ_LAST(head, type, field) \ #define STAILQ_LAST(head, type, field) \
(STAILQ_EMPTY(head) ? \ (STAILQ_EMPTY(head) ? \
NULL : \ NULL : \
((struct type *) \ ((struct type *) \
((char *)((head)->stqh_last) - __offsetof(struct type, field)))) ((char *)((head)->stqh_last) - __offsetof(struct type, field))))
#define STAILQ_NEXT(elm, field) ((elm)->field.stqe_next) #define STAILQ_NEXT(elm, field) ((elm)->field.stqe_next)
#define STAILQ_REMOVE(head, elm, type, field) do { \ #define STAILQ_REMOVE(head, elm, type, field) do { \
if (STAILQ_FIRST((head)) == (elm)) { \ if (STAILQ_FIRST((head)) == (elm)) { \
STAILQ_REMOVE_HEAD(head, field); \ STAILQ_REMOVE_HEAD(head, field); \
} \ } \
else { \ else { \
struct type *curelm = STAILQ_FIRST((head)); \ struct type *curelm = STAILQ_FIRST((head)); \
while (STAILQ_NEXT(curelm, field) != (elm)) \ while (STAILQ_NEXT(curelm, field) != (elm)) \
curelm = STAILQ_NEXT(curelm, field); \ curelm = STAILQ_NEXT(curelm, field); \
if ((STAILQ_NEXT(curelm, field) = \ if ((STAILQ_NEXT(curelm, field) = \
STAILQ_NEXT(STAILQ_NEXT(curelm, field), field)) == NULL)\ STAILQ_NEXT(STAILQ_NEXT(curelm, field), field)) == NULL)\
(head)->stqh_last = &STAILQ_NEXT((curelm), field);\ (head)->stqh_last = &STAILQ_NEXT((curelm), field);\
} \ } \
} while (0) } while (0)
#define STAILQ_REMOVE_HEAD(head, field) do { \ #define STAILQ_REMOVE_HEAD(head, field) do { \
if ((STAILQ_FIRST((head)) = \ if ((STAILQ_FIRST((head)) = \
STAILQ_NEXT(STAILQ_FIRST((head)), field)) == NULL) \ STAILQ_NEXT(STAILQ_FIRST((head)), field)) == NULL) \
(head)->stqh_last = &STAILQ_FIRST((head)); \ (head)->stqh_last = &STAILQ_FIRST((head)); \
} while (0) } while (0)
#define STAILQ_REMOVE_HEAD_UNTIL(head, elm, field) do { \ #define STAILQ_REMOVE_HEAD_UNTIL(head, elm, field) do { \
if ((STAILQ_FIRST((head)) = STAILQ_NEXT((elm), field)) == NULL) \ if ((STAILQ_FIRST((head)) = STAILQ_NEXT((elm), field)) == NULL) \
(head)->stqh_last = &STAILQ_FIRST((head)); \ (head)->stqh_last = &STAILQ_FIRST((head)); \
} while (0) } while (0)
/* /*
* List declarations. * List declarations.
*/ */
#define LIST_HEAD(name, type) \ #define LIST_HEAD(name, type) \
struct name { \ struct name { \
struct type *lh_first; /* first element */ \ struct type *lh_first; /* first element */ \
} }
#define LIST_HEAD_INITIALIZER(head) \ #define LIST_HEAD_INITIALIZER(head) \
{ NULL } { NULL }
#define LIST_ENTRY(type) \ #define LIST_ENTRY(type) \
struct { \ struct { \
struct type *le_next; /* next element */ \ struct type *le_next; /* next element */ \
struct type **le_prev; /* address of previous next element */ \ struct type **le_prev; /* address of previous next element */ \
} }
/* /*
* List functions. * List functions.
*/ */
#define LIST_EMPTY(head) ((head)->lh_first == NULL) #define LIST_EMPTY(head) ((head)->lh_first == NULL)
#define LIST_FIRST(head) ((head)->lh_first) #define LIST_FIRST(head) ((head)->lh_first)
#define LIST_FOREACH(var, head, field) \ #define LIST_FOREACH(var, head, field) \
for ((var) = LIST_FIRST((head)); \ for ((var) = LIST_FIRST((head)); \
(var); \ (var); \
(var) = LIST_NEXT((var), field)) (var) = LIST_NEXT((var), field))
#define LIST_INIT(head) do { \ #define LIST_INIT(head) do { \
LIST_FIRST((head)) = NULL; \ LIST_FIRST((head)) = NULL; \
} while (0) } while (0)
#define LIST_INSERT_AFTER(listelm, elm, field) do { \ #define LIST_INSERT_AFTER(listelm, elm, field) do { \
if ((LIST_NEXT((elm), field) = LIST_NEXT((listelm), field)) != NULL)\ if ((LIST_NEXT((elm), field) = LIST_NEXT((listelm), field)) != NULL)\
LIST_NEXT((listelm), field)->field.le_prev = \ LIST_NEXT((listelm), field)->field.le_prev = \
&LIST_NEXT((elm), field); \ &LIST_NEXT((elm), field); \
LIST_NEXT((listelm), field) = (elm); \ LIST_NEXT((listelm), field) = (elm); \
(elm)->field.le_prev = &LIST_NEXT((listelm), field); \ (elm)->field.le_prev = &LIST_NEXT((listelm), field); \
} while (0) } while (0)
#define LIST_INSERT_BEFORE(listelm, elm, field) do { \ #define LIST_INSERT_BEFORE(listelm, elm, field) do { \
(elm)->field.le_prev = (listelm)->field.le_prev; \ (elm)->field.le_prev = (listelm)->field.le_prev; \
LIST_NEXT((elm), field) = (listelm); \ LIST_NEXT((elm), field) = (listelm); \
*(listelm)->field.le_prev = (elm); \ *(listelm)->field.le_prev = (elm); \
(listelm)->field.le_prev = &LIST_NEXT((elm), field); \ (listelm)->field.le_prev = &LIST_NEXT((elm), field); \
} while (0) } while (0)
#define LIST_INSERT_HEAD(head, elm, field) do { \ #define LIST_INSERT_HEAD(head, elm, field) do { \
if ((LIST_NEXT((elm), field) = LIST_FIRST((head))) != NULL) \ if ((LIST_NEXT((elm), field) = LIST_FIRST((head))) != NULL) \
LIST_FIRST((head))->field.le_prev = &LIST_NEXT((elm), field);\ LIST_FIRST((head))->field.le_prev = &LIST_NEXT((elm), field);\
LIST_FIRST((head)) = (elm); \ LIST_FIRST((head)) = (elm); \
(elm)->field.le_prev = &LIST_FIRST((head)); \ (elm)->field.le_prev = &LIST_FIRST((head)); \
} while (0) } while (0)
#define LIST_NEXT(elm, field) ((elm)->field.le_next) #define LIST_NEXT(elm, field) ((elm)->field.le_next)
#define LIST_REMOVE(elm, field) do { \ #define LIST_REMOVE(elm, field) do { \
if (LIST_NEXT((elm), field) != NULL) \ if (LIST_NEXT((elm), field) != NULL) \
LIST_NEXT((elm), field)->field.le_prev = \ LIST_NEXT((elm), field)->field.le_prev = \
(elm)->field.le_prev; \ (elm)->field.le_prev; \
*(elm)->field.le_prev = LIST_NEXT((elm), field); \ *(elm)->field.le_prev = LIST_NEXT((elm), field); \
} while (0) } while (0)
/* /*
* Tail queue declarations. * Tail queue declarations.
*/ */
#define TAILQ_HEAD(name, type) \ #define TAILQ_HEAD(name, type) \
struct name { \ struct name { \
struct type *tqh_first; /* first element */ \ struct type *tqh_first; /* first element */ \
struct type **tqh_last; /* addr of last next element */ \ struct type **tqh_last; /* addr of last next element */ \
} }
#define TAILQ_HEAD_INITIALIZER(head) \ #define TAILQ_HEAD_INITIALIZER(head) \
{ NULL, &(head).tqh_first } { NULL, &(head).tqh_first }
#define TAILQ_ENTRY(type) \ #define TAILQ_ENTRY(type) \
struct { \ struct { \
struct type *tqe_next; /* next element */ \ struct type *tqe_next; /* next element */ \
struct type **tqe_prev; /* address of previous next element */ \ struct type **tqe_prev; /* address of previous next element */ \
} }
/* /*
* Tail queue functions. * Tail queue functions.
*/ */
#define TAILQ_EMPTY(head) ((head)->tqh_first == NULL) #define TAILQ_EMPTY(head) ((head)->tqh_first == NULL)
#define TAILQ_FIRST(head) ((head)->tqh_first) #define TAILQ_FIRST(head) ((head)->tqh_first)
#define TAILQ_FOREACH(var, head, field) \ #define TAILQ_FOREACH(var, head, field) \
for ((var) = TAILQ_FIRST((head)); \ for ((var) = TAILQ_FIRST((head)); \
(var); \ (var); \
(var) = TAILQ_NEXT((var), field)) (var) = TAILQ_NEXT((var), field))
#define TAILQ_FOREACH_REVERSE(var, head, headname, field) \ #define TAILQ_FOREACH_REVERSE(var, head, headname, field) \
for ((var) = TAILQ_LAST((head), headname); \ for ((var) = TAILQ_LAST((head), headname); \
(var); \ (var); \
(var) = TAILQ_PREV((var), headname, field)) (var) = TAILQ_PREV((var), headname, field))
#define TAILQ_INIT(head) do { \ #define TAILQ_INIT(head) do { \
TAILQ_FIRST((head)) = NULL; \ TAILQ_FIRST((head)) = NULL; \
(head)->tqh_last = &TAILQ_FIRST((head)); \ (head)->tqh_last = &TAILQ_FIRST((head)); \
} while (0) } while (0)
#define TAILQ_INSERT_AFTER(head, listelm, elm, field) do { \ #define TAILQ_INSERT_AFTER(head, listelm, elm, field) do { \
if ((TAILQ_NEXT((elm), field) = TAILQ_NEXT((listelm), field)) != NULL)\ if ((TAILQ_NEXT((elm), field) = TAILQ_NEXT((listelm), field)) != NULL)\
TAILQ_NEXT((elm), field)->field.tqe_prev = \ TAILQ_NEXT((elm), field)->field.tqe_prev = \
&TAILQ_NEXT((elm), field); \ &TAILQ_NEXT((elm), field); \
else \ else \
(head)->tqh_last = &TAILQ_NEXT((elm), field); \ (head)->tqh_last = &TAILQ_NEXT((elm), field); \
TAILQ_NEXT((listelm), field) = (elm); \ TAILQ_NEXT((listelm), field) = (elm); \
(elm)->field.tqe_prev = &TAILQ_NEXT((listelm), field); \ (elm)->field.tqe_prev = &TAILQ_NEXT((listelm), field); \
} while (0) } while (0)
#define TAILQ_INSERT_BEFORE(listelm, elm, field) do { \ #define TAILQ_INSERT_BEFORE(listelm, elm, field) do { \
(elm)->field.tqe_prev = (listelm)->field.tqe_prev; \ (elm)->field.tqe_prev = (listelm)->field.tqe_prev; \
TAILQ_NEXT((elm), field) = (listelm); \ TAILQ_NEXT((elm), field) = (listelm); \
*(listelm)->field.tqe_prev = (elm); \ *(listelm)->field.tqe_prev = (elm); \
(listelm)->field.tqe_prev = &TAILQ_NEXT((elm), field); \ (listelm)->field.tqe_prev = &TAILQ_NEXT((elm), field); \
} while (0) } while (0)
#define TAILQ_INSERT_HEAD(head, elm, field) do { \ #define TAILQ_INSERT_HEAD(head, elm, field) do { \
if ((TAILQ_NEXT((elm), field) = TAILQ_FIRST((head))) != NULL) \ if ((TAILQ_NEXT((elm), field) = TAILQ_FIRST((head))) != NULL) \
TAILQ_FIRST((head))->field.tqe_prev = \ TAILQ_FIRST((head))->field.tqe_prev = \
&TAILQ_NEXT((elm), field); \ &TAILQ_NEXT((elm), field); \
else \ else \
(head)->tqh_last = &TAILQ_NEXT((elm), field); \ (head)->tqh_last = &TAILQ_NEXT((elm), field); \
TAILQ_FIRST((head)) = (elm); \ TAILQ_FIRST((head)) = (elm); \
(elm)->field.tqe_prev = &TAILQ_FIRST((head)); \ (elm)->field.tqe_prev = &TAILQ_FIRST((head)); \
} while (0) } while (0)
#define TAILQ_INSERT_TAIL(head, elm, field) do { \ #define TAILQ_INSERT_TAIL(head, elm, field) do { \
TAILQ_NEXT((elm), field) = NULL; \ TAILQ_NEXT((elm), field) = NULL; \
(elm)->field.tqe_prev = (head)->tqh_last; \ (elm)->field.tqe_prev = (head)->tqh_last; \
*(head)->tqh_last = (elm); \ *(head)->tqh_last = (elm); \
(head)->tqh_last = &TAILQ_NEXT((elm), field); \ (head)->tqh_last = &TAILQ_NEXT((elm), field); \
} while (0) } while (0)
#define TAILQ_LAST(head, headname) \ #define TAILQ_LAST(head, headname) \
(*(((struct headname *)((head)->tqh_last))->tqh_last)) (*(((struct headname *)((head)->tqh_last))->tqh_last))
#define TAILQ_NEXT(elm, field) ((elm)->field.tqe_next) #define TAILQ_NEXT(elm, field) ((elm)->field.tqe_next)
#define TAILQ_PREV(elm, headname, field) \ #define TAILQ_PREV(elm, headname, field) \
(*(((struct headname *)((elm)->field.tqe_prev))->tqh_last)) (*(((struct headname *)((elm)->field.tqe_prev))->tqh_last))
#define TAILQ_REMOVE(head, elm, field) do { \ #define TAILQ_REMOVE(head, elm, field) do { \
if ((TAILQ_NEXT((elm), field)) != NULL) \ if ((TAILQ_NEXT((elm), field)) != NULL) \
TAILQ_NEXT((elm), field)->field.tqe_prev = \ TAILQ_NEXT((elm), field)->field.tqe_prev = \
(elm)->field.tqe_prev; \ (elm)->field.tqe_prev; \
else \ else \
(head)->tqh_last = (elm)->field.tqe_prev; \ (head)->tqh_last = (elm)->field.tqe_prev; \
*(elm)->field.tqe_prev = TAILQ_NEXT((elm), field); \ *(elm)->field.tqe_prev = TAILQ_NEXT((elm), field); \
} while (0) } while (0)
/* /*
* Circular queue declarations. * Circular queue declarations.
*/ */
#define CIRCLEQ_HEAD(name, type) \ #define CIRCLEQ_HEAD(name, type) \
struct name { \ struct name { \
struct type *cqh_first; /* first element */ \ struct type *cqh_first; /* first element */ \
struct type *cqh_last; /* last element */ \ struct type *cqh_last; /* last element */ \
} }
#define CIRCLEQ_HEAD_INITIALIZER(head) \ #define CIRCLEQ_HEAD_INITIALIZER(head) \
{ (void *)&(head), (void *)&(head) } { (void *)&(head), (void *)&(head) }
#define CIRCLEQ_ENTRY(type) \ #define CIRCLEQ_ENTRY(type) \
struct { \ struct { \
struct type *cqe_next; /* next element */ \ struct type *cqe_next; /* next element */ \
struct type *cqe_prev; /* previous element */ \ struct type *cqe_prev; /* previous element */ \
} }
/* /*
* Circular queue functions. * Circular queue functions.
*/ */
#define CIRCLEQ_EMPTY(head) ((head)->cqh_first == (void *)(head)) #define CIRCLEQ_EMPTY(head) ((head)->cqh_first == (void *)(head))
#define CIRCLEQ_FIRST(head) ((head)->cqh_first) #define CIRCLEQ_FIRST(head) ((head)->cqh_first)
#define CIRCLEQ_FOREACH(var, head, field) \ #define CIRCLEQ_FOREACH(var, head, field) \
for ((var) = CIRCLEQ_FIRST((head)); \ for ((var) = CIRCLEQ_FIRST((head)); \
(var) != (void *)(head); \ (var) != (void *)(head); \
(var) = CIRCLEQ_NEXT((var), field)) (var) = CIRCLEQ_NEXT((var), field))
#define CIRCLEQ_FOREACH_REVERSE(var, head, field) \ #define CIRCLEQ_FOREACH_REVERSE(var, head, field) \
for ((var) = CIRCLEQ_LAST((head)); \ for ((var) = CIRCLEQ_LAST((head)); \
(var) != (void *)(head); \ (var) != (void *)(head); \
(var) = CIRCLEQ_PREV((var), field)) (var) = CIRCLEQ_PREV((var), field))
#define CIRCLEQ_INIT(head) do { \ #define CIRCLEQ_INIT(head) do { \
CIRCLEQ_FIRST((head)) = (void *)(head); \ CIRCLEQ_FIRST((head)) = (void *)(head); \
CIRCLEQ_LAST((head)) = (void *)(head); \ CIRCLEQ_LAST((head)) = (void *)(head); \
} while (0) } while (0)
#define CIRCLEQ_INSERT_AFTER(head, listelm, elm, field) do { \ #define CIRCLEQ_INSERT_AFTER(head, listelm, elm, field) do { \
CIRCLEQ_NEXT((elm), field) = CIRCLEQ_NEXT((listelm), field); \ CIRCLEQ_NEXT((elm), field) = CIRCLEQ_NEXT((listelm), field); \
CIRCLEQ_PREV((elm), field) = (listelm); \ CIRCLEQ_PREV((elm), field) = (listelm); \
if (CIRCLEQ_NEXT((listelm), field) == (void *)(head)) \ if (CIRCLEQ_NEXT((listelm), field) == (void *)(head)) \
CIRCLEQ_LAST((head)) = (elm); \ CIRCLEQ_LAST((head)) = (elm); \
else \ else \
CIRCLEQ_PREV(CIRCLEQ_NEXT((listelm), field), field) = (elm);\ CIRCLEQ_PREV(CIRCLEQ_NEXT((listelm), field), field) = (elm);\
CIRCLEQ_NEXT((listelm), field) = (elm); \ CIRCLEQ_NEXT((listelm), field) = (elm); \
} while (0) } while (0)
#define CIRCLEQ_INSERT_BEFORE(head, listelm, elm, field) do { \ #define CIRCLEQ_INSERT_BEFORE(head, listelm, elm, field) do { \
CIRCLEQ_NEXT((elm), field) = (listelm); \ CIRCLEQ_NEXT((elm), field) = (listelm); \
CIRCLEQ_PREV((elm), field) = CIRCLEQ_PREV((listelm), field); \ CIRCLEQ_PREV((elm), field) = CIRCLEQ_PREV((listelm), field); \
if (CIRCLEQ_PREV((listelm), field) == (void *)(head)) \ if (CIRCLEQ_PREV((listelm), field) == (void *)(head)) \
CIRCLEQ_FIRST((head)) = (elm); \ CIRCLEQ_FIRST((head)) = (elm); \
else \ else \
CIRCLEQ_NEXT(CIRCLEQ_PREV((listelm), field), field) = (elm);\ CIRCLEQ_NEXT(CIRCLEQ_PREV((listelm), field), field) = (elm);\
CIRCLEQ_PREV((listelm), field) = (elm); \ CIRCLEQ_PREV((listelm), field) = (elm); \
} while (0) } while (0)
#define CIRCLEQ_INSERT_HEAD(head, elm, field) do { \ #define CIRCLEQ_INSERT_HEAD(head, elm, field) do { \
CIRCLEQ_NEXT((elm), field) = CIRCLEQ_FIRST((head)); \ CIRCLEQ_NEXT((elm), field) = CIRCLEQ_FIRST((head)); \
CIRCLEQ_PREV((elm), field) = (void *)(head); \ CIRCLEQ_PREV((elm), field) = (void *)(head); \
if (CIRCLEQ_LAST((head)) == (void *)(head)) \ if (CIRCLEQ_LAST((head)) == (void *)(head)) \
CIRCLEQ_LAST((head)) = (elm); \ CIRCLEQ_LAST((head)) = (elm); \
else \ else \
CIRCLEQ_PREV(CIRCLEQ_FIRST((head)), field) = (elm); \ CIRCLEQ_PREV(CIRCLEQ_FIRST((head)), field) = (elm); \
CIRCLEQ_FIRST((head)) = (elm); \ CIRCLEQ_FIRST((head)) = (elm); \
} while (0) } while (0)
#define CIRCLEQ_INSERT_TAIL(head, elm, field) do { \ #define CIRCLEQ_INSERT_TAIL(head, elm, field) do { \
CIRCLEQ_NEXT((elm), field) = (void *)(head); \ CIRCLEQ_NEXT((elm), field) = (void *)(head); \
CIRCLEQ_PREV((elm), field) = CIRCLEQ_LAST((head)); \ CIRCLEQ_PREV((elm), field) = CIRCLEQ_LAST((head)); \
if (CIRCLEQ_FIRST((head)) == (void *)(head)) \ if (CIRCLEQ_FIRST((head)) == (void *)(head)) \
CIRCLEQ_FIRST((head)) = (elm); \ CIRCLEQ_FIRST((head)) = (elm); \
else \ else \
CIRCLEQ_NEXT(CIRCLEQ_LAST((head)), field) = (elm); \ CIRCLEQ_NEXT(CIRCLEQ_LAST((head)), field) = (elm); \
CIRCLEQ_LAST((head)) = (elm); \ CIRCLEQ_LAST((head)) = (elm); \
} while (0) } while (0)
#define CIRCLEQ_LAST(head) ((head)->cqh_last) #define CIRCLEQ_LAST(head) ((head)->cqh_last)
#define CIRCLEQ_NEXT(elm,field) ((elm)->field.cqe_next) #define CIRCLEQ_NEXT(elm,field) ((elm)->field.cqe_next)
#define CIRCLEQ_PREV(elm,field) ((elm)->field.cqe_prev) #define CIRCLEQ_PREV(elm,field) ((elm)->field.cqe_prev)
#define CIRCLEQ_REMOVE(head, elm, field) do { \ #define CIRCLEQ_REMOVE(head, elm, field) do { \
if (CIRCLEQ_NEXT((elm), field) == (void *)(head)) \ if (CIRCLEQ_NEXT((elm), field) == (void *)(head)) \
CIRCLEQ_LAST((head)) = CIRCLEQ_PREV((elm), field); \ CIRCLEQ_LAST((head)) = CIRCLEQ_PREV((elm), field); \
else \ else \
CIRCLEQ_PREV(CIRCLEQ_NEXT((elm), field), field) = \ CIRCLEQ_PREV(CIRCLEQ_NEXT((elm), field), field) = \
CIRCLEQ_PREV((elm), field); \ CIRCLEQ_PREV((elm), field); \
if (CIRCLEQ_PREV((elm), field) == (void *)(head)) \ if (CIRCLEQ_PREV((elm), field) == (void *)(head)) \
CIRCLEQ_FIRST((head)) = CIRCLEQ_NEXT((elm), field); \ CIRCLEQ_FIRST((head)) = CIRCLEQ_NEXT((elm), field); \
else \ else \
CIRCLEQ_NEXT(CIRCLEQ_PREV((elm), field), field) = \ CIRCLEQ_NEXT(CIRCLEQ_PREV((elm), field), field) = \
CIRCLEQ_NEXT((elm), field); \ CIRCLEQ_NEXT((elm), field); \
} while (0) } while (0)
#ifdef _KERNEL #ifdef _KERNEL
@@ -523,38 +523,38 @@ struct { \
*/ */
struct quehead { struct quehead {
struct quehead *qh_link; struct quehead *qh_link;
struct quehead *qh_rlink; struct quehead *qh_rlink;
}; };
#ifdef __GNUC__ #ifdef __GNUC__
static __inline void static __inline void
insque(void *a, void *b) insque(void *a, void *b)
{ {
struct quehead *element = (struct quehead *)a, struct quehead *element = (struct quehead *)a,
*head = (struct quehead *)b; *head = (struct quehead *)b;
element->qh_link = head->qh_link; element->qh_link = head->qh_link;
element->qh_rlink = head; element->qh_rlink = head;
head->qh_link = element; head->qh_link = element;
element->qh_link->qh_rlink = element; element->qh_link->qh_rlink = element;
} }
static __inline void static __inline void
remque(void *a) remque(void *a)
{ {
struct quehead *element = (struct quehead *)a; struct quehead *element = (struct quehead *)a;
element->qh_link->qh_rlink = element->qh_rlink; element->qh_link->qh_rlink = element->qh_rlink;
element->qh_rlink->qh_link = element->qh_link; element->qh_rlink->qh_link = element->qh_link;
element->qh_rlink = 0; element->qh_rlink = 0;
} }
#else /* !__GNUC__ */ #else /* !__GNUC__ */
void insque __P((void *a, void *b)); void insque __P((void *a, void *b));
void remque __P((void *a)); void remque __P((void *a));
#endif /* __GNUC__ */ #endif /* __GNUC__ */
File diff suppressed because it is too large Load Diff
@@ -1,6 +1,6 @@
/*----------------------------------------------------------------------------* /*----------------------------------------------------------------------------*
* * * *
* n w - g t p v 2 c * * 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 * * 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 *
* * * *
* * * *
@@ -35,8 +35,8 @@
#ifndef __NW_ERROR_H__ #ifndef __NW_ERROR_H__
#define __NW_ERROR_H__ #define __NW_ERROR_H__
/** /**
* @file NwError.h * @file NwError.h
* @brief This header file contains return error code type definitions. * @brief This header file contains return error code type definitions.
*/ */
@@ -54,7 +54,8 @@ typedef enum {
NW_GTPV2C_MANDATORY_IE_MISSING, NW_GTPV2C_MANDATORY_IE_MISSING,
NW_GTPV2C_MSG_MALFORMED, NW_GTPV2C_MSG_MALFORMED,
NW_FAILURE = 0xFFFFFFFE NW_FAILURE = 0xFFFFFFFE
} NwRcT; }
NwRcT;
#ifdef __cplusplus #ifdef __cplusplus
} }
+105 -124
View File
@@ -1,6 +1,6 @@
/*----------------------------------------------------------------------------* /*----------------------------------------------------------------------------*
* * * *
* n w - g t p v 2 c * * 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 * * 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 *
* * * *
* * * *
@@ -44,46 +44,46 @@
@section intro Introduction @section intro Introduction
nw-gtpv2c library is a free and open source control plane implementation of GPRS 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. Tunneling protocol v2 also known as eGTPc as per 3GPP TS29274-930.
The library is published under BSD three clause license. The library is published under BSD three clause license.
@section scope Scope @section scope Scope
The stack library also does basic tasks like packet/header validation, The stack library also does basic tasks like packet/header validation,
retransmission and message parsing. retransmission and message parsing.
@section design Design Philosophy @section design Design Philosophy
The stack is fully-asynchronous in design for compatibility with event loop 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 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 applications. It should compile on Linux, *BSD, Mac OS X, Solaris and Windows
(cygwin). (cygwin).
The stack is designed for high portability not only for the hardware and OS it will 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 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 conditions on the user application architecture or design. The stack relies on
the user application for infrastructure utilities such as I/O, timers, the user application for infrastructure utilities such as I/O, timers,
logs and multithreading. This realized by using callback mechanisms and enables the 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 stack library to seamlessly integrate without or very little changes to the existing
application framework. application framework.
The stack architecture builds upon following mentioned entities that are external to it. The stack architecture builds upon following mentioned entities that are external to it.
User Layer Protocol (ULP) Entity: User Layer Protocol (ULP) Entity:
This layer implements the intelligent logic for the application and sits on top of the This layer implements the intelligent logic for the application and sits on top of the
stack. stack.
UDP Entity: UDP Entity:
This is the layer below the stack and is responsible for UDP I/O with the stack and network. 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. It may or may not be housed in ULP.
Timer Manager Entity: Timer Manager Entity:
Timer Manager Entity provides the stack with infrastructure for timer CRUD operations. Timer Manager Entity provides the stack with infrastructure for timer CRUD operations.
Log Manager Entity: Log Manager Entity:
Log Manager Entity provides the stack with callbacks for logging operations. It may Log Manager Entity provides the stack with callbacks for logging operations. It may
or may not be housed in ULP. or may not be housed in ULP.
The application may implement all above entities as a single or multiple object. The application may implement all above entities as a single or multiple object.
@@ -96,10 +96,10 @@
/** /**
* @file NwGtpv2c.h * @file NwGtpv2c.h
* @author Amit Chawre * @author Amit Chawre
* @brief * @brief
* *
* This header file contains all required definitions and functions * This header file contains all required definitions and functions
* prototypes for using nw-gtpv2c library. * prototypes for using nw-gtpv2c library.
* *
**/ **/
@@ -108,11 +108,11 @@
*--------------------------------------------------------------------------*/ *--------------------------------------------------------------------------*/
typedef NwPtrT NwGtpv2cStackHandleT; /**< Gtpv2c Stack Handle */ typedef NwPtrT NwGtpv2cStackHandleT; /**< Gtpv2c Stack Handle */
typedef NwPtrT NwGtpv2cUlpHandleT; /**< Gtpv2c Stack Ulp Entity Handle */ typedef NwPtrT NwGtpv2cUlpHandleT; /**< Gtpv2c Stack Ulp Entity Handle */
typedef NwPtrT NwGtpv2cUdpHandleT; /**< Gtpv2c Stack Udp Entity Handle */ typedef NwPtrT NwGtpv2cUdpHandleT; /**< Gtpv2c Stack Udp Entity Handle */
typedef NwPtrT NwGtpv2cTimerMgrHandleT; /**< Gtpv2c Stack Timer Manager Handle */ typedef NwPtrT NwGtpv2cTimerMgrHandleT; /**< Gtpv2c Stack Timer Manager Handle */
typedef NwPtrT NwGtpv2cMemMgrHandleT; /**< Gtpv2c Stack Memory Manager Handle */ typedef NwPtrT NwGtpv2cMemMgrHandleT; /**< Gtpv2c Stack Memory Manager Handle */
typedef NwPtrT NwGtpv2cLogMgrHandleT; /**< Gtpv2c Stack Log Manager Handle */ typedef NwPtrT NwGtpv2cLogMgrHandleT; /**< Gtpv2c Stack Log Manager Handle */
typedef NwPtrT NwGtpv2cTimerHandleT; /**< Gtpv2c Stack Timer Handle */ typedef NwPtrT NwGtpv2cTimerHandleT; /**< Gtpv2c Stack Timer Handle */
typedef NwPtrT NwGtpv2cMsgHandleT; /**< Gtpv2c Msg Handle */ typedef NwPtrT NwGtpv2cMsgHandleT; /**< Gtpv2c Msg Handle */
typedef NwPtrT NwGtpv2cTrxnHandleT; /**< Gtpv2c Transaction Handle */ typedef NwPtrT NwGtpv2cTrxnHandleT; /**< Gtpv2c Transaction Handle */
@@ -122,8 +122,7 @@ typedef NwPtrT NwGtpv2cUlpTunnelHandleT; /**< Gtpv2c Ulp
typedef NwU8T NwGtpv2cMsgTypeT; /**< Gtpv2c Msg Type */ typedef NwU8T NwGtpv2cMsgTypeT; /**< Gtpv2c Msg Type */
typedef struct NwGtpv2cStackConfigS typedef struct NwGtpv2cStackConfigS {
{
NwU16T __tbd; NwU16T __tbd;
} NwGtpv2cStackConfigT; } NwGtpv2cStackConfigT;
@@ -140,12 +139,11 @@ typedef struct NwGtpv2cStackConfigS
* Gtpv2c Stack ULP API type definitions * Gtpv2c Stack ULP API type definitions
*--------------------------------------------------------------------------*/ *--------------------------------------------------------------------------*/
/** /**
* APIs types between ULP and Stack * APIs types between ULP and Stack
*/ */
typedef enum typedef enum {
{
/* APIs from ULP to stack */ /* APIs from ULP to stack */
NW_GTPV2C_ULP_API_INITIAL_REQ = 0x00000000, /**< Send a initial message */ NW_GTPV2C_ULP_API_INITIAL_REQ = 0x00000000, /**< Send a initial message */
@@ -173,8 +171,7 @@ typedef enum
* Error information of incoming GTP messages * Error information of incoming GTP messages
*/ */
typedef struct NwGtpv2cErrorS typedef struct NwGtpv2cErrorS {
{
NW_IN NwU8T cause; NW_IN NwU8T cause;
NW_IN NwU8T flags; NW_IN NwU8T flags;
struct { struct {
@@ -183,13 +180,12 @@ typedef struct NwGtpv2cErrorS
} offendingIe; } offendingIe;
} NwGtpv2cErrorT; } NwGtpv2cErrorT;
/** /**
* API information elements between ULP and Stack for * API information elements between ULP and Stack for
* sending a Gtpv2c initial message. * sending a Gtpv2c initial message.
*/ */
typedef struct typedef struct {
{
NW_INOUT NwGtpv2cTunnelHandleT hTunnel; /**< Tunnel handle over which the mesasge is to be sent.*/ NW_INOUT NwGtpv2cTunnelHandleT hTunnel; /**< Tunnel handle over which the mesasge is to be sent.*/
NW_IN NwU16T t3Timer; NW_IN NwU16T t3Timer;
NW_IN NwU16T maxRetries; NW_IN NwU16T maxRetries;
@@ -200,13 +196,12 @@ typedef struct
NW_IN NwGtpv2cUlpTunnelHandleT hUlpTunnel; /**< Required only in case when hTunnel == 0 */ NW_IN NwGtpv2cUlpTunnelHandleT hUlpTunnel; /**< Required only in case when hTunnel == 0 */
} NwGtpv2cInitialReqInfoT; } NwGtpv2cInitialReqInfoT;
/** /**
* API information elements between ULP and Stack for * API information elements between ULP and Stack for
* sending a Gtpv2c triggered request message. * sending a Gtpv2c triggered request message.
*/ */
typedef struct typedef struct {
{
NW_IN NwGtpv2cTunnelHandleT hTunnel; /**< Tunnel handle over which the mesasge is to be sent */ 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 NwGtpv2cTrxnHandleT hTrxn; /**< Request Trxn handle which to which triggered req is being sent */
NW_IN NwU16T t3Timer; NW_IN NwU16T t3Timer;
@@ -218,28 +213,26 @@ typedef struct
} NwGtpv2cTriggeredReqInfoT; } NwGtpv2cTriggeredReqInfoT;
/** /**
* API information elements between ULP and Stack for * API information elements between ULP and Stack for
* sending a Gtpv2c triggered response message. * sending a Gtpv2c triggered response message.
*/ */
typedef struct typedef struct {
{
NW_IN NwGtpv2cTrxnHandleT hTrxn; /**< Request Trxn handle which to which triggered rsp is being sent */ 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 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_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_OUT NwGtpv2cTunnelHandleT hTunnel; /**< Returned only in case flags is set to
NW_GTPV2C_ULP_API_FLAG_CREATE_LOCAL_TUNNEL */ NW_GTPV2C_ULP_API_FLAG_CREATE_LOCAL_TUNNEL */
} NwGtpv2cTriggeredRspInfoT; } NwGtpv2cTriggeredRspInfoT;
/** /**
* API information elements between ULP and Stack for * API information elements between ULP and Stack for
* sending a Gtpv2c initial message. * sending a Gtpv2c initial message.
*/ */
typedef struct typedef struct {
{
NW_IN NwGtpv2cErrorT error; NW_IN NwGtpv2cErrorT error;
NW_IN NwGtpv2cTrxnHandleT hTrxn; NW_IN NwGtpv2cTrxnHandleT hTrxn;
NW_IN NwGtpv2cUlpTrxnHandleT hUlpTrxn; NW_IN NwGtpv2cUlpTrxnHandleT hUlpTrxn;
@@ -250,13 +243,12 @@ typedef struct
NW_INOUT NwGtpv2cTunnelHandleT hTunnel; NW_INOUT NwGtpv2cTunnelHandleT hTunnel;
} NwGtpv2cInitialReqIndInfoT; } NwGtpv2cInitialReqIndInfoT;
/** /**
* API information elements between ULP and Stack for * API information elements between ULP and Stack for
* sending a Gtpv2c triggered request message. * sending a Gtpv2c triggered request message.
*/ */
typedef struct typedef struct {
{
NW_IN NwGtpv2cErrorT error; NW_IN NwGtpv2cErrorT error;
NW_IN NwGtpv2cTrxnHandleT hTrxn; NW_IN NwGtpv2cTrxnHandleT hTrxn;
NW_IN NwGtpv2cUlpTrxnHandleT hUlpTrxn; NW_IN NwGtpv2cUlpTrxnHandleT hUlpTrxn;
@@ -267,37 +259,34 @@ typedef struct
NW_IN NwGtpv2cUlpTunnelHandleT hUlpTunnel; NW_IN NwGtpv2cUlpTunnelHandleT hUlpTunnel;
} NwGtpv2cTriggeredReqIndInfoT; } NwGtpv2cTriggeredReqIndInfoT;
/** /**
* API information elements between ULP and Stack for * API information elements between ULP and Stack for
* sending a Gtpv2c triggered response message. * sending a Gtpv2c triggered response message.
*/ */
typedef struct typedef struct {
{
NW_IN NwGtpv2cErrorT error; NW_IN NwGtpv2cErrorT error;
NW_IN NwGtpv2cUlpTrxnHandleT hUlpTrxn; NW_IN NwGtpv2cUlpTrxnHandleT hUlpTrxn;
NW_IN NwGtpv2cUlpTunnelHandleT hUlpTunnel; NW_IN NwGtpv2cUlpTunnelHandleT hUlpTunnel;
NW_IN NwGtpv2cMsgTypeT msgType; NW_IN NwGtpv2cMsgTypeT msgType;
} NwGtpv2cTriggeredRspIndInfoT; } NwGtpv2cTriggeredRspIndInfoT;
/** /**
* API information elements between ULP and Stack for * API information elements between ULP and Stack for
* receving a path failure indication from stack. * receving a path failure indication from stack.
*/ */
typedef struct typedef struct {
{
NW_IN NwGtpv2cUlpTrxnHandleT hUlpTrxn; NW_IN NwGtpv2cUlpTrxnHandleT hUlpTrxn;
NW_IN NwGtpv2cUlpTunnelHandleT hUlpTunnel; NW_IN NwGtpv2cUlpTunnelHandleT hUlpTunnel;
} NwGtpv2cRspFailureIndInfoT; } NwGtpv2cRspFailureIndInfoT;
/** /**
* API information elements between ULP and Stack for * API information elements between ULP and Stack for
* creating local tunnel. * creating local tunnel.
*/ */
typedef struct typedef struct {
{
NW_OUT NwGtpv2cTunnelHandleT hTunnel; NW_OUT NwGtpv2cTunnelHandleT hTunnel;
NW_IN NwGtpv2cUlpTunnelHandleT hUlpTunnel; NW_IN NwGtpv2cUlpTunnelHandleT hUlpTunnel;
NW_IN NwU32T teidLocal; NW_IN NwU32T teidLocal;
@@ -305,27 +294,24 @@ typedef struct
} NwGtpv2cCreateLocalTunnelInfoT; } NwGtpv2cCreateLocalTunnelInfoT;
/** /**
* API information elements between ULP and Stack for * API information elements between ULP and Stack for
* deleting a local tunnel. * deleting a local tunnel.
*/ */
typedef struct typedef struct {
{
NW_IN NwGtpv2cTunnelHandleT hTunnel; NW_IN NwGtpv2cTunnelHandleT hTunnel;
} NwGtpv2cDeleteLocalTunnelInfoT; } NwGtpv2cDeleteLocalTunnelInfoT;
/** /**
* API container structure between ULP and Stack. * API container structure between ULP and Stack.
*/ */
typedef struct typedef struct {
{
NwGtpv2cUlpApiTypeT apiType; /**< First bytes of this field is used as flag holder */ NwGtpv2cUlpApiTypeT apiType; /**< First bytes of this field is used as flag holder */
NwGtpv2cMsgHandleT hMsg; /**< Handle associated with this API */ NwGtpv2cMsgHandleT hMsg; /**< Handle associated with this API */
union union {
{
NwGtpv2cInitialReqInfoT initialReqInfo; NwGtpv2cInitialReqInfoT initialReqInfo;
NwGtpv2cTriggeredRspInfoT triggeredRspInfo; NwGtpv2cTriggeredRspInfoT triggeredRspInfo;
NwGtpv2cTriggeredReqInfoT triggeredReqInfo; NwGtpv2cTriggeredReqInfoT triggeredReqInfo;
@@ -347,10 +333,9 @@ typedef struct
* Gtpv2c ULP entity definition * Gtpv2c ULP entity definition
*/ */
typedef struct typedef struct {
{
NwGtpv2cUlpHandleT hUlp; NwGtpv2cUlpHandleT hUlp;
NwRcT (*ulpReqCallback) ( NW_IN NwGtpv2cUlpHandleT hUlp, NwRcT (*ulpReqCallback) ( NW_IN NwGtpv2cUlpHandleT hUlp,
NW_IN NwGtpv2cUlpApiT *pUlpApi); NW_IN NwGtpv2cUlpApiT *pUlpApi);
} NwGtpv2cUlpEntityT; } NwGtpv2cUlpEntityT;
@@ -359,11 +344,10 @@ typedef struct
* Gtpv2c UDP entity definition * Gtpv2c UDP entity definition
*/ */
typedef struct typedef struct {
{
NwGtpv2cUdpHandleT hUdp; NwGtpv2cUdpHandleT hUdp;
NwRcT (*udpDataReqCallback) ( NW_IN NwGtpv2cUdpHandleT udpHandle, NwRcT (*udpDataReqCallback) ( NW_IN NwGtpv2cUdpHandleT udpHandle,
NW_IN NwU8T* dataBuf, NW_IN NwU8T* dataBuf,
NW_IN NwU32T dataSize, NW_IN NwU32T dataSize,
NW_IN NwU32T peerIp, NW_IN NwU32T peerIp,
NW_IN NwU32T peerPort); NW_IN NwU32T peerPort);
@@ -373,15 +357,14 @@ typedef struct
* Gtpv2c Memory Manager entity definition * Gtpv2c Memory Manager entity definition
*/ */
typedef struct typedef struct {
{
NwGtpv2cMemMgrHandleT hMemMgr; NwGtpv2cMemMgrHandleT hMemMgr;
void* (*memAlloc)( NW_IN NwGtpv2cMemMgrHandleT hMemMgr, void* (*memAlloc)( NW_IN NwGtpv2cMemMgrHandleT hMemMgr,
NW_IN NwU32T memSize, NW_IN NwU32T memSize,
NW_IN NwCharT* fileName, NW_IN NwCharT* fileName,
NW_IN NwU32T lineNumber); NW_IN NwU32T lineNumber);
void (*memFree) ( NW_IN NwGtpv2cMemMgrHandleT hMemMgr, void (*memFree) ( NW_IN NwGtpv2cMemMgrHandleT hMemMgr,
NW_IN void* hMem, NW_IN void* hMem,
NW_IN NwCharT* fileName, NW_IN NwCharT* fileName,
NW_IN NwU32T lineNumber); NW_IN NwU32T lineNumber);
@@ -394,17 +377,16 @@ typedef struct
* Gtpv2c Timer Manager entity definition * Gtpv2c Timer Manager entity definition
*/ */
typedef struct typedef struct {
{
NwGtpv2cTimerMgrHandleT tmrMgrHandle; NwGtpv2cTimerMgrHandleT tmrMgrHandle;
NwRcT (*tmrStartCallback)( NW_IN NwGtpv2cTimerMgrHandleT tmrMgrHandle, NwRcT (*tmrStartCallback)( NW_IN NwGtpv2cTimerMgrHandleT tmrMgrHandle,
NW_IN NwU32T timeoutSec, NW_IN NwU32T timeoutSec,
NW_IN NwU32T timeoutUsec, NW_IN NwU32T timeoutUsec,
NW_IN NwU32T tmrType, NW_IN NwU32T tmrType,
NW_IN void* tmrArg, NW_IN void* tmrArg,
NW_OUT NwGtpv2cTimerHandleT* tmrHandle); NW_OUT NwGtpv2cTimerHandleT* tmrHandle);
NwRcT (*tmrStopCallback) ( NW_IN NwGtpv2cTimerMgrHandleT tmrMgrHandle, NwRcT (*tmrStopCallback) ( NW_IN NwGtpv2cTimerMgrHandleT tmrMgrHandle,
NW_IN NwGtpv2cTimerHandleT tmrHandle); NW_IN NwGtpv2cTimerHandleT tmrHandle);
} NwGtpv2cTimerMgrEntityT; } NwGtpv2cTimerMgrEntityT;
@@ -412,10 +394,9 @@ typedef struct
* Gtpv2c Log manager entity definition * Gtpv2c Log manager entity definition
*/ */
typedef struct typedef struct {
{
NwGtpv2cLogMgrHandleT logMgrHandle; NwGtpv2cLogMgrHandleT logMgrHandle;
NwRcT (*logReqCallback) (NW_IN NwGtpv2cLogMgrHandleT logMgrHandle, NwRcT (*logReqCallback) (NW_IN NwGtpv2cLogMgrHandleT logMgrHandle,
NW_IN NwU32T logLevel, NW_IN NwU32T logLevel,
NW_IN NwCharT* filename, NW_IN NwCharT* filename,
NW_IN NwU32T line, NW_IN NwU32T line,
@@ -430,8 +411,8 @@ typedef struct
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
/** /**
Constructor. Initialize nw-gtpv2c stack instance. Constructor. Initialize nw-gtpv2c stack instance.
@param[in,out] phGtpcStackHandle : Pointer to stack instance handle @param[in,out] phGtpcStackHandle : Pointer to stack instance handle
@@ -440,7 +421,7 @@ extern "C" {
NwRcT NwRcT
nwGtpv2cInitialize( NW_INOUT NwGtpv2cStackHandleT* phGtpcStackHandle); nwGtpv2cInitialize( NW_INOUT NwGtpv2cStackHandleT* phGtpcStackHandle);
/** /**
Destructor. Destroy nw-gtpv2c stack instance . Destructor. Destroy nw-gtpv2c stack instance .
@param[in] hGtpcStackHandle : Stack instance handle @param[in] hGtpcStackHandle : Stack instance handle
@@ -449,7 +430,7 @@ nwGtpv2cInitialize( NW_INOUT NwGtpv2cStackHandleT* phGtpcStackHandle);
NwRcT NwRcT
nwGtpv2cFinalize( NW_IN NwGtpv2cStackHandleT hGtpcStackHandle); nwGtpv2cFinalize( NW_IN NwGtpv2cStackHandleT hGtpcStackHandle);
/** /**
Set Configuration for the nw-gtpv2c stack. Set Configuration for the nw-gtpv2c stack.
@param[in,out] phGtpcStackHandle : Pointer to stack handle @param[in,out] phGtpcStackHandle : Pointer to stack handle
@@ -458,7 +439,7 @@ nwGtpv2cFinalize( NW_IN NwGtpv2cStackHandleT hGtpcStackHandle);
NwRcT NwRcT
nwGtpv2cConfigSet( NW_IN NwGtpv2cStackHandleT* phGtpcStackHandle, NW_IN NwGtpv2cStackConfigT* pConfig); nwGtpv2cConfigSet( NW_IN NwGtpv2cStackHandleT* phGtpcStackHandle, NW_IN NwGtpv2cStackConfigT* pConfig);
/** /**
Get Configuration for the nw-gtpv2c stack. Get Configuration for the nw-gtpv2c stack.
@param[in,out] phGtpcStackHandle : Pointer to stack handle @param[in,out] phGtpcStackHandle : Pointer to stack handle
@@ -467,7 +448,7 @@ nwGtpv2cConfigSet( NW_IN NwGtpv2cStackHandleT* phGtpcStackHandle, NW_IN NwGtpv2c
NwRcT NwRcT
nwGtpv2cConfigGet( NW_IN NwGtpv2cStackHandleT* phGtpcStackHandle, NW_OUT NwGtpv2cStackConfigT* pConfig); nwGtpv2cConfigGet( NW_IN NwGtpv2cStackHandleT* phGtpcStackHandle, NW_OUT NwGtpv2cStackConfigT* pConfig);
/** /**
Set ULP entity for the stack. Set ULP entity for the stack.
@param[in] hGtpcStackHandle : Stack handle @param[in] hGtpcStackHandle : Stack handle
@@ -477,9 +458,9 @@ nwGtpv2cConfigGet( NW_IN NwGtpv2cStackHandleT* phGtpcStackHandle, NW_OUT NwGtpv2
NwRcT NwRcT
nwGtpv2cSetUlpEntity( NW_IN NwGtpv2cStackHandleT hGtpcStackHandle, nwGtpv2cSetUlpEntity( NW_IN NwGtpv2cStackHandleT hGtpcStackHandle,
NW_IN NwGtpv2cUlpEntityT* pUlpEntity); NW_IN NwGtpv2cUlpEntityT* pUlpEntity);
/** /**
Set UDP entity for the stack. Set UDP entity for the stack.
@param[in] hGtpcStackHandle : Stack handle @param[in] hGtpcStackHandle : Stack handle
@@ -489,9 +470,9 @@ nwGtpv2cSetUlpEntity( NW_IN NwGtpv2cStackHandleT hGtpcStackHandle,
NwRcT NwRcT
nwGtpv2cSetUdpEntity( NW_IN NwGtpv2cStackHandleT hGtpcStackHandle, nwGtpv2cSetUdpEntity( NW_IN NwGtpv2cStackHandleT hGtpcStackHandle,
NW_IN NwGtpv2cUdpEntityT* pUdpEntity); NW_IN NwGtpv2cUdpEntityT* pUdpEntity);
/** /**
Set MemMgr entity for the stack. Set MemMgr entity for the stack.
@param[in] hGtpcStackHandle : Stack handle @param[in] hGtpcStackHandle : Stack handle
@@ -501,10 +482,10 @@ nwGtpv2cSetUdpEntity( NW_IN NwGtpv2cStackHandleT hGtpcStackHandle,
NwRcT NwRcT
nwGtpv2cSetMemMgrEntity( NW_IN NwGtpv2cStackHandleT hGtpcStackHandle, nwGtpv2cSetMemMgrEntity( NW_IN NwGtpv2cStackHandleT hGtpcStackHandle,
NW_IN NwGtpv2cMemMgrEntityT* pMemMgr); NW_IN NwGtpv2cMemMgrEntityT* pMemMgr);
/** /**
Set TmrMgr entity for the stack. Set TmrMgr entity for the stack.
@param[in] hGtpcStackHandle : Stack handle @param[in] hGtpcStackHandle : Stack handle
@@ -514,9 +495,9 @@ nwGtpv2cSetMemMgrEntity( NW_IN NwGtpv2cStackHandleT hGtpcStackHandle,
NwRcT NwRcT
nwGtpv2cSetTimerMgrEntity( NW_IN NwGtpv2cStackHandleT hGtpcStackHandle, nwGtpv2cSetTimerMgrEntity( NW_IN NwGtpv2cStackHandleT hGtpcStackHandle,
NW_IN NwGtpv2cTimerMgrEntityT* pTmrMgr); NW_IN NwGtpv2cTimerMgrEntityT* pTmrMgr);
/** /**
Set LogMgr entity for the stack. Set LogMgr entity for the stack.
@param[in] hGtpcStackHandle : Stack handle @param[in] hGtpcStackHandle : Stack handle
@@ -526,9 +507,9 @@ nwGtpv2cSetTimerMgrEntity( NW_IN NwGtpv2cStackHandleT hGtpcStackHandle,
NwRcT NwRcT
nwGtpv2cSetLogMgrEntity( NW_IN NwGtpv2cStackHandleT hGtpcStackHandle, nwGtpv2cSetLogMgrEntity( NW_IN NwGtpv2cStackHandleT hGtpcStackHandle,
NW_IN NwGtpv2cLogMgrEntityT* pLogMgr); NW_IN NwGtpv2cLogMgrEntityT* pLogMgr);
/** /**
Set log level for the stack. Set log level for the stack.
@param[in] hGtpcStackHandle : Stack handle @param[in] hGtpcStackHandle : Stack handle
@@ -552,12 +533,12 @@ nwGtpv2cSetLogLevel( NW_IN NwGtpv2cStackHandleT hGtpcStackHandle,
@return NW_OK on success. @return NW_OK on success.
*/ */
NwRcT NwRcT
nwGtpv2cProcessUdpReq( NW_IN NwGtpv2cStackHandleT hGtpcStackHandle, nwGtpv2cProcessUdpReq( NW_IN NwGtpv2cStackHandleT hGtpcStackHandle,
NW_IN NwU8T* udpData, NW_IN NwU8T* udpData,
NW_IN NwU32T udpDataLen, NW_IN NwU32T udpDataLen,
NW_IN NwU16T peerPort, NW_IN NwU16T peerPort,
NW_IN NwU32T peerIP); NW_IN NwU32T peerIP);
/** /**
Process Request from ULP entity. Process Request from ULP entity.
@@ -569,7 +550,7 @@ nwGtpv2cProcessUdpReq( NW_IN NwGtpv2cStackHandleT hGtpcStackHandle,
NwRcT NwRcT
nwGtpv2cProcessUlpReq( NW_IN NwGtpv2cStackHandleT hGtpcStackHandle, nwGtpv2cProcessUlpReq( NW_IN NwGtpv2cStackHandleT hGtpcStackHandle,
NW_IN NwGtpv2cUlpApiT *ulpReq); NW_IN NwGtpv2cUlpApiT *ulpReq);
/** /**
@@ -1,6 +1,6 @@
/*----------------------------------------------------------------------------* /*----------------------------------------------------------------------------*
* * * *
* n w - g t p v 2 c * * 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 * * 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 *
* * * *
* * * *
@@ -31,7 +31,7 @@
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
/** /**
* @file NwGtpv2cIe.h * @file NwGtpv2cIe.h
* @brief This header file contains Information Element definitions for GTPv2c * @brief This header file contains Information Element definitions for GTPv2c
* as per 3GPP TS 29274-930. * as per 3GPP TS 29274-930.
@@ -130,14 +130,14 @@
* 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 * * 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_REQUEST_ACCEPTED (16)
#define NW_GTPV2C_CAUSE_INVALID_LENGTH (67) #define NW_GTPV2C_CAUSE_INVALID_LENGTH (67)
#define NW_GTPV2C_CAUSE_MANDATORY_IE_INCORRECT (69) #define NW_GTPV2C_CAUSE_MANDATORY_IE_INCORRECT (69)
#define NW_GTPV2C_CAUSE_MANDATORY_IE_MISSING (70) #define NW_GTPV2C_CAUSE_MANDATORY_IE_MISSING (70)
#define NW_GTPV2C_CAUSE_SYSTEM_FAILURE (72) #define NW_GTPV2C_CAUSE_SYSTEM_FAILURE (72)
#define NW_GTPV2C_CAUSE_REQUEST_REJECTED (94) #define NW_GTPV2C_CAUSE_REQUEST_REJECTED (94)
#define NW_GTPV2C_CAUSE_REMOTE_PEER_NOT_RESPONDING (100) #define NW_GTPV2C_CAUSE_REMOTE_PEER_NOT_RESPONDING (100)
#define NW_GTPV2C_CAUSE_CONDITIONAL_IE_MISSING (103) #define NW_GTPV2C_CAUSE_CONDITIONAL_IE_MISSING (103)
#define NW_GTPV2C_IE_INSTANCE_ZERO (0) #define NW_GTPV2C_IE_INSTANCE_ZERO (0)
#define NW_GTPV2C_IE_INSTANCE_ONE (1) #define NW_GTPV2C_IE_INSTANCE_ONE (1)
@@ -1,6 +1,6 @@
/*----------------------------------------------------------------------------* /*----------------------------------------------------------------------------*
* * * *
* n w - g t p v 2 c * * 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 * * 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 *
* * * *
* * * *
@@ -37,7 +37,7 @@
#include "NwTypes.h" #include "NwTypes.h"
#include "NwGtpv2c.h" #include "NwGtpv2c.h"
/** /**
* @file NwGtpv2cMsg.h * @file NwGtpv2cMsg.h
* @brief This file defines APIs for to build new outgoing gtpv2c messages and to parse incoming messages. * @brief This file defines APIs for to build new outgoing gtpv2c messages and to parse incoming messages.
*/ */
@@ -185,40 +185,35 @@ extern "C" {
#pragma pack(1) #pragma pack(1)
typedef struct NwGtpv2cIeTv1 typedef struct NwGtpv2cIeTv1 {
{
NwU8T t; NwU8T t;
NwU16T l; NwU16T l;
NwU8T i; NwU8T i;
NwU8T v; NwU8T v;
} NwGtpv2cIeTv1T; } NwGtpv2cIeTv1T;
typedef struct NwGtpv2cIeTv2 typedef struct NwGtpv2cIeTv2 {
{
NwU8T t; NwU8T t;
NwU16T l; NwU16T l;
NwU8T i; NwU8T i;
NwU16T v; NwU16T v;
} NwGtpv2cIeTv2T; } NwGtpv2cIeTv2T;
typedef struct NwGtpv2cIeTv4 typedef struct NwGtpv2cIeTv4 {
{
NwU8T t; NwU8T t;
NwU16T l; NwU16T l;
NwU8T i; NwU8T i;
NwU32T v; NwU32T v;
} NwGtpv2cIeTv4T; } NwGtpv2cIeTv4T;
typedef struct NwGtpv2cIeTv8 typedef struct NwGtpv2cIeTv8 {
{
NwU8T t; NwU8T t;
NwU16T l; NwU16T l;
NwU8T i; NwU8T i;
NwU64T v; NwU64T v;
} NwGtpv2cIeTv8T; } NwGtpv2cIeTv8T;
typedef struct NwGtpv2cIeTlv typedef struct NwGtpv2cIeTlv {
{
NwU8T t; NwU8T t;
NwU16T l; NwU16T l;
NwU8T i; NwU8T i;
@@ -227,16 +222,16 @@ typedef struct NwGtpv2cIeTlv
#pragma pack() #pragma pack()
/** /**
* Allocate a gtpv2c message. * Allocate a gtpv2c message.
* *
* @param[in] hGtpcStackHandle : gtpv2c stack handle. * @param[in] hGtpcStackHandle : gtpv2c stack handle.
* @param[in] teidPresent : TEID is present flag. * @param[in] teidPresent : TEID is present flag.
* @param[in] msgType : Message type for this message. * @param[in] msgType : Message type for this message.
* @param[in] teid : TEID for this message. * @param[in] teid : TEID for this message.
* @param[in] seqNum : Sequence number for this message. * @param[in] seqNum : Sequence number for this message.
* @param[out] phMsg : Pointer to message handle. * @param[out] phMsg : Pointer to message handle.
*/ */
NwRcT NwRcT
nwGtpv2cMsgNew( NW_IN NwGtpv2cStackHandleT hGtpcStackHandle, nwGtpv2cMsgNew( NW_IN NwGtpv2cStackHandleT hGtpcStackHandle,
@@ -247,363 +242,363 @@ nwGtpv2cMsgNew( NW_IN NwGtpv2cStackHandleT hGtpcStackHandle,
NW_OUT NwGtpv2cMsgHandleT *phMsg); NW_OUT NwGtpv2cMsgHandleT *phMsg);
/** /**
* Allocate a gtpv2c message from data buffer. * Allocate a gtpv2c message from data buffer.
* *
* @param[in] hGtpcStackHandle : gtpv2c stack handle. * @param[in] hGtpcStackHandle : gtpv2c stack handle.
* @param[in] pBuf: Buffer to be copied in this message. * @param[in] pBuf: Buffer to be copied in this message.
* @param[in] bufLen: Buffer length to be copied in this message. * @param[in] bufLen: Buffer length to be copied in this message.
* @param[out] phMsg : Pointer to message handle. * @param[out] phMsg : Pointer to message handle.
*/ */
NwRcT NwRcT
nwGtpv2cMsgFromBufferNew( NW_IN NwGtpv2cStackHandleT hGtpcStackHandle, nwGtpv2cMsgFromBufferNew( NW_IN NwGtpv2cStackHandleT hGtpcStackHandle,
NW_IN NwU8T* pBuf, NW_IN NwU8T* pBuf,
NW_IN NwU32T bufLen, NW_IN NwU32T bufLen,
NW_OUT NwGtpv2cMsgHandleT *phMsg); NW_OUT NwGtpv2cMsgHandleT *phMsg);
/** /**
* Free a gtpv2c message. * Free a gtpv2c message.
* *
* @param[in] hGtpcStackHandle : gtpv2c stack handle. * @param[in] hGtpcStackHandle : gtpv2c stack handle.
* @param[in] hMsg : Message handle. * @param[in] hMsg : Message handle.
*/ */
NwRcT NwRcT
nwGtpv2cMsgDelete( NW_IN NwGtpv2cStackHandleT hGtpcStackHandle, nwGtpv2cMsgDelete( NW_IN NwGtpv2cStackHandleT hGtpcStackHandle,
NW_IN NwGtpv2cMsgHandleT hMsg); NW_IN NwGtpv2cMsgHandleT hMsg);
/** /**
* Set TEID for gtpv2c message. * Set TEID for gtpv2c message.
* *
* @param[in] hMsg : Message handle. * @param[in] hMsg : Message handle.
* @param[in] teid: TEID value. * @param[in] teid: TEID value.
*/ */
NwRcT NwRcT
nwGtpv2cMsgSetTeid(NW_IN NwGtpv2cMsgHandleT hMsg, NwU32T teid); nwGtpv2cMsgSetTeid(NW_IN NwGtpv2cMsgHandleT hMsg, NwU32T teid);
/** /**
* Set TEID present flag for gtpv2c message. * Set TEID present flag for gtpv2c message.
* *
* @param[in] hMsg : Message handle. * @param[in] hMsg : Message handle.
* @param[in] teidPesent: Flag boolean value. * @param[in] teidPesent: Flag boolean value.
*/ */
NwRcT NwRcT
nwGtpv2cMsgSetTeidPresent(NW_IN NwGtpv2cMsgHandleT hMsg, NwBoolT teidPresent); nwGtpv2cMsgSetTeidPresent(NW_IN NwGtpv2cMsgHandleT hMsg, NwBoolT teidPresent);
/** /**
* Set sequence for gtpv2c message. * Set sequence for gtpv2c message.
* *
* @param[in] hMsg : Message handle. * @param[in] hMsg : Message handle.
* @param[in] seqNum: Flag boolean value. * @param[in] seqNum: Flag boolean value.
*/ */
NwRcT NwRcT
nwGtpv2cMsgSetSeqNumber(NW_IN NwGtpv2cMsgHandleT hMsg, NwU32T seqNum); nwGtpv2cMsgSetSeqNumber(NW_IN NwGtpv2cMsgHandleT hMsg, NwU32T seqNum);
/** /**
* Get TEID present for gtpv2c message. * Get TEID present for gtpv2c message.
* *
* @param[in] hMsg : Message handle. * @param[in] hMsg : Message handle.
*/ */
NwU32T NwU32T
nwGtpv2cMsgGetTeid(NW_IN NwGtpv2cMsgHandleT hMsg); nwGtpv2cMsgGetTeid(NW_IN NwGtpv2cMsgHandleT hMsg);
/** /**
* Get TEID present for gtpv2c message. * Get TEID present for gtpv2c message.
* *
* @param[in] hMsg : Message handle. * @param[in] hMsg : Message handle.
*/ */
NwBoolT NwBoolT
nwGtpv2cMsgGetTeidPresent(NW_IN NwGtpv2cMsgHandleT hMsg); nwGtpv2cMsgGetTeidPresent(NW_IN NwGtpv2cMsgHandleT hMsg);
/** /**
* Get sequence number for gtpv2c message. * Get sequence number for gtpv2c message.
* *
* @param[in] hMsg : Message handle. * @param[in] hMsg : Message handle.
*/ */
NwU32T NwU32T
nwGtpv2cMsgGetSeqNumber(NW_IN NwGtpv2cMsgHandleT hMsg); nwGtpv2cMsgGetSeqNumber(NW_IN NwGtpv2cMsgHandleT hMsg);
/** /**
* Get msg lenght for gtpv2c message. * Get msg lenght for gtpv2c message.
* *
* @param[in] hMsg : Message handle. * @param[in] hMsg : Message handle.
*/ */
NwU32T NwU32T
nwGtpv2cMsgGetLength(NW_IN NwGtpv2cMsgHandleT hMsg); nwGtpv2cMsgGetLength(NW_IN NwGtpv2cMsgHandleT hMsg);
/** /**
* Add a gtpv2c information element of length 1 to gtpv2c message. * Add a gtpv2c information element of length 1 to gtpv2c message.
* *
* @param[in] hMsg : Handle to gtpv2c message. * @param[in] hMsg : Handle to gtpv2c message.
* @param[in] type : IE type. * @param[in] type : IE type.
* @param[in] instance : IE instance. * @param[in] instance : IE instance.
* @param[in] value : IE value. * @param[in] value : IE value.
*/ */
NwRcT NwRcT
nwGtpv2cMsgAddIeTV1(NW_IN NwGtpv2cMsgHandleT hMsg, nwGtpv2cMsgAddIeTV1(NW_IN NwGtpv2cMsgHandleT hMsg,
NW_IN NwU8T type, NW_IN NwU8T type,
NW_IN NwU8T instance, NW_IN NwU8T instance,
NW_IN NwU8T value); NW_IN NwU8T value);
/** /**
* Add a gtpv2c information element of length 2 to gtpv2c message. * Add a gtpv2c information element of length 2 to gtpv2c message.
* *
* @param[in] hMsg : Handle to gtpv2c message. * @param[in] hMsg : Handle to gtpv2c message.
* @param[in] type : IE type. * @param[in] type : IE type.
* @param[in] instance : IE instance. * @param[in] instance : IE instance.
* @param[in] value : IE value. * @param[in] value : IE value.
*/ */
NwRcT NwRcT
nwGtpv2cMsgAddIeTV2(NW_IN NwGtpv2cMsgHandleT hMsg, nwGtpv2cMsgAddIeTV2(NW_IN NwGtpv2cMsgHandleT hMsg,
NW_IN NwU8T type, NW_IN NwU8T type,
NW_IN NwU8T instance, NW_IN NwU8T instance,
NW_IN NwU16T value); NW_IN NwU16T value);
/** /**
* Add a gtpv2c information element of length 4 to gtpv2c message. * Add a gtpv2c information element of length 4 to gtpv2c message.
* *
* @param[in] hMsg : Handle to gtpv2c message. * @param[in] hMsg : Handle to gtpv2c message.
* @param[in] type : IE type. * @param[in] type : IE type.
* @param[in] instance : IE instance. * @param[in] instance : IE instance.
* @param[in] value : IE value. * @param[in] value : IE value.
*/ */
NwRcT NwRcT
nwGtpv2cMsgAddIeTV4(NW_IN NwGtpv2cMsgHandleT hMsg, nwGtpv2cMsgAddIeTV4(NW_IN NwGtpv2cMsgHandleT hMsg,
NW_IN NwU8T type, NW_IN NwU8T type,
NW_IN NwU8T instance, NW_IN NwU8T instance,
NW_IN NwU32T value); NW_IN NwU32T value);
/** /**
* Add a gtpv2c information element of variable length to gtpv2c message. * Add a gtpv2c information element of variable length to gtpv2c message.
* *
* @param[in] hMsg : Handle to gtpv2c message. * @param[in] hMsg : Handle to gtpv2c message.
* @param[in] type : IE type. * @param[in] type : IE type.
* @param[in] length : IE length. * @param[in] length : IE length.
* @param[in] instance : IE instance. * @param[in] instance : IE instance.
* @param[in] value : IE value. * @param[in] value : IE value.
*/ */
NwRcT NwRcT
nwGtpv2cMsgAddIe(NW_IN NwGtpv2cMsgHandleT hMsg, nwGtpv2cMsgAddIe(NW_IN NwGtpv2cMsgHandleT hMsg,
NW_IN NwU8T type, NW_IN NwU8T type,
NW_IN NwU16T length, NW_IN NwU16T length,
NW_IN NwU8T instance, NW_IN NwU8T instance,
NW_IN NwU8T* pVal); NW_IN NwU8T* pVal);
/** /**
* Add CAUSE information element to gtpv2c message. * Add CAUSE information element to gtpv2c message.
* *
* @param[in] hMsg : Handle to gtpv2c message. * @param[in] hMsg : Handle to gtpv2c message.
* @param[in] instance : IE instance. * @param[in] instance : IE instance.
* @param[in] causeValue: Cause value. * @param[in] causeValue: Cause value.
* @param[in] bitFlags: PDN Connetiion IE Error Flag, Bearer Context IE Error Flag, Cause Source Flag. * @param[in] bitFlags: PDN Connetiion IE Error Flag, Bearer Context IE Error Flag, Cause Source Flag.
* @param[in] offendingIeType: Offending IE type. * @param[in] offendingIeType: Offending IE type.
* @param[in] offendingIeInstance: Offending IE instance. * @param[in] offendingIeInstance: Offending IE instance.
*/ */
NwRcT NwRcT
nwGtpv2cMsgAddIeCause(NW_IN NwGtpv2cMsgHandleT hMsg, nwGtpv2cMsgAddIeCause(NW_IN NwGtpv2cMsgHandleT hMsg,
NW_IN NwU8T instance, NW_IN NwU8T instance,
NW_IN NwU8T causeValue, NW_IN NwU8T causeValue,
NW_IN NwU8T bitFlags, NW_IN NwU8T bitFlags,
NW_IN NwU8T offendingIeType, NW_IN NwU8T offendingIeType,
NW_IN NwU8T offendingIeInstance); NW_IN NwU8T offendingIeInstance);
/** /**
* Add F-TEID information element to gtpv2c message. * Add F-TEID information element to gtpv2c message.
* *
* @param[in] hMsg : Handle to gtpv2c message. * @param[in] hMsg : Handle to gtpv2c message.
* @param[in] instance : IE instance. * @param[in] instance : IE instance.
* @param[in] ifType : Interface Type. * @param[in] ifType : Interface Type.
* @param[in] teidOrGreKey: TEID/ GRE Key * @param[in] teidOrGreKey: TEID/ GRE Key
* @param[in] ipv4Addr : Ipv4 Address in Network Byte Order. * @param[in] ipv4Addr : Ipv4 Address in Network Byte Order.
* @param[in] pIpv6Addr: Pointer to IPv6 Address in Network Byte Order. * @param[in] pIpv6Addr: Pointer to IPv6 Address in Network Byte Order.
*/ */
NwRcT NwRcT
nwGtpv2cMsgAddIeFteid(NW_IN NwGtpv2cMsgHandleT hMsg, nwGtpv2cMsgAddIeFteid(NW_IN NwGtpv2cMsgHandleT hMsg,
NW_IN NwU8T instance, NW_IN NwU8T instance,
NW_IN NwU8T ifType, NW_IN NwU8T ifType,
NW_IN NwU32T teidOrGreKey, NW_IN NwU32T teidOrGreKey,
NW_IN NwU32T ipv4Addr, NW_IN NwU32T ipv4Addr,
NW_IN NwU8T* pIpv6Addr); NW_IN NwU8T* pIpv6Addr);
NwRcT NwRcT
nwGtpv2cMsgGroupedIeStart(NW_IN NwGtpv2cMsgHandleT hMsg, nwGtpv2cMsgGroupedIeStart(NW_IN NwGtpv2cMsgHandleT hMsg,
NW_IN NwU8T type, NW_IN NwU8T type,
NW_IN NwU8T instance); NW_IN NwU8T instance);
NwRcT NwRcT
nwGtpv2cMsgGroupedIeEnd(NW_IN NwGtpv2cMsgHandleT hMsg); nwGtpv2cMsgGroupedIeEnd(NW_IN NwGtpv2cMsgHandleT hMsg);
/** /**
* Check if information element of type and instance is present * Check if information element of type and instance is present
* in gtpv2c message. * in gtpv2c message.
* *
* @param[in] hMsg : Handle to gtpv2c message. * @param[in] hMsg : Handle to gtpv2c message.
* @param[in] type : IE Type. * @param[in] type : IE Type.
* @param[in] instance : IE instance. * @param[in] instance : IE instance.
* @return NW_TRUE on success, NW_FALSE on failure. * @return NW_TRUE on success, NW_FALSE on failure.
*/ */
NwBoolT NwBoolT
nwGtpv2cMsgIsIePresent(NW_IN NwGtpv2cMsgHandleT hMsg, nwGtpv2cMsgIsIePresent(NW_IN NwGtpv2cMsgHandleT hMsg,
NW_IN NwU8T type, NW_IN NwU8T type,
NW_IN NwU8T instance); NW_IN NwU8T instance);
/** /**
* Get an information element of type 'NwU8T' from gtpv2c message. * Get an information element of type 'NwU8T' from gtpv2c message.
* *
* @param[in] hMsg : Handle to gtpv2c message. * @param[in] hMsg : Handle to gtpv2c message.
* @param[in] type : IE Type. * @param[in] type : IE Type.
* @param[in] instance : IE instance. * @param[in] instance : IE instance.
* @param[out] pVal : Pointer to value buffer. * @param[out] pVal : Pointer to value buffer.
* @return NW_OK on success. * @return NW_OK on success.
*/ */
NwRcT NwRcT
nwGtpv2cMsgGetIeTV1(NW_IN NwGtpv2cMsgHandleT hMsg, nwGtpv2cMsgGetIeTV1(NW_IN NwGtpv2cMsgHandleT hMsg,
NW_IN NwU8T type, NW_IN NwU8T type,
NW_IN NwU8T instance, NW_IN NwU8T instance,
NW_OUT NwU8T* pVal); NW_OUT NwU8T* pVal);
/** /**
* Get an information element of type 'NwU16T' from gtpv2c message. * Get an information element of type 'NwU16T' from gtpv2c message.
* *
* @param[in] hMsg : Handle to gtpv2c message. * @param[in] hMsg : Handle to gtpv2c message.
* @param[in] tyep : IE Type. * @param[in] tyep : IE Type.
* @param[in] instance : IE instance. * @param[in] instance : IE instance.
* @param[out] pVal : Pointer to value buffer. * @param[out] pVal : Pointer to value buffer.
* @return NW_OK on success. * @return NW_OK on success.
*/ */
NwRcT NwRcT
nwGtpv2cMsgGetIeTV2(NW_IN NwGtpv2cMsgHandleT hMsg, nwGtpv2cMsgGetIeTV2(NW_IN NwGtpv2cMsgHandleT hMsg,
NW_IN NwU8T type, NW_IN NwU8T type,
NW_IN NwU8T instance, NW_IN NwU8T instance,
NW_OUT NwU16T* pVal); NW_OUT NwU16T* pVal);
/** /**
* Get an information element of type 'NwU32T' from gtpv2c message. * Get an information element of type 'NwU32T' from gtpv2c message.
* *
* @param[in] hMsg : Handle to gtpv2c message. * @param[in] hMsg : Handle to gtpv2c message.
* @param[in] tyep : IE Type. * @param[in] tyep : IE Type.
* @param[in] instance : IE instance. * @param[in] instance : IE instance.
* @param[out] pVal : Pointer to value buffer. * @param[out] pVal : Pointer to value buffer.
* @return NW_OK on success. * @return NW_OK on success.
*/ */
NwRcT NwRcT
nwGtpv2cMsgGetIeTV4(NW_IN NwGtpv2cMsgHandleT hMsg, nwGtpv2cMsgGetIeTV4(NW_IN NwGtpv2cMsgHandleT hMsg,
NW_IN NwU8T type, NW_IN NwU8T type,
NW_IN NwU8T instance, NW_IN NwU8T instance,
NW_OUT NwU32T* pVal); NW_OUT NwU32T* pVal);
/** /**
* Get an information element of type 'NwU64T' from gtpv2c message. * Get an information element of type 'NwU64T' from gtpv2c message.
* *
* @param[in] hMsg : Handle to gtpv2c message. * @param[in] hMsg : Handle to gtpv2c message.
* @param[in] tyep : IE Type. * @param[in] tyep : IE Type.
* @param[in] instance : IE instance. * @param[in] instance : IE instance.
* @param[out] pVal : Pointer to IE value buffer. * @param[out] pVal : Pointer to IE value buffer.
* @return NW_OK on success. * @return NW_OK on success.
*/ */
NwRcT NwRcT
nwGtpv2cMsgGetIeTV8(NW_IN NwGtpv2cMsgHandleT hMsg, nwGtpv2cMsgGetIeTV8(NW_IN NwGtpv2cMsgHandleT hMsg,
NW_IN NwU8T type, NW_IN NwU8T type,
NW_IN NwU8T instance, NW_IN NwU8T instance,
NW_OUT NwU64T* pVal); NW_OUT NwU64T* pVal);
/** /**
* Get an information element of variable length from gtpv2c message. * Get an information element of variable length from gtpv2c message.
* *
* @param[in] hMsg : Handle to gtpv2c message. * @param[in] hMsg : Handle to gtpv2c message.
* @param[in] tyep : IE Type. * @param[in] tyep : IE Type.
* @param[in] instance : IE instance. * @param[in] instance : IE instance.
* @param[in] maxLen : Maximum length of IE. * @param[in] maxLen : Maximum length of IE.
* @param[out] pVal : Pointer to IE value buffer. * @param[out] pVal : Pointer to IE value buffer.
* @param[out] pLen : Pointer to IE length buffer. * @param[out] pLen : Pointer to IE length buffer.
* @return NW_OK on success. * @return NW_OK on success.
*/ */
NwRcT NwRcT
nwGtpv2cMsgGetIeTlv(NW_IN NwGtpv2cMsgHandleT hMsg, nwGtpv2cMsgGetIeTlv(NW_IN NwGtpv2cMsgHandleT hMsg,
NW_IN NwU8T type, NW_IN NwU8T type,
NW_IN NwU8T instance, NW_IN NwU8T instance,
NW_IN NwU16T maxLen, NW_IN NwU16T maxLen,
NW_OUT NwU8T* pVal, NW_OUT NwU8T* pVal,
NW_OUT NwU16T* pLen); NW_OUT NwU16T* pLen);
/** /**
* Get an information element of variable length from gtpv2c message. * Get an information element of variable length from gtpv2c message.
* *
* @param[in] hMsg : Handle to gtpv2c message. * @param[in] hMsg : Handle to gtpv2c message.
* @param[in] tyep : IE Type. * @param[in] tyep : IE Type.
* @param[in] instance : IE instance. * @param[in] instance : IE instance.
* @param[out] ppVal : Pointer to IE value buffer pointer. * @param[out] ppVal : Pointer to IE value buffer pointer.
* @param[out] pLen : Pointer to IE length buffer. * @param[out] pLen : Pointer to IE length buffer.
* @return NW_OK on success. * @return NW_OK on success.
*/ */
NwRcT NwRcT
nwGtpv2cMsgGetIeTlvP(NW_IN NwGtpv2cMsgHandleT hMsg, nwGtpv2cMsgGetIeTlvP(NW_IN NwGtpv2cMsgHandleT hMsg,
NW_IN NwU8T type, NW_IN NwU8T type,
NW_IN NwU8T instance, NW_IN NwU8T instance,
NW_OUT NwU8T** ppVal, NW_OUT NwU8T** ppVal,
NW_OUT NwU16T* pLen); NW_OUT NwU16T* pLen);
/** /**
* Get F-TEID information element to gtpv2c message. * Get F-TEID information element to gtpv2c message.
* *
* @param[in] hMsg : Handle to gtpv2c message. * @param[in] hMsg : Handle to gtpv2c message.
* @param[in] instance : IE instance. * @param[in] instance : IE instance.
* @param[out] ifType : Interface Type. * @param[out] ifType : Interface Type.
* @param[out] teidOrGreKey: TEID/ GRE Key * @param[out] teidOrGreKey: TEID/ GRE Key
* @param[out] ipv4Addr : Ipv4 Address in Network Byte Order. * @param[out] ipv4Addr : Ipv4 Address in Network Byte Order.
* @param[out] pIpv6Addr: Pointer to IPv6 Address in Network Byte Order. * @param[out] pIpv6Addr: Pointer to IPv6 Address in Network Byte Order.
*/ */
NwRcT NwRcT
nwGtpv2cMsgGetIeFteid(NW_IN NwGtpv2cMsgHandleT hMsg, nwGtpv2cMsgGetIeFteid(NW_IN NwGtpv2cMsgHandleT hMsg,
NW_IN NwU8T instance, NW_IN NwU8T instance,
NW_OUT NwU8T* ifType, NW_OUT NwU8T* ifType,
NW_OUT NwU32T* teidOrGreKey, NW_OUT NwU32T* teidOrGreKey,
NW_OUT NwU32T* ipv4Addr, NW_OUT NwU32T* ipv4Addr,
NW_OUT NwU8T* pIpv6Addr); NW_OUT NwU8T* pIpv6Addr);
NwRcT NwRcT
nwGtpv2cMsgGetIeCause(NW_IN NwGtpv2cMsgHandleT hMsg, nwGtpv2cMsgGetIeCause(NW_IN NwGtpv2cMsgHandleT hMsg,
NW_IN NwU8T instance, NW_IN NwU8T instance,
NW_OUT NwU8T* causeValue, NW_OUT NwU8T* causeValue,
NW_OUT NwU8T* flags, NW_OUT NwU8T* flags,
NW_OUT NwU8T* offendingIeType, NW_OUT NwU8T* offendingIeType,
NW_OUT NwU8T* offendingIeInstance); NW_OUT NwU8T* offendingIeInstance);
/** /**
* Get msg type for gtpv2c message. * Get msg type for gtpv2c message.
* *
* @param[in] hMsg : Message handle. * @param[in] hMsg : Message handle.
*/ */
NwU32T NwU32T
nwGtpv2cMsgGetMsgType(NW_IN NwGtpv2cMsgHandleT hMsg); nwGtpv2cMsgGetMsgType(NW_IN NwGtpv2cMsgHandleT hMsg);
@@ -1,6 +1,6 @@
/*----------------------------------------------------------------------------* /*----------------------------------------------------------------------------*
* * * *
* n w - g t p v 2 c * * 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 * * 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 *
* * * *
* * * *
@@ -39,13 +39,12 @@
#ifndef __NW_GTPV2C_MSG_PARSER_H__ #ifndef __NW_GTPV2C_MSG_PARSER_H__
#define __NW_GTPV2C_MSG_PARSER_H__ #define __NW_GTPV2C_MSG_PARSER_H__
/** /**
* @file NwGtpv2cMsgParser.h * @file NwGtpv2cMsgParser.h
* @brief This file defines APIs to parser gtpv2c messages. * @brief This file defines APIs to parser gtpv2c messages.
*/ */
typedef struct typedef struct {
{
NwU16T msgType; NwU16T msgType;
NwU16T mandatoryIeCount; NwU16T mandatoryIeCount;
NwGtpv2cStackHandleT hStack; NwGtpv2cStackHandleT hStack;
@@ -65,73 +64,73 @@ typedef struct
extern "C" { extern "C" {
#endif #endif
/** /**
* Allocate a gtpv2c message Parser. * Allocate a gtpv2c message Parser.
* *
* @param[in] hGtpcStackHandle : gtpv2c stack handle. * @param[in] hGtpcStackHandle : gtpv2c stack handle.
* @param[in] msgType : Message type for this message parser. * @param[in] msgType : Message type for this message parser.
* @param[out] pthiz : Pointer to message parser handle. * @param[out] pthiz : Pointer to message parser handle.
*/ */
NwRcT NwRcT
nwGtpv2cMsgParserNew( NW_IN NwGtpv2cStackHandleT hGtpcStackHandle, nwGtpv2cMsgParserNew( NW_IN NwGtpv2cStackHandleT hGtpcStackHandle,
NW_IN NwU8T msgType, NW_IN NwU8T msgType,
NW_IN NwRcT (*ieReadCallback) (NwU8T ieType, NW_IN NwRcT (*ieReadCallback) (NwU8T ieType,
NwU8T ieLength, NwU8T ieLength,
NwU8T ieInstance, NwU8T ieInstance,
NwU8T* ieValue, NwU8T* ieValue,
void* ieReadCallbackArg), void* ieReadCallbackArg),
NW_IN void* ieReadCallbackArg, NW_IN void* ieReadCallbackArg,
NW_IN NwGtpv2cMsgParserT **pthiz); NW_IN NwGtpv2cMsgParserT **pthiz);
/** /**
* Free a gtpv2c message parser. * Free a gtpv2c message parser.
* *
* @param[in] hGtpcStackHandle : gtpv2c stack handle. * @param[in] hGtpcStackHandle : gtpv2c stack handle.
* @param[in] thiz : Message parser handle. * @param[in] thiz : Message parser handle.
*/ */
NwRcT NwRcT
nwGtpv2cMsgParserDelete( NW_IN NwGtpv2cStackHandleT hGtpcStackHandle, nwGtpv2cMsgParserDelete( NW_IN NwGtpv2cStackHandleT hGtpcStackHandle,
NW_IN NwGtpv2cMsgParserT* thiz); NW_IN NwGtpv2cMsgParserT* thiz);
NwRcT NwRcT
nwGtpv2cMsgParserUpdateIe( NW_IN NwGtpv2cMsgParserT* thiz, nwGtpv2cMsgParserUpdateIe( NW_IN NwGtpv2cMsgParserT* thiz,
NW_IN NwU8T ieType, NW_IN NwU8T ieType,
NW_IN NwU8T ieInstance, NW_IN NwU8T ieInstance,
NW_IN NwU8T iePresence, NW_IN NwU8T iePresence,
NW_IN NwRcT (*ieReadCallback) (NwU8T ieType, NW_IN NwRcT (*ieReadCallback) (NwU8T ieType,
NwU8T ieLength, NwU8T ieLength,
NwU8T ieInstance, NwU8T ieInstance,
NwU8T* ieValue, NwU8T* ieValue,
void* ieReadCallbackArg), void* ieReadCallbackArg),
NW_IN void* ieReadCallbackArg); NW_IN void* ieReadCallbackArg);
NwRcT NwRcT
nwGtpv2cMsgParserUpdateIeReadCallback( NW_IN NwGtpv2cMsgParserT* thiz, nwGtpv2cMsgParserUpdateIeReadCallback( NW_IN NwGtpv2cMsgParserT* thiz,
NW_IN NwRcT (*ieReadCallback) (NwU8T ieType, NW_IN NwRcT (*ieReadCallback) (NwU8T ieType,
NwU8T ieLength, NwU8T ieLength,
NwU8T ieInstance, NwU8T ieInstance,
NwU8T* ieValue, NwU8T* ieValue,
void* ieReadCallbackArg)); void* ieReadCallbackArg));
NwRcT NwRcT
nwGtpv2cMsgParserUpdateIeReadCallbackArg( NW_IN NwGtpv2cMsgParserT* thiz, nwGtpv2cMsgParserUpdateIeReadCallbackArg( NW_IN NwGtpv2cMsgParserT* thiz,
NW_IN void* ieReadCallbackArg); NW_IN void* ieReadCallbackArg);
NwRcT NwRcT
nwGtpv2cMsgParserAddIe( NW_IN NwGtpv2cMsgParserT* thiz, nwGtpv2cMsgParserAddIe( NW_IN NwGtpv2cMsgParserT* thiz,
NW_IN NwU8T ieType, NW_IN NwU8T ieType,
NW_IN NwU8T ieInstance, NW_IN NwU8T ieInstance,
NW_IN NwU8T iePresence, NW_IN NwU8T iePresence,
NW_IN NwRcT (*ieReadCallback) (NwU8T ieType, NW_IN NwRcT (*ieReadCallback) (NwU8T ieType,
NwU8T ieLength, NwU8T ieLength,
NwU8T ieInstance, NwU8T ieInstance,
NwU8T* ieValue, NwU8T* ieValue,
void* ieReadCallbackArg), void* ieReadCallbackArg),
NW_IN void* ieReadCallbackArg); NW_IN void* ieReadCallbackArg);
NwRcT NwRcT
@@ -1,6 +1,6 @@
/*----------------------------------------------------------------------------* /*----------------------------------------------------------------------------*
* * * *
* n w - g t p v 2 c * * 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 * * 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 *
* * * *
* * * *
@@ -39,8 +39,8 @@
#include "NwTypes.h" #include "NwTypes.h"
/** /**
* @file NwLog.h * @file NwLog.h
* @brief This header file contains global shared logging definitions. * @brief This header file contains global shared logging definitions.
*/ */
@@ -56,7 +56,7 @@ extern "C" {
#define NW_LOG_LEVEL_ALER (1) /**< action must be taken immediately*/ #define NW_LOG_LEVEL_ALER (1) /**< action must be taken immediately*/
#define NW_LOG_LEVEL_CRIT (2) /**< critical conditions */ #define NW_LOG_LEVEL_CRIT (2) /**< critical conditions */
#define NW_LOG_LEVEL_ERRO (3) /**< error conditions */ #define NW_LOG_LEVEL_ERRO (3) /**< error conditions */
#define NW_LOG_LEVEL_WARN (4) /**< warning conditions */ #define NW_LOG_LEVEL_WARN (4) /**< warning conditions */
#define NW_LOG_LEVEL_NOTI (5) /**< normal but signification condition */ #define NW_LOG_LEVEL_NOTI (5) /**< normal but signification condition */
#define NW_LOG_LEVEL_INFO (6) /**< informational */ #define NW_LOG_LEVEL_INFO (6) /**< informational */
#define NW_LOG_LEVEL_DEBG (7) /**< debug-level messages */ #define NW_LOG_LEVEL_DEBG (7) /**< debug-level messages */
@@ -1,6 +1,6 @@
/*----------------------------------------------------------------------------* /*----------------------------------------------------------------------------*
* * * *
* n w - g t p v 2 c * * 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 * * 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 *
* * * *
* * * *
@@ -38,7 +38,7 @@
#ifndef __NW_TYPES_H__ #ifndef __NW_TYPES_H__
#define __NW_TYPES_H__ #define __NW_TYPES_H__
/** /**
* @file NwTypes.h * @file NwTypes.h
* @brief This header file contains basic type definitions. * @brief This header file contains basic type definitions.
*/ */
@@ -1,6 +1,6 @@
/*----------------------------------------------------------------------------* /*----------------------------------------------------------------------------*
* * * *
* n w - g t p v 2 c * * 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 * * 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 *
* * * *
* * * *
@@ -37,13 +37,13 @@
#define __NW_UTILS_H__ #define __NW_UTILS_H__
/** /**
* @file NwUtils.h * @file NwUtils.h
* @brief This header file contains utility macro and function definitions. * @brief This header file contains utility macro and function definitions.
*/ */
#define NW_ASSERT assert /**< Assertion */ #define NW_ASSERT assert /**< Assertion */
#define NW_CHK_NULL_PTR(_ptr) NW_ASSERT(_ptr != NULL) /**< Null pointer check */ #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_HTONS(x) ( ( ((x) & 0xff00) >> 8 ) | ( ((x) & 0x00ff) << 8 ) )
@@ -56,7 +56,7 @@
( ( ((NwU64T)x) & 0x0000ff0000000000ULL ) >> 24 ) | ( ( ((NwU64T)x) & 0x000000ff00000000ULL ) >> 8 ) | \ ( ( ((NwU64T)x) & 0x0000ff0000000000ULL ) >> 24 ) | ( ( ((NwU64T)x) & 0x000000ff00000000ULL ) >> 8 ) | \
( ( ((NwU64T)x) & 0x000000000000ff00ULL ) << 40 ) | ( ( ((NwU64T)x) & 0x00000000000000ffULL ) << 56 ) | \ ( ( ((NwU64T)x) & 0x000000000000ff00ULL ) << 40 ) | ( ( ((NwU64T)x) & 0x00000000000000ffULL ) << 56 ) | \
( ( ((NwU64T)x) & 0x0000000000ff0000ULL ) << 24 ) | ( ( ((NwU64T)x) & 0x00000000ff000000ULL ) << 8 ) \ ( ( ((NwU64T)x) & 0x0000000000ff0000ULL ) << 24 ) | ( ( ((NwU64T)x) & 0x00000000ff000000ULL ) << 8 ) \
) )
#define NW_NTOHS NW_HTONS #define NW_NTOHS NW_HTONS
File diff suppressed because it is too large Load Diff
+197 -181
View File
@@ -1,6 +1,6 @@
/*----------------------------------------------------------------------------* /*----------------------------------------------------------------------------*
* * * *
* n w - g t p v 2 c * * 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 * * 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 *
* * * *
* * * *
@@ -73,18 +73,14 @@ nwGtpv2cMsgNew( NW_IN NwGtpv2cStackHandleT hGtpcStackHandle,
NW_ASSERT(pStack); NW_ASSERT(pStack);
if(gpGtpv2cMsgPool) if(gpGtpv2cMsgPool) {
{
pMsg = gpGtpv2cMsgPool; pMsg = gpGtpv2cMsgPool;
gpGtpv2cMsgPool = gpGtpv2cMsgPool->next; gpGtpv2cMsgPool = gpGtpv2cMsgPool->next;
} } else {
else
{
NW_GTPV2C_MALLOC(pStack, sizeof(NwGtpv2cMsgT), pMsg, NwGtpv2cMsgT*); NW_GTPV2C_MALLOC(pStack, sizeof(NwGtpv2cMsgT), pMsg, NwGtpv2cMsgT*);
} }
if(pMsg) if(pMsg) {
{
pMsg->version = NW_GTP_VERSION; pMsg->version = NW_GTP_VERSION;
pMsg->teidPresent = teidPresent; pMsg->teidPresent = teidPresent;
pMsg->msgType = msgType; pMsg->msgType = msgType;
@@ -105,27 +101,23 @@ nwGtpv2cMsgNew( NW_IN NwGtpv2cStackHandleT hGtpcStackHandle,
NwRcT NwRcT
nwGtpv2cMsgFromBufferNew( NW_IN NwGtpv2cStackHandleT hGtpcStackHandle, nwGtpv2cMsgFromBufferNew( NW_IN NwGtpv2cStackHandleT hGtpcStackHandle,
NW_IN NwU8T* pBuf, NW_IN NwU8T* pBuf,
NW_IN NwU32T bufLen, NW_IN NwU32T bufLen,
NW_OUT NwGtpv2cMsgHandleT *phMsg) NW_OUT NwGtpv2cMsgHandleT *phMsg)
{ {
NwGtpv2cStackT* pStack = (NwGtpv2cStackT*) hGtpcStackHandle; NwGtpv2cStackT* pStack = (NwGtpv2cStackT*) hGtpcStackHandle;
NwGtpv2cMsgT *pMsg; NwGtpv2cMsgT *pMsg;
NW_ASSERT(pStack); NW_ASSERT(pStack);
if(gpGtpv2cMsgPool) if(gpGtpv2cMsgPool) {
{
pMsg = gpGtpv2cMsgPool; pMsg = gpGtpv2cMsgPool;
gpGtpv2cMsgPool = gpGtpv2cMsgPool->next; gpGtpv2cMsgPool = gpGtpv2cMsgPool->next;
} } else {
else
{
NW_GTPV2C_MALLOC(pStack, sizeof(NwGtpv2cMsgT), pMsg, NwGtpv2cMsgT*); NW_GTPV2C_MALLOC(pStack, sizeof(NwGtpv2cMsgT), pMsg, NwGtpv2cMsgT*);
} }
if(pMsg) if(pMsg) {
{
*phMsg = (NwGtpv2cMsgHandleT) pMsg; *phMsg = (NwGtpv2cMsgHandleT) pMsg;
memcpy(pMsg->msgBuf, pBuf, bufLen); memcpy(pMsg->msgBuf, pBuf, bufLen);
pMsg->msgLen = bufLen; pMsg->msgLen = bufLen;
@@ -137,8 +129,7 @@ nwGtpv2cMsgFromBufferNew( NW_IN NwGtpv2cStackHandleT hGtpcStackHandle,
pMsg->msgType = *(pBuf); pMsg->msgType = *(pBuf);
pBuf += 3; pBuf += 3;
if(pMsg->teidPresent) if(pMsg->teidPresent) {
{
pMsg->teid = ntohl(*((NwU32T*)(pBuf))); pMsg->teid = ntohl(*((NwU32T*)(pBuf)));
pBuf += 4; pBuf += 4;
} }
@@ -150,6 +141,7 @@ nwGtpv2cMsgFromBufferNew( NW_IN NwGtpv2cStackHandleT hGtpcStackHandle,
NW_LOG(pStack, NW_LOG_LEVEL_DEBG, "Created message %p!", pMsg); NW_LOG(pStack, NW_LOG_LEVEL_DEBG, "Created message %p!", pMsg);
return NW_OK; return NW_OK;
} }
return NW_FAILURE; return NW_FAILURE;
} }
@@ -166,82 +158,82 @@ nwGtpv2cMsgDelete( NW_IN NwGtpv2cStackHandleT hGtpcStackHandle,
return NW_OK; return NW_OK;
} }
/** /**
* Set TEID for gtpv2c message. * Set TEID for gtpv2c message.
* *
* @param[in] hMsg : Message handle. * @param[in] hMsg : Message handle.
* @param[in] teid: TEID value. * @param[in] teid: TEID value.
*/ */
NwRcT NwRcT
nwGtpv2cMsgSetTeid(NW_IN NwGtpv2cMsgHandleT hMsg, NwU32T teid) nwGtpv2cMsgSetTeid(NW_IN NwGtpv2cMsgHandleT hMsg, NwU32T teid)
{ {
NwGtpv2cMsgT *thiz = (NwGtpv2cMsgT*) hMsg; NwGtpv2cMsgT *thiz = (NwGtpv2cMsgT*) hMsg;
thiz->teid = teid; thiz->teid = teid;
return NW_OK; return NW_OK;
} }
/** /**
* Set TEID present flag for gtpv2c message. * Set TEID present flag for gtpv2c message.
* *
* @param[in] hMsg : Message handle. * @param[in] hMsg : Message handle.
* @param[in] teidPesent: Flag boolean value. * @param[in] teidPesent: Flag boolean value.
*/ */
NwRcT NwRcT
nwGtpv2cMsgSetTeidPresent(NW_IN NwGtpv2cMsgHandleT hMsg, NwBoolT teidPresent) nwGtpv2cMsgSetTeidPresent(NW_IN NwGtpv2cMsgHandleT hMsg, NwBoolT teidPresent)
{ {
NwGtpv2cMsgT *thiz = (NwGtpv2cMsgT*) hMsg; NwGtpv2cMsgT *thiz = (NwGtpv2cMsgT*) hMsg;
thiz->teidPresent = teidPresent; thiz->teidPresent = teidPresent;
return NW_OK; return NW_OK;
} }
/** /**
* Set sequence for gtpv2c message. * Set sequence for gtpv2c message.
* *
* @param[in] hMsg : Message handle. * @param[in] hMsg : Message handle.
* @param[in] seqNum: Flag boolean value. * @param[in] seqNum: Flag boolean value.
*/ */
NwRcT NwRcT
nwGtpv2cMsgSetSeqNumber(NW_IN NwGtpv2cMsgHandleT hMsg, NwU32T seqNum) nwGtpv2cMsgSetSeqNumber(NW_IN NwGtpv2cMsgHandleT hMsg, NwU32T seqNum)
{ {
NwGtpv2cMsgT *thiz = (NwGtpv2cMsgT*) hMsg; NwGtpv2cMsgT *thiz = (NwGtpv2cMsgT*) hMsg;
thiz->seqNum = seqNum; thiz->seqNum = seqNum;
return NW_OK; return NW_OK;
} }
/** /**
* Get TEID present for gtpv2c message. * Get TEID present for gtpv2c message.
* *
* @param[in] hMsg : Message handle. * @param[in] hMsg : Message handle.
*/ */
NwU32T NwU32T
nwGtpv2cMsgGetTeid(NW_IN NwGtpv2cMsgHandleT hMsg) nwGtpv2cMsgGetTeid(NW_IN NwGtpv2cMsgHandleT hMsg)
{ {
NwGtpv2cMsgT *thiz = (NwGtpv2cMsgT*) hMsg; NwGtpv2cMsgT *thiz = (NwGtpv2cMsgT*) hMsg;
return (thiz->teid); return (thiz->teid);
} }
/** /**
* Get TEID present for gtpv2c message. * Get TEID present for gtpv2c message.
* *
* @param[in] hMsg : Message handle. * @param[in] hMsg : Message handle.
*/ */
NwBoolT NwBoolT
nwGtpv2cMsgGetTeidPresent(NW_IN NwGtpv2cMsgHandleT hMsg) nwGtpv2cMsgGetTeidPresent(NW_IN NwGtpv2cMsgHandleT hMsg)
{ {
NwGtpv2cMsgT *thiz = (NwGtpv2cMsgT*) hMsg; NwGtpv2cMsgT *thiz = (NwGtpv2cMsgT*) hMsg;
return (thiz->teidPresent); return (thiz->teidPresent);
} }
/** /**
* Get sequence number for gtpv2c message. * Get sequence number for gtpv2c message.
* *
* @param[in] hMsg : Message handle. * @param[in] hMsg : Message handle.
*/ */
NwU32T NwU32T
nwGtpv2cMsgGetSeqNumber(NW_IN NwGtpv2cMsgHandleT hMsg) nwGtpv2cMsgGetSeqNumber(NW_IN NwGtpv2cMsgHandleT hMsg)
@@ -250,11 +242,11 @@ nwGtpv2cMsgGetSeqNumber(NW_IN NwGtpv2cMsgHandleT hMsg)
return (thiz->seqNum); return (thiz->seqNum);
} }
/** /**
* Get msg type for gtpv2c message. * Get msg type for gtpv2c message.
* *
* @param[in] hMsg : Message handle. * @param[in] hMsg : Message handle.
*/ */
NwU32T NwU32T
nwGtpv2cMsgGetMsgType(NW_IN NwGtpv2cMsgHandleT hMsg) nwGtpv2cMsgGetMsgType(NW_IN NwGtpv2cMsgHandleT hMsg)
@@ -263,11 +255,11 @@ nwGtpv2cMsgGetMsgType(NW_IN NwGtpv2cMsgHandleT hMsg)
return (thiz->msgType); return (thiz->msgType);
} }
/** /**
* Get msg type for gtpv2c message. * Get msg type for gtpv2c message.
* *
* @param[in] hMsg : Message handle. * @param[in] hMsg : Message handle.
*/ */
NwU32T NwU32T
nwGtpv2cMsgGetLength(NW_IN NwGtpv2cMsgHandleT hMsg) nwGtpv2cMsgGetLength(NW_IN NwGtpv2cMsgHandleT hMsg)
@@ -278,10 +270,10 @@ nwGtpv2cMsgGetLength(NW_IN NwGtpv2cMsgHandleT hMsg)
NwRcT NwRcT
nwGtpv2cMsgAddIeTV1(NW_IN NwGtpv2cMsgHandleT hMsg, nwGtpv2cMsgAddIeTV1(NW_IN NwGtpv2cMsgHandleT hMsg,
NW_IN NwU8T type, NW_IN NwU8T type,
NW_IN NwU8T instance, NW_IN NwU8T instance,
NW_IN NwU8T value) NW_IN NwU8T value)
{ {
NwGtpv2cMsgT *pMsg = (NwGtpv2cMsgT*) hMsg; NwGtpv2cMsgT *pMsg = (NwGtpv2cMsgT*) hMsg;
NwGtpv2cIeTv1T *pIe; NwGtpv2cIeTv1T *pIe;
@@ -299,10 +291,10 @@ nwGtpv2cMsgAddIeTV1(NW_IN NwGtpv2cMsgHandleT hMsg,
} }
NwRcT NwRcT
nwGtpv2cMsgAddIeTV2(NW_IN NwGtpv2cMsgHandleT hMsg, nwGtpv2cMsgAddIeTV2(NW_IN NwGtpv2cMsgHandleT hMsg,
NW_IN NwU8T type, NW_IN NwU8T type,
NW_IN NwU8T instance, NW_IN NwU8T instance,
NW_IN NwU16T value) NW_IN NwU16T value)
{ {
NwGtpv2cMsgT *pMsg = (NwGtpv2cMsgT*) hMsg; NwGtpv2cMsgT *pMsg = (NwGtpv2cMsgT*) hMsg;
NwGtpv2cIeTv2T *pIe; NwGtpv2cIeTv2T *pIe;
@@ -320,10 +312,10 @@ nwGtpv2cMsgAddIeTV2(NW_IN NwGtpv2cMsgHandleT hMsg,
} }
NwRcT NwRcT
nwGtpv2cMsgAddIeTV4(NW_IN NwGtpv2cMsgHandleT hMsg, nwGtpv2cMsgAddIeTV4(NW_IN NwGtpv2cMsgHandleT hMsg,
NW_IN NwU8T type, NW_IN NwU8T type,
NW_IN NwU8T instance, NW_IN NwU8T instance,
NW_IN NwU32T value) NW_IN NwU32T value)
{ {
NwGtpv2cMsgT *pMsg = (NwGtpv2cMsgT*) hMsg; NwGtpv2cMsgT *pMsg = (NwGtpv2cMsgT*) hMsg;
NwGtpv2cIeTv4T *pIe; NwGtpv2cIeTv4T *pIe;
@@ -341,11 +333,11 @@ nwGtpv2cMsgAddIeTV4(NW_IN NwGtpv2cMsgHandleT hMsg,
} }
NwRcT NwRcT
nwGtpv2cMsgAddIe(NW_IN NwGtpv2cMsgHandleT hMsg, nwGtpv2cMsgAddIe(NW_IN NwGtpv2cMsgHandleT hMsg,
NW_IN NwU8T type, NW_IN NwU8T type,
NW_IN NwU16T length, NW_IN NwU16T length,
NW_IN NwU8T instance, NW_IN NwU8T instance,
NW_IN NwU8T* pVal) NW_IN NwU8T* pVal)
{ {
NwGtpv2cMsgT *pMsg = (NwGtpv2cMsgT*) hMsg; NwGtpv2cMsgT *pMsg = (NwGtpv2cMsgT*) hMsg;
NwGtpv2cIeTlvT *pIe; NwGtpv2cIeTlvT *pIe;
@@ -363,9 +355,9 @@ nwGtpv2cMsgAddIe(NW_IN NwGtpv2cMsgHandleT hMsg,
} }
NwRcT NwRcT
nwGtpv2cMsgGroupedIeStart(NW_IN NwGtpv2cMsgHandleT hMsg, nwGtpv2cMsgGroupedIeStart(NW_IN NwGtpv2cMsgHandleT hMsg,
NW_IN NwU8T type, NW_IN NwU8T type,
NW_IN NwU8T instance) NW_IN NwU8T instance)
{ {
NwGtpv2cMsgT *pMsg = (NwGtpv2cMsgT*) hMsg; NwGtpv2cMsgT *pMsg = (NwGtpv2cMsgT*) hMsg;
NwGtpv2cIeTlvT *pIe; NwGtpv2cIeTlvT *pIe;
@@ -386,11 +378,11 @@ nwGtpv2cMsgGroupedIeStart(NW_IN NwGtpv2cMsgHandleT hMsg,
} }
NwRcT NwRcT
nwGtpv2cMsgGroupedIeEnd(NW_IN NwGtpv2cMsgHandleT hMsg) nwGtpv2cMsgGroupedIeEnd(NW_IN NwGtpv2cMsgHandleT hMsg)
{ {
NwGtpv2cMsgT *pMsg = (NwGtpv2cMsgT*) hMsg; NwGtpv2cMsgT *pMsg = (NwGtpv2cMsgT*) hMsg;
NwGtpv2cIeTlvT *pIe; NwGtpv2cIeTlvT *pIe;
NW_ASSERT(pMsg->groupedIeEncodeStack.top > 0); NW_ASSERT(pMsg->groupedIeEncodeStack.top > 0);
pMsg->groupedIeEncodeStack.top--; pMsg->groupedIeEncodeStack.top--;
@@ -402,7 +394,7 @@ nwGtpv2cMsgGroupedIeEnd(NW_IN NwGtpv2cMsgHandleT hMsg)
} }
NwRcT NwRcT
nwGtpv2cMsgAddIeCause(NW_IN NwGtpv2cMsgHandleT hMsg, nwGtpv2cMsgAddIeCause(NW_IN NwGtpv2cMsgHandleT hMsg,
NW_IN NwU8T instance, NW_IN NwU8T instance,
NW_IN NwU8T causeValue, NW_IN NwU8T causeValue,
NW_IN NwU8T bitFlags, NW_IN NwU8T bitFlags,
@@ -414,8 +406,7 @@ nwGtpv2cMsgAddIeCause(NW_IN NwGtpv2cMsgHandleT hMsg,
causeBuf[0] = causeValue; causeBuf[0] = causeValue;
causeBuf[1] = bitFlags; causeBuf[1] = bitFlags;
if(offendingIeType) if(offendingIeType) {
{
causeBuf[2] = offendingIeType; causeBuf[2] = offendingIeType;
causeBuf[3] = 0; causeBuf[3] = 0;
causeBuf[4] = 0; causeBuf[4] = 0;
@@ -426,12 +417,12 @@ nwGtpv2cMsgAddIeCause(NW_IN NwGtpv2cMsgHandleT hMsg,
} }
NwRcT NwRcT
nwGtpv2cMsgAddIeFteid(NW_IN NwGtpv2cMsgHandleT hMsg, nwGtpv2cMsgAddIeFteid(NW_IN NwGtpv2cMsgHandleT hMsg,
NW_IN NwU8T instance, NW_IN NwU8T instance,
NW_IN NwU8T ifType, NW_IN NwU8T ifType,
NW_IN NwU32T teidOrGreKey, NW_IN NwU32T teidOrGreKey,
NW_IN NwU32T ipv4Addr, NW_IN NwU32T ipv4Addr,
NW_IN NwU8T* pIpv6Addr) NW_IN NwU8T* pIpv6Addr)
{ {
NwU8T fteidBuf[32]; NwU8T fteidBuf[32];
@@ -440,188 +431,209 @@ nwGtpv2cMsgAddIeFteid(NW_IN NwGtpv2cMsgHandleT hMsg,
fteidBuf[0] = (ifType & 0x1F); fteidBuf[0] = (ifType & 0x1F);
pFteidBuf++; pFteidBuf++;
*((NwU32T*)(pFteidBuf)) = htonl((teidOrGreKey)); *((NwU32T*)(pFteidBuf)) = htonl((teidOrGreKey));
pFteidBuf += 4; pFteidBuf += 4;
if(ipv4Addr) if(ipv4Addr) {
{
fteidBuf[0] |= (0x01 << 7); fteidBuf[0] |= (0x01 << 7);
*((NwU32T*)(pFteidBuf)) = htonl(ipv4Addr); *((NwU32T*)(pFteidBuf)) = htonl(ipv4Addr);
pFteidBuf += 4; pFteidBuf += 4;
} }
if(pIpv6Addr) if(pIpv6Addr) {
{
fteidBuf[0] |= (0x01 << 6); fteidBuf[0] |= (0x01 << 6);
memcpy((pFteidBuf), pIpv6Addr, 16); memcpy((pFteidBuf), pIpv6Addr, 16);
pFteidBuf += 16; pFteidBuf += 16;
} }
return (nwGtpv2cMsgAddIe(hMsg, NW_GTPV2C_IE_FTEID, (pFteidBuf - fteidBuf), instance, fteidBuf)); return (nwGtpv2cMsgAddIe(hMsg, NW_GTPV2C_IE_FTEID, (pFteidBuf - fteidBuf), instance, fteidBuf));
} }
NwBoolT NwBoolT
nwGtpv2cMsgIsIePresent(NW_IN NwGtpv2cMsgHandleT hMsg, nwGtpv2cMsgIsIePresent(NW_IN NwGtpv2cMsgHandleT hMsg,
NW_IN NwU8T type, NW_IN NwU8T type,
NW_IN NwU8T instance) NW_IN NwU8T instance)
{ {
NwGtpv2cMsgT *thiz = (NwGtpv2cMsgT*) hMsg; NwGtpv2cMsgT *thiz = (NwGtpv2cMsgT*) hMsg;
if((NwGtpv2cIeTv1T*) thiz->pIe[type][instance]) if((NwGtpv2cIeTv1T*) thiz->pIe[type][instance])
return NW_TRUE; return NW_TRUE;
return NW_FALSE;
return NW_FALSE;
} }
NwRcT NwRcT
nwGtpv2cMsgGetIeTV1(NW_IN NwGtpv2cMsgHandleT hMsg, nwGtpv2cMsgGetIeTV1(NW_IN NwGtpv2cMsgHandleT hMsg,
NW_IN NwU8T type, NW_IN NwU8T type,
NW_IN NwU8T instance, NW_IN NwU8T instance,
NW_OUT NwU8T* pVal) NW_OUT NwU8T* pVal)
{ {
NwGtpv2cMsgT *thiz = (NwGtpv2cMsgT*) hMsg; NwGtpv2cMsgT *thiz = (NwGtpv2cMsgT*) hMsg;
NwGtpv2cIeTv1T *pIe; NwGtpv2cIeTv1T *pIe;
NW_ASSERT(instance <= NW_GTPV2C_IE_INSTANCE_MAXIMUM); NW_ASSERT(instance <= NW_GTPV2C_IE_INSTANCE_MAXIMUM);
if(thiz->isIeValid[type][instance])
{ if(thiz->isIeValid[type][instance]) {
pIe = (NwGtpv2cIeTv1T*) thiz->pIe[type][instance]; pIe = (NwGtpv2cIeTv1T*) thiz->pIe[type][instance];
if(ntohs(pIe->l) != 0x01) if(ntohs(pIe->l) != 0x01)
return NW_GTPV2C_IE_INCORRECT; return NW_GTPV2C_IE_INCORRECT;
if(pVal) *pVal = pIe->v; if(pVal) *pVal = pIe->v;
return NW_OK; return NW_OK;
} }
return NW_GTPV2C_IE_MISSING; return NW_GTPV2C_IE_MISSING;
} }
NwRcT NwRcT
nwGtpv2cMsgGetIeTV2( NW_IN NwGtpv2cMsgHandleT hMsg, nwGtpv2cMsgGetIeTV2( NW_IN NwGtpv2cMsgHandleT hMsg,
NW_IN NwU8T type, NW_IN NwU8T type,
NW_IN NwU8T instance, NW_IN NwU8T instance,
NW_OUT NwU16T* pVal) NW_OUT NwU16T* pVal)
{ {
NwGtpv2cMsgT *thiz = (NwGtpv2cMsgT*) hMsg; NwGtpv2cMsgT *thiz = (NwGtpv2cMsgT*) hMsg;
NwGtpv2cIeTv2T *pIe; NwGtpv2cIeTv2T *pIe;
NW_ASSERT(instance <= NW_GTPV2C_IE_INSTANCE_MAXIMUM); NW_ASSERT(instance <= NW_GTPV2C_IE_INSTANCE_MAXIMUM);
if(thiz->isIeValid[type][instance])
{ if(thiz->isIeValid[type][instance]) {
pIe = (NwGtpv2cIeTv2T*) thiz->pIe[type][instance]; pIe = (NwGtpv2cIeTv2T*) thiz->pIe[type][instance];
if(ntohs(pIe->l) != 0x02) if(ntohs(pIe->l) != 0x02)
return NW_GTPV2C_IE_INCORRECT; return NW_GTPV2C_IE_INCORRECT;
if(pVal) *pVal = ntohs(pIe->v); if(pVal) *pVal = ntohs(pIe->v);
return NW_OK; return NW_OK;
} }
return NW_GTPV2C_IE_MISSING; return NW_GTPV2C_IE_MISSING;
} }
NwRcT NwRcT
nwGtpv2cMsgGetIeTV4( NW_IN NwGtpv2cMsgHandleT hMsg, nwGtpv2cMsgGetIeTV4( NW_IN NwGtpv2cMsgHandleT hMsg,
NW_IN NwU8T type, NW_IN NwU8T type,
NW_IN NwU8T instance, NW_IN NwU8T instance,
NW_OUT NwU32T* pVal) NW_OUT NwU32T* pVal)
{ {
NwGtpv2cMsgT *thiz = (NwGtpv2cMsgT*) hMsg; NwGtpv2cMsgT *thiz = (NwGtpv2cMsgT*) hMsg;
NwGtpv2cIeTv4T *pIe; NwGtpv2cIeTv4T *pIe;
NW_ASSERT(instance <= NW_GTPV2C_IE_INSTANCE_MAXIMUM); NW_ASSERT(instance <= NW_GTPV2C_IE_INSTANCE_MAXIMUM);
if(thiz->isIeValid[type][instance])
{ if(thiz->isIeValid[type][instance]) {
pIe = (NwGtpv2cIeTv4T*) thiz->pIe[type][instance]; pIe = (NwGtpv2cIeTv4T*) thiz->pIe[type][instance];
if(ntohs(pIe->l) != 0x04) if(ntohs(pIe->l) != 0x04)
return NW_GTPV2C_IE_INCORRECT; return NW_GTPV2C_IE_INCORRECT;
if(pVal) *pVal = ntohl(pIe->v); if(pVal) *pVal = ntohl(pIe->v);
return NW_OK; return NW_OK;
} }
return NW_GTPV2C_IE_MISSING; return NW_GTPV2C_IE_MISSING;
} }
NwRcT NwRcT
nwGtpv2cMsgGetIeTV8( NW_IN NwGtpv2cMsgHandleT hMsg, nwGtpv2cMsgGetIeTV8( NW_IN NwGtpv2cMsgHandleT hMsg,
NW_IN NwU8T type, NW_IN NwU8T type,
NW_IN NwU8T instance, NW_IN NwU8T instance,
NW_OUT NwU64T* pVal) NW_OUT NwU64T* pVal)
{ {
NwGtpv2cMsgT *thiz = (NwGtpv2cMsgT*) hMsg; NwGtpv2cMsgT *thiz = (NwGtpv2cMsgT*) hMsg;
NwGtpv2cIeTv8T *pIe; NwGtpv2cIeTv8T *pIe;
NW_ASSERT(instance <= NW_GTPV2C_IE_INSTANCE_MAXIMUM); NW_ASSERT(instance <= NW_GTPV2C_IE_INSTANCE_MAXIMUM);
if(thiz->isIeValid[type][instance])
{ if(thiz->isIeValid[type][instance]) {
pIe = (NwGtpv2cIeTv8T*) thiz->pIe[type][instance]; pIe = (NwGtpv2cIeTv8T*) thiz->pIe[type][instance];
if(ntohs(pIe->l) != 0x08) if(ntohs(pIe->l) != 0x08)
return NW_GTPV2C_IE_INCORRECT; return NW_GTPV2C_IE_INCORRECT;
if(pVal) *pVal = NW_NTOHLL((pIe->v)); if(pVal) *pVal = NW_NTOHLL((pIe->v));
return NW_OK; return NW_OK;
} }
NW_LOG(thiz->hStack, NW_LOG_LEVEL_ERRO, "Cannot retrieve IE of type %u instance %u !", type, instance); NW_LOG(thiz->hStack, NW_LOG_LEVEL_ERRO, "Cannot retrieve IE of type %u instance %u !", type, instance);
return NW_GTPV2C_IE_MISSING; return NW_GTPV2C_IE_MISSING;
} }
NwRcT NwRcT
nwGtpv2cMsgGetIeTlv( NW_IN NwGtpv2cMsgHandleT hMsg, nwGtpv2cMsgGetIeTlv( NW_IN NwGtpv2cMsgHandleT hMsg,
NW_IN NwU8T type, NW_IN NwU8T type,
NW_IN NwU8T instance, NW_IN NwU8T instance,
NW_IN NwU16T maxLen, NW_IN NwU16T maxLen,
NW_OUT NwU8T* pVal, NW_OUT NwU8T* pVal,
NW_OUT NwU16T* pLen) NW_OUT NwU16T* pLen)
{ {
NwGtpv2cMsgT *thiz = (NwGtpv2cMsgT*) hMsg; NwGtpv2cMsgT *thiz = (NwGtpv2cMsgT*) hMsg;
NwGtpv2cIeTlvT *pIe; NwGtpv2cIeTlvT *pIe;
NW_ASSERT(instance <= NW_GTPV2C_IE_INSTANCE_MAXIMUM); NW_ASSERT(instance <= NW_GTPV2C_IE_INSTANCE_MAXIMUM);
if(thiz->isIeValid[type][instance])
{ if(thiz->isIeValid[type][instance]) {
pIe = (NwGtpv2cIeTlvT*) thiz->pIe[type][instance]; pIe = (NwGtpv2cIeTlvT*) thiz->pIe[type][instance];
if(ntohs(pIe->l) <= maxLen)
{ if(ntohs(pIe->l) <= maxLen) {
if(pVal) memcpy(pVal, ((NwU8T*) pIe) + 4, ntohs(pIe->l)); if(pVal) memcpy(pVal, ((NwU8T*) pIe) + 4, ntohs(pIe->l));
if(pLen) *pLen = ntohs(pIe->l); if(pLen) *pLen = ntohs(pIe->l);
return NW_OK; return NW_OK;
} }
} }
return NW_GTPV2C_IE_MISSING; return NW_GTPV2C_IE_MISSING;
} }
NwRcT NwRcT
nwGtpv2cMsgGetIeTlvP( NW_IN NwGtpv2cMsgHandleT hMsg, nwGtpv2cMsgGetIeTlvP( NW_IN NwGtpv2cMsgHandleT hMsg,
NW_IN NwU8T type, NW_IN NwU8T type,
NW_IN NwU8T instance, NW_IN NwU8T instance,
NW_OUT NwU8T** ppVal, NW_OUT NwU8T** ppVal,
NW_OUT NwU16T* pLen) NW_OUT NwU16T* pLen)
{ {
NwGtpv2cMsgT *thiz = (NwGtpv2cMsgT*) hMsg; NwGtpv2cMsgT *thiz = (NwGtpv2cMsgT*) hMsg;
NwGtpv2cIeTlvT *pIe; NwGtpv2cIeTlvT *pIe;
NW_ASSERT(instance <= NW_GTPV2C_IE_INSTANCE_MAXIMUM); NW_ASSERT(instance <= NW_GTPV2C_IE_INSTANCE_MAXIMUM);
if(thiz->isIeValid[type][instance])
{ if(thiz->isIeValid[type][instance]) {
pIe = (NwGtpv2cIeTlvT*) thiz->pIe[type][instance]; pIe = (NwGtpv2cIeTlvT*) thiz->pIe[type][instance];
if(ppVal) *ppVal = ((NwU8T*) pIe) + 4; if(ppVal) *ppVal = ((NwU8T*) pIe) + 4;
if(pLen) *pLen = ntohs(pIe->l); if(pLen) *pLen = ntohs(pIe->l);
return NW_OK; return NW_OK;
} }
return NW_GTPV2C_IE_MISSING; return NW_GTPV2C_IE_MISSING;
} }
NwRcT NwRcT
nwGtpv2cMsgGetIeCause(NW_IN NwGtpv2cMsgHandleT hMsg, nwGtpv2cMsgGetIeCause(NW_IN NwGtpv2cMsgHandleT hMsg,
NW_IN NwU8T instance, NW_IN NwU8T instance,
NW_OUT NwU8T* causeValue, NW_OUT NwU8T* causeValue,
NW_OUT NwU8T* flags, NW_OUT NwU8T* flags,
NW_OUT NwU8T* offendingIeType, NW_OUT NwU8T* offendingIeType,
NW_OUT NwU8T* offendingIeInstance) NW_OUT NwU8T* offendingIeInstance)
{ {
NwGtpv2cMsgT *thiz = (NwGtpv2cMsgT*) hMsg; NwGtpv2cMsgT *thiz = (NwGtpv2cMsgT*) hMsg;
NwGtpv2cIeTlvT *pIe; NwGtpv2cIeTlvT *pIe;
NW_ASSERT(instance <= NW_GTPV2C_IE_INSTANCE_MAXIMUM); NW_ASSERT(instance <= NW_GTPV2C_IE_INSTANCE_MAXIMUM);
if(thiz->isIeValid[NW_GTPV2C_IE_CAUSE][instance])
{ if(thiz->isIeValid[NW_GTPV2C_IE_CAUSE][instance]) {
pIe = (NwGtpv2cIeTlvT*) thiz->pIe[NW_GTPV2C_IE_CAUSE][instance]; pIe = (NwGtpv2cIeTlvT*) thiz->pIe[NW_GTPV2C_IE_CAUSE][instance];
*causeValue = *((NwU8T*)(((NwU8T*)pIe) + 4)); *causeValue = *((NwU8T*)(((NwU8T*)pIe) + 4));
*flags = *((NwU8T*)(((NwU8T*)pIe) + 5)); *flags = *((NwU8T*)(((NwU8T*)pIe) + 5));
if(pIe->l == 6)
{ if(pIe->l == 6) {
*offendingIeType = *((NwU8T*)(((NwU8T*)pIe) + 6)); *offendingIeType = *((NwU8T*)(((NwU8T*)pIe) + 6));
*offendingIeType = *((NwU8T*)(((NwU8T*)pIe) + 8)); *offendingIeType = *((NwU8T*)(((NwU8T*)pIe) + 8));
} }
return NW_OK; return NW_OK;
} }
@@ -629,35 +641,34 @@ nwGtpv2cMsgGetIeCause(NW_IN NwGtpv2cMsgHandleT hMsg,
} }
NwRcT NwRcT
nwGtpv2cMsgGetIeFteid(NW_IN NwGtpv2cMsgHandleT hMsg, nwGtpv2cMsgGetIeFteid(NW_IN NwGtpv2cMsgHandleT hMsg,
NW_IN NwU8T instance, NW_IN NwU8T instance,
NW_OUT NwU8T* ifType, NW_OUT NwU8T* ifType,
NW_OUT NwU32T* teidOrGreKey, NW_OUT NwU32T* teidOrGreKey,
NW_OUT NwU32T* ipv4Addr, NW_OUT NwU32T* ipv4Addr,
NW_OUT NwU8T* pIpv6Addr) NW_OUT NwU8T* pIpv6Addr)
{ {
NwGtpv2cMsgT *thiz = (NwGtpv2cMsgT*) hMsg; NwGtpv2cMsgT *thiz = (NwGtpv2cMsgT*) hMsg;
NwGtpv2cIeTlvT *pIe; NwGtpv2cIeTlvT *pIe;
NW_ASSERT(instance <= NW_GTPV2C_IE_INSTANCE_MAXIMUM); NW_ASSERT(instance <= NW_GTPV2C_IE_INSTANCE_MAXIMUM);
if(thiz->isIeValid[NW_GTPV2C_IE_FTEID][instance]) if(thiz->isIeValid[NW_GTPV2C_IE_FTEID][instance]) {
{ pIe = (NwGtpv2cIeTlvT*) thiz->pIe[NW_GTPV2C_IE_FTEID][instance];
pIe = (NwGtpv2cIeTlvT*) thiz->pIe[NW_GTPV2C_IE_FTEID][instance];
NwU8T flags; NwU8T flags;
NwU8T* pIeValue = ((NwU8T*) pIe) + 4; NwU8T* pIeValue = ((NwU8T*) pIe) + 4;
flags = (*pIeValue) & 0xE0; flags = (*pIeValue) & 0xE0;
*ifType = (*pIeValue) & 0x1F; *ifType = (*pIeValue) & 0x1F;
pIeValue += 1; pIeValue += 1;
*teidOrGreKey = ntohl(*((NwU32T*)(pIeValue))); *teidOrGreKey = ntohl(*((NwU32T*)(pIeValue)));
pIeValue += 4; pIeValue += 4;
if(flags & 0x80) if(flags & 0x80) {
{
*ipv4Addr = ntohl(*((NwU32T*)(pIeValue))); *ipv4Addr = ntohl(*((NwU32T*)(pIeValue)));
pIeValue += 4; pIeValue += 4;
} }
return NW_OK; return NW_OK;
} }
@@ -680,14 +691,16 @@ nwGtpv2cMsgHexDump(NwGtpv2cMsgHandleT hMsg, FILE* fp)
char hexstr[ 16*3 + 5] = {0}; char hexstr[ 16*3 + 5] = {0};
char charstr[16*1 + 5] = {0}; char charstr[16*1 + 5] = {0};
fprintf((FILE*)fp, "\n"); fprintf((FILE*)fp, "\n");
for(n=1;n<=size;n++) {
for(n=1; n<=size; n++) {
if (n%16 == 1) { if (n%16 == 1) {
/* store address for this line */ /* store address for this line */
snprintf(addrstr, sizeof(addrstr), "%.4lx", snprintf(addrstr, sizeof(addrstr), "%.4lx",
((unsigned long)p-(unsigned long)data) ); ((unsigned long)p-(unsigned long)data) );
} }
c = *p; c = *p;
if (isalnum(c) == 0) { if (isalnum(c) == 0) {
c = '.'; c = '.';
} }
@@ -699,6 +712,7 @@ nwGtpv2cMsgHexDump(NwGtpv2cMsgHandleT hMsg, FILE* fp)
/* store char str (for right side) */ /* store char str (for right side) */
snprintf(bytestr, sizeof(bytestr), "%c", c); snprintf(bytestr, sizeof(bytestr), "%c", c);
strncat(charstr, bytestr, sizeof(charstr)-strlen(charstr)-1); strncat(charstr, bytestr, sizeof(charstr)-strlen(charstr)-1);
if(n%16 == 0) { if(n%16 == 0) {
/* line completed */ /* line completed */
fprintf((FILE*)fp, "[%4.4s] %-50.50s %s\n", addrstr, hexstr, charstr); fprintf((FILE*)fp, "[%4.4s] %-50.50s %s\n", addrstr, hexstr, charstr);
@@ -709,6 +723,7 @@ nwGtpv2cMsgHexDump(NwGtpv2cMsgHandleT hMsg, FILE* fp)
strncat(hexstr, " ", sizeof(hexstr)-strlen(hexstr)-1); strncat(hexstr, " ", sizeof(hexstr)-strlen(hexstr)-1);
strncat(charstr, " ", sizeof(charstr)-strlen(charstr)-1); strncat(charstr, " ", sizeof(charstr)-strlen(charstr)-1);
} }
p++; /* next byte */ p++; /* next byte */
} }
@@ -717,6 +732,7 @@ nwGtpv2cMsgHexDump(NwGtpv2cMsgHandleT hMsg, FILE* fp)
fprintf((FILE*)fp, "[%4.4s] %-50.50s %s\n", addrstr, hexstr, charstr); fprintf((FILE*)fp, "[%4.4s] %-50.50s %s\n", addrstr, hexstr, charstr);
} }
fprintf((FILE*)fp, "\n"); fprintf((FILE*)fp, "\n");
return NW_OK; return NW_OK;
@@ -729,6 +745,6 @@ nwGtpv2cMsgHexDump(NwGtpv2cMsgHandleT hMsg, FILE* fp)
/*--------------------------------------------------------------------------* /*--------------------------------------------------------------------------*
* E N D O F F I L E * * E N D O F F I L E *
*--------------------------------------------------------------------------*/ *--------------------------------------------------------------------------*/
@@ -1,6 +1,6 @@
/*----------------------------------------------------------------------------* /*----------------------------------------------------------------------------*
* * * *
* n w - g t p v 2 c * * 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 * * 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 *
* * * *
* * * *
@@ -49,8 +49,7 @@ extern "C" {
#endif #endif
typedef struct NwGtpv2cMsgIeInfo typedef struct NwGtpv2cMsgIeInfo {
{
NwU8T ieType; NwU8T ieType;
NwU8T ieMinLength; NwU8T ieMinLength;
NwU8T ieInstance; NwU8T ieInstance;
@@ -59,8 +58,7 @@ typedef struct NwGtpv2cMsgIeInfo
} NwGtpv2cMsgIeInfoT; } NwGtpv2cMsgIeInfoT;
static static
NwGtpv2cMsgIeInfoT createSessionReqBearerCtxtTobeCreatedIeInfoTbl[] = NwGtpv2cMsgIeInfoT createSessionReqBearerCtxtTobeCreatedIeInfoTbl[] = {
{
{ NW_GTPV2C_IE_EBI , 1, NW_GTPV2C_IE_INSTANCE_ZERO , NW_GTPV2C_IE_PRESENCE_MANDATORY , NULL}, { NW_GTPV2C_IE_EBI , 1, NW_GTPV2C_IE_INSTANCE_ZERO , NW_GTPV2C_IE_PRESENCE_MANDATORY , NULL},
{ NW_GTPV2C_IE_BEARER_TFT , 0, NW_GTPV2C_IE_INSTANCE_ZERO , NW_GTPV2C_IE_PRESENCE_OPTIONAL , NULL}, { NW_GTPV2C_IE_BEARER_TFT , 0, NW_GTPV2C_IE_INSTANCE_ZERO , NW_GTPV2C_IE_PRESENCE_OPTIONAL , NULL},
{ NW_GTPV2C_IE_FTEID , 9, NW_GTPV2C_IE_INSTANCE_ZERO , NW_GTPV2C_IE_PRESENCE_CONDITIONAL , NULL}, { NW_GTPV2C_IE_FTEID , 9, NW_GTPV2C_IE_INSTANCE_ZERO , NW_GTPV2C_IE_PRESENCE_CONDITIONAL , NULL},
@@ -69,15 +67,14 @@ NwGtpv2cMsgIeInfoT createSessionReqBearerCtxtTobeCreatedIeInfoTbl[] =
{ NW_GTPV2C_IE_FTEID , 9, NW_GTPV2C_IE_INSTANCE_THREE , NW_GTPV2C_IE_PRESENCE_CONDITIONAL , NULL}, { NW_GTPV2C_IE_FTEID , 9, NW_GTPV2C_IE_INSTANCE_THREE , NW_GTPV2C_IE_PRESENCE_CONDITIONAL , NULL},
{ NW_GTPV2C_IE_FTEID , 9, NW_GTPV2C_IE_INSTANCE_FOUR , NW_GTPV2C_IE_PRESENCE_CONDITIONAL , NULL}, { NW_GTPV2C_IE_FTEID , 9, NW_GTPV2C_IE_INSTANCE_FOUR , NW_GTPV2C_IE_PRESENCE_CONDITIONAL , NULL},
{ NW_GTPV2C_IE_BEARER_LEVEL_QOS, 18, NW_GTPV2C_IE_INSTANCE_ZERO , NW_GTPV2C_IE_PRESENCE_MANDATORY , NULL}, { NW_GTPV2C_IE_BEARER_LEVEL_QOS, 18, NW_GTPV2C_IE_INSTANCE_ZERO , NW_GTPV2C_IE_PRESENCE_MANDATORY , NULL},
// { NW_GTPV2C_IE_IMSI , 0, NW_GTPV2C_IE_INSTANCE_ZERO , NW_GTPV2C_IE_PRESENCE_CONDITIONAL , NULL}, // { NW_GTPV2C_IE_IMSI , 0, NW_GTPV2C_IE_INSTANCE_ZERO , NW_GTPV2C_IE_PRESENCE_CONDITIONAL , NULL},
/* Do not add below this */ /* Do not add below this */
{ 0, 0, 0} { 0, 0, 0}
}; };
static static
NwGtpv2cMsgIeInfoT createSessionReqBearerCtxtTobeRemovedIeInfoTbl[] = NwGtpv2cMsgIeInfoT createSessionReqBearerCtxtTobeRemovedIeInfoTbl[] = {
{
{ NW_GTPV2C_IE_IMSI , 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL}, { NW_GTPV2C_IE_IMSI , 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL},
/* Do not add below this */ /* Do not add below this */
@@ -85,17 +82,15 @@ NwGtpv2cMsgIeInfoT createSessionReqBearerCtxtTobeRemovedIeInfoTbl[] =
}; };
static static
NwGtpv2cMsgIeInfoT echoRspIeInfoTbl[] = NwGtpv2cMsgIeInfoT echoRspIeInfoTbl[] = {
{
{ NW_GTPV2C_IE_RECOVERY , 1, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_MANDATORY, NULL}, { NW_GTPV2C_IE_RECOVERY , 1, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_MANDATORY, NULL},
/* Do not add below this */ /* Do not add below this */
{ 0, 0, 0} { 0, 0, 0}
}; };
static static
NwGtpv2cMsgIeInfoT createSessionReqIeInfoTbl[] = NwGtpv2cMsgIeInfoT createSessionReqIeInfoTbl[] = {
{
{ NW_GTPV2C_IE_IMSI , 8, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL}, { NW_GTPV2C_IE_IMSI , 8, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL},
{ NW_GTPV2C_IE_MSISDN , 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL}, { NW_GTPV2C_IE_MSISDN , 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL},
{ NW_GTPV2C_IE_MEI , 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL}, { NW_GTPV2C_IE_MEI , 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL},
@@ -128,8 +123,7 @@ NwGtpv2cMsgIeInfoT createSessionReqIeInfoTbl[] =
}; };
static static
NwGtpv2cMsgIeInfoT modifyBearerReqIeInfoTbl[] = NwGtpv2cMsgIeInfoT modifyBearerReqIeInfoTbl[] = {
{
{ NW_GTPV2C_IE_MEI , 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL }, { NW_GTPV2C_IE_MEI , 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL },
{ NW_GTPV2C_IE_SERVING_NETWORK, 3, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL}, { NW_GTPV2C_IE_SERVING_NETWORK, 3, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL},
{ NW_GTPV2C_IE_ULI , 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL }, { NW_GTPV2C_IE_ULI , 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL },
@@ -145,8 +139,7 @@ NwGtpv2cMsgIeInfoT modifyBearerReqIeInfoTbl[] =
}; };
static static
NwGtpv2cMsgIeInfoT deleteSessionReqIeInfoTbl[] = NwGtpv2cMsgIeInfoT deleteSessionReqIeInfoTbl[] = {
{
{ NW_GTPV2C_IE_CAUSE , 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL }, { NW_GTPV2C_IE_CAUSE , 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL },
{ NW_GTPV2C_IE_EBI , 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL }, { NW_GTPV2C_IE_EBI , 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL },
{ NW_GTPV2C_IE_ULI , 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL }, { NW_GTPV2C_IE_ULI , 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL },
@@ -160,8 +153,7 @@ NwGtpv2cMsgIeInfoT deleteSessionReqIeInfoTbl[] =
}; };
static static
NwGtpv2cMsgIeInfoT createSessionRspIeInfoTbl[] = NwGtpv2cMsgIeInfoT createSessionRspIeInfoTbl[] = {
{
{ NW_GTPV2C_IE_CAUSE , 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_MANDATORY , NULL }, { NW_GTPV2C_IE_CAUSE , 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_MANDATORY , NULL },
{ NW_GTPV2C_IE_PAA , 5, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL }, { NW_GTPV2C_IE_PAA , 5, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL },
{ NW_GTPV2C_IE_APN_RESTRICTION, 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL }, { NW_GTPV2C_IE_APN_RESTRICTION, 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL },
@@ -177,8 +169,7 @@ NwGtpv2cMsgIeInfoT createSessionRspIeInfoTbl[] =
}; };
static static
NwGtpv2cMsgIeInfoT modifyBearerRspIeInfoTbl[] = NwGtpv2cMsgIeInfoT modifyBearerRspIeInfoTbl[] = {
{
{ NW_GTPV2C_IE_CAUSE , 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_MANDATORY , NULL }, { NW_GTPV2C_IE_CAUSE , 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_MANDATORY , NULL },
{ NW_GTPV2C_IE_PAA , 5, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL }, { NW_GTPV2C_IE_PAA , 5, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL },
{ NW_GTPV2C_IE_APN_RESTRICTION, 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL }, { NW_GTPV2C_IE_APN_RESTRICTION, 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL },
@@ -192,8 +183,7 @@ NwGtpv2cMsgIeInfoT modifyBearerRspIeInfoTbl[] =
}; };
static static
NwGtpv2cMsgIeInfoT deleteSessionRspIeInfoTbl[] = NwGtpv2cMsgIeInfoT deleteSessionRspIeInfoTbl[] = {
{
{ NW_GTPV2C_IE_CAUSE , 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_MANDATORY , NULL }, { NW_GTPV2C_IE_CAUSE , 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_MANDATORY , NULL },
{ NW_GTPV2C_IE_RECOVERY , 1, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL }, { NW_GTPV2C_IE_RECOVERY , 1, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL },
{ NW_GTPV2C_IE_PCO , 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL }, { NW_GTPV2C_IE_PCO , 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL },
@@ -205,165 +195,156 @@ NwGtpv2cMsgIeInfoT deleteSessionRspIeInfoTbl[] =
/* Message sent over s10 interface */ /* Message sent over s10 interface */
static static
NwGtpv2cMsgIeInfoT identificationReqIeInfoTbl[] = NwGtpv2cMsgIeInfoT identificationReqIeInfoTbl[] = {
{ { NW_GTPV2C_IE_GUTI , 6, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL },
{ NW_GTPV2C_IE_GUTI , 6, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL }, { NW_GTPV2C_IE_COMPLETE_REQUEST_MESSAGE, 1, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL },
{ NW_GTPV2C_IE_COMPLETE_REQUEST_MESSAGE, 1, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL }, { NW_GTPV2C_IE_SERVING_NETWORK, 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL_OPTIONAL, NULL },
{ NW_GTPV2C_IE_SERVING_NETWORK, 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL_OPTIONAL, NULL }, { NW_GTPV2C_IE_PRIVATE_EXTENSION, 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_OPTIONAL , NULL },
{ NW_GTPV2C_IE_PRIVATE_EXTENSION, 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_OPTIONAL , NULL },
/* Do not add below this */ /* Do not add below this */
{ 0, 0, 0} { 0, 0, 0}
}; };
static static
NwGtpv2cMsgIeInfoT identificationRspIeInfoTbl[] = NwGtpv2cMsgIeInfoT identificationRspIeInfoTbl[] = {
{ { NW_GTPV2C_IE_CAUSE , 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_MANDATORY , NULL },
{ NW_GTPV2C_IE_CAUSE , 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_MANDATORY , NULL }, { NW_GTPV2C_IE_IMSI , 8, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL },
{ NW_GTPV2C_IE_IMSI , 8, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL }, { NW_GTPV2C_IE_MM_CONTEXT , 1, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL },
{ NW_GTPV2C_IE_MM_CONTEXT , 1, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL }, { NW_GTPV2C_IE_TRACE_INFORMATION, 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL_OPTIONAL, NULL },
{ NW_GTPV2C_IE_TRACE_INFORMATION, 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL_OPTIONAL, NULL }, { NW_GTPV2C_IE_PRIVATE_EXTENSION, 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_OPTIONAL , NULL },
{ NW_GTPV2C_IE_PRIVATE_EXTENSION, 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_OPTIONAL , NULL },
/* Do not add below this */ /* Do not add below this */
{ 0, 0, 0} { 0, 0, 0}
}; };
static static
NwGtpv2cMsgIeInfoT contextReqIeInfoTbl[] = NwGtpv2cMsgIeInfoT contextReqIeInfoTbl[] = {
{ { NW_GTPV2C_IE_IMSI , 8, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL },
{ NW_GTPV2C_IE_IMSI , 8, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL }, { NW_GTPV2C_IE_GUTI , 5, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL },
{ NW_GTPV2C_IE_GUTI , 5, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL }, { NW_GTPV2C_IE_ULI , 7, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL },
{ NW_GTPV2C_IE_ULI , 7, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL }, { NW_GTPV2C_IE_PTMSI , 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL },
{ NW_GTPV2C_IE_PTMSI , 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL }, { NW_GTPV2C_IE_COMPLETE_REQUEST_MESSAGE, 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL },
{ NW_GTPV2C_IE_COMPLETE_REQUEST_MESSAGE, 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL }, { NW_GTPV2C_IE_FTEID , 9, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL },
{ NW_GTPV2C_IE_FTEID , 9, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL }, { NW_GTPV2C_IE_UDP_SOURCE_PORT_NUMBER, 9, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL },
{ NW_GTPV2C_IE_UDP_SOURCE_PORT_NUMBER, 9, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL }, { NW_GTPV2C_IE_RAT_TYPE , 1, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL },
{ NW_GTPV2C_IE_RAT_TYPE , 1, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL }, { NW_GTPV2C_IE_INDICATION , 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_OPTIONAL , NULL },
{ NW_GTPV2C_IE_INDICATION , 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_OPTIONAL , NULL }, { NW_GTPV2C_IE_HOP_COUNTER , 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_OPTIONAL , NULL },
{ NW_GTPV2C_IE_HOP_COUNTER , 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_OPTIONAL , NULL }, { NW_GTPV2C_IE_SERVING_NETWORK, 3, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL_OPTIONAL, NULL },
{ NW_GTPV2C_IE_SERVING_NETWORK, 3, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL_OPTIONAL, NULL }, { NW_GTPV2C_IE_LDN , 3, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_OPTIONAL , NULL },
{ NW_GTPV2C_IE_LDN , 3, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_OPTIONAL , NULL }, { NW_GTPV2C_IE_PRIVATE_EXTENSION, 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_OPTIONAL , NULL },
{ NW_GTPV2C_IE_PRIVATE_EXTENSION, 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_OPTIONAL , NULL },
/* Do not add below this */ /* Do not add below this */
{ 0, 0, 0} { 0, 0, 0}
}; };
static static
NwGtpv2cMsgIeInfoT contextRspIeInfoTbl[] = NwGtpv2cMsgIeInfoT contextRspIeInfoTbl[] = {
{ { NW_GTPV2C_IE_CAUSE , 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_MANDATORY , NULL },
{ NW_GTPV2C_IE_CAUSE , 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_MANDATORY , NULL }, { NW_GTPV2C_IE_IMSI , 8, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL , NULL },
{ NW_GTPV2C_IE_IMSI , 8, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL , NULL }, { NW_GTPV2C_IE_MM_CONTEXT , 4, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL , NULL },
{ NW_GTPV2C_IE_MM_CONTEXT , 4, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL , NULL }, { NW_GTPV2C_IE_PDN_CONNECTION , 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL , NULL },
{ NW_GTPV2C_IE_PDN_CONNECTION , 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL , NULL }, { NW_GTPV2C_IE_FTEID , 9, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL , NULL },
{ NW_GTPV2C_IE_FTEID , 9, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL , NULL }, { NW_GTPV2C_IE_FTEID , 9, NW_GTPV2C_IE_INSTANCE_ONE , NW_GTPV2C_IE_PRESENCE_CONDITIONAL , NULL },
{ NW_GTPV2C_IE_FTEID , 9, NW_GTPV2C_IE_INSTANCE_ONE , NW_GTPV2C_IE_PRESENCE_CONDITIONAL , NULL }, { NW_GTPV2C_IE_FQDN , 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL , NULL },
{ NW_GTPV2C_IE_FQDN , 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL , NULL }, { NW_GTPV2C_IE_INDICATION , 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL , NULL },
{ NW_GTPV2C_IE_INDICATION , 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL , NULL }, { NW_GTPV2C_IE_TRACE_INFORMATION, 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL , NULL },
{ NW_GTPV2C_IE_TRACE_INFORMATION, 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL , NULL }, { NW_GTPV2C_IE_IP_ADDRESS , 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL , NULL },
{ NW_GTPV2C_IE_IP_ADDRESS , 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL , NULL }, { NW_GTPV2C_IE_IP_ADDRESS , 0, NW_GTPV2C_IE_INSTANCE_ONE , NW_GTPV2C_IE_PRESENCE_CONDITIONAL , NULL },
{ NW_GTPV2C_IE_IP_ADDRESS , 0, NW_GTPV2C_IE_INSTANCE_ONE , NW_GTPV2C_IE_PRESENCE_CONDITIONAL , NULL }, { NW_GTPV2C_IE_RFSP_INDEX , 2, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL_OPTIONAL, NULL },
{ NW_GTPV2C_IE_RFSP_INDEX , 2, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL_OPTIONAL, NULL }, { NW_GTPV2C_IE_RFSP_INDEX , 2, NW_GTPV2C_IE_INSTANCE_ONE , NW_GTPV2C_IE_PRESENCE_CONDITIONAL_OPTIONAL, NULL },
{ NW_GTPV2C_IE_RFSP_INDEX , 2, NW_GTPV2C_IE_INSTANCE_ONE , NW_GTPV2C_IE_PRESENCE_CONDITIONAL_OPTIONAL, NULL }, { NW_GTPV2C_IE_UE_TIME_ZONE , 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL_OPTIONAL, NULL },
{ NW_GTPV2C_IE_UE_TIME_ZONE , 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL_OPTIONAL, NULL }, { NW_GTPV2C_IE_LDN , 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_OPTIONAL , NULL },
{ NW_GTPV2C_IE_LDN , 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_OPTIONAL , NULL }, { NW_GTPV2C_IE_PRIVATE_EXTENSION, 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_OPTIONAL , NULL },
{ NW_GTPV2C_IE_PRIVATE_EXTENSION, 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_OPTIONAL , NULL },
/* Do not add below this */ /* Do not add below this */
{ 0, 0, 0} { 0, 0, 0}
}; };
static static
NwGtpv2cMsgIeInfoT contextAckIeInfoTbl[] = NwGtpv2cMsgIeInfoT contextAckIeInfoTbl[] = {
{ { NW_GTPV2C_IE_CAUSE , 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_MANDATORY , NULL },
{ NW_GTPV2C_IE_CAUSE , 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_MANDATORY , NULL }, { NW_GTPV2C_IE_INDICATION , 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL },
{ NW_GTPV2C_IE_INDICATION , 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL }, { NW_GTPV2C_IE_PRIVATE_EXTENSION, 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_OPTIONAL , NULL },
{ NW_GTPV2C_IE_PRIVATE_EXTENSION, 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_OPTIONAL , NULL },
/* Do not add below this */ /* Do not add below this */
{ 0, 0, 0} { 0, 0, 0}
}; };
static static
NwGtpv2cMsgIeInfoT forwardRelocationReqIeInfoTbl[] = NwGtpv2cMsgIeInfoT forwardRelocationReqIeInfoTbl[] = {
{ { NW_GTPV2C_IE_IMSI , 8, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL },
{ NW_GTPV2C_IE_IMSI , 8, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL }, { NW_GTPV2C_IE_FTEID , 9, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_MANDATORY , NULL },
{ NW_GTPV2C_IE_FTEID , 9, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_MANDATORY , NULL }, { NW_GTPV2C_IE_PDN_CONNECTION , 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_MANDATORY , NULL },
{ NW_GTPV2C_IE_PDN_CONNECTION , 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_MANDATORY , NULL }, { NW_GTPV2C_IE_FTEID , 9, NW_GTPV2C_IE_INSTANCE_ONE , NW_GTPV2C_IE_PRESENCE_MANDATORY , NULL },
{ NW_GTPV2C_IE_FTEID , 9, NW_GTPV2C_IE_INSTANCE_ONE , NW_GTPV2C_IE_PRESENCE_MANDATORY , NULL }, { NW_GTPV2C_IE_FQDN , 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL },
{ NW_GTPV2C_IE_FQDN , 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL }, { NW_GTPV2C_IE_MM_CONTEXT , 4, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_MANDATORY , NULL },
{ NW_GTPV2C_IE_MM_CONTEXT , 4, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_MANDATORY , NULL }, { NW_GTPV2C_IE_INDICATION , 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL },
{ NW_GTPV2C_IE_INDICATION , 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL }, { NW_GTPV2C_IE_F_CONTAINER , 1, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL },
{ NW_GTPV2C_IE_F_CONTAINER , 1, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL }, { NW_GTPV2C_IE_F_CONTAINER , 1, NW_GTPV2C_IE_INSTANCE_ONE , NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL },
{ NW_GTPV2C_IE_F_CONTAINER , 1, NW_GTPV2C_IE_INSTANCE_ONE , NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL }, { NW_GTPV2C_IE_TARGET_IDENTIFICATION, 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL },
{ NW_GTPV2C_IE_TARGET_IDENTIFICATION, 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL }, { NW_GTPV2C_IE_IP_ADDRESS , 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL },
{ NW_GTPV2C_IE_IP_ADDRESS , 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL }, { NW_GTPV2C_IE_IP_ADDRESS , 0, NW_GTPV2C_IE_INSTANCE_ONE , NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL },
{ NW_GTPV2C_IE_IP_ADDRESS , 0, NW_GTPV2C_IE_INSTANCE_ONE , NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL }, { NW_GTPV2C_IE_F_CAUSE , 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL },
{ NW_GTPV2C_IE_F_CAUSE , 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL }, { NW_GTPV2C_IE_F_CAUSE , 0, NW_GTPV2C_IE_INSTANCE_ONE , NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL },
{ NW_GTPV2C_IE_F_CAUSE , 0, NW_GTPV2C_IE_INSTANCE_ONE , NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL }, { NW_GTPV2C_IE_F_CONTAINER , 1, NW_GTPV2C_IE_INSTANCE_TWO , NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL },
{ NW_GTPV2C_IE_F_CONTAINER , 1, NW_GTPV2C_IE_INSTANCE_TWO , NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL }, { NW_GTPV2C_IE_SOURCE_IDENTIFICATION, 1, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL },
{ NW_GTPV2C_IE_SOURCE_IDENTIFICATION, 1, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL }, { NW_GTPV2C_IE_F_CAUSE , 0, NW_GTPV2C_IE_INSTANCE_TWO , NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL },
{ NW_GTPV2C_IE_F_CAUSE , 0, NW_GTPV2C_IE_INSTANCE_TWO , NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL }, { NW_GTPV2C_IE_SELECTED_PLMN_ID, 0, NW_GTPV2C_IE_INSTANCE_ONE , NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL },
{ NW_GTPV2C_IE_SELECTED_PLMN_ID, 0, NW_GTPV2C_IE_INSTANCE_ONE , NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL }, { NW_GTPV2C_IE_RECOVERY , 1, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL },
{ NW_GTPV2C_IE_RECOVERY , 1, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL }, { NW_GTPV2C_IE_TRACE_INFORMATION, 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL },
{ NW_GTPV2C_IE_TRACE_INFORMATION, 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL }, { NW_GTPV2C_IE_RFSP_INDEX , 2, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL_OPTIONAL, NULL },
{ NW_GTPV2C_IE_RFSP_INDEX , 2, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL_OPTIONAL, NULL }, { NW_GTPV2C_IE_RFSP_INDEX , 2, NW_GTPV2C_IE_INSTANCE_ONE , NW_GTPV2C_IE_PRESENCE_CONDITIONAL_OPTIONAL, NULL },
{ NW_GTPV2C_IE_RFSP_INDEX , 2, NW_GTPV2C_IE_INSTANCE_ONE , NW_GTPV2C_IE_PRESENCE_CONDITIONAL_OPTIONAL, NULL }, { NW_GTPV2C_IE_CSG_ID , 4, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL_OPTIONAL, NULL },
{ NW_GTPV2C_IE_CSG_ID , 4, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL_OPTIONAL, NULL }, { NW_GTPV2C_IE_CSG_MEMBERSHIP_INDICATION, 1, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL_OPTIONAL, NULL },
{ NW_GTPV2C_IE_CSG_MEMBERSHIP_INDICATION, 1, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL_OPTIONAL, NULL }, { NW_GTPV2C_IE_UE_TIME_ZONE , 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL_OPTIONAL, NULL },
{ NW_GTPV2C_IE_UE_TIME_ZONE , 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL_OPTIONAL, NULL }, { NW_GTPV2C_IE_LDN , 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_OPTIONAL , NULL },
{ NW_GTPV2C_IE_LDN , 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_OPTIONAL , NULL }, { NW_GTPV2C_IE_ADDITIONAL_MM_CTXT_FOR_SRVCC,0,NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL_OPTIONAL, NULL },
{ NW_GTPV2C_IE_ADDITIONAL_MM_CTXT_FOR_SRVCC,0,NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL_OPTIONAL, NULL }, { NW_GTPV2C_IE_ADDITIONAL_FLAGS_FOR_SRVCC, 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL_OPTIONAL, NULL },
{ NW_GTPV2C_IE_ADDITIONAL_FLAGS_FOR_SRVCC, 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL_OPTIONAL, NULL }, { NW_GTPV2C_IE_MSISDN , 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL_OPTIONAL, NULL },
{ NW_GTPV2C_IE_MSISDN , 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL_OPTIONAL, NULL }, { NW_GTPV2C_IE_PRIVATE_EXTENSION, 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_OPTIONAL , NULL },
{ NW_GTPV2C_IE_PRIVATE_EXTENSION, 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_OPTIONAL , NULL },
/* Do not add below this */ /* Do not add below this */
{ 0, 0, 0 } { 0, 0, 0 }
}; };
static static
NwGtpv2cMsgIeInfoT forwardRelocationRspIeInfoTbl[] = NwGtpv2cMsgIeInfoT forwardRelocationRspIeInfoTbl[] = {
{ { NW_GTPV2C_IE_CAUSE , 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_MANDATORY , NULL },
{ NW_GTPV2C_IE_CAUSE , 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_MANDATORY , NULL }, { NW_GTPV2C_IE_FTEID , 9, NW_GTPV2C_IE_INSTANCE_ONE , NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL },
{ NW_GTPV2C_IE_FTEID , 9, NW_GTPV2C_IE_INSTANCE_ONE , NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL }, { NW_GTPV2C_IE_INDICATION , 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL },
{ NW_GTPV2C_IE_INDICATION , 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL }, { NW_GTPV2C_IE_BEARER_CONTEXT , 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL },
{ NW_GTPV2C_IE_BEARER_CONTEXT , 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL }, { NW_GTPV2C_IE_BEARER_CONTEXT , 0, NW_GTPV2C_IE_INSTANCE_ONE , NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL },
{ NW_GTPV2C_IE_BEARER_CONTEXT , 0, NW_GTPV2C_IE_INSTANCE_ONE , NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL }, { NW_GTPV2C_IE_BEARER_CONTEXT , 0, NW_GTPV2C_IE_INSTANCE_TWO , NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL },
{ NW_GTPV2C_IE_BEARER_CONTEXT , 0, NW_GTPV2C_IE_INSTANCE_TWO , NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL }, { NW_GTPV2C_IE_F_CAUSE , 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL },
{ NW_GTPV2C_IE_F_CAUSE , 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL }, { NW_GTPV2C_IE_F_CAUSE , 0, NW_GTPV2C_IE_INSTANCE_ONE , NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL },
{ NW_GTPV2C_IE_F_CAUSE , 0, NW_GTPV2C_IE_INSTANCE_ONE , NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL }, { NW_GTPV2C_IE_F_CONTAINER , 1, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL },
{ NW_GTPV2C_IE_F_CONTAINER , 1, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL }, { NW_GTPV2C_IE_F_CONTAINER , 1, NW_GTPV2C_IE_INSTANCE_ONE , NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL },
{ NW_GTPV2C_IE_F_CONTAINER , 1, NW_GTPV2C_IE_INSTANCE_ONE , NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL }, { NW_GTPV2C_IE_F_CONTAINER , 1, NW_GTPV2C_IE_INSTANCE_TWO , NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL },
{ NW_GTPV2C_IE_F_CONTAINER , 1, NW_GTPV2C_IE_INSTANCE_TWO , NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL }, { NW_GTPV2C_IE_F_CAUSE , 0, NW_GTPV2C_IE_INSTANCE_TWO , NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL },
{ NW_GTPV2C_IE_F_CAUSE , 0, NW_GTPV2C_IE_INSTANCE_TWO , NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL }, { NW_GTPV2C_IE_LDN , 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_OPTIONAL , NULL },
{ NW_GTPV2C_IE_LDN , 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_OPTIONAL , NULL }, { NW_GTPV2C_IE_PRIVATE_EXTENSION, 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_OPTIONAL , NULL },
{ NW_GTPV2C_IE_PRIVATE_EXTENSION, 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_OPTIONAL , NULL },
/* Do not add below this */ /* Do not add below this */
{ 0, 0, 0} { 0, 0, 0}
}; };
static static
NwGtpv2cMsgIeInfoT forwardRelocationCompleteNtfIeInfoTbl[] = NwGtpv2cMsgIeInfoT forwardRelocationCompleteNtfIeInfoTbl[] = {
{ { NW_GTPV2C_IE_INDICATION , 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL },
{ NW_GTPV2C_IE_INDICATION , 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_CONDITIONAL, NULL }, { NW_GTPV2C_IE_PRIVATE_EXTENSION, 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_OPTIONAL , NULL },
{ NW_GTPV2C_IE_PRIVATE_EXTENSION, 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_OPTIONAL , NULL },
/* Do not add below this */ /* Do not add below this */
{ 0, 0, 0} { 0, 0, 0}
}; };
static static
NwGtpv2cMsgIeInfoT forwardRelocationCompleteAckIeInfoTbl[] = NwGtpv2cMsgIeInfoT forwardRelocationCompleteAckIeInfoTbl[] = {
{ { NW_GTPV2C_IE_CAUSE , 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_MANDATORY , NULL },
{ NW_GTPV2C_IE_CAUSE , 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_MANDATORY , NULL }, { NW_GTPV2C_IE_RECOVERY , 1, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_OPTIONAL , NULL },
{ NW_GTPV2C_IE_RECOVERY , 1, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_OPTIONAL , NULL }, { NW_GTPV2C_IE_PRIVATE_EXTENSION, 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_OPTIONAL , NULL },
{ NW_GTPV2C_IE_PRIVATE_EXTENSION, 0, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_OPTIONAL , NULL },
/* Do not add below this */ /* Do not add below this */
{ 0, 0, 0} { 0, 0, 0}
}; };
/*----------------------------------------------------------------------------* /*----------------------------------------------------------------------------*
@@ -373,16 +354,18 @@ NwGtpv2cMsgIeInfoT forwardRelocationCompleteAckIeInfoTbl[] =
static NwU32T static NwU32T
nwGtpv2cMsgGroupedIeCount(NwGtpv2cMsgIeInfoT *pMsgIeInfo) nwGtpv2cMsgGroupedIeCount(NwGtpv2cMsgIeInfoT *pMsgIeInfo)
{ {
NwU32T count = 0; NwU32T count = 0;
NwGtpv2cMsgIeInfoT *pGroupedIeInfo = pMsgIeInfo; NwGtpv2cMsgIeInfoT *pGroupedIeInfo = pMsgIeInfo;
while (pGroupedIeInfo++) {
if (pGroupedIeInfo->ieType == 0) { while (pGroupedIeInfo++) {
break; if (pGroupedIeInfo->ieType == 0) {
} break;
count ++;
} }
return count; count ++;
}
return count;
} }
static NwRcT static NwRcT
@@ -391,52 +374,53 @@ nwGtpv2cMsgIeParseInfoUpdate(NwGtpv2cMsgIeParseInfoT *thiz,
{ {
NwU32T i, j; NwU32T i, j;
for (i = 0; pMsgIeInfo[i].ieType; i++) for (i = 0; pMsgIeInfo[i].ieType; i++) {
{
if (pMsgIeInfo[i].pGroupedIeInfo) { if (pMsgIeInfo[i].pGroupedIeInfo) {
NwGtpv2cGroupedIeParseInfoT *pMsgIeParseInfo; NwGtpv2cGroupedIeParseInfoT *pMsgIeParseInfo;
NW_GTPV2C_MALLOC(thiz->hStack, sizeof(NwGtpv2cGroupedIeParseInfoT), NW_GTPV2C_MALLOC(thiz->hStack, sizeof(NwGtpv2cGroupedIeParseInfoT),
pMsgIeParseInfo, NwGtpv2cGroupedIeParseInfoT*); pMsgIeParseInfo, NwGtpv2cGroupedIeParseInfoT*);
pMsgIeParseInfo->groupedIeType = pMsgIeInfo[i].ieType; pMsgIeParseInfo->groupedIeType = pMsgIeInfo[i].ieType;
pMsgIeParseInfo->hStack = thiz->hStack; pMsgIeParseInfo->hStack = thiz->hStack;
for (j = 0; pMsgIeInfo[i].pGroupedIeInfo[j].ieType; j++) { for (j = 0; pMsgIeInfo[i].pGroupedIeInfo[j].ieType; j++) {
pMsgIeParseInfo->ieParseInfo[pMsgIeInfo[i].pGroupedIeInfo[j].ieType][pMsgIeInfo[i].pGroupedIeInfo[j].ieInstance].ieMinLength = pMsgIeParseInfo->ieParseInfo[pMsgIeInfo[i].pGroupedIeInfo[j].ieType][pMsgIeInfo[i].pGroupedIeInfo[j].ieInstance].ieMinLength =
pMsgIeInfo[i].pGroupedIeInfo[j].ieMinLength; pMsgIeInfo[i].pGroupedIeInfo[j].ieMinLength;
pMsgIeParseInfo->ieParseInfo[pMsgIeInfo[i].pGroupedIeInfo[j].ieType][pMsgIeInfo[i].pGroupedIeInfo[j].ieInstance].iePresence = pMsgIeParseInfo->ieParseInfo[pMsgIeInfo[i].pGroupedIeInfo[j].ieType][pMsgIeInfo[i].pGroupedIeInfo[j].ieInstance].iePresence =
pMsgIeInfo[i].pGroupedIeInfo[j].iePresence; pMsgIeInfo[i].pGroupedIeInfo[j].iePresence;
if(pMsgIeInfo[i].pGroupedIeInfo[j].iePresence == NW_GTPV2C_IE_PRESENCE_MANDATORY) if(pMsgIeInfo[i].pGroupedIeInfo[j].iePresence == NW_GTPV2C_IE_PRESENCE_MANDATORY)
pMsgIeParseInfo->mandatoryIeCount++; pMsgIeParseInfo->mandatoryIeCount++;
} }
thiz->ieParseInfo[pMsgIeInfo[i].ieType][pMsgIeInfo[i].ieInstance].pGroupedIeInfo = pMsgIeParseInfo;
thiz->ieParseInfo[pMsgIeInfo[i].ieType][pMsgIeInfo[i].ieInstance].pGroupedIeInfo = pMsgIeParseInfo;
} else { } else {
thiz->ieParseInfo[pMsgIeInfo[i].ieType][pMsgIeInfo[i].ieInstance].pGroupedIeInfo = NULL; thiz->ieParseInfo[pMsgIeInfo[i].ieType][pMsgIeInfo[i].ieInstance].pGroupedIeInfo = NULL;
} }
thiz->ieParseInfo[pMsgIeInfo[i].ieType][pMsgIeInfo[i].ieInstance].iePresence = pMsgIeInfo[i].iePresence; thiz->ieParseInfo[pMsgIeInfo[i].ieType][pMsgIeInfo[i].ieInstance].iePresence = pMsgIeInfo[i].iePresence;
thiz->ieParseInfo[pMsgIeInfo[i].ieType][pMsgIeInfo[i].ieInstance].ieMinLength = pMsgIeInfo[i].ieMinLength; thiz->ieParseInfo[pMsgIeInfo[i].ieType][pMsgIeInfo[i].ieInstance].ieMinLength = pMsgIeInfo[i].ieMinLength;
if(pMsgIeInfo[i].iePresence == NW_GTPV2C_IE_PRESENCE_MANDATORY) if(pMsgIeInfo[i].iePresence == NW_GTPV2C_IE_PRESENCE_MANDATORY)
thiz->mandatoryIeCount++; thiz->mandatoryIeCount++;
} }
return NW_OK; return NW_OK;
} }
static NwRcT static NwRcT
nwGtpv2cMsgGroupedIeParse(NW_IN NwGtpv2cGroupedIeParseInfoT* thiz, nwGtpv2cMsgGroupedIeParse(NW_IN NwGtpv2cGroupedIeParseInfoT* thiz,
NW_IN NwU8T ieType, NW_IN NwU8T ieType,
NW_IN NwU16T ieLength, NW_IN NwU16T ieLength,
NW_IN NwU8T ieInstance, NW_IN NwU8T ieInstance,
NW_IN NwU8T *pIeValue) NW_IN NwU8T *pIeValue)
{ {
NW_ASSERT(thiz); NW_ASSERT(thiz);
NW_LOG(thiz->hStack, NW_LOG_LEVEL_DEBG, "Received grouped IE %u with instance %u of length %u in msg-type %u!", NW_LOG(thiz->hStack, NW_LOG_LEVEL_DEBG, "Received grouped IE %u with instance %u of length %u in msg-type %u!",
ieType, ieInstance, ieLength, thiz->groupedIeType); ieType, ieInstance, ieLength, thiz->groupedIeType);
return NW_OK; return NW_OK;
} }
@@ -454,121 +438,117 @@ nwGtpv2cMsgIeParseInfoNew(NwGtpv2cStackHandleT hStack, NwU8T msgType)
{ {
NwRcT rc; NwRcT rc;
NwGtpv2cMsgIeParseInfoT *thiz; NwGtpv2cMsgIeParseInfoT *thiz;
NW_GTPV2C_MALLOC(hStack, sizeof(NwGtpv2cMsgIeParseInfoT), thiz, NwGtpv2cMsgIeParseInfoT*); NW_GTPV2C_MALLOC(hStack, sizeof(NwGtpv2cMsgIeParseInfoT), thiz, NwGtpv2cMsgIeParseInfoT*);
if(thiz) if(thiz) {
{
memset(thiz, 0, sizeof(NwGtpv2cMsgIeParseInfoT)); memset(thiz, 0, sizeof(NwGtpv2cMsgIeParseInfoT));
thiz->hStack = hStack; thiz->hStack = hStack;
thiz->msgType = msgType; thiz->msgType = msgType;
switch(msgType) switch(msgType) {
{ case NW_GTP_ECHO_RSP: {
case NW_GTP_ECHO_RSP: rc = nwGtpv2cMsgIeParseInfoUpdate(thiz, echoRspIeInfoTbl);
{ NW_ASSERT(NW_OK == rc);
rc = nwGtpv2cMsgIeParseInfoUpdate(thiz, echoRspIeInfoTbl); }
NW_ASSERT(NW_OK == rc); break;
}
break;
case NW_GTP_CREATE_SESSION_REQ:
{
rc = nwGtpv2cMsgIeParseInfoUpdate(thiz, createSessionReqIeInfoTbl);
NW_ASSERT(NW_OK == rc);
}
break;
case NW_GTP_CREATE_SESSION_RSP:
{
rc = nwGtpv2cMsgIeParseInfoUpdate(thiz, createSessionRspIeInfoTbl);
NW_ASSERT(NW_OK == rc);
}
break;
case NW_GTP_DELETE_SESSION_REQ:
{
rc = nwGtpv2cMsgIeParseInfoUpdate(thiz, deleteSessionReqIeInfoTbl);
NW_ASSERT(NW_OK == rc);
}
break;
case NW_GTP_DELETE_SESSION_RSP:
{
rc = nwGtpv2cMsgIeParseInfoUpdate(thiz, deleteSessionRspIeInfoTbl);
NW_ASSERT(NW_OK == rc);
}
break;
case NW_GTP_MODIFY_BEARER_REQ:
{
rc = nwGtpv2cMsgIeParseInfoUpdate(thiz, modifyBearerReqIeInfoTbl);
NW_ASSERT(NW_OK == rc);
}
break;
case NW_GTP_MODIFY_BEARER_RSP:
{
rc = nwGtpv2cMsgIeParseInfoUpdate(thiz, modifyBearerRspIeInfoTbl);
NW_ASSERT(NW_OK == rc);
}
break;
case NW_GTP_FORWARD_RELOCATION_REQ:
{
rc = nwGtpv2cMsgIeParseInfoUpdate(thiz, forwardRelocationReqIeInfoTbl);
NW_ASSERT(NW_OK == rc);
}
break;
case NW_GTP_FORWARD_RELOCATION_RSP:
{
rc = nwGtpv2cMsgIeParseInfoUpdate(thiz, forwardRelocationRspIeInfoTbl);
NW_ASSERT(NW_OK == rc);
}
break;
case NW_GTP_FORWARD_RELOCATION_COMPLETE_NTF:
{
rc = nwGtpv2cMsgIeParseInfoUpdate(thiz, forwardRelocationCompleteNtfIeInfoTbl);
NW_ASSERT(NW_OK == rc);
}
break;
case NW_GTP_FORWARD_RELOCATION_COMPLETE_ACK:
{
rc = nwGtpv2cMsgIeParseInfoUpdate(thiz, forwardRelocationCompleteAckIeInfoTbl);
NW_ASSERT(NW_OK == rc);
}
break;
case NW_GTP_CONTEXT_REQ:
{
rc = nwGtpv2cMsgIeParseInfoUpdate(thiz, contextReqIeInfoTbl);
NW_ASSERT(NW_OK == rc);
}
break;
case NW_GTP_CONTEXT_RSP:
{
rc = nwGtpv2cMsgIeParseInfoUpdate(thiz, contextRspIeInfoTbl);
NW_ASSERT(NW_OK == rc);
}
break;
case NW_GTP_CONTEXT_ACK:
{
rc = nwGtpv2cMsgIeParseInfoUpdate(thiz, contextAckIeInfoTbl);
NW_ASSERT(NW_OK == rc);
}
break;
case NW_GTP_IDENTIFICATION_REQ:
{
rc = nwGtpv2cMsgIeParseInfoUpdate(thiz, identificationReqIeInfoTbl);
NW_ASSERT(NW_OK == rc);
}
break;
case NW_GTP_IDENTIFICATION_RSP:
{
rc = nwGtpv2cMsgIeParseInfoUpdate(thiz, identificationRspIeInfoTbl);
NW_ASSERT(NW_OK == rc);
}
break;
default: case NW_GTP_CREATE_SESSION_REQ: {
{ rc = nwGtpv2cMsgIeParseInfoUpdate(thiz, createSessionReqIeInfoTbl);
free(thiz); NW_ASSERT(NW_OK == rc);
thiz = NULL; }
} break;
break;
case NW_GTP_CREATE_SESSION_RSP: {
rc = nwGtpv2cMsgIeParseInfoUpdate(thiz, createSessionRspIeInfoTbl);
NW_ASSERT(NW_OK == rc);
}
break;
case NW_GTP_DELETE_SESSION_REQ: {
rc = nwGtpv2cMsgIeParseInfoUpdate(thiz, deleteSessionReqIeInfoTbl);
NW_ASSERT(NW_OK == rc);
}
break;
case NW_GTP_DELETE_SESSION_RSP: {
rc = nwGtpv2cMsgIeParseInfoUpdate(thiz, deleteSessionRspIeInfoTbl);
NW_ASSERT(NW_OK == rc);
}
break;
case NW_GTP_MODIFY_BEARER_REQ: {
rc = nwGtpv2cMsgIeParseInfoUpdate(thiz, modifyBearerReqIeInfoTbl);
NW_ASSERT(NW_OK == rc);
}
break;
case NW_GTP_MODIFY_BEARER_RSP: {
rc = nwGtpv2cMsgIeParseInfoUpdate(thiz, modifyBearerRspIeInfoTbl);
NW_ASSERT(NW_OK == rc);
}
break;
case NW_GTP_FORWARD_RELOCATION_REQ: {
rc = nwGtpv2cMsgIeParseInfoUpdate(thiz, forwardRelocationReqIeInfoTbl);
NW_ASSERT(NW_OK == rc);
}
break;
case NW_GTP_FORWARD_RELOCATION_RSP: {
rc = nwGtpv2cMsgIeParseInfoUpdate(thiz, forwardRelocationRspIeInfoTbl);
NW_ASSERT(NW_OK == rc);
}
break;
case NW_GTP_FORWARD_RELOCATION_COMPLETE_NTF: {
rc = nwGtpv2cMsgIeParseInfoUpdate(thiz, forwardRelocationCompleteNtfIeInfoTbl);
NW_ASSERT(NW_OK == rc);
}
break;
case NW_GTP_FORWARD_RELOCATION_COMPLETE_ACK: {
rc = nwGtpv2cMsgIeParseInfoUpdate(thiz, forwardRelocationCompleteAckIeInfoTbl);
NW_ASSERT(NW_OK == rc);
}
break;
case NW_GTP_CONTEXT_REQ: {
rc = nwGtpv2cMsgIeParseInfoUpdate(thiz, contextReqIeInfoTbl);
NW_ASSERT(NW_OK == rc);
}
break;
case NW_GTP_CONTEXT_RSP: {
rc = nwGtpv2cMsgIeParseInfoUpdate(thiz, contextRspIeInfoTbl);
NW_ASSERT(NW_OK == rc);
}
break;
case NW_GTP_CONTEXT_ACK: {
rc = nwGtpv2cMsgIeParseInfoUpdate(thiz, contextAckIeInfoTbl);
NW_ASSERT(NW_OK == rc);
}
break;
case NW_GTP_IDENTIFICATION_REQ: {
rc = nwGtpv2cMsgIeParseInfoUpdate(thiz, identificationReqIeInfoTbl);
NW_ASSERT(NW_OK == rc);
}
break;
case NW_GTP_IDENTIFICATION_RSP: {
rc = nwGtpv2cMsgIeParseInfoUpdate(thiz, identificationRspIeInfoTbl);
NW_ASSERT(NW_OK == rc);
}
break;
default: {
free(thiz);
thiz = NULL;
}
break;
} }
} }
@@ -588,14 +568,14 @@ nwGtpv2cMsgIeParseInfoDelete(NwGtpv2cMsgIeParseInfoT* thiz)
} }
/** /**
* Parse message * Parse message
* @return NW_OK on success. * @return NW_OK on success.
*/ */
NwRcT NwRcT
nwGtpv2cMsgIeParse(NW_IN NwGtpv2cMsgIeParseInfoT* thiz, nwGtpv2cMsgIeParse(NW_IN NwGtpv2cMsgIeParseInfoT* thiz,
NW_IN NwGtpv2cMsgHandleT hMsg, NW_IN NwGtpv2cMsgHandleT hMsg,
NW_INOUT NwGtpv2cErrorT *pError) NW_INOUT NwGtpv2cErrorT *pError)
{ {
NwRcT rc = NW_OK; NwRcT rc = NW_OK;
NwU16T mandatoryIeCount =0; NwU16T mandatoryIeCount =0;
@@ -614,8 +594,7 @@ nwGtpv2cMsgIeParse(NW_IN NwGtpv2cMsgIeParseInfoT* thiz,
//memset(pMsg->pIe, 0, sizeof(NwU8T*) * (NW_GTPV2C_IE_TYPE_MAXIMUM) * (NW_GTPV2C_IE_INSTANCE_MAXIMUM)); //memset(pMsg->pIe, 0, sizeof(NwU8T*) * (NW_GTPV2C_IE_TYPE_MAXIMUM) * (NW_GTPV2C_IE_INSTANCE_MAXIMUM));
memset(pMsg->isIeValid, (NW_FALSE), sizeof(NwU8T) * (NW_GTPV2C_IE_TYPE_MAXIMUM) * (NW_GTPV2C_IE_INSTANCE_MAXIMUM)); memset(pMsg->isIeValid, (NW_FALSE), sizeof(NwU8T) * (NW_GTPV2C_IE_TYPE_MAXIMUM) * (NW_GTPV2C_IE_INSTANCE_MAXIMUM));
while (pIeBufStart < pIeBufEnd) while (pIeBufStart < pIeBufEnd) {
{
pIe = (NwGtpv2cIeTlvT*) pIeBufStart; pIe = (NwGtpv2cIeTlvT*) pIeBufStart;
ieType = pIe->t; ieType = pIe->t;
ieLength = ntohs(pIe->l); ieLength = ntohs(pIe->l);
@@ -624,8 +603,8 @@ nwGtpv2cMsgIeParse(NW_IN NwGtpv2cMsgIeParseInfoT* thiz,
NW_ASSERT(NW_GTPV2C_IE_INSTANCE_MAXIMUM >= ieInstance); NW_ASSERT(NW_GTPV2C_IE_INSTANCE_MAXIMUM >= ieInstance);
NW_LOG(thiz->hStack, NW_LOG_LEVEL_DEBG, "Received IE %u with instance %u of length %u in msg-type %u!", ieType, ieInstance, ieLength, thiz->msgType); NW_LOG(thiz->hStack, NW_LOG_LEVEL_DEBG, "Received IE %u with instance %u of length %u in msg-type %u!", ieType, ieInstance, ieLength, thiz->msgType);
if(pIeBufStart + 4 + ieLength > pIeBufEnd)
{ if(pIeBufStart + 4 + ieLength > pIeBufEnd) {
NW_LOG(thiz->hStack, NW_LOG_LEVEL_ERRO, "Invalid length for IE of type %u and instance %u!", ieType, ieInstance); NW_LOG(thiz->hStack, NW_LOG_LEVEL_ERRO, "Invalid length for IE of type %u and instance %u!", ieType, ieInstance);
pError->cause = NW_GTPV2C_CAUSE_INVALID_LENGTH; pError->cause = NW_GTPV2C_CAUSE_INVALID_LENGTH;
pError->offendingIe.type = ieType; pError->offendingIe.type = ieType;
@@ -633,18 +612,13 @@ nwGtpv2cMsgIeParse(NW_IN NwGtpv2cMsgIeParseInfoT* thiz,
return NW_FAILURE; return NW_FAILURE;
} }
if((thiz->ieParseInfo[ieType][ieInstance].iePresence)) if((thiz->ieParseInfo[ieType][ieInstance].iePresence)) {
{ if((ieLength < (thiz->ieParseInfo[ieType][ieInstance].ieMinLength))) {
if((ieLength < (thiz->ieParseInfo[ieType][ieInstance].ieMinLength))) if(thiz->ieParseInfo[ieType][ieInstance].iePresence == NW_GTPV2C_IE_PRESENCE_OPTIONAL) {
{
if(thiz->ieParseInfo[ieType][ieInstance].iePresence == NW_GTPV2C_IE_PRESENCE_OPTIONAL)
{
/* Ignore TLV */ /* Ignore TLV */
pIeBufStart += (ieLength + 4); pIeBufStart += (ieLength + 4);
continue; continue;
} } else {
else
{
pError->cause = NW_GTPV2C_CAUSE_MANDATORY_IE_INCORRECT; pError->cause = NW_GTPV2C_CAUSE_MANDATORY_IE_INCORRECT;
pError->offendingIe.type = ieType; pError->offendingIe.type = ieType;
pError->offendingIe.instance = ieInstance; pError->offendingIe.instance = ieInstance;
@@ -653,28 +627,27 @@ nwGtpv2cMsgIeParse(NW_IN NwGtpv2cMsgIeParseInfoT* thiz,
} }
} }
if(pMsg->isIeValid[ieType][ieInstance] == NW_TRUE) if(pMsg->isIeValid[ieType][ieInstance] == NW_TRUE) {
{ /*
/* * If an information element is repeated in a GTP signalling
* If an information element is repeated in a GTP signalling * message in which repetition of the information element is
* message in which repetition of the information element is * not specified, only the contents of the information element
* not specified, only the contents of the information element * appearing first shall be handled and all subsequent repetitions
* appearing first shall be handled and all subsequent repetitions * of the information element shall be ignored.
* of the information element shall be ignored.
* TODO: Add handling for IEs for which repetition is allowed. * TODO: Add handling for IEs for which repetition is allowed.
*/ */
pIeBufStart += (ieLength + 4); pIeBufStart += (ieLength + 4);
continue; continue;
} }
pMsg->pIe[ieType][ieInstance] = (NwU8T*) pIeBufStart; pMsg->pIe[ieType][ieInstance] = (NwU8T*) pIeBufStart;
pMsg->isIeValid[ieType][ieInstance] = NW_TRUE; pMsg->isIeValid[ieType][ieInstance] = NW_TRUE;
if(thiz->ieParseInfo[ieType][ieInstance].pGroupedIeInfo) if(thiz->ieParseInfo[ieType][ieInstance].pGroupedIeInfo) {
{
/* Parse the grouped IE */ /* Parse the grouped IE */
rc = nwGtpv2cMsgGroupedIeParse(thiz->ieParseInfo[ieType][ieInstance].pGroupedIeInfo, ieType, ieLength, ieInstance, ((NwU8T*) pIe) + 4); rc = nwGtpv2cMsgGroupedIeParse(thiz->ieParseInfo[ieType][ieInstance].pGroupedIeInfo, ieType, ieLength, ieInstance, ((NwU8T*) pIe) + 4);
if (rc != NW_OK)
{ if (rc != NW_OK) {
pError->cause = NW_GTPV2C_CAUSE_MANDATORY_IE_INCORRECT; pError->cause = NW_GTPV2C_CAUSE_MANDATORY_IE_INCORRECT;
pError->offendingIe.type = ieType; pError->offendingIe.type = ieType;
pError->offendingIe.instance = ieInstance; pError->offendingIe.instance = ieInstance;
@@ -683,29 +656,21 @@ nwGtpv2cMsgIeParse(NW_IN NwGtpv2cMsgIeParseInfoT* thiz,
} }
} }
if(thiz->ieParseInfo[ieType][ieInstance].iePresence == NW_GTPV2C_IE_PRESENCE_MANDATORY) if(thiz->ieParseInfo[ieType][ieInstance].iePresence == NW_GTPV2C_IE_PRESENCE_MANDATORY) {
{
mandatoryIeCount++; mandatoryIeCount++;
} }
} } else {
else
{
NW_LOG(thiz->hStack, NW_LOG_LEVEL_WARN, "Unexpected IE %u with instance %u of length %u received in msg %u!", ieType, ieInstance, ieLength, thiz->msgType); NW_LOG(thiz->hStack, NW_LOG_LEVEL_WARN, "Unexpected IE %u with instance %u of length %u received in msg %u!", ieType, ieInstance, ieLength, thiz->msgType);
} }
pIeBufStart += (ieLength + 4); pIeBufStart += (ieLength + 4);
} }
if((NW_OK == rc) && (mandatoryIeCount != thiz->mandatoryIeCount)) if((NW_OK == rc) && (mandatoryIeCount != thiz->mandatoryIeCount)) {
{ for(ieType = 0; ieType < NW_GTPV2C_IE_TYPE_MAXIMUM; ieType++) {
for(ieType = 0; ieType < NW_GTPV2C_IE_TYPE_MAXIMUM; ieType++) for(ieInstance = 0; ieInstance < NW_GTPV2C_IE_INSTANCE_MAXIMUM; ieInstance++) {
{ if(thiz->ieParseInfo[ieType][ieInstance].iePresence == NW_GTPV2C_IE_PRESENCE_MANDATORY) {
for(ieInstance = 0; ieInstance < NW_GTPV2C_IE_INSTANCE_MAXIMUM; ieInstance++) if(pMsg->isIeValid[ieType][ieInstance] == NW_FALSE) {
{
if(thiz->ieParseInfo[ieType][ieInstance].iePresence == NW_GTPV2C_IE_PRESENCE_MANDATORY)
{
if(pMsg->isIeValid[ieType][ieInstance] == NW_FALSE)
{
NW_LOG(thiz->hStack, NW_LOG_LEVEL_ERRO, "Mandatory IE of type %u and instance %u missing in msg type %u", ieType, ieInstance, pMsg->msgType); NW_LOG(thiz->hStack, NW_LOG_LEVEL_ERRO, "Mandatory IE of type %u and instance %u missing in msg type %u", ieType, ieInstance, pMsg->msgType);
pError->cause = NW_GTPV2C_CAUSE_MANDATORY_IE_MISSING; pError->cause = NW_GTPV2C_CAUSE_MANDATORY_IE_MISSING;
pError->offendingIe.type = ieType; pError->offendingIe.type = ieType;
@@ -715,6 +680,7 @@ nwGtpv2cMsgIeParse(NW_IN NwGtpv2cMsgIeParseInfoT* thiz,
} }
} }
} }
NW_LOG(thiz->hStack, NW_LOG_LEVEL_CRIT, "Unknown mandatory IE missing. Msg parser formed incorrectly!"); NW_LOG(thiz->hStack, NW_LOG_LEVEL_CRIT, "Unknown mandatory IE missing. Msg parser formed incorrectly!");
pError->cause = NW_GTPV2C_CAUSE_MANDATORY_IE_MISSING; pError->cause = NW_GTPV2C_CAUSE_MANDATORY_IE_MISSING;
pError->offendingIe.type = 0; pError->offendingIe.type = 0;
@@ -732,6 +698,6 @@ nwGtpv2cMsgIeParse(NW_IN NwGtpv2cMsgIeParseInfoT* thiz,
#endif #endif
/*--------------------------------------------------------------------------* /*--------------------------------------------------------------------------*
* E N D O F F I L E * * E N D O F F I L E *
*--------------------------------------------------------------------------*/ *--------------------------------------------------------------------------*/
@@ -1,6 +1,6 @@
/*----------------------------------------------------------------------------* /*----------------------------------------------------------------------------*
* * * *
* n w - g t p v 2 c * * 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 * * 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 *
* * * *
* * * *
@@ -44,30 +44,30 @@
extern "C" { extern "C" {
#endif #endif
/** /**
* Allocate a gtpv2c message Parser. * Allocate a gtpv2c message Parser.
* *
* @param[in] hGtpcStackHandle : gtpv2c stack handle. * @param[in] hGtpcStackHandle : gtpv2c stack handle.
* @param[in] msgType : Message type for this message parser. * @param[in] msgType : Message type for this message parser.
* @param[out] pthiz : Pointer to message parser handle. * @param[out] pthiz : Pointer to message parser handle.
*/ */
NwRcT NwRcT
nwGtpv2cMsgParserNew( NW_IN NwGtpv2cStackHandleT hGtpcStackHandle, nwGtpv2cMsgParserNew( NW_IN NwGtpv2cStackHandleT hGtpcStackHandle,
NW_IN NwU8T msgType, NW_IN NwU8T msgType,
NW_IN NwRcT (*ieReadCallback) (NwU8T ieType, NW_IN NwRcT (*ieReadCallback) (NwU8T ieType,
NwU8T ieLength, NwU8T ieLength,
NwU8T ieInstance, NwU8T ieInstance,
NwU8T* ieValue, NwU8T* ieValue,
void* ieReadCallbackArg), void* ieReadCallbackArg),
NW_IN void* ieReadCallbackArg, NW_IN void* ieReadCallbackArg,
NW_IN NwGtpv2cMsgParserT **pthiz) NW_IN NwGtpv2cMsgParserT **pthiz)
{ {
NwGtpv2cMsgParserT* thiz; NwGtpv2cMsgParserT* thiz;
// NW_GTPV2C_MALLOC(hGtpcStackHandle, sizeof(NwGtpv2cMsgParserT), thiz, NwGtpv2cMsgParserT*); // NW_GTPV2C_MALLOC(hGtpcStackHandle, sizeof(NwGtpv2cMsgParserT), thiz, NwGtpv2cMsgParserT*);
thiz = (NwGtpv2cMsgParserT*) malloc (sizeof(NwGtpv2cMsgParserT)); thiz = (NwGtpv2cMsgParserT*) malloc (sizeof(NwGtpv2cMsgParserT));
if(thiz)
{ if(thiz) {
memset(thiz, 0, sizeof(NwGtpv2cMsgParserT)); memset(thiz, 0, sizeof(NwGtpv2cMsgParserT));
thiz->msgType = msgType; thiz->msgType = msgType;
thiz->hStack = hGtpcStackHandle; thiz->hStack = hGtpcStackHandle;
@@ -76,19 +76,20 @@ nwGtpv2cMsgParserNew( NW_IN NwGtpv2cStackHandleT hGtpcStackHandle,
thiz->ieReadCallbackArg = ieReadCallbackArg; thiz->ieReadCallbackArg = ieReadCallbackArg;
return NW_OK; return NW_OK;
} }
return NW_FAILURE; return NW_FAILURE;
} }
/** /**
* Free a gtpv2c message parser. * Free a gtpv2c message parser.
* *
* @param[in] hGtpcStackHandle : gtpv2c stack handle. * @param[in] hGtpcStackHandle : gtpv2c stack handle.
* @param[in] thiz : Message parser handle. * @param[in] thiz : Message parser handle.
*/ */
NwRcT NwRcT
nwGtpv2cMsgParserDelete( NW_IN NwGtpv2cStackHandleT hGtpcStackHandle, nwGtpv2cMsgParserDelete( NW_IN NwGtpv2cStackHandleT hGtpcStackHandle,
NW_IN NwGtpv2cMsgParserT* thiz) NW_IN NwGtpv2cMsgParserT* thiz)
{ {
NW_GTPV2C_FREE(hGtpcStackHandle, thiz); NW_GTPV2C_FREE(hGtpcStackHandle, thiz);
return NW_OK; return NW_OK;
@@ -96,29 +97,29 @@ nwGtpv2cMsgParserDelete( NW_IN NwGtpv2cStackHandleT hGtpcStackHandle,
NwRcT NwRcT
nwGtpv2cMsgParserUpdateIeReadCallback( NW_IN NwGtpv2cMsgParserT* thiz, nwGtpv2cMsgParserUpdateIeReadCallback( NW_IN NwGtpv2cMsgParserT* thiz,
NW_IN NwRcT (*ieReadCallback) (NwU8T ieType, NW_IN NwRcT (*ieReadCallback) (NwU8T ieType,
NwU8T ieLength, NwU8T ieLength,
NwU8T ieInstance, NwU8T ieInstance,
NwU8T* ieValue, NwU8T* ieValue,
void* ieReadCallbackArg)) void* ieReadCallbackArg))
{ {
if(thiz) if(thiz) {
{
thiz->ieReadCallback = ieReadCallback; thiz->ieReadCallback = ieReadCallback;
return NW_OK; return NW_OK;
} }
return NW_FAILURE; return NW_FAILURE;
} }
NwRcT NwRcT
nwGtpv2cMsgParserUpdateIeReadCallbackArg( NW_IN NwGtpv2cMsgParserT* thiz, nwGtpv2cMsgParserUpdateIeReadCallbackArg( NW_IN NwGtpv2cMsgParserT* thiz,
NW_IN void* ieReadCallbackArg) NW_IN void* ieReadCallbackArg)
{ {
if(thiz) if(thiz) {
{
thiz->ieReadCallbackArg = ieReadCallbackArg; thiz->ieReadCallbackArg = ieReadCallbackArg;
return NW_OK; return NW_OK;
} }
return NW_FAILURE; return NW_FAILURE;
} }
@@ -127,29 +128,26 @@ nwGtpv2cMsgParserAddIe( NW_IN NwGtpv2cMsgParserT* thiz,
NW_IN NwU8T ieType, NW_IN NwU8T ieType,
NW_IN NwU8T ieInstance, NW_IN NwU8T ieInstance,
NW_IN NwU8T iePresence, NW_IN NwU8T iePresence,
NW_IN NwRcT (*ieReadCallback) (NwU8T ieType, NW_IN NwRcT (*ieReadCallback) (NwU8T ieType,
NwU8T ieLength, NwU8T ieLength,
NwU8T ieInstance, NwU8T ieInstance,
NwU8T* ieValue, NwU8T* ieValue,
void* ieReadCallbackArg), void* ieReadCallbackArg),
NW_IN void* ieReadCallbackArg) NW_IN void* ieReadCallbackArg)
{ {
NW_ASSERT(thiz); NW_ASSERT(thiz);
if(thiz->ieParseInfo[ieType][ieInstance].iePresence == 0)
{ if(thiz->ieParseInfo[ieType][ieInstance].iePresence == 0) {
NW_ASSERT(ieInstance <= NW_GTPV2C_IE_INSTANCE_MAXIMUM); NW_ASSERT(ieInstance <= NW_GTPV2C_IE_INSTANCE_MAXIMUM);
thiz->ieParseInfo[ieType][ieInstance].ieReadCallback = ieReadCallback; thiz->ieParseInfo[ieType][ieInstance].ieReadCallback = ieReadCallback;
thiz->ieParseInfo[ieType][ieInstance].ieReadCallbackArg = ieReadCallbackArg; thiz->ieParseInfo[ieType][ieInstance].ieReadCallbackArg = ieReadCallbackArg;
thiz->ieParseInfo[ieType][ieInstance].iePresence = iePresence; thiz->ieParseInfo[ieType][ieInstance].iePresence = iePresence;
if (iePresence == NW_GTPV2C_IE_PRESENCE_MANDATORY) if (iePresence == NW_GTPV2C_IE_PRESENCE_MANDATORY) {
{
thiz->mandatoryIeCount++; thiz->mandatoryIeCount++;
} }
} } else {
else
{
NW_LOG(thiz->hStack, NW_LOG_LEVEL_ERRO, "Cannot add IE to parser for type %u and instance %u. IE info already exists!", ieType, ieInstance); NW_LOG(thiz->hStack, NW_LOG_LEVEL_ERRO, "Cannot add IE to parser for type %u and instance %u. IE info already exists!", ieType, ieInstance);
} }
@@ -158,26 +156,24 @@ nwGtpv2cMsgParserAddIe( NW_IN NwGtpv2cMsgParserT* thiz,
NwRcT NwRcT
nwGtpv2cMsgParserUpdateIe( NW_IN NwGtpv2cMsgParserT* thiz, nwGtpv2cMsgParserUpdateIe( NW_IN NwGtpv2cMsgParserT* thiz,
NW_IN NwU8T ieType, NW_IN NwU8T ieType,
NW_IN NwU8T ieInstance, NW_IN NwU8T ieInstance,
NW_IN NwU8T iePresence, NW_IN NwU8T iePresence,
NW_IN NwRcT (*ieReadCallback) (NwU8T ieType, NW_IN NwRcT (*ieReadCallback) (NwU8T ieType,
NwU8T ieLength, NwU8T ieLength,
NwU8T ieInstance, NwU8T ieInstance,
NwU8T* ieValue, NwU8T* ieValue,
void* ieReadCallbackArg), void* ieReadCallbackArg),
NW_IN void* ieReadCallbackArg) NW_IN void* ieReadCallbackArg)
{ {
NW_ASSERT(thiz); NW_ASSERT(thiz);
if(thiz->ieParseInfo[ieType][ieInstance].iePresence)
{ if(thiz->ieParseInfo[ieType][ieInstance].iePresence) {
thiz->ieParseInfo[ieType][ieInstance].ieReadCallback = ieReadCallback; thiz->ieParseInfo[ieType][ieInstance].ieReadCallback = ieReadCallback;
thiz->ieParseInfo[ieType][ieInstance].ieReadCallbackArg = ieReadCallbackArg; thiz->ieParseInfo[ieType][ieInstance].ieReadCallbackArg = ieReadCallbackArg;
thiz->ieParseInfo[ieType][ieInstance].iePresence = iePresence; thiz->ieParseInfo[ieType][ieInstance].iePresence = iePresence;
} } else {
else
{
NW_LOG(thiz->hStack, NW_LOG_LEVEL_ERRO, "Cannot update IE info for type %u and instance %u. IE info does not exist!", ieType, ieInstance); NW_LOG(thiz->hStack, NW_LOG_LEVEL_ERRO, "Cannot update IE info for type %u and instance %u. IE info does not exist!", ieType, ieInstance);
} }
@@ -211,86 +207,66 @@ nwGtpv2cMsgParserRun( NW_IN NwGtpv2cMsgParserT *thiz,
memset(thiz->pIe, 0, sizeof(NwU8T*) * (NW_GTPV2C_IE_TYPE_MAXIMUM) * (NW_GTPV2C_IE_INSTANCE_MAXIMUM)); memset(thiz->pIe, 0, sizeof(NwU8T*) * (NW_GTPV2C_IE_TYPE_MAXIMUM) * (NW_GTPV2C_IE_INSTANCE_MAXIMUM));
memset(pMsg->pIe, 0, sizeof(NwU8T*) * (NW_GTPV2C_IE_TYPE_MAXIMUM) * (NW_GTPV2C_IE_INSTANCE_MAXIMUM)); memset(pMsg->pIe, 0, sizeof(NwU8T*) * (NW_GTPV2C_IE_TYPE_MAXIMUM) * (NW_GTPV2C_IE_INSTANCE_MAXIMUM));
while (pIeStart < pIeEnd) while (pIeStart < pIeEnd) {
{
pIe = (NwGtpv2cIeTlvT*) pIeStart; pIe = (NwGtpv2cIeTlvT*) pIeStart;
ieLength = ntohs(pIe->l); ieLength = ntohs(pIe->l);
if(pIeStart + 4 + ieLength > pIeEnd) if(pIeStart + 4 + ieLength > pIeEnd) {
{
*pOffendingIeType = pIe->t; *pOffendingIeType = pIe->t;
*pOffendingIeLength = pIe->l; *pOffendingIeLength = pIe->l;
*pOffendingIeInstance = pIe->i; *pOffendingIeInstance = pIe->i;
return NW_GTPV2C_MSG_MALFORMED; return NW_GTPV2C_MSG_MALFORMED;
} }
if((thiz->ieParseInfo[pIe->t][pIe->i].iePresence)) if((thiz->ieParseInfo[pIe->t][pIe->i].iePresence)) {
{
thiz->pIe[pIe->t][pIe->i] = (NwU8T*) pIeStart; thiz->pIe[pIe->t][pIe->i] = (NwU8T*) pIeStart;
pMsg->pIe[pIe->t][pIe->i] = (NwU8T*) pIeStart; pMsg->pIe[pIe->t][pIe->i] = (NwU8T*) pIeStart;
NW_LOG(thiz->hStack, NW_LOG_LEVEL_DEBG, "Received IE %u of length %u!", pIe->t, ieLength); NW_LOG(thiz->hStack, NW_LOG_LEVEL_DEBG, "Received IE %u of length %u!", pIe->t, ieLength);
if((thiz->ieParseInfo[pIe->t][pIe->i].ieReadCallback) != NULL )
{ if((thiz->ieParseInfo[pIe->t][pIe->i].ieReadCallback) != NULL ) {
rc = thiz->ieParseInfo[pIe->t][pIe->i].ieReadCallback(pIe->t, ieLength, pIe->i, pIeStart + 4, thiz->ieParseInfo[pIe->t][pIe->i].ieReadCallbackArg); rc = thiz->ieParseInfo[pIe->t][pIe->i].ieReadCallback(pIe->t, ieLength, pIe->i, pIeStart + 4, thiz->ieParseInfo[pIe->t][pIe->i].ieReadCallbackArg);
if(NW_OK == rc) if(NW_OK == rc) {
{ if(thiz->ieParseInfo[pIe->t][pIe->i].iePresence == NW_GTPV2C_IE_PRESENCE_MANDATORY)
if(thiz->ieParseInfo[pIe->t][pIe->i].iePresence == NW_GTPV2C_IE_PRESENCE_MANDATORY)
mandatoryIeCount++; mandatoryIeCount++;
} } else {
else
{
NW_LOG(thiz->hStack, NW_LOG_LEVEL_ERRO, "Error while parsing IE %u with instance %u and length %u!", pIe->t, pIe->i, ieLength); NW_LOG(thiz->hStack, NW_LOG_LEVEL_ERRO, "Error while parsing IE %u with instance %u and length %u!", pIe->t, pIe->i, ieLength);
break; break;
} }
} } else {
else if((thiz->ieReadCallback) != NULL ) {
{
if((thiz->ieReadCallback) != NULL )
{
NW_LOG(thiz->hStack, NW_LOG_LEVEL_DEBG, "Received IE %u of length %u!", pIe->t, ieLength); NW_LOG(thiz->hStack, NW_LOG_LEVEL_DEBG, "Received IE %u of length %u!", pIe->t, ieLength);
rc = thiz->ieReadCallback(pIe->t, ieLength, pIe->i, pIeStart + 4, thiz->ieReadCallbackArg); rc = thiz->ieReadCallback(pIe->t, ieLength, pIe->i, pIeStart + 4, thiz->ieReadCallbackArg);
if(NW_OK == rc) if(NW_OK == rc) {
{ if(thiz->ieParseInfo[pIe->t][pIe->i].iePresence == NW_GTPV2C_IE_PRESENCE_MANDATORY)
if(thiz->ieParseInfo[pIe->t][pIe->i].iePresence == NW_GTPV2C_IE_PRESENCE_MANDATORY)
mandatoryIeCount++; mandatoryIeCount++;
} } else {
else
{
NW_LOG(thiz->hStack, NW_LOG_LEVEL_ERRO, "Error while parsing IE %u of length %u!", pIe->t, ieLength); NW_LOG(thiz->hStack, NW_LOG_LEVEL_ERRO, "Error while parsing IE %u of length %u!", pIe->t, ieLength);
break; break;
} }
} } else {
else
{
NW_LOG(thiz->hStack, NW_LOG_LEVEL_WARN, "No parse method defined for received IE type %u of length %u in message %u!", pIe->t, ieLength, thiz->msgType); NW_LOG(thiz->hStack, NW_LOG_LEVEL_WARN, "No parse method defined for received IE type %u of length %u in message %u!", pIe->t, ieLength, thiz->msgType);
} }
} }
} } else {
else
{
NW_LOG(thiz->hStack, NW_LOG_LEVEL_WARN, "Unexpected IE %u of length %u received in msg %u!", pIe->t, ieLength, thiz->msgType); NW_LOG(thiz->hStack, NW_LOG_LEVEL_WARN, "Unexpected IE %u of length %u received in msg %u!", pIe->t, ieLength, thiz->msgType);
} }
pIeStart += (ieLength + 4); pIeStart += (ieLength + 4);
} }
if((NW_OK == rc) && (mandatoryIeCount != thiz->mandatoryIeCount)) if((NW_OK == rc) && (mandatoryIeCount != thiz->mandatoryIeCount)) {
{
NwU16T t, i; NwU16T t, i;
*pOffendingIeType = 0; *pOffendingIeType = 0;
*pOffendingIeInstance = 0; *pOffendingIeInstance = 0;
*pOffendingIeLength = 0; *pOffendingIeLength = 0;
for(t = 0; t < NW_GTPV2C_IE_TYPE_MAXIMUM; t++)
{ for(t = 0; t < NW_GTPV2C_IE_TYPE_MAXIMUM; t++) {
for(i = 0; i < NW_GTPV2C_IE_INSTANCE_MAXIMUM; i++) for(i = 0; i < NW_GTPV2C_IE_INSTANCE_MAXIMUM; i++) {
{ if(thiz->ieParseInfo[t][i].iePresence == NW_GTPV2C_IE_PRESENCE_MANDATORY) {
if(thiz->ieParseInfo[t][i].iePresence == NW_GTPV2C_IE_PRESENCE_MANDATORY) if(thiz->pIe[t][i] == NULL) {
{
if(thiz->pIe[t][i] == NULL)
{
*pOffendingIeType = t; *pOffendingIeType = t;
*pOffendingIeInstance = i; *pOffendingIeInstance = i;
return NW_GTPV2C_MANDATORY_IE_MISSING; return NW_GTPV2C_MANDATORY_IE_MISSING;
@@ -298,6 +274,7 @@ nwGtpv2cMsgParserRun( NW_IN NwGtpv2cMsgParserT *thiz,
} }
} }
} }
NW_LOG(thiz->hStack, NW_LOG_LEVEL_WARN, "Unknown mandatory IE missing. Parser formed incorrectly! %u:%u", mandatoryIeCount, thiz->mandatoryIeCount); NW_LOG(thiz->hStack, NW_LOG_LEVEL_WARN, "Unknown mandatory IE missing. Parser formed incorrectly! %u:%u", mandatoryIeCount, thiz->mandatoryIeCount);
return NW_GTPV2C_MANDATORY_IE_MISSING; return NW_GTPV2C_MANDATORY_IE_MISSING;
} }
@@ -1,6 +1,6 @@
/*----------------------------------------------------------------------------* /*----------------------------------------------------------------------------*
* * * *
* n w - g t p v 2 c * * 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 * * 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 *
* * * *
* * * *
@@ -69,11 +69,11 @@ nwGtpv2cTrxnSendMsgRetransmission(NwGtpv2cTrxnT* thiz)
NW_ASSERT(thiz->pMsg); NW_ASSERT(thiz->pMsg);
rc = thiz->pStack->udp.udpDataReqCallback(thiz->pStack->udp.hUdp, rc = thiz->pStack->udp.udpDataReqCallback(thiz->pStack->udp.hUdp,
thiz->pMsg->msgBuf, thiz->pMsg->msgBuf,
thiz->pMsg->msgLen, thiz->pMsg->msgLen,
thiz->peerIp, thiz->peerIp,
thiz->peerPort); thiz->peerPort);
thiz->maxRetries--; thiz->maxRetries--;
@@ -97,15 +97,12 @@ nwGtpv2cTrxnPeerRspWaitTimeout(void* arg)
thiz->hRspTmr = 0; thiz->hRspTmr = 0;
if(thiz->maxRetries) if(thiz->maxRetries) {
{
rc = nwGtpv2cTrxnSendMsgRetransmission(thiz); rc = nwGtpv2cTrxnSendMsgRetransmission(thiz);
NW_ASSERT(NW_OK == rc); NW_ASSERT(NW_OK == rc);
rc = nwGtpv2cStartTimer(thiz->pStack, thiz->t3Timer, 0, NW_GTPV2C_TMR_TYPE_ONE_SHOT, nwGtpv2cTrxnPeerRspWaitTimeout, thiz, &thiz->hRspTmr); rc = nwGtpv2cStartTimer(thiz->pStack, thiz->t3Timer, 0, NW_GTPV2C_TMR_TYPE_ONE_SHOT, nwGtpv2cTrxnPeerRspWaitTimeout, thiz, &thiz->hRspTmr);
} } else {
else
{
NwGtpv2cUlpApiT ulpApi; NwGtpv2cUlpApiT ulpApi;
ulpApi.hMsg = 0; ulpApi.hMsg = 0;
@@ -121,6 +118,7 @@ nwGtpv2cTrxnPeerRspWaitTimeout(void* arg)
rc = pStack->ulp.ulpReqCallback(pStack->ulp.hUlp, &ulpApi); rc = pStack->ulp.ulpReqCallback(pStack->ulp.hUlp, &ulpApi);
} }
return rc; return rc;
} }
@@ -152,7 +150,7 @@ nwGtpv2cTrxnDuplicateRequestWaitTimeout(void* arg)
/** /**
* Start timer to wait for rsp of a req message * Start timer to wait for rsp of a req message
* *
* @param[in] thiz : Pointer to transaction * @param[in] thiz : Pointer to transaction
* @param[in] timeoutCallbackFunc : Timeout handler callback function. * @param[in] timeoutCallbackFunc : Timeout handler callback function.
* @return NW_OK on success. * @return NW_OK on success.
@@ -210,27 +208,23 @@ nwGtpv2cTrxnStopPeerRspTimer(NwGtpv2cTrxnT* thiz)
/** /**
* Constructor * Constructor
* *
* @param[in] thiz : Pointer to stack * @param[in] thiz : Pointer to stack
* @param[out] ppTrxn : Pointer to pointer to Trxn object. * @param[out] ppTrxn : Pointer to pointer to Trxn object.
* @return NW_OK on success. * @return NW_OK on success.
*/ */
NwGtpv2cTrxnT* NwGtpv2cTrxnT*
nwGtpv2cTrxnNew( NW_IN NwGtpv2cStackT* thiz) nwGtpv2cTrxnNew( NW_IN NwGtpv2cStackT* thiz)
{ {
NwGtpv2cTrxnT *pTrxn; NwGtpv2cTrxnT *pTrxn;
if(gpGtpv2cTrxnPool) if(gpGtpv2cTrxnPool) {
{
pTrxn = gpGtpv2cTrxnPool; pTrxn = gpGtpv2cTrxnPool;
gpGtpv2cTrxnPool = gpGtpv2cTrxnPool->next; gpGtpv2cTrxnPool = gpGtpv2cTrxnPool->next;
} } else {
else
{
NW_GTPV2C_MALLOC(thiz, sizeof(NwGtpv2cTrxnT), pTrxn, NwGtpv2cTrxnT*); NW_GTPV2C_MALLOC(thiz, sizeof(NwGtpv2cTrxnT), pTrxn, NwGtpv2cTrxnT*);
} }
if (pTrxn) if (pTrxn) {
{
pTrxn->pStack = thiz; pTrxn->pStack = thiz;
pTrxn->pMsg = NULL; pTrxn->pMsg = NULL;
pTrxn->maxRetries = 2; pTrxn->maxRetries = 2;
@@ -239,6 +233,7 @@ nwGtpv2cTrxnNew( NW_IN NwGtpv2cStackT* thiz)
/* Increment sequence number */ /* Increment sequence number */
thiz->seqNum++; thiz->seqNum++;
if(thiz->seqNum == 0x800000) if(thiz->seqNum == 0x800000)
thiz->seqNum = 0; thiz->seqNum = 0;
@@ -252,28 +247,24 @@ nwGtpv2cTrxnNew( NW_IN NwGtpv2cStackT* thiz)
/** /**
* Overloaded Constructor * Overloaded Constructor
* *
* @param[in] thiz : Pointer to stack. * @param[in] thiz : Pointer to stack.
* @param[in] seqNum : Sequence number for this transaction. * @param[in] seqNum : Sequence number for this transaction.
* @return Pointer to Trxn object. * @return Pointer to Trxn object.
*/ */
NwGtpv2cTrxnT* NwGtpv2cTrxnT*
nwGtpv2cTrxnWithSeqNumNew( NW_IN NwGtpv2cStackT* thiz, nwGtpv2cTrxnWithSeqNumNew( NW_IN NwGtpv2cStackT* thiz,
NW_IN NwU32T seqNum) NW_IN NwU32T seqNum)
{ {
NwGtpv2cTrxnT *pTrxn; NwGtpv2cTrxnT *pTrxn;
if(gpGtpv2cTrxnPool) if(gpGtpv2cTrxnPool) {
{
pTrxn = gpGtpv2cTrxnPool; pTrxn = gpGtpv2cTrxnPool;
gpGtpv2cTrxnPool = gpGtpv2cTrxnPool->next; gpGtpv2cTrxnPool = gpGtpv2cTrxnPool->next;
} } else {
else
{
NW_GTPV2C_MALLOC(thiz, sizeof(NwGtpv2cTrxnT), pTrxn, NwGtpv2cTrxnT*); NW_GTPV2C_MALLOC(thiz, sizeof(NwGtpv2cTrxnT), pTrxn, NwGtpv2cTrxnT*);
} }
if (pTrxn) if (pTrxn) {
{
pTrxn->pStack = thiz; pTrxn->pStack = thiz;
pTrxn->pMsg = NULL; pTrxn->pMsg = NULL;
pTrxn->maxRetries = 2; pTrxn->maxRetries = 2;
@@ -288,10 +279,10 @@ nwGtpv2cTrxnWithSeqNumNew( NW_IN NwGtpv2cStackT* thiz,
} }
/** /**
* Another overloaded constructor. Create transaction as outstanding * Another overloaded constructor. Create transaction as outstanding
* RX transaction for detecting duplicated requests. * RX transaction for detecting duplicated requests.
* *
* @param[in] thiz : Pointer to stack. * @param[in] thiz : Pointer to stack.
* @param[in] teidLocal : Trxn teid. * @param[in] teidLocal : Trxn teid.
* @param[in] peerIp : Peer Ip address. * @param[in] peerIp : Peer Ip address.
* @param[in] peerPort : Peer Ip port. * @param[in] peerPort : Peer Ip port.
@@ -301,26 +292,22 @@ nwGtpv2cTrxnWithSeqNumNew( NW_IN NwGtpv2cStackT* thiz,
NwGtpv2cTrxnT* NwGtpv2cTrxnT*
nwGtpv2cTrxnOutstandingRxNew( NW_IN NwGtpv2cStackT* thiz, nwGtpv2cTrxnOutstandingRxNew( NW_IN NwGtpv2cStackT* thiz,
NW_IN NwU32T teidLocal, NW_IN NwU32T teidLocal,
NW_IN NwU32T peerIp, NW_IN NwU32T peerIp,
NW_IN NwU32T peerPort, NW_IN NwU32T peerPort,
NW_IN NwU32T seqNum) NW_IN NwU32T seqNum)
{ {
NwRcT rc; NwRcT rc;
NwGtpv2cTrxnT *pTrxn, *pCollision; NwGtpv2cTrxnT *pTrxn, *pCollision;
if(gpGtpv2cTrxnPool) if(gpGtpv2cTrxnPool) {
{
pTrxn = gpGtpv2cTrxnPool; pTrxn = gpGtpv2cTrxnPool;
gpGtpv2cTrxnPool = gpGtpv2cTrxnPool->next; gpGtpv2cTrxnPool = gpGtpv2cTrxnPool->next;
} } else {
else
{
NW_GTPV2C_MALLOC(thiz, sizeof(NwGtpv2cTrxnT), pTrxn, NwGtpv2cTrxnT*); NW_GTPV2C_MALLOC(thiz, sizeof(NwGtpv2cTrxnT), pTrxn, NwGtpv2cTrxnT*);
} }
if (pTrxn) if (pTrxn) {
{
pTrxn->pStack = thiz; pTrxn->pStack = thiz;
pTrxn->maxRetries = 2; pTrxn->maxRetries = 2;
pTrxn->t3Timer = 2; pTrxn->t3Timer = 2;
@@ -332,18 +319,17 @@ nwGtpv2cTrxnOutstandingRxNew( NW_IN NwGtpv2cStackT* thiz,
pCollision = RB_INSERT(NwGtpv2cOutstandingRxSeqNumTrxnMap, &(thiz->outstandingRxSeqNumMap), pTrxn); pCollision = RB_INSERT(NwGtpv2cOutstandingRxSeqNumTrxnMap, &(thiz->outstandingRxSeqNumMap), pTrxn);
if(pCollision) if(pCollision) {
{
NW_LOG(thiz, NW_LOG_LEVEL_WARN, "Duplicate request message received for seq num 0x%x!", NW_LOG(thiz, NW_LOG_LEVEL_WARN, "Duplicate request message received for seq num 0x%x!",
(NwU32T) seqNum); (NwU32T) seqNum);
/* Case of duplicate request message from peer. Retransmit response. */ /* Case of duplicate request message from peer. Retransmit response. */
if(pCollision->pMsg) if(pCollision->pMsg) {
{ rc = pCollision->pStack->udp.udpDataReqCallback(pCollision->pStack->udp.hUdp,
rc = pCollision->pStack->udp.udpDataReqCallback(pCollision->pStack->udp.hUdp, pCollision->pMsg->msgBuf,
pCollision->pMsg->msgBuf, pCollision->pMsg->msgLen,
pCollision->pMsg->msgLen, pCollision->peerIp,
pCollision->peerIp, pCollision->peerPort);
pCollision->peerPort);
} }
rc = nwGtpv2cTrxnDelete(&pTrxn); rc = nwGtpv2cTrxnDelete(&pTrxn);
@@ -374,14 +360,12 @@ nwGtpv2cTrxnDelete( NW_INOUT NwGtpv2cTrxnT **pthiz)
pStack = thiz->pStack; pStack = thiz->pStack;
if(thiz->hRspTmr) if(thiz->hRspTmr) {
{
rc = nwGtpv2cTrxnStopPeerRspTimer(thiz); rc = nwGtpv2cTrxnStopPeerRspTimer(thiz);
NW_ASSERT(NW_OK == rc); NW_ASSERT(NW_OK == rc);
} }
if(thiz->pMsg) if(thiz->pMsg) {
{
rc = nwGtpv2cMsgDelete((NwGtpv2cStackHandleT)pStack, (NwGtpv2cMsgHandleT)thiz->pMsg); rc = nwGtpv2cMsgDelete((NwGtpv2cStackHandleT)pStack, (NwGtpv2cMsgHandleT)thiz->pMsg);
NW_ASSERT(NW_OK == rc); NW_ASSERT(NW_OK == rc);
} }
@@ -400,6 +384,6 @@ nwGtpv2cTrxnDelete( NW_INOUT NwGtpv2cTrxnT **pthiz)
#endif #endif
/*--------------------------------------------------------------------------* /*--------------------------------------------------------------------------*
* E N D O F F I L E * * E N D O F F I L E *
*--------------------------------------------------------------------------*/ *--------------------------------------------------------------------------*/
@@ -1,6 +1,6 @@
/*----------------------------------------------------------------------------* /*----------------------------------------------------------------------------*
* * * *
* n w - g t p v 2 c * * 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 * * 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 *
* * * *
* * * *
@@ -52,23 +52,20 @@ nwGtpv2cTunnelNew(struct NwGtpv2cStack *pStack, NwU32T teid, NwU32T ipv4AddrRemo
{ {
NwGtpv2cTunnelT* thiz; NwGtpv2cTunnelT* thiz;
if(gpGtpv2cTunnelPool) if(gpGtpv2cTunnelPool) {
{
thiz = gpGtpv2cTunnelPool; thiz = gpGtpv2cTunnelPool;
gpGtpv2cTunnelPool = gpGtpv2cTunnelPool->next; gpGtpv2cTunnelPool = gpGtpv2cTunnelPool->next;
} } else {
else
{
NW_GTPV2C_MALLOC(pStack, sizeof(NwGtpv2cTunnelT), thiz, NwGtpv2cTunnelT*); NW_GTPV2C_MALLOC(pStack, sizeof(NwGtpv2cTunnelT), thiz, NwGtpv2cTunnelT*);
} }
if(thiz) if(thiz) {
{
memset(thiz, 0, sizeof(NwGtpv2cTunnelT)); memset(thiz, 0, sizeof(NwGtpv2cTunnelT));
thiz->teid = teid; thiz->teid = teid;
thiz->ipv4AddrRemote = ipv4AddrRemote; thiz->ipv4AddrRemote = ipv4AddrRemote;
thiz->hUlpTunnel = hUlpTunnel; thiz->hUlpTunnel = hUlpTunnel;
} }
return thiz; return thiz;
} }
@@ -3,7 +3,7 @@
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
/** /**
* @file NwEgtPingMain.c * @file NwEgtPingMain.c
* @brief This is a program demostrating usage of nw-gtpv2c library for eGTP ping. * @brief This is a program demostrating usage of nw-gtpv2c library for eGTP ping.
*/ */
@@ -23,14 +23,13 @@
#ifndef NW_ASSERT #ifndef NW_ASSERT
#define NW_ASSERT assert #define NW_ASSERT assert
#endif #endif
static static
NwCharT* gLogLevelStr[] = {"EMER", "ALER", "CRIT", "ERRO", "WARN", "NOTI", "INFO", "DEBG"}; NwCharT* gLogLevelStr[] = {"EMER", "ALER", "CRIT", "ERRO", "WARN", "NOTI", "INFO", "DEBG"};
typedef struct NwEgtPingS typedef struct NwEgtPingS {
{
NwU8T localIpStr[20]; NwU8T localIpStr[20];
NwU8T targetIpStr[20]; NwU8T targetIpStr[20];
NwU32T pingInterval; NwU32T pingInterval;
@@ -47,7 +46,8 @@ static NwEgtPingT egtPing;
void nwEgtPingHandleSignal(int sigNum) void nwEgtPingHandleSignal(int sigNum)
{ {
printf("\n--- %s ("NW_IPV4_ADDR") EGTPING statistics --- ", egtPing.targetIpStr, NW_IPV4_ADDR_FORMAT(inet_addr(egtPing.targetIpStr))); printf("\n--- %s ("NW_IPV4_ADDR") EGTPING statistics --- ", egtPing.targetIpStr, NW_IPV4_ADDR_FORMAT(inet_addr(egtPing.targetIpStr)));
printf("\n%u requests sent, %u response received, %d%% packet loss \n\n", udpObj.packetsSent, udpObj.packetsRcvd, (udpObj.packetsSent ? 100 * (udpObj.packetsSent - udpObj.packetsRcvd ) / udpObj.packetsSent : 0) ); printf("\n%u requests sent, %u response received, %d%% packet loss \n\n", udpObj.packetsSent, udpObj.packetsRcvd,
(udpObj.packetsSent ? 100 * (udpObj.packetsSent - udpObj.packetsRcvd ) / udpObj.packetsSent : 0) );
exit(sigNum); exit(sigNum);
} }
@@ -82,50 +82,45 @@ nwEgtPingParseCmdLineOpts(int argc, char* argv[])
if( (argc == 2) && if( (argc == 2) &&
((strcmp("--help", argv[i]) == 0) ((strcmp("--help", argv[i]) == 0)
|| (strcmp(argv[i], "-h") == 0))) || (strcmp(argv[i], "-h") == 0)))
return NW_FAILURE; return NW_FAILURE;
while( i < argc - 1) while( i < argc - 1) {
{
NW_LOG(NW_LOG_LEVEL_DEBG, "Processing cmdline arg %s", argv[i]); NW_LOG(NW_LOG_LEVEL_DEBG, "Processing cmdline arg %s", argv[i]);
if((strcmp("--local-ip", argv[i]) == 0) if((strcmp("--local-ip", argv[i]) == 0)
|| (strcmp(argv[i], "-l") == 0)) || (strcmp(argv[i], "-l") == 0)) {
{
i++; i++;
if(i >= (argc - 1)) if(i >= (argc - 1))
return NW_FAILURE; return NW_FAILURE;
strcpy(egtPing.localIpStr, (argv[i])); strcpy(egtPing.localIpStr, (argv[i]));
} } else if((strcmp("--interval", argv[i]) == 0)
else if((strcmp("--interval", argv[i]) == 0) || (strcmp(argv[i], "-i") == 0)) {
|| (strcmp(argv[i], "-i") == 0))
{
i++; i++;
if(i >= (argc - 1)) if(i >= (argc - 1))
return NW_FAILURE; return NW_FAILURE;
egtPing.pingInterval = atoi(argv[i]); egtPing.pingInterval = atoi(argv[i]);
} } else if((strcmp("--count", argv[i]) == 0)
else if((strcmp("--count", argv[i]) == 0) || (strcmp(argv[i], "-c") == 0)) {
|| (strcmp(argv[i], "-c") == 0))
{
i++; i++;
if(i >= (argc - 1)) if(i >= (argc - 1))
return NW_FAILURE; return NW_FAILURE;
egtPing.pingCount = atoi(argv[i]); egtPing.pingCount = atoi(argv[i]);
} } else if((strcmp("--help", argv[i]) == 0)
else if((strcmp("--help", argv[i]) == 0) || (strcmp(argv[i], "-h") == 0)) {
|| (strcmp(argv[i], "-h") == 0))
{
rc = NW_FAILURE; rc = NW_FAILURE;
} } else {
else
{
return NW_FAILURE; return NW_FAILURE;
} }
i++; i++;
} }
@@ -135,12 +130,12 @@ nwEgtPingParseCmdLineOpts(int argc, char* argv[])
} }
/*--------------------------------------------------------------------------- /*---------------------------------------------------------------------------
* T H E M A I N F U N C T I O N * T H E M A I N F U N C T I O N
*--------------------------------------------------------------------------*/ *--------------------------------------------------------------------------*/
int main(int argc, char* argv[]) int main(int argc, char* argv[])
{ {
NwRcT rc; NwRcT rc;
NwU32T logLevel; NwU32T logLevel;
NwU8T* logLevelStr; NwU8T* logLevelStr;
@@ -154,20 +149,16 @@ int main(int argc, char* argv[])
printf("EGTPING 0.1, Copyright (C) 2011 Amit Chawre.\n"); printf("EGTPING 0.1, Copyright (C) 2011 Amit Chawre.\n");
rc = nwEgtPingParseCmdLineOpts(argc, argv); rc = nwEgtPingParseCmdLineOpts(argc, argv);
if(rc != NW_OK) if(rc != NW_OK) {
{
rc = nwEgtPingHelp(); rc = nwEgtPingHelp();
exit(rc); exit(rc);
} }
logLevelStr = getenv ("NW_LOG_LEVEL"); logLevelStr = getenv ("NW_LOG_LEVEL");
if(logLevelStr == NULL) if(logLevelStr == NULL) {
{
logLevel = NW_LOG_LEVEL_INFO; logLevel = NW_LOG_LEVEL_INFO;
} } else {
else
{
if(strncmp(logLevelStr, "EMER",4) == 0) if(strncmp(logLevelStr, "EMER",4) == 0)
logLevel = NW_LOG_LEVEL_EMER; logLevel = NW_LOG_LEVEL_EMER;
else if(strncmp(logLevelStr, "ALER",4) == 0) else if(strncmp(logLevelStr, "ALER",4) == 0)
@@ -193,7 +184,7 @@ int main(int argc, char* argv[])
NW_EVT_INIT(); NW_EVT_INIT();
/*--------------------------------------------------------------------------- /*---------------------------------------------------------------------------
* Initialize Log Manager * Initialize Log Manager
*--------------------------------------------------------------------------*/ *--------------------------------------------------------------------------*/
nwMiniLogMgrInit(nwMiniLogMgrGetInstance(), logLevel); nwMiniLogMgrInit(nwMiniLogMgrGetInstance(), logLevel);
@@ -202,8 +193,7 @@ int main(int argc, char* argv[])
*--------------------------------------------------------------------------*/ *--------------------------------------------------------------------------*/
rc = nwGtpv2cInitialize(&hGtpv2cStack); rc = nwGtpv2cInitialize(&hGtpv2cStack);
if(rc != NW_OK) if(rc != NW_OK) {
{
NW_LOG(NW_LOG_LEVEL_ERRO, "Failed to create gtpv2c stack instance. Error '%u' occured", rc); NW_LOG(NW_LOG_LEVEL_ERRO, "Failed to create gtpv2c stack instance. Error '%u' occured", rc);
exit(1); exit(1);
} }
@@ -211,7 +201,7 @@ int main(int argc, char* argv[])
rc = nwGtpv2cSetLogLevel(hGtpv2cStack, logLevel); rc = nwGtpv2cSetLogLevel(hGtpv2cStack, logLevel);
/*--------------------------------------------------------------------------- /*---------------------------------------------------------------------------
* Set up Ulp Entity * Set up Ulp Entity
*--------------------------------------------------------------------------*/ *--------------------------------------------------------------------------*/
rc = nwGtpv2cUlpInit(&ulpObj, hGtpv2cStack, egtPing.localIpStr); rc = nwGtpv2cUlpInit(&ulpObj, hGtpv2cStack, egtPing.localIpStr);
NW_ASSERT(NW_OK == rc); NW_ASSERT(NW_OK == rc);
@@ -223,7 +213,7 @@ int main(int argc, char* argv[])
NW_ASSERT(NW_OK == rc); NW_ASSERT(NW_OK == rc);
/*--------------------------------------------------------------------------- /*---------------------------------------------------------------------------
* Set up Udp Entity * Set up Udp Entity
*--------------------------------------------------------------------------*/ *--------------------------------------------------------------------------*/
rc = nwGtpv2cUdpInit(&udpObj, hGtpv2cStack, egtPing.localIpStr); rc = nwGtpv2cUdpInit(&udpObj, hGtpv2cStack, egtPing.localIpStr);
NW_ASSERT(NW_OK == rc); NW_ASSERT(NW_OK == rc);
@@ -235,7 +225,7 @@ int main(int argc, char* argv[])
NW_ASSERT(NW_OK == rc); NW_ASSERT(NW_OK == rc);
/*--------------------------------------------------------------------------- /*---------------------------------------------------------------------------
* Set up Log Entity * Set up Log Entity
*--------------------------------------------------------------------------*/ *--------------------------------------------------------------------------*/
tmrMgr.tmrMgrHandle = 0; tmrMgr.tmrMgrHandle = 0;
tmrMgr.tmrStartCallback = nwTimerStart; tmrMgr.tmrStartCallback = nwTimerStart;
@@ -245,7 +235,7 @@ int main(int argc, char* argv[])
NW_ASSERT(NW_OK == rc); NW_ASSERT(NW_OK == rc);
/*--------------------------------------------------------------------------- /*---------------------------------------------------------------------------
* Set up Log Entity * Set up Log Entity
*--------------------------------------------------------------------------*/ *--------------------------------------------------------------------------*/
logMgr.logMgrHandle = (NwGtpv2cLogMgrHandleT) nwMiniLogMgrGetInstance(); logMgr.logMgrHandle = (NwGtpv2cLogMgrHandleT) nwMiniLogMgrGetInstance();
logMgr.logReqCallback = nwMiniLogMgrLogRequest; logMgr.logReqCallback = nwMiniLogMgrLogRequest;
@@ -257,21 +247,21 @@ int main(int argc, char* argv[])
* Send Message Request to Gtpv2c Stack Instance * Send Message Request to Gtpv2c Stack Instance
*--------------------------------------------------------------------------*/ *--------------------------------------------------------------------------*/
NW_LOG(NW_LOG_LEVEL_NOTI, "EGTPING %s ("NW_IPV4_ADDR")", egtPing.targetIpStr, NW_IPV4_ADDR_FORMAT(inet_addr(egtPing.targetIpStr))); NW_LOG(NW_LOG_LEVEL_NOTI, "EGTPING %s ("NW_IPV4_ADDR")", egtPing.targetIpStr, NW_IPV4_ADDR_FORMAT(inet_addr(egtPing.targetIpStr)));
rc = nwGtpv2cUlpPing(&ulpObj, rc = nwGtpv2cUlpPing(&ulpObj,
inet_addr(egtPing.targetIpStr), inet_addr(egtPing.targetIpStr),
egtPing.pingCount, egtPing.pingCount,
egtPing.pingInterval, egtPing.pingInterval,
2, 2,
3); 3);
NW_ASSERT(NW_OK == rc); NW_ASSERT(NW_OK == rc);
/*--------------------------------------------------------------------------- /*---------------------------------------------------------------------------
* Install signal handler * Install signal handler
*--------------------------------------------------------------------------*/ *--------------------------------------------------------------------------*/
signal(SIGINT, nwEgtPingHandleSignal); signal(SIGINT, nwEgtPingHandleSignal);
/*--------------------------------------------------------------------------- /*---------------------------------------------------------------------------
* Event loop * Event loop
*--------------------------------------------------------------------------*/ *--------------------------------------------------------------------------*/
NW_EVT_LOOP(); NW_EVT_LOOP();
@@ -281,8 +271,8 @@ int main(int argc, char* argv[])
* Destroy Gtpv2c Stack Instance * Destroy Gtpv2c Stack Instance
*--------------------------------------------------------------------------*/ *--------------------------------------------------------------------------*/
rc = nwGtpv2cFinalize(hGtpv2cStack); rc = nwGtpv2cFinalize(hGtpv2cStack);
if(rc != NW_OK)
{ if(rc != NW_OK) {
NW_LOG(NW_LOG_LEVEL_ERRO, "Failed to finalize gtpv2c stack instance. Error '%u' occured", rc); NW_LOG(NW_LOG_LEVEL_ERRO, "Failed to finalize gtpv2c stack instance. Error '%u' occured", rc);
} }
@@ -29,9 +29,9 @@
#ifndef __NW_EVT_H__ #ifndef __NW_EVT_H__
#define __NW_EVT_H__ #define __NW_EVT_H__
/** /**
* @file NwEvt.h * @file NwEvt.h
* @brief * @brief
*/ */
#ifdef __WITH_LIBEVENT__ #ifdef __WITH_LIBEVENT__
@@ -60,9 +60,8 @@ typedef struct event NwEventT;
/* HACK : Defining dummy values for compilation!*/ /* HACK : Defining dummy values for compilation!*/
typedef struct typedef struct {
{ int __tbd;
int __tbd;
} NwEventT; } NwEventT;
#define NW_EVT_READ (0) #define NW_EVT_READ (0)
@@ -71,9 +70,9 @@ typedef struct
#define NW_TMR_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_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_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) #define NW_EVENT_ADD(...) do { printf("error: Event library not defined!\n"); exit (0); } while(0)
#endif #endif
@@ -6,7 +6,7 @@
* * * *
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
/** /**
* @file hello-world.c * @file hello-world.c
* @brief This file contains example of a minimalistic log manager entity. * @brief This file contains example of a minimalistic log manager entity.
*/ */
@@ -21,7 +21,7 @@
#include "NwMiniLogMgrEntity.h" #include "NwMiniLogMgrEntity.h"
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
@@ -52,18 +52,19 @@ NwRcT nwMiniLogMgrSetLogLevel(NwMiniLogMgrT* thiz, NwU32T logLevel)
} }
NwRcT nwMiniLogMgrLogRequest (NwGtpv2cLogMgrHandleT hLogMgr, NwRcT nwMiniLogMgrLogRequest (NwGtpv2cLogMgrHandleT hLogMgr,
NwU32T logLevel, NwU32T logLevel,
NwCharT* file, NwCharT* file,
NwU32T line, NwU32T line,
NwCharT* logStr) NwCharT* logStr)
{ {
NwMiniLogMgrT* thiz = (NwMiniLogMgrT*) hLogMgr; NwMiniLogMgrT* thiz = (NwMiniLogMgrT*) hLogMgr;
if(thiz->logLevel >= logLevel) if(thiz->logLevel >= logLevel)
//printf("NWEGTPSTK %s - %s <%s,%u>\n", gLogLevelStr[logLevel], logStr, basename(file), line); //printf("NWEGTPSTK %s - %s <%s,%u>\n", gLogLevelStr[logLevel], logStr, basename(file), line);
return NW_OK; return NW_OK;
} }
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
@@ -6,7 +6,7 @@
* * * *
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
/** /**
* @file hello-world.c * @file hello-world.c
* @brief This file contains example of a minimalistic log manager entity. * @brief This file contains example of a minimalistic log manager entity.
*/ */
@@ -18,7 +18,7 @@
#ifndef NW_ASSERT #ifndef NW_ASSERT
#define NW_ASSERT assert #define NW_ASSERT assert
#endif #endif
#ifndef __NW_MINI_LOG_MGR_H__ #ifndef __NW_MINI_LOG_MGR_H__
#define __NW_MINI_LOG_MGR_H__ #define __NW_MINI_LOG_MGR_H__
@@ -33,11 +33,10 @@
} \ } \
} while(0) } while(0)
/** /**
* MiniLogMgr Class Definition * MiniLogMgr Class Definition
*/ */
typedef struct NwMiniLogMgr typedef struct NwMiniLogMgr {
{
NwU8T logLevel; /*< Log level */ NwU8T logLevel; /*< Log level */
} NwMiniLogMgrT; } NwMiniLogMgrT;
@@ -50,27 +49,27 @@ typedef struct NwMiniLogMgr
extern "C" { extern "C" {
#endif #endif
/** /**
* Get global singleton MiniLogMgr instance * Get global singleton MiniLogMgr instance
*/ */
NwMiniLogMgrT* nwMiniLogMgrGetInstance(); NwMiniLogMgrT* nwMiniLogMgrGetInstance();
/** /**
* Initialize MiniLogMgr * Initialize MiniLogMgr
* @param thiz : Pointer to global singleton MiniLogMgr instance * @param thiz : Pointer to global singleton MiniLogMgr instance
* @param logLevel : Log Level * @param logLevel : Log Level
*/ */
NwRcT nwMiniLogMgrInit(NwMiniLogMgrT* thiz, NwU32T logLevel ); NwRcT nwMiniLogMgrInit(NwMiniLogMgrT* thiz, NwU32T logLevel );
/** /**
* Set MiniLogMgr log level * Set MiniLogMgr log level
* @param thiz : Pointer to global singleton MiniLogMgr instance * @param thiz : Pointer to global singleton MiniLogMgr instance
* @param logLevel : Log Level * @param logLevel : Log Level
*/ */
NwRcT nwMiniLogMgrSetLogLevel(NwMiniLogMgrT* thiz, NwU32T logLevel); NwRcT nwMiniLogMgrSetLogLevel(NwMiniLogMgrT* thiz, NwU32T logLevel);
/** /**
* Process log request from stack * Process log request from stack
* @param thiz : Pointer to global singleton MiniLogMgr instance * @param thiz : Pointer to global singleton MiniLogMgr instance
* @param logLevel : Log Level * @param logLevel : Log Level
* @param file : Filename * @param file : Filename
@@ -78,12 +77,12 @@ NwRcT nwMiniLogMgrSetLogLevel(NwMiniLogMgrT* thiz, NwU32T logLevel);
* @param logStr : Log string * @param logStr : Log string
*/ */
NwRcT nwMiniLogMgrLogRequest (NwGtpv2cLogMgrHandleT logMgrHandle, NwRcT nwMiniLogMgrLogRequest (NwGtpv2cLogMgrHandleT logMgrHandle,
NwU32T logLevel, NwU32T logLevel,
NwCharT* file, NwCharT* file,
NwU32T line, NwU32T line,
NwCharT* logStr); NwCharT* logStr);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
@@ -6,7 +6,7 @@
* * * *
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
/** /**
* @file NwMiniTmrMgrEntity.c * @file NwMiniTmrMgrEntity.c
* @brief This file ontains example of a minimalistic timer manager entity. * @brief This file ontains example of a minimalistic timer manager entity.
*/ */
@@ -20,7 +20,7 @@
#ifndef NW_ASSERT #ifndef NW_ASSERT
#define NW_ASSERT assert #define NW_ASSERT assert
#endif #endif
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
@@ -55,11 +55,11 @@ NW_TMR_CALLBACK(nwGtpv2cNodeHandleStackTimerTimeout)
*--------------------------------------------------------------------------*/ *--------------------------------------------------------------------------*/
NwRcT nwTimerStart( NwGtpv2cTimerMgrHandleT tmrMgrHandle, NwRcT nwTimerStart( NwGtpv2cTimerMgrHandleT tmrMgrHandle,
NwU32T timeoutSec, NwU32T timeoutSec,
NwU32T timeoutUsec, NwU32T timeoutUsec,
NwU32T tmrType, NwU32T tmrType,
void* timeoutArg, void* timeoutArg,
NwGtpv2cTimerHandleT* hTmr) NwGtpv2cTimerHandleT* hTmr)
{ {
NwRcT rc = NW_OK; NwRcT rc = NW_OK;
NwGtpv2cNodeTmrT *pTmr; NwGtpv2cNodeTmrT *pTmr;
@@ -85,7 +85,7 @@ NwRcT nwTimerStart( NwGtpv2cTimerMgrHandleT tmrMgrHandle,
} }
NwRcT nwTimerStop( NwGtpv2cTimerMgrHandleT tmrMgrHandle, NwRcT nwTimerStop( NwGtpv2cTimerMgrHandleT tmrMgrHandle,
NwGtpv2cTimerHandleT hTmr) NwGtpv2cTimerHandleT hTmr)
{ {
evtimer_del(&(((NwGtpv2cNodeTmrT*)hTmr)->ev)); evtimer_del(&(((NwGtpv2cNodeTmrT*)hTmr)->ev));
free((void*)hTmr); free((void*)hTmr);
@@ -7,7 +7,7 @@
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
/** /**
* @file NwMiniTmrMgrEntity.c * @file NwMiniTmrMgrEntity.c
* @brief This file ontains example of a minimalistic timer manager entity. * @brief This file ontains example of a minimalistic timer manager entity.
*/ */
@@ -19,18 +19,16 @@
#ifndef NW_ASSERT #ifndef NW_ASSERT
#define NW_ASSERT assert #define NW_ASSERT assert
#endif #endif
#ifndef __NW_MINI_TMR_MGR_H__ #ifndef __NW_MINI_TMR_MGR_H__
#define __NW_MINI_TMR_MGR_H__ #define __NW_MINI_TMR_MGR_H__
typedef struct typedef struct {
{
NwU8T _tbd; NwU8T _tbd;
} NwGtpv2cNodeTmrMgrT; } NwGtpv2cNodeTmrMgrT;
typedef struct typedef struct {
{
NwEventT ev; NwEventT ev;
void* timeoutArg; void* timeoutArg;
} NwGtpv2cNodeTmrT; } NwGtpv2cNodeTmrT;
@@ -41,15 +39,15 @@ extern "C" {
#endif #endif
NwRcT nwTimerStart( NwGtpv2cTimerMgrHandleT tmrMgrHandle, NwRcT nwTimerStart( NwGtpv2cTimerMgrHandleT tmrMgrHandle,
NwU32T timeoutSec, NwU32T timeoutSec,
NwU32T timeoutUsec, NwU32T timeoutUsec,
NwU32T tmrType, NwU32T tmrType,
void* timeoutArg, void* timeoutArg,
NwGtpv2cTimerHandleT* hTmr); NwGtpv2cTimerHandleT* hTmr);
NwRcT nwTimerStop( NwGtpv2cTimerMgrHandleT tmrMgrHandle, NwRcT nwTimerStop( NwGtpv2cTimerMgrHandleT tmrMgrHandle,
NwGtpv2cTimerHandleT hTmr); NwGtpv2cTimerHandleT hTmr);
#ifdef __cplusplus #ifdef __cplusplus
@@ -7,7 +7,7 @@
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
/** /**
* @file NwMiniUdpEntity.c * @file NwMiniUdpEntity.c
* @brief This file contains example of a minimalistic ULP entity. * @brief This file contains example of a minimalistic ULP entity.
*/ */
@@ -27,7 +27,7 @@
#ifndef NW_ASSERT #ifndef NW_ASSERT
#define NW_ASSERT assert #define NW_ASSERT assert
#endif #endif
#define MAX_UDP_PAYLOAD_LEN (4096) #define MAX_UDP_PAYLOAD_LEN (4096)
@@ -56,39 +56,38 @@ void NW_EVT_CALLBACK(nwUdpDataIndicationCallbackData)
peerLen = sizeof(peer); peerLen = sizeof(peer);
bytesRead = recvfrom(fd, udpBuf, MAX_UDP_PAYLOAD_LEN , 0, (struct sockaddr *) &peer,(socklen_t*) &peerLen); bytesRead = recvfrom(fd, udpBuf, MAX_UDP_PAYLOAD_LEN , 0, (struct sockaddr *) &peer,(socklen_t*) &peerLen);
if(bytesRead > 0)
{ if(bytesRead > 0) {
thiz->packetsRcvd++; thiz->packetsRcvd++;
NW_LOG(NW_LOG_LEVEL_DEBG, "Received UDP message of size %u from peer %u.%u.%u.%u:%u", bytesRead, NW_LOG(NW_LOG_LEVEL_DEBG, "Received UDP message of size %u from peer %u.%u.%u.%u:%u", bytesRead,
(peer.sin_addr.s_addr & 0x000000ff), (peer.sin_addr.s_addr & 0x000000ff),
(peer.sin_addr.s_addr & 0x0000ff00) >> 8, (peer.sin_addr.s_addr & 0x0000ff00) >> 8,
(peer.sin_addr.s_addr & 0x00ff0000) >> 16, (peer.sin_addr.s_addr & 0x00ff0000) >> 16,
(peer.sin_addr.s_addr & 0xff000000) >> 24, (peer.sin_addr.s_addr & 0xff000000) >> 24,
ntohs(peer.sin_port)); ntohs(peer.sin_port));
rc = nwGtpv2cProcessUdpReq(thiz->hGtpv2cStack, udpBuf, bytesRead, ntohs(peer.sin_port), ntohl(peer.sin_addr.s_addr)); rc = nwGtpv2cProcessUdpReq(thiz->hGtpv2cStack, udpBuf, bytesRead, ntohs(peer.sin_port), ntohl(peer.sin_addr.s_addr));
} } else {
else switch (errno) {
{
switch (errno)
{
case ENETUNREACH: case ENETUNREACH:
NW_LOG(NW_LOG_LEVEL_ERRO, "Network not reachable", errno, strerror(errno)); NW_LOG(NW_LOG_LEVEL_ERRO, "Network not reachable", errno, strerror(errno));
break; break;
case EHOSTUNREACH: case EHOSTUNREACH:
NW_LOG(NW_LOG_LEVEL_ERRO, "Host not reachable", errno, strerror(errno)); NW_LOG(NW_LOG_LEVEL_ERRO, "Host not reachable", errno, strerror(errno));
break; break;
case ECONNREFUSED: case ECONNREFUSED:
NW_LOG(NW_LOG_LEVEL_ERRO, "Port not reachable", errno, strerror(errno)); NW_LOG(NW_LOG_LEVEL_ERRO, "Port not reachable", errno, strerror(errno));
break; break;
default: default:
NW_LOG(NW_LOG_LEVEL_ERRO, "%s", strerror(errno)); NW_LOG(NW_LOG_LEVEL_ERRO, "%s", strerror(errno));
} }
nwGtpv2cUdpReset(thiz); nwGtpv2cUdpReset(thiz);
} }
return; return;
} }
@@ -97,15 +96,14 @@ void NW_EVT_CALLBACK(nwUdpDataIndicationCallbackData)
* Public functions * Public functions
*--------------------------------------------------------------------------*/ *--------------------------------------------------------------------------*/
NwRcT nwGtpv2cUdpInit(NwGtpv2cNodeUdpT* thiz, NwGtpv2cStackHandleT hGtpv2cStack, NwU8T* ipAddrStr) NwRcT nwGtpv2cUdpInit(NwGtpv2cNodeUdpT* thiz, NwGtpv2cStackHandleT hGtpv2cStack, NwU8T* ipAddrStr)
{ {
int sd; int sd;
struct sockaddr_in addr; struct sockaddr_in addr;
sd = socket(AF_INET, SOCK_DGRAM, 0); sd = socket(AF_INET, SOCK_DGRAM, 0);
if (sd < 0) if (sd < 0) {
{
NW_LOG(NW_LOG_LEVEL_ERRO, "%s", strerror(errno)); NW_LOG(NW_LOG_LEVEL_ERRO, "%s", strerror(errno));
NW_ASSERT(0); NW_ASSERT(0);
} }
@@ -115,15 +113,14 @@ NwRcT nwGtpv2cUdpInit(NwGtpv2cNodeUdpT* thiz, NwGtpv2cStackHandleT hGtpv2cStack,
addr.sin_addr.s_addr = (strlen(ipAddrStr) ? inet_addr(ipAddrStr) : INADDR_ANY); addr.sin_addr.s_addr = (strlen(ipAddrStr) ? inet_addr(ipAddrStr) : INADDR_ANY);
memset(addr.sin_zero, '\0', sizeof (addr.sin_zero)); memset(addr.sin_zero, '\0', sizeof (addr.sin_zero));
if(bind(sd, (struct sockaddr *)&addr, sizeof(addr)) < 0) if(bind(sd, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
{
NW_LOG(NW_LOG_LEVEL_ERRO, "Error - %s", strerror(errno)); NW_LOG(NW_LOG_LEVEL_ERRO, "Error - %s", strerror(errno));
NW_ASSERT(0); NW_ASSERT(0);
} }
yes = 1; yes = 1;
if (setsockopt(sd, SOL_IP, IP_RECVERR, &yes, sizeof(yes)))
{ if (setsockopt(sd, SOL_IP, IP_RECVERR, &yes, sizeof(yes))) {
NW_LOG(NW_LOG_LEVEL_ERRO, "%s", strerror(errno)); NW_LOG(NW_LOG_LEVEL_ERRO, "%s", strerror(errno));
NW_ASSERT(0); NW_ASSERT(0);
} }
@@ -152,8 +149,7 @@ NwRcT nwGtpv2cUdpReset(NwGtpv2cNodeUdpT* thiz)
sd = socket(AF_INET, SOCK_DGRAM, 0); sd = socket(AF_INET, SOCK_DGRAM, 0);
if (sd < 0) if (sd < 0) {
{
NW_LOG(NW_LOG_LEVEL_ERRO, "%s", strerror(errno)); NW_LOG(NW_LOG_LEVEL_ERRO, "%s", strerror(errno));
NW_ASSERT(0); NW_ASSERT(0);
} }
@@ -163,15 +159,14 @@ NwRcT nwGtpv2cUdpReset(NwGtpv2cNodeUdpT* thiz)
addr.sin_addr.s_addr = (thiz->ipv4Addr); addr.sin_addr.s_addr = (thiz->ipv4Addr);
memset(addr.sin_zero, '\0', sizeof (addr.sin_zero)); memset(addr.sin_zero, '\0', sizeof (addr.sin_zero));
if(bind(sd, (struct sockaddr *)&addr, sizeof(addr)) < 0) if(bind(sd, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
{
NW_LOG(NW_LOG_LEVEL_ERRO, "%s", strerror(errno)); NW_LOG(NW_LOG_LEVEL_ERRO, "%s", strerror(errno));
NW_ASSERT(0); NW_ASSERT(0);
} }
yes = 1; yes = 1;
if (setsockopt(sd, SOL_IP, IP_RECVERR, &yes, sizeof(yes)))
{ if (setsockopt(sd, SOL_IP, IP_RECVERR, &yes, sizeof(yes))) {
NW_LOG(NW_LOG_LEVEL_ERRO, "%s", strerror(errno)); NW_LOG(NW_LOG_LEVEL_ERRO, "%s", strerror(errno));
NW_ASSERT(0); NW_ASSERT(0);
} }
@@ -184,21 +179,21 @@ NwRcT nwGtpv2cUdpReset(NwGtpv2cNodeUdpT* thiz)
} }
NwRcT nwGtpv2cUdpDataReq(NwGtpv2cUdpHandleT udpHandle, NwRcT nwGtpv2cUdpDataReq(NwGtpv2cUdpHandleT udpHandle,
NwU8T* dataBuf, NwU8T* dataBuf,
NwU32T dataSize, NwU32T dataSize,
NwU32T peerIp, NwU32T peerIp,
NwU32T peerPort) NwU32T peerPort)
{ {
struct sockaddr_in peerAddr; struct sockaddr_in peerAddr;
NwS32T bytesSent; NwS32T bytesSent;
NwGtpv2cNodeUdpT* thiz = (NwGtpv2cNodeUdpT*) udpHandle; NwGtpv2cNodeUdpT* thiz = (NwGtpv2cNodeUdpT*) udpHandle;
NW_LOG(NW_LOG_LEVEL_DEBG, "Sending %u bytes of data to %u.%u.%u.%u:%u", dataSize, NW_LOG(NW_LOG_LEVEL_DEBG, "Sending %u bytes of data to %u.%u.%u.%u:%u", dataSize,
(peerIp & 0xff000000) >> 24, (peerIp & 0xff000000) >> 24,
(peerIp & 0x00ff0000) >> 16, (peerIp & 0x00ff0000) >> 16,
(peerIp & 0x0000ff00) >> 8, (peerIp & 0x0000ff00) >> 8,
(peerIp & 0x000000ff), (peerIp & 0x000000ff),
peerPort); peerPort);
peerAddr.sin_family = AF_INET; peerAddr.sin_family = AF_INET;
peerAddr.sin_port = htons(peerPort); peerAddr.sin_port = htons(peerPort);
@@ -206,12 +201,10 @@ NwRcT nwGtpv2cUdpDataReq(NwGtpv2cUdpHandleT udpHandle,
memset(peerAddr.sin_zero, '\0', sizeof (peerAddr.sin_zero)); memset(peerAddr.sin_zero, '\0', sizeof (peerAddr.sin_zero));
bytesSent = sendto (thiz->hSocket, dataBuf, dataSize, 0, (struct sockaddr *) &peerAddr, sizeof(peerAddr)); bytesSent = sendto (thiz->hSocket, dataBuf, dataSize, 0, (struct sockaddr *) &peerAddr, sizeof(peerAddr));
if(bytesSent < 0)
{ if(bytesSent < 0) {
NW_LOG(NW_LOG_LEVEL_ERRO, "sendto - %s", strerror(errno)); NW_LOG(NW_LOG_LEVEL_ERRO, "sendto - %s", strerror(errno));
} } else {
else
{
thiz->packetsSent++; thiz->packetsSent++;
} }
@@ -7,7 +7,7 @@
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
/** /**
* @file NwMiniUdpEntity.c * @file NwMiniUdpEntity.c
* @brief This file contains example of a minimalistic ULP entity. * @brief This file contains example of a minimalistic ULP entity.
*/ */
@@ -19,13 +19,12 @@
#ifndef NW_ASSERT #ifndef NW_ASSERT
#define NW_ASSERT assert #define NW_ASSERT assert
#endif #endif
#ifndef __NW_MINI_UDP_ENTITY_H__ #ifndef __NW_MINI_UDP_ENTITY_H__
#define __NW_MINI_UDP_ENTITY_H__ #define __NW_MINI_UDP_ENTITY_H__
typedef struct typedef struct {
{
NwU32T ipv4Addr; NwU32T ipv4Addr;
NwU32T hSocket; NwU32T hSocket;
NwEventT ev; NwEventT ev;
@@ -43,10 +42,10 @@ NwRcT nwGtpv2cUdpInit(NwGtpv2cNodeUdpT* thiz, NwGtpv2cStackHandleT hGtpv2cStack,
NwRcT nwGtpv2cUdpDestroy(NwGtpv2cNodeUdpT* thiz); NwRcT nwGtpv2cUdpDestroy(NwGtpv2cNodeUdpT* thiz);
NwRcT nwGtpv2cUdpDataReq(NwGtpv2cUdpHandleT udpHandle, NwRcT nwGtpv2cUdpDataReq(NwGtpv2cUdpHandleT udpHandle,
NwU8T* dataBuf, NwU8T* dataBuf,
NwU32T dataSize, NwU32T dataSize,
NwU32T peerIp, NwU32T peerIp,
NwU32T peerPort); NwU32T peerPort);
NwRcT nwGtpv2cUdpReset(NwGtpv2cNodeUdpT* thiz); NwRcT nwGtpv2cUdpReset(NwGtpv2cNodeUdpT* thiz);

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