diff --git a/lib/gtp/Makefile.am b/lib/gtp/Makefile.am index e6e9148a1..b5be62236 100644 --- a/lib/gtp/Makefile.am +++ b/lib/gtp/Makefile.am @@ -3,10 +3,10 @@ noinst_LTLIBRARIES = libgtp.la libgtp_la_SOURCES = \ - gtp_tlv.h gtp_types.h gtp_path.h + gtp_tlv.h gtp_types.h gtp_path.h gtp_xact.h nodist_libgtp_la_SOURCES = \ - gtp_tlv.c gtp_types.c gtp_path.c + gtp_tlv.c gtp_types.c gtp_path.c gtp_xact.c libgtp_la_DEPENDENCIES = \ $(top_srcdir)/lib/3gpp/lib3gpp.la diff --git a/lib/gtp/gtp_path.c b/lib/gtp/gtp_path.c index 44180d762..b0e3e6eac 100644 --- a/lib/gtp/gtp_path.c +++ b/lib/gtp/gtp_path.c @@ -6,63 +6,69 @@ #include "3gpp_defs.h" #include "gtp_path.h" -status_t gtp_open(net_sock_t **sock, net_sock_handler handler, void *data, - const c_uint32_t addr, const c_uint16_t port) +status_t gtp_open(gtp_node_t *gnode, net_sock_handler handler) { char buf[INET_ADDRSTRLEN]; int rc; - rc = net_listen_with_addr(sock, SOCK_DGRAM, IPPROTO_UDP, port, addr); + d_assert(gnode, return CORE_ERROR, "Null param"); + + rc = net_listen_with_addr(&gnode->s, SOCK_DGRAM, IPPROTO_UDP, + gnode->local_port, gnode->local_addr); if (rc != 0) { d_error("Can't establish GTP[%s:%d] path(%d:%s)", - INET_NTOP(&addr, buf), port, errno, strerror(errno)); + INET_NTOP(&gnode->local_addr, buf), gnode->local_port, + errno, strerror(errno)); return CORE_ERROR; } - rc = net_register_sock(*sock, handler, data); + rc = net_register_sock(gnode->s, handler, gnode); if (rc != 0) { d_error("Can't establish GTP path(%d:%s)", errno, strerror(errno)); - net_close(*sock); + net_close(gnode->s); return CORE_ERROR; } - d_trace(1, "gtp_listen() %s:%d\n", INET_NTOP(&addr, buf), port); + d_trace(1, "gtp_listen() %s:%d\n", + INET_NTOP(&gnode->local_addr, buf), gnode->local_port); return CORE_OK; } -status_t gtp_close(net_sock_t *sock) +status_t gtp_close(gtp_node_t *gnode) { - d_assert(sock, return CORE_ERROR, "Null param"); + d_assert(gnode, return CORE_ERROR, "Null param"); + d_assert(gnode->s, return CORE_ERROR, "Null param"); - net_unregister_sock(sock); - net_close(sock); + net_unregister_sock(gnode->s); + net_close(gnode->s); return CORE_OK; } -pkbuf_t *gtp_read(net_sock_t *net_sock) +pkbuf_t *gtp_read(gtp_node_t *gnode) { pkbuf_t *pkb; int r; - d_assert(net_sock, return NULL, "Null param"); + d_assert(gnode, return NULL, "Null param"); + d_assert(gnode->s, return NULL, "Null param"); pkb = pkbuf_alloc(0, MAX_SDU_LEN); d_assert(pkb, return NULL, "Can't allocate pkbuf"); - r = net_read(net_sock, pkb->payload, pkb->len, 0); + r = net_read(gnode->s, pkb->payload, pkb->len, 0); if (r <= 0) { pkbuf_free(pkb); - if (net_sock->sndrcv_errno != EAGAIN) + if (gnode->s->sndrcv_errno != EAGAIN) { d_warn("net_read failed(%d:%s)", - net_sock->sndrcv_errno, strerror(net_sock->sndrcv_errno)); + gnode->s->sndrcv_errno, strerror(gnode->s->sndrcv_errno)); } return NULL; @@ -75,23 +81,24 @@ pkbuf_t *gtp_read(net_sock_t *net_sock) } } -status_t gtp_send(net_sock_t *s, - pkbuf_t *pkbuf, c_uint32_t ip_addr, c_uint16_t port) +status_t gtp_send(gtp_node_t *gnode, pkbuf_t *pkbuf) { char buf[INET_ADDRSTRLEN]; ssize_t sent; - d_assert(s, return CORE_ERROR, "Null param"); + d_assert(gnode, return CORE_ERROR, "Null param"); + d_assert(gnode->s, return CORE_ERROR, "Null param"); d_assert(pkbuf, return CORE_ERROR, "Null param"); - sent = net_sendto(s, pkbuf->payload, pkbuf->len, ip_addr, port); - d_trace(1,"Sent %d->%d bytes to [%s:%d]\n", - pkbuf->len, sent, INET_NTOP(&ip_addr, buf), port); + sent = net_sendto(gnode->s, pkbuf->payload, pkbuf->len, + gnode->remote_addr, gnode->remote_port); + d_trace(1,"Sent %d->%d bytes to [%s:%d]\n", pkbuf->len, sent, + INET_NTOP(&gnode->remote_addr, buf), gnode->remote_port); d_trace_hex(1, pkbuf->payload, pkbuf->len); if (sent < 0 || sent != pkbuf->len) { d_error("net_send error (%d:%s)", - s->sndrcv_errno, strerror(s->sndrcv_errno)); + gnode->s->sndrcv_errno, strerror(gnode->s->sndrcv_errno)); return CORE_ERROR; } diff --git a/lib/gtp/gtp_path.h b/lib/gtp/gtp_path.h index ec0b583b6..36aabdde7 100644 --- a/lib/gtp/gtp_path.h +++ b/lib/gtp/gtp_path.h @@ -3,22 +3,49 @@ #include "core_pkbuf.h" #include "core_net.h" +#include "core_list.h" #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ -#define S11_UDP_PORT 2123 -#define S5_UDP_PORT 2152 +#define GTPV2_C_UDP_PORT 2123 +#define GTPV1_U_UDP_PORT 2152 -CORE_DECLARE(status_t) gtp_open(net_sock_t **sock, net_sock_handler handler, - void *data, const c_uint32_t addr, const c_uint16_t port); -CORE_DECLARE(status_t) gtp_close(net_sock_t *sock); +#define GTP_COMPARE_REMOTE_NODE(__id1, __id2) \ + (((__id1)->remote_addr) == ((__id2)->remote_addr) && \ + ((__id1)->remote_port) == ((__id2)->remote_port)) -CORE_DECLARE(pkbuf_t *) gtp_read(net_sock_t *net_sock); +/** + * This structure keeps active transactions and their histrory */ +typedef struct _gtp_xact_info_t { + list_t local_xlist; /**< List of local initiated transactions */ + list_t remote_xlist; /**< List of Remote initiated transactions */ +} gtp_xact_info_t; -CORE_DECLARE(status_t) gtp_send(net_sock_t *s, - pkbuf_t *pkb, c_uint32_t ip_addr, c_uint16_t port); +/** + * This structure represents the commonalities of GTP node such as MME, SGW, + * PGW gateway. Some of members may not be used by the specific type of node */ +typedef struct _gtp_node_t { + lnode_t node; /**< A node of list_t */ + + c_uint32_t local_addr; /**< Network byte order IP Address */ + c_uint16_t local_port; /**< Host byte order Port number */ + c_uint32_t remote_addr; /**< Network byte order IP Address */ + c_uint16_t remote_port; /**< Host byte order Port number */ + + gtp_xact_info_t xi; /**< Transaction information */ + + net_sock_t *s; /**< Network socket */ +} gtp_node_t; + +CORE_DECLARE(status_t) gtp_open( + gtp_node_t *gnode, net_sock_handler handler); +CORE_DECLARE(status_t) gtp_close(gtp_node_t *gnode); + +CORE_DECLARE(pkbuf_t *) gtp_read(gtp_node_t *gnode); + +CORE_DECLARE(status_t) gtp_send(gtp_node_t *gnode, pkbuf_t *pkbuf); #ifdef __cplusplus } diff --git a/lib/gtp/gtp_types.h b/lib/gtp/gtp_types.h index 41213c1f4..d544549cd 100644 --- a/lib/gtp/gtp_types.h +++ b/lib/gtp/gtp_types.h @@ -9,6 +9,27 @@ extern "C" { #endif /* __cplusplus */ +/* 5.1 General format */ +#define GTPV2C_HEADER_LEN 12 +#define GTPV2C_TEID_LEN 4 +typedef struct _gtpv2c_header_t { +ED4(c_uint8_t version:3;, + c_uint8_t piggybacked:1;, + c_uint8_t teid_presence:1;, + c_uint8_t spare1:3;) + c_uint8_t type; + c_uint16_t length; + union { + struct { + c_uint32_t teid; + /* sqn : 31bit ~ 8bit, spare : 7bit ~ 0bit */ + c_uint32_t sqn; + }; + /* sqn : 31bit ~ 8bit, spare : 7bit ~ 0bit */ + c_uint32_t spare2; + }; +} __attribute__ ((packed)) gtpv2c_header_t; + /* 8.7 Aggregate Maximum Bit Rate (AMBR) */ typedef struct _gtp_ambr_t { c_uint32_t uplink; diff --git a/lib/gtp/gtp_xact.c b/lib/gtp/gtp_xact.c new file mode 100644 index 000000000..e5095c9ac --- /dev/null +++ b/lib/gtp/gtp_xact.c @@ -0,0 +1,103 @@ +#define TRACE_MODULE _gtp_xact +#include "core_debug.h" +#include "core_pool.h" + +#include "gtp_xact.h" + +#define SIZE_OF_GTP_XACT_POOL 32 + +#define GTP_XACT_NEXT_ID(__id) \ + ((__id) == 0x800000 ? 1 : ((__id) + 1)) +#define GTP_XACT_COMPARE_ID(__id1, __id2) \ + ((__id2) > (__id1) ? ((__id2) - (__id1) < 0x7fffff ? -1 : 1) : \ + (__id1) > (__id2) ? ((__id1) - (__id2) < 0x7fffff ? 1 : -1) : 0) + +static int g_gtp_xact_initialized = 0; + +pool_declare(gtp_xact_pool, gtp_xact_ctx_t, SIZE_OF_GTP_XACT_POOL); + +/** + * Initialize the transaction framework + */ +status_t gtp_xact_init(void) +{ + d_assert(g_gtp_xact_initialized == 0, return CORE_ERROR, + "XACTION already has been initialized"); + + pool_init(>p_xact_pool, SIZE_OF_GTP_XACT_POOL); + + g_gtp_xact_initialized = 1; + + return CORE_OK; +} + +/** + * Finalize the transaction framework + */ +status_t gtp_xact_final(void) +{ + d_assert(g_gtp_xact_initialized == 1, return CORE_ERROR, + "XACTION ASNGW context already has been finalized"); + + pool_final(>p_xact_pool); + + g_gtp_xact_initialized = 0; + + return CORE_OK; +} + +/** + * Create a new transaction which was initiated by local ASN node. + */ +status_t gtp_xact_new_local(gtp_xact_ctx_t **xact, c_uint8_t type, + pkbuf_t *pkb, gtp_node_t *gnode) +{ + return CORE_OK; +} + +/** + * Create a new transaction which was initiated by remote node + */ +status_t gtp_xact_new_remote(gtp_xact_ctx_t **xact) +{ + return CORE_OK; +} +/** + * Delete a transaction + */ +status_t gtp_xact_delete(gtp_xact_ctx_t *xact) +{ + return CORE_OK; +} + +/** + * Update the transaction with the new packet to be sent for the next step + */ +status_t gtp_xact_update_tx(gtp_xact_ctx_t *xact, pkbuf_t *pkb) +{ + return CORE_OK; +} + +/** + * Update the transaction with the new received packet for the next step + */ +status_t gtp_xact_update_rx(gtp_xact_ctx_t *xact) +{ + return CORE_OK; +} + +/** + * Apply and commit the updated of the transcation + */ +status_t gtp_xact_commit(gtp_xact_ctx_t *xact) +{ + return CORE_OK; +} + +/** + * Find the transaction with the given ASN header + */ +gtp_xact_ctx_t * gtp_xact_find() +{ + return CORE_OK; +} diff --git a/lib/gtp/gtp_xact.h b/lib/gtp/gtp_xact.h new file mode 100644 index 000000000..17dfeac16 --- /dev/null +++ b/lib/gtp/gtp_xact.h @@ -0,0 +1,86 @@ +#ifndef __GTP_XACT_H__ +#define __GTP_XACT_H__ + +#include "core_pkbuf.h" +#include "core_list.h" +#include "core_net.h" +#include "core_timer.h" + +#include "gtp_path.h" + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#define GTP_MAX_MESSAGE_TYPE 256 + +/** + * Transaction context + */ +typedef struct _gtp_xact_ctx_t { + lnode_t node; /**< A node of list */ + + c_uint32_t xid; /**< Transaction ID */ + +#define GTP_LOCAL_ORIGINATOR 0 +#define GTP_REMOTE_ORIGINATOR 1 + c_uint8_t org; /**< Transaction' originator. + local or remote */ + gtp_node_t *gnode; /**< RElevant GTP node context */ + void *xctx; /**< Relevant context */ + tm_block_id tm_wait; /**< Timer waiting for next message */ + int retry_count; /**< Retry count waiting for next message */ + +} gtp_xact_ctx_t; + +/** + * Initialize the transaction framework + */ +CORE_DECLARE(status_t) gtp_xact_init(void); + +/** + * Finalize the transaction framework + */ +CORE_DECLARE(status_t) gtp_xact_final(void); + +/** + * Create a new transaction which was initiated by local ASN node. + */ +CORE_DECLARE(status_t) gtp_xact_new_local(gtp_xact_ctx_t **xact, c_uint8_t type, + pkbuf_t *pkb, gtp_node_t *gnode); + +/** + * Create a new transaction which was initiated by remote node + */ +CORE_DECLARE(status_t) gtp_xact_new_remote(gtp_xact_ctx_t **xact); + +/** + * Delete a transaction + */ +CORE_DECLARE(status_t) gtp_xact_delete(gtp_xact_ctx_t *xact); + +/** + * Update the transaction with the new packet to be sent for the next step + */ +CORE_DECLARE(status_t) gtp_xact_update_tx(gtp_xact_ctx_t *xact, pkbuf_t *pkb); + +/** + * Update the transaction with the new received packet for the next step + */ +CORE_DECLARE(status_t) gtp_xact_update_rx(gtp_xact_ctx_t *xact); + +/** + * Apply and commit the updated of the transcation + */ +CORE_DECLARE(status_t) gtp_xact_commit(gtp_xact_ctx_t *xact); + +/** + * Find the transaction with the given ASN header + */ +CORE_DECLARE(gtp_xact_ctx_t *) gtp_xact_find(); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* __GTP_XACT_H__ */ diff --git a/main.c b/main.c index 721d9c8e5..674e4e46c 100644 --- a/main.c +++ b/main.c @@ -53,11 +53,12 @@ static int check_signal(int signum) { pkbuf_t *pkbuf = NULL; CORE_DECLARE(status_t) s11_build_create_session_req(pkbuf_t **pkbuf, void *ue); - CORE_DECLARE(status_t) mme_s11_send_to_sgw(pkbuf_t *pkbuf); + CORE_DECLARE(status_t) mme_s11_send_to_sgw(void *sgw, pkbuf_t *pkbuf); + CORE_DECLARE(void*) mme_ctx_sgw_first(void); s11_build_create_session_req(&pkbuf, NULL); d_print_hex(pkbuf->payload, pkbuf->len); - mme_s11_send_to_sgw(pkbuf); + mme_s11_send_to_sgw(mme_ctx_sgw_first(), pkbuf); break; } default: diff --git a/src/mme/context.c b/src/mme/context.c index d1093bd5c..d9091d8dc 100644 --- a/src/mme/context.c +++ b/src/mme/context.c @@ -13,6 +13,7 @@ #define UE_PER_ENB 128 #define RAB_PER_UE 16 +#define SIZE_OF_SGW_POOL 8 #define SIZE_OF_ENB_POOL 128 #define SIZE_OF_UE_POOL (SIZE_OF_ENB_POOL * UE_PER_ENB) #define SIZE_OF_RAB_POOL (SIZE_OF_UE_POOL * RAB_PER_UE) @@ -21,12 +22,14 @@ static mme_ctx_t self; +pool_declare(sgw_pool, sgw_ctx_t, SIZE_OF_SGW_POOL); pool_declare(enb_pool, enb_ctx_t, SIZE_OF_ENB_POOL); pool_declare(ue_pool, ue_ctx_t, SIZE_OF_UE_POOL); pool_declare(rab_pool, rab_ctx_t, SIZE_OF_RAB_POOL); static int ctx_initialized = 0; +static list_t sgw_list; static list_t enb_list; status_t mme_ctx_init() @@ -34,21 +37,19 @@ status_t mme_ctx_init() d_assert(ctx_initialized == 0, return CORE_ERROR, "MME context already has been ctx_initialized"); + pool_init(&sgw_pool, SIZE_OF_SGW_POOL); pool_init(&enb_pool, SIZE_OF_ENB_POOL); pool_init(&ue_pool, SIZE_OF_UE_POOL); pool_init(&rab_pool, SIZE_OF_RAB_POOL); + list_init(&sgw_list); list_init(&enb_list); /* Initialize MME context */ memset(&self, 0, sizeof(mme_ctx_t)); - self.mme_local_addr = inet_addr("127.0.0.1"); - self.sgw_remote_addr = inet_addr("127.0.0.1"); - + self.s1ap_addr = inet_addr("127.0.0.1"); self.s1ap_port = S1AP_SCTP_PORT; - self.s11_local_port = S11_UDP_PORT; - self.s11_remote_port = S11_UDP_PORT + 1; /* MCC : 001, MNC : 01 */ plmn_id_build(&self.plmn_id, 1, 1, 2); @@ -80,6 +81,7 @@ status_t mme_ctx_final() mme_ctx_enb_remove_all(); + pool_final(&sgw_pool); pool_final(&enb_pool); pool_final(&ue_pool); pool_final(&rab_pool); @@ -94,6 +96,73 @@ mme_ctx_t* mme_self() return &self; } +sgw_ctx_t* mme_ctx_sgw_add() +{ + sgw_ctx_t *sgw = NULL; + + pool_alloc_node(&sgw_pool, &sgw); + d_assert(sgw, return NULL, "Null param"); + + memset(sgw, 0, sizeof(sgw_ctx_t)); + + list_append(&sgw_list, sgw); + + return sgw; +} + +status_t mme_ctx_sgw_remove(sgw_ctx_t *sgw) +{ + d_assert(sgw, return CORE_ERROR, "Null param"); + + list_remove(&sgw_list, sgw); + pool_free_node(&sgw_pool, sgw); + + return CORE_OK; +} + +status_t mme_ctx_sgw_remove_all() +{ + sgw_ctx_t *sgw = NULL, *next_sgw = NULL; + + sgw = mme_ctx_sgw_first(); + while (sgw) + { + next_sgw = mme_ctx_sgw_next(sgw); + + mme_ctx_sgw_remove(sgw); + + sgw = next_sgw; + } + + return CORE_OK; +} + +sgw_ctx_t* mme_ctx_sgw_find_by_node(gtp_node_t *gnode) +{ + sgw_ctx_t *sgw = NULL; + + sgw = mme_ctx_sgw_first(); + while (sgw) + { + if (GTP_COMPARE_REMOTE_NODE(&sgw->gnode, gnode)) + break; + + sgw = mme_ctx_sgw_next(sgw); + } + + return sgw; +} + +sgw_ctx_t* mme_ctx_sgw_first() +{ + return list_first(&sgw_list); +} + +sgw_ctx_t* mme_ctx_sgw_next(sgw_ctx_t *sgw) +{ + return list_next(sgw); +} + enb_ctx_t* mme_ctx_enb_add() { enb_ctx_t *enb = NULL; diff --git a/src/mme/context.h b/src/mme/context.h index 4c650e3c0..a9e291694 100644 --- a/src/mme/context.h +++ b/src/mme/context.h @@ -9,6 +9,8 @@ #include "3gpp_defs.h" #include "3gpp_types.h" #include "nas_types.h" +#include "gtp_path.h" + #include "sm.h" #ifdef __cplusplus @@ -33,15 +35,9 @@ typedef struct _served_gummei { } srvd_gummei_t; typedef struct _mme_ctx_t { - c_uint32_t mme_local_addr; - c_uint32_t sgw_remote_addr; - - net_sock_t *s1ap_sock; + c_uint32_t s1ap_addr; c_uint16_t s1ap_port; - - net_sock_t *s11_sock; - c_uint16_t s11_local_port; - c_uint16_t s11_remote_port; + net_sock_t *s1ap_sock; msgq_id queue_id; tm_service_t tm_service; @@ -71,6 +67,11 @@ typedef struct _mme_ctx_t { c_uint8_t relative_capacity; } mme_ctx_t; +typedef struct _sgw_ctx_t { + gtp_node_t gnode; + +} sgw_ctx_t; + typedef struct _enb_ctx_t { lnode_t node; /**< A node of list_t */ @@ -134,6 +135,13 @@ CORE_DECLARE(status_t) mme_ctx_final(void); CORE_DECLARE(mme_ctx_t*) mme_self(void); +CORE_DECLARE(sgw_ctx_t*) mme_ctx_sgw_add(void); +CORE_DECLARE(status_t) mme_ctx_sgw_remove(sgw_ctx_t *sgw); +CORE_DECLARE(status_t) mme_ctx_sgw_remove_all(void); +CORE_DECLARE(sgw_ctx_t*) mme_ctx_sgw_find_by_node(gtp_node_t *gnode); +CORE_DECLARE(sgw_ctx_t*) mme_ctx_sgw_first(void); +CORE_DECLARE(sgw_ctx_t*) mme_ctx_sgw_next(sgw_ctx_t *sgw); + CORE_DECLARE(enb_ctx_t*) mme_ctx_enb_add(void); CORE_DECLARE(status_t) mme_ctx_enb_remove(enb_ctx_t *enb); CORE_DECLARE(status_t) mme_ctx_enb_remove_all(void); diff --git a/src/mme/event.c b/src/mme/event.c index 6520fa910..300d7248b 100644 --- a/src/mme/event.c +++ b/src/mme/event.c @@ -6,6 +6,8 @@ #include "s1ap_path.h" #include "nas_message.h" +static char EVT_NAME_LO_MME_ENGAGE_SGW[] = "LO_MME_ENGAGE_SGW"; + static char EVT_NAME_LO_ENB_S1AP_ACCEPT[] = "LO_ENB_S1AP_ACCEPT"; static char EVT_NAME_LO_ENB_S1AP_CONNREFUSED[] = "LO_ENB_S1AP_CONNREFUSED"; @@ -25,17 +27,20 @@ char* mme_event_get_name(event_t *e) case FSM_EXIT_SIG: return FSM_NAME_EXIT_SIG; + case EVT_LO_MME_ENGAGE_SGW: + return EVT_NAME_LO_MME_ENGAGE_SGW; + case EVT_LO_ENB_S1AP_ACCEPT: - return EVT_NAME_LO_ENB_S1AP_ACCEPT; + return EVT_NAME_LO_ENB_S1AP_ACCEPT; case EVT_LO_ENB_S1AP_CONNREFUSED: - return EVT_NAME_LO_ENB_S1AP_CONNREFUSED; + return EVT_NAME_LO_ENB_S1AP_CONNREFUSED; case EVT_MSG_ENB_S1AP: - return EVT_NAME_MSG_ENB_S1AP; + return EVT_NAME_MSG_ENB_S1AP; case EVT_MSG_UE_EMM: - return EVT_NAME_MSG_UE_EMM; + return EVT_NAME_MSG_UE_EMM; case EVT_MSG_MME_S11: - return EVT_NAME_MSG_MME_S11; + return EVT_NAME_MSG_MME_S11; default: break; diff --git a/src/mme/event.h b/src/mme/event.h index 1edddf0a1..ab737d0b3 100644 --- a/src/mme/event.h +++ b/src/mme/event.h @@ -15,6 +15,8 @@ extern "C" { typedef enum { MME_EVT_BASE = FSM_USER_SIG, + EVT_LO_MME_ENGAGE_SGW, + EVT_LO_ENB_S1AP_ACCEPT, EVT_LO_ENB_S1AP_CONNREFUSED, diff --git a/src/mme/mme_sm.c b/src/mme/mme_sm.c index ee30c6ee3..8e8d52938 100644 --- a/src/mme/mme_sm.c +++ b/src/mme/mme_sm.c @@ -35,34 +35,55 @@ void mme_state_operational(mme_sm_t *s, event_t *e) { case FSM_ENTRY_SIG: { + /* FIXME: for test */ + { + event_t e; + sgw_ctx_t *sgw = mme_ctx_sgw_add(); + + d_assert(sgw, break, "Can't add SGW context"); + + sgw->gnode.local_addr = inet_addr("127.0.0.1"); + sgw->gnode.local_port = GTPV2_C_UDP_PORT; + sgw->gnode.remote_addr = inet_addr("127.0.0.1"); + sgw->gnode.remote_port = GTPV2_C_UDP_PORT+1; + + event_set(&e, EVT_LO_MME_ENGAGE_SGW); + event_set_param1(&e, sgw); + event_send(mme_self()->queue_id, &e); + } + rv = s1ap_open(); if (rv != CORE_OK) { d_error("Can't establish S1AP path"); break; } - rv = mme_s11_open(); - if (rv != CORE_OK) - { - d_error("Can't establish S11 path"); - break; - } break; } case FSM_EXIT_SIG: { + sgw_ctx_t *sgw = mme_ctx_sgw_first(); + while(sgw) + { + mme_s11_close(sgw); + sgw = mme_ctx_sgw_next(sgw); + } + rv = s1ap_close(); if (rv != CORE_OK) { d_error("Can't close S1AP path"); break; } - rv = mme_s11_close(); - if (rv != CORE_OK) - { - d_error("Can't close S11 path"); - break; - } + + break; + } + case EVT_LO_MME_ENGAGE_SGW: + { + sgw_ctx_t *sgw = (sgw_ctx_t *)event_get_param1(e); + d_assert(sgw, break, "LO_MME_ENGAGE_SGW has no BS context"); + + mme_s11_open(sgw); break; } case EVT_LO_ENB_S1AP_ACCEPT: diff --git a/src/mme/s11_build.c b/src/mme/s11_build.c new file mode 100644 index 000000000..bbb60faff --- /dev/null +++ b/src/mme/s11_build.c @@ -0,0 +1,145 @@ +#define TRACE_MODULE _s11_build + +#include "core_debug.h" + +#include "context.h" + +#include "3gpp_conv.h" +#include "gtp_types.h" +#include "gtp_tlv.h" + +status_t s11_build_create_session_req(pkbuf_t **pkbuf, ue_ctx_t *ue) +{ + gtp_create_session_request_t req; + gtp_uli_t uli; + char uli_buf[GTP_MAX_ULI_LEN]; + plmn_id_t serving_network; + gtp_f_teid_t s11, s5; + gtp_paa_t paa; + gtp_ambr_t ambr; + gtp_pco_t pco; + char pcobuf[GTP_MAX_PCO_LEN]; + gtp_bearer_qos_t bearer_qos; + char bearer_qos_buf[GTP_BEARER_QOS_LEN]; + gtp_ue_timezone_t ue_timezone; + + memset(&req, 0, sizeof(gtp_create_session_request_t)); + + req.imsi.presence = 1; + req.imsi.data = (c_uint8_t *)"\x55\x15\x30\x11\x34\x00\x10\xf4"; + req.imsi.len = 8; + + req.msisdn.presence = 1; + req.msisdn.data = (c_uint8_t *)"\x94\x71\x52\x76\x00\x41"; + req.msisdn.len = 6; + + req.me_identity.presence = 1; + req.me_identity.data = (c_uint8_t *)"\x53\x61\x20\x00\x91\x78\x84\x00"; + req.me_identity.len = 8; + + memset(&uli, 0, sizeof(gtp_uli_t)); + uli.flags.ecgi = 1; + uli.flags.tai = 1; + plmn_id_build(&uli.tai.plmn_id, 555, 10, 2); + uli.tai.tac = 4130; + plmn_id_build(&uli.ecgi.plmn_id, 555, 10, 2); + uli.ecgi.eci = 105729; + req.user_location_information.presence = 1; + gtp_build_uli(&req.user_location_information, &uli, + uli_buf, GTP_MAX_ULI_LEN); + + req.serving_network.presence = 1; + req.serving_network.data = plmn_id_build(&serving_network, 555, 10, 2); + req.serving_network.len = sizeof(serving_network); + + req.rat_type.presence = 1; + req.rat_type.u8 = GTP_RAT_TYPE_EUTRAN; + + memset(&s11, 0, sizeof(gtp_f_teid_t)); + s11.ipv4 = 1; + s11.interface_type = GTP_F_TEID_S11_MME_GTP_C; + s11.teid = htonl(0x80000084); + s11.ipv4_addr = inet_addr("10.50.54.10"); + req.sender_f_teid_for_control_plane.presence = 1; + req.sender_f_teid_for_control_plane.data = &s11; + req.sender_f_teid_for_control_plane.len = GTP_F_TEID_IPV4_LEN; + + memset(&s5, 0, sizeof(gtp_f_teid_t)); + s5.ipv4 = 1; + s5.interface_type = GTP_F_TEID_S5_S8_PGW_GTP_C; + s5.ipv4_addr = inet_addr("10.50.54.37"); + req.pgw_s5_s8_address_for_control_plane_or_pmip.presence = 1; + req.pgw_s5_s8_address_for_control_plane_or_pmip.data = &s5; + req.pgw_s5_s8_address_for_control_plane_or_pmip.len = GTP_F_TEID_IPV4_LEN; + + req.access_point_name.presence = 1; + req.access_point_name.data = "cellwire.com"; + req.access_point_name.len = strlen(req.access_point_name.data); + + req.selection_mode.presence = 1; + req.selection_mode.u8 = GTP_SELECTION_MODE_MS_OR_NETWORK_PROVIDED_APN | 0xfc; + + req.pdn_type.presence = 1; + req.pdn_type.u8 = GTP_PDN_TYPE_IPV4; + + memset(&paa, 0, sizeof(gtp_paa_t)); + paa.pdn_type = GTP_PDN_TYPE_IPV4; + req.pdn_address_allocation.presence = 1; + req.pdn_address_allocation.data = &paa; + req.pdn_address_allocation.len = GTP_PAA_IPV4_LEN; + + req.maximum_apn_restriction.presence = 1; + req.maximum_apn_restriction.u8 = GTP_APN_NO_RESTRICTION; + + memset(&ambr, 0, sizeof(gtp_ambr_t)); + ambr.uplink = htonl(1000); + ambr.downlink = htonl(2000); + req.aggregate_maximum_bit_rate.presence = 1; + req.aggregate_maximum_bit_rate.data = &ambr; + req.aggregate_maximum_bit_rate.len = sizeof(ambr); + + memset(&pco, 0, sizeof(gtp_pco_t)); + pco.ext = 1; + pco.configuration_protocol = + GTP_PCO_PPP_FOR_USE_WITH_IP_PDP_TYPE_OR_IP_PDN_TYPE; + pco.num_of_id = 3; + pco.ids[0].id = GTP_PROTOCOL_OR_CONTAINER_ID_INTERNET_PROTOCOL_CONTROL_PROTOCOL; + pco.ids[0].contents = (c_uint8_t *)"\x01\x00\x00\x10\x81\x06\x00\x00\x00\x00\x83\x06\x00\x00\x00\x00"; + pco.ids[0].length = 16; + pco.ids[1].id = GTP_PROTOCOL_OR_CONTAINER_ID_DNS_SERVER_IPV4_ADDRESS_REQUEST; + pco.ids[1].length = 0; + pco.ids[2].id = GTP_PROTOCOL_OR_CONTAINER_ID_IP_ADDRESS_ALLOCATION_VIA_NAS_SIGNALLING; + pco.ids[2].length = 0; + req.protocol_configuration_options.presence = 1; + gtp_build_pco(&req.protocol_configuration_options, &pco, + pcobuf, GTP_MAX_PCO_LEN); + + req.bearer_contexts_to_be_created.presence = 1; + req.bearer_contexts_to_be_created.eps_bearer_id.presence = 1; + req.bearer_contexts_to_be_created.eps_bearer_id.u8 = 5; + + memset(&bearer_qos, 0, sizeof(bearer_qos)); + bearer_qos.pvi = 1; + bearer_qos.pl = 1; + bearer_qos.pci = 1; + bearer_qos.qci = 5; + req.bearer_contexts_to_be_created.bearer_level_qos.presence = 1; + gtp_build_bearer_qos(&req.bearer_contexts_to_be_created.bearer_level_qos, + &bearer_qos, bearer_qos_buf, GTP_BEARER_QOS_LEN); + + memset(&ue_timezone, 0, sizeof(ue_timezone)); + ue_timezone.timezone = 0x40; + ue_timezone.daylight_saving_time = + GTP_UE_TIME_ZONE_NO_ADJUSTMENT_FOR_DAYLIGHT_SAVING_TIME; + req.ue_time_zone.presence = 1; + req.ue_time_zone.data = &ue_timezone; + req.ue_time_zone.len = sizeof(ue_timezone); + + req.charging_characteristics.presence = 1; + req.charging_characteristics.data = (c_uint8_t *)"\x54\x00"; + req.charging_characteristics.len = 2; + + return tlv_build_msg(pkbuf, &tlv_desc_create_session_request, &req, + TLV_MODE_T1_L2_I1); +} + diff --git a/src/mme/s11_build.h b/src/mme/s11_build.h new file mode 100644 index 000000000..957ad1b67 --- /dev/null +++ b/src/mme/s11_build.h @@ -0,0 +1,17 @@ +#ifndef __S11_BUILD_H__ +#define __S11_BUILD_H__ + +#include "s1ap_message.h" + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +CORE_DECLARE(status_t) s11_build_create_session_req( + pkbuf_t **pkbuf, ue_ctx_t *ue); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* __S11_BUILD_H__ */ diff --git a/src/mme/s11_path.c b/src/mme/s11_path.c index a60918799..501638487 100644 --- a/src/mme/s11_path.c +++ b/src/mme/s11_path.c @@ -8,12 +8,16 @@ static int _mme_s11_recv_cb(net_sock_t *net_sock, void *data) { + char buf[INET_ADDRSTRLEN]; event_t e; int rc; pkbuf_t *pkbuf = NULL; - d_assert(net_sock, return -1, "Null param"); + gtp_node_t *gnode = data; - pkbuf = gtp_read(net_sock); + d_assert(net_sock, return -1, "Null param"); + d_assert(gnode, return -1, "Null param"); + + pkbuf = gtp_read(gnode); if (pkbuf == NULL) { if (net_sock->sndrcv_errno == EAGAIN) @@ -22,33 +26,59 @@ static int _mme_s11_recv_cb(net_sock_t *net_sock, void *data) return -1; } - d_trace(1, "S11_PDU is received from SGW\n"); + d_trace(1, "S11_PDU is received from SGW[%s:%d]\n", + INET_NTOP(&gnode->remote_addr, buf), gnode->remote_port); d_trace_hex(1, pkbuf->payload, pkbuf->len); event_set(&e, EVT_MSG_MME_S11); - event_set_param1(&e, (c_uintptr_t)net_sock); + event_set_param1(&e, (c_uintptr_t)gnode); event_set_param2(&e, (c_uintptr_t)pkbuf); rc = event_send(mme_self()->queue_id, &e); if (rc <= 0) + { + pkbuf_free(pkbuf); return rc; + } return 0; } -status_t mme_s11_open() +status_t mme_s11_open(void *sgw) { - return gtp_open(&mme_self()->s11_sock, _mme_s11_recv_cb, NULL, - mme_self()->sgw_remote_addr, mme_self()->s11_local_port); + char buf[INET_ADDRSTRLEN]; + status_t rv; + gtp_node_t *gnode = sgw; + + rv = gtp_open(gnode, _mme_s11_recv_cb); + if (rv != CORE_OK) + { + d_error("Can't establish S11 Path with SGW[%s:%d]", + INET_NTOP(&gnode->remote_addr, buf), gnode->remote_port); + return rv; + } + + return CORE_OK; } -status_t mme_s11_close() +status_t mme_s11_close(void *sgw) { - return gtp_close(mme_self()->s11_sock); + char buf[INET_ADDRSTRLEN]; + status_t rv; + gtp_node_t *gnode = sgw; + + rv = gtp_close(gnode); + if (rv != CORE_OK) + { + d_error("Can't close S11 Path with SGW[%s:%d]", + INET_NTOP(&gnode->remote_addr, buf), gnode->remote_port); + return rv; + } + + return CORE_OK; } -status_t mme_s11_send_to_sgw(pkbuf_t *pkbuf) +status_t mme_s11_send_to_sgw(void *sgw, pkbuf_t *pkbuf) { - return gtp_send(mme_self()->s11_sock, pkbuf, - mme_self()->sgw_remote_addr, mme_self()->s11_remote_port); + return gtp_send(sgw, pkbuf); } diff --git a/src/mme/s11_path.h b/src/mme/s11_path.h index 816bbe8cb..738a83caa 100644 --- a/src/mme/s11_path.h +++ b/src/mme/s11_path.h @@ -7,10 +7,10 @@ extern "C" { #endif /* __cplusplus */ -CORE_DECLARE(status_t) mme_s11_open(); -CORE_DECLARE(status_t) mme_s11_close(); +CORE_DECLARE(status_t) mme_s11_open(void *sgw); +CORE_DECLARE(status_t) mme_s11_close(void *sgw); -CORE_DECLARE(status_t) mme_s11_send_to_sgw(pkbuf_t *pkbuf); +CORE_DECLARE(status_t) mme_s11_send_to_sgw(void *sgw, pkbuf_t *pkbuf); #ifdef __cplusplus } diff --git a/src/mme/s1ap_path.c b/src/mme/s1ap_path.c index a3d83e605..ed2d3ef0d 100644 --- a/src/mme/s1ap_path.c +++ b/src/mme/s1ap_path.c @@ -15,7 +15,7 @@ status_t s1ap_open(void) rc = net_listen_with_addr(&mme_self()->s1ap_sock, SOCK_STREAM, IPPROTO_SCTP, mme_self()->s1ap_port, - mme_self()->mme_local_addr); + mme_self()->s1ap_addr); if (rc != 0) { d_error("Can't establish S1-ENB(port:%d) path(%d:%s)", @@ -36,7 +36,7 @@ status_t s1ap_open(void) } d_trace(1, "s1_enb_listen() %s:%d\n", - INET_NTOP(&mme_self()->mme_local_addr, buf), mme_self()->s1ap_port); + INET_NTOP(&mme_self()->s1ap_addr, buf), mme_self()->s1ap_port); return CORE_OK; } diff --git a/src/sgw/Makefile.am b/src/sgw/Makefile.am index d2a1d894f..ee9a91449 100644 --- a/src/sgw/Makefile.am +++ b/src/sgw/Makefile.am @@ -4,12 +4,12 @@ noinst_LTLIBRARIES = libsgw.la libsgw_la_SOURCES = \ event.h context.h \ - s11_path.h \ + sgw_path.h \ sm.h nodist_libsgw_la_SOURCES = \ init.c event.c context.c \ - s11_path.c \ + sgw_path.c \ sgw_sm.c libsgw_la_DEPENDENCIES = \ diff --git a/src/sgw/context.c b/src/sgw/context.c index bdde49ee7..6d088fe2c 100644 --- a/src/sgw/context.c +++ b/src/sgw/context.c @@ -19,12 +19,20 @@ status_t sgw_ctx_init() /* Initialize MME context */ memset(&self, 0, sizeof(sgw_ctx_t)); - self.sgw_local_addr = inet_addr("127.0.0.1"); - self.mme_remote_addr = inet_addr("127.0.0.1"); - self.pgw_remote_addr = inet_addr("127.0.0.1"); + self.s11_node.local_addr = inet_addr("127.0.0.1"); + self.s11_node.local_port = GTPV2_C_UDP_PORT + 1; + self.s11_node.remote_addr = inet_addr("127.0.0.1"); + self.s11_node.remote_port = GTPV2_C_UDP_PORT; - self.s11_local_port = S11_UDP_PORT + 1; - self.s11_remote_port = S11_UDP_PORT; + self.s5c_node.local_addr = inet_addr("127.0.0.1"); + self.s5c_node.local_port = GTPV2_C_UDP_PORT + 2; + self.s5c_node.remote_addr = inet_addr("127.0.0.1"); + self.s5c_node.remote_port = GTPV2_C_UDP_PORT + 3; + + self.s5u_node.local_addr = inet_addr("127.0.0.1"); + self.s5u_node.local_port = GTPV1_U_UDP_PORT; + self.s5u_node.remote_addr = inet_addr("127.0.0.1"); + self.s5u_node.remote_port = GTPV1_U_UDP_PORT + 1; ctx_initialized = 1; diff --git a/src/sgw/context.h b/src/sgw/context.h index 3daced397..fd65e5c82 100644 --- a/src/sgw/context.h +++ b/src/sgw/context.h @@ -7,18 +7,16 @@ #include "sm.h" +#include "gtp_path.h" + #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ typedef struct _sgw_ctx_t { - c_uint32_t sgw_local_addr; - c_uint32_t mme_remote_addr; - c_uint32_t pgw_remote_addr; - - net_sock_t *s11_sock; - c_uint16_t s11_local_port; - c_uint16_t s11_remote_port; + gtp_node_t s11_node; + gtp_node_t s5c_node; + gtp_node_t s5u_node; msgq_id queue_id; tm_service_t tm_service; diff --git a/src/sgw/event.h b/src/sgw/event.h index c8bf894ca..9a1df8baf 100644 --- a/src/sgw/event.h +++ b/src/sgw/event.h @@ -11,6 +11,7 @@ typedef enum { SGW_EVT_BASE = FSM_USER_SIG, EVT_MSG_SGW_S11, + EVT_MSG_SGW_S5C, SGW_EVT_TOP, diff --git a/src/sgw/s11_path.c b/src/sgw/s11_path.c deleted file mode 100644 index 13bf025e1..000000000 --- a/src/sgw/s11_path.c +++ /dev/null @@ -1,57 +0,0 @@ -#define TRACE_MODULE _sgw_s11_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 "s11_path.h" - -static int _sgw_s11_recv_cb(net_sock_t *net_sock, void *data) -{ - event_t e; - int rc; - pkbuf_t *pkbuf = NULL; - d_assert(net_sock, return -1, "Null param"); - - pkbuf = gtp_read(net_sock); - if (pkbuf == NULL) - { - if (net_sock->sndrcv_errno == EAGAIN) - return 0; - - return -1; - } - - d_trace(1, "S11_PDU is received from SGW\n"); - d_trace_hex(1, pkbuf->payload, pkbuf->len); - - event_set(&e, EVT_MSG_SGW_S11); - event_set_param1(&e, (c_uintptr_t)net_sock); - event_set_param2(&e, (c_uintptr_t)pkbuf); - - rc = event_send(sgw_self()->queue_id, &e); - if (rc <= 0) - return rc; - - return 0; -} - -status_t sgw_s11_open() -{ - return gtp_open(&sgw_self()->s11_sock, _sgw_s11_recv_cb, NULL, - sgw_self()->sgw_local_addr, sgw_self()->s11_local_port); -} - -status_t sgw_s11_close() -{ - return gtp_close(sgw_self()->s11_sock); -} - -status_t sgw_s11_send_to_mme(pkbuf_t *pkbuf) -{ - return gtp_send(sgw_self()->s11_sock, pkbuf, - sgw_self()->mme_remote_addr, sgw_self()->s11_remote_port); -} diff --git a/src/sgw/s11_path.h b/src/sgw/s11_path.h deleted file mode 100644 index 4d5736534..000000000 --- a/src/sgw/s11_path.h +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef __SGW_S11_PATH_H__ -#define __SGW_S11_PATH_H__ - -#include "gtp_path.h" - -#ifdef __cplusplus -extern "C" { -#endif /* __cplusplus */ - -CORE_DECLARE(status_t) sgw_s11_open(); -CORE_DECLARE(status_t) sgw_s11_close(); - -CORE_DECLARE(status_t) sgw_s11_send_to_mme(pkbuf_t *pkbuf); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* __SGW_S11_PATH_H__ */ diff --git a/src/sgw/sgw_path.c b/src/sgw/sgw_path.c new file mode 100644 index 000000000..986f12865 --- /dev/null +++ b/src/sgw/sgw_path.c @@ -0,0 +1,155 @@ +#define TRACE_MODULE _sgw_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 "sgw_path.h" + +static int _gtpv2_c_recv_cb(net_sock_t *net_sock, void *data) +{ + event_t e; + int rc; + pkbuf_t *pkbuf = NULL; + gtp_node_t *gnode = data; + + d_assert(net_sock, return -1, "Null param"); + d_assert(gnode, return -1, "Null param"); + + pkbuf = gtp_read(gnode); + if (pkbuf == NULL) + { + if (net_sock->sndrcv_errno == EAGAIN) + return 0; + + return -1; + } + + if (GTP_COMPARE_REMOTE_NODE(gnode, &sgw_self()->s11_node)) + { + d_trace(1, "S11 PDU received from MME\n"); + event_set(&e, EVT_MSG_SGW_S11); + } + else if (GTP_COMPARE_REMOTE_NODE(gnode, &sgw_self()->s5c_node)) + { + d_trace(1, "S5-C PDU received from PGW\n"); + event_set(&e, EVT_MSG_SGW_S5C); + } + else + d_assert(0, pkbuf_free(pkbuf); return -1, "Unknown GTP-Node"); + + d_trace_hex(1, pkbuf->payload, pkbuf->len); + + event_set_param1(&e, (c_uintptr_t)gnode); + event_set_param2(&e, (c_uintptr_t)pkbuf); + + rc = event_send(sgw_self()->queue_id, &e); + if (rc <= 0) + { + pkbuf_free(pkbuf); + return rc; + } + + return 0; +} + +static int _gtpv1_u_recv_cb(net_sock_t *net_sock, void *data) +{ + pkbuf_t *pkbuf = NULL; + gtp_node_t *gnode = data; + + d_assert(net_sock, return -1, "Null param"); + d_assert(gnode, return -1, "Null param"); + + pkbuf = gtp_read(gnode); + if (pkbuf == NULL) + { + if (net_sock->sndrcv_errno == EAGAIN) + return 0; + + return -1; + } + + d_trace(1, "S5U PDU received from GTP\n"); + d_trace_hex(1, pkbuf->payload, pkbuf->len); + + /* TODO */ + + pkbuf_free(pkbuf); + return 0; +} + +status_t sgw_path_open() +{ + status_t rv; + + rv = gtp_open(&sgw_self()->s11_node, _gtpv2_c_recv_cb); + if (rv != CORE_OK) + { + d_error("Can't establish S11 Path with MME"); + return rv; + } + + rv = gtp_open(&sgw_self()->s5c_node, _gtpv2_c_recv_cb); + if (rv != CORE_OK) + { + d_error("Can't establish S5-C Path with PGW"); + return rv; + } + + rv = gtp_open(&sgw_self()->s5u_node, _gtpv1_u_recv_cb); + if (rv != CORE_OK) + { + d_error("Can't establish S5-U Path with PGW"); + return rv; + } + + return CORE_OK; +} + +status_t sgw_path_close() +{ + status_t rv; + + rv = gtp_close(&sgw_self()->s11_node); + if (rv != CORE_OK) + { + d_error("Can't close S11 Path with MME"); + return rv; + } + + rv = gtp_close(&sgw_self()->s5c_node); + if (rv != CORE_OK) + { + d_error("Can't close S5-C Path with MME"); + return rv; + } + + rv = gtp_close(&sgw_self()->s5u_node); + if (rv != CORE_OK) + { + d_error("Can't close S5-U Path with MME"); + return rv; + } + + return CORE_OK; +} + +status_t sgw_path_send_to_s11(pkbuf_t *pkbuf) +{ + return gtp_send(&sgw_self()->s11_node, pkbuf); +} + +status_t sgw_path_send_to_s5c(pkbuf_t *pkbuf) +{ + return gtp_send(&sgw_self()->s5c_node, pkbuf); +} + +status_t sgw_path_send_to_s5u(pkbuf_t *pkbuf) +{ + return gtp_send(&sgw_self()->s5u_node, pkbuf); +} + diff --git a/src/sgw/sgw_path.h b/src/sgw/sgw_path.h new file mode 100644 index 000000000..ed42b202f --- /dev/null +++ b/src/sgw/sgw_path.h @@ -0,0 +1,21 @@ +#ifndef __SGW_PATH_H__ +#define __SGW_PATH_H__ + +#include "gtp_path.h" + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +CORE_DECLARE(status_t) sgw_path_open(); +CORE_DECLARE(status_t) sgw_path_close(); + +CORE_DECLARE(status_t) sgw_path_send_to_s11(pkbuf_t *pkbuf); +CORE_DECLARE(status_t) sgw_path_send_to_s5c(pkbuf_t *pkbuf); +CORE_DECLARE(status_t) sgw_path_send_to_s5u(pkbuf_t *pkbuf); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* __SGW_PATH_H__ */ diff --git a/src/sgw/sgw_sm.c b/src/sgw/sgw_sm.c index 96c12dbd6..006130d74 100644 --- a/src/sgw/sgw_sm.c +++ b/src/sgw/sgw_sm.c @@ -4,7 +4,7 @@ #include "sm.h" #include "context.h" #include "event.h" -#include "s11_path.h" +#include "sgw_path.h" void sgw_state_initial(sgw_sm_t *s, event_t *e) { @@ -34,7 +34,7 @@ void sgw_state_operational(sgw_sm_t *s, event_t *e) { case FSM_ENTRY_SIG: { - rv = sgw_s11_open(); + rv = sgw_path_open(); if (rv != CORE_OK) { d_error("Can't establish S11 path"); @@ -44,7 +44,7 @@ void sgw_state_operational(sgw_sm_t *s, event_t *e) } case FSM_EXIT_SIG: { - rv = sgw_s11_close(); + rv = sgw_path_close(); if (rv != CORE_OK) { d_error("Can't close S11 path"); @@ -54,12 +54,20 @@ void sgw_state_operational(sgw_sm_t *s, event_t *e) } case EVT_MSG_SGW_S11: { - net_sock_t *sock = (net_sock_t *)event_get_param1(e); - d_assert(sock, break, "Null param"); + gtp_node_t *gnode = (gtp_node_t *)event_get_param1(e); + d_assert(gnode, break, "Null param"); d_info("EVT_MSG_MME_S11 received"); break; } + case EVT_MSG_SGW_S5C: + { + gtp_node_t *gnode = (gtp_node_t *)event_get_param1(e); + d_assert(gnode, break, "Null param"); + + d_info("EVT_MSG_MME_S5C received"); + break; + } default: { d_error("No handler for event %s", sgw_event_get_name(e)); diff --git a/test/tests1ap.c b/test/tests1ap.c index 72dc0b673..ede9cdad4 100644 --- a/test/tests1ap.c +++ b/test/tests1ap.c @@ -17,7 +17,7 @@ net_sock_t *tests1ap_enb_connect(void) if (!mme) return NULL; - rv = net_open_with_addr(&sock, mme->mme_local_addr, "127.0.0.1", 0, + rv = net_open_with_addr(&sock, mme->s1ap_addr, "127.0.0.1", 0, mme->s1ap_port, SOCK_SEQPACKET, IPPROTO_SCTP, 0); if (rv != CORE_OK) return NULL; diff --git a/test/testutil.c b/test/testutil.c index 851702173..f8465396d 100644 --- a/test/testutil.c +++ b/test/testutil.c @@ -45,7 +45,7 @@ void test_initialize(void) { cellwire_initialize(NULL, NULL); - inet_pton(AF_INET, "127.0.0.1", &mme_self()->mme_local_addr); + inet_pton(AF_INET, "127.0.0.1", &mme_self()->s1ap_addr); atexit(test_terminate); }