PGW is added initially
This commit is contained in:
parent
be32184914
commit
917e6443f5
|
@ -12,11 +12,15 @@ The implementation consists in several components:
|
|||
|
||||
- lib/s6a : the freeDiameter wrapper for S6A
|
||||
|
||||
- lib/gtp : the GTPv2-C/GTP-U message encoding/decoding library
|
||||
- lib/gtp : the GTPv2-C/GTP-U protocol stack library
|
||||
|
||||
- src/mme : the heart of MME protocol stack
|
||||
|
||||
- src/hss : the heart of HSS protocol stack
|
||||
|
||||
- src/sgw : the heart of SGW protocol stack
|
||||
|
||||
- src/pgw : the heart of PGW protocol stack
|
||||
|
||||
|
||||
See INSTALL.md for information on building and using this software.
|
||||
|
|
|
@ -314,6 +314,7 @@ AC_CONFIG_FILES([lib/Makefile])
|
|||
AC_CONFIG_FILES([src/mme/Makefile])
|
||||
AC_CONFIG_FILES([src/hss/Makefile])
|
||||
AC_CONFIG_FILES([src/sgw/Makefile])
|
||||
AC_CONFIG_FILES([src/pgw/Makefile])
|
||||
AC_CONFIG_FILES([src/Makefile])
|
||||
AC_CONFIG_FILES([test/Makefile])
|
||||
AC_CONFIG_FILES([Makefile])
|
||||
|
|
|
@ -116,7 +116,8 @@ gtp_xact_t *gtp_xact_create(gtp_xact_ctx_t *context,
|
|||
list_append(xact->org == GTP_LOCAL_ORIGINATOR ?
|
||||
xact->gnode->local_list : xact->gnode->remote_list, xact);
|
||||
|
||||
d_trace(1, "%s Create : xid = 0x%x, type = %d\n",
|
||||
d_trace(1, "[%d]%s Create : xid = 0x%x, type = %d\n",
|
||||
gnode->port,
|
||||
xact->org == GTP_LOCAL_ORIGINATOR ? "LOCAL " : "REMOTE",
|
||||
xact->xid, xact->type);
|
||||
|
||||
|
@ -134,12 +135,13 @@ status_t gtp_xact_delete(gtp_xact_t *xact)
|
|||
{
|
||||
d_assert(xact, , "Null param");
|
||||
|
||||
d_trace(1, "%s Delete : xid = 0x%x, type = %d\n",
|
||||
d_assert(xact->gnode, , "Null param");
|
||||
|
||||
d_trace(1, "[%d]%s Delete : xid = 0x%x, type = %d\n",
|
||||
xact->gnode->port,
|
||||
xact->org == GTP_LOCAL_ORIGINATOR ? "LOCAL " : "REMOTE",
|
||||
xact->xid, xact->type);
|
||||
|
||||
d_assert(xact->gnode, , "Null param");
|
||||
|
||||
d_assert(xact->pkbuf, , "Null param");
|
||||
pkbuf_free(xact->pkbuf);
|
||||
|
||||
|
@ -194,8 +196,16 @@ status_t gtp_xact_commit(gtp_xact_t *xact)
|
|||
|
||||
d_assert(xact, goto out, "Null param");
|
||||
|
||||
d_trace(1, "%s Commit : xid = 0x%x, type = %d, "
|
||||
sock = xact->sock;
|
||||
d_assert(sock, goto out, "Null param");
|
||||
gnode = xact->gnode;
|
||||
d_assert(gnode, goto out, "Null param");
|
||||
pkbuf = xact->pkbuf;
|
||||
d_assert(pkbuf, goto out, "Null param");
|
||||
|
||||
d_trace(1, "[%d]%s Commit : xid = 0x%x, type = %d, "
|
||||
"retry_count = %d\n",
|
||||
xact->gnode->port,
|
||||
xact->org == GTP_LOCAL_ORIGINATOR ? "LOCAL " : "REMOTE",
|
||||
xact->xid, xact->type, xact->retry_count);
|
||||
|
||||
|
@ -203,13 +213,6 @@ status_t gtp_xact_commit(gtp_xact_t *xact)
|
|||
{
|
||||
if (xact->org == GTP_LOCAL_ORIGINATOR)
|
||||
{
|
||||
sock = xact->sock;
|
||||
d_assert(sock, goto out, "Null param");
|
||||
gnode = xact->gnode;
|
||||
d_assert(gnode, goto out, "Null param");
|
||||
pkbuf = xact->pkbuf;
|
||||
d_assert(pkbuf, goto out, "Null param");
|
||||
|
||||
rv = gtp_send(sock, gnode, pkbuf);
|
||||
if (rv != CORE_OK)
|
||||
{
|
||||
|
@ -291,7 +294,8 @@ gtp_xact_t *gtp_xact_find(gtp_node_t *gnode, pkbuf_t *pkbuf)
|
|||
|
||||
if (xact)
|
||||
{
|
||||
d_trace(1, "%s Find : xid = 0x%x, type = %d\n",
|
||||
d_trace(1, "[%d]%s Find : xid = 0x%x, type = %d\n",
|
||||
gnode->port,
|
||||
xact->org == GTP_LOCAL_ORIGINATOR ? "LOCAL " : "REMOTE",
|
||||
xact->xid, xact->type);
|
||||
}
|
||||
|
@ -321,7 +325,8 @@ gtp_xact_t *gtp_xact_recv(gtp_xact_ctx_t *context,
|
|||
GTP_SQN_TO_XID(h->sqn), h->type, pkbuf);
|
||||
}
|
||||
|
||||
d_trace(1, "%s Receive : xid = 0x%x, type = %d\n",
|
||||
d_trace(1, "[%d]%s Receive : xid = 0x%x, type = %d\n",
|
||||
gnode->port,
|
||||
xact->org == GTP_LOCAL_ORIGINATOR ? "LOCAL " : "REMOTE",
|
||||
xact->xid, xact->type);
|
||||
|
||||
|
@ -373,7 +378,8 @@ gtp_xact_t *gtp_xact_associated_send(gtp_xact_ctx_t *context,
|
|||
rv = gtp_xact_commit(xact);
|
||||
d_assert(rv == CORE_OK, return NULL, "Null param");
|
||||
|
||||
d_trace(1, "%s Send : xid = 0x%x, type = %d\n",
|
||||
d_trace(1, "[%d]%s Send : xid = 0x%x, type = %d\n",
|
||||
gnode->port,
|
||||
xact->org == GTP_LOCAL_ORIGINATOR ? "LOCAL " : "REMOTE",
|
||||
xact->xid, xact->type);
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
## Process this file with automake to produce Makefile.in.
|
||||
|
||||
SUBDIRS = mme hss sgw
|
||||
SUBDIRS = mme hss sgw pgw
|
||||
|
||||
noinst_LTLIBRARIES = libcellwire.la
|
||||
|
||||
|
@ -14,13 +14,15 @@ libcellwire_la_DEPENDENCIES = \
|
|||
$(top_srcdir)/lib/logger/liblogger.la \
|
||||
$(top_srcdir)/src/mme/libmme.la \
|
||||
$(top_srcdir)/src/hss/libhss.la \
|
||||
$(top_srcdir)/src/sgw/libsgw.la
|
||||
$(top_srcdir)/src/sgw/libsgw.la \
|
||||
$(top_srcdir)/src/pgw/libpgw.la
|
||||
|
||||
libcellwire_la_LIBADD = \
|
||||
$(top_srcdir)/lib/logger/liblogger.la \
|
||||
$(top_srcdir)/src/mme/libmme.la \
|
||||
$(top_srcdir)/src/hss/libhss.la \
|
||||
$(top_srcdir)/src/sgw/libsgw.la
|
||||
$(top_srcdir)/src/sgw/libsgw.la \
|
||||
$(top_srcdir)/src/pgw/libpgw.la
|
||||
|
||||
AM_CPPFLAGS = \
|
||||
-I$(top_srcdir)/lib/core/include \
|
||||
|
|
|
@ -20,6 +20,9 @@ CORE_DECLARE_NONSTD(void) hss_terminate(void);
|
|||
CORE_DECLARE(status_t) sgw_initialize();
|
||||
CORE_DECLARE_NONSTD(void) sgw_terminate(void);
|
||||
|
||||
CORE_DECLARE(status_t) pgw_initialize();
|
||||
CORE_DECLARE_NONSTD(void) pgw_terminate(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
|
|
@ -60,6 +60,8 @@ status_t cellwire_initialize(char *config_path, char *log_path)
|
|||
}
|
||||
|
||||
/* Parent */
|
||||
rv = pgw_initialize();
|
||||
if (rv != CORE_OK) return rv;
|
||||
rv = sgw_initialize();
|
||||
if (rv != CORE_OK) return rv;
|
||||
rv = mme_initialize();
|
||||
|
@ -78,6 +80,7 @@ void cellwire_terminate(void)
|
|||
thread_delete(net_thread);
|
||||
mme_terminate();
|
||||
sgw_terminate();
|
||||
pgw_terminate();
|
||||
|
||||
core_kill(hss_pid, SIGTERM);
|
||||
core_kill(logger_pid, SIGTERM);
|
||||
|
|
|
@ -0,0 +1,32 @@
|
|||
## Process this file with automake to produce Makefile.in.
|
||||
|
||||
noinst_LTLIBRARIES = libpgw.la
|
||||
|
||||
libpgw_la_SOURCES = \
|
||||
event.h context.h \
|
||||
pgw_path.h sm.h s11_handler.h
|
||||
|
||||
nodist_libpgw_la_SOURCES = \
|
||||
init.c event.c context.c \
|
||||
pgw_path.c pgw_sm.c s5c_handler.c
|
||||
|
||||
libpgw_la_DEPENDENCIES = \
|
||||
$(top_srcdir)/lib/core/src/libcore.la \
|
||||
$(top_srcdir)/lib/gtp/libgtp.la
|
||||
|
||||
libpgw_la_LIBADD = \
|
||||
$(top_srcdir)/lib/core/src/libcore.la \
|
||||
$(top_srcdir)/lib/gtp/libgtp.la
|
||||
|
||||
AM_CPPFLAGS = \
|
||||
-I$(top_srcdir)/lib/core/include \
|
||||
-I$(top_srcdir)/lib/3gpp \
|
||||
-I$(top_srcdir)/lib/gtp
|
||||
|
||||
AM_CFLAGS = \
|
||||
-Wall -Werror
|
||||
|
||||
MAINTAINERCLEANFILES = Makefile.in
|
||||
MOSTLYCLEANFILES = core *.stackdump
|
||||
|
||||
EXTRA_DIST = .libs $(noinst_LTLIBRARIES)
|
|
@ -0,0 +1,53 @@
|
|||
#define TRACE_MODULE _pgw_ctx
|
||||
|
||||
#include "core_debug.h"
|
||||
#include "core_pool.h"
|
||||
#include "core_index.h"
|
||||
|
||||
#include "context.h"
|
||||
#include "gtp_path.h"
|
||||
|
||||
static pgw_ctx_t self;
|
||||
|
||||
static int ctx_initialized = 0;
|
||||
|
||||
status_t pgw_ctx_init()
|
||||
{
|
||||
d_assert(ctx_initialized == 0, return CORE_ERROR,
|
||||
"MME context already has been initialized");
|
||||
|
||||
memset(&self, 0, sizeof(pgw_ctx_t));
|
||||
|
||||
self.s5c_addr = inet_addr("127.0.0.1");
|
||||
self.s5c_port = GTPV2_C_UDP_PORT + 3;
|
||||
self.s5c_node.addr = inet_addr("127.0.0.1");
|
||||
self.s5c_node.port = GTPV2_C_UDP_PORT + 2;
|
||||
list_init(&self.s5c_node.initial_list);
|
||||
list_init(&self.s5c_node.triggered_list);
|
||||
self.s5c_node.local_list = &self.s5c_node.initial_list;
|
||||
self.s5c_node.remote_list = &self.s5c_node.triggered_list;
|
||||
|
||||
self.s5u_addr = inet_addr("127.0.0.1");
|
||||
self.s5u_port = GTPV1_U_UDP_PORT + 1;
|
||||
self.s5u_node.addr = inet_addr("127.0.0.1");
|
||||
self.s5u_node.port = GTPV1_U_UDP_PORT;
|
||||
|
||||
ctx_initialized = 1;
|
||||
|
||||
return CORE_OK;
|
||||
}
|
||||
|
||||
status_t pgw_ctx_final()
|
||||
{
|
||||
d_assert(ctx_initialized == 1, return CORE_ERROR,
|
||||
"HyperCell context already has been finalized");
|
||||
|
||||
ctx_initialized = 0;
|
||||
|
||||
return CORE_OK;
|
||||
}
|
||||
|
||||
pgw_ctx_t* pgw_self()
|
||||
{
|
||||
return &self;
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
#ifndef __PGW_CTX_H__
|
||||
#define __PGW_CTX_H__
|
||||
|
||||
#include "core_list.h"
|
||||
#include "core_errno.h"
|
||||
#include "core_net.h"
|
||||
|
||||
#include "sm.h"
|
||||
|
||||
#include "gtp_xact.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
typedef struct _pgw_ctx_t {
|
||||
c_uint32_t s5c_addr; /* PGW S5-C local address */
|
||||
c_uint32_t s5c_port; /* PGW S5-C local port */
|
||||
net_sock_t* s5c_sock; /* PGW S5-C local listen socket */
|
||||
gtp_node_t s5c_node; /* PGW S5-C remote GTPv2-C node */
|
||||
|
||||
c_uint32_t s5u_addr; /* PGW S5-U local address */
|
||||
c_uint32_t s5u_port; /* PGW S5-U local port */
|
||||
net_sock_t* s5u_sock; /* PGW S5-U local listen socket */
|
||||
gtp_node_t s5u_node; /* PGW S5-U remote GTPv1-U node */
|
||||
|
||||
msgq_id queue_id; /* Queue for processing PGW control plane */
|
||||
tm_service_t tm_service; /* Timer Service */
|
||||
gtp_xact_ctx_t gtp_xact_ctx; /* GTP Transaction Context */
|
||||
} pgw_ctx_t;
|
||||
|
||||
CORE_DECLARE(status_t) pgw_ctx_init(void);
|
||||
CORE_DECLARE(status_t) pgw_ctx_final(void);
|
||||
|
||||
CORE_DECLARE(pgw_ctx_t*) pgw_self(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* __PGW_CTX_H__ */
|
|
@ -0,0 +1,34 @@
|
|||
#define TRACE_MODULE _pgw_evt
|
||||
|
||||
#include "core_debug.h"
|
||||
#include "event.h"
|
||||
#include "context.h"
|
||||
|
||||
static char EVT_NAME_TM_PGW_T3[] = "TM_PGW_PGW_T3";
|
||||
|
||||
static char EVT_NAME_MSG_PGW_S5C[] = "MSG_PGW_S5C";
|
||||
|
||||
char* pgw_event_get_name(event_t *e)
|
||||
{
|
||||
if (e == NULL)
|
||||
return FSM_NAME_INIT_SIG;
|
||||
|
||||
switch (event_get(e))
|
||||
{
|
||||
case FSM_ENTRY_SIG:
|
||||
return FSM_NAME_ENTRY_SIG;
|
||||
case FSM_EXIT_SIG:
|
||||
return FSM_NAME_EXIT_SIG;
|
||||
|
||||
case EVT_TM_PGW_T3:
|
||||
return EVT_NAME_TM_PGW_T3;
|
||||
|
||||
case EVT_MSG_PGW_S5C:
|
||||
return EVT_NAME_MSG_PGW_S5C;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return EVT_NAME_UNKNOWN;
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
#ifndef __PGW_EVENT_H__
|
||||
#define __PGW_EVENT_H__
|
||||
|
||||
#include "core_event.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
typedef enum {
|
||||
PGW_EVT_BASE = FSM_USER_SIG,
|
||||
|
||||
EVT_TM_PGW_T3,
|
||||
|
||||
EVT_MSG_PGW_S5C,
|
||||
|
||||
PGW_EVT_TOP,
|
||||
|
||||
} event_e;
|
||||
|
||||
#define pgw_event_send(__ptr_e) event_send(pgw_self()->queue_id, (__ptr_e))
|
||||
|
||||
CORE_DECLARE(char*) pgw_event_get_name(event_t *e);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* __PGW_EVENT_H__ */
|
|
@ -0,0 +1,87 @@
|
|||
#define TRACE_MODULE _pgw_init
|
||||
|
||||
#include "core_debug.h"
|
||||
#include "core_thread.h"
|
||||
|
||||
#include "context.h"
|
||||
#include "event.h"
|
||||
|
||||
static thread_id pgw_sm_thread;
|
||||
void *THREAD_FUNC pgw_sm_main(thread_id id, void *data);
|
||||
|
||||
status_t pgw_initialize()
|
||||
{
|
||||
status_t rv;
|
||||
|
||||
rv = pgw_ctx_init();
|
||||
if (rv != CORE_OK) return rv;
|
||||
|
||||
rv = thread_create(&pgw_sm_thread, NULL, pgw_sm_main, NULL);
|
||||
if (rv != CORE_OK) return rv;
|
||||
|
||||
return CORE_OK;
|
||||
}
|
||||
|
||||
void pgw_terminate(void)
|
||||
{
|
||||
thread_delete(pgw_sm_thread);
|
||||
|
||||
pgw_ctx_final();
|
||||
}
|
||||
|
||||
void *THREAD_FUNC pgw_sm_main(thread_id id, void *data)
|
||||
{
|
||||
event_t event;
|
||||
pgw_sm_t pgw_sm;
|
||||
c_time_t prev_tm, now_tm;
|
||||
int r;
|
||||
|
||||
memset(&event, 0, sizeof(event_t));
|
||||
|
||||
pgw_self()->queue_id = event_create();
|
||||
d_assert(pgw_self()->queue_id, return NULL,
|
||||
"PGW event queue creation failed");
|
||||
tm_service_init(&pgw_self()->tm_service);
|
||||
gtp_xact_init(&pgw_self()->gtp_xact_ctx, &pgw_self()->tm_service,
|
||||
EVT_TM_PGW_T3, 3000, 3); /* 3 sec, 3 retry-count */
|
||||
|
||||
fsm_create(&pgw_sm.fsm, pgw_state_initial, pgw_state_final);
|
||||
d_assert(&pgw_sm.fsm, return NULL, "PGW state machine creation failed");
|
||||
fsm_init((fsm_t*)&pgw_sm, 0);
|
||||
|
||||
prev_tm = time_now();
|
||||
|
||||
while ((!thread_should_stop()))
|
||||
{
|
||||
r = event_timedrecv(pgw_self()->queue_id, &event, EVENT_WAIT_TIMEOUT);
|
||||
|
||||
d_assert(r != CORE_ERROR, continue,
|
||||
"While receiving a event message, error occurs");
|
||||
|
||||
now_tm = time_now();
|
||||
|
||||
/* if the gap is over 10 ms, execute preriodic jobs */
|
||||
if (now_tm - prev_tm > EVENT_WAIT_TIMEOUT)
|
||||
{
|
||||
tm_execute_tm_service(
|
||||
&pgw_self()->tm_service, pgw_self()->queue_id);
|
||||
|
||||
prev_tm = now_tm;
|
||||
}
|
||||
|
||||
if (r == CORE_TIMEUP)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
fsm_dispatch((fsm_t*)&pgw_sm, (fsm_event_t*)&event);
|
||||
}
|
||||
|
||||
fsm_final((fsm_t*)&pgw_sm, 0);
|
||||
fsm_clear((fsm_t*)&pgw_sm);
|
||||
|
||||
gtp_xact_final();
|
||||
event_delete(pgw_self()->queue_id);
|
||||
|
||||
return NULL;
|
||||
}
|
|
@ -0,0 +1,136 @@
|
|||
#define TRACE_MODULE _pgw_path
|
||||
#include "core_debug.h"
|
||||
#include "core_pkbuf.h"
|
||||
#include "core_net.h"
|
||||
|
||||
#include "3gpp_defs.h"
|
||||
#include "gtp_path.h"
|
||||
|
||||
#include "context.h"
|
||||
#include "pgw_path.h"
|
||||
|
||||
static int _gtpv2_c_recv_cb(net_sock_t *sock, void *data)
|
||||
{
|
||||
event_t e;
|
||||
status_t rv;
|
||||
pkbuf_t *pkbuf = NULL;
|
||||
gtp_node_t *gnode = data;
|
||||
|
||||
d_assert(sock, return -1, "Null param");
|
||||
d_assert(gnode, return -1, "Null param");
|
||||
|
||||
pkbuf = gtp_read(sock);
|
||||
if (pkbuf == NULL)
|
||||
{
|
||||
if (sock->sndrcv_errno == EAGAIN)
|
||||
return 0;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
d_trace(1, "S5-C PDU received from PGW\n");
|
||||
d_trace_hex(1, pkbuf->payload, pkbuf->len);
|
||||
|
||||
event_set(&e, EVT_MSG_PGW_S5C);
|
||||
event_set_param1(&e, (c_uintptr_t)sock);
|
||||
event_set_param2(&e, (c_uintptr_t)gnode);
|
||||
event_set_param3(&e, (c_uintptr_t)pkbuf);
|
||||
rv = pgw_event_send(&e);
|
||||
if (rv != CORE_OK)
|
||||
{
|
||||
d_error("pgw_event_send error");
|
||||
pkbuf_free(pkbuf);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _gtpv1_u_recv_cb(net_sock_t *sock, void *data)
|
||||
{
|
||||
pkbuf_t *pkbuf = NULL;
|
||||
gtp_node_t *gnode = data;
|
||||
|
||||
d_assert(sock, return -1, "Null param");
|
||||
d_assert(gnode, return -1, "Null param");
|
||||
|
||||
pkbuf = gtp_read(sock);
|
||||
if (pkbuf == NULL)
|
||||
{
|
||||
if (sock->sndrcv_errno == EAGAIN)
|
||||
return 0;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
d_trace(1, "S5-U PDU received from GTP\n");
|
||||
d_trace_hex(1, pkbuf->payload, pkbuf->len);
|
||||
|
||||
/* TODO */
|
||||
|
||||
pkbuf_free(pkbuf);
|
||||
return 0;
|
||||
}
|
||||
|
||||
status_t pgw_path_open()
|
||||
{
|
||||
status_t rv;
|
||||
|
||||
rv = gtp_listen(&pgw_self()->s5c_sock, _gtpv2_c_recv_cb,
|
||||
pgw_self()->s5c_addr, pgw_self()->s5c_port, &pgw_self()->s5c_node);
|
||||
if (rv != CORE_OK)
|
||||
{
|
||||
d_error("Can't establish S5-C Path for PGW");
|
||||
return rv;
|
||||
}
|
||||
|
||||
rv = gtp_listen(&pgw_self()->s5u_sock, _gtpv1_u_recv_cb,
|
||||
pgw_self()->s5u_addr, pgw_self()->s5u_port, &pgw_self()->s5u_node);
|
||||
if (rv != CORE_OK)
|
||||
{
|
||||
d_error("Can't establish S5-U Path for PGW");
|
||||
return rv;
|
||||
}
|
||||
|
||||
return CORE_OK;
|
||||
}
|
||||
|
||||
status_t pgw_path_close()
|
||||
{
|
||||
status_t rv;
|
||||
|
||||
rv = gtp_close(pgw_self()->s5c_sock);
|
||||
if (rv != CORE_OK)
|
||||
{
|
||||
d_error("Can't close S5-C Path for MME");
|
||||
return rv;
|
||||
}
|
||||
|
||||
rv = gtp_close(pgw_self()->s5u_sock);
|
||||
if (rv != CORE_OK)
|
||||
{
|
||||
d_error("Can't close S5-U Path for MME");
|
||||
return rv;
|
||||
}
|
||||
|
||||
return CORE_OK;
|
||||
}
|
||||
|
||||
gtp_xact_t *pgw_s5c_send_to_sgw(c_uint8_t type, pkbuf_t *pkbuf)
|
||||
{
|
||||
gtp_xact_t *xact;
|
||||
|
||||
d_assert(pkbuf, return NULL, "Null param");
|
||||
|
||||
xact = gtp_xact_send(&pgw_self()->gtp_xact_ctx, pgw_self()->s5c_sock,
|
||||
&pgw_self()->s5c_node, type, pkbuf);
|
||||
d_assert(xact, return NULL, "Null param");
|
||||
|
||||
return xact;
|
||||
}
|
||||
|
||||
status_t pgw_s5u_send_to_sgw(pkbuf_t *pkbuf)
|
||||
{
|
||||
d_assert(pkbuf, return CORE_ERROR, "Null param");
|
||||
return gtp_send(pgw_self()->s5u_sock, &pgw_self()->s5u_node, pkbuf);
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
#ifndef __PGW_PATH_H__
|
||||
#define __PGW_PATH_H__
|
||||
|
||||
#include "gtp_xact.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
CORE_DECLARE(status_t) pgw_path_open();
|
||||
CORE_DECLARE(status_t) pgw_path_close();
|
||||
|
||||
CORE_DECLARE(gtp_xact_t *) pgw_s5c_send_to_sgw(c_uint8_t type, pkbuf_t *pkbuf);
|
||||
CORE_DECLARE(status_t) pgw_s5u_send_to_sgw(pkbuf_t *pkbuf);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* __PGW_PATH_H__ */
|
|
@ -0,0 +1,100 @@
|
|||
#define TRACE_MODULE _pgw_sm
|
||||
#include "core_debug.h"
|
||||
|
||||
#include "sm.h"
|
||||
#include "context.h"
|
||||
#include "event.h"
|
||||
#include "pgw_path.h"
|
||||
#include "s5c_handler.h"
|
||||
|
||||
void pgw_state_initial(pgw_sm_t *s, event_t *e)
|
||||
{
|
||||
pgw_sm_trace(1, e);
|
||||
|
||||
d_assert(s, return, "Null param");
|
||||
|
||||
FSM_TRAN(s, &pgw_state_operational);
|
||||
}
|
||||
|
||||
void pgw_state_final(pgw_sm_t *s, event_t *e)
|
||||
{
|
||||
pgw_sm_trace(1, e);
|
||||
|
||||
d_assert(s, return, "Null param");
|
||||
}
|
||||
|
||||
void pgw_state_operational(pgw_sm_t *s, event_t *e)
|
||||
{
|
||||
status_t rv;
|
||||
|
||||
pgw_sm_trace(1, e);
|
||||
|
||||
d_assert(s, return, "Null param");
|
||||
|
||||
switch (event_get(e))
|
||||
{
|
||||
case FSM_ENTRY_SIG:
|
||||
{
|
||||
rv = pgw_path_open();
|
||||
if (rv != CORE_OK)
|
||||
{
|
||||
d_error("Can't establish S11 path");
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case FSM_EXIT_SIG:
|
||||
{
|
||||
rv = pgw_path_close();
|
||||
if (rv != CORE_OK)
|
||||
{
|
||||
d_error("Can't close S11 path");
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case EVT_MSG_PGW_S5C:
|
||||
{
|
||||
net_sock_t *sock = (net_sock_t *)event_get_param1(e);
|
||||
gtp_node_t *gnode = (gtp_node_t *)event_get_param2(e);
|
||||
pkbuf_t *pkbuf = (pkbuf_t *)event_get_param3(e);
|
||||
gtp_xact_t *xact = NULL;
|
||||
gtp_message_t gtp_message;
|
||||
|
||||
d_assert(sock, break, "Null param");
|
||||
d_assert(gnode, break, "Null param");
|
||||
d_assert(pkbuf, break, "Null param");
|
||||
|
||||
xact = gtp_xact_recv(&pgw_self()->gtp_xact_ctx, sock, gnode, pkbuf);
|
||||
d_assert(xact, break, "Null param");
|
||||
|
||||
rv = gtp_parse_msg(xact->type, >p_message, pkbuf);
|
||||
d_assert(rv == CORE_OK, break, "parse error");
|
||||
|
||||
switch(xact->type)
|
||||
{
|
||||
case GTP_CREATE_SESSION_REQUEST_TYPE:
|
||||
{
|
||||
pgw_s5c_handle_create_session_request(
|
||||
xact, >p_message.create_session_request);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case EVT_TM_PGW_T3:
|
||||
{
|
||||
gtp_xact_t *xact = (gtp_xact_t *)event_get_param1(e);
|
||||
d_assert(xact, break, "Nill param");
|
||||
|
||||
gtp_xact_commit(xact);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
d_error("No handler for event %s", pgw_event_get_name(e));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
#define TRACE_MODULE _pgw_handler
|
||||
|
||||
#include "core_debug.h"
|
||||
|
||||
#include "event.h"
|
||||
#include "pgw_path.h"
|
||||
#include "s5c_handler.h"
|
||||
|
||||
void pgw_s5c_handle_create_session_request(
|
||||
gtp_xact_t *xact, gtp_create_session_request_t *req)
|
||||
{
|
||||
d_info("pgw_s5c_handle_create_session_request");
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
#ifndef __PGW_S5C_HANDLER_H__
|
||||
#define __PGW_S5C_HANDLER_H__
|
||||
|
||||
#include "gtp_tlv.h"
|
||||
#include "context.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
CORE_DECLARE(void) pgw_s5c_handle_create_session_request(
|
||||
gtp_xact_t *xact, gtp_create_session_request_t *req);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* __PGW_S5C_HANDLER_H__ */
|
|
@ -0,0 +1,33 @@
|
|||
#ifndef __PGW_SM_H__
|
||||
#define __PGW_SM_H__
|
||||
|
||||
#include "core_param.h"
|
||||
#include "core_fsm.h"
|
||||
|
||||
#include "event.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
typedef struct _pgw_sm_t {
|
||||
fsm_t fsm;
|
||||
void *ctx;
|
||||
} pgw_sm_t;
|
||||
|
||||
void pgw_state_initial(pgw_sm_t *s, event_t *e);
|
||||
void pgw_state_final(pgw_sm_t *s, event_t *e);
|
||||
void pgw_state_operational(pgw_sm_t *s, event_t *e);
|
||||
void pgw_state_exception(pgw_sm_t *s, event_t *e);
|
||||
|
||||
#define pgw_sm_print(__pe) \
|
||||
d_print("%s(): %s\n", __func__, pgw_event_get_name(__pe))
|
||||
|
||||
#define pgw_sm_trace(__l, __pe) \
|
||||
d_trace(__l, "%s(): %s\n", __func__, pgw_event_get_name(__pe))
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* !__PGW_SM_H__ */
|
|
@ -37,7 +37,6 @@ status_t sgw_ctx_init()
|
|||
list_init(&s11_list);
|
||||
list_init(&s5c_list);
|
||||
|
||||
/* Initialize MME context */
|
||||
memset(&self, 0, sizeof(sgw_ctx_t));
|
||||
|
||||
self.s11_addr = inet_addr("127.0.0.1");
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
#include "sgw_path.h"
|
||||
#include "s11_handler.h"
|
||||
|
||||
void sgw_handle_create_session_request(
|
||||
void sgw_s11_handle_create_session_request(
|
||||
gtp_xact_t *xact, gtp_create_session_request_t *req)
|
||||
{
|
||||
status_t rv;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
#ifndef __SGW_HANDLER_H__
|
||||
#define __SGW_HANDLER_H__
|
||||
#ifndef __SGW_S11_HANDLER_H__
|
||||
#define __SGW_S11_HANDLER_H__
|
||||
|
||||
#include "gtp_tlv.h"
|
||||
#include "context.h"
|
||||
|
@ -8,11 +8,11 @@
|
|||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
CORE_DECLARE(void) sgw_handle_create_session_request(
|
||||
CORE_DECLARE(void) sgw_s11_handle_create_session_request(
|
||||
gtp_xact_t *xact, gtp_create_session_request_t *req);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* __SGW_HANDLER_H__ */
|
||||
#endif /* __SGW_S11_HANDLER_H__ */
|
||||
|
|
|
@ -74,7 +74,7 @@ static int _gtpv1_u_recv_cb(net_sock_t *sock, void *data)
|
|||
return -1;
|
||||
}
|
||||
|
||||
d_trace(1, "S5U PDU received from GTP\n");
|
||||
d_trace(1, "S5-U PDU received from GTP\n");
|
||||
d_trace_hex(1, pkbuf->payload, pkbuf->len);
|
||||
|
||||
/* TODO */
|
||||
|
|
|
@ -14,9 +14,6 @@ void sgw_state_initial(sgw_sm_t *s, event_t *e)
|
|||
d_assert(s, return, "Null param");
|
||||
|
||||
FSM_TRAN(s, &sgw_state_operational);
|
||||
{
|
||||
_sgw_sm = 100;
|
||||
}
|
||||
}
|
||||
|
||||
void sgw_state_final(sgw_sm_t *s, event_t *e)
|
||||
|
@ -79,7 +76,7 @@ void sgw_state_operational(sgw_sm_t *s, event_t *e)
|
|||
{
|
||||
case GTP_CREATE_SESSION_REQUEST_TYPE:
|
||||
{
|
||||
sgw_handle_create_session_request(
|
||||
sgw_s11_handle_create_session_request(
|
||||
xact, >p_message.create_session_request);
|
||||
break;
|
||||
}
|
||||
|
@ -101,7 +98,4 @@ void sgw_state_operational(sgw_sm_t *s, event_t *e)
|
|||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* If event was packet type, its buffer allocated by data-plane should
|
||||
* be freed here */
|
||||
}
|
||||
|
|
20
src/sgw/sm.h
20
src/sgw/sm.h
|
@ -20,26 +20,6 @@ void sgw_state_final(sgw_sm_t *s, event_t *e);
|
|||
void sgw_state_operational(sgw_sm_t *s, event_t *e);
|
||||
void sgw_state_exception(sgw_sm_t *s, event_t *e);
|
||||
|
||||
typedef struct _s11_sm_t {
|
||||
fsm_t fsm;
|
||||
void *ctx;
|
||||
} s11_sm_t;
|
||||
|
||||
void sgw_s11_state_initial(s11_sm_t *s, event_t *e);
|
||||
void sgw_s11_state_final(s11_sm_t *s, event_t *e);
|
||||
void sgw_s11_state_operational(s11_sm_t *s, event_t *e);
|
||||
void sgw_s11_state_exception(s11_sm_t *s, event_t *e);
|
||||
|
||||
typedef struct _s5c_sm_t {
|
||||
fsm_t fsm;
|
||||
void *ctx;
|
||||
} s5c_sm_t;
|
||||
|
||||
void sgw_s5c_state_initial(s5c_sm_t *s, event_t *e);
|
||||
void sgw_s5c_state_final(s5c_sm_t *s, event_t *e);
|
||||
void sgw_s5c_state_operational(s5c_sm_t *s, event_t *e);
|
||||
void sgw_s5c_state_exception(s5c_sm_t *s, event_t *e);
|
||||
|
||||
#define sgw_sm_print(__pe) \
|
||||
d_print("%s(): %s\n", __func__, sgw_event_get_name(__pe))
|
||||
|
||||
|
|
Loading…
Reference in New Issue