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
+12 -12
View File
@@ -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);
} }
File diff suppressed because it is too large Load Diff
+31 -31
View File
@@ -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
+1 -1
View File
@@ -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>
+25 -33
View File
@@ -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 -6
View File
@@ -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_ */
+13 -14
View File
@@ -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;
+341 -356
View File
@@ -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);
}
} }
+69 -69
View File
@@ -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;
} }
+142 -136
View File
@@ -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;
} }
+10 -10
View File
@@ -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
+2 -2
View File
@@ -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_ */
+181 -181
View File
@@ -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:
gtpuah_param_act(GTPUAH_PARAM_BAD_VALUE, "GTPUAH", "--peer-ip", s);
break;
}
}
switch (flag) case PARAM_RADDR:
{ gtpuah_param_act(GTPUAH_PARAM_BAD_VALUE, "GTPUAH", "--peer-ip", s);
case PARAM_LADDR: break;
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
} }
+310 -258
View File
@@ -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");
pr_info("GTPUAH: Modified by EURECOM Lionel GAUTHIER 2014\n");
#ifndef CMAKER #ifndef CMAKER
pr_info("GTPUAH: Compiled %s at time %s\n",__DATE__,__TIME__); pr_info("GTPUAH: Compiled %s at time %s\n",__DATE__,__TIME__);
#endif #endif
#if defined(WITH_IPV6) #if defined(WITH_IPV6)
pr_info("GTPURH: IPv4/IPv6 enabled\n"); pr_info("GTPURH: IPv4/IPv6 enabled\n");
#else #else
pr_info("GTPURH: IPv4 only enabled\n"); pr_info("GTPURH: IPv4 only enabled\n");
#endif #endif
return xt_register_targets(gtpuah_tg_reg, ARRAY_SIZE(gtpuah_tg_reg)); 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)));
}; };
+182 -173
View File
@@ -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
} }
+382 -336
View File
@@ -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_OUTGOING;
#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",
info_pP->action,
iph_p->saddr & 0xFF,
(iph_p->saddr & 0x0000FF00) >> 8,
(iph_p->saddr & 0x00FF0000) >> 16,
iph_p->saddr >> 24,
iph_p->daddr & 0xFF,
(iph_p->daddr & 0x0000FF00) >> 8,
(iph_p->daddr & 0x00FF0000) >> 16,
iph_p->daddr >> 24,
iph_p->protocol,
ntohs(iph_p->tot_len),
skb_pP->mark,
skb_pP->pkt_type);
#endif
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 GTPURH_FAILURE;
} }
};
//skb_pP->pkt_type = PACKET_OTHERHOST;
skb_pP->pkt_type = PACKET_OUTGOING;
#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",
info_pP->action,
iph_p->saddr & 0xFF,
(iph_p->saddr & 0x0000FF00) >> 8,
(iph_p->saddr & 0x00FF0000) >> 16,
iph_p->saddr >> 24,
iph_p->daddr & 0xFF,
(iph_p->daddr & 0x0000FF00) >> 8,
(iph_p->daddr & 0x00FF0000) >> 16,
iph_p->daddr >> 24,
iph_p->protocol,
ntohs(iph_p->tot_len),
skb_pP->mark,
skb_pP->pkt_type);
#endif
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 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 #endif
#if defined(WITH_IPV6) #if defined(WITH_IPV6)
pr_info("GTPURH: IPv4/IPv6 enabled\n"); pr_info("GTPURH: IPv4/IPv6 enabled\n");
#else #else
pr_info("GTPURH: IPv4 only enabled\n"); pr_info("GTPURH: IPv4 only enabled\n");
#endif #endif
return xt_register_targets(gtpurh_tg_reg, ARRAY_SIZE(gtpurh_tg_reg)); 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
} }
@@ -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;
@@ -98,8 +97,7 @@ typedef struct NwGtpv1uStack
* 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 */
@@ -117,8 +115,7 @@ typedef struct NwGtpv1uTunnelEndPoint
* 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*);
@@ -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;
@@ -181,8 +177,7 @@ typedef struct NwGtpv1uMsg
* 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;
+49 -67
View File
@@ -79,8 +79,7 @@ typedef NwPtrT NwGtpv1uLogMgrHandleT; /**< Gtpv2 Stack Log M
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;
@@ -96,8 +95,7 @@ typedef struct NwGtpv1uStackConfig
* 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 */
@@ -133,8 +131,7 @@ typedef NwU32T NwGtpv1uUlpSessionHandleT; /**< Gtpv2 Ulp session Handle */
* 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;
@@ -145,8 +142,7 @@ typedef struct
* destroying a session. * destroying a session.
*/ */
typedef struct typedef struct {
{
NW_IN NwGtpv1uStackSessionHandleT hStackSessionHandle; NW_IN NwGtpv1uStackSessionHandleT hStackSessionHandle;
} NwGtpv1uDestroyTunnelEndPointT; } NwGtpv1uDestroyTunnelEndPointT;
@@ -155,8 +151,7 @@ typedef struct
* 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;
@@ -169,8 +164,7 @@ typedef struct
* 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;
@@ -185,8 +179,7 @@ typedef struct
* 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;
@@ -202,8 +195,7 @@ typedef struct
* 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;
@@ -216,8 +208,7 @@ typedef struct
* 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;
@@ -231,8 +222,7 @@ typedef struct
* 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;
@@ -247,8 +237,7 @@ typedef struct
* 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;
@@ -261,12 +250,10 @@ typedef struct
* 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;
@@ -449,7 +431,7 @@ 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.
@@ -461,7 +443,7 @@ 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.
@@ -473,7 +455,7 @@ 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);
/** /**
@@ -486,7 +468,7 @@ 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.
@@ -498,7 +480,7 @@ 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.
@@ -528,10 +510,10 @@ nwGtpv1uSetLogLevel( NW_IN NwGtpv1uStackHandleT hGtpuStackHandle,
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
@@ -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
} }
+135 -139
View File
@@ -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.
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
@@ -60,8 +60,7 @@ 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;
@@ -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
@@ -36,8 +36,7 @@ extern NwU32T g_log_level;
} \ } \
} while(0) } while(0)
typedef struct typedef struct {
{
NwU8T logLevel; NwU8T logLevel;
} NwMiniLogMgrT; } NwMiniLogMgrT;
@@ -46,10 +45,10 @@ 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
} }
@@ -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
@@ -24,8 +24,7 @@
#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;
} }
@@ -24,8 +24,7 @@
#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
@@ -19,8 +19,7 @@
#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;
@@ -56,7 +55,7 @@ nwMiniUlpTpduSend(NwMiniUlpEntityT* thiz, NwU8T* tpduBuf, NwU32T tpduLen , NwU16
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;
} }
@@ -42,8 +42,7 @@
* @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;
@@ -81,8 +79,8 @@ 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
} }
@@ -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;
@@ -121,8 +120,7 @@ typedef struct NwGtpv2cStack
* 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;
@@ -60,7 +60,7 @@ nwGtpv2cTrxnNew( NW_IN NwGtpv2cStackT* pStack);
*/ */
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
@@ -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);
@@ -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;
+298 -298
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
@@ -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
} }
@@ -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;
@@ -144,8 +143,7 @@ typedef struct NwGtpv2cStackConfigS
* 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 {
@@ -188,8 +185,7 @@ typedef struct NwGtpv2cErrorS
* 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;
@@ -205,8 +201,7 @@ typedef struct
* 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;
@@ -223,8 +218,7 @@ typedef struct
* 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. */
@@ -238,8 +232,7 @@ typedef struct
* 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;
@@ -255,8 +248,7 @@ typedef struct
* 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;
@@ -272,8 +264,7 @@ typedef struct
* 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;
@@ -285,8 +276,7 @@ typedef struct
* 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;
@@ -296,8 +286,7 @@ typedef struct
* 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;
@@ -310,8 +299,7 @@ typedef struct
* deleting a local tunnel. * deleting a local tunnel.
*/ */
typedef struct typedef struct {
{
NW_IN NwGtpv2cTunnelHandleT hTunnel; NW_IN NwGtpv2cTunnelHandleT hTunnel;
} NwGtpv2cDeleteLocalTunnelInfoT; } NwGtpv2cDeleteLocalTunnelInfoT;
@@ -320,12 +308,10 @@ typedef struct
* 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,8 +333,7 @@ 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);
@@ -359,8 +344,7 @@ 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,
@@ -373,8 +357,7 @@ 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,
@@ -394,8 +377,7 @@ 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,
@@ -412,8 +394,7 @@ 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,
@@ -477,7 +458,7 @@ 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.
@@ -489,7 +470,7 @@ 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.
@@ -501,7 +482,7 @@ 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);
/** /**
@@ -514,7 +495,7 @@ 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.
@@ -526,7 +507,7 @@ 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.
@@ -554,10 +535,10 @@ nwGtpv2cSetLogLevel( NW_IN NwGtpv2cStackHandleT hGtpcStackHandle,
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);
/** /**
@@ -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,173 +242,173 @@ 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,
@@ -423,187 +418,187 @@ nwGtpv2cMsgAddIeCause(NW_IN NwGtpv2cMsgHandleT hMsg,
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);
@@ -44,8 +44,7 @@
* @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,62 +64,62 @@ 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,
@@ -128,10 +127,10 @@ nwGtpv2cMsgParserAddIe( NW_IN NwGtpv2cMsgParserT* thiz,
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
File diff suppressed because it is too large Load Diff
+161 -145
View File
@@ -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,12 +158,12 @@ 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)
@@ -181,12 +173,12 @@ nwGtpv2cMsgSetTeid(NW_IN NwGtpv2cMsgHandleT hMsg, NwU32T 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)
@@ -196,12 +188,12 @@ nwGtpv2cMsgSetTeidPresent(NW_IN NwGtpv2cMsgHandleT hMsg, NwBoolT 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)
@@ -211,11 +203,11 @@ nwGtpv2cMsgSetSeqNumber(NW_IN NwGtpv2cMsgHandleT hMsg, NwU32T 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)
@@ -224,11 +216,11 @@ nwGtpv2cMsgGetTeid(NW_IN NwGtpv2cMsgHandleT 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)
@@ -237,11 +229,11 @@ nwGtpv2cMsgGetTeidPresent(NW_IN NwGtpv2cMsgHandleT 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)
@@ -279,9 +271,9 @@ 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;
@@ -300,9 +292,9 @@ 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;
@@ -321,9 +313,9 @@ 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;
@@ -342,10 +334,10 @@ 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;
@@ -364,8 +356,8 @@ 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;
@@ -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;
@@ -427,11 +418,11 @@ 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];
@@ -443,185 +434,206 @@ nwGtpv2cMsgAddIeFteid(NW_IN NwGtpv2cMsgHandleT hMsg,
*((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;
} }
@@ -630,19 +642,18 @@ 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;
@@ -653,11 +664,11 @@ nwGtpv2cMsgGetIeFteid(NW_IN NwGtpv2cMsgHandleT hMsg,
*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;
@@ -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,8 +82,7 @@ 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 */
@@ -94,8 +90,7 @@ NwGtpv2cMsgIeInfoT echoRspIeInfoTbl[] =
}; };
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,30 +374,31 @@ 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;
@@ -457,118 +441,114 @@ nwGtpv2cMsgIeParseInfoNew(NwGtpv2cStackHandleT hStack, NwU8T msgType)
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;
} }
} }
@@ -594,8 +574,8 @@ 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)
{ {
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,8 +627,7 @@ 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
@@ -666,15 +639,15 @@ nwGtpv2cMsgIeParse(NW_IN NwGtpv2cMsgIeParseInfoT* thiz,
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;
@@ -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;
@@ -97,28 +98,28 @@ 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;
} }
@@ -128,28 +129,25 @@ nwGtpv2cMsgParserAddIe( NW_IN NwGtpv2cMsgParserT* thiz,
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;
} }
@@ -70,10 +70,10 @@ 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;
} }
@@ -219,18 +217,14 @@ 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;
@@ -258,22 +253,18 @@ nwGtpv2cTrxnNew( NW_IN NwGtpv2cStackT* thiz)
*/ */
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;
@@ -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);
} }
@@ -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;
} }
@@ -29,8 +29,7 @@ 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++;
} }
@@ -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)
@@ -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);
} }
@@ -258,11 +248,11 @@ int main(int argc, char* argv[])
*--------------------------------------------------------------------------*/ *--------------------------------------------------------------------------*/
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);
/*--------------------------------------------------------------------------- /*---------------------------------------------------------------------------
@@ -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);
} }
@@ -60,8 +60,7 @@ 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;
@@ -52,15 +52,16 @@ 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
@@ -36,8 +36,7 @@
/** /**
* MiniLogMgr Class Definition * MiniLogMgr Class Definition
*/ */
typedef struct NwMiniLogMgr typedef struct NwMiniLogMgr {
{
NwU8T logLevel; /*< Log level */ NwU8T logLevel; /*< Log level */
} NwMiniLogMgrT; } NwMiniLogMgrT;
@@ -78,10 +77,10 @@ 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
} }
@@ -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);
@@ -24,13 +24,11 @@
#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
@@ -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;
} }
@@ -104,8 +103,7 @@ NwRcT nwGtpv2cUdpInit(NwGtpv2cNodeUdpT* thiz, NwGtpv2cStackHandleT hGtpv2cStack,
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++;
} }
@@ -24,8 +24,7 @@
#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);
@@ -55,8 +55,7 @@ nwGtpv2cUlpDestroy(NwGtpv2cNodeUlpT* thiz)
return NW_OK; return NW_OK;
} }
typedef struct NwGtpv2cPeerS typedef struct NwGtpv2cPeerS {
{
NwU32T ipv4Addr; NwU32T ipv4Addr;
NwU32T pingCount; NwU32T pingCount;
NwU32T pingInterval; NwU32T pingInterval;
@@ -74,8 +73,7 @@ nwGtpv2cUlpCreatePeerContext(NwGtpv2cNodeUlpT* thiz, NwU32T peerIp)
NwGtpv2cUlpApiT ulpReq; NwGtpv2cUlpApiT ulpReq;
NwGtpv2cPeerT *pPeer = (NwGtpv2cPeerT*) malloc(sizeof(NwGtpv2cPeerT)); NwGtpv2cPeerT *pPeer = (NwGtpv2cPeerT*) malloc(sizeof(NwGtpv2cPeerT));
if(pPeer) if(pPeer) {
{
pPeer->ipv4Addr = peerIp; pPeer->ipv4Addr = peerIp;
/* /*
@@ -93,6 +91,7 @@ nwGtpv2cUlpCreatePeerContext(NwGtpv2cNodeUlpT* thiz, NwU32T peerIp)
NW_ASSERT(NW_OK == rc); NW_ASSERT(NW_OK == rc);
pPeer->hTunnel = ulpReq.apiInfo.createLocalTunnelInfo.hTunnel; pPeer->hTunnel = ulpReq.apiInfo.createLocalTunnelInfo.hTunnel;
} }
return pPeer; return pPeer;
} }
@@ -114,11 +113,11 @@ nwGtpv2cUlpSendEchoRequestToPeer(NwGtpv2cNodeUlpT* thiz, NwGtpv2cPeerT *pPeer)
ulpReq.apiInfo.initialReqInfo.hUlpTunnel = (NwGtpv2cUlpTunnelHandleT)pPeer; ulpReq.apiInfo.initialReqInfo.hUlpTunnel = (NwGtpv2cUlpTunnelHandleT)pPeer;
rc = nwGtpv2cMsgNew( thiz->hGtpv2cStack, rc = nwGtpv2cMsgNew( thiz->hGtpv2cStack,
NW_FALSE, NW_FALSE,
NW_GTP_ECHO_REQ, NW_GTP_ECHO_REQ,
0, 0,
0, 0,
&(ulpReq.hMsg)); &(ulpReq.hMsg));
NW_ASSERT(NW_OK == rc); NW_ASSERT(NW_OK == rc);
@@ -163,7 +162,7 @@ nwGtpv2cUlpPing(NwGtpv2cNodeUlpT* thiz,
NwRcT NwRcT
nwGtpv2cUlpProcessStackReqCallback (NwGtpv2cUlpHandleT hUlp, nwGtpv2cUlpProcessStackReqCallback (NwGtpv2cUlpHandleT hUlp,
NwGtpv2cUlpApiT *pUlpApi) NwGtpv2cUlpApiT *pUlpApi)
{ {
NwRcT rc; NwRcT rc;
NwU32T seqNum; NwU32T seqNum;
@@ -176,43 +175,42 @@ nwGtpv2cUlpProcessStackReqCallback (NwGtpv2cUlpHandleT hUlp,
thiz = (NwGtpv2cNodeUlpT*) hUlp; thiz = (NwGtpv2cNodeUlpT*) hUlp;
switch(pUlpApi->apiType) switch(pUlpApi->apiType) {
{ case NW_GTPV2C_ULP_API_TRIGGERED_RSP_IND: {
case NW_GTPV2C_ULP_API_TRIGGERED_RSP_IND: pPeer = (NwGtpv2cPeerT*)pUlpApi->apiInfo.triggeredRspIndInfo.hUlpTrxn;
{
pPeer = (NwGtpv2cPeerT*)pUlpApi->apiInfo.triggeredRspIndInfo.hUlpTrxn;
if(pUlpApi->apiInfo.triggeredRspIndInfo.msgType == NW_GTP_ECHO_RSP) if(pUlpApi->apiInfo.triggeredRspIndInfo.msgType == NW_GTP_ECHO_RSP) {
{ seqNum = nwGtpv2cMsgGetSeqNumber(pUlpApi->hMsg);
seqNum = nwGtpv2cMsgGetSeqNumber(pUlpApi->hMsg); len = nwGtpv2cMsgGetLength(pUlpApi->hMsg);
len = nwGtpv2cMsgGetLength(pUlpApi->hMsg);
NW_ASSERT(gettimeofday(&tv, NULL) == 0); NW_ASSERT(gettimeofday(&tv, NULL) == 0);
recvTimeStamp = (tv.tv_sec * 1000000) + tv.tv_usec; recvTimeStamp = (tv.tv_sec * 1000000) + tv.tv_usec;
NW_LOG(NW_LOG_LEVEL_NOTI, "%u bytes of response from "NW_IPV4_ADDR": gtp_seq=%u time=%2.2f ms", len, NW_IPV4_ADDR_FORMAT(pPeer->ipv4Addr), seqNum, (float) (recvTimeStamp - pPeer->sendTimeStamp) / 1000 ); NW_LOG(NW_LOG_LEVEL_NOTI, "%u bytes of response from "NW_IPV4_ADDR": gtp_seq=%u time=%2.2f ms", len, NW_IPV4_ADDR_FORMAT(pPeer->ipv4Addr), seqNum,
if(pPeer->pingCount) (float) (recvTimeStamp - pPeer->sendTimeStamp) / 1000 );
{
sleep(pPeer->pingInterval);
rc = nwGtpv2cUlpSendEchoRequestToPeer(thiz, pPeer);
if(pPeer->pingCount != 0xffffffff) pPeer->pingCount--;
}
}
} if(pPeer->pingCount) {
break; sleep(pPeer->pingInterval);
case NW_GTPV2C_ULP_API_RSP_FAILURE_IND:
{
pPeer = (NwGtpv2cPeerT*)pUlpApi->apiInfo.rspFailureInfo.hUlpTrxn;
NW_LOG(NW_LOG_LEVEL_DEBG, "No response from "NW_IPV4_ADDR" (2123)!", NW_IPV4_ADDR_FORMAT(pPeer->ipv4Addr));
rc = nwGtpv2cUlpSendEchoRequestToPeer(thiz, pPeer); rc = nwGtpv2cUlpSendEchoRequestToPeer(thiz, pPeer);
}
break;
default: if(pPeer->pingCount != 0xffffffff) pPeer->pingCount--;
NW_LOG(NW_LOG_LEVEL_WARN, "Received undefined UlpApi from gtpv2c stack!"); }
}
} }
break;
case NW_GTPV2C_ULP_API_RSP_FAILURE_IND: {
pPeer = (NwGtpv2cPeerT*)pUlpApi->apiInfo.rspFailureInfo.hUlpTrxn;
NW_LOG(NW_LOG_LEVEL_DEBG, "No response from "NW_IPV4_ADDR" (2123)!", NW_IPV4_ADDR_FORMAT(pPeer->ipv4Addr));
rc = nwGtpv2cUlpSendEchoRequestToPeer(thiz, pPeer);
}
break;
default:
NW_LOG(NW_LOG_LEVEL_WARN, "Received undefined UlpApi from gtpv2c stack!");
}
return NW_OK; return NW_OK;
} }
@@ -19,8 +19,7 @@
#ifndef __NW_MINI_ULP_H__ #ifndef __NW_MINI_ULP_H__
#define __NW_MINI_ULP_H__ #define __NW_MINI_ULP_H__
typedef struct typedef struct {
{
NwU8T peerIpStr[16]; NwU8T peerIpStr[16];
NwU32T restartCounter; NwU32T restartCounter;
NwGtpv2cStackHandleT hGtpv2cStack; NwGtpv2cStackHandleT hGtpv2cStack;
@@ -38,7 +37,7 @@ nwGtpv2cUlpDestroy(NwGtpv2cNodeUlpT* thiz);
NwRcT NwRcT
nwGtpv2cUlpProcessStackReqCallback (NwGtpv2cUlpHandleT hUlp, nwGtpv2cUlpProcessStackReqCallback (NwGtpv2cUlpHandleT hUlp,
NwGtpv2cUlpApiT *pUlpApi); NwGtpv2cUlpApiT *pUlpApi);
NwRcT NwRcT
nwGtpv2cUlpPing(NwGtpv2cNodeUlpT* thiz, nwGtpv2cUlpPing(NwGtpv2cNodeUlpT* thiz,
@@ -60,8 +60,7 @@ 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;
@@ -52,14 +52,16 @@ 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("NWGTPV2C-STK %s - %s <%s,%u>\n", gLogLevelStr[logLevel], logStr, basename(file), line); printf("NWGTPV2C-STK %s - %s <%s,%u>\n", gLogLevelStr[logLevel], logStr, basename(file), line);
return NW_OK; return NW_OK;
} }
@@ -36,8 +36,7 @@
/** /**
* MiniLogMgr Class Definition * MiniLogMgr Class Definition
*/ */
typedef struct NwMiniLogMgr typedef struct NwMiniLogMgr {
{
NwU8T logLevel; /*< Log level */ NwU8T logLevel; /*< Log level */
} NwMiniLogMgrT; } NwMiniLogMgrT;
@@ -78,10 +77,10 @@ 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
} }
@@ -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;
@@ -87,7 +87,7 @@ NwRcT nwTimerStart( NwGtpv2cTimerMgrHandleT tmrMgrHandle,
} }
NwRcT nwTimerStop( NwGtpv2cTimerMgrHandleT tmrMgrHandle, NwRcT nwTimerStop( NwGtpv2cTimerMgrHandleT tmrMgrHandle,
NwGtpv2cTimerHandleT hTmr) NwGtpv2cTimerHandleT hTmr)
{ {
NW_LOG(NW_LOG_LEVEL_DEBG, "Received stop timer request from stack for timer handle %u", hTmr); NW_LOG(NW_LOG_LEVEL_DEBG, "Received stop timer request from stack for timer handle %u", hTmr);
evtimer_del(&(((NwGtpv2cNodeTmrT*)hTmr)->ev)); evtimer_del(&(((NwGtpv2cNodeTmrT*)hTmr)->ev));
@@ -24,13 +24,11 @@
#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
@@ -55,19 +55,17 @@ 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)
{ if(bytesRead) {
NwU32T peerIp = (peer.sin_addr.s_addr); NwU32T peerIp = (peer.sin_addr.s_addr);
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,
(peerIp & 0x000000ff), (peerIp & 0x000000ff),
(peerIp & 0x0000ff00) >> 8, (peerIp & 0x0000ff00) >> 8,
(peerIp & 0x00ff0000) >> 16, (peerIp & 0x00ff0000) >> 16,
(peerIp & 0xff000000) >> 24, (peerIp & 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
{
NW_LOG(NW_LOG_LEVEL_ERRO, "%s", strerror(errno)); NW_LOG(NW_LOG_LEVEL_ERRO, "%s", strerror(errno));
} }
} }
@@ -84,8 +82,7 @@ NwRcT nwGtpv2cUdpInit(NwGtpv2cNodeUdpT* thiz, NwGtpv2cStackHandleT hGtpv2cStack,
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);
} }
@@ -95,8 +92,7 @@ NwRcT nwGtpv2cUdpInit(NwGtpv2cNodeUdpT* thiz, NwGtpv2cStackHandleT hGtpv2cStack,
addr.sin_addr.s_addr = inet_addr(ipv4Addr); addr.sin_addr.s_addr = inet_addr(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);
} }
@@ -115,21 +111,21 @@ 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)
{ {
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 buf of size %u for on handle %x to peer %u.%u.%u.%u:%u", dataSize, udpHandle, NW_LOG(NW_LOG_LEVEL_DEBG, "Sending buf of size %u for on handle %x to peer %u.%u.%u.%u:%u", dataSize, udpHandle,
(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);
@@ -138,11 +134,11 @@ NwRcT nwGtpv2cUdpDataReq(NwGtpv2cUdpHandleT udpHandle,
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, "%s", strerror(errno)); NW_LOG(NW_LOG_LEVEL_ERRO, "%s", strerror(errno));
NW_ASSERT(0); NW_ASSERT(0);
} }
return NW_OK; return NW_OK;
} }
@@ -24,8 +24,7 @@
#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;
NwGtpv2cStackHandleT hGtpv2cStack; NwGtpv2cStackHandleT hGtpv2cStack;
@@ -40,10 +39,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);
#ifdef __cplusplus #ifdef __cplusplus
} }
@@ -79,11 +79,11 @@ nwGtpv2cUlpSenEchoRequestToPeer(NwGtpv2cNodeUlpT* thiz, NwU32T peerIp)
ulpReq.apiInfo.initialReqInfo.peerIp = htonl(peerIp); ulpReq.apiInfo.initialReqInfo.peerIp = htonl(peerIp);
rc = nwGtpv2cMsgNew( thiz->hGtpv2cStack, rc = nwGtpv2cMsgNew( thiz->hGtpv2cStack,
NW_FALSE, NW_FALSE,
NW_GTP_ECHO_REQ, NW_GTP_ECHO_REQ,
0, 0,
0, 0,
&(ulpReq.hMsg)); &(ulpReq.hMsg));
NW_ASSERT(NW_OK == rc); NW_ASSERT(NW_OK == rc);
@@ -113,11 +113,11 @@ nwGtpv2cUlpCreateSessionRequestToPeer(NwGtpv2cNodeUlpT* thiz)
ulpReq.apiInfo.initialReqInfo.peerIp = ntohl(inet_addr(thiz->peerIpStr)); ulpReq.apiInfo.initialReqInfo.peerIp = ntohl(inet_addr(thiz->peerIpStr));
rc = nwGtpv2cMsgNew( thiz->hGtpv2cStack, rc = nwGtpv2cMsgNew( thiz->hGtpv2cStack,
NW_TRUE, NW_TRUE,
NW_GTP_CREATE_SESSION_REQ, NW_GTP_CREATE_SESSION_REQ,
0, 0,
0, 0,
&(ulpReq.hMsg)); &(ulpReq.hMsg));
NW_ASSERT(NW_OK == rc); NW_ASSERT(NW_OK == rc);
@@ -132,7 +132,7 @@ nwGtpv2cUlpCreateSessionRequestToPeer(NwGtpv2cNodeUlpT* thiz)
NwRcT NwRcT
nwGtpv2cUlpProcessStackReqCallback (NwGtpv2cUlpHandleT hUlp, nwGtpv2cUlpProcessStackReqCallback (NwGtpv2cUlpHandleT hUlp,
NwGtpv2cUlpApiT *pUlpApi) NwGtpv2cUlpApiT *pUlpApi)
{ {
NwRcT rc; NwRcT rc;
NwGtpv2cNodeUlpT* thiz; NwGtpv2cNodeUlpT* thiz;
@@ -140,142 +140,135 @@ nwGtpv2cUlpProcessStackReqCallback (NwGtpv2cUlpHandleT hUlp,
thiz = (NwGtpv2cNodeUlpT*) hUlp; thiz = (NwGtpv2cNodeUlpT*) hUlp;
switch(pUlpApi->apiType) switch(pUlpApi->apiType) {
{
case NW_GTPV2C_ULP_API_INITIAL_REQ_IND: case NW_GTPV2C_ULP_API_INITIAL_REQ_IND: {
{ NwGtpv2cUlpApiT ulpReq;
NwGtpv2cUlpApiT ulpReq; NwGtpv2cMsgParserT *pMsgParser;
NwGtpv2cMsgParserT *pMsgParser; NW_LOG(NW_LOG_LEVEL_DEBG, "Received NW_GTPV2C_ULP_API_INITIAL_REQ_IND from gtpv2c stack! %X:%u", pUlpApi->apiInfo.initialReqIndInfo.peerIp, pUlpApi->apiInfo.initialReqIndInfo.peerPort);
NW_LOG(NW_LOG_LEVEL_DEBG, "Received NW_GTPV2C_ULP_API_INITIAL_REQ_IND from gtpv2c stack! %X:%u", pUlpApi->apiInfo.initialReqIndInfo.peerIp, pUlpApi->apiInfo.initialReqIndInfo.peerPort);
rc = nwGtpv2cMsgParserNew(thiz->hGtpv2cStack, NW_GTP_CREATE_SESSION_REQ, nwGtpv2cCreateSessionRequestIeIndication, NULL, &pMsgParser); rc = nwGtpv2cMsgParserNew(thiz->hGtpv2cStack, NW_GTP_CREATE_SESSION_REQ, nwGtpv2cCreateSessionRequestIeIndication, NULL, &pMsgParser);
NW_ASSERT(NW_OK == rc); NW_ASSERT(NW_OK == rc);
if(pUlpApi->apiInfo.initialReqIndInfo.msgType == NW_GTP_CREATE_SESSION_REQ) if(pUlpApi->apiInfo.initialReqIndInfo.msgType == NW_GTP_CREATE_SESSION_REQ) {
{
struct struct {
{ NwU8T causeValue;
NwU8T causeValue; NwU8T spare:5;
NwU8T spare:5; NwU8T pce:1;
NwU8T pce:1; NwU8T bce:1;
NwU8T bce:1; NwU8T cs:1;
NwU8T cs:1; } cause;
} cause;
rc = nwGtpv2cMsgParserAddIe(pMsgParser, NW_GTPV2C_IE_RECOVERY, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_MANDATORY, nwGtpv2cCreateSessionRequestIeIndication, NULL); rc = nwGtpv2cMsgParserAddIe(pMsgParser, NW_GTPV2C_IE_RECOVERY, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_MANDATORY, nwGtpv2cCreateSessionRequestIeIndication, NULL);
NW_ASSERT(NW_OK == rc); NW_ASSERT(NW_OK == rc);
NwU8T offendingIeType, OffendingIeLength; NwU8T offendingIeType, OffendingIeLength;
rc = nwGtpv2cMsgParserRun(pMsgParser, (pUlpApi->hMsg), &offendingIeType, &OffendingIeLength); rc = nwGtpv2cMsgParserRun(pMsgParser, (pUlpApi->hMsg), &offendingIeType, &OffendingIeLength);
if( rc != NW_OK )
{
switch(rc)
{
case NW_GTPV2C_MANDATORY_IE_MISSING:
NW_LOG(NW_LOG_LEVEL_ERRO, "Mandatory IE type '%u' of instance '%u' missing!", offendingIeType, OffendingIeLength);
cause.causeValue = NW_GTPV2C_CAUSE_MANDATORY_IE_MISSING;
break;
default:
NW_LOG(NW_LOG_LEVEL_ERRO, "Unknown message parse error!");
cause.causeValue = 0;
break;
}
} if( rc != NW_OK ) {
else switch(rc) {
{ case NW_GTPV2C_MANDATORY_IE_MISSING:
cause.causeValue = NW_GTPV2C_CAUSE_REQUEST_ACCEPTED; NW_LOG(NW_LOG_LEVEL_ERRO, "Mandatory IE type '%u' of instance '%u' missing!", offendingIeType, OffendingIeLength);
} cause.causeValue = NW_GTPV2C_CAUSE_MANDATORY_IE_MISSING;
break;
/* default:
* Send Message Request to Gtpv2c Stack Instance NW_LOG(NW_LOG_LEVEL_ERRO, "Unknown message parse error!");
*/ cause.causeValue = 0;
ulpReq.apiType = NW_GTPV2C_ULP_API_TRIGGERED_RSP; break;
ulpReq.apiInfo.triggeredRspInfo.hTrxn = pUlpApi->apiInfo.initialReqIndInfo.hTrxn;
rc = nwGtpv2cMsgNew( thiz->hGtpv2cStack,
NW_TRUE,
NW_GTP_CREATE_SESSION_RSP,
0,
nwGtpv2cMsgGetSeqNumber(pUlpApi->hMsg),
&(ulpReq.hMsg));
rc = nwGtpv2cMsgAddIe((ulpReq.hMsg), NW_GTPV2C_IE_CAUSE, 2, 0, (NwU8T*)&cause);
NW_ASSERT(NW_OK == rc);
NW_LOG(NW_LOG_LEVEL_NOTI, "Received NW_GTP_CREATE_SESSION_REQ, Sending NW_GTP_CREATE_SESSION_RSP!");
rc = nwGtpv2cProcessUlpReq(thiz->hGtpv2cStack, &ulpReq);
NW_ASSERT(NW_OK == rc);
} }
rc = nwGtpv2cMsgParserDelete(thiz->hGtpv2cStack, pMsgParser); } else {
NW_ASSERT(NW_OK == rc); cause.causeValue = NW_GTPV2C_CAUSE_REQUEST_ACCEPTED;
rc = nwGtpv2cMsgDelete(thiz->hGtpv2cStack, (pUlpApi->hMsg));
NW_ASSERT(NW_OK == rc);
} }
break;
case NW_GTPV2C_ULP_API_TRIGGERED_RSP_IND: /*
{ * Send Message Request to Gtpv2c Stack Instance
NwGtpv2cUlpApiT ulpReq; */
NwGtpv2cMsgParserT *pMsgParser; ulpReq.apiType = NW_GTPV2C_ULP_API_TRIGGERED_RSP;
NW_LOG(NW_LOG_LEVEL_DEBG, "Received NW_GTPV2C_ULP_API_TRIGGERED_RSP_IND from gtpv2c stack!", pUlpApi->apiInfo.triggeredRspIndInfo, pUlpApi->apiInfo.triggeredRspIndInfo);
rc = nwGtpv2cMsgParserNew(thiz->hGtpv2cStack, NW_GTP_CREATE_SESSION_REQ, nwGtpv2cCreateSessionRequestIeIndication, NULL, &pMsgParser); ulpReq.apiInfo.triggeredRspInfo.hTrxn = pUlpApi->apiInfo.initialReqIndInfo.hTrxn;
NW_ASSERT(NW_OK == rc);
if(pUlpApi->apiInfo.triggeredRspIndInfo.msgType == NW_GTP_CREATE_SESSION_RSP) rc = nwGtpv2cMsgNew( thiz->hGtpv2cStack,
{ NW_TRUE,
rc = nwGtpv2cMsgParserAddIe(pMsgParser, NW_GTPV2C_IE_CAUSE, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_MANDATORY, nwGtpv2cCreateSessionRequestIeIndication, NULL); NW_GTP_CREATE_SESSION_RSP,
NW_ASSERT(NW_OK == rc); 0,
nwGtpv2cMsgGetSeqNumber(pUlpApi->hMsg),
&(ulpReq.hMsg));
NwU8T offendingIeType, OffendingIeLength; rc = nwGtpv2cMsgAddIe((ulpReq.hMsg), NW_GTPV2C_IE_CAUSE, 2, 0, (NwU8T*)&cause);
rc = nwGtpv2cMsgParserRun(pMsgParser, (pUlpApi->hMsg), &offendingIeType, &OffendingIeLength); NW_ASSERT(NW_OK == rc);
if( rc != NW_OK )
{
switch(rc)
{
case NW_GTPV2C_MANDATORY_IE_MISSING:
NW_LOG(NW_LOG_LEVEL_ERRO, "Mandatory IE Missing!");
break;
default:
NW_LOG(NW_LOG_LEVEL_ERRO, "Unknown message parse error!");
break;
} NW_LOG(NW_LOG_LEVEL_NOTI, "Received NW_GTP_CREATE_SESSION_REQ, Sending NW_GTP_CREATE_SESSION_RSP!");
rc = nwGtpv2cProcessUlpReq(thiz->hGtpv2cStack, &ulpReq);
NW_ASSERT(NW_OK == rc);
}
} rc = nwGtpv2cMsgParserDelete(thiz->hGtpv2cStack, pMsgParser);
NW_ASSERT(NW_OK == rc);
/* rc = nwGtpv2cMsgDelete(thiz->hGtpv2cStack, (pUlpApi->hMsg));
* Send Message Request to Gtpv2c Stack Instance NW_ASSERT(NW_OK == rc);
*/
NW_LOG(NW_LOG_LEVEL_NOTI, "Received NW_GTP_CREATE_SESSION_RSP, Sending NW_GTP_CREATE_SESSION_REQ!");
nwGtpv2cUlpCreateSessionRequestToPeer(thiz);
}
rc = nwGtpv2cMsgParserDelete(thiz->hGtpv2cStack, pMsgParser);
NW_ASSERT(NW_OK == rc);
rc = nwGtpv2cMsgDelete(thiz->hGtpv2cStack, (pUlpApi->hMsg));
NW_ASSERT(NW_OK == rc);
}
break;
case NW_GTPV2C_ULP_API_RSP_FAILURE_IND:
{
NW_LOG(NW_LOG_LEVEL_ERRO, "Received NW_GTPV2C_ULP_API_RSP_FAILURE from gtpv2c stack for transaction '%x'!", thiz);
}
break;
default:
NW_LOG(NW_LOG_LEVEL_WARN, "Received undefined UlpApi from gtpv2c stack!");
} }
break;
case NW_GTPV2C_ULP_API_TRIGGERED_RSP_IND: {
NwGtpv2cUlpApiT ulpReq;
NwGtpv2cMsgParserT *pMsgParser;
NW_LOG(NW_LOG_LEVEL_DEBG, "Received NW_GTPV2C_ULP_API_TRIGGERED_RSP_IND from gtpv2c stack!", pUlpApi->apiInfo.triggeredRspIndInfo, pUlpApi->apiInfo.triggeredRspIndInfo);
rc = nwGtpv2cMsgParserNew(thiz->hGtpv2cStack, NW_GTP_CREATE_SESSION_REQ, nwGtpv2cCreateSessionRequestIeIndication, NULL, &pMsgParser);
NW_ASSERT(NW_OK == rc);
if(pUlpApi->apiInfo.triggeredRspIndInfo.msgType == NW_GTP_CREATE_SESSION_RSP) {
rc = nwGtpv2cMsgParserAddIe(pMsgParser, NW_GTPV2C_IE_CAUSE, NW_GTPV2C_IE_INSTANCE_ZERO, NW_GTPV2C_IE_PRESENCE_MANDATORY, nwGtpv2cCreateSessionRequestIeIndication, NULL);
NW_ASSERT(NW_OK == rc);
NwU8T offendingIeType, OffendingIeLength;
rc = nwGtpv2cMsgParserRun(pMsgParser, (pUlpApi->hMsg), &offendingIeType, &OffendingIeLength);
if( rc != NW_OK ) {
switch(rc) {
case NW_GTPV2C_MANDATORY_IE_MISSING:
NW_LOG(NW_LOG_LEVEL_ERRO, "Mandatory IE Missing!");
break;
default:
NW_LOG(NW_LOG_LEVEL_ERRO, "Unknown message parse error!");
break;
}
}
/*
* Send Message Request to Gtpv2c Stack Instance
*/
NW_LOG(NW_LOG_LEVEL_NOTI, "Received NW_GTP_CREATE_SESSION_RSP, Sending NW_GTP_CREATE_SESSION_REQ!");
nwGtpv2cUlpCreateSessionRequestToPeer(thiz);
}
rc = nwGtpv2cMsgParserDelete(thiz->hGtpv2cStack, pMsgParser);
NW_ASSERT(NW_OK == rc);
rc = nwGtpv2cMsgDelete(thiz->hGtpv2cStack, (pUlpApi->hMsg));
NW_ASSERT(NW_OK == rc);
}
break;
case NW_GTPV2C_ULP_API_RSP_FAILURE_IND: {
NW_LOG(NW_LOG_LEVEL_ERRO, "Received NW_GTPV2C_ULP_API_RSP_FAILURE from gtpv2c stack for transaction '%x'!", thiz);
}
break;
default:
NW_LOG(NW_LOG_LEVEL_WARN, "Received undefined UlpApi from gtpv2c stack!");
}
return NW_OK; return NW_OK;
} }
@@ -19,8 +19,7 @@
#ifndef __NW_MINI_ULP_H__ #ifndef __NW_MINI_ULP_H__
#define __NW_MINI_ULP_H__ #define __NW_MINI_ULP_H__
typedef struct typedef struct {
{
NwU8T peerIpStr[16]; NwU8T peerIpStr[16];
NwU32T restartCounter; NwU32T restartCounter;
NwGtpv2cStackHandleT hGtpv2cStack; NwGtpv2cStackHandleT hGtpv2cStack;
@@ -41,7 +40,7 @@ nwGtpv2cUlpCreateSessionRequestToPeer(NwGtpv2cNodeUlpT* thiz);
NwRcT NwRcT
nwGtpv2cUlpProcessStackReqCallback (NwGtpv2cUlpHandleT hUlp, nwGtpv2cUlpProcessStackReqCallback (NwGtpv2cUlpHandleT hUlp,
NwGtpv2cUlpApiT *pUlpApi); NwGtpv2cUlpApiT *pUlpApi);
#ifdef __cplusplus #ifdef __cplusplus
} }
@@ -54,20 +54,16 @@ int main(int argc, char* argv[])
NwGtpv2cTimerMgrEntityT tmrMgr; NwGtpv2cTimerMgrEntityT tmrMgr;
NwGtpv2cLogMgrEntityT logMgr; NwGtpv2cLogMgrEntityT logMgr;
if(argc != 3) if(argc != 3) {
{
printf("Usage: %s <local-ip> <peer-ip>\n", argv[0]); printf("Usage: %s <local-ip> <peer-ip>\n", argv[0]);
exit(0); exit(0);
} }
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)
@@ -102,11 +98,11 @@ 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);
} }
NW_LOG(NW_LOG_LEVEL_INFO, "Gtpv2c Stack Handle '%X' Creation Successful!", hGtpv2cStack); NW_LOG(NW_LOG_LEVEL_INFO, "Gtpv2c Stack Handle '%X' Creation Successful!", hGtpv2cStack);
rc = nwGtpv2cSetLogLevel(hGtpv2cStack, logLevel); rc = nwGtpv2cSetLogLevel(hGtpv2cStack, logLevel);
@@ -172,12 +168,10 @@ 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);
} } else {
else
{
NW_LOG(NW_LOG_LEVEL_INFO, "Gtpv2c Stack Handle '%X' Finalize Successful!", hGtpv2cStack); NW_LOG(NW_LOG_LEVEL_INFO, "Gtpv2c Stack Handle '%X' Finalize Successful!", hGtpv2cStack);
} }
+332 -319
View File
@@ -56,381 +56,394 @@ int mme_app_request_authentication_info(const mme_app_imsi_t imsi,
const plmn_t *plmn, const plmn_t *plmn,
const uint8_t *auts) const uint8_t *auts)
{ {
s6a_auth_info_req_t *auth_info_req = NULL; s6a_auth_info_req_t *auth_info_req = NULL;
MessageDef *message_p = NULL; MessageDef *message_p = NULL;
DevAssert(plmn != NULL); DevAssert(plmn != NULL);
message_p = itti_alloc_new_message(TASK_MME_APP, S6A_AUTH_INFO_REQ); message_p = itti_alloc_new_message(TASK_MME_APP, S6A_AUTH_INFO_REQ);
auth_info_req = &message_p->ittiMsg.s6a_auth_info_req; auth_info_req = &message_p->ittiMsg.s6a_auth_info_req;
memset(auth_info_req, 0, sizeof(*auth_info_req)); memset(auth_info_req, 0, sizeof(*auth_info_req));
auth_info_req->imsi_length = MME_APP_IMSI_TO_STRING(imsi, auth_info_req->imsi); auth_info_req->imsi_length = MME_APP_IMSI_TO_STRING(imsi, auth_info_req->imsi);
memcpy(&auth_info_req->visited_plmn, plmn, sizeof(plmn_t)); memcpy(&auth_info_req->visited_plmn, plmn, sizeof(plmn_t));
MME_APP_DEBUG("%s visited_plmn MCC %X%X%X MNC %X%X%X\n", MME_APP_DEBUG("%s visited_plmn MCC %X%X%X MNC %X%X%X\n",
__FUNCTION__, __FUNCTION__,
auth_info_req->visited_plmn.MCCdigit1, auth_info_req->visited_plmn.MCCdigit1,
auth_info_req->visited_plmn.MCCdigit2, auth_info_req->visited_plmn.MCCdigit2,
auth_info_req->visited_plmn.MCCdigit3, auth_info_req->visited_plmn.MCCdigit3,
auth_info_req->visited_plmn.MNCdigit1, auth_info_req->visited_plmn.MNCdigit1,
auth_info_req->visited_plmn.MNCdigit2, auth_info_req->visited_plmn.MNCdigit2,
auth_info_req->visited_plmn.MNCdigit3); auth_info_req->visited_plmn.MNCdigit3);
uint8_t *ptr = (uint8_t *)&auth_info_req->visited_plmn; uint8_t *ptr = (uint8_t *)&auth_info_req->visited_plmn;
MME_APP_DEBUG("%s visited_plmn %02X%02X%02X\n", MME_APP_DEBUG("%s visited_plmn %02X%02X%02X\n",
__FUNCTION__, __FUNCTION__,
ptr[0], ptr[0],
ptr[1], ptr[1],
ptr[2]); ptr[2]);
auth_info_req->nb_of_vectors = nb_of_vectors; auth_info_req->nb_of_vectors = nb_of_vectors;
if (auts != NULL) {
auth_info_req->re_synchronization = 1;
memcpy(auth_info_req->auts, auts, sizeof(auth_info_req->auts));
} else {
auth_info_req->re_synchronization = 0;
memset(auth_info_req->auts, 0, sizeof(auth_info_req->auts));
}
return itti_send_msg_to_task(TASK_S6A, INSTANCE_DEFAULT, message_p); if (auts != NULL) {
auth_info_req->re_synchronization = 1;
memcpy(auth_info_req->auts, auts, sizeof(auth_info_req->auts));
} else {
auth_info_req->re_synchronization = 0;
memset(auth_info_req->auts, 0, sizeof(auth_info_req->auts));
}
return itti_send_msg_to_task(TASK_S6A, INSTANCE_DEFAULT, message_p);
} }
int mme_app_handle_nas_auth_resp(const nas_auth_resp_t * const nas_auth_resp_pP) int mme_app_handle_nas_auth_resp(const nas_auth_resp_t * const nas_auth_resp_pP)
{ {
struct ue_context_s *ue_context = NULL; struct ue_context_s *ue_context = NULL;
uint64_t imsi = 0; uint64_t imsi = 0;
DevAssert(nas_auth_resp_pP != NULL); DevAssert(nas_auth_resp_pP != NULL);
MME_APP_STRING_TO_IMSI((char *)nas_auth_resp_pP->imsi, &imsi); MME_APP_STRING_TO_IMSI((char *)nas_auth_resp_pP->imsi, &imsi);
MME_APP_DEBUG("Handling imsi %"IMSI_FORMAT"\n", imsi); MME_APP_DEBUG("Handling imsi %"IMSI_FORMAT"\n", imsi);
if ((ue_context = mme_ue_context_exists_imsi(&mme_app_desc.mme_ue_contexts, if ((ue_context = mme_ue_context_exists_imsi(&mme_app_desc.mme_ue_contexts,
imsi)) == NULL) { imsi)) == NULL) {
MME_APP_ERROR("That's embarrassing as we don't know this IMSI\n"); MME_APP_ERROR("That's embarrassing as we don't know this IMSI\n");
AssertFatal(0, "That's embarrassing as we don't know this IMSI\n"); AssertFatal(0, "That's embarrassing as we don't know this IMSI\n");
return -1;
}
/* Consider the UE authenticated */
ue_context->imsi_auth = IMSI_AUTHENTICATED;
/* TODO: Get keys... */
/* Now generate S6A ULR */
{
MessageDef *message_p = NULL;
s6a_update_location_req_t *s6a_ulr = NULL;
message_p = itti_alloc_new_message(TASK_MME_APP, S6A_UPDATE_LOCATION_REQ);
if (message_p == NULL) {
return -1;
}
s6a_ulr = &message_p->ittiMsg.s6a_update_location_req;
memcpy(s6a_ulr->imsi, nas_auth_resp_pP->imsi, 16);
s6a_ulr->initial_attach = INITIAL_ATTACH;
s6a_ulr->rat_type = RAT_EUTRAN;
/* Check if we already have UE data */
s6a_ulr->skip_subscriber_data = 0;
return itti_send_msg_to_task(TASK_S6A, INSTANCE_DEFAULT, message_p);
}
return -1; return -1;
}
/* Consider the UE authenticated */
ue_context->imsi_auth = IMSI_AUTHENTICATED;
/* TODO: Get keys... */
/* Now generate S6A ULR */
{
MessageDef *message_p = NULL;
s6a_update_location_req_t *s6a_ulr = NULL;
message_p = itti_alloc_new_message(TASK_MME_APP, S6A_UPDATE_LOCATION_REQ);
if (message_p == NULL) {
return -1;
}
s6a_ulr = &message_p->ittiMsg.s6a_update_location_req;
memcpy(s6a_ulr->imsi, nas_auth_resp_pP->imsi, 16);
s6a_ulr->initial_attach = INITIAL_ATTACH;
s6a_ulr->rat_type = RAT_EUTRAN;
/* Check if we already have UE data */
s6a_ulr->skip_subscriber_data = 0;
return itti_send_msg_to_task(TASK_S6A, INSTANCE_DEFAULT, message_p);
}
return -1;
} }
int int
mme_app_handle_authentication_info_answer( mme_app_handle_authentication_info_answer(
const s6a_auth_info_ans_t * const s6a_auth_info_ans_pP) const s6a_auth_info_ans_t * const s6a_auth_info_ans_pP)
{ {
struct ue_context_s *ue_context; struct ue_context_s *ue_context;
uint64_t imsi; uint64_t imsi;
DevAssert(s6a_auth_info_ans_pP != NULL); DevAssert(s6a_auth_info_ans_pP != NULL);
MME_APP_STRING_TO_IMSI((char *)s6a_auth_info_ans_pP->imsi, &imsi); MME_APP_STRING_TO_IMSI((char *)s6a_auth_info_ans_pP->imsi, &imsi);
MME_APP_DEBUG("Handling imsi %"IMSI_FORMAT"\n", imsi); MME_APP_DEBUG("Handling imsi %"IMSI_FORMAT"\n", imsi);
if ((ue_context = mme_ue_context_exists_imsi(&mme_app_desc.mme_ue_contexts, if ((ue_context = mme_ue_context_exists_imsi(&mme_app_desc.mme_ue_contexts,
imsi)) == NULL) { imsi)) == NULL) {
MME_APP_ERROR("That's embarrassing as we don't know this IMSI\n"); MME_APP_ERROR("That's embarrassing as we don't know this IMSI\n");
return -1; return -1;
} }
if ((s6a_auth_info_ans_pP->result.present == S6A_RESULT_BASE) && if ((s6a_auth_info_ans_pP->result.present == S6A_RESULT_BASE) &&
(s6a_auth_info_ans_pP->result.choice.base == DIAMETER_SUCCESS)) { (s6a_auth_info_ans_pP->result.choice.base == DIAMETER_SUCCESS)) {
/* S6A procedure has succeeded. /* S6A procedure has succeeded.
* We have to request UE authentication. * We have to request UE authentication.
*/ */
/* Check that list is not empty and contain only one element */ /* Check that list is not empty and contain only one element */
DevCheck(s6a_auth_info_ans_pP->auth_info.nb_of_vectors == 1, DevCheck(s6a_auth_info_ans_pP->auth_info.nb_of_vectors == 1,
s6a_auth_info_ans_pP->auth_info.nb_of_vectors, 1, 0); s6a_auth_info_ans_pP->auth_info.nb_of_vectors, 1, 0);
if (ue_context->vector_list == NULL) { if (ue_context->vector_list == NULL) {
ue_context->vector_list = malloc(sizeof(eutran_vector_t)); ue_context->vector_list = malloc(sizeof(eutran_vector_t));
DevAssert(ue_context->vector_list != NULL); DevAssert(ue_context->vector_list != NULL);
} else {
/* Some vector already exist */
ue_context->vector_list = realloc(
ue_context->vector_list,
(ue_context->nb_of_vectors + s6a_auth_info_ans_pP->auth_info.nb_of_vectors) * sizeof(eutran_vector_t));
DevAssert(ue_context->vector_list != NULL);
}
memcpy(&ue_context->vector_list[ue_context->nb_of_vectors],
&s6a_auth_info_ans_pP->auth_info.eutran_vector, sizeof(eutran_vector_t));
ue_context->vector_in_use = &ue_context->vector_list[ue_context->nb_of_vectors];
ue_context->nb_of_vectors += s6a_auth_info_ans_pP->auth_info.nb_of_vectors;
MME_APP_DEBUG("INFORMING NAS ABOUT AUTH RESP SUCCESS got %u vector(s)\n",
s6a_auth_info_ans_pP->auth_info.nb_of_vectors);
mme_app_itti_auth_rsp(ue_context->ue_id,
1,
&s6a_auth_info_ans_pP->auth_info.eutran_vector);
} else { } else {
MME_APP_ERROR("INFORMING NAS ABOUT AUTH RESP ERROR CODE\n"); /* Some vector already exist */
/* Inform NAS layer with the right failure */ ue_context->vector_list = realloc(
if (s6a_auth_info_ans_pP->result.present == S6A_RESULT_BASE) { ue_context->vector_list,
mme_app_itti_auth_fail(ue_context->ue_id, s6a_error_2_nas_cause( (ue_context->nb_of_vectors + s6a_auth_info_ans_pP->auth_info.nb_of_vectors) * sizeof(eutran_vector_t));
s6a_auth_info_ans_pP->result.choice.base, 0));
} else { DevAssert(ue_context->vector_list != NULL);
mme_app_itti_auth_fail(ue_context->ue_id, s6a_error_2_nas_cause(
s6a_auth_info_ans_pP->result.choice.experimental, 1));
}
} }
return 0; memcpy(&ue_context->vector_list[ue_context->nb_of_vectors],
&s6a_auth_info_ans_pP->auth_info.eutran_vector, sizeof(eutran_vector_t));
ue_context->vector_in_use = &ue_context->vector_list[ue_context->nb_of_vectors];
ue_context->nb_of_vectors += s6a_auth_info_ans_pP->auth_info.nb_of_vectors;
MME_APP_DEBUG("INFORMING NAS ABOUT AUTH RESP SUCCESS got %u vector(s)\n",
s6a_auth_info_ans_pP->auth_info.nb_of_vectors);
mme_app_itti_auth_rsp(ue_context->ue_id,
1,
&s6a_auth_info_ans_pP->auth_info.eutran_vector);
} else {
MME_APP_ERROR("INFORMING NAS ABOUT AUTH RESP ERROR CODE\n");
/* Inform NAS layer with the right failure */
if (s6a_auth_info_ans_pP->result.present == S6A_RESULT_BASE) {
mme_app_itti_auth_fail(ue_context->ue_id, s6a_error_2_nas_cause(
s6a_auth_info_ans_pP->result.choice.base, 0));
} else {
mme_app_itti_auth_fail(ue_context->ue_id, s6a_error_2_nas_cause(
s6a_auth_info_ans_pP->result.choice.experimental, 1));
}
}
return 0;
} }
#if defined(DISABLE_USE_NAS) #if defined(DISABLE_USE_NAS)
int mme_app_handle_attach_req(nas_attach_req_t *attach_req_p) int mme_app_handle_attach_req(nas_attach_req_t *attach_req_p)
{ {
/* An attach request has been received from NAS layer. /* An attach request has been received from NAS layer.
* If the UE authentication vectors for the UE are known within MME then the * If the UE authentication vectors for the UE are known within MME then the
* authentication procedure should be triggered only if the request is an * authentication procedure should be triggered only if the request is an
* initial attach, otherwise an update location should be sent to the HSS * initial attach, otherwise an update location should be sent to the HSS
* and default bearer should be established for the provided APN. * and default bearer should be established for the provided APN.
* In case of initial attach procedure, the default APN retrieved from the * In case of initial attach procedure, the default APN retrieved from the
* HSS will be used to establish the default bearer within EPC. * HSS will be used to establish the default bearer within EPC.
* The default APN is the one that matches the context-identifier * The default APN is the one that matches the context-identifier
*/
struct ue_context_s *ue_context;
uint64_t imsi = 0;
DevAssert(attach_req_p != NULL);
MME_APP_STRING_TO_IMSI((char *)attach_req_p->imsi, &imsi);
MME_APP_DEBUG("Handling imsi %"IMSI_FORMAT"\n", imsi);
ue_context = mme_ue_context_exists_imsi(&mme_app_desc.mme_ue_contexts, imsi);
if (ue_context == NULL) {
/* The MME doesn't know this IMSI.
* Insert the UE to the list of known equipements and
* Retrieve the authentication vector from HSS.
*/ */
struct ue_context_s *ue_context; MME_APP_DEBUG("UE context doesn't exist -> create one\n");
uint64_t imsi = 0;
DevAssert(attach_req_p != NULL); if ((ue_context = mme_create_new_ue_context()) == NULL) {
/* Error during ue context malloc */
/* TODO */
DevMessage("mme_create_new_ue_context");
return -1;
}
MME_APP_STRING_TO_IMSI((char *)attach_req_p->imsi, &imsi); ue_context->imsi = imsi;
MME_APP_DEBUG("Handling imsi %"IMSI_FORMAT"\n", imsi); ue_context->eNB_ue_s1ap_id = attach_req_p->transparent.eNB_ue_s1ap_id;
ue_context->mme_ue_s1ap_id = attach_req_p->transparent.mme_ue_s1ap_id;
ue_context->ue_id = attach_req_p->transparent.mme_ue_s1ap_id;
ue_context = mme_ue_context_exists_imsi(&mme_app_desc.mme_ue_contexts, imsi); // STAILQ_INIT(&ue_context->vector_list);
if (ue_context == NULL) { DevAssert(mme_insert_ue_context(&mme_app_desc.mme_ue_contexts, ue_context) == 0);
/* The MME doesn't know this IMSI. goto request_auth;
* Insert the UE to the list of known equipements and } else {
* Retrieve the authentication vector from HSS. /* MME knows this IMSI, check if UE is authenticated and authentication
*/ * vectors are known.
MME_APP_DEBUG("UE context doesn't exist -> create one\n"); */
if ((ue_context = mme_create_new_ue_context()) == NULL) { MME_APP_DEBUG("UE context already exists, use it\n");
/* Error during ue context malloc */
/* TODO */
DevMessage("mme_create_new_ue_context");
return -1;
}
ue_context->imsi = imsi;
ue_context->eNB_ue_s1ap_id = attach_req_p->transparent.eNB_ue_s1ap_id; /* Update mme ue s1ap id */
ue_context->mme_ue_s1ap_id = attach_req_p->transparent.mme_ue_s1ap_id; ue_context->mme_ue_s1ap_id = attach_req_p->transparent.mme_ue_s1ap_id;
ue_context->ue_id = attach_req_p->transparent.mme_ue_s1ap_id;
// STAILQ_INIT(&ue_context->vector_list); if ((ue_context->imsi_auth == IMSI_AUTHENTICATED) &&
DevAssert(mme_insert_ue_context(&mme_app_desc.mme_ue_contexts, ue_context) == 0); (attach_req_p->initial != INITIAL_REQUEST)) {
goto request_auth; /* We have to send an update location request to the HSS */
MME_APP_DEBUG("UE is authenticated\n");
} else { } else {
/* MME knows this IMSI, check if UE is authenticated and authentication MME_APP_DEBUG("UE is not authenticated\n");
* vectors are known.
*/
MME_APP_DEBUG("UE context already exists, use it\n");
/* Update mme ue s1ap id */ /* UE is not authenticated or an initial request */
ue_context->mme_ue_s1ap_id = attach_req_p->transparent.mme_ue_s1ap_id; // if (STAILQ_EMPTY(&ue_context->vector_list))
if (ue_context->nb_of_vectors == 0)
if ((ue_context->imsi_auth == IMSI_AUTHENTICATED) &&
(attach_req_p->initial != INITIAL_REQUEST)) {
/* We have to send an update location request to the HSS */
MME_APP_DEBUG("UE is authenticated\n");
} else {
MME_APP_DEBUG("UE is not authenticated\n");
/* UE is not authenticated or an initial request */
// if (STAILQ_EMPTY(&ue_context->vector_list))
if (ue_context->nb_of_vectors == 0)
request_auth: { request_auth: {
/* We have no vector for this UE, send an authentication request
* to the HSS.
*/
AssertFatal(0, "Hardcoded MCC/MNC");
plmn_t plmn = {
.MCCdigit2 = 0,
.MCCdigit1 = 8,
.MCCdigit3 = 2,
.MNCdigit1 = 0,
.MNCdigit2 = 4,
.MNCdigit3 = 3,
};
memcpy(&ue_context->e_utran_cgi, &attach_req_p->transparent.e_utran_cgi,
sizeof(cgi_t));
/* Acquire the current time */
time(&ue_context->cell_age);
/* Some random values for GUTI */
ue_context->guti.m_tmsi = 0x24568956;
ue_context->guti.gummei.MMEcode = 0x01;
ue_context->guti.gummei.MMEgid = 0x5691;
memcpy(&ue_context->guti.gummei.plmn, &plmn, sizeof(plmn_t));
MME_APP_DEBUG("and we have no auth. vector for it, request"
" authentication information\n");
// mme_app_dump_ue_contexts();
mme_app_request_authentication_info(imsi, 1, &plmn, NULL);
} else {
nas_auth_req_t *nas_auth_req_p;
MessageDef *message_p;
/* We have a vector... USE it */
MME_APP_DEBUG("but we have an auth. vector for it, request"
" authentication from NAS\n");
message_p = itti_alloc_new_message(TASK_MME_APP, NAS_AUTHENTICATION_PARAM_FAIL);
nas_auth_req_p = &message_p->ittiMsg.nas_auth_req;
MME_APP_IMSI_TO_STRING(imsi, nas_auth_req_p->imsi);
nas_auth_req_p->failure = NAS_FAILURE_OK;
return itti_send_msg_to_task(TASK_NAS_MME, INSTANCE_DEFAULT, message_p);
}
}
}
return 0;
}
#else
void
mme_app_handle_nas_auth_param_req(
const nas_auth_param_req_t * const nas_auth_param_req_pP)
{
plmn_t *visited_plmn = NULL;
struct ue_context_s *ue_context = NULL;
uint64_t imsi = 0;
int mnc_length = 0;
plmn_t visited_plmn_from_req = {
.MCCdigit3 = 0,
.MCCdigit2 = 0,
.MCCdigit1 = 0,
.MNCdigit1 = 0,
.MNCdigit2 = 0,
.MNCdigit3 = 0,
};
DevAssert(nas_auth_param_req_pP != NULL);
visited_plmn = &visited_plmn_from_req;
visited_plmn_from_req.MCCdigit1 = nas_auth_param_req_pP->imsi[0];
visited_plmn_from_req.MCCdigit2 = nas_auth_param_req_pP->imsi[1];
visited_plmn_from_req.MCCdigit3 = nas_auth_param_req_pP->imsi[2];
mnc_length = find_mnc_length(nas_auth_param_req_pP->imsi[0],
nas_auth_param_req_pP->imsi[1],
nas_auth_param_req_pP->imsi[2],
nas_auth_param_req_pP->imsi[3],
nas_auth_param_req_pP->imsi[4],
nas_auth_param_req_pP->imsi[5]
);
if (mnc_length == 2) {
visited_plmn_from_req.MNCdigit1 = nas_auth_param_req_pP->imsi[3];
visited_plmn_from_req.MNCdigit2 = nas_auth_param_req_pP->imsi[4];
visited_plmn_from_req.MNCdigit3 = 15;
} else if (mnc_length == 3) {
visited_plmn_from_req.MNCdigit1 = nas_auth_param_req_pP->imsi[3];
visited_plmn_from_req.MNCdigit2 = nas_auth_param_req_pP->imsi[4];
visited_plmn_from_req.MNCdigit3 = nas_auth_param_req_pP->imsi[5];
} else {
AssertFatal(0, "MNC Not found (mcc_mnc_list)");
}
if (mnc_length == 3) {
MME_APP_DEBUG("%s visited_plmn_from_req %1d%1d%1d.%1d%1d%1d\n",
__FUNCTION__,
visited_plmn_from_req.MCCdigit1,
visited_plmn_from_req.MCCdigit2,
visited_plmn_from_req.MCCdigit3,
visited_plmn_from_req.MNCdigit1,
visited_plmn_from_req.MNCdigit2,
visited_plmn_from_req.MNCdigit3);
} else {
MME_APP_DEBUG("%s visited_plmn_from_req %1d%1d%1d.%1d%1d\n",
__FUNCTION__,
visited_plmn_from_req.MCCdigit1,
visited_plmn_from_req.MCCdigit2,
visited_plmn_from_req.MCCdigit3,
visited_plmn_from_req.MNCdigit1,
visited_plmn_from_req.MNCdigit2);
}
MME_APP_STRING_TO_IMSI(nas_auth_param_req_pP->imsi, &imsi);
MME_APP_DEBUG("%s Handling imsi %"IMSI_FORMAT"\n", __FUNCTION__, imsi);
MME_APP_DEBUG("%s Handling imsi from req %s (mnc length %d)\n",
__FUNCTION__,
nas_auth_param_req_pP->imsi,
mnc_length);
/* Fetch the context associated with this IMSI */
ue_context = mme_ue_context_exists_imsi(&mme_app_desc.mme_ue_contexts, imsi);
if (ue_context == NULL) {
/* Currently no context available -> trigger an authentication request
* to the HSS.
*/
MME_APP_DEBUG("UE context search by IMSI failed, try by ue id\n");
ue_context = mme_ue_context_exists_nas_ue_id(&mme_app_desc.mme_ue_contexts, nas_auth_param_req_pP->ue_id);
if (ue_context == NULL) {
// should have been created by initial ue message
MME_APP_ERROR("UE context doesn't exist -> create one\n");
if ((ue_context = mme_create_new_ue_context()) == NULL) {
/* Error during ue context malloc */
/* TODO */
DevMessage("mme_create_new_ue_context");
return;
}
ue_context->ue_id = nas_auth_param_req_pP->ue_id;
ue_context->mme_ue_s1ap_id = nas_auth_param_req_pP->ue_id;
DevAssert(mme_insert_ue_context(&mme_app_desc.mme_ue_contexts, ue_context) == 0);
}
ue_context->imsi = imsi;
/* We have no vector for this UE, send an authentication request /* We have no vector for this UE, send an authentication request
* to the HSS. * to the HSS.
*/ */
AssertFatal(0, "Hardcoded MCC/MNC");
plmn_t plmn = {
.MCCdigit2 = 0,
.MCCdigit1 = 8,
.MCCdigit3 = 2,
.MNCdigit1 = 0,
.MNCdigit2 = 4,
.MNCdigit3 = 3,
};
memcpy(&ue_context->e_utran_cgi, &attach_req_p->transparent.e_utran_cgi,
sizeof(cgi_t));
/* Acquire the current time */ /* Acquire the current time */
time(&ue_context->cell_age); time(&ue_context->cell_age);
memcpy(&ue_context->guti.gummei.plmn, visited_plmn, sizeof(plmn_t)); /* Some random values for GUTI */
ue_context->guti.m_tmsi = 0x24568956;
ue_context->guti.gummei.MMEcode = 0x01;
ue_context->guti.gummei.MMEgid = 0x5691;
memcpy(&ue_context->guti.gummei.plmn, &plmn, sizeof(plmn_t));
MME_APP_DEBUG("and we have no auth. vector for it, request" MME_APP_DEBUG("and we have no auth. vector for it, request"
" authentication information\n"); " authentication information\n");
mme_app_request_authentication_info(imsi, 1, visited_plmn, NULL); // mme_app_dump_ue_contexts();
} else { mme_app_request_authentication_info(imsi, 1, &plmn, NULL);
memcpy(&ue_context->guti.gummei.plmn, visited_plmn, sizeof(plmn_t)); } else {
nas_auth_req_t *nas_auth_req_p;
MessageDef *message_p;
/* We have a vector... USE it */
MME_APP_DEBUG("but we have an auth. vector for it, request"
" authentication from NAS\n");
message_p = itti_alloc_new_message(TASK_MME_APP, NAS_AUTHENTICATION_PARAM_FAIL);
mme_app_request_authentication_info(imsi, 1, visited_plmn, nas_auth_param_req_pP->auts); nas_auth_req_p = &message_p->ittiMsg.nas_auth_req;
MME_APP_IMSI_TO_STRING(imsi, nas_auth_req_p->imsi);
nas_auth_req_p->failure = NAS_FAILURE_OK;
return itti_send_msg_to_task(TASK_NAS_MME, INSTANCE_DEFAULT, message_p);
}
} }
}
return 0;
}
#else
void
mme_app_handle_nas_auth_param_req(
const nas_auth_param_req_t * const nas_auth_param_req_pP)
{
plmn_t *visited_plmn = NULL;
struct ue_context_s *ue_context = NULL;
uint64_t imsi = 0;
int mnc_length = 0;
plmn_t visited_plmn_from_req = {
.MCCdigit3 = 0,
.MCCdigit2 = 0,
.MCCdigit1 = 0,
.MNCdigit1 = 0,
.MNCdigit2 = 0,
.MNCdigit3 = 0,
};
DevAssert(nas_auth_param_req_pP != NULL);
visited_plmn = &visited_plmn_from_req;
visited_plmn_from_req.MCCdigit1 = nas_auth_param_req_pP->imsi[0];
visited_plmn_from_req.MCCdigit2 = nas_auth_param_req_pP->imsi[1];
visited_plmn_from_req.MCCdigit3 = nas_auth_param_req_pP->imsi[2];
mnc_length = find_mnc_length(nas_auth_param_req_pP->imsi[0],
nas_auth_param_req_pP->imsi[1],
nas_auth_param_req_pP->imsi[2],
nas_auth_param_req_pP->imsi[3],
nas_auth_param_req_pP->imsi[4],
nas_auth_param_req_pP->imsi[5]
);
if (mnc_length == 2) {
visited_plmn_from_req.MNCdigit1 = nas_auth_param_req_pP->imsi[3];
visited_plmn_from_req.MNCdigit2 = nas_auth_param_req_pP->imsi[4];
visited_plmn_from_req.MNCdigit3 = 15;
} else if (mnc_length == 3) {
visited_plmn_from_req.MNCdigit1 = nas_auth_param_req_pP->imsi[3];
visited_plmn_from_req.MNCdigit2 = nas_auth_param_req_pP->imsi[4];
visited_plmn_from_req.MNCdigit3 = nas_auth_param_req_pP->imsi[5];
} else {
AssertFatal(0, "MNC Not found (mcc_mnc_list)");
}
if (mnc_length == 3) {
MME_APP_DEBUG("%s visited_plmn_from_req %1d%1d%1d.%1d%1d%1d\n",
__FUNCTION__,
visited_plmn_from_req.MCCdigit1,
visited_plmn_from_req.MCCdigit2,
visited_plmn_from_req.MCCdigit3,
visited_plmn_from_req.MNCdigit1,
visited_plmn_from_req.MNCdigit2,
visited_plmn_from_req.MNCdigit3);
} else {
MME_APP_DEBUG("%s visited_plmn_from_req %1d%1d%1d.%1d%1d\n",
__FUNCTION__,
visited_plmn_from_req.MCCdigit1,
visited_plmn_from_req.MCCdigit2,
visited_plmn_from_req.MCCdigit3,
visited_plmn_from_req.MNCdigit1,
visited_plmn_from_req.MNCdigit2);
}
MME_APP_STRING_TO_IMSI(nas_auth_param_req_pP->imsi, &imsi);
MME_APP_DEBUG("%s Handling imsi %"IMSI_FORMAT"\n", __FUNCTION__, imsi);
MME_APP_DEBUG("%s Handling imsi from req %s (mnc length %d)\n",
__FUNCTION__,
nas_auth_param_req_pP->imsi,
mnc_length);
/* Fetch the context associated with this IMSI */
ue_context = mme_ue_context_exists_imsi(&mme_app_desc.mme_ue_contexts, imsi);
if (ue_context == NULL) {
/* Currently no context available -> trigger an authentication request
* to the HSS.
*/
MME_APP_DEBUG("UE context search by IMSI failed, try by ue id\n");
ue_context = mme_ue_context_exists_nas_ue_id(&mme_app_desc.mme_ue_contexts, nas_auth_param_req_pP->ue_id);
if (ue_context == NULL) {
// should have been created by initial ue message
MME_APP_ERROR("UE context doesn't exist -> create one\n");
if ((ue_context = mme_create_new_ue_context()) == NULL) {
/* Error during ue context malloc */
/* TODO */
DevMessage("mme_create_new_ue_context");
return;
}
ue_context->ue_id = nas_auth_param_req_pP->ue_id;
ue_context->mme_ue_s1ap_id = nas_auth_param_req_pP->ue_id;
DevAssert(mme_insert_ue_context(&mme_app_desc.mme_ue_contexts, ue_context) == 0);
}
ue_context->imsi = imsi;
/* We have no vector for this UE, send an authentication request
* to the HSS.
*/
/* Acquire the current time */
time(&ue_context->cell_age);
memcpy(&ue_context->guti.gummei.plmn, visited_plmn, sizeof(plmn_t));
MME_APP_DEBUG("and we have no auth. vector for it, request"
" authentication information\n");
mme_app_request_authentication_info(imsi, 1, visited_plmn, NULL);
} else {
memcpy(&ue_context->guti.gummei.plmn, visited_plmn, sizeof(plmn_t));
mme_app_request_authentication_info(imsi, 1, visited_plmn, nas_auth_param_req_pP->auts);
}
} }
#endif #endif
+414 -382
View File
@@ -53,7 +53,7 @@
int int
mme_app_send_s11_create_session_req( mme_app_send_s11_create_session_req(
struct ue_context_s * const ue_context_pP) struct ue_context_s * const ue_context_pP)
{ {
uint8_t i = 0; uint8_t i = 0;
task_id_t to_task = TASK_UNKNOWN; task_id_t to_task = TASK_UNKNOWN;
@@ -76,10 +76,10 @@ mme_app_send_s11_create_session_req(
MME_APP_DEBUG("Handling imsi %"IMSI_FORMAT"\n", ue_context_pP->imsi); MME_APP_DEBUG("Handling imsi %"IMSI_FORMAT"\n", ue_context_pP->imsi);
if (ue_context_pP->sub_status != SS_SERVICE_GRANTED) { if (ue_context_pP->sub_status != SS_SERVICE_GRANTED) {
/* HSS rejected the bearer creation or roaming is not allowed for this /* HSS rejected the bearer creation or roaming is not allowed for this
* UE. This result will trigger an ESM Failure message sent to UE. * UE. This result will trigger an ESM Failure message sent to UE.
*/ */
DevMessage("Not implemented: ACCESS NOT GRANTED, send ESM Failure to NAS\n"); DevMessage("Not implemented: ACCESS NOT GRANTED, send ESM Failure to NAS\n");
} }
message_p = itti_alloc_new_message(TASK_MME_APP, SGW_CREATE_SESSION_REQUEST); message_p = itti_alloc_new_message(TASK_MME_APP, SGW_CREATE_SESSION_REQUEST);
@@ -114,34 +114,36 @@ mme_app_send_s11_create_session_req(
/* Copy the MSISDN */ /* Copy the MSISDN */
memcpy( memcpy(
session_request_p->msisdn.digit, session_request_p->msisdn.digit,
ue_context_pP->msisdn, ue_context_pP->msisdn,
ue_context_pP->msisdn_length); ue_context_pP->msisdn_length);
session_request_p->msisdn.length = ue_context_pP->msisdn_length; session_request_p->msisdn.length = ue_context_pP->msisdn_length;
session_request_p->rat_type = RAT_EUTRAN; session_request_p->rat_type = RAT_EUTRAN;
/* Copy the subscribed ambr to the sgw create session request message */ /* Copy the subscribed ambr to the sgw create session request message */
memcpy( memcpy(
&session_request_p->ambr, &session_request_p->ambr,
&ue_context_pP->subscribed_ambr, &ue_context_pP->subscribed_ambr,
sizeof(ambr_t)); sizeof(ambr_t));
if (ue_context_pP->apn_profile.nb_apns == 0) { if (ue_context_pP->apn_profile.nb_apns == 0) {
DevMessage("No APN returned by the HSS"); DevMessage("No APN returned by the HSS");
} }
context_identifier = ue_context_pP->apn_profile.context_identifier; context_identifier = ue_context_pP->apn_profile.context_identifier;
for (i = 0; i < ue_context_pP->apn_profile.nb_apns; i++) { for (i = 0; i < ue_context_pP->apn_profile.nb_apns; i++) {
default_apn_p = &ue_context_pP->apn_profile.apn_configuration[i]; default_apn_p = &ue_context_pP->apn_profile.apn_configuration[i];
/* OK we got our default APN */
if (default_apn_p->context_identifier == context_identifier) /* OK we got our default APN */
break; if (default_apn_p->context_identifier == context_identifier)
break;
} }
if (!default_apn_p) { if (!default_apn_p) {
/* Unfortunately we didn't find our default APN... */ /* Unfortunately we didn't find our default APN... */
DevMessage("No default APN found"); DevMessage("No default APN found");
} }
memcpy(&session_request_p->bearer_to_create.bearer_level_qos.gbr, memcpy(&session_request_p->bearer_to_create.bearer_level_qos.gbr,
@@ -150,14 +152,14 @@ mme_app_send_s11_create_session_req(
&default_apn_p->ambr, sizeof(ambr_t)); &default_apn_p->ambr, sizeof(ambr_t));
session_request_p->bearer_to_create.bearer_level_qos.qci = session_request_p->bearer_to_create.bearer_level_qos.qci =
default_apn_p->subscribed_qos.qci; default_apn_p->subscribed_qos.qci;
session_request_p->bearer_to_create.bearer_level_qos.pvi = session_request_p->bearer_to_create.bearer_level_qos.pvi =
default_apn_p->subscribed_qos.allocation_retention_priority.pre_emp_vulnerability; default_apn_p->subscribed_qos.allocation_retention_priority.pre_emp_vulnerability;
session_request_p->bearer_to_create.bearer_level_qos.pci = session_request_p->bearer_to_create.bearer_level_qos.pci =
default_apn_p->subscribed_qos.allocation_retention_priority.pre_emp_capability; default_apn_p->subscribed_qos.allocation_retention_priority.pre_emp_capability;
session_request_p->bearer_to_create.bearer_level_qos.pl = session_request_p->bearer_to_create.bearer_level_qos.pl =
default_apn_p->subscribed_qos.allocation_retention_priority.priority_level; default_apn_p->subscribed_qos.allocation_retention_priority.priority_level;
/* Asking for default bearer in initial UE message. /* Asking for default bearer in initial UE message.
* Use the address of ue_context as unique TEID: Need to find better here * Use the address of ue_context as unique TEID: Need to find better here
@@ -176,23 +178,26 @@ mme_app_send_s11_create_session_req(
/* Set PDN type for pdn_type and PAA even if this IE is redundant */ /* Set PDN type for pdn_type and PAA even if this IE is redundant */
session_request_p->pdn_type = default_apn_p->pdn_type; session_request_p->pdn_type = default_apn_p->pdn_type;
session_request_p->paa.pdn_type = default_apn_p->pdn_type; session_request_p->paa.pdn_type = default_apn_p->pdn_type;
if (default_apn_p->nb_ip_address == 0) {
/* UE DHCPv4 allocated ip address */
memset(session_request_p->paa.ipv4_address, 0, 4);
memset(session_request_p->paa.ipv6_address, 0, 16);
} else {
uint8_t j;
for (j = 0; j < default_apn_p->nb_ip_address; j++) { if (default_apn_p->nb_ip_address == 0) {
ip_address_t *ip_address; /* UE DHCPv4 allocated ip address */
ip_address = &default_apn_p->ip_address[j]; memset(session_request_p->paa.ipv4_address, 0, 4);
if (ip_address->pdn_type == IPv4) { memset(session_request_p->paa.ipv6_address, 0, 16);
memcpy(session_request_p->paa.ipv4_address, ip_address->address.ipv4_address, 4); } else {
} else if (ip_address->pdn_type == IPv6) { uint8_t j;
memcpy(session_request_p->paa.ipv6_address, ip_address->address.ipv6_address, 16);
} for (j = 0; j < default_apn_p->nb_ip_address; j++) {
// free(ip_address); ip_address_t *ip_address;
ip_address = &default_apn_p->ip_address[j];
if (ip_address->pdn_type == IPv4) {
memcpy(session_request_p->paa.ipv4_address, ip_address->address.ipv4_address, 4);
} else if (ip_address->pdn_type == IPv6) {
memcpy(session_request_p->paa.ipv6_address, ip_address->address.ipv6_address, 16);
} }
// free(ip_address);
}
} }
config_read_lock(&mme_config); config_read_lock(&mme_config);
@@ -215,7 +220,7 @@ mme_app_send_s11_create_session_req(
int int
mme_app_handle_nas_pdn_connectivity_req( mme_app_handle_nas_pdn_connectivity_req(
nas_pdn_connectivity_req_t * const nas_pdn_connectivity_req_pP) nas_pdn_connectivity_req_t * const nas_pdn_connectivity_req_pP)
{ {
struct ue_context_s *ue_context_p = NULL; struct ue_context_s *ue_context_p = NULL;
uint64_t imsi = 0; uint64_t imsi = 0;
@@ -228,9 +233,9 @@ mme_app_handle_nas_pdn_connectivity_req(
MME_APP_DEBUG("Handling imsi %"IMSI_FORMAT"\n", imsi); MME_APP_DEBUG("Handling imsi %"IMSI_FORMAT"\n", imsi);
if ((ue_context_p = mme_ue_context_exists_imsi(&mme_app_desc.mme_ue_contexts, if ((ue_context_p = mme_ue_context_exists_imsi(&mme_app_desc.mme_ue_contexts,
imsi)) == NULL) { imsi)) == NULL) {
MME_APP_ERROR("That's embarrassing as we don't know this IMSI\n"); MME_APP_ERROR("That's embarrassing as we don't know this IMSI\n");
return -1; return -1;
} }
/* Consider the UE authenticated */ /* Consider the UE authenticated */
@@ -239,15 +244,15 @@ mme_app_handle_nas_pdn_connectivity_req(
// Temp: save request, in near future merge wisely params in context // Temp: save request, in near future merge wisely params in context
memset(ue_context_p->pending_pdn_connectivity_req_imsi,0, 16); memset(ue_context_p->pending_pdn_connectivity_req_imsi,0, 16);
AssertFatal((nas_pdn_connectivity_req_pP->imsi_length > 0) && AssertFatal((nas_pdn_connectivity_req_pP->imsi_length > 0) &&
(nas_pdn_connectivity_req_pP->imsi_length < 16), (nas_pdn_connectivity_req_pP->imsi_length < 16),
"BAD IMSI LENGTH %d", nas_pdn_connectivity_req_pP->imsi_length); "BAD IMSI LENGTH %d", nas_pdn_connectivity_req_pP->imsi_length);
AssertFatal((nas_pdn_connectivity_req_pP->imsi_length > 0) && AssertFatal((nas_pdn_connectivity_req_pP->imsi_length > 0) &&
(nas_pdn_connectivity_req_pP->imsi_length < 16), (nas_pdn_connectivity_req_pP->imsi_length < 16),
"STOP ON IMSI LENGTH %d", nas_pdn_connectivity_req_pP->imsi_length); "STOP ON IMSI LENGTH %d", nas_pdn_connectivity_req_pP->imsi_length);
memcpy(ue_context_p->pending_pdn_connectivity_req_imsi, memcpy(ue_context_p->pending_pdn_connectivity_req_imsi,
nas_pdn_connectivity_req_pP->imsi, nas_pdn_connectivity_req_pP->imsi,
nas_pdn_connectivity_req_pP->imsi_length); nas_pdn_connectivity_req_pP->imsi_length);
ue_context_p->pending_pdn_connectivity_req_imsi_length = nas_pdn_connectivity_req_pP->imsi_length; ue_context_p->pending_pdn_connectivity_req_imsi_length = nas_pdn_connectivity_req_pP->imsi_length;
DUP_OCTET_STRING(nas_pdn_connectivity_req_pP->apn, ue_context_p->pending_pdn_connectivity_req_apn); DUP_OCTET_STRING(nas_pdn_connectivity_req_pP->apn, ue_context_p->pending_pdn_connectivity_req_apn);
FREE_OCTET_STRING(nas_pdn_connectivity_req_pP->apn) FREE_OCTET_STRING(nas_pdn_connectivity_req_pP->apn)
@@ -265,11 +270,11 @@ mme_app_handle_nas_pdn_connectivity_req(
ue_context_p->pending_pdn_connectivity_req_request_type = nas_pdn_connectivity_req_pP->request_type; ue_context_p->pending_pdn_connectivity_req_request_type = nas_pdn_connectivity_req_pP->request_type;
//if ((nas_pdn_connectivity_req_pP->apn.value == NULL) || (nas_pdn_connectivity_req_pP->apn.length == 0)) { //if ((nas_pdn_connectivity_req_pP->apn.value == NULL) || (nas_pdn_connectivity_req_pP->apn.length == 0)) {
/* TODO: Get keys... */ /* TODO: Get keys... */
/* Now generate S6A ULR */ /* Now generate S6A ULR */
return mme_app_send_s6a_update_location_req(ue_context_p); return mme_app_send_s6a_update_location_req(ue_context_p);
//} else { //} else {
//return mme_app_send_s11_create_session_req(ue_context_p); //return mme_app_send_s11_create_session_req(ue_context_p);
//} //}
//return -1; //return -1;
@@ -280,71 +285,75 @@ mme_app_handle_nas_pdn_connectivity_req(
// sent by NAS // sent by NAS
void void
mme_app_handle_conn_est_cnf( mme_app_handle_conn_est_cnf(
const nas_conn_est_cnf_t * const nas_conn_est_cnf_pP) const nas_conn_est_cnf_t * const nas_conn_est_cnf_pP)
{ {
struct ue_context_s *ue_context_p = NULL; struct ue_context_s *ue_context_p = NULL;
MessageDef *message_p = NULL; MessageDef *message_p = NULL;
mme_app_connection_establishment_cnf_t *establishment_cnf_p = NULL; mme_app_connection_establishment_cnf_t *establishment_cnf_p = NULL;
bearer_context_t *current_bearer_p = NULL; bearer_context_t *current_bearer_p = NULL;
ebi_t bearer_id = 0; ebi_t bearer_id = 0;
uint8_t keNB[32]; uint8_t keNB[32];
MME_APP_DEBUG("Received NAS_CONNECTION_ESTABLISHMENT_CNF from NAS\n"); MME_APP_DEBUG("Received NAS_CONNECTION_ESTABLISHMENT_CNF from NAS\n");
ue_context_p = mme_ue_context_exists_nas_ue_id(&mme_app_desc.mme_ue_contexts, nas_conn_est_cnf_pP->UEid); ue_context_p = mme_ue_context_exists_nas_ue_id(&mme_app_desc.mme_ue_contexts, nas_conn_est_cnf_pP->UEid);
if (ue_context_p == NULL) {
MME_APP_ERROR("UE context doesn't exist for UE 0x%08X/dec%u\n",
nas_conn_est_cnf_pP->UEid,
nas_conn_est_cnf_pP->UEid);
return;
}
message_p = itti_alloc_new_message(TASK_MME_APP, MME_APP_CONNECTION_ESTABLISHMENT_CNF); if (ue_context_p == NULL) {
establishment_cnf_p = &message_p->ittiMsg.mme_app_connection_establishment_cnf; MME_APP_ERROR("UE context doesn't exist for UE 0x%08X/dec%u\n",
memset(establishment_cnf_p, 0, sizeof(mme_app_connection_establishment_cnf_t)); nas_conn_est_cnf_pP->UEid,
nas_conn_est_cnf_pP->UEid);
return;
}
memcpy(&establishment_cnf_p->nas_conn_est_cnf, message_p = itti_alloc_new_message(TASK_MME_APP, MME_APP_CONNECTION_ESTABLISHMENT_CNF);
nas_conn_est_cnf_pP, establishment_cnf_p = &message_p->ittiMsg.mme_app_connection_establishment_cnf;
sizeof(nas_conn_est_cnf_t)); memset(establishment_cnf_p, 0, sizeof(mme_app_connection_establishment_cnf_t));
bearer_id = ue_context_p->default_bearer_id; memcpy(&establishment_cnf_p->nas_conn_est_cnf,
current_bearer_p = &ue_context_p->eps_bearers[bearer_id]; nas_conn_est_cnf_pP,
establishment_cnf_p->eps_bearer_id = bearer_id; sizeof(nas_conn_est_cnf_t));
establishment_cnf_p->bearer_s1u_sgw_fteid.interface_type = S1_U_SGW_GTP_U; bearer_id = ue_context_p->default_bearer_id;
establishment_cnf_p->bearer_s1u_sgw_fteid.teid = current_bearer_p->s_gw_teid; current_bearer_p = &ue_context_p->eps_bearers[bearer_id];
if ((current_bearer_p->s_gw_address.pdn_type == IPv4) || establishment_cnf_p->eps_bearer_id = bearer_id;
(current_bearer_p->s_gw_address.pdn_type == IPv4_AND_v6)) {
establishment_cnf_p->bearer_s1u_sgw_fteid.ipv4 = 1; establishment_cnf_p->bearer_s1u_sgw_fteid.interface_type = S1_U_SGW_GTP_U;
memcpy(&establishment_cnf_p->bearer_s1u_sgw_fteid.ipv4_address, establishment_cnf_p->bearer_s1u_sgw_fteid.teid = current_bearer_p->s_gw_teid;
current_bearer_p->s_gw_address.address.ipv4_address,
4); if ((current_bearer_p->s_gw_address.pdn_type == IPv4) ||
} (current_bearer_p->s_gw_address.pdn_type == IPv4_AND_v6)) {
if ((current_bearer_p->s_gw_address.pdn_type == IPv6) || establishment_cnf_p->bearer_s1u_sgw_fteid.ipv4 = 1;
(current_bearer_p->s_gw_address.pdn_type == IPv4_AND_v6)) { memcpy(&establishment_cnf_p->bearer_s1u_sgw_fteid.ipv4_address,
establishment_cnf_p->bearer_s1u_sgw_fteid.ipv6 = 1; current_bearer_p->s_gw_address.address.ipv4_address,
memcpy(establishment_cnf_p->bearer_s1u_sgw_fteid.ipv6_address, 4);
current_bearer_p->s_gw_address.address.ipv6_address, }
16);
} if ((current_bearer_p->s_gw_address.pdn_type == IPv6) ||
establishment_cnf_p->bearer_qos_qci = current_bearer_p->qci; (current_bearer_p->s_gw_address.pdn_type == IPv4_AND_v6)) {
establishment_cnf_p->bearer_qos_prio_level = current_bearer_p->prio_level; establishment_cnf_p->bearer_s1u_sgw_fteid.ipv6 = 1;
establishment_cnf_p->bearer_qos_pre_emp_vulnerability = current_bearer_p->pre_emp_vulnerability; memcpy(establishment_cnf_p->bearer_s1u_sgw_fteid.ipv6_address,
establishment_cnf_p->bearer_qos_pre_emp_capability = current_bearer_p->pre_emp_capability; current_bearer_p->s_gw_address.address.ipv6_address,
16);
}
establishment_cnf_p->bearer_qos_qci = current_bearer_p->qci;
establishment_cnf_p->bearer_qos_prio_level = current_bearer_p->prio_level;
establishment_cnf_p->bearer_qos_pre_emp_vulnerability = current_bearer_p->pre_emp_vulnerability;
establishment_cnf_p->bearer_qos_pre_emp_capability = current_bearer_p->pre_emp_capability;
#warning "Check ue_context_p ambr" #warning "Check ue_context_p ambr"
establishment_cnf_p->ambr.br_ul = ue_context_p->subscribed_ambr.br_ul; establishment_cnf_p->ambr.br_ul = ue_context_p->subscribed_ambr.br_ul;
establishment_cnf_p->ambr.br_dl = ue_context_p->subscribed_ambr.br_dl; establishment_cnf_p->ambr.br_dl = ue_context_p->subscribed_ambr.br_dl;
establishment_cnf_p->security_capabilities_encryption_algorithms = nas_conn_est_cnf_pP->selected_encryption_algorithm; establishment_cnf_p->security_capabilities_encryption_algorithms = nas_conn_est_cnf_pP->selected_encryption_algorithm;
establishment_cnf_p->security_capabilities_integrity_algorithms = nas_conn_est_cnf_pP->selected_integrity_algorithm; establishment_cnf_p->security_capabilities_integrity_algorithms = nas_conn_est_cnf_pP->selected_integrity_algorithm;
MME_APP_DEBUG("security_capabilities_encryption_algorithms 0x%04X\n", establishment_cnf_p->security_capabilities_encryption_algorithms); MME_APP_DEBUG("security_capabilities_encryption_algorithms 0x%04X\n", establishment_cnf_p->security_capabilities_encryption_algorithms);
MME_APP_DEBUG("security_capabilities_integrity_algorithms 0x%04X\n", establishment_cnf_p->security_capabilities_integrity_algorithms); MME_APP_DEBUG("security_capabilities_integrity_algorithms 0x%04X\n", establishment_cnf_p->security_capabilities_integrity_algorithms);
MME_APP_DEBUG("Derive keNB with UL NAS COUNT %x\n", nas_conn_est_cnf_pP->ul_nas_count); MME_APP_DEBUG("Derive keNB with UL NAS COUNT %x\n", nas_conn_est_cnf_pP->ul_nas_count);
derive_keNB(ue_context_p->vector_in_use->kasme, nas_conn_est_cnf_pP->ul_nas_count, keNB); //156 derive_keNB(ue_context_p->vector_in_use->kasme, nas_conn_est_cnf_pP->ul_nas_count, keNB); //156
memcpy(establishment_cnf_p->keNB, keNB, 32); memcpy(establishment_cnf_p->keNB, keNB, 32);
itti_send_msg_to_task(TASK_S1AP, INSTANCE_DEFAULT, message_p); itti_send_msg_to_task(TASK_S1AP, INSTANCE_DEFAULT, message_p);
} }
@@ -352,317 +361,340 @@ mme_app_handle_conn_est_cnf(
// sent by S1AP // sent by S1AP
void void
mme_app_handle_conn_est_ind( mme_app_handle_conn_est_ind(
const mme_app_connection_establishment_ind_t * const conn_est_ind_pP) const mme_app_connection_establishment_ind_t * const conn_est_ind_pP)
{ {
struct ue_context_s *ue_context_p = NULL; struct ue_context_s *ue_context_p = NULL;
MessageDef *message_p = NULL; MessageDef *message_p = NULL;
MME_APP_DEBUG("Received MME_APP_CONNECTION_ESTABLISHMENT_IND from S1AP\n"); MME_APP_DEBUG("Received MME_APP_CONNECTION_ESTABLISHMENT_IND from S1AP\n");
ue_context_p = mme_ue_context_exists_mme_ue_s1ap_id( ue_context_p = mme_ue_context_exists_mme_ue_s1ap_id(
&mme_app_desc.mme_ue_contexts, &mme_app_desc.mme_ue_contexts,
conn_est_ind_pP->mme_ue_s1ap_id); conn_est_ind_pP->mme_ue_s1ap_id);
if (ue_context_p == NULL) {
MME_APP_DEBUG("We didn't find this mme_ue_s1ap_id in list of UE: 0x%08x/dec%u\n",
conn_est_ind_pP->mme_ue_s1ap_id,
conn_est_ind_pP->mme_ue_s1ap_id);
MME_APP_DEBUG("UE context doesn't exist -> create one\n");
if ((ue_context_p = mme_create_new_ue_context()) == NULL) {
/* Error during ue context malloc */
/* TODO */
DevMessage("mme_create_new_ue_context");
return;
}
// S1AP UE ID AND NAS UE ID ARE THE SAME
ue_context_p->mme_ue_s1ap_id = conn_est_ind_pP->mme_ue_s1ap_id;
ue_context_p->ue_id = conn_est_ind_pP->mme_ue_s1ap_id;
DevAssert(mme_insert_ue_context(&mme_app_desc.mme_ue_contexts, ue_context_p) == 0);
// tests if (ue_context_p == NULL) {
ue_context_p = mme_ue_context_exists_mme_ue_s1ap_id( MME_APP_DEBUG("We didn't find this mme_ue_s1ap_id in list of UE: 0x%08x/dec%u\n",
&mme_app_desc.mme_ue_contexts, conn_est_ind_pP->mme_ue_s1ap_id,
conn_est_ind_pP->mme_ue_s1ap_id); conn_est_ind_pP->mme_ue_s1ap_id);
AssertFatal(ue_context_p != NULL, "mme_ue_context_exists_mme_ue_s1ap_id Failed"); MME_APP_DEBUG("UE context doesn't exist -> create one\n");
ue_context_p = mme_ue_context_exists_nas_ue_id(
&mme_app_desc.mme_ue_contexts, if ((ue_context_p = mme_create_new_ue_context()) == NULL) {
conn_est_ind_pP->mme_ue_s1ap_id); /* Error during ue context malloc */
AssertFatal(ue_context_p != NULL, "mme_ue_context_exists_nas_ue_id Failed"); /* TODO */
DevMessage("mme_create_new_ue_context");
return;
} }
message_p = itti_alloc_new_message(TASK_MME_APP, NAS_CONNECTION_ESTABLISHMENT_IND); // S1AP UE ID AND NAS UE ID ARE THE SAME
memcpy(&NAS_CONN_EST_IND(message_p).nas, ue_context_p->mme_ue_s1ap_id = conn_est_ind_pP->mme_ue_s1ap_id;
&conn_est_ind_pP->nas, ue_context_p->ue_id = conn_est_ind_pP->mme_ue_s1ap_id;
sizeof (nas_establish_ind_t)); DevAssert(mme_insert_ue_context(&mme_app_desc.mme_ue_contexts, ue_context_p) == 0);
itti_send_msg_to_task(TASK_NAS_MME, INSTANCE_DEFAULT, message_p); // tests
ue_context_p = mme_ue_context_exists_mme_ue_s1ap_id(
&mme_app_desc.mme_ue_contexts,
conn_est_ind_pP->mme_ue_s1ap_id);
AssertFatal(ue_context_p != NULL, "mme_ue_context_exists_mme_ue_s1ap_id Failed");
ue_context_p = mme_ue_context_exists_nas_ue_id(
&mme_app_desc.mme_ue_contexts,
conn_est_ind_pP->mme_ue_s1ap_id);
AssertFatal(ue_context_p != NULL, "mme_ue_context_exists_nas_ue_id Failed");
}
message_p = itti_alloc_new_message(TASK_MME_APP, NAS_CONNECTION_ESTABLISHMENT_IND);
memcpy(&NAS_CONN_EST_IND(message_p).nas,
&conn_est_ind_pP->nas,
sizeof (nas_establish_ind_t));
itti_send_msg_to_task(TASK_NAS_MME, INSTANCE_DEFAULT, message_p);
} }
int int
mme_app_handle_create_sess_resp( mme_app_handle_create_sess_resp(
const SgwCreateSessionResponse * const create_sess_resp_pP) const SgwCreateSessionResponse * const create_sess_resp_pP)
{ {
struct ue_context_s *ue_context_p = NULL; struct ue_context_s *ue_context_p = NULL;
bearer_context_t *current_bearer_p = NULL; bearer_context_t *current_bearer_p = NULL;
MessageDef *message_p = NULL; MessageDef *message_p = NULL;
int16_t bearer_id; int16_t bearer_id;
DevAssert(create_sess_resp_pP != NULL); DevAssert(create_sess_resp_pP != NULL);
MME_APP_DEBUG("Received SGW_CREATE_SESSION_RESPONSE from S+P-GW\n"); MME_APP_DEBUG("Received SGW_CREATE_SESSION_RESPONSE from S+P-GW\n");
ue_context_p = mme_ue_context_exists_s11_teid(&mme_app_desc.mme_ue_contexts, ue_context_p = mme_ue_context_exists_s11_teid(&mme_app_desc.mme_ue_contexts,
create_sess_resp_pP->teid); create_sess_resp_pP->teid);
if (ue_context_p == NULL) {
MME_APP_DEBUG("We didn't find this teid in list of UE: %08x\n",
create_sess_resp_pP->teid);
return -1;
}
/* Store the S-GW teid */ if (ue_context_p == NULL) {
ue_context_p->sgw_s11_teid = create_sess_resp_pP->s11_sgw_teid.teid; MME_APP_DEBUG("We didn't find this teid in list of UE: %08x\n",
create_sess_resp_pP->teid);
return -1;
}
//--------------------------------------------------------- /* Store the S-GW teid */
// Process SgwCreateSessionResponse.bearer_context_created ue_context_p->sgw_s11_teid = create_sess_resp_pP->s11_sgw_teid.teid;
//---------------------------------------------------------
bearer_id = create_sess_resp_pP->bearer_context_created.eps_bearer_id/* - 5*/;
/* Depending on s11 result we have to send reject or accept for bearers */
DevCheck((bearer_id < BEARERS_PER_UE) && (bearer_id >= 0),
bearer_id,
BEARERS_PER_UE,
0);
ue_context_p->default_bearer_id = bearer_id;
if (create_sess_resp_pP->bearer_context_created.cause != REQUEST_ACCEPTED) { //---------------------------------------------------------
DevMessage("Cases where bearer cause != REQUEST_ACCEPTED are not handled\n"); // Process SgwCreateSessionResponse.bearer_context_created
} //---------------------------------------------------------
DevAssert(create_sess_resp_pP->bearer_context_created.s1u_sgw_fteid.interface_type == S1_U_SGW_GTP_U); bearer_id = create_sess_resp_pP->bearer_context_created.eps_bearer_id/* - 5*/;
/* Depending on s11 result we have to send reject or accept for bearers */
DevCheck((bearer_id < BEARERS_PER_UE) && (bearer_id >= 0),
bearer_id,
BEARERS_PER_UE,
0);
ue_context_p->default_bearer_id = bearer_id;
/* Updating statistics */ if (create_sess_resp_pP->bearer_context_created.cause != REQUEST_ACCEPTED) {
mme_app_desc.mme_ue_contexts.nb_bearers_managed++; DevMessage("Cases where bearer cause != REQUEST_ACCEPTED are not handled\n");
mme_app_desc.mme_ue_contexts.nb_bearers_since_last_stat++; }
current_bearer_p = &ue_context_p->eps_bearers[bearer_id]; DevAssert(create_sess_resp_pP->bearer_context_created.s1u_sgw_fteid.interface_type == S1_U_SGW_GTP_U);
current_bearer_p->s_gw_teid = create_sess_resp_pP->bearer_context_created.s1u_sgw_fteid.teid;
switch (create_sess_resp_pP->bearer_context_created.s1u_sgw_fteid.ipv4 + /* Updating statistics */
(create_sess_resp_pP->bearer_context_created.s1u_sgw_fteid.ipv6 << 1)) mme_app_desc.mme_ue_contexts.nb_bearers_managed++;
{ mme_app_desc.mme_ue_contexts.nb_bearers_since_last_stat++;
default:
case 0: { current_bearer_p = &ue_context_p->eps_bearers[bearer_id];
/* No address provided: impossible case */ current_bearer_p->s_gw_teid = create_sess_resp_pP->bearer_context_created.s1u_sgw_fteid.teid;
DevMessage("No ip address for user-plane provided...\n");
} break; switch (create_sess_resp_pP->bearer_context_created.s1u_sgw_fteid.ipv4 +
case 1: { (create_sess_resp_pP->bearer_context_created.s1u_sgw_fteid.ipv6 << 1)) {
/* Only IPv4 address */ default:
current_bearer_p->s_gw_address.pdn_type = IPv4; case 0: {
memcpy(current_bearer_p->s_gw_address.address.ipv4_address, /* No address provided: impossible case */
&create_sess_resp_pP->bearer_context_created.s1u_sgw_fteid.ipv4_address, 4); DevMessage("No ip address for user-plane provided...\n");
} break; }
case 2: { break;
/* Only IPv6 address */
current_bearer_p->s_gw_address.pdn_type = IPv6; case 1: {
memcpy(current_bearer_p->s_gw_address.address.ipv6_address, /* Only IPv4 address */
create_sess_resp_pP->bearer_context_created.s1u_sgw_fteid.ipv6_address, 16); current_bearer_p->s_gw_address.pdn_type = IPv4;
} break; memcpy(current_bearer_p->s_gw_address.address.ipv4_address,
case 3: { &create_sess_resp_pP->bearer_context_created.s1u_sgw_fteid.ipv4_address, 4);
/* Both IPv4 and Ipv6 */ }
current_bearer_p->s_gw_address.pdn_type = IPv4_AND_v6; break;
memcpy(current_bearer_p->s_gw_address.address.ipv4_address,
&create_sess_resp_pP->bearer_context_created.s1u_sgw_fteid.ipv4_address, 4); case 2: {
memcpy(current_bearer_p->s_gw_address.address.ipv6_address, /* Only IPv6 address */
create_sess_resp_pP->bearer_context_created.s1u_sgw_fteid.ipv6_address, 16); current_bearer_p->s_gw_address.pdn_type = IPv6;
} break; memcpy(current_bearer_p->s_gw_address.address.ipv6_address,
} create_sess_resp_pP->bearer_context_created.s1u_sgw_fteid.ipv6_address, 16);
current_bearer_p->p_gw_teid = create_sess_resp_pP->bearer_context_created.s5_s8_u_pgw_fteid.teid; }
memset(&current_bearer_p->p_gw_address,0, sizeof(ip_address_t)); break;
if (create_sess_resp_pP->bearer_context_created.bearer_level_qos != NULL) {
current_bearer_p->qci = create_sess_resp_pP->bearer_context_created.bearer_level_qos->qci; case 3: {
current_bearer_p->prio_level = create_sess_resp_pP->bearer_context_created.bearer_level_qos->pl; /* Both IPv4 and Ipv6 */
current_bearer_p->pre_emp_vulnerability = create_sess_resp_pP->bearer_context_created.bearer_level_qos->pvi; current_bearer_p->s_gw_address.pdn_type = IPv4_AND_v6;
current_bearer_p->pre_emp_capability = create_sess_resp_pP->bearer_context_created.bearer_level_qos->pci; memcpy(current_bearer_p->s_gw_address.address.ipv4_address,
MME_APP_DEBUG("%s set qci %u in bearer %u\n", &create_sess_resp_pP->bearer_context_created.s1u_sgw_fteid.ipv4_address, 4);
__FUNCTION__, memcpy(current_bearer_p->s_gw_address.address.ipv6_address,
current_bearer_p->qci, create_sess_resp_pP->bearer_context_created.s1u_sgw_fteid.ipv6_address, 16);
ue_context_p->default_bearer_id); }
} else { break;
// if null, it is not modified }
//current_bearer_p->qci = ue_context_p->pending_pdn_connectivity_req_qos.qci;
current_bearer_p->p_gw_teid = create_sess_resp_pP->bearer_context_created.s5_s8_u_pgw_fteid.teid;
memset(&current_bearer_p->p_gw_address,0, sizeof(ip_address_t));
if (create_sess_resp_pP->bearer_context_created.bearer_level_qos != NULL) {
current_bearer_p->qci = create_sess_resp_pP->bearer_context_created.bearer_level_qos->qci;
current_bearer_p->prio_level = create_sess_resp_pP->bearer_context_created.bearer_level_qos->pl;
current_bearer_p->pre_emp_vulnerability = create_sess_resp_pP->bearer_context_created.bearer_level_qos->pvi;
current_bearer_p->pre_emp_capability = create_sess_resp_pP->bearer_context_created.bearer_level_qos->pci;
MME_APP_DEBUG("%s set qci %u in bearer %u\n",
__FUNCTION__,
current_bearer_p->qci,
ue_context_p->default_bearer_id);
} else {
// if null, it is not modified
//current_bearer_p->qci = ue_context_p->pending_pdn_connectivity_req_qos.qci;
#warning "may force QCI here to 9" #warning "may force QCI here to 9"
current_bearer_p->qci = 9; current_bearer_p->qci = 9;
current_bearer_p->prio_level = 1; current_bearer_p->prio_level = 1;
current_bearer_p->pre_emp_vulnerability = 0; current_bearer_p->pre_emp_vulnerability = 0;
current_bearer_p->pre_emp_capability = 0; current_bearer_p->pre_emp_capability = 0;
MME_APP_DEBUG("%s set qci %u in bearer %u (qos not modified by S/P-GW)\n", MME_APP_DEBUG("%s set qci %u in bearer %u (qos not modified by S/P-GW)\n",
__FUNCTION__, __FUNCTION__,
current_bearer_p->qci, current_bearer_p->qci,
ue_context_p->default_bearer_id); ue_context_p->default_bearer_id);
}
mme_app_dump_ue_contexts(&mme_app_desc.mme_ue_contexts);
{
//uint8_t *keNB = NULL;
message_p = itti_alloc_new_message(TASK_MME_APP, NAS_PDN_CONNECTIVITY_RSP);
memset((void*)&message_p->ittiMsg.nas_pdn_connectivity_rsp,
0,
sizeof(nas_pdn_connectivity_rsp_t));
// moved to NAS_CONNECTION_ESTABLISHMENT_CONF, keNB not handled in NAS MME
//derive_keNB(ue_context_p->vector_in_use->kasme, 156, &keNB);
//memcpy(NAS_PDN_CONNECTIVITY_RSP(message_p).keNB, keNB, 32);
//free(keNB);
NAS_PDN_CONNECTIVITY_RSP(message_p).pti = ue_context_p->pending_pdn_connectivity_req_pti; // NAS internal ref
NAS_PDN_CONNECTIVITY_RSP(message_p).ue_id = ue_context_p->pending_pdn_connectivity_req_ue_id; // NAS internal ref
// TO REWORK:
if ((ue_context_p->pending_pdn_connectivity_req_apn.value != NULL)
&& (ue_context_p->pending_pdn_connectivity_req_apn.length != 0)) {
DUP_OCTET_STRING(
ue_context_p->pending_pdn_connectivity_req_apn,
NAS_PDN_CONNECTIVITY_RSP(message_p).apn);
MME_APP_DEBUG("SET APN FROM NAS PDN CONNECTIVITY CREATE: %s\n", NAS_PDN_CONNECTIVITY_RSP(message_p).apn.value);
} else {
int i;
context_identifier_t context_identifier = ue_context_p->apn_profile.context_identifier;
for (i = 0; i < ue_context_p->apn_profile.nb_apns; i++) {
if (ue_context_p->apn_profile.apn_configuration[i].context_identifier == context_identifier) {
AssertFatal(ue_context_p->apn_profile.apn_configuration[i].service_selection_length > 0, "Bad APN string (len = 0)");
if (ue_context_p->apn_profile.apn_configuration[i].service_selection_length > 0) {
NAS_PDN_CONNECTIVITY_RSP(message_p).apn.value = malloc(ue_context_p->apn_profile.apn_configuration[i].service_selection_length + 1);
NAS_PDN_CONNECTIVITY_RSP(message_p).apn.length = ue_context_p->apn_profile.apn_configuration[i].service_selection_length;
AssertFatal(ue_context_p->apn_profile.apn_configuration[i].service_selection_length <= APN_MAX_LENGTH,
"Bad APN string length %d",
ue_context_p->apn_profile.apn_configuration[i].service_selection_length);
memcpy(NAS_PDN_CONNECTIVITY_RSP(message_p).apn.value,
ue_context_p->apn_profile.apn_configuration[i].service_selection,
ue_context_p->apn_profile.apn_configuration[i].service_selection_length);
NAS_PDN_CONNECTIVITY_RSP(message_p).apn.value[ue_context_p->apn_profile.apn_configuration[i].service_selection_length] = '\0';
MME_APP_DEBUG("SET APN FROM HSS ULA: %s\n", NAS_PDN_CONNECTIVITY_RSP(message_p).apn.value);
break;
}
}
}
} }
mme_app_dump_ue_contexts(&mme_app_desc.mme_ue_contexts); MME_APP_DEBUG("APN: %s\n", NAS_PDN_CONNECTIVITY_RSP(message_p).apn.value);
{ switch (create_sess_resp_pP->paa.pdn_type) {
//uint8_t *keNB = NULL; case IPv4:
NAS_PDN_CONNECTIVITY_RSP(message_p).pdn_addr.length = 4;
NAS_PDN_CONNECTIVITY_RSP(message_p).pdn_addr.value = malloc(NAS_PDN_CONNECTIVITY_RSP(message_p).pdn_addr.length+1);
DevAssert(NAS_PDN_CONNECTIVITY_RSP(message_p).pdn_addr.value != NULL);
memcpy(
NAS_PDN_CONNECTIVITY_RSP(message_p).pdn_addr.value,
create_sess_resp_pP->paa.ipv4_address,
NAS_PDN_CONNECTIVITY_RSP(message_p).pdn_addr.length);
NAS_PDN_CONNECTIVITY_RSP(message_p).pdn_addr.value[NAS_PDN_CONNECTIVITY_RSP(message_p).pdn_addr.length] = '0';
break;
message_p = itti_alloc_new_message(TASK_MME_APP, NAS_PDN_CONNECTIVITY_RSP); case IPv6:
memset((void*)&message_p->ittiMsg.nas_pdn_connectivity_rsp, DevAssert(create_sess_resp_pP->paa.ipv6_prefix_length == 64); // NAS seems to only support 64 bits
0, NAS_PDN_CONNECTIVITY_RSP(message_p).pdn_addr.length = create_sess_resp_pP->paa.ipv6_prefix_length/8;
sizeof(nas_pdn_connectivity_rsp_t)); NAS_PDN_CONNECTIVITY_RSP(message_p).pdn_addr.value = malloc(NAS_PDN_CONNECTIVITY_RSP(message_p).pdn_addr.length+1);
DevAssert(NAS_PDN_CONNECTIVITY_RSP(message_p).pdn_addr.value != NULL);
memcpy(
NAS_PDN_CONNECTIVITY_RSP(message_p).pdn_addr.value,
create_sess_resp_pP->paa.ipv6_address,
NAS_PDN_CONNECTIVITY_RSP(message_p).pdn_addr.length);
NAS_PDN_CONNECTIVITY_RSP(message_p).pdn_addr.value[NAS_PDN_CONNECTIVITY_RSP(message_p).pdn_addr.length] = '0';
break;
// moved to NAS_CONNECTION_ESTABLISHMENT_CONF, keNB not handled in NAS MME case IPv4_AND_v6:
//derive_keNB(ue_context_p->vector_in_use->kasme, 156, &keNB); DevAssert(create_sess_resp_pP->paa.ipv6_prefix_length == 64); // NAS seems to only support 64 bits
//memcpy(NAS_PDN_CONNECTIVITY_RSP(message_p).keNB, keNB, 32); NAS_PDN_CONNECTIVITY_RSP(message_p).pdn_addr.length = 4 + create_sess_resp_pP->paa.ipv6_prefix_length/8;
NAS_PDN_CONNECTIVITY_RSP(message_p).pdn_addr.value = malloc(NAS_PDN_CONNECTIVITY_RSP(message_p).pdn_addr.length+1);
DevAssert(NAS_PDN_CONNECTIVITY_RSP(message_p).pdn_addr.value != NULL);
memcpy(
NAS_PDN_CONNECTIVITY_RSP(message_p).pdn_addr.value,
create_sess_resp_pP->paa.ipv4_address,
4);
memcpy(
&NAS_PDN_CONNECTIVITY_RSP(message_p).pdn_addr.value[4],
create_sess_resp_pP->paa.ipv6_address,
create_sess_resp_pP->paa.ipv6_prefix_length/8);
NAS_PDN_CONNECTIVITY_RSP(message_p).pdn_addr.value[NAS_PDN_CONNECTIVITY_RSP(message_p).pdn_addr.length] = '0';
break;
//free(keNB); case IPv4_OR_v6:
NAS_PDN_CONNECTIVITY_RSP(message_p).pdn_addr.length = 4;
NAS_PDN_CONNECTIVITY_RSP(message_p).pdn_addr.value = malloc(NAS_PDN_CONNECTIVITY_RSP(message_p).pdn_addr.length+1);
DevAssert(NAS_PDN_CONNECTIVITY_RSP(message_p).pdn_addr.value != NULL);
memcpy(
NAS_PDN_CONNECTIVITY_RSP(message_p).pdn_addr.value,
create_sess_resp_pP->paa.ipv4_address,
NAS_PDN_CONNECTIVITY_RSP(message_p).pdn_addr.length);
NAS_PDN_CONNECTIVITY_RSP(message_p).pdn_addr.value[NAS_PDN_CONNECTIVITY_RSP(message_p).pdn_addr.length] = '0';
break;
NAS_PDN_CONNECTIVITY_RSP(message_p).pti = ue_context_p->pending_pdn_connectivity_req_pti; // NAS internal ref default:
NAS_PDN_CONNECTIVITY_RSP(message_p).ue_id = ue_context_p->pending_pdn_connectivity_req_ue_id; // NAS internal ref DevAssert(0);
// TO REWORK: }
if ((ue_context_p->pending_pdn_connectivity_req_apn.value != NULL)
&& (ue_context_p->pending_pdn_connectivity_req_apn.length != 0)) {
DUP_OCTET_STRING(
ue_context_p->pending_pdn_connectivity_req_apn,
NAS_PDN_CONNECTIVITY_RSP(message_p).apn);
MME_APP_DEBUG("SET APN FROM NAS PDN CONNECTIVITY CREATE: %s\n", NAS_PDN_CONNECTIVITY_RSP(message_p).apn.value);
} else {
int i;
context_identifier_t context_identifier = ue_context_p->apn_profile.context_identifier;
for (i = 0; i < ue_context_p->apn_profile.nb_apns; i++) {
if (ue_context_p->apn_profile.apn_configuration[i].context_identifier == context_identifier) {
AssertFatal(ue_context_p->apn_profile.apn_configuration[i].service_selection_length > 0, "Bad APN string (len = 0)");
if (ue_context_p->apn_profile.apn_configuration[i].service_selection_length > 0) {
NAS_PDN_CONNECTIVITY_RSP(message_p).apn.value = malloc(ue_context_p->apn_profile.apn_configuration[i].service_selection_length + 1);
NAS_PDN_CONNECTIVITY_RSP(message_p).apn.length = ue_context_p->apn_profile.apn_configuration[i].service_selection_length;
AssertFatal(ue_context_p->apn_profile.apn_configuration[i].service_selection_length <= APN_MAX_LENGTH,
"Bad APN string length %d",
ue_context_p->apn_profile.apn_configuration[i].service_selection_length);
memcpy(NAS_PDN_CONNECTIVITY_RSP(message_p).apn.value,
ue_context_p->apn_profile.apn_configuration[i].service_selection,
ue_context_p->apn_profile.apn_configuration[i].service_selection_length);
NAS_PDN_CONNECTIVITY_RSP(message_p).apn.value[ue_context_p->apn_profile.apn_configuration[i].service_selection_length] = '\0';
MME_APP_DEBUG("SET APN FROM HSS ULA: %s\n", NAS_PDN_CONNECTIVITY_RSP(message_p).apn.value);
break;
}
}
}
}
MME_APP_DEBUG("APN: %s\n", NAS_PDN_CONNECTIVITY_RSP(message_p).apn.value);
switch (create_sess_resp_pP->paa.pdn_type) { NAS_PDN_CONNECTIVITY_RSP(message_p).pdn_type = create_sess_resp_pP->paa.pdn_type;
case IPv4: NAS_PDN_CONNECTIVITY_RSP(message_p).proc_data = ue_context_p->pending_pdn_connectivity_req_proc_data; // NAS internal ref
NAS_PDN_CONNECTIVITY_RSP(message_p).pdn_addr.length = 4; ue_context_p->pending_pdn_connectivity_req_proc_data = NULL;
NAS_PDN_CONNECTIVITY_RSP(message_p).pdn_addr.value = malloc(NAS_PDN_CONNECTIVITY_RSP(message_p).pdn_addr.length+1);
DevAssert(NAS_PDN_CONNECTIVITY_RSP(message_p).pdn_addr.value != NULL);
memcpy(
NAS_PDN_CONNECTIVITY_RSP(message_p).pdn_addr.value,
create_sess_resp_pP->paa.ipv4_address,
NAS_PDN_CONNECTIVITY_RSP(message_p).pdn_addr.length);
NAS_PDN_CONNECTIVITY_RSP(message_p).pdn_addr.value[NAS_PDN_CONNECTIVITY_RSP(message_p).pdn_addr.length] = '0';
break;
case IPv6:
DevAssert(create_sess_resp_pP->paa.ipv6_prefix_length == 64); // NAS seems to only support 64 bits
NAS_PDN_CONNECTIVITY_RSP(message_p).pdn_addr.length = create_sess_resp_pP->paa.ipv6_prefix_length/8;
NAS_PDN_CONNECTIVITY_RSP(message_p).pdn_addr.value = malloc(NAS_PDN_CONNECTIVITY_RSP(message_p).pdn_addr.length+1);
DevAssert(NAS_PDN_CONNECTIVITY_RSP(message_p).pdn_addr.value != NULL);
memcpy(
NAS_PDN_CONNECTIVITY_RSP(message_p).pdn_addr.value,
create_sess_resp_pP->paa.ipv6_address,
NAS_PDN_CONNECTIVITY_RSP(message_p).pdn_addr.length);
NAS_PDN_CONNECTIVITY_RSP(message_p).pdn_addr.value[NAS_PDN_CONNECTIVITY_RSP(message_p).pdn_addr.length] = '0';
break;
case IPv4_AND_v6:
DevAssert(create_sess_resp_pP->paa.ipv6_prefix_length == 64); // NAS seems to only support 64 bits
NAS_PDN_CONNECTIVITY_RSP(message_p).pdn_addr.length = 4 + create_sess_resp_pP->paa.ipv6_prefix_length/8;
NAS_PDN_CONNECTIVITY_RSP(message_p).pdn_addr.value = malloc(NAS_PDN_CONNECTIVITY_RSP(message_p).pdn_addr.length+1);
DevAssert(NAS_PDN_CONNECTIVITY_RSP(message_p).pdn_addr.value != NULL);
memcpy(
NAS_PDN_CONNECTIVITY_RSP(message_p).pdn_addr.value,
create_sess_resp_pP->paa.ipv4_address,
4);
memcpy(
&NAS_PDN_CONNECTIVITY_RSP(message_p).pdn_addr.value[4],
create_sess_resp_pP->paa.ipv6_address,
create_sess_resp_pP->paa.ipv6_prefix_length/8);
NAS_PDN_CONNECTIVITY_RSP(message_p).pdn_addr.value[NAS_PDN_CONNECTIVITY_RSP(message_p).pdn_addr.length] = '0';
break;
case IPv4_OR_v6:
NAS_PDN_CONNECTIVITY_RSP(message_p).pdn_addr.length = 4;
NAS_PDN_CONNECTIVITY_RSP(message_p).pdn_addr.value = malloc(NAS_PDN_CONNECTIVITY_RSP(message_p).pdn_addr.length+1);
DevAssert(NAS_PDN_CONNECTIVITY_RSP(message_p).pdn_addr.value != NULL);
memcpy(
NAS_PDN_CONNECTIVITY_RSP(message_p).pdn_addr.value,
create_sess_resp_pP->paa.ipv4_address,
NAS_PDN_CONNECTIVITY_RSP(message_p).pdn_addr.length);
NAS_PDN_CONNECTIVITY_RSP(message_p).pdn_addr.value[NAS_PDN_CONNECTIVITY_RSP(message_p).pdn_addr.length] = '0';
break;
default:
DevAssert(0);
}
NAS_PDN_CONNECTIVITY_RSP(message_p).pdn_type = create_sess_resp_pP->paa.pdn_type;
NAS_PDN_CONNECTIVITY_RSP(message_p).proc_data = ue_context_p->pending_pdn_connectivity_req_proc_data; // NAS internal ref
ue_context_p->pending_pdn_connectivity_req_proc_data = NULL;
#warning "QOS hardcoded here" #warning "QOS hardcoded here"
//memcpy(&NAS_PDN_CONNECTIVITY_RSP(message_p).qos, //memcpy(&NAS_PDN_CONNECTIVITY_RSP(message_p).qos,
// &ue_context_p->pending_pdn_connectivity_req_qos, // &ue_context_p->pending_pdn_connectivity_req_qos,
// sizeof(network_qos_t)); // sizeof(network_qos_t));
NAS_PDN_CONNECTIVITY_RSP(message_p).qos.gbrUL = 64; /* 64=64kb/s Guaranteed Bit Rate for uplink */ NAS_PDN_CONNECTIVITY_RSP(message_p).qos.gbrUL = 64; /* 64=64kb/s Guaranteed Bit Rate for uplink */
NAS_PDN_CONNECTIVITY_RSP(message_p).qos.gbrDL = 120; /* 120=512kb/s Guaranteed Bit Rate for downlink */ NAS_PDN_CONNECTIVITY_RSP(message_p).qos.gbrDL = 120; /* 120=512kb/s Guaranteed Bit Rate for downlink */
NAS_PDN_CONNECTIVITY_RSP(message_p).qos.mbrUL = 72; /* 72=128kb/s Maximum Bit Rate for uplink */ NAS_PDN_CONNECTIVITY_RSP(message_p).qos.mbrUL = 72; /* 72=128kb/s Maximum Bit Rate for uplink */
NAS_PDN_CONNECTIVITY_RSP(message_p).qos.mbrDL = 135; /*135=1024kb/s Maximum Bit Rate for downlink */ NAS_PDN_CONNECTIVITY_RSP(message_p).qos.mbrDL = 135; /*135=1024kb/s Maximum Bit Rate for downlink */
NAS_PDN_CONNECTIVITY_RSP(message_p).qos.qci = 9; /* QoS Class Identifier */ NAS_PDN_CONNECTIVITY_RSP(message_p).qos.qci = 9; /* QoS Class Identifier */
NAS_PDN_CONNECTIVITY_RSP(message_p).request_type = ue_context_p->pending_pdn_connectivity_req_request_type; // NAS internal ref NAS_PDN_CONNECTIVITY_RSP(message_p).request_type = ue_context_p->pending_pdn_connectivity_req_request_type; // NAS internal ref
ue_context_p->pending_pdn_connectivity_req_request_type = 0; ue_context_p->pending_pdn_connectivity_req_request_type = 0;
// here at this point OctetString are saved in resp, no loss of memory (apn, pdn_addr) // here at this point OctetString are saved in resp, no loss of memory (apn, pdn_addr)
NAS_PDN_CONNECTIVITY_RSP(message_p).eNB_ue_s1ap_id = ue_context_p->eNB_ue_s1ap_id; NAS_PDN_CONNECTIVITY_RSP(message_p).eNB_ue_s1ap_id = ue_context_p->eNB_ue_s1ap_id;
NAS_PDN_CONNECTIVITY_RSP(message_p).mme_ue_s1ap_id = ue_context_p->mme_ue_s1ap_id; NAS_PDN_CONNECTIVITY_RSP(message_p).mme_ue_s1ap_id = ue_context_p->mme_ue_s1ap_id;
NAS_PDN_CONNECTIVITY_RSP(message_p).ebi = bearer_id; NAS_PDN_CONNECTIVITY_RSP(message_p).ebi = bearer_id;
NAS_PDN_CONNECTIVITY_RSP(message_p).qci = current_bearer_p->qci; NAS_PDN_CONNECTIVITY_RSP(message_p).qci = current_bearer_p->qci;
NAS_PDN_CONNECTIVITY_RSP(message_p).prio_level = current_bearer_p->prio_level; NAS_PDN_CONNECTIVITY_RSP(message_p).prio_level = current_bearer_p->prio_level;
NAS_PDN_CONNECTIVITY_RSP(message_p).pre_emp_vulnerability = current_bearer_p->pre_emp_vulnerability; NAS_PDN_CONNECTIVITY_RSP(message_p).pre_emp_vulnerability = current_bearer_p->pre_emp_vulnerability;
NAS_PDN_CONNECTIVITY_RSP(message_p).pre_emp_capability = current_bearer_p->pre_emp_capability; NAS_PDN_CONNECTIVITY_RSP(message_p).pre_emp_capability = current_bearer_p->pre_emp_capability;
NAS_PDN_CONNECTIVITY_RSP(message_p).sgw_s1u_teid = current_bearer_p->s_gw_teid; NAS_PDN_CONNECTIVITY_RSP(message_p).sgw_s1u_teid = current_bearer_p->s_gw_teid;
memcpy(&NAS_PDN_CONNECTIVITY_RSP(message_p).sgw_s1u_address, memcpy(&NAS_PDN_CONNECTIVITY_RSP(message_p).sgw_s1u_address,
&current_bearer_p->s_gw_address, sizeof(ip_address_t)); &current_bearer_p->s_gw_address, sizeof(ip_address_t));
NAS_PDN_CONNECTIVITY_RSP(message_p).ambr.br_ul = ue_context_p->subscribed_ambr.br_ul; NAS_PDN_CONNECTIVITY_RSP(message_p).ambr.br_ul = ue_context_p->subscribed_ambr.br_ul;
NAS_PDN_CONNECTIVITY_RSP(message_p).ambr.br_dl = ue_context_p->subscribed_ambr.br_dl; NAS_PDN_CONNECTIVITY_RSP(message_p).ambr.br_dl = ue_context_p->subscribed_ambr.br_dl;
return itti_send_msg_to_task(TASK_NAS_MME, INSTANCE_DEFAULT, message_p); return itti_send_msg_to_task(TASK_NAS_MME, INSTANCE_DEFAULT, message_p);
} }
return 0; return 0;
} }
void void
mme_app_handle_initial_context_setup_rsp( mme_app_handle_initial_context_setup_rsp(
const mme_app_initial_context_setup_rsp_t * const initial_ctxt_setup_rsp_pP) const mme_app_initial_context_setup_rsp_t * const initial_ctxt_setup_rsp_pP)
{ {
struct ue_context_s *ue_context_p = NULL; struct ue_context_s *ue_context_p = NULL;
MessageDef *message_p = NULL; MessageDef *message_p = NULL;
task_id_t to_task = TASK_UNKNOWN; task_id_t to_task = TASK_UNKNOWN;
MME_APP_DEBUG("Received MME_APP_INITIAL_CONTEXT_SETUP_RSP from S1AP\n"); MME_APP_DEBUG("Received MME_APP_INITIAL_CONTEXT_SETUP_RSP from S1AP\n");
ue_context_p = mme_ue_context_exists_mme_ue_s1ap_id( ue_context_p = mme_ue_context_exists_mme_ue_s1ap_id(
&mme_app_desc.mme_ue_contexts, &mme_app_desc.mme_ue_contexts,
initial_ctxt_setup_rsp_pP->mme_ue_s1ap_id); initial_ctxt_setup_rsp_pP->mme_ue_s1ap_id);
if (ue_context_p == NULL) {
MME_APP_DEBUG("We didn't find this mme_ue_s1ap_id in list of UE: %08x %d(dec)\n", if (ue_context_p == NULL) {
initial_ctxt_setup_rsp_pP->mme_ue_s1ap_id, MME_APP_DEBUG("We didn't find this mme_ue_s1ap_id in list of UE: %08x %d(dec)\n",
initial_ctxt_setup_rsp_pP->mme_ue_s1ap_id); initial_ctxt_setup_rsp_pP->mme_ue_s1ap_id,
return; initial_ctxt_setup_rsp_pP->mme_ue_s1ap_id);
} return;
}
#if !defined(ENABLE_STANDALONE_EPC) #if !defined(ENABLE_STANDALONE_EPC)
to_task = TASK_S11; to_task = TASK_S11;
@@ -672,29 +704,29 @@ mme_app_handle_initial_context_setup_rsp(
message_p = itti_alloc_new_message(TASK_MME_APP, SGW_MODIFY_BEARER_REQUEST); message_p = itti_alloc_new_message(TASK_MME_APP, SGW_MODIFY_BEARER_REQUEST);
AssertFatal(message_p != NULL, "itti_alloc_new_message Failed"); AssertFatal(message_p != NULL, "itti_alloc_new_message Failed");
memset((void*)&message_p->ittiMsg.sgwModifyBearerRequest, memset((void*)&message_p->ittiMsg.sgwModifyBearerRequest,
0, 0,
sizeof(SgwModifyBearerRequest)); sizeof(SgwModifyBearerRequest));
SGW_MODIFY_BEARER_REQUEST(message_p).teid = ue_context_p->sgw_s11_teid; SGW_MODIFY_BEARER_REQUEST(message_p).teid = ue_context_p->sgw_s11_teid;
/* Delay Value in integer multiples of 50 millisecs, or zero */ /* Delay Value in integer multiples of 50 millisecs, or zero */
SGW_MODIFY_BEARER_REQUEST(message_p).delay_dl_packet_notif_req = 0; // TO DO SGW_MODIFY_BEARER_REQUEST(message_p).delay_dl_packet_notif_req = 0; // TO DO
SGW_MODIFY_BEARER_REQUEST(message_p).bearer_context_to_modify.eps_bearer_id = initial_ctxt_setup_rsp_pP->eps_bearer_id; SGW_MODIFY_BEARER_REQUEST(message_p).bearer_context_to_modify.eps_bearer_id = initial_ctxt_setup_rsp_pP->eps_bearer_id;
memcpy(&SGW_MODIFY_BEARER_REQUEST(message_p).bearer_context_to_modify.s1_eNB_fteid, memcpy(&SGW_MODIFY_BEARER_REQUEST(message_p).bearer_context_to_modify.s1_eNB_fteid,
&initial_ctxt_setup_rsp_pP->bearer_s1u_enb_fteid, &initial_ctxt_setup_rsp_pP->bearer_s1u_enb_fteid,
sizeof(SGW_MODIFY_BEARER_REQUEST(message_p).bearer_context_to_modify.s1_eNB_fteid)); sizeof(SGW_MODIFY_BEARER_REQUEST(message_p).bearer_context_to_modify.s1_eNB_fteid));
SGW_MODIFY_BEARER_REQUEST(message_p).mme_fq_csid.node_id_type = GLOBAL_UNICAST_IPv4; // TO DO SGW_MODIFY_BEARER_REQUEST(message_p).mme_fq_csid.node_id_type = GLOBAL_UNICAST_IPv4; // TO DO
SGW_MODIFY_BEARER_REQUEST(message_p).mme_fq_csid.csid = 0; // TO DO ... SGW_MODIFY_BEARER_REQUEST(message_p).mme_fq_csid.csid = 0; // TO DO ...
SGW_MODIFY_BEARER_REQUEST(message_p).indication_flags = 0; // TO DO SGW_MODIFY_BEARER_REQUEST(message_p).indication_flags = 0; // TO DO
SGW_MODIFY_BEARER_REQUEST(message_p).rat_type = RAT_EUTRAN; SGW_MODIFY_BEARER_REQUEST(message_p).rat_type = RAT_EUTRAN;
/* S11 stack specific parameter. Not used in standalone epc mode */ /* S11 stack specific parameter. Not used in standalone epc mode */
SGW_MODIFY_BEARER_REQUEST(message_p).trxn = NULL; SGW_MODIFY_BEARER_REQUEST(message_p).trxn = NULL;
itti_send_msg_to_task(to_task, INSTANCE_DEFAULT, message_p); itti_send_msg_to_task(to_task, INSTANCE_DEFAULT, message_p);
} }
+1 -1
View File
@@ -51,7 +51,7 @@
int int
mme_app_handle_s1ap_ue_capabilities_ind( mme_app_handle_s1ap_ue_capabilities_ind(
const s1ap_ue_cap_ind_t const * s1ap_ue_cap_ind_pP) const s1ap_ue_cap_ind_t const * s1ap_ue_cap_ind_pP)
{ {
DevAssert(s1ap_ue_cap_ind_pP != NULL); DevAssert(s1ap_ue_cap_ind_pP != NULL);
//unsigned eNB_ue_s1ap_id:24; //unsigned eNB_ue_s1ap_id:24;
+199 -177
View File
@@ -41,7 +41,8 @@
#include <libconfig.h> #include <libconfig.h>
#include "mme_app_config.h" #include "mme_app_config.h"
int mme_app_config_init(char* lib_config_file_name_pP, mme_app_config_t* config_pP) { int mme_app_config_init(char* lib_config_file_name_pP, mme_app_config_t* config_pP)
{
config_t cfg; config_t cfg;
config_setting_t *setting_sgw = NULL; config_setting_t *setting_sgw = NULL;
@@ -85,201 +86,222 @@ int mme_app_config_init(char* lib_config_file_name_pP, mme_app_config_t* config_
config_init(&cfg); config_init(&cfg);
if(lib_config_file_name_pP != NULL) if(lib_config_file_name_pP != NULL) {
{ /* Read the file. If there is an error, report it and exit. */
/* Read the file. If there is an error, report it and exit. */ if(! config_read_file(&cfg, lib_config_file_name_pP)) {
if(! config_read_file(&cfg, lib_config_file_name_pP)) MME_APP_ERROR("%s:%d - %s\n", lib_config_file_name_pP, config_error_line(&cfg), config_error_text(&cfg));
{
MME_APP_ERROR("%s:%d - %s\n", lib_config_file_name_pP, config_error_line(&cfg), config_error_text(&cfg));
config_destroy(&cfg);
AssertFatal (1 == 0, "Failed to parse eNB configuration file %s!\n", lib_config_file_name_pP);
}
}
else
{
SPGW_APP_ERROR("No SP-GW configuration file provided!\n");
config_destroy(&cfg); config_destroy(&cfg);
AssertFatal (0, "No SP-GW configuration file provided!\n"); AssertFatal (1 == 0, "Failed to parse eNB configuration file %s!\n", lib_config_file_name_pP);
}
} else {
SPGW_APP_ERROR("No SP-GW configuration file provided!\n");
config_destroy(&cfg);
AssertFatal (0, "No SP-GW configuration file provided!\n");
} }
setting_sgw = config_lookup(&cfg, SGW_CONFIG_STRING_SGW_CONFIG); setting_sgw = config_lookup(&cfg, SGW_CONFIG_STRING_SGW_CONFIG);
if(setting_sgw != NULL) { if(setting_sgw != NULL) {
subsetting = config_setting_get_member (setting_sgw, SGW_CONFIG_STRING_NETWORK_INTERFACES_CONFIG); subsetting = config_setting_get_member (setting_sgw, SGW_CONFIG_STRING_NETWORK_INTERFACES_CONFIG);
if(subsetting != NULL) {
if( (
config_setting_lookup_string( subsetting, SGW_CONFIG_STRING_SGW_INTERFACE_NAME_FOR_S1U_S12_S4_UP, (const char **)&sgw_interface_name_for_S1u_S12_S4_up)
&& config_setting_lookup_string( subsetting, SGW_CONFIG_STRING_SGW_IPV4_ADDRESS_FOR_S1U_S12_S4_UP, (const char **)&sgw_ipv4_address_for_S1u_S12_S4_up)
&& config_setting_lookup_string( subsetting, SGW_CONFIG_STRING_SGW_INTERFACE_NAME_FOR_S5_S8_UP, (const char **)&sgw_interface_name_for_S5_S8_up)
&& config_setting_lookup_string( subsetting, SGW_CONFIG_STRING_SGW_IPV4_ADDRESS_FOR_S5_S8_UP, (const char **)&sgw_ipv4_address_for_S5_S8_up)
&& config_setting_lookup_string( subsetting, SGW_CONFIG_STRING_SGW_INTERFACE_NAME_FOR_S11, (const char **)&sgw_interface_name_for_S11)
&& config_setting_lookup_string( subsetting, SGW_CONFIG_STRING_SGW_IPV4_ADDRESS_FOR_S11, (const char **)&sgw_ipv4_address_for_S11)
)
) {
config_pP->sgw_config.ipv4.sgw_interface_name_for_S1u_S12_S4_up = strdup(sgw_interface_name_for_S1u_S12_S4_up);
cidr = strdup(sgw_ipv4_address_for_S1u_S12_S4_up);
address = strtok(cidr, "/");
mask = strtok(NULL, "/");
IPV4_STR_ADDR_TO_INT_NWBO ( address, config_pP->sgw_config.ipv4.sgw_ipv4_address_for_S1u_S12_S4_up, "BAD IP ADDRESS FORMAT FOR S1u_S12_S4 !\n" )
config_pP->sgw_config.ipv4.sgw_ip_netmask_for_S1u_S12_S4_up = atoi(mask);
free(cidr);
config_pP->sgw_config.ipv4.sgw_interface_name_for_S5_S8_up = strdup(sgw_interface_name_for_S5_S8_up); if(subsetting != NULL) {
cidr = strdup(sgw_ipv4_address_for_S5_S8_up); if( (
address = strtok(cidr, "/"); config_setting_lookup_string( subsetting, SGW_CONFIG_STRING_SGW_INTERFACE_NAME_FOR_S1U_S12_S4_UP, (const char **)&sgw_interface_name_for_S1u_S12_S4_up)
mask = strtok(NULL, "/"); && config_setting_lookup_string( subsetting, SGW_CONFIG_STRING_SGW_IPV4_ADDRESS_FOR_S1U_S12_S4_UP, (const char **)&sgw_ipv4_address_for_S1u_S12_S4_up)
IPV4_STR_ADDR_TO_INT_NWBO ( address, config_pP->sgw_config.ipv4.sgw_ipv4_address_for_S5_S8_up, "BAD IP ADDRESS FORMAT FOR S5_S8 !\n" ) && config_setting_lookup_string( subsetting, SGW_CONFIG_STRING_SGW_INTERFACE_NAME_FOR_S5_S8_UP, (const char **)&sgw_interface_name_for_S5_S8_up)
config_pP->sgw_config.ipv4.sgw_ip_netmask_for_S5_S8_up = atoi(mask); && config_setting_lookup_string( subsetting, SGW_CONFIG_STRING_SGW_IPV4_ADDRESS_FOR_S5_S8_UP, (const char **)&sgw_ipv4_address_for_S5_S8_up)
free(cidr); && config_setting_lookup_string( subsetting, SGW_CONFIG_STRING_SGW_INTERFACE_NAME_FOR_S11, (const char **)&sgw_interface_name_for_S11)
&& config_setting_lookup_string( subsetting, SGW_CONFIG_STRING_SGW_IPV4_ADDRESS_FOR_S11, (const char **)&sgw_ipv4_address_for_S11)
)
) {
config_pP->sgw_config.ipv4.sgw_interface_name_for_S1u_S12_S4_up = strdup(sgw_interface_name_for_S1u_S12_S4_up);
cidr = strdup(sgw_ipv4_address_for_S1u_S12_S4_up);
address = strtok(cidr, "/");
mask = strtok(NULL, "/");
IPV4_STR_ADDR_TO_INT_NWBO ( address, config_pP->sgw_config.ipv4.sgw_ipv4_address_for_S1u_S12_S4_up, "BAD IP ADDRESS FORMAT FOR S1u_S12_S4 !\n" )
config_pP->sgw_config.ipv4.sgw_ip_netmask_for_S1u_S12_S4_up = atoi(mask);
free(cidr);
config_pP->sgw_config.ipv4.sgw_interface_name_for_S11 = strdup(sgw_interface_name_for_S11); config_pP->sgw_config.ipv4.sgw_interface_name_for_S5_S8_up = strdup(sgw_interface_name_for_S5_S8_up);
cidr = strdup(sgw_ipv4_address_for_S11); cidr = strdup(sgw_ipv4_address_for_S5_S8_up);
address = strtok(cidr, "/"); address = strtok(cidr, "/");
mask = strtok(NULL, "/"); mask = strtok(NULL, "/");
IPV4_STR_ADDR_TO_INT_NWBO ( address, config_pP->sgw_config.ipv4.sgw_ipv4_address_for_S11, "BAD IP ADDRESS FORMAT FOR S11 !\n" ) IPV4_STR_ADDR_TO_INT_NWBO ( address, config_pP->sgw_config.ipv4.sgw_ipv4_address_for_S5_S8_up, "BAD IP ADDRESS FORMAT FOR S5_S8 !\n" )
config_pP->sgw_config.ipv4.sgw_ip_netmask_for_S11 = atoi(mask); config_pP->sgw_config.ipv4.sgw_ip_netmask_for_S5_S8_up = atoi(mask);
free(cidr); free(cidr);
}
config_pP->sgw_config.ipv4.sgw_interface_name_for_S11 = strdup(sgw_interface_name_for_S11);
cidr = strdup(sgw_ipv4_address_for_S11);
address = strtok(cidr, "/");
mask = strtok(NULL, "/");
IPV4_STR_ADDR_TO_INT_NWBO ( address, config_pP->sgw_config.ipv4.sgw_ipv4_address_for_S11, "BAD IP ADDRESS FORMAT FOR S11 !\n" )
config_pP->sgw_config.ipv4.sgw_ip_netmask_for_S11 = atoi(mask);
free(cidr);
} }
}
} }
setting_pgw = config_lookup(&cfg, PGW_CONFIG_STRING_PGW_CONFIG); setting_pgw = config_lookup(&cfg, PGW_CONFIG_STRING_PGW_CONFIG);
if(setting_pgw != NULL)
{
subsetting = config_setting_get_member (setting_pgw, SGW_CONFIG_STRING_NETWORK_INTERFACES_CONFIG);
if(subsetting != NULL) {
if( (
config_setting_lookup_string(subsetting,
PGW_CONFIG_STRING_PGW_INTERFACE_NAME_FOR_S5_S8,
(const char **)&pgw_interface_name_for_S5_S8)
&& config_setting_lookup_string(subsetting,
PGW_CONFIG_STRING_PGW_IPV4_ADDRESS_FOR_S5_S8,
(const char **)&pgw_ipv4_address_for_S5_S8)
&& config_setting_lookup_string(subsetting,
PGW_CONFIG_STRING_PGW_INTERFACE_NAME_FOR_SGI,
(const char **)&pgw_interface_name_for_SGI)
&& config_setting_lookup_string(subsetting,
PGW_CONFIG_STRING_PGW_IPV4_ADDR_FOR_SGI,
(const char **)&pgw_ipv4_address_for_SGI)
)
) {
config_pP->pgw_config.ipv4.pgw_interface_name_for_S5_S8 = strdup(pgw_interface_name_for_S5_S8);
cidr = strdup(pgw_ipv4_address_for_S5_S8);
address = strtok(cidr, "/");
mask = strtok(NULL, "/");
IPV4_STR_ADDR_TO_INT_NWBO ( address, config_pP->pgw_config.ipv4.pgw_ipv4_address_for_S5_S8, "BAD IP ADDRESS FORMAT FOR S5_S8 !\n" )
config_pP->pgw_config.ipv4.pgw_ip_netmask_for_S5_S8 = atoi(mask);
free(cidr);
config_pP->pgw_config.ipv4.pgw_interface_name_for_SGI = strdup(pgw_interface_name_for_SGI); if(setting_pgw != NULL) {
cidr = strdup(pgw_ipv4_address_for_SGI); subsetting = config_setting_get_member (setting_pgw, SGW_CONFIG_STRING_NETWORK_INTERFACES_CONFIG);
address = strtok(cidr, "/");
mask = strtok(NULL, "/"); if(subsetting != NULL) {
IPV4_STR_ADDR_TO_INT_NWBO ( address, config_pP->pgw_config.ipv4.pgw_ipv4_address_for_SGI, "BAD IP ADDRESS FORMAT FOR SGI !\n" ) if( (
config_pP->pgw_config.ipv4.pgw_ip_netmask_for_SGI = atoi(mask); config_setting_lookup_string(subsetting,
free(cidr); PGW_CONFIG_STRING_PGW_INTERFACE_NAME_FOR_S5_S8,
} (const char **)&pgw_interface_name_for_S5_S8)
&& config_setting_lookup_string(subsetting,
PGW_CONFIG_STRING_PGW_IPV4_ADDRESS_FOR_S5_S8,
(const char **)&pgw_ipv4_address_for_S5_S8)
&& config_setting_lookup_string(subsetting,
PGW_CONFIG_STRING_PGW_INTERFACE_NAME_FOR_SGI,
(const char **)&pgw_interface_name_for_SGI)
&& config_setting_lookup_string(subsetting,
PGW_CONFIG_STRING_PGW_IPV4_ADDR_FOR_SGI,
(const char **)&pgw_ipv4_address_for_SGI)
)
) {
config_pP->pgw_config.ipv4.pgw_interface_name_for_S5_S8 = strdup(pgw_interface_name_for_S5_S8);
cidr = strdup(pgw_ipv4_address_for_S5_S8);
address = strtok(cidr, "/");
mask = strtok(NULL, "/");
IPV4_STR_ADDR_TO_INT_NWBO ( address, config_pP->pgw_config.ipv4.pgw_ipv4_address_for_S5_S8, "BAD IP ADDRESS FORMAT FOR S5_S8 !\n" )
config_pP->pgw_config.ipv4.pgw_ip_netmask_for_S5_S8 = atoi(mask);
free(cidr);
config_pP->pgw_config.ipv4.pgw_interface_name_for_SGI = strdup(pgw_interface_name_for_SGI);
cidr = strdup(pgw_ipv4_address_for_SGI);
address = strtok(cidr, "/");
mask = strtok(NULL, "/");
IPV4_STR_ADDR_TO_INT_NWBO ( address, config_pP->pgw_config.ipv4.pgw_ipv4_address_for_SGI, "BAD IP ADDRESS FORMAT FOR SGI !\n" )
config_pP->pgw_config.ipv4.pgw_ip_netmask_for_SGI = atoi(mask);
free(cidr);
} }
subsetting = config_setting_get_member (setting_pgw, PGW_CONFIG_STRING_IP_ADDRESS_POOL); }
if(subsetting != NULL) {
sub2setting = config_setting_get_member (subsetting, PGW_CONFIG_STRING_IPV4_ADDRESS_LIST); subsetting = config_setting_get_member (setting_pgw, PGW_CONFIG_STRING_IP_ADDRESS_POOL);
if(sub2setting != NULL) {
num = config_setting_length(sub2setting); if(subsetting != NULL) {
for (i = 0; i < num; i++) { sub2setting = config_setting_get_member (subsetting, PGW_CONFIG_STRING_IPV4_ADDRESS_LIST);
astring = config_setting_get_string_elem(sub2setting,i);
if (astring != NULL) { if(sub2setting != NULL) {
trim(astring, strlen(astring)+1); num = config_setting_length(sub2setting);
if (inet_pton(AF_INET, astring, buf_in_addr) < 1) {
// failure, test if there is a range specified in the string for (i = 0; i < num; i++) {
atoken = strtok(astring, PGW_CONFIG_STRING_IP_ADDRESS_RANGE_DELIMITERS); astring = config_setting_get_string_elem(sub2setting,i);
if (inet_pton(AF_INET, astring, buf_in_addr) == 1) {
memcpy (&addr_start, buf_in_addr, sizeof(struct in_addr)); if (astring != NULL) {
// valid address trim(astring, strlen(astring)+1);
atoken2 = strtok(NULL, PGW_CONFIG_STRING_IP_ADDRESS_RANGE_DELIMITERS);
if (inet_pton(AF_INET, atoken2, buf_in_addr) == 1) { if (inet_pton(AF_INET, astring, buf_in_addr) < 1) {
memcpy (&addr_end, buf_in_addr, sizeof(struct in_addr)); // failure, test if there is a range specified in the string
// valid address atoken = strtok(astring, PGW_CONFIG_STRING_IP_ADDRESS_RANGE_DELIMITERS);
for (jh = ntohl(addr_start.s_addr); jh <= ntohl(addr_end.s_addr); jh++) {
DevAssert(PGW_MAX_ALLOCATED_PDN_ADDRESSES > config_pP->pgw_config.pool_pdn_addresses.num_ipv4_addresses); if (inet_pton(AF_INET, astring, buf_in_addr) == 1) {
jn = htonl(jh); memcpy (&addr_start, buf_in_addr, sizeof(struct in_addr));
if (IN_CLASSA(addr_start.s_addr)) { // valid address
if ((jh & 0xFF) && (jh & 0xFF) != 0xFF) { atoken2 = strtok(NULL, PGW_CONFIG_STRING_IP_ADDRESS_RANGE_DELIMITERS);
config_pP->pgw_config.pool_pdn_addresses.ipv4_addresses[config_pP->pgw_config.pool_pdn_addresses.num_ipv4_addresses++].s_addr = jn;
} if (inet_pton(AF_INET, atoken2, buf_in_addr) == 1) {
} else if (IN_CLASSB(addr_start.s_addr)) { memcpy (&addr_end, buf_in_addr, sizeof(struct in_addr));
if ((jh & 0xFF) && (jh & 0xFF) != 0xFF) {
config_pP->pgw_config.pool_pdn_addresses.ipv4_addresses[config_pP->pgw_config.pool_pdn_addresses.num_ipv4_addresses++].s_addr = jn; // valid address
} for (jh = ntohl(addr_start.s_addr); jh <= ntohl(addr_end.s_addr); jh++) {
} else if (IN_CLASSC(addr_start.s_addr)) { DevAssert(PGW_MAX_ALLOCATED_PDN_ADDRESSES > config_pP->pgw_config.pool_pdn_addresses.num_ipv4_addresses);
if ((jh & 0xFF) && (jh & 0xFF) != 0xFF) { jn = htonl(jh);
config_pP->pgw_config.pool_pdn_addresses.ipv4_addresses[config_pP->pgw_config.pool_pdn_addresses.num_ipv4_addresses++].s_addr = jn;
} if (IN_CLASSA(addr_start.s_addr)) {
} else { if ((jh & 0xFF) && (jh & 0xFF) != 0xFF) {
printf("ERROR ON ADDRESS CLASS %d.%d.%d.%d\n", NIPADDR(jn)); config_pP->pgw_config.pool_pdn_addresses.ipv4_addresses[config_pP->pgw_config.pool_pdn_addresses.num_ipv4_addresses++].s_addr = jn;
}
}
}
}
} else {
DevAssert(PGW_MAX_ALLOCATED_PDN_ADDRESSES > config_pP->pgw_config.pool_pdn_addresses.num_ipv4_addresses);
memcpy (&addr_start, buf_in_addr, sizeof(struct in_addr));
config_pP->pgw_config.pool_pdn_addresses.ipv4_addresses[config_pP->pgw_config.pool_pdn_addresses.num_ipv4_addresses++].s_addr = addr_start.s_addr;
} }
} } else if (IN_CLASSB(addr_start.s_addr)) {
} if ((jh & 0xFF) && (jh & 0xFF) != 0xFF) {
} config_pP->pgw_config.pool_pdn_addresses.ipv4_addresses[config_pP->pgw_config.pool_pdn_addresses.num_ipv4_addresses++].s_addr = jn;
sub2setting = config_setting_get_member (subsetting, PGW_CONFIG_STRING_IPV6_ADDRESS_LIST);
if(sub2setting != NULL) {
num = config_setting_length(sub2setting);
for (i = 0; i < num; i++) {
astring = config_setting_get_string_elem(sub2setting,i);
if (astring != NULL) {
trim(astring, strlen(astring)+1);
if (inet_pton(AF_INET6, astring, buf_in6_addr) < 1) {
// failure, test if there is a range specified in the string
atoken = strtok(astring, PGW_CONFIG_STRING_IPV6_PREFIX_DELIMITER);
if (inet_pton(AF_INET6, astring, buf_in6_addr) == 1) {
atoken2 = strtok(NULL, PGW_CONFIG_STRING_IPV6_PREFIX_DELIMITER);
prefix_mask = atoi(atoken2);
// arbitrary values
DevAssert((prefix_mask < 128) && (prefix_mask >= 64));
memcpy (&addr6_start, buf_in6_addr, sizeof(struct in6_addr));
memcpy (&addr6_mask, buf_in6_addr, sizeof(struct in6_addr));
sgw_ipv6_mask_in6_addr(&addr6_mask, prefix_mask);
if (memcmp(&addr6_start, &addr6_mask, sizeof(struct in6_addr)) != 0) {
AssertFatal(0, "BAD IPV6 ADDR CONFIG/MASK PAIRING %s/%d\n", astring, prefix_mask);
}
counter64 = 0xFFFFFFFFFFFFFFFF >> prefix_mask; // address Prefix_mask/0..0 not valid
do {
addr6_start.s6_addr32[3] = addr6_start.s6_addr32[3] + htonl(1);
if (addr6_start.s6_addr32[3] == 0) {
addr6_start.s6_addr32[2] = addr6_start.s6_addr32[2] + htonl(1);
if (addr6_start.s6_addr32[2] == 0) {
// should not happen since mask is no less than 64
addr6_start.s6_addr32[1] = addr6_start.s6_addr32[1] + htonl(1);
if (addr6_start.s6_addr32[1] == 0) {
addr6_start.s6_addr32[0] = addr6_start.s6_addr32[0] + htonl(1);
}
}
}
memcpy (&config_pP->pgw_config.pool_pdn_addresses.ipv6_addresses[config_pP->pgw_config.pool_pdn_addresses.num_ipv6_addresses++],
&addr6_start,
sizeof(struct in6_addr));
counter64 = counter64 - 1;
} while (counter64 > 0);
}
} else {
DevAssert(PGW_MAX_ALLOCATED_PDN_ADDRESSES > config_pP->pgw_config.pool_pdn_addresses.num_ipv6_addresses);
memcpy (&config_pP->pgw_config.pool_pdn_addresses.ipv6_addresses[config_pP->pgw_config.pool_pdn_addresses.num_ipv6_addresses++],
buf_in6_addr,
sizeof(struct in6_addr));
} }
} else if (IN_CLASSC(addr_start.s_addr)) {
if ((jh & 0xFF) && (jh & 0xFF) != 0xFF) {
config_pP->pgw_config.pool_pdn_addresses.ipv4_addresses[config_pP->pgw_config.pool_pdn_addresses.num_ipv4_addresses++].s_addr = jn;
}
} else {
printf("ERROR ON ADDRESS CLASS %d.%d.%d.%d\n", NIPADDR(jn));
}
} }
}
} }
} else {
DevAssert(PGW_MAX_ALLOCATED_PDN_ADDRESSES > config_pP->pgw_config.pool_pdn_addresses.num_ipv4_addresses);
memcpy (&addr_start, buf_in_addr, sizeof(struct in_addr));
config_pP->pgw_config.pool_pdn_addresses.ipv4_addresses[config_pP->pgw_config.pool_pdn_addresses.num_ipv4_addresses++].s_addr = addr_start.s_addr;
}
} }
}
} }
sub2setting = config_setting_get_member (subsetting, PGW_CONFIG_STRING_IPV6_ADDRESS_LIST);
if(sub2setting != NULL) {
num = config_setting_length(sub2setting);
for (i = 0; i < num; i++) {
astring = config_setting_get_string_elem(sub2setting,i);
if (astring != NULL) {
trim(astring, strlen(astring)+1);
if (inet_pton(AF_INET6, astring, buf_in6_addr) < 1) {
// failure, test if there is a range specified in the string
atoken = strtok(astring, PGW_CONFIG_STRING_IPV6_PREFIX_DELIMITER);
if (inet_pton(AF_INET6, astring, buf_in6_addr) == 1) {
atoken2 = strtok(NULL, PGW_CONFIG_STRING_IPV6_PREFIX_DELIMITER);
prefix_mask = atoi(atoken2);
// arbitrary values
DevAssert((prefix_mask < 128) && (prefix_mask >= 64));
memcpy (&addr6_start, buf_in6_addr, sizeof(struct in6_addr));
memcpy (&addr6_mask, buf_in6_addr, sizeof(struct in6_addr));
sgw_ipv6_mask_in6_addr(&addr6_mask, prefix_mask);
if (memcmp(&addr6_start, &addr6_mask, sizeof(struct in6_addr)) != 0) {
AssertFatal(0, "BAD IPV6 ADDR CONFIG/MASK PAIRING %s/%d\n", astring, prefix_mask);
}
counter64 = 0xFFFFFFFFFFFFFFFF >> prefix_mask; // address Prefix_mask/0..0 not valid
do {
addr6_start.s6_addr32[3] = addr6_start.s6_addr32[3] + htonl(1);
if (addr6_start.s6_addr32[3] == 0) {
addr6_start.s6_addr32[2] = addr6_start.s6_addr32[2] + htonl(1);
if (addr6_start.s6_addr32[2] == 0) {
// should not happen since mask is no less than 64
addr6_start.s6_addr32[1] = addr6_start.s6_addr32[1] + htonl(1);
if (addr6_start.s6_addr32[1] == 0) {
addr6_start.s6_addr32[0] = addr6_start.s6_addr32[0] + htonl(1);
}
}
}
memcpy (&config_pP->pgw_config.pool_pdn_addresses.ipv6_addresses[config_pP->pgw_config.pool_pdn_addresses.num_ipv6_addresses++],
&addr6_start,
sizeof(struct in6_addr));
counter64 = counter64 - 1;
} while (counter64 > 0);
}
} else {
DevAssert(PGW_MAX_ALLOCATED_PDN_ADDRESSES > config_pP->pgw_config.pool_pdn_addresses.num_ipv6_addresses);
memcpy (&config_pP->pgw_config.pool_pdn_addresses.ipv6_addresses[config_pP->pgw_config.pool_pdn_addresses.num_ipv6_addresses++],
buf_in6_addr,
sizeof(struct in6_addr));
}
}
}
}
}
} }
return 0; return 0;
} }
+288 -276
View File
@@ -51,7 +51,7 @@
#include "mme_app_defs.h" #include "mme_app_defs.h"
static inline int ue_context_compare_identifiers(struct ue_context_s *p1, static inline int ue_context_compare_identifiers(struct ue_context_s *p1,
struct ue_context_s *p2); struct ue_context_s *p2);
RB_PROTOTYPE(ue_context_map, ue_context_s, rb_entry, RB_PROTOTYPE(ue_context_map, ue_context_s, rb_entry,
ue_context_compare_identifiers); ue_context_compare_identifiers);
@@ -60,348 +60,360 @@ RB_GENERATE(ue_context_map, ue_context_s, rb_entry,
ue_context_compare_identifiers); ue_context_compare_identifiers);
static inline int ue_context_compare_identifiers( static inline int ue_context_compare_identifiers(
struct ue_context_s *p1, struct ue_context_s *p2) struct ue_context_s *p1, struct ue_context_s *p2)
{ {
MME_APP_DEBUG(" ue_context_compare_identifiers IMSI %"SCNu64"\n", p1->imsi); MME_APP_DEBUG(" ue_context_compare_identifiers IMSI %"SCNu64"\n", p1->imsi);
MME_APP_DEBUG(" ue_context_compare_identifiers mme_s11_teid %08x\n" , p1->mme_s11_teid); MME_APP_DEBUG(" ue_context_compare_identifiers mme_s11_teid %08x\n" , p1->mme_s11_teid);
MME_APP_DEBUG(" ue_context_compare_identifiers mme_ue_s1ap_id %08x\n" , p1->mme_ue_s1ap_id); MME_APP_DEBUG(" ue_context_compare_identifiers mme_ue_s1ap_id %08x\n" , p1->mme_ue_s1ap_id);
MME_APP_DEBUG(" ue_context_compare_identifiers ue_id %08x\n" , p1->ue_id); MME_APP_DEBUG(" ue_context_compare_identifiers ue_id %08x\n" , p1->ue_id);
if (p1->imsi > 0) { if (p1->imsi > 0) {
/* if IMSI provided */ /* if IMSI provided */
if (p1->imsi > p2->imsi) { if (p1->imsi > p2->imsi) {
return 1; return 1;
}
if (p1->imsi < p2->imsi) {
return -1;
}
} else if (p1->mme_s11_teid > 0) {
/* if s11 teid provided */
if (p1->mme_s11_teid > p2->mme_s11_teid) {
return 1;
}
if (p1->mme_s11_teid < p2->mme_s11_teid) {
return -1;
}
} else if (p1->mme_ue_s1ap_id > 0) {
MME_APP_DEBUG(" with mme_ue_s1ap_id %d\n" , p2->mme_ue_s1ap_id);
/* if s1ap ue id provided */
if (p1->mme_ue_s1ap_id > p2->mme_ue_s1ap_id) {
return 1;
}
if (p1->mme_ue_s1ap_id < p2->mme_ue_s1ap_id) {
return -1;
}
} else if (p1->ue_id > 0) {
/* if nas ue_id provided */
if (p1->ue_id > p2->ue_id) {
return 1;
}
if (p1->ue_id < p2->ue_id) {
return -1;
}
} else {
uint16_t mcc1;
uint16_t mnc1;
uint16_t mnc1_len;
uint16_t mcc2;
uint16_t mnc2;
uint16_t mnc2_len;
PLMN_T_TO_MCC_MNC(p1->guti.gummei.plmn, mcc1, mnc1, mnc1_len);
PLMN_T_TO_MCC_MNC(p1->guti.gummei.plmn, mcc2, mnc2, mnc2_len);
/* else compare by GUTI */
if ((p1->guti.m_tmsi < p2->guti.m_tmsi) &&
(p1->guti.gummei.MMEcode < p2->guti.gummei.MMEcode) &&
(p1->guti.gummei.MMEgid < p2->guti.gummei.MMEgid) &&
(mcc1 < mcc2) &&
(mnc1 < mnc2) &&
(mnc1_len < mnc2_len))
return 1;
if ((p1->guti.m_tmsi > p2->guti.m_tmsi) &&
(p1->guti.gummei.MMEcode > p2->guti.gummei.MMEcode) &&
(p1->guti.gummei.MMEgid > p2->guti.gummei.MMEgid) &&
(mcc1 > mcc2) &&
(mnc1 > mnc2) &&
(mnc1_len > mnc2_len))
return -1;
} }
/* Match -> return 0 */
return 0; if (p1->imsi < p2->imsi) {
return -1;
}
} else if (p1->mme_s11_teid > 0) {
/* if s11 teid provided */
if (p1->mme_s11_teid > p2->mme_s11_teid) {
return 1;
}
if (p1->mme_s11_teid < p2->mme_s11_teid) {
return -1;
}
} else if (p1->mme_ue_s1ap_id > 0) {
MME_APP_DEBUG(" with mme_ue_s1ap_id %d\n" , p2->mme_ue_s1ap_id);
/* if s1ap ue id provided */
if (p1->mme_ue_s1ap_id > p2->mme_ue_s1ap_id) {
return 1;
}
if (p1->mme_ue_s1ap_id < p2->mme_ue_s1ap_id) {
return -1;
}
} else if (p1->ue_id > 0) {
/* if nas ue_id provided */
if (p1->ue_id > p2->ue_id) {
return 1;
}
if (p1->ue_id < p2->ue_id) {
return -1;
}
} else {
uint16_t mcc1;
uint16_t mnc1;
uint16_t mnc1_len;
uint16_t mcc2;
uint16_t mnc2;
uint16_t mnc2_len;
PLMN_T_TO_MCC_MNC(p1->guti.gummei.plmn, mcc1, mnc1, mnc1_len);
PLMN_T_TO_MCC_MNC(p1->guti.gummei.plmn, mcc2, mnc2, mnc2_len);
/* else compare by GUTI */
if ((p1->guti.m_tmsi < p2->guti.m_tmsi) &&
(p1->guti.gummei.MMEcode < p2->guti.gummei.MMEcode) &&
(p1->guti.gummei.MMEgid < p2->guti.gummei.MMEgid) &&
(mcc1 < mcc2) &&
(mnc1 < mnc2) &&
(mnc1_len < mnc2_len))
return 1;
if ((p1->guti.m_tmsi > p2->guti.m_tmsi) &&
(p1->guti.gummei.MMEcode > p2->guti.gummei.MMEcode) &&
(p1->guti.gummei.MMEgid > p2->guti.gummei.MMEgid) &&
(mcc1 > mcc2) &&
(mnc1 > mnc2) &&
(mnc1_len > mnc2_len))
return -1;
}
/* Match -> return 0 */
return 0;
} }
ue_context_t *mme_create_new_ue_context(void) ue_context_t *mme_create_new_ue_context(void)
{ {
ue_context_t *new_p; ue_context_t *new_p;
new_p = malloc(sizeof(ue_context_t)); new_p = malloc(sizeof(ue_context_t));
if (new_p == NULL) {
return NULL; if (new_p == NULL) {
} return NULL;
memset(new_p, 0, sizeof(ue_context_t)); }
return new_p;
memset(new_p, 0, sizeof(ue_context_t));
return new_p;
} }
inline inline
struct ue_context_s *mme_ue_context_exists_imsi(mme_ue_context_t *mme_ue_context, struct ue_context_s *mme_ue_context_exists_imsi(mme_ue_context_t *mme_ue_context,
mme_app_imsi_t imsi) mme_app_imsi_t imsi)
{ {
struct ue_context_s reference; struct ue_context_s reference;
DevAssert(mme_ue_context != NULL); DevAssert(mme_ue_context != NULL);
memset(&reference, 0, sizeof(struct ue_context_s)); memset(&reference, 0, sizeof(struct ue_context_s));
reference.imsi = imsi; reference.imsi = imsi;
return RB_FIND(ue_context_map, &mme_ue_context->ue_context_tree, return RB_FIND(ue_context_map, &mme_ue_context->ue_context_tree,
&reference); &reference);
} }
inline inline
struct ue_context_s *mme_ue_context_exists_s11_teid(mme_ue_context_t *mme_ue_context, struct ue_context_s *mme_ue_context_exists_s11_teid(mme_ue_context_t *mme_ue_context,
uint32_t teid) uint32_t teid)
{ {
struct ue_context_s reference; struct ue_context_s reference;
DevAssert(mme_ue_context != NULL); DevAssert(mme_ue_context != NULL);
memset(&reference, 0, sizeof(struct ue_context_s)); memset(&reference, 0, sizeof(struct ue_context_s));
reference.mme_s11_teid = teid; reference.mme_s11_teid = teid;
return RB_FIND(ue_context_map, &mme_ue_context->ue_context_tree, return RB_FIND(ue_context_map, &mme_ue_context->ue_context_tree,
&reference); &reference);
} }
inline inline
ue_context_t *mme_ue_context_exists_mme_ue_s1ap_id( ue_context_t *mme_ue_context_exists_mme_ue_s1ap_id(
mme_ue_context_t *mme_ue_context, mme_ue_context_t *mme_ue_context,
uint32_t mme_ue_s1ap_id) uint32_t mme_ue_s1ap_id)
{ {
struct ue_context_s reference; struct ue_context_s reference;
DevAssert(mme_ue_context != NULL); DevAssert(mme_ue_context != NULL);
memset(&reference, 0, sizeof(struct ue_context_s)); memset(&reference, 0, sizeof(struct ue_context_s));
reference.mme_ue_s1ap_id = mme_ue_s1ap_id; reference.mme_ue_s1ap_id = mme_ue_s1ap_id;
return RB_FIND(ue_context_map, &mme_ue_context->ue_context_tree, return RB_FIND(ue_context_map, &mme_ue_context->ue_context_tree,
&reference); &reference);
} }
inline inline
ue_context_t *mme_ue_context_exists_nas_ue_id( ue_context_t *mme_ue_context_exists_nas_ue_id(
mme_ue_context_t *mme_ue_context, mme_ue_context_t *mme_ue_context,
uint32_t nas_ue_id) uint32_t nas_ue_id)
{ {
struct ue_context_s reference; struct ue_context_s reference;
DevAssert(mme_ue_context != NULL); DevAssert(mme_ue_context != NULL);
memset(&reference, 0, sizeof(struct ue_context_s)); memset(&reference, 0, sizeof(struct ue_context_s));
reference.ue_id = nas_ue_id; reference.ue_id = nas_ue_id;
return RB_FIND(ue_context_map, &mme_ue_context->ue_context_tree, return RB_FIND(ue_context_map, &mme_ue_context->ue_context_tree,
&reference); &reference);
} }
inline inline
ue_context_t *mme_ue_context_exists_guti(mme_ue_context_t *mme_ue_context, ue_context_t *mme_ue_context_exists_guti(mme_ue_context_t *mme_ue_context,
GUTI_t guti) GUTI_t guti)
{ {
struct ue_context_s reference; struct ue_context_s reference;
DevAssert(mme_ue_context != NULL); DevAssert(mme_ue_context != NULL);
memset(&reference, 0, sizeof(struct ue_context_s)); memset(&reference, 0, sizeof(struct ue_context_s));
memcpy(&reference.guti, &guti, sizeof(GUTI_t)); memcpy(&reference.guti, &guti, sizeof(GUTI_t));
return RB_FIND(ue_context_map, &mme_ue_context->ue_context_tree, return RB_FIND(ue_context_map, &mme_ue_context->ue_context_tree,
&reference); &reference);
} }
int mme_insert_ue_context(mme_ue_context_t *mme_ue_context, struct ue_context_s *ue_context_p) int mme_insert_ue_context(mme_ue_context_t *mme_ue_context, struct ue_context_s *ue_context_p)
{ {
struct ue_context_s *collision_p = NULL; struct ue_context_s *collision_p = NULL;
DevAssert(mme_ue_context != NULL); DevAssert(mme_ue_context != NULL);
DevAssert(ue_context_p != NULL); DevAssert(ue_context_p != NULL);
/* Updating statistics */ /* Updating statistics */
mme_ue_context->nb_ue_managed++; mme_ue_context->nb_ue_managed++;
mme_ue_context->nb_ue_since_last_stat++; mme_ue_context->nb_ue_since_last_stat++;
collision_p = RB_INSERT(ue_context_map, &mme_ue_context->ue_context_tree, collision_p = RB_INSERT(ue_context_map, &mme_ue_context->ue_context_tree,
ue_context_p); ue_context_p);
if (collision_p != NULL) {
fprintf(stderr, "This ue context already exists...\n");
return -1;
}
return 0; if (collision_p != NULL) {
fprintf(stderr, "This ue context already exists...\n");
return -1;
}
return 0;
} }
void mme_app_dump_ue_contexts(mme_ue_context_t *mme_ue_context) void mme_app_dump_ue_contexts(mme_ue_context_t *mme_ue_context)
{ {
struct ue_context_s *context_p; struct ue_context_s *context_p;
MME_APP_DEBUG("-----------------------UE contexts-----------------------\n"); MME_APP_DEBUG("-----------------------UE contexts-----------------------\n");
RB_FOREACH(context_p, ue_context_map, &mme_ue_context->ue_context_tree) RB_FOREACH(context_p, ue_context_map, &mme_ue_context->ue_context_tree) {
{ uint8_t j;
uint8_t j;
MME_APP_DEBUG(" - IMSI ...........: %"SCNu64"\n", context_p->imsi); MME_APP_DEBUG(" - IMSI ...........: %"SCNu64"\n", context_p->imsi);
MME_APP_DEBUG(" | m_tmsi | mmec | mmegid | mcc | mnc |\n"); MME_APP_DEBUG(" | m_tmsi | mmec | mmegid | mcc | mnc |\n");
MME_APP_DEBUG(" - GUTI............: | %08x | %02x | %04x | %03u | %03u |\n", MME_APP_DEBUG(" - GUTI............: | %08x | %02x | %04x | %03u | %03u |\n",
context_p->guti.m_tmsi, context_p->guti.gummei.MMEcode, context_p->guti.m_tmsi, context_p->guti.gummei.MMEcode,
context_p->guti.gummei.MMEgid, context_p->guti.gummei.MMEgid,
/* TODO check if two or three digits MNC... */ /* TODO check if two or three digits MNC... */
context_p->guti.gummei.plmn.MCCdigit3 * 100 + context_p->guti.gummei.plmn.MCCdigit3 * 100 +
context_p->guti.gummei.plmn.MCCdigit2 * 10 + context_p->guti.gummei.plmn.MCCdigit2 * 10 +
context_p->guti.gummei.plmn.MCCdigit1, context_p->guti.gummei.plmn.MCCdigit1,
context_p->guti.gummei.plmn.MNCdigit3 * 100 + context_p->guti.gummei.plmn.MNCdigit3 * 100 +
context_p->guti.gummei.plmn.MNCdigit2 * 10 + context_p->guti.gummei.plmn.MNCdigit2 * 10 +
context_p->guti.gummei.plmn.MNCdigit1); context_p->guti.gummei.plmn.MNCdigit1);
MME_APP_DEBUG(" - Authenticated ..: %s\n", MME_APP_DEBUG(" - Authenticated ..: %s\n",
(context_p->imsi_auth == IMSI_UNAUTHENTICATED) ? "FALSE": "TRUE"); (context_p->imsi_auth == IMSI_UNAUTHENTICATED) ? "FALSE": "TRUE");
MME_APP_DEBUG(" - eNB UE s1ap ID .: %08x\n", context_p->eNB_ue_s1ap_id); MME_APP_DEBUG(" - eNB UE s1ap ID .: %08x\n", context_p->eNB_ue_s1ap_id);
MME_APP_DEBUG(" - MME UE s1ap ID .: %08x\n", context_p->mme_ue_s1ap_id); MME_APP_DEBUG(" - MME UE s1ap ID .: %08x\n", context_p->mme_ue_s1ap_id);
MME_APP_DEBUG(" - MME S11 TEID ...: %08x\n", context_p->mme_s11_teid); MME_APP_DEBUG(" - MME S11 TEID ...: %08x\n", context_p->mme_s11_teid);
MME_APP_DEBUG(" - SGW S11 TEID ...: %08x\n", context_p->sgw_s11_teid); MME_APP_DEBUG(" - SGW S11 TEID ...: %08x\n", context_p->sgw_s11_teid);
MME_APP_DEBUG(" | mcc | mnc | cell id |\n"); MME_APP_DEBUG(" | mcc | mnc | cell id |\n");
MME_APP_DEBUG(" - E-UTRAN CGI ....: | %03u | %03u | %08x |\n", MME_APP_DEBUG(" - E-UTRAN CGI ....: | %03u | %03u | %08x |\n",
context_p->e_utran_cgi.plmn.MCCdigit3 * 100 + context_p->e_utran_cgi.plmn.MCCdigit3 * 100 +
context_p->e_utran_cgi.plmn.MCCdigit2 * 10 + context_p->e_utran_cgi.plmn.MCCdigit2 * 10 +
context_p->e_utran_cgi.plmn.MCCdigit1, context_p->e_utran_cgi.plmn.MCCdigit1,
context_p->e_utran_cgi.plmn.MNCdigit3 * 100 + context_p->e_utran_cgi.plmn.MNCdigit3 * 100 +
context_p->e_utran_cgi.plmn.MNCdigit2 * 10 + context_p->e_utran_cgi.plmn.MNCdigit2 * 10 +
context_p->e_utran_cgi.plmn.MNCdigit1, context_p->e_utran_cgi.plmn.MNCdigit1,
context_p->e_utran_cgi.cell_identity); context_p->e_utran_cgi.cell_identity);
/* Ctime return a \n in the string */ /* Ctime return a \n in the string */
MME_APP_DEBUG(" - Last acquired ..: %s", ctime(&context_p->cell_age)); MME_APP_DEBUG(" - Last acquired ..: %s", ctime(&context_p->cell_age));
/* Display UE info only if we know them */ /* Display UE info only if we know them */
if (context_p->subscription_known == SUBSCRIPTION_KNOWN) if (context_p->subscription_known == SUBSCRIPTION_KNOWN) {
{ MME_APP_DEBUG(" - Status .........: %s\n",
MME_APP_DEBUG(" - Status .........: %s\n", (context_p->sub_status == SS_SERVICE_GRANTED) ? "Granted" : "Barred");
(context_p->sub_status == SS_SERVICE_GRANTED) ? "Granted" : "Barred");
#define DISPLAY_BIT_MASK_PRESENT(mASK) \ #define DISPLAY_BIT_MASK_PRESENT(mASK) \
((context_p->access_restriction_data & mASK) ? 'X' : 'O') ((context_p->access_restriction_data & mASK) ? 'X' : 'O')
MME_APP_DEBUG(" (O = allowed, X = !O) |UTRAN|GERAN|GAN|HSDPA EVO|E_UTRAN|HO TO NO 3GPP|\n"); MME_APP_DEBUG(" (O = allowed, X = !O) |UTRAN|GERAN|GAN|HSDPA EVO|E_UTRAN|HO TO NO 3GPP|\n");
MME_APP_DEBUG(" - Access restriction | %c | %c | %c | %c | %c | %c |\n", MME_APP_DEBUG(" - Access restriction | %c | %c | %c | %c | %c | %c |\n",
DISPLAY_BIT_MASK_PRESENT(ARD_UTRAN_NOT_ALLOWED), DISPLAY_BIT_MASK_PRESENT(ARD_UTRAN_NOT_ALLOWED),
DISPLAY_BIT_MASK_PRESENT(ARD_GERAN_NOT_ALLOWED), DISPLAY_BIT_MASK_PRESENT(ARD_GERAN_NOT_ALLOWED),
DISPLAY_BIT_MASK_PRESENT(ARD_GAN_NOT_ALLOWED), DISPLAY_BIT_MASK_PRESENT(ARD_GAN_NOT_ALLOWED),
DISPLAY_BIT_MASK_PRESENT(ARD_I_HSDPA_EVO_NOT_ALLOWED), DISPLAY_BIT_MASK_PRESENT(ARD_I_HSDPA_EVO_NOT_ALLOWED),
DISPLAY_BIT_MASK_PRESENT(ARD_E_UTRAN_NOT_ALLOWED), DISPLAY_BIT_MASK_PRESENT(ARD_E_UTRAN_NOT_ALLOWED),
DISPLAY_BIT_MASK_PRESENT(ARD_HO_TO_NON_3GPP_NOT_ALLOWED)); DISPLAY_BIT_MASK_PRESENT(ARD_HO_TO_NON_3GPP_NOT_ALLOWED));
MME_APP_DEBUG(" - Access Mode ....: %s\n", MME_APP_DEBUG(" - Access Mode ....: %s\n",
ACCESS_MODE_TO_STRING(context_p->access_mode)); ACCESS_MODE_TO_STRING(context_p->access_mode));
MME_APP_DEBUG(" - MSISDN .........: %-*s\n", MME_APP_DEBUG(" - MSISDN .........: %-*s\n",
MSISDN_LENGTH, context_p->msisdn); MSISDN_LENGTH, context_p->msisdn);
MME_APP_DEBUG(" - RAU/TAU timer ..: %u\n", context_p->rau_tau_timer); MME_APP_DEBUG(" - RAU/TAU timer ..: %u\n", context_p->rau_tau_timer);
MME_APP_DEBUG(" - IMEISV .........: %*s\n", 15, MME_APP_DEBUG(" - IMEISV .........: %*s\n", 15,
context_p->me_identity.imeisv); context_p->me_identity.imeisv);
MME_APP_DEBUG(" - AMBR (bits/s) ( Downlink | Uplink )\n"); MME_APP_DEBUG(" - AMBR (bits/s) ( Downlink | Uplink )\n");
MME_APP_DEBUG(" Subscribed ...: (%010"PRIu64"|%010"PRIu64")\n", MME_APP_DEBUG(" Subscribed ...: (%010"PRIu64"|%010"PRIu64")\n",
context_p->subscribed_ambr.br_dl, context_p->subscribed_ambr.br_dl,
context_p->subscribed_ambr.br_ul); context_p->subscribed_ambr.br_ul);
MME_APP_DEBUG(" Allocated ....: (%010"PRIu64"|%010"PRIu64")\n", MME_APP_DEBUG(" Allocated ....: (%010"PRIu64"|%010"PRIu64")\n",
context_p->used_ambr.br_dl, context_p->used_ambr.br_ul); context_p->used_ambr.br_dl, context_p->used_ambr.br_ul);
MME_APP_DEBUG(" - Known vectors ..: %u\n", context_p->nb_of_vectors); MME_APP_DEBUG(" - Known vectors ..: %u\n", context_p->nb_of_vectors);
for (j = 0; j < context_p->nb_of_vectors; j++)
{
int k;
char xres_string[3 * XRES_LENGTH_MAX + 1];
eutran_vector_t *vector_p;
vector_p = &context_p->vector_list[j]; for (j = 0; j < context_p->nb_of_vectors; j++) {
int k;
char xres_string[3 * XRES_LENGTH_MAX + 1];
eutran_vector_t *vector_p;
MME_APP_DEBUG(" - RAND ..: "RAND_FORMAT"\n", vector_p = &context_p->vector_list[j];
RAND_DISPLAY(vector_p->rand));
MME_APP_DEBUG(" - AUTN ..: "AUTN_FORMAT"\n",
AUTN_DISPLAY(vector_p->autn));
MME_APP_DEBUG(" - KASME .: "KASME_FORMAT"\n",
KASME_DISPLAY_1(vector_p->kasme));
MME_APP_DEBUG(" "KASME_FORMAT"\n",
KASME_DISPLAY_2(vector_p->kasme));
for (k = 0; k < vector_p->xres.size; k++) MME_APP_DEBUG(" - RAND ..: "RAND_FORMAT"\n",
{ RAND_DISPLAY(vector_p->rand));
sprintf(&xres_string[k * 3], "%02x,", vector_p->xres.data[k]); MME_APP_DEBUG(" - AUTN ..: "AUTN_FORMAT"\n",
} AUTN_DISPLAY(vector_p->autn));
xres_string[k * 3 - 1] = '\0'; MME_APP_DEBUG(" - KASME .: "KASME_FORMAT"\n",
MME_APP_DEBUG(" - XRES ..: %s\n", xres_string); KASME_DISPLAY_1(vector_p->kasme));
} MME_APP_DEBUG(" "KASME_FORMAT"\n",
MME_APP_DEBUG(" - PDN List:\n"); KASME_DISPLAY_2(vector_p->kasme));
for (j = 0; j < context_p->apn_profile.nb_apns; j++)
{
struct apn_configuration_s *apn_config_p;
apn_config_p = &context_p->apn_profile.apn_configuration[j]; for (k = 0; k < vector_p->xres.size; k++) {
sprintf(&xres_string[k * 3], "%02x,", vector_p->xres.data[k]);
/* Default APN ? */
MME_APP_DEBUG(" - Default APN ...: %s\n",
(apn_config_p->context_identifier == context_p->apn_profile.context_identifier)
? "TRUE" : "FALSE");
MME_APP_DEBUG(" - APN ...........: %s\n", apn_config_p->service_selection);
MME_APP_DEBUG(" - AMBR (bits/s) ( Downlink | Uplink )\n");
MME_APP_DEBUG(" (%010"PRIu64"|%010"PRIu64")\n",
apn_config_p->ambr.br_dl, apn_config_p->ambr.br_ul);
MME_APP_DEBUG(" - PDN type ......: %s\n",
PDN_TYPE_TO_STRING(apn_config_p->pdn_type));
MME_APP_DEBUG(" - QOS\n");
MME_APP_DEBUG(" QCI .........: %u\n",
apn_config_p->subscribed_qos.qci);
MME_APP_DEBUG(" Prio level ..: %u\n",
apn_config_p->subscribed_qos.allocation_retention_priority.priority_level);
MME_APP_DEBUG(" Pre-emp vul .: %s\n",
(apn_config_p->subscribed_qos.allocation_retention_priority.pre_emp_vulnerability
== PRE_EMPTION_VULNERABILITY_ENABLED) ? "ENABLED" : "DISABLED");
MME_APP_DEBUG(" Pre-emp cap .: %s\n",
(apn_config_p->subscribed_qos.allocation_retention_priority.pre_emp_capability
== PRE_EMPTION_CAPABILITY_ENABLED) ? "ENABLED" : "DISABLED");
if (apn_config_p->nb_ip_address == 0) {
MME_APP_DEBUG(" IP addr .....: Dynamic allocation\n");
} else {
int i;
MME_APP_DEBUG(" IP addresses :\n");
for (i = 0; i < apn_config_p->nb_ip_address; i++)
{
if (apn_config_p->ip_address[i].pdn_type == IPv4) {
MME_APP_DEBUG(" ["IPV4_ADDR"]\n",
IPV4_ADDR_DISPLAY_8(apn_config_p->ip_address[i].address.ipv4_address));
} else {
char ipv6[40];
inet_ntop(AF_INET6, apn_config_p->ip_address[i].address.ipv6_address,ipv6, 40);
MME_APP_DEBUG(" [%s]\n", ipv6);
}
}
}
MME_APP_DEBUG("\n");
}
MME_APP_DEBUG(" - Bearer List:\n");
for (j = 0; j < BEARERS_PER_UE; j++)
{
bearer_context_t *bearer_context_p;
bearer_context_p = &context_p->eps_bearers[j];
if (bearer_context_p->s_gw_teid != 0) {
MME_APP_DEBUG(" Bearer id .......: %02u\n", j);
MME_APP_DEBUG(" S-GW TEID (UP)...: %08x\n", bearer_context_p->s_gw_teid);
MME_APP_DEBUG(" P-GW TEID (UP)...: %08x\n", bearer_context_p->p_gw_teid);
MME_APP_DEBUG(" QCI .............: %u\n",
bearer_context_p->qci);
MME_APP_DEBUG(" Priority level ..: %u\n",
bearer_context_p->prio_level);
MME_APP_DEBUG(" Pre-emp vul .....: %s\n",
(bearer_context_p->pre_emp_vulnerability
== PRE_EMPTION_VULNERABILITY_ENABLED) ? "ENABLED" : "DISABLED");
MME_APP_DEBUG(" Pre-emp cap .....: %s\n",
(bearer_context_p->pre_emp_capability
== PRE_EMPTION_CAPABILITY_ENABLED) ? "ENABLED" : "DISABLED");
}
}
} }
xres_string[k * 3 - 1] = '\0';
MME_APP_DEBUG(" - XRES ..: %s\n", xres_string);
}
MME_APP_DEBUG(" - PDN List:\n");
for (j = 0; j < context_p->apn_profile.nb_apns; j++) {
struct apn_configuration_s *apn_config_p;
apn_config_p = &context_p->apn_profile.apn_configuration[j];
/* Default APN ? */
MME_APP_DEBUG(" - Default APN ...: %s\n",
(apn_config_p->context_identifier == context_p->apn_profile.context_identifier)
? "TRUE" : "FALSE");
MME_APP_DEBUG(" - APN ...........: %s\n", apn_config_p->service_selection);
MME_APP_DEBUG(" - AMBR (bits/s) ( Downlink | Uplink )\n");
MME_APP_DEBUG(" (%010"PRIu64"|%010"PRIu64")\n",
apn_config_p->ambr.br_dl, apn_config_p->ambr.br_ul);
MME_APP_DEBUG(" - PDN type ......: %s\n",
PDN_TYPE_TO_STRING(apn_config_p->pdn_type));
MME_APP_DEBUG(" - QOS\n");
MME_APP_DEBUG(" QCI .........: %u\n",
apn_config_p->subscribed_qos.qci);
MME_APP_DEBUG(" Prio level ..: %u\n",
apn_config_p->subscribed_qos.allocation_retention_priority.priority_level);
MME_APP_DEBUG(" Pre-emp vul .: %s\n",
(apn_config_p->subscribed_qos.allocation_retention_priority.pre_emp_vulnerability
== PRE_EMPTION_VULNERABILITY_ENABLED) ? "ENABLED" : "DISABLED");
MME_APP_DEBUG(" Pre-emp cap .: %s\n",
(apn_config_p->subscribed_qos.allocation_retention_priority.pre_emp_capability
== PRE_EMPTION_CAPABILITY_ENABLED) ? "ENABLED" : "DISABLED");
if (apn_config_p->nb_ip_address == 0) {
MME_APP_DEBUG(" IP addr .....: Dynamic allocation\n");
} else {
int i;
MME_APP_DEBUG(" IP addresses :\n");
for (i = 0; i < apn_config_p->nb_ip_address; i++) {
if (apn_config_p->ip_address[i].pdn_type == IPv4) {
MME_APP_DEBUG(" ["IPV4_ADDR"]\n",
IPV4_ADDR_DISPLAY_8(apn_config_p->ip_address[i].address.ipv4_address));
} else {
char ipv6[40];
inet_ntop(AF_INET6, apn_config_p->ip_address[i].address.ipv6_address,ipv6, 40);
MME_APP_DEBUG(" [%s]\n", ipv6);
}
}
}
MME_APP_DEBUG("\n");
}
MME_APP_DEBUG(" - Bearer List:\n");
for (j = 0; j < BEARERS_PER_UE; j++) {
bearer_context_t *bearer_context_p;
bearer_context_p = &context_p->eps_bearers[j];
if (bearer_context_p->s_gw_teid != 0) {
MME_APP_DEBUG(" Bearer id .......: %02u\n", j);
MME_APP_DEBUG(" S-GW TEID (UP)...: %08x\n", bearer_context_p->s_gw_teid);
MME_APP_DEBUG(" P-GW TEID (UP)...: %08x\n", bearer_context_p->p_gw_teid);
MME_APP_DEBUG(" QCI .............: %u\n",
bearer_context_p->qci);
MME_APP_DEBUG(" Priority level ..: %u\n",
bearer_context_p->prio_level);
MME_APP_DEBUG(" Pre-emp vul .....: %s\n",
(bearer_context_p->pre_emp_vulnerability
== PRE_EMPTION_VULNERABILITY_ENABLED) ? "ENABLED" : "DISABLED");
MME_APP_DEBUG(" Pre-emp cap .....: %s\n",
(bearer_context_p->pre_emp_capability
== PRE_EMPTION_CAPABILITY_ENABLED) ? "ENABLED" : "DISABLED");
}
}
} }
MME_APP_DEBUG("---------------------------------------------------------\n"); }
MME_APP_DEBUG("---------------------------------------------------------\n");
} }
+4 -4
View File
@@ -47,11 +47,11 @@
#endif #endif
typedef struct { typedef struct {
/* UE contexts + some statistics variables */ /* UE contexts + some statistics variables */
mme_ue_context_t mme_ue_contexts; mme_ue_context_t mme_ue_contexts;
long statistic_timer_id; long statistic_timer_id;
uint32_t statistic_timer_period; uint32_t statistic_timer_period;
} mme_app_desc_t; } mme_app_desc_t;
extern mme_app_desc_t mme_app_desc; extern mme_app_desc_t mme_app_desc;
+16 -16
View File
@@ -33,35 +33,35 @@
static inline void static inline void
mme_app_itti_auth_fail( mme_app_itti_auth_fail(
const uint32_t ue_id, const uint32_t ue_id,
const nas_cause_t cause) const nas_cause_t cause)
{ {
MessageDef *message_p; MessageDef *message_p;
message_p = itti_alloc_new_message(TASK_MME_APP, NAS_AUTHENTICATION_PARAM_FAIL); message_p = itti_alloc_new_message(TASK_MME_APP, NAS_AUTHENTICATION_PARAM_FAIL);
NAS_AUTHENTICATION_PARAM_FAIL(message_p).ue_id = ue_id; NAS_AUTHENTICATION_PARAM_FAIL(message_p).ue_id = ue_id;
NAS_AUTHENTICATION_PARAM_FAIL(message_p).cause = cause; NAS_AUTHENTICATION_PARAM_FAIL(message_p).cause = cause;
itti_send_msg_to_task(TASK_NAS_MME, INSTANCE_DEFAULT, message_p); itti_send_msg_to_task(TASK_NAS_MME, INSTANCE_DEFAULT, message_p);
} }
static inline void mme_app_itti_auth_rsp( static inline void mme_app_itti_auth_rsp(
const uint32_t ue_id, const uint32_t ue_id,
const uint8_t nb_vectors, const uint8_t nb_vectors,
const eutran_vector_t * const vector) const eutran_vector_t * const vector)
{ {
MessageDef *message_p; MessageDef *message_p;
message_p = itti_alloc_new_message(TASK_MME_APP, NAS_AUTHENTICATION_PARAM_RSP); message_p = itti_alloc_new_message(TASK_MME_APP, NAS_AUTHENTICATION_PARAM_RSP);
NAS_AUTHENTICATION_PARAM_RSP(message_p).ue_id = ue_id; NAS_AUTHENTICATION_PARAM_RSP(message_p).ue_id = ue_id;
NAS_AUTHENTICATION_PARAM_RSP(message_p).nb_vectors = nb_vectors; NAS_AUTHENTICATION_PARAM_RSP(message_p).nb_vectors = nb_vectors;
memcpy(&NAS_AUTHENTICATION_PARAM_RSP(message_p).vector, vector, sizeof(*vector)); memcpy(&NAS_AUTHENTICATION_PARAM_RSP(message_p).vector, vector, sizeof(*vector));
itti_send_msg_to_task(TASK_NAS_MME, INSTANCE_DEFAULT, message_p); itti_send_msg_to_task(TASK_NAS_MME, INSTANCE_DEFAULT, message_p);
} }
#endif /* MME_APP_ITTI_MESSAGING_H_ */ #endif /* MME_APP_ITTI_MESSAGING_H_ */
+49 -48
View File
@@ -54,7 +54,7 @@
int int
mme_app_send_s6a_update_location_req( mme_app_send_s6a_update_location_req(
struct ue_context_s * const ue_context_pP) struct ue_context_s * const ue_context_pP)
{ {
struct ue_context_s *ue_context_p = NULL; struct ue_context_s *ue_context_p = NULL;
uint64_t imsi = 0; uint64_t imsi = 0;
@@ -67,14 +67,15 @@ mme_app_send_s6a_update_location_req(
MME_APP_DEBUG("Handling imsi %"IMSI_FORMAT"\n", imsi); MME_APP_DEBUG("Handling imsi %"IMSI_FORMAT"\n", imsi);
if ((ue_context_p = mme_ue_context_exists_imsi(&mme_app_desc.mme_ue_contexts, if ((ue_context_p = mme_ue_context_exists_imsi(&mme_app_desc.mme_ue_contexts,
imsi)) == NULL) { imsi)) == NULL) {
MME_APP_ERROR("That's embarrassing as we don't know this IMSI\n"); MME_APP_ERROR("That's embarrassing as we don't know this IMSI\n");
return -1; return -1;
} }
message_p = itti_alloc_new_message(TASK_MME_APP, S6A_UPDATE_LOCATION_REQ); message_p = itti_alloc_new_message(TASK_MME_APP, S6A_UPDATE_LOCATION_REQ);
if (message_p == NULL) { if (message_p == NULL) {
return -1; return -1;
} }
s6a_ulr_p = &message_p->ittiMsg.s6a_update_location_req; s6a_ulr_p = &message_p->ittiMsg.s6a_update_location_req;
@@ -95,61 +96,61 @@ mme_app_send_s6a_update_location_req(
int int
mme_app_handle_s6a_update_location_ans( mme_app_handle_s6a_update_location_ans(
const s6a_update_location_ans_t * const ula_pP) const s6a_update_location_ans_t * const ula_pP)
{ {
uint64_t imsi = 0; uint64_t imsi = 0;
struct ue_context_s *ue_context_p = NULL; struct ue_context_s *ue_context_p = NULL;
DevAssert(ula_pP != NULL); DevAssert(ula_pP != NULL);
if (ula_pP->result.present == S6A_RESULT_BASE) { if (ula_pP->result.present == S6A_RESULT_BASE) {
if (ula_pP->result.choice.base != DIAMETER_SUCCESS) { if (ula_pP->result.choice.base != DIAMETER_SUCCESS) {
/* The update location procedure has failed. Notify the NAS layer /* The update location procedure has failed. Notify the NAS layer
* and don't initiate the bearer creation on S-GW side. * and don't initiate the bearer creation on S-GW side.
*/ */
MME_APP_DEBUG("ULR/ULA procedure returned non success (ULA.result.choice.base=%d)\n", ula_pP->result.choice.base); MME_APP_DEBUG("ULR/ULA procedure returned non success (ULA.result.choice.base=%d)\n", ula_pP->result.choice.base);
DevMessage("ULR/ULA procedure returned non success\n"); DevMessage("ULR/ULA procedure returned non success\n");
}
} else {
/* The update location procedure has failed. Notify the NAS layer
* and don't initiate the bearer creation on S-GW side.
*/
MME_APP_DEBUG("ULR/ULA procedure returned non success (ULA.result.present=%d)\n", ula_pP->result.present);
DevMessage("ULR/ULA procedure returned non success\n");
} }
} else {
/* The update location procedure has failed. Notify the NAS layer
* and don't initiate the bearer creation on S-GW side.
*/
MME_APP_DEBUG("ULR/ULA procedure returned non success (ULA.result.present=%d)\n", ula_pP->result.present);
DevMessage("ULR/ULA procedure returned non success\n");
}
MME_APP_STRING_TO_IMSI((char *)ula_pP->imsi, &imsi); MME_APP_STRING_TO_IMSI((char *)ula_pP->imsi, &imsi);
MME_APP_DEBUG("%s Handling imsi %"IMSI_FORMAT"\n", __FUNCTION__, imsi); MME_APP_DEBUG("%s Handling imsi %"IMSI_FORMAT"\n", __FUNCTION__, imsi);
if ((ue_context_p = mme_ue_context_exists_imsi(&mme_app_desc.mme_ue_contexts, imsi)) == NULL) { if ((ue_context_p = mme_ue_context_exists_imsi(&mme_app_desc.mme_ue_contexts, imsi)) == NULL) {
MME_APP_ERROR("That's embarrassing as we don't know this IMSI\n"); MME_APP_ERROR("That's embarrassing as we don't know this IMSI\n");
return -1; return -1;
} }
ue_context_p->subscription_known = SUBSCRIPTION_KNOWN; ue_context_p->subscription_known = SUBSCRIPTION_KNOWN;
ue_context_p->sub_status = ula_pP->subscription_data.subscriber_status; ue_context_p->sub_status = ula_pP->subscription_data.subscriber_status;
ue_context_p->access_restriction_data = ula_pP->subscription_data.access_restriction; ue_context_p->access_restriction_data = ula_pP->subscription_data.access_restriction;
/* Copy the subscribed ambr to the sgw create session request message */ /* Copy the subscribed ambr to the sgw create session request message */
memcpy(&ue_context_p->subscribed_ambr, &ula_pP->subscription_data.subscribed_ambr, memcpy(&ue_context_p->subscribed_ambr, &ula_pP->subscription_data.subscribed_ambr,
sizeof(ambr_t)); sizeof(ambr_t));
memcpy( memcpy(
ue_context_p->msisdn, ue_context_p->msisdn,
ula_pP->subscription_data.msisdn, ula_pP->subscription_data.msisdn,
ula_pP->subscription_data.msisdn_length); ula_pP->subscription_data.msisdn_length);
ue_context_p->msisdn_length = ula_pP->subscription_data.msisdn_length; ue_context_p->msisdn_length = ula_pP->subscription_data.msisdn_length;
AssertFatal(ula_pP->subscription_data.msisdn_length != 0, "MSISDN LENGTH IS 0"); AssertFatal(ula_pP->subscription_data.msisdn_length != 0, "MSISDN LENGTH IS 0");
AssertFatal(ula_pP->subscription_data.msisdn_length <= MSISDN_LENGTH, "MSISDN LENGTH is too high %u", MSISDN_LENGTH); AssertFatal(ula_pP->subscription_data.msisdn_length <= MSISDN_LENGTH, "MSISDN LENGTH is too high %u", MSISDN_LENGTH);
ue_context_p->msisdn[ue_context_p->msisdn_length] = '\0'; ue_context_p->msisdn[ue_context_p->msisdn_length] = '\0';
ue_context_p->rau_tau_timer = ula_pP->subscription_data.rau_tau_timer; ue_context_p->rau_tau_timer = ula_pP->subscription_data.rau_tau_timer;
ue_context_p->access_mode = ula_pP->subscription_data.access_mode; ue_context_p->access_mode = ula_pP->subscription_data.access_mode;
memcpy(&ue_context_p->apn_profile, &ula_pP->subscription_data.apn_config_profile, memcpy(&ue_context_p->apn_profile, &ula_pP->subscription_data.apn_config_profile,
sizeof(apn_config_profile_t)); sizeof(apn_config_profile_t));
return mme_app_send_s11_create_session_req(ue_context_p); return mme_app_send_s11_create_session_req(ue_context_p);
} }
+116 -99
View File
@@ -49,124 +49,141 @@ void *mme_app_thread(void *args);
void *mme_app_thread(void *args) void *mme_app_thread(void *args)
{ {
itti_mark_task_ready(TASK_MME_APP); itti_mark_task_ready(TASK_MME_APP);
while(1) { while(1) {
MessageDef *received_message_p = NULL; MessageDef *received_message_p = NULL;
/* Trying to fetch a message from the message queue. /* Trying to fetch a message from the message queue.
* If the queue is empty, this function will block till a * If the queue is empty, this function will block till a
* message is sent to the task. * message is sent to the task.
*/ */
itti_receive_msg(TASK_MME_APP, &received_message_p); itti_receive_msg(TASK_MME_APP, &received_message_p);
DevAssert(received_message_p != NULL); DevAssert(received_message_p != NULL);
switch (ITTI_MSG_ID(received_message_p)) switch (ITTI_MSG_ID(received_message_p)) {
{ case S6A_AUTH_INFO_ANS: {
case S6A_AUTH_INFO_ANS: { /* We received the authentication vectors from HSS, trigger a ULR
/* We received the authentication vectors from HSS, trigger a ULR * for now. Normaly should trigger an authentication procedure with UE.
* for now. Normaly should trigger an authentication procedure with UE. */
*/ mme_app_handle_authentication_info_answer(&received_message_p->ittiMsg.s6a_auth_info_ans);
mme_app_handle_authentication_info_answer(&received_message_p->ittiMsg.s6a_auth_info_ans); }
} break; break;
case S6A_UPDATE_LOCATION_ANS: { case S6A_UPDATE_LOCATION_ANS: {
/* We received the update location answer message from HSS -> Handle it */ /* We received the update location answer message from HSS -> Handle it */
mme_app_handle_s6a_update_location_ans(&received_message_p->ittiMsg.s6a_update_location_ans); mme_app_handle_s6a_update_location_ans(&received_message_p->ittiMsg.s6a_update_location_ans);
} break; }
break;
case SGW_CREATE_SESSION_RESPONSE: { case SGW_CREATE_SESSION_RESPONSE: {
mme_app_handle_create_sess_resp(&received_message_p->ittiMsg.sgwCreateSessionResponse); mme_app_handle_create_sess_resp(&received_message_p->ittiMsg.sgwCreateSessionResponse);
} break; }
break;
case SGW_MODIFY_BEARER_RESPONSE: { case SGW_MODIFY_BEARER_RESPONSE: {
MME_APP_DEBUG(" TO DO HANDLE SGW_MODIFY_BEARER_RESPONSE"); MME_APP_DEBUG(" TO DO HANDLE SGW_MODIFY_BEARER_RESPONSE");
// TO DO // TO DO
} break; }
break;
#if defined(DISABLE_USE_NAS) #if defined(DISABLE_USE_NAS)
case NAS_ATTACH_REQ: {
mme_app_handle_attach_req(&received_message_p->ittiMsg.nas_attach_req);
} break;
case NAS_AUTHENTICATION_RESP: { case NAS_ATTACH_REQ: {
mme_app_handle_nas_auth_resp(&received_message_p->ittiMsg.nas_auth_resp); mme_app_handle_attach_req(&received_message_p->ittiMsg.nas_attach_req);
} break; }
break;
case NAS_AUTHENTICATION_RESP: {
mme_app_handle_nas_auth_resp(&received_message_p->ittiMsg.nas_auth_resp);
}
break;
#else #else
case NAS_AUTHENTICATION_PARAM_REQ: {
mme_app_handle_nas_auth_param_req(&received_message_p->ittiMsg.nas_auth_param_req); case NAS_AUTHENTICATION_PARAM_REQ: {
} break; mme_app_handle_nas_auth_param_req(&received_message_p->ittiMsg.nas_auth_param_req);
}
break;
#endif #endif
case NAS_PDN_CONNECTIVITY_REQ: { case NAS_PDN_CONNECTIVITY_REQ: {
mme_app_handle_nas_pdn_connectivity_req(&received_message_p->ittiMsg.nas_pdn_connectivity_req); mme_app_handle_nas_pdn_connectivity_req(&received_message_p->ittiMsg.nas_pdn_connectivity_req);
} break;
case NAS_CONNECTION_ESTABLISHMENT_CNF: {
mme_app_handle_conn_est_cnf(&NAS_CONNECTION_ESTABLISHMENT_CNF(received_message_p));
} break;
// From S1AP Initiating Message/EMM Attach Request
case MME_APP_CONNECTION_ESTABLISHMENT_IND: {
mme_app_handle_conn_est_ind(&MME_APP_CONNECTION_ESTABLISHMENT_IND(received_message_p));
} break;
case MME_APP_INITIAL_CONTEXT_SETUP_RSP: {
mme_app_handle_initial_context_setup_rsp(&MME_APP_INITIAL_CONTEXT_SETUP_RSP(received_message_p));
} break;
case TIMER_HAS_EXPIRED: {
/* Check if it is the statistic timer */
if (received_message_p->ittiMsg.timer_has_expired.timer_id ==
mme_app_desc.statistic_timer_id) {
mme_app_statistics_display();
}
} break;
case TERMINATE_MESSAGE: {
/* Termination message received TODO -> release any data allocated */
itti_exit_task();
} break;
case S1AP_UE_CAPABILITIES_IND: {
mme_app_handle_s1ap_ue_capabilities_ind(&received_message_p->ittiMsg.s1ap_ue_cap_ind);
} break;
default: {
MME_APP_DEBUG("Unkwnon message ID %d:%s\n",
ITTI_MSG_ID(received_message_p), ITTI_MSG_NAME(received_message_p));
AssertFatal(0, "Unkwnon message ID %d:%s\n",
ITTI_MSG_ID(received_message_p), ITTI_MSG_NAME(received_message_p));
} break;
}
itti_free(ITTI_MSG_ORIGIN_ID(received_message_p), received_message_p);
received_message_p = NULL;
} }
return NULL; break;
case NAS_CONNECTION_ESTABLISHMENT_CNF: {
mme_app_handle_conn_est_cnf(&NAS_CONNECTION_ESTABLISHMENT_CNF(received_message_p));
}
break;
// From S1AP Initiating Message/EMM Attach Request
case MME_APP_CONNECTION_ESTABLISHMENT_IND: {
mme_app_handle_conn_est_ind(&MME_APP_CONNECTION_ESTABLISHMENT_IND(received_message_p));
}
break;
case MME_APP_INITIAL_CONTEXT_SETUP_RSP: {
mme_app_handle_initial_context_setup_rsp(&MME_APP_INITIAL_CONTEXT_SETUP_RSP(received_message_p));
}
break;
case TIMER_HAS_EXPIRED: {
/* Check if it is the statistic timer */
if (received_message_p->ittiMsg.timer_has_expired.timer_id ==
mme_app_desc.statistic_timer_id) {
mme_app_statistics_display();
}
}
break;
case TERMINATE_MESSAGE: {
/* Termination message received TODO -> release any data allocated */
itti_exit_task();
}
break;
case S1AP_UE_CAPABILITIES_IND: {
mme_app_handle_s1ap_ue_capabilities_ind(&received_message_p->ittiMsg.s1ap_ue_cap_ind);
}
break;
default: {
MME_APP_DEBUG("Unkwnon message ID %d:%s\n",
ITTI_MSG_ID(received_message_p), ITTI_MSG_NAME(received_message_p));
AssertFatal(0, "Unkwnon message ID %d:%s\n",
ITTI_MSG_ID(received_message_p), ITTI_MSG_NAME(received_message_p));
}
break;
}
itti_free(ITTI_MSG_ORIGIN_ID(received_message_p), received_message_p);
received_message_p = NULL;
}
return NULL;
} }
int mme_app_init(const mme_config_t *mme_config_p) int mme_app_init(const mme_config_t *mme_config_p)
{ {
MME_APP_DEBUG("Initializing MME applicative layer\n"); MME_APP_DEBUG("Initializing MME applicative layer\n");
memset(&mme_app_desc, 0, sizeof(mme_app_desc)); memset(&mme_app_desc, 0, sizeof(mme_app_desc));
/* Create the thread associated with MME applicative layer */ /* Create the thread associated with MME applicative layer */
if (itti_create_task(TASK_MME_APP, &mme_app_thread, NULL) < 0) { if (itti_create_task(TASK_MME_APP, &mme_app_thread, NULL) < 0) {
MME_APP_ERROR("MME APP create task failed\n"); MME_APP_ERROR("MME APP create task failed\n");
return -1; return -1;
} }
mme_app_desc.statistic_timer_period = mme_config_p->mme_statistic_timer; mme_app_desc.statistic_timer_period = mme_config_p->mme_statistic_timer;
/* Request for periodic timer */ /* Request for periodic timer */
if (timer_setup(mme_config_p->mme_statistic_timer, 0, TASK_MME_APP, INSTANCE_DEFAULT, if (timer_setup(mme_config_p->mme_statistic_timer, 0, TASK_MME_APP, INSTANCE_DEFAULT,
TIMER_PERIODIC, NULL, &mme_app_desc.statistic_timer_id) < 0) TIMER_PERIODIC, NULL, &mme_app_desc.statistic_timer_id) < 0) {
{ MME_APP_ERROR("Failed to request new timer for statistics with %ds "
MME_APP_ERROR("Failed to request new timer for statistics with %ds " "of periocidity\n", mme_config_p->mme_statistic_timer);
"of periocidity\n", mme_config_p->mme_statistic_timer); mme_app_desc.statistic_timer_id = 0;
mme_app_desc.statistic_timer_id = 0; }
}
MME_APP_DEBUG("Initializing MME applicative layer: DONE\n"); MME_APP_DEBUG("Initializing MME applicative layer: DONE\n");
return 0; return 0;
} }
+11 -11
View File
@@ -39,17 +39,17 @@
int int
mme_app_statistics_display(void) mme_app_statistics_display(void)
{ {
fprintf(stdout, "================== Statistics ==================\n"); fprintf(stdout, "================== Statistics ==================\n");
fprintf(stdout, " | Global | Since last display |\n"); fprintf(stdout, " | Global | Since last display |\n");
fprintf(stdout, "UE | %10u | %10u |\n", fprintf(stdout, "UE | %10u | %10u |\n",
mme_app_desc.mme_ue_contexts.nb_ue_managed, mme_app_desc.mme_ue_contexts.nb_ue_managed,
mme_app_desc.mme_ue_contexts.nb_ue_since_last_stat); mme_app_desc.mme_ue_contexts.nb_ue_since_last_stat);
fprintf(stdout, "Bearers | %10u | %10u |\n", fprintf(stdout, "Bearers | %10u | %10u |\n",
mme_app_desc.mme_ue_contexts.nb_bearers_managed, mme_app_desc.mme_ue_contexts.nb_bearers_managed,
mme_app_desc.mme_ue_contexts.nb_bearers_since_last_stat); mme_app_desc.mme_ue_contexts.nb_bearers_since_last_stat);
mme_app_desc.mme_ue_contexts.nb_ue_since_last_stat = 0; mme_app_desc.mme_ue_contexts.nb_ue_since_last_stat = 0;
mme_app_desc.mme_ue_contexts.nb_bearers_since_last_stat = 0; mme_app_desc.mme_ue_contexts.nb_bearers_since_last_stat = 0;
return 0; return 0;
} }

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