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:
@@ -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
@@ -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
@@ -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>
|
||||||
|
|||||||
@@ -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_ */
|
||||||
|
|||||||
@@ -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_ */
|
||||||
|
|||||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
|
||||||
|
|||||||
@@ -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
@@ -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_ */
|
||||||
|
|||||||
@@ -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_ */
|
||||||
|
|||||||
@@ -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_ */
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
|
|
||||||
|
|||||||
@@ -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_ */
|
||||||
|
|||||||
@@ -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_ */
|
||||||
|
|||||||
@@ -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_ */
|
||||||
|
|||||||
@@ -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
@@ -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_ */
|
||||||
|
|||||||
@@ -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(>puah_tg_reg);
|
register_target(>puah_tg_reg);
|
||||||
#else
|
#else
|
||||||
xtables_register_target(>puah_tg_reg);
|
xtables_register_target(>puah_tg_reg);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -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)));
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -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(>purh_tg_reg);
|
register_target(>purh_tg_reg);
|
||||||
#else
|
#else
|
||||||
xtables_register_target(>purh_tg_reg);
|
xtables_register_target(>purh_tg_reg);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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)));
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+664
-626
File diff suppressed because it is too large
Load Diff
@@ -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_ */
|
||||||
|
|||||||
@@ -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_ */
|
||||||
|
|||||||
@@ -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
@@ -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(>pu_2_print_buffer[buffer_marker], GTPU_2_PRINT_BUFFER_LEN - buffer_marker,
|
buffer_marker+=snprintf(>pu_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(>pu_2_print_buffer[buffer_marker], GTPU_2_PRINT_BUFFER_LEN - buffer_marker, " |\n");
|
buffer_marker+=snprintf(>pu_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(>pu_2_print_buffer[buffer_marker], GTPU_2_PRINT_BUFFER_LEN - buffer_marker, " %04ld |", octet_index);
|
buffer_marker+=snprintf(>pu_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(>pu_2_print_buffer[buffer_marker], GTPU_2_PRINT_BUFFER_LEN - buffer_marker, " ");
|
buffer_marker+=snprintf(>pu_2_print_buffer[buffer_marker], GTPU_2_PRINT_BUFFER_LEN - buffer_marker, " ");
|
||||||
//GTPU_DEBUG(" ");
|
|
||||||
|
//GTPU_DEBUG(" ");
|
||||||
buffer_marker+=snprintf(>pu_2_print_buffer[buffer_marker], GTPU_2_PRINT_BUFFER_LEN - buffer_marker, " |\n");
|
buffer_marker+=snprintf(>pu_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**)>pv1u_teid2enb_info);
|
hash_rc = hashtable_get(gtpv1u_sgw_data.S1U_mapping, reqP->sgw_S1u_teid, (void**)>pv1u_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**)>pv1u_teid2enb_info);
|
|
||||||
|
|
||||||
if (hash_rc == HASH_TABLE_KEY_NOT_EXISTS) {
|
|
||||||
GTPU_ERROR("nwGtpv1uProcessUlpReq failed: while getting teid %u in hashtable S1U_mapping\n", data_req_p->local_S1u_teid);
|
|
||||||
} else {
|
|
||||||
stack_req.apiType = NW_GTPV1U_ULP_API_SEND_TPDU;
|
|
||||||
//stack_req.apiInfo.sendtoInfo.teid = data_req_p->local_S1u_teid;
|
|
||||||
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**)>pv1u_teid2enb_info);
|
||||||
|
|
||||||
|
if (hash_rc == HASH_TABLE_KEY_NOT_EXISTS) {
|
||||||
|
GTPU_ERROR("nwGtpv1uProcessUlpReq failed: while getting teid %u in hashtable S1U_mapping\n", data_req_p->local_S1u_teid);
|
||||||
|
} else {
|
||||||
|
stack_req.apiType = NW_GTPV1U_ULP_API_SEND_TPDU;
|
||||||
|
//stack_req.apiInfo.sendtoInfo.teid = data_req_p->local_S1u_teid;
|
||||||
|
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(>pv1u_sgw_data, 0, sizeof(gtpv1u_sgw_data));
|
memset(>pv1u_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(>pv1u_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(>pv1u_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, >pv1u_thread, NULL) < 0) {
|
|
||||||
GTPU_ERROR("gtpv1u phtread_create: %s", strerror(errno));
|
if (itti_create_task(TASK_GTPV1_U, >pv1u_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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
@@ -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
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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
@@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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
@@ -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(¤t_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(¤t_bearer_p->p_gw_address,0, sizeof(ip_address_t));
|
||||||
|
|
||||||
|
if (create_sess_resp_pP->bearer_context_created.bearer_level_qos != NULL) {
|
||||||
|
current_bearer_p->qci = create_sess_resp_pP->bearer_context_created.bearer_level_qos->qci;
|
||||||
|
current_bearer_p->prio_level = create_sess_resp_pP->bearer_context_created.bearer_level_qos->pl;
|
||||||
|
current_bearer_p->pre_emp_vulnerability = create_sess_resp_pP->bearer_context_created.bearer_level_qos->pvi;
|
||||||
|
current_bearer_p->pre_emp_capability = create_sess_resp_pP->bearer_context_created.bearer_level_qos->pci;
|
||||||
|
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,
|
||||||
¤t_bearer_p->s_gw_address, sizeof(ip_address_t));
|
¤t_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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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_ */
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
Reference in New Issue
Block a user