update it

This commit is contained in:
Sukchan Lee 2017-03-27 13:22:42 +09:00
parent 5cef8ad7e0
commit 1f3ddd2639
13 changed files with 149 additions and 141 deletions

View File

@ -6,69 +6,63 @@
#include "3gpp_defs.h"
#include "gtp_path.h"
status_t gtp_open(gtp_node_t *gnode, net_sock_handler handler)
status_t gtp_listen(net_sock_t **sock,
net_sock_handler handler, c_uint32_t addr, c_uint16_t port, void *data)
{
char buf[INET_ADDRSTRLEN];
int rc;
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);
rc = net_listen_with_addr(sock, SOCK_DGRAM, IPPROTO_UDP, port, addr);
if (rc != 0)
{
d_error("Can't establish GTP[%s:%d] path(%d:%s)",
INET_NTOP(&gnode->local_addr, buf), gnode->local_port,
errno, strerror(errno));
INET_NTOP(&addr, buf), port, errno, strerror(errno));
return CORE_ERROR;
}
rc = net_register_sock(gnode->s, handler, gnode);
rc = net_register_sock(*sock, handler, data);
if (rc != 0)
{
d_error("Can't establish GTP path(%d:%s)",
errno, strerror(errno));
net_close(gnode->s);
net_close(*sock);
return CORE_ERROR;
}
d_trace(1, "gtp_listen() %s:%d\n",
INET_NTOP(&gnode->local_addr, buf), gnode->local_port);
d_trace(1, "gtp_listen() %s:%d\n", INET_NTOP(&addr, buf), port);
return CORE_OK;
}
status_t gtp_close(gtp_node_t *gnode)
status_t gtp_close(net_sock_t *sock)
{
d_assert(gnode, return CORE_ERROR, "Null param");
d_assert(gnode->s, return CORE_ERROR, "Null param");
d_assert(sock, return CORE_ERROR, "Null param");
net_unregister_sock(gnode->s);
net_close(gnode->s);
net_unregister_sock(sock);
net_close(sock);
return CORE_OK;
}
pkbuf_t *gtp_read(gtp_node_t *gnode)
pkbuf_t *gtp_read(net_sock_t *sock)
{
pkbuf_t *pkb;
int r;
d_assert(gnode, return NULL, "Null param");
d_assert(gnode->s, return NULL, "Null param");
d_assert(sock, return NULL, "Null param");
pkb = pkbuf_alloc(0, MAX_SDU_LEN);
d_assert(pkb, return NULL, "Can't allocate pkbuf");
r = net_read(gnode->s, pkb->payload, pkb->len, 0);
r = net_read(sock, pkb->payload, pkb->len, 0);
if (r <= 0)
{
pkbuf_free(pkb);
if (gnode->s->sndrcv_errno != EAGAIN)
if (sock->sndrcv_errno != EAGAIN)
{
d_warn("net_read failed(%d:%s)",
gnode->s->sndrcv_errno, strerror(gnode->s->sndrcv_errno));
sock->sndrcv_errno, strerror(sock->sndrcv_errno));
}
return NULL;
@ -81,24 +75,24 @@ pkbuf_t *gtp_read(gtp_node_t *gnode)
}
}
status_t gtp_send(gtp_node_t *gnode, pkbuf_t *pkbuf)
status_t gtp_send(net_sock_t *sock, gtp_node_t *gnode, pkbuf_t *pkbuf)
{
char buf[INET_ADDRSTRLEN];
ssize_t sent;
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");
d_assert(pkbuf, return CORE_ERROR, "Null param");
sent = net_sendto(gnode->s, pkbuf->payload, pkbuf->len,
gnode->remote_addr, gnode->remote_port);
sent = net_sendto(sock, pkbuf->payload, pkbuf->len,
gnode->addr, gnode->port);
d_trace(1,"Sent %d->%d bytes to [%s:%d]\n", pkbuf->len, sent,
INET_NTOP(&gnode->remote_addr, buf), gnode->remote_port);
INET_NTOP(&gnode->addr, buf), gnode->port);
d_trace_hex(1, pkbuf->payload, pkbuf->len);
if (sent < 0 || sent != pkbuf->len)
{
d_error("net_send error (%d:%s)",
gnode->s->sndrcv_errno, strerror(gnode->s->sndrcv_errno));
sock->sndrcv_errno, strerror(sock->sndrcv_errno));
return CORE_ERROR;
}

View File

@ -12,9 +12,8 @@ extern "C" {
#define GTPV2_C_UDP_PORT 2123
#define GTPV1_U_UDP_PORT 2152
#define GTP_COMPARE_REMOTE_NODE(__id1, __id2) \
(((__id1)->remote_addr) == ((__id2)->remote_addr) && \
((__id1)->remote_port) == ((__id2)->remote_port))
#define GTP_COMPARE_NODE(__id1, __id2) \
(((__id1)->addr) == ((__id2)->addr) && ((__id1)->port) == ((__id2)->port))
/**
* This structure keeps active transactions and their histrory */
@ -29,23 +28,23 @@ typedef struct _gtp_xact_info_t {
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 */
c_uint32_t addr; /**< Network byte order IP Address */
c_uint16_t port; /**< Host byte order Port number */
net_sock_t *sock; /**< Network Socket */
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(status_t) gtp_listen(net_sock_t **sock,
net_sock_handler handler, c_uint32_t addr, c_uint16_t port, void *data);
CORE_DECLARE(status_t) gtp_close(net_sock_t *sock);
CORE_DECLARE(pkbuf_t *) gtp_read(gtp_node_t *gnode);
CORE_DECLARE(pkbuf_t *) gtp_read(net_sock_t *sock);
CORE_DECLARE(status_t) gtp_send(gtp_node_t *gnode, pkbuf_t *pkbuf);
CORE_DECLARE(status_t) gtp_send(net_sock_t *sock,
gtp_node_t *gnode, pkbuf_t *pkbuf);
#ifdef __cplusplus
}

View File

@ -51,6 +51,12 @@ status_t mme_ctx_init()
self.s1ap_addr = inet_addr("127.0.0.1");
self.s1ap_port = S1AP_SCTP_PORT;
sgw_ctx_t *sgw = mme_ctx_sgw_add();
d_assert(sgw, return CORE_ERROR, "Can't add SGW context");
sgw->gnode.addr = inet_addr("127.0.0.1");
sgw->gnode.port = GTPV2_C_UDP_PORT+1;
/* MCC : 001, MNC : 01 */
plmn_id_build(&self.plmn_id, 1, 1, 2);
self.tracking_area_code = 12345;
@ -79,6 +85,7 @@ status_t mme_ctx_final()
d_assert(ctx_initialized == 1, return CORE_ERROR,
"HyperCell context already has been finalized");
mme_ctx_sgw_remove_all();
mme_ctx_enb_remove_all();
pool_final(&sgw_pool);
@ -144,7 +151,7 @@ sgw_ctx_t* mme_ctx_sgw_find_by_node(gtp_node_t *gnode)
sgw = mme_ctx_sgw_first();
while (sgw)
{
if (GTP_COMPARE_REMOTE_NODE(&sgw->gnode, gnode))
if (GTP_COMPARE_NODE(&sgw->gnode, gnode))
break;
sgw = mme_ctx_sgw_next(sgw);

View File

@ -35,9 +35,13 @@ typedef struct _served_gummei {
} srvd_gummei_t;
typedef struct _mme_ctx_t {
c_uint32_t s1ap_addr;
c_uint16_t s1ap_port;
net_sock_t *s1ap_sock;
c_uint32_t s1ap_addr; /* MME S1AP local address */
c_uint16_t s1ap_port; /* MME S1AP local port */
net_sock_t *s1ap_sock; /* MME S1AP local listen socket */
c_uint32_t s11_addr; /* MME S11 local address */
c_uint16_t s11_port; /* MME S11 local port */
net_sock_t *s11_sock; /* MME S11 local listen socket */
msgq_id queue_id;
tm_service_t tm_service;
@ -68,7 +72,7 @@ typedef struct _mme_ctx_t {
} mme_ctx_t;
typedef struct _sgw_ctx_t {
gtp_node_t gnode;
gtp_node_t gnode; /* SGW S11 remote GTPv2-C node */
} sgw_ctx_t;

View File

@ -35,24 +35,14 @@ void mme_state_operational(mme_sm_t *s, event_t *e)
{
case FSM_ENTRY_SIG:
{
/* FIXME: for test */
rv = mme_s11_listen();
if (rv != CORE_OK)
{
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);
mme_event_send(&e);
d_error("Can't establish S11 path");
break;
}
rv = s1ap_open();
rv = s1ap_listen();
if (rv != CORE_OK)
{
d_error("Can't establish S1AP path");
@ -62,11 +52,11 @@ void mme_state_operational(mme_sm_t *s, event_t *e)
}
case FSM_EXIT_SIG:
{
sgw_ctx_t *sgw = mme_ctx_sgw_first();
while(sgw)
rv = mme_s11_close();
if (rv != CORE_OK)
{
mme_s11_close(sgw);
sgw = mme_ctx_sgw_next(sgw);
d_error("Can't close S11 path");
break;
}
rv = s1ap_close();
@ -78,14 +68,6 @@ void mme_state_operational(mme_sm_t *s, event_t *e)
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:
{
int rc;

View File

@ -6,18 +6,25 @@
#include "event.h"
#include "s11_path.h"
static int _mme_s11_recv_cb(net_sock_t *net_sock, void *data)
static int _gtpv2_c_recv_cb(net_sock_t *net_sock, void *data)
{
char buf[INET_ADDRSTRLEN];
status_t rv;
event_t e;
pkbuf_t *pkbuf = NULL;
gtp_node_t *gnode = data;
gtp_node_t gnode;
sgw_ctx_t *sgw = NULL;
d_assert(net_sock, return -1, "Null param");
d_assert(gnode, return -1, "Null param");
pkbuf = gtp_read(gnode);
gnode.addr = net_sock->remote.sin_addr.s_addr;
gnode.port = net_sock->remote.sin_port;
sgw = mme_ctx_sgw_find_by_node(&gnode);
d_assert(sgw, return -1, "Can't find SGW from [%s:%d]",
INET_NTOP(&gnode.addr, buf), gnode.port);
pkbuf = gtp_read(net_sock);
if (pkbuf == NULL)
{
if (net_sock->sndrcv_errno == EAGAIN)
@ -27,11 +34,11 @@ static int _mme_s11_recv_cb(net_sock_t *net_sock, void *data)
}
d_trace(1, "S11_PDU is received from SGW[%s:%d]\n",
INET_NTOP(&gnode->remote_addr, buf), gnode->remote_port);
INET_NTOP(&gnode.addr, buf), gnode.port);
d_trace_hex(1, pkbuf->payload, pkbuf->len);
event_set(&e, EVT_MSG_MME_S11);
event_set_param1(&e, (c_uintptr_t)gnode);
event_set_param1(&e, (c_uintptr_t)sgw);
event_set_param2(&e, (c_uintptr_t)pkbuf);
rv = mme_event_send(&e);
if (rv != CORE_OK)
@ -43,34 +50,29 @@ static int _mme_s11_recv_cb(net_sock_t *net_sock, void *data)
return 0;
}
status_t mme_s11_open(void *sgw)
status_t mme_s11_listen()
{
char buf[INET_ADDRSTRLEN];
status_t rv;
gtp_node_t *gnode = sgw;
rv = gtp_open(gnode, _mme_s11_recv_cb);
rv = gtp_listen(&mme_self()->s11_sock, _gtpv2_c_recv_cb,
mme_self()->s11_addr, mme_self()->s11_port, NULL);
if (rv != CORE_OK)
{
d_error("Can't establish S11 Path with SGW[%s:%d]",
INET_NTOP(&gnode->remote_addr, buf), gnode->remote_port);
d_error("Can't establish S11 Path for SGW");
return rv;
}
return CORE_OK;
}
status_t mme_s11_close(void *sgw)
status_t mme_s11_close()
{
char buf[INET_ADDRSTRLEN];
status_t rv;
gtp_node_t *gnode = sgw;
rv = gtp_close(gnode);
rv = gtp_close(mme_self()->s11_sock);
if (rv != CORE_OK)
{
d_error("Can't close S11 Path with SGW[%s:%d]",
INET_NTOP(&gnode->remote_addr, buf), gnode->remote_port);
d_error("Can't close S11 Path for SGW");
return rv;
}
@ -79,5 +81,8 @@ status_t mme_s11_close(void *sgw)
status_t mme_s11_send_to_sgw(void *sgw, pkbuf_t *pkbuf)
{
return gtp_send(sgw, pkbuf);
d_assert(sgw, return CORE_ERROR, "Null param");
d_assert(pkbuf, return CORE_ERROR, "Null param");
return gtp_send(mme_self()->s11_sock, sgw, pkbuf);
}

View File

@ -7,8 +7,8 @@
extern "C" {
#endif /* __cplusplus */
CORE_DECLARE(status_t) mme_s11_open(void *sgw);
CORE_DECLARE(status_t) mme_s11_close(void *sgw);
CORE_DECLARE(status_t) mme_s11_listen();
CORE_DECLARE(status_t) mme_s11_close();
CORE_DECLARE(status_t) mme_s11_send_to_sgw(void *sgw, pkbuf_t *pkbuf);

View File

@ -8,7 +8,7 @@
static int _s1ap_accept_cb(net_sock_t *net_sock, void *data);
status_t s1ap_open(void)
status_t s1ap_listen(void)
{
char buf[INET_ADDRSTRLEN];
int rc;

View File

@ -10,7 +10,7 @@
extern "C" {
#endif /* __cplusplus */
CORE_DECLARE(status_t) s1ap_open();
CORE_DECLARE(status_t) s1ap_listen();
CORE_DECLARE(status_t) s1ap_close();
CORE_DECLARE(status_t) s1ap_send(net_sock_t *s, pkbuf_t *pkb);

View File

@ -19,20 +19,20 @@ status_t sgw_ctx_init()
/* Initialize MME context */
memset(&self, 0, sizeof(sgw_ctx_t));
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_addr = inet_addr("127.0.0.1");
self.s11_port = GTPV2_C_UDP_PORT + 1;
self.s11_node.addr = inet_addr("127.0.0.1");
self.s11_node.port = GTPV2_C_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.s5c_addr = inet_addr("127.0.0.1");
self.s5c_port = GTPV2_C_UDP_PORT + 2;
self.s5c_node.addr = inet_addr("127.0.0.1");
self.s5c_node.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;
self.s5u_addr = inet_addr("127.0.0.1");
self.s5u_port = GTPV1_U_UDP_PORT;
self.s5u_node.addr = inet_addr("127.0.0.1");
self.s5u_node.port = GTPV1_U_UDP_PORT + 1;
ctx_initialized = 1;

View File

@ -14,9 +14,20 @@ extern "C" {
#endif /* __cplusplus */
typedef struct _sgw_ctx_t {
gtp_node_t s11_node;
gtp_node_t s5c_node;
gtp_node_t s5u_node;
c_uint32_t s11_addr; /* SGW S11 local address */
c_uint32_t s11_port; /* SGW S11 local port */
net_sock_t* s11_sock; /* SGW S11 local listen socket */
gtp_node_t s11_node; /* MME S11 remote GTPv2-C node */
c_uint32_t s5c_addr; /* SGW S5-C local address */
c_uint32_t s5c_port; /* SGW S5-C local port */
net_sock_t* s5c_sock; /* SGW S5-C local listen socket */
gtp_node_t s5c_node; /* PGW S5-C remote GTPv2-C node */
c_uint32_t s5u_addr; /* SGW S5-U local address */
c_uint32_t s5u_port; /* SGW S5-U local port */
net_sock_t* s5u_sock; /* SGW S5-U local listen socket */
gtp_node_t s5u_node; /* PGW S5-U remote GTPv1-U node */
msgq_id queue_id;
tm_service_t tm_service;

View File

@ -9,31 +9,31 @@
#include "context.h"
#include "sgw_path.h"
static int _gtpv2_c_recv_cb(net_sock_t *net_sock, void *data)
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(net_sock, return -1, "Null param");
d_assert(sock, return -1, "Null param");
d_assert(gnode, return -1, "Null param");
pkbuf = gtp_read(gnode);
pkbuf = gtp_read(sock);
if (pkbuf == NULL)
{
if (net_sock->sndrcv_errno == EAGAIN)
if (sock->sndrcv_errno == EAGAIN)
return 0;
return -1;
}
if (GTP_COMPARE_REMOTE_NODE(gnode, &sgw_self()->s11_node))
if (GTP_COMPARE_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))
else if (GTP_COMPARE_NODE(gnode, &sgw_self()->s5c_node))
{
d_trace(1, "S5-C PDU received from PGW\n");
event_set(&e, EVT_MSG_SGW_S5C);
@ -56,18 +56,18 @@ static int _gtpv2_c_recv_cb(net_sock_t *net_sock, void *data)
return 0;
}
static int _gtpv1_u_recv_cb(net_sock_t *net_sock, void *data)
static int _gtpv1_u_recv_cb(net_sock_t *sock, void *data)
{
pkbuf_t *pkbuf = NULL;
gtp_node_t *gnode = data;
d_assert(net_sock, return -1, "Null param");
d_assert(sock, return -1, "Null param");
d_assert(gnode, return -1, "Null param");
pkbuf = gtp_read(gnode);
pkbuf = gtp_read(sock);
if (pkbuf == NULL)
{
if (net_sock->sndrcv_errno == EAGAIN)
if (sock->sndrcv_errno == EAGAIN)
return 0;
return -1;
@ -86,24 +86,27 @@ status_t sgw_path_open()
{
status_t rv;
rv = gtp_open(&sgw_self()->s11_node, _gtpv2_c_recv_cb);
rv = gtp_listen(&sgw_self()->s11_sock, _gtpv2_c_recv_cb,
sgw_self()->s11_addr, sgw_self()->s11_port, &sgw_self()->s11_node);
if (rv != CORE_OK)
{
d_error("Can't establish S11 Path with MME");
d_error("Can't establish S11 Path for MME");
return rv;
}
rv = gtp_open(&sgw_self()->s5c_node, _gtpv2_c_recv_cb);
rv = gtp_listen(&sgw_self()->s5c_sock, _gtpv2_c_recv_cb,
sgw_self()->s5c_addr, sgw_self()->s5c_port, &sgw_self()->s5c_node);
if (rv != CORE_OK)
{
d_error("Can't establish S5-C Path with PGW");
d_error("Can't establish S5-C Path for PGW");
return rv;
}
rv = gtp_open(&sgw_self()->s5u_node, _gtpv1_u_recv_cb);
rv = gtp_listen(&sgw_self()->s5u_sock, _gtpv1_u_recv_cb,
sgw_self()->s5u_addr, sgw_self()->s5u_port, &sgw_self()->s5u_node);
if (rv != CORE_OK)
{
d_error("Can't establish S5-U Path with PGW");
d_error("Can't establish S5-U Path for PGW");
return rv;
}
@ -114,42 +117,45 @@ status_t sgw_path_close()
{
status_t rv;
rv = gtp_close(&sgw_self()->s11_node);
rv = gtp_close(sgw_self()->s11_sock);
if (rv != CORE_OK)
{
d_error("Can't close S11 Path with MME");
d_error("Can't close S11 Path for MME");
return rv;
}
rv = gtp_close(&sgw_self()->s5c_node);
rv = gtp_close(sgw_self()->s5c_sock);
if (rv != CORE_OK)
{
d_error("Can't close S5-C Path with MME");
d_error("Can't close S5-C Path for MME");
return rv;
}
rv = gtp_close(&sgw_self()->s5u_node);
rv = gtp_close(sgw_self()->s5u_sock);
if (rv != CORE_OK)
{
d_error("Can't close S5-U Path with MME");
d_error("Can't close S5-U Path for MME");
return rv;
}
return CORE_OK;
}
status_t sgw_path_send_to_s11(pkbuf_t *pkbuf)
status_t sgw_s11_send_to_mme(pkbuf_t *pkbuf)
{
return gtp_send(&sgw_self()->s11_node, pkbuf);
d_assert(pkbuf, return CORE_ERROR, "Null param");
return gtp_send(sgw_self()->s11_sock, &sgw_self()->s11_node, pkbuf);
}
status_t sgw_path_send_to_s5c(pkbuf_t *pkbuf)
status_t sgw_s5c_send_to_pgw(pkbuf_t *pkbuf)
{
return gtp_send(&sgw_self()->s5c_node, pkbuf);
d_assert(pkbuf, return CORE_ERROR, "Null param");
return gtp_send(sgw_self()->s5c_sock, &sgw_self()->s5c_node, pkbuf);
}
status_t sgw_path_send_to_s5u(pkbuf_t *pkbuf)
status_t sgw_s5u_send_to_pgw(pkbuf_t *pkbuf)
{
return gtp_send(&sgw_self()->s5u_node, pkbuf);
d_assert(pkbuf, return CORE_ERROR, "Null param");
return gtp_send(sgw_self()->s5u_sock, &sgw_self()->s5u_node, pkbuf);
}

View File

@ -10,9 +10,9 @@ extern "C" {
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);
CORE_DECLARE(status_t) sgw_s11_send_to_mme(pkbuf_t *pkbuf);
CORE_DECLARE(status_t) sgw_s5c_send_to_pgw(pkbuf_t *pkbuf);
CORE_DECLARE(status_t) sgw_s5u_send_to_pgw(pkbuf_t *pkbuf);
#ifdef __cplusplus
}