From 917e6443f5530bfb242205b708e91dcc538d3538 Mon Sep 17 00:00:00 2001 From: Sukchan Lee Date: Fri, 31 Mar 2017 00:15:13 +0900 Subject: [PATCH] PGW is added initially --- README.md | 6 +- configure.ac | 1 + lib/gtp/gtp_xact.c | 36 ++++++----- src/Makefile.am | 8 ++- src/cellwire.h | 3 + src/init.c | 3 + src/pgw/Makefile.am | 32 ++++++++++ src/pgw/context.c | 53 ++++++++++++++++ src/pgw/context.h | 41 +++++++++++++ src/pgw/event.c | 34 +++++++++++ src/pgw/event.h | 29 +++++++++ src/pgw/init.c | 87 +++++++++++++++++++++++++++ src/pgw/pgw_path.c | 136 ++++++++++++++++++++++++++++++++++++++++++ src/pgw/pgw_path.h | 20 +++++++ src/pgw/pgw_sm.c | 100 +++++++++++++++++++++++++++++++ src/pgw/s5c_handler.c | 13 ++++ src/pgw/s5c_handler.h | 18 ++++++ src/pgw/sm.h | 33 ++++++++++ src/sgw/context.c | 1 - src/sgw/s11_handler.c | 2 +- src/sgw/s11_handler.h | 8 +-- src/sgw/sgw_path.c | 2 +- src/sgw/sgw_sm.c | 8 +-- src/sgw/sm.h | 20 ------- 24 files changed, 641 insertions(+), 53 deletions(-) create mode 100644 src/pgw/Makefile.am create mode 100644 src/pgw/context.c create mode 100644 src/pgw/context.h create mode 100644 src/pgw/event.c create mode 100644 src/pgw/event.h create mode 100644 src/pgw/init.c create mode 100644 src/pgw/pgw_path.c create mode 100644 src/pgw/pgw_path.h create mode 100644 src/pgw/pgw_sm.c create mode 100644 src/pgw/s5c_handler.c create mode 100644 src/pgw/s5c_handler.h create mode 100644 src/pgw/sm.h diff --git a/README.md b/README.md index 9bd7df3891..ce94dbc9bb 100644 --- a/README.md +++ b/README.md @@ -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. diff --git a/configure.ac b/configure.ac index 932ff4091d..fd6b3b8175 100644 --- a/configure.ac +++ b/configure.ac @@ -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]) diff --git a/lib/gtp/gtp_xact.c b/lib/gtp/gtp_xact.c index 0ac274e14b..e62cc44d83 100644 --- a/lib/gtp/gtp_xact.c +++ b/lib/gtp/gtp_xact.c @@ -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); diff --git a/src/Makefile.am b/src/Makefile.am index 6608f4b4c3..bdafa2f713 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -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 \ diff --git a/src/cellwire.h b/src/cellwire.h index 495fd7498b..4731d0fd2d 100644 --- a/src/cellwire.h +++ b/src/cellwire.h @@ -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 */ diff --git a/src/init.c b/src/init.c index 8e720cdada..6f8f6839f4 100644 --- a/src/init.c +++ b/src/init.c @@ -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); diff --git a/src/pgw/Makefile.am b/src/pgw/Makefile.am new file mode 100644 index 0000000000..40b29df461 --- /dev/null +++ b/src/pgw/Makefile.am @@ -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) diff --git a/src/pgw/context.c b/src/pgw/context.c new file mode 100644 index 0000000000..46438cffdb --- /dev/null +++ b/src/pgw/context.c @@ -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; +} diff --git a/src/pgw/context.h b/src/pgw/context.h new file mode 100644 index 0000000000..2fcb137f13 --- /dev/null +++ b/src/pgw/context.h @@ -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__ */ diff --git a/src/pgw/event.c b/src/pgw/event.c new file mode 100644 index 0000000000..7d5fc236ba --- /dev/null +++ b/src/pgw/event.c @@ -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; +} diff --git a/src/pgw/event.h b/src/pgw/event.h new file mode 100644 index 0000000000..8e27c50ee3 --- /dev/null +++ b/src/pgw/event.h @@ -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__ */ diff --git a/src/pgw/init.c b/src/pgw/init.c new file mode 100644 index 0000000000..ac9f0dc165 --- /dev/null +++ b/src/pgw/init.c @@ -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; +} diff --git a/src/pgw/pgw_path.c b/src/pgw/pgw_path.c new file mode 100644 index 0000000000..99efc02afa --- /dev/null +++ b/src/pgw/pgw_path.c @@ -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); +} diff --git a/src/pgw/pgw_path.h b/src/pgw/pgw_path.h new file mode 100644 index 0000000000..b69746666c --- /dev/null +++ b/src/pgw/pgw_path.h @@ -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__ */ diff --git a/src/pgw/pgw_sm.c b/src/pgw/pgw_sm.c new file mode 100644 index 0000000000..77ac41b0f3 --- /dev/null +++ b/src/pgw/pgw_sm.c @@ -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; + } + } +} diff --git a/src/pgw/s5c_handler.c b/src/pgw/s5c_handler.c new file mode 100644 index 0000000000..d996637618 --- /dev/null +++ b/src/pgw/s5c_handler.c @@ -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"); +} diff --git a/src/pgw/s5c_handler.h b/src/pgw/s5c_handler.h new file mode 100644 index 0000000000..b6ef23d493 --- /dev/null +++ b/src/pgw/s5c_handler.h @@ -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__ */ diff --git a/src/pgw/sm.h b/src/pgw/sm.h new file mode 100644 index 0000000000..7aef295afd --- /dev/null +++ b/src/pgw/sm.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__ */ diff --git a/src/sgw/context.c b/src/sgw/context.c index c35f7087a8..467fa94a28 100644 --- a/src/sgw/context.c +++ b/src/sgw/context.c @@ -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"); diff --git a/src/sgw/s11_handler.c b/src/sgw/s11_handler.c index 5f055f4be5..c45ea7f817 100644 --- a/src/sgw/s11_handler.c +++ b/src/sgw/s11_handler.c @@ -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; diff --git a/src/sgw/s11_handler.h b/src/sgw/s11_handler.h index 0968239b68..6cc1d9a7e8 100644 --- a/src/sgw/s11_handler.h +++ b/src/sgw/s11_handler.h @@ -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__ */ diff --git a/src/sgw/sgw_path.c b/src/sgw/sgw_path.c index a07a1adaa4..aead539819 100644 --- a/src/sgw/sgw_path.c +++ b/src/sgw/sgw_path.c @@ -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 */ diff --git a/src/sgw/sgw_sm.c b/src/sgw/sgw_sm.c index 8eda09f89f..2466e77b52 100644 --- a/src/sgw/sgw_sm.c +++ b/src/sgw/sgw_sm.c @@ -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 */ } diff --git a/src/sgw/sm.h b/src/sgw/sm.h index 0771497887..de751a57e2 100644 --- a/src/sgw/sm.h +++ b/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))