All GTP re-archi done

This commit is contained in:
Sukchan Lee 2017-09-02 01:48:09 +09:00
parent 6ddaa2a91e
commit 3bef0ac82f
11 changed files with 165 additions and 306 deletions

View File

@ -637,9 +637,7 @@ status_t gtp_xact_receive(gtp_node_t *gnode, pkbuf_t *pkbuf,
new = gtp_xact_find_by_xid(gnode, h->type, GTP_SQN_TO_XID(h->sqn)); new = gtp_xact_find_by_xid(gnode, h->type, GTP_SQN_TO_XID(h->sqn));
if (!new) if (!new)
{
new = gtp_xact_remote_create(gnode, h->sqn); new = gtp_xact_remote_create(gnode, h->sqn);
}
d_assert(new, return CORE_ERROR, "Null param"); d_assert(new, return CORE_ERROR, "Null param");
d_trace(3, "[%d] %s Receive peer %s:%d\n", d_trace(3, "[%d] %s Receive peer %s:%d\n",

View File

@ -881,14 +881,14 @@ status_t mme_sgw_remove_all()
return CORE_OK; return CORE_OK;
} }
mme_sgw_t* mme_sgw_find_by_node(mme_sgw_t *gnode) mme_sgw_t* mme_sgw_find(c_uint32_t addr, c_uint16_t port)
{ {
mme_sgw_t *sgw = NULL; mme_sgw_t *sgw = NULL;
sgw = mme_sgw_first(); sgw = mme_sgw_first();
while (sgw) while (sgw)
{ {
if (GTP_COMPARE_NODE(sgw, gnode)) if (sgw->addr == addr && sgw->port == port)
break; break;
sgw = mme_sgw_next(sgw); sgw = mme_sgw_next(sgw);

View File

@ -321,7 +321,7 @@ CORE_DECLARE(status_t) mme_context_setup_trace_module(void);
CORE_DECLARE(mme_sgw_t*) mme_sgw_add(void); CORE_DECLARE(mme_sgw_t*) mme_sgw_add(void);
CORE_DECLARE(status_t) mme_sgw_remove(mme_sgw_t *sgw); CORE_DECLARE(status_t) mme_sgw_remove(mme_sgw_t *sgw);
CORE_DECLARE(status_t) mme_sgw_remove_all(void); CORE_DECLARE(status_t) mme_sgw_remove_all(void);
CORE_DECLARE(mme_sgw_t*) mme_sgw_find_by_node(gtp_node_t *gnode); CORE_DECLARE(mme_sgw_t*) mme_sgw_find(c_uint32_t addr, c_uint16_t port);
CORE_DECLARE(mme_sgw_t*) mme_sgw_first(void); CORE_DECLARE(mme_sgw_t*) mme_sgw_first(void);
CORE_DECLARE(mme_sgw_t*) mme_sgw_next(mme_sgw_t *sgw); CORE_DECLARE(mme_sgw_t*) mme_sgw_next(mme_sgw_t *sgw);

View File

@ -13,7 +13,8 @@ static int _gtpv2_c_recv_cb(net_sock_t *sock, void *data)
status_t rv; status_t rv;
event_t e; event_t e;
pkbuf_t *pkbuf = NULL; pkbuf_t *pkbuf = NULL;
gtp_node_t gnode; c_uint32_t addr;
c_uint16_t port;
mme_sgw_t *sgw = NULL; mme_sgw_t *sgw = NULL;
d_assert(sock, return -1, "Null param"); d_assert(sock, return -1, "Null param");
@ -27,16 +28,17 @@ static int _gtpv2_c_recv_cb(net_sock_t *sock, void *data)
return -1; return -1;
} }
gnode.addr = sock->remote.sin_addr.s_addr; addr = sock->remote.sin_addr.s_addr;
gnode.port = ntohs(sock->remote.sin_port); port = ntohs(sock->remote.sin_port);
gnode.sock = sock; /* is it needed? */
sgw = mme_sgw_find_by_node(&gnode); sgw = mme_sgw_find(addr, port);
d_assert(sgw, return -1, "Can't find SGW from [%s:%d]", d_assert(sgw, return -1, "Can't find SGW from [%s:%d]",
INET_NTOP(&gnode.addr, buf), gnode.port); INET_NTOP(&addr, buf), port);
sgw->sock = sock; /* Is it needed? */
d_trace(10, "S11_PDU is received from SGW[%s:%d]\n", d_trace(10, "S11_PDU is received from SGW[%s:%d]\n",
INET_NTOP(&gnode.addr, buf), gnode.port); INET_NTOP(&addr, buf), port);
d_trace_hex(10, pkbuf->payload, pkbuf->len); d_trace_hex(10, pkbuf->payload, pkbuf->len);
event_set(&e, MME_EVT_S11_MESSAGE); event_set(&e, MME_EVT_S11_MESSAGE);

View File

@ -37,9 +37,6 @@ status_t pgw_context_init()
pool_init(&pgw_ip_pool_pool, MAX_POOL_OF_SESS); pool_init(&pgw_ip_pool_pool, MAX_POOL_OF_SESS);
list_init(&self.s5c_node.local_list);
list_init(&self.s5c_node.remote_list);
self.sess_hash = hash_make(); self.sess_hash = hash_make();
context_initiaized = 1; context_initiaized = 1;
@ -52,9 +49,7 @@ status_t pgw_context_final()
d_assert(context_initiaized == 1, return CORE_ERROR, d_assert(context_initiaized == 1, return CORE_ERROR,
"PGW context already has been finalized"); "PGW context already has been finalized");
gtp_xact_delete_all(&self.s5c_node);
pgw_sess_remove_all(); pgw_sess_remove_all();
pgw_sgw_remove_all(); pgw_sgw_remove_all();
d_assert(self.sess_hash, , "Null param"); d_assert(self.sess_hash, , "Null param");
@ -98,8 +93,6 @@ pgw_context_t* pgw_self()
static status_t pgw_context_prepare() static status_t pgw_context_prepare()
{ {
self.s5c_port = GTPV2_C_UDP_PORT; self.s5c_port = GTPV2_C_UDP_PORT;
self.s5c_node.port = GTPV2_C_UDP_PORT;
self.s5u_port = GTPV1_U_UDP_PORT; self.s5u_port = GTPV1_U_UDP_PORT;
return CORE_OK; return CORE_OK;
@ -113,12 +106,6 @@ static status_t pgw_context_validation()
context_self()->config.path); context_self()->config.path);
return CORE_ERROR; return CORE_ERROR;
} }
if (self.s5c_node.addr == 0)
{
d_error("No SGW.NEWORK.S5C_ADDR in '%s'",
context_self()->config.path);
return CORE_ERROR;
}
if (self.s5c_addr == 0) if (self.s5c_addr == 0)
{ {
d_error("No PGW.NEWORK.S5C_ADDR in '%s'", d_error("No PGW.NEWORK.S5C_ADDR in '%s'",
@ -162,7 +149,6 @@ status_t pgw_context_parse_config()
typedef enum { typedef enum {
START, ROOT, START, ROOT,
SGW_START, SGW_ROOT,
PGW_START, PGW_ROOT, PGW_START, PGW_ROOT,
SKIP, STOP SKIP, STOP
} parse_state; } parse_state;
@ -170,7 +156,6 @@ status_t pgw_context_parse_config()
parse_state stack = STOP; parse_state stack = STOP;
size_t root_tokens = 0; size_t root_tokens = 0;
size_t sgw_tokens = 0;
size_t pgw_tokens = 0; size_t pgw_tokens = 0;
size_t skip_tokens = 0; size_t skip_tokens = 0;
int i, j, m, n; int i, j, m, n;
@ -196,11 +181,7 @@ status_t pgw_context_parse_config()
} }
case ROOT: case ROOT:
{ {
if (jsmntok_equal(json, t, "SGW") == 0) if (jsmntok_equal(json, t, "PGW") == 0)
{
state = SGW_START;
}
else if (jsmntok_equal(json, t, "PGW") == 0)
{ {
state = PGW_START; state = PGW_START;
} }
@ -215,53 +196,6 @@ status_t pgw_context_parse_config()
} }
break; break;
} }
case SGW_START:
{
state = SGW_ROOT;
sgw_tokens = t->size;
break;
}
case SGW_ROOT:
{
if (jsmntok_equal(json, t, "NETWORK") == 0)
{
m = 1;
size = 1;
if ((t+1)->type == JSMN_ARRAY)
{
m = 2;
}
for (arr = 0; arr < size; arr++)
{
for (n = 1; n > 0; m++, n--)
{
n += (t+m)->size;
if (jsmntok_equal(json, t+m, "S5C_ADDR") == 0)
{
char *v = jsmntok_to_string(json, t+m+1);
if (v) self.s5c_node.addr = inet_addr(v);
}
else if (jsmntok_equal(json, t+m, "S5C_PORT") == 0)
{
char *v = jsmntok_to_string(json, t+m+1);
if (v) self.s5c_node.port = atoi(v);
}
}
}
}
state = SKIP;
stack = SGW_ROOT;
skip_tokens = t->size;
sgw_tokens--;
if (sgw_tokens == 0) stack = ROOT;
break;
}
case PGW_START: case PGW_START:
{ {
state = PGW_ROOT; state = PGW_ROOT;
@ -529,14 +463,14 @@ status_t pgw_sgw_remove_all()
return CORE_OK; return CORE_OK;
} }
pgw_sgw_t* pgw_sgw_find_by_node(pgw_sgw_t *gnode) pgw_sgw_t* pgw_sgw_find(c_uint32_t addr, c_uint16_t port)
{ {
pgw_sgw_t *sgw = NULL; pgw_sgw_t *sgw = NULL;
sgw = pgw_sgw_first(); sgw = pgw_sgw_first();
while (sgw) while (sgw)
{ {
if (GTP_COMPARE_NODE(sgw, gnode)) if (sgw->addr == addr && sgw->port == port)
break; break;
sgw = pgw_sgw_next(sgw); sgw = pgw_sgw_next(sgw);

View File

@ -25,7 +25,6 @@ typedef struct _pgw_context_t {
c_uint32_t s5c_addr; /* PGW S5-C local address */ c_uint32_t s5c_addr; /* PGW S5-C local address */
c_uint32_t s5c_port; /* PGW S5-C local port */ c_uint32_t s5c_port; /* PGW S5-C local port */
net_sock_t* s5c_sock; /* PGW S5-C local listen socket */ 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_addr; /* PGW S5-U local address */
c_uint32_t s5u_port; /* PGW S5-U local port */ c_uint32_t s5u_port; /* PGW S5-U local port */
@ -121,7 +120,7 @@ CORE_DECLARE(status_t) pgw_context_setup_trace_module(void);
CORE_DECLARE(pgw_sgw_t*) pgw_sgw_add(void); CORE_DECLARE(pgw_sgw_t*) pgw_sgw_add(void);
CORE_DECLARE(status_t) pgw_sgw_remove(pgw_sgw_t *sgw); CORE_DECLARE(status_t) pgw_sgw_remove(pgw_sgw_t *sgw);
CORE_DECLARE(status_t) pgw_sgw_remove_all(void); CORE_DECLARE(status_t) pgw_sgw_remove_all(void);
CORE_DECLARE(pgw_sgw_t*) pgw_sgw_find_by_node(gtp_node_t *gnode); CORE_DECLARE(pgw_sgw_t*) pgw_sgw_find(c_uint32_t addr, c_uint16_t port);
CORE_DECLARE(pgw_sgw_t*) pgw_sgw_first(void); CORE_DECLARE(pgw_sgw_t*) pgw_sgw_first(void);
CORE_DECLARE(pgw_sgw_t*) pgw_sgw_next(pgw_sgw_t *sgw); CORE_DECLARE(pgw_sgw_t*) pgw_sgw_next(pgw_sgw_t *sgw);

View File

@ -86,10 +86,11 @@ static int _gtpv2_c_recv_cb(net_sock_t *sock, void *data)
event_t e; event_t e;
status_t rv; status_t rv;
pkbuf_t *pkbuf = NULL; pkbuf_t *pkbuf = NULL;
gtp_node_t *gnode = data; c_uint32_t addr;
c_uint16_t port;
pgw_sgw_t *sgw = NULL;
d_assert(sock, return -1, "Null param"); d_assert(sock, return -1, "Null param");
d_assert(gnode, return -1, "Null param");
pkbuf = gtp_read(sock); pkbuf = gtp_read(sock);
if (pkbuf == NULL) if (pkbuf == NULL)
@ -103,8 +104,22 @@ static int _gtpv2_c_recv_cb(net_sock_t *sock, void *data)
d_trace(10, "S5-C PDU received from PGW\n"); d_trace(10, "S5-C PDU received from PGW\n");
d_trace_hex(10, pkbuf->payload, pkbuf->len); d_trace_hex(10, pkbuf->payload, pkbuf->len);
addr = sock->remote.sin_addr.s_addr;
port = ntohs(sock->remote.sin_port);
sgw = pgw_sgw_find(addr, port);
if (!sgw)
{
sgw = pgw_sgw_add();
d_assert(sgw, return -1, "Can't add MME-GTP node");
sgw->addr = addr;
sgw->port = port;
sgw->sock = sock;
}
event_set(&e, PGW_EVT_S5C_MESSAGE); event_set(&e, PGW_EVT_S5C_MESSAGE);
event_set_param1(&e, (c_uintptr_t)gnode); event_set_param1(&e, (c_uintptr_t)sgw);
event_set_param2(&e, (c_uintptr_t)pkbuf); event_set_param2(&e, (c_uintptr_t)pkbuf);
rv = pgw_event_send(&e); rv = pgw_event_send(&e);
if (rv != CORE_OK) if (rv != CORE_OK)
@ -160,15 +175,13 @@ status_t pgw_gtp_open()
status_t rv; status_t rv;
rv = gtp_listen(&pgw_self()->s5c_sock, _gtpv2_c_recv_cb, rv = gtp_listen(&pgw_self()->s5c_sock, _gtpv2_c_recv_cb,
pgw_self()->s5c_addr, pgw_self()->s5c_port, &pgw_self()->s5c_node); pgw_self()->s5c_addr, pgw_self()->s5c_port, NULL);
if (rv != CORE_OK) if (rv != CORE_OK)
{ {
d_error("Can't establish S5-C Path for PGW"); d_error("Can't establish S5-C Path for PGW");
return rv; return rv;
} }
pgw_self()->s5c_node.sock = pgw_self()->s5c_sock;
rv = gtp_listen(&pgw_self()->s5u_sock, _gtpv1_u_recv_cb, rv = gtp_listen(&pgw_self()->s5u_sock, _gtpv1_u_recv_cb,
pgw_self()->s5u_addr, pgw_self()->s5u_port, NULL); pgw_self()->s5u_addr, pgw_self()->s5u_port, NULL);
if (rv != CORE_OK) if (rv != CORE_OK)

View File

@ -39,12 +39,6 @@ status_t sgw_context_init()
index_init(&sgw_sess_pool, MAX_POOL_OF_SESS); index_init(&sgw_sess_pool, MAX_POOL_OF_SESS);
index_init(&sgw_bearer_pool, MAX_POOL_OF_BEARER); index_init(&sgw_bearer_pool, MAX_POOL_OF_BEARER);
list_init(&self.s11_node.local_list);
list_init(&self.s11_node.remote_list);
list_init(&self.s5c_node.local_list);
list_init(&self.s5c_node.remote_list);
self.imsi_ue_hash = hash_make(); self.imsi_ue_hash = hash_make();
context_initialized = 1; context_initialized = 1;
@ -57,11 +51,7 @@ status_t sgw_context_final()
d_assert(context_initialized == 1, return CORE_ERROR, d_assert(context_initialized == 1, return CORE_ERROR,
"SGW context already has been finalized"); "SGW context already has been finalized");
gtp_xact_delete_all(&self.s11_node);
gtp_xact_delete_all(&self.s5c_node);
sgw_ue_remove_all(); sgw_ue_remove_all();
sgw_mme_remove_all(); sgw_mme_remove_all();
sgw_pgw_remove_all(); sgw_pgw_remove_all();
@ -88,11 +78,7 @@ sgw_context_t* sgw_self()
static status_t sgw_context_prepare() static status_t sgw_context_prepare()
{ {
self.s11_port = GTPV2_C_UDP_PORT; self.s11_port = GTPV2_C_UDP_PORT;
self.s11_node.port = GTPV2_C_UDP_PORT;
self.s5c_port = GTPV2_C_UDP_PORT; self.s5c_port = GTPV2_C_UDP_PORT;
self.s5c_node.port = GTPV2_C_UDP_PORT;
self.s1u_port = GTPV1_U_UDP_PORT; self.s1u_port = GTPV1_U_UDP_PORT;
self.s5u_port = GTPV1_U_UDP_PORT; self.s5u_port = GTPV1_U_UDP_PORT;
@ -101,18 +87,6 @@ static status_t sgw_context_prepare()
static status_t sgw_context_validation() static status_t sgw_context_validation()
{ {
if (self.s11_node.addr == 0)
{
d_error("No MME.NEWORK.S11_ADDR in '%s'",
context_self()->config.path);
return CORE_ERROR;
}
if (self.s5c_node.addr == 0)
{
d_error("No PGW.NEWORK.S5C_ADDR in '%s'",
context_self()->config.path);
return CORE_ERROR;
}
if (self.s11_addr == 0) if (self.s11_addr == 0)
{ {
d_error("No SGW.NEWORK.S11_ADDR in '%s'", d_error("No SGW.NEWORK.S11_ADDR in '%s'",
@ -150,18 +124,14 @@ status_t sgw_context_parse_config()
typedef enum { typedef enum {
START, ROOT, START, ROOT,
MME_START, MME_ROOT,
SGW_START, SGW_ROOT, SGW_START, SGW_ROOT,
PGW_START, PGW_ROOT,
SKIP, STOP SKIP, STOP
} parse_state; } parse_state;
parse_state state = START; parse_state state = START;
parse_state stack = STOP; parse_state stack = STOP;
size_t root_tokens = 0; size_t root_tokens = 0;
size_t mme_tokens = 0;
size_t sgw_tokens = 0; size_t sgw_tokens = 0;
size_t pgw_tokens = 0;
size_t skip_tokens = 0; size_t skip_tokens = 0;
int i, j, m, n; int i, j, m, n;
int arr, size; int arr, size;
@ -186,18 +156,10 @@ status_t sgw_context_parse_config()
} }
case ROOT: case ROOT:
{ {
if (jsmntok_equal(json, t, "MME") == 0) if (jsmntok_equal(json, t, "SGW") == 0)
{
state = MME_START;
}
else if (jsmntok_equal(json, t, "SGW") == 0)
{ {
state = SGW_START; state = SGW_START;
} }
else if (jsmntok_equal(json, t, "PGW") == 0)
{
state = PGW_START;
}
else else
{ {
state = SKIP; state = SKIP;
@ -209,53 +171,6 @@ status_t sgw_context_parse_config()
} }
break; break;
} }
case MME_START:
{
state = MME_ROOT;
mme_tokens = t->size;
break;
}
case MME_ROOT:
{
if (jsmntok_equal(json, t, "NETWORK") == 0)
{
m = 1;
size = 1;
if ((t+1)->type == JSMN_ARRAY)
{
m = 2;
}
for (arr = 0; arr < size; arr++)
{
for (n = 1; n > 0; m++, n--)
{
n += (t+m)->size;
if (jsmntok_equal(json, t+m, "S11_ADDR") == 0)
{
char *v = jsmntok_to_string(json, t+m+1);
if (v) self.s11_node.addr = inet_addr(v);
}
else if (jsmntok_equal(json, t+m, "S11_PORT") == 0)
{
char *v = jsmntok_to_string(json, t+m+1);
if (v) self.s11_node.port = atoi(v);
}
}
}
}
state = SKIP;
stack = MME_ROOT;
skip_tokens = t->size;
mme_tokens--;
if (mme_tokens == 0) stack = ROOT;
break;
}
case SGW_START: case SGW_START:
{ {
state = SGW_ROOT; state = SGW_ROOT;
@ -333,53 +248,6 @@ status_t sgw_context_parse_config()
if (sgw_tokens == 0) stack = ROOT; if (sgw_tokens == 0) stack = ROOT;
break; break;
} }
case PGW_START:
{
state = PGW_ROOT;
pgw_tokens = t->size;
break;
}
case PGW_ROOT:
{
if (jsmntok_equal(json, t, "NETWORK") == 0)
{
m = 1;
size = 1;
if ((t+1)->type == JSMN_ARRAY)
{
m = 2;
}
for (arr = 0; arr < size; arr++)
{
for (n = 1; n > 0; m++, n--)
{
n += (t+m)->size;
if (jsmntok_equal(json, t+m, "S5C_ADDR") == 0)
{
char *v = jsmntok_to_string(json, t+m+1);
if (v) self.s5c_node.addr = inet_addr(v);
}
else if (jsmntok_equal(json, t+m, "S5C_PORT") == 0)
{
char *v = jsmntok_to_string(json, t+m+1);
if (v) self.s5c_node.port = atoi(v);
}
}
}
}
state = SKIP;
stack = PGW_ROOT;
skip_tokens = t->size;
pgw_tokens--;
if (pgw_tokens == 0) stack = ROOT;
break;
}
case SKIP: case SKIP:
{ {
skip_tokens += t->size; skip_tokens += t->size;
@ -449,64 +317,64 @@ status_t sgw_context_setup_trace_module()
sgw_mme_t* sgw_mme_add() sgw_mme_t* sgw_mme_add()
{ {
sgw_mme_t *sgw = NULL; sgw_mme_t *mme = NULL;
pool_alloc_node(&sgw_mme_pool, &sgw); pool_alloc_node(&sgw_mme_pool, &mme);
d_assert(sgw, return NULL, "Null param"); d_assert(mme, return NULL, "Null param");
memset(sgw, 0, sizeof(sgw_mme_t)); memset(mme, 0, sizeof(sgw_mme_t));
list_init(&sgw->local_list); list_init(&mme->local_list);
list_init(&sgw->remote_list); list_init(&mme->remote_list);
list_append(&self.mme_list, sgw); list_append(&self.mme_list, mme);
return sgw; return mme;
} }
status_t sgw_mme_remove(sgw_mme_t *sgw) status_t sgw_mme_remove(sgw_mme_t *mme)
{ {
d_assert(sgw, return CORE_ERROR, "Null param"); d_assert(mme, return CORE_ERROR, "Null param");
gtp_xact_delete_all(sgw); gtp_xact_delete_all(mme);
list_remove(&self.mme_list, sgw); list_remove(&self.mme_list, mme);
pool_free_node(&sgw_mme_pool, sgw); pool_free_node(&sgw_mme_pool, mme);
return CORE_OK; return CORE_OK;
} }
status_t sgw_mme_remove_all() status_t sgw_mme_remove_all()
{ {
sgw_mme_t *sgw = NULL, *next_sgw = NULL; sgw_mme_t *mme = NULL, *next_mme = NULL;
sgw = sgw_mme_first(); mme = sgw_mme_first();
while (sgw) while (mme)
{ {
next_sgw = sgw_mme_next(sgw); next_mme = sgw_mme_next(mme);
sgw_mme_remove(sgw); sgw_mme_remove(mme);
sgw = next_sgw; mme = next_mme;
} }
return CORE_OK; return CORE_OK;
} }
sgw_mme_t* sgw_mme_find_by_node(sgw_mme_t *gnode) sgw_mme_t* sgw_mme_find(c_uint32_t addr, c_uint16_t port)
{ {
sgw_mme_t *sgw = NULL; sgw_mme_t *mme = NULL;
sgw = sgw_mme_first(); mme = sgw_mme_first();
while (sgw) while (mme)
{ {
if (GTP_COMPARE_NODE(sgw, gnode)) if (mme->addr == addr && mme->port == port)
break; break;
sgw = sgw_mme_next(sgw); mme = sgw_mme_next(mme);
} }
return sgw; return mme;
} }
sgw_mme_t* sgw_mme_first() sgw_mme_t* sgw_mme_first()
@ -514,71 +382,71 @@ sgw_mme_t* sgw_mme_first()
return list_first(&self.mme_list); return list_first(&self.mme_list);
} }
sgw_mme_t* sgw_mme_next(sgw_mme_t *sgw) sgw_mme_t* sgw_mme_next(sgw_mme_t *mme)
{ {
return list_next(sgw); return list_next(mme);
} }
sgw_pgw_t* sgw_pgw_add() sgw_pgw_t* sgw_pgw_add()
{ {
sgw_pgw_t *sgw = NULL; sgw_pgw_t *pgw = NULL;
pool_alloc_node(&sgw_pgw_pool, &sgw); pool_alloc_node(&sgw_pgw_pool, &pgw);
d_assert(sgw, return NULL, "Null param"); d_assert(pgw, return NULL, "Null param");
memset(sgw, 0, sizeof(sgw_pgw_t)); memset(pgw, 0, sizeof(sgw_pgw_t));
list_init(&sgw->local_list); list_init(&pgw->local_list);
list_init(&sgw->remote_list); list_init(&pgw->remote_list);
list_append(&self.pgw_list, sgw); list_append(&self.pgw_list, pgw);
return sgw; return pgw;
} }
status_t sgw_pgw_remove(sgw_pgw_t *sgw) status_t sgw_pgw_remove(sgw_pgw_t *pgw)
{ {
d_assert(sgw, return CORE_ERROR, "Null param"); d_assert(pgw, return CORE_ERROR, "Null param");
gtp_xact_delete_all(sgw); gtp_xact_delete_all(pgw);
list_remove(&self.pgw_list, sgw); list_remove(&self.pgw_list, pgw);
pool_free_node(&sgw_pgw_pool, sgw); pool_free_node(&sgw_pgw_pool, pgw);
return CORE_OK; return CORE_OK;
} }
status_t sgw_pgw_remove_all() status_t sgw_pgw_remove_all()
{ {
sgw_pgw_t *sgw = NULL, *next_sgw = NULL; sgw_pgw_t *pgw = NULL, *next_pgw = NULL;
sgw = sgw_pgw_first(); pgw = sgw_pgw_first();
while (sgw) while (pgw)
{ {
next_sgw = sgw_pgw_next(sgw); next_pgw = sgw_pgw_next(pgw);
sgw_pgw_remove(sgw); sgw_pgw_remove(pgw);
sgw = next_sgw; pgw = next_pgw;
} }
return CORE_OK; return CORE_OK;
} }
sgw_pgw_t* sgw_pgw_find_by_node(sgw_pgw_t *gnode) sgw_pgw_t* sgw_pgw_find(c_uint32_t addr, c_uint16_t port)
{ {
sgw_pgw_t *sgw = NULL; sgw_pgw_t *pgw = NULL;
sgw = sgw_pgw_first(); pgw = sgw_pgw_first();
while (sgw) while (pgw)
{ {
if (GTP_COMPARE_NODE(sgw, gnode)) if (pgw->addr == addr && pgw->port == port)
break; break;
sgw = sgw_pgw_next(sgw); pgw = sgw_pgw_next(pgw);
} }
return sgw; return pgw;
} }
sgw_pgw_t* sgw_pgw_first() sgw_pgw_t* sgw_pgw_first()
@ -586,9 +454,9 @@ sgw_pgw_t* sgw_pgw_first()
return list_first(&self.pgw_list); return list_first(&self.pgw_list);
} }
sgw_pgw_t* sgw_pgw_next(sgw_pgw_t *sgw) sgw_pgw_t* sgw_pgw_next(sgw_pgw_t *pgw)
{ {
return list_next(sgw); return list_next(pgw);
} }
sgw_ue_t* sgw_ue_add( sgw_ue_t* sgw_ue_add(

View File

@ -25,12 +25,10 @@ typedef struct _sgw_context_t {
c_uint32_t s11_addr; /* SGW S11 local address */ c_uint32_t s11_addr; /* SGW S11 local address */
c_uint32_t s11_port; /* SGW S11 local port */ c_uint32_t s11_port; /* SGW S11 local port */
net_sock_t* s11_sock; /* SGW S11 local listen socket */ 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_addr; /* SGW S5-C local address */
c_uint32_t s5c_port; /* SGW S5-C local port */ c_uint32_t s5c_port; /* SGW S5-C local port */
net_sock_t* s5c_sock; /* SGW S5-C local listen socket */ 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 s1u_addr; /* SGW S1-U local address */ c_uint32_t s1u_addr; /* SGW S1-U local address */
c_uint32_t s1u_port; /* SGW S1-U local port */ c_uint32_t s1u_port; /* SGW S1-U local port */
@ -85,6 +83,8 @@ typedef struct _sgw_sess_t {
list_t bearer_list; list_t bearer_list;
/* Related Context */ /* Related Context */
sgw_mme_t *mme;
sgw_mme_t *pgw;
sgw_ue_t *sgw_ue; sgw_ue_t *sgw_ue;
} sgw_sess_t; } sgw_sess_t;
@ -138,18 +138,18 @@ CORE_DECLARE(status_t) sgw_context_parse_config(void);
CORE_DECLARE(status_t) sgw_context_setup_trace_module(void); CORE_DECLARE(status_t) sgw_context_setup_trace_module(void);
CORE_DECLARE(sgw_mme_t*) sgw_mme_add(void); CORE_DECLARE(sgw_mme_t*) sgw_mme_add(void);
CORE_DECLARE(status_t) sgw_mme_remove(sgw_mme_t *sgw); CORE_DECLARE(status_t) sgw_mme_remove(sgw_mme_t *mme);
CORE_DECLARE(status_t) sgw_mme_remove_all(void); CORE_DECLARE(status_t) sgw_mme_remove_all(void);
CORE_DECLARE(sgw_mme_t*) sgw_mme_find_by_node(gtp_node_t *gnode); CORE_DECLARE(sgw_mme_t*) sgw_mme_find(c_uint32_t addr, c_uint16_t port);
CORE_DECLARE(sgw_mme_t*) sgw_mme_first(void); CORE_DECLARE(sgw_mme_t*) sgw_mme_first(void);
CORE_DECLARE(sgw_mme_t*) sgw_mme_next(sgw_mme_t *sgw); CORE_DECLARE(sgw_mme_t*) sgw_mme_next(sgw_mme_t *mme);
CORE_DECLARE(sgw_pgw_t*) sgw_pgw_add(void); CORE_DECLARE(sgw_pgw_t*) sgw_pgw_add(void);
CORE_DECLARE(status_t) sgw_pgw_remove(sgw_pgw_t *sgw); CORE_DECLARE(status_t) sgw_pgw_remove(sgw_pgw_t *pgw);
CORE_DECLARE(status_t) sgw_pgw_remove_all(void); CORE_DECLARE(status_t) sgw_pgw_remove_all(void);
CORE_DECLARE(sgw_pgw_t*) sgw_pgw_find_by_node(gtp_node_t *gnode); CORE_DECLARE(sgw_pgw_t*) sgw_pgw_find(c_uint32_t addr, c_uint16_t port);
CORE_DECLARE(sgw_pgw_t*) sgw_pgw_first(void); CORE_DECLARE(sgw_pgw_t*) sgw_pgw_first(void);
CORE_DECLARE(sgw_pgw_t*) sgw_pgw_next(sgw_pgw_t *sgw); CORE_DECLARE(sgw_pgw_t*) sgw_pgw_next(sgw_pgw_t *pgw);
CORE_DECLARE(sgw_ue_t*) sgw_ue_add(c_uint8_t *imsi, int imsi_len, CORE_DECLARE(sgw_ue_t*) sgw_ue_add(c_uint8_t *imsi, int imsi_len,
c_int8_t *apn, c_uint8_t id); c_int8_t *apn, c_uint8_t id);

View File

@ -15,10 +15,12 @@ static int _gtpv2_c_recv_cb(net_sock_t *sock, void *data)
event_t e; event_t e;
status_t rv; status_t rv;
pkbuf_t *pkbuf = NULL; pkbuf_t *pkbuf = NULL;
gtp_node_t *gnode = data; c_uint32_t addr;
c_uint16_t port;
event_e event = (event_e)data;
d_assert(sock, return -1, "Null param"); d_assert(sock, return -1, "Null param");
d_assert(gnode, return -1, "Null param"); d_assert(data, return -1, "Null param");
pkbuf = gtp_read(sock); pkbuf = gtp_read(sock);
if (pkbuf == NULL) if (pkbuf == NULL)
@ -29,23 +31,42 @@ static int _gtpv2_c_recv_cb(net_sock_t *sock, void *data)
return -1; return -1;
} }
if (GTP_COMPARE_NODE(gnode, &sgw_self()->s11_node)) addr = sock->remote.sin_addr.s_addr;
port = ntohs(sock->remote.sin_port);
event_set(&e, event);
event_set_param2(&e, (c_uintptr_t)pkbuf);
if (event == SGW_EVT_S11_MESSAGE)
{ {
sgw_mme_t *mme = sgw_mme_find(addr, port);
if (!mme)
{
mme = sgw_mme_add();
d_assert(mme, return -1, "Can't add MME-GTP node");
mme->addr = addr;
mme->port = port;
mme->sock = sock;
}
d_trace(10, "S11 PDU received from MME\n"); d_trace(10, "S11 PDU received from MME\n");
event_set(&e, SGW_EVT_S11_MESSAGE);
event_set_param1(&e, (c_uintptr_t)mme);
} }
else if (GTP_COMPARE_NODE(gnode, &sgw_self()->s5c_node)) else if (event == SGW_EVT_S5C_MESSAGE)
{ {
sgw_pgw_t *pgw = sgw_pgw_find(addr, port);
d_assert(pgw, return -1, "Can't add PGW-GTP node");
d_trace(10, "S5-C PDU received from PGW\n"); d_trace(10, "S5-C PDU received from PGW\n");
event_set(&e, SGW_EVT_S5C_MESSAGE);
event_set_param1(&e, (c_uintptr_t)pgw);
} }
else else
d_assert(0, pkbuf_free(pkbuf); return -1, "Unknown GTP-Node"); d_assert(0, pkbuf_free(pkbuf); return -1, "Unknown GTP-Node");
d_trace_hex(10, pkbuf->payload, pkbuf->len); d_trace_hex(10, pkbuf->payload, pkbuf->len);
event_set_param1(&e, (c_uintptr_t)gnode);
event_set_param2(&e, (c_uintptr_t)pkbuf);
rv = sgw_event_send(&e); rv = sgw_event_send(&e);
if (rv != CORE_OK) if (rv != CORE_OK)
{ {
@ -243,25 +264,23 @@ status_t sgw_gtp_open()
status_t rv; status_t rv;
rv = gtp_listen(&sgw_self()->s11_sock, _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); sgw_self()->s11_addr, sgw_self()->s11_port,
(void*)SGW_EVT_S11_MESSAGE);
if (rv != CORE_OK) if (rv != CORE_OK)
{ {
d_error("Can't establish S11 Path for SGW"); d_error("Can't establish S11 Path for SGW");
return rv; return rv;
} }
sgw_self()->s11_node.sock = sgw_self()->s11_sock;
rv = gtp_listen(&sgw_self()->s5c_sock, _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); sgw_self()->s5c_addr, sgw_self()->s5c_port,
(void*)SGW_EVT_S5C_MESSAGE);
if (rv != CORE_OK) if (rv != CORE_OK)
{ {
d_error("Can't establish S5-C Path for SGW"); d_error("Can't establish S5-C Path for SGW");
return rv; return rv;
} }
sgw_self()->s5c_node.sock = sgw_self()->s5c_sock;
rv = gtp_listen(&sgw_self()->s5u_sock, _gtpv1_s5u_recv_cb, rv = gtp_listen(&sgw_self()->s5u_sock, _gtpv1_s5u_recv_cb,
sgw_self()->s5u_addr, sgw_self()->s5u_port, NULL); sgw_self()->s5u_addr, sgw_self()->s5u_port, NULL);
if (rv != CORE_OK) if (rv != CORE_OK)

View File

@ -17,6 +17,10 @@ void sgw_handle_create_session_request(gtp_xact_t *s11_xact,
gtp_create_session_request_t *req = NULL; gtp_create_session_request_t *req = NULL;
pkbuf_t *pkbuf = NULL; pkbuf_t *pkbuf = NULL;
gtp_f_teid_t *mme_s11_teid = NULL; gtp_f_teid_t *mme_s11_teid = NULL;
gtp_f_teid_t *pgw_s5c_teid = NULL;
sgw_pgw_t *pgw = NULL;
c_uint32_t addr;
c_uint16_t port;
gtp_f_teid_t sgw_s5c_teid, sgw_s5u_teid; gtp_f_teid_t sgw_s5c_teid, sgw_s5u_teid;
gtp_xact_t *s5c_xact = NULL; gtp_xact_t *s5c_xact = NULL;
@ -49,6 +53,11 @@ void sgw_handle_create_session_request(gtp_xact_t *s11_xact,
d_error("No APN"); d_error("No APN");
return; return;
} }
if (req->pgw_s5_s8_address_for_control_plane_or_pmip.presence == 0)
{
d_error("No PGW IP");
return;
}
sess = sgw_sess_find_by_ebi(sgw_ue, sess = sgw_sess_find_by_ebi(sgw_ue,
req->bearer_contexts_to_be_created.eps_bearer_id.u8); req->bearer_contexts_to_be_created.eps_bearer_id.u8);
@ -78,6 +87,26 @@ void sgw_handle_create_session_request(gtp_xact_t *s11_xact,
req->sender_f_teid_for_control_plane.len = GTP_F_TEID_IPV4_LEN; req->sender_f_teid_for_control_plane.len = GTP_F_TEID_IPV4_LEN;
/* Remove PGW-S5C */ /* Remove PGW-S5C */
pgw_s5c_teid = req->pgw_s5_s8_address_for_control_plane_or_pmip.data;
addr = pgw_s5c_teid->ipv4_addr;
port = GTPV2_C_UDP_PORT;
pgw = sgw_pgw_find(addr, port);
if (!pgw)
{
pgw = sgw_pgw_add();
d_assert(pgw, return, "Can't add PGW-GTP node");
pgw->addr = addr;
pgw->port = port;
pgw->sock = sgw_self()->s5c_sock;
}
/* Setup GTP Node */
sess->pgw = pgw;
sess->mme = s11_xact->gnode;
req->pgw_s5_s8_address_for_control_plane_or_pmip.presence = 0; req->pgw_s5_s8_address_for_control_plane_or_pmip.presence = 0;
/* Send Data Plane(DL) : SGW-S5U */ /* Send Data Plane(DL) : SGW-S5U */
@ -96,8 +125,7 @@ void sgw_handle_create_session_request(gtp_xact_t *s11_xact,
rv = gtp_build_msg(&pkbuf, gtp_message); rv = gtp_build_msg(&pkbuf, gtp_message);
d_assert(rv == CORE_OK, return, "gtp build failed"); d_assert(rv == CORE_OK, return, "gtp build failed");
s5c_xact = gtp_xact_local_create( s5c_xact = gtp_xact_local_create(sess->pgw, &gtp_message->h, pkbuf);
&sgw_self()->s5c_node, &gtp_message->h, pkbuf);
d_assert(s5c_xact, return, "Null param"); d_assert(s5c_xact, return, "Null param");
gtp_xact_associate(s11_xact, s5c_xact); gtp_xact_associate(s11_xact, s5c_xact);
@ -207,8 +235,7 @@ void sgw_handle_delete_session_request(gtp_xact_t *s11_xact,
rv = gtp_build_msg(&pkbuf, gtp_message); rv = gtp_build_msg(&pkbuf, gtp_message);
d_assert(rv == CORE_OK, return, "gtp build failed"); d_assert(rv == CORE_OK, return, "gtp build failed");
s5c_xact = gtp_xact_local_create( s5c_xact = gtp_xact_local_create(sess->pgw, &gtp_message->h, pkbuf);
&sgw_self()->s5c_node, &gtp_message->h, pkbuf);
d_assert(s5c_xact, return, "Null param"); d_assert(s5c_xact, return, "Null param");
gtp_xact_associate(s11_xact, s5c_xact); gtp_xact_associate(s11_xact, s5c_xact);
@ -319,8 +346,7 @@ void sgw_handle_lo_dldata_notification(sgw_bearer_t *bearer)
rv = gtp_build_msg(&pkbuf, &gtp_message); rv = gtp_build_msg(&pkbuf, &gtp_message);
d_assert(rv == CORE_OK, return, "gtp build failed"); d_assert(rv == CORE_OK, return, "gtp build failed");
xact = gtp_xact_local_create( xact = gtp_xact_local_create(sess->mme, &gtp_message.h, pkbuf);
&sgw_self()->s11_node, &gtp_message.h, pkbuf);
d_assert(xact, return, "Null param"); d_assert(xact, return, "Null param");
rv = gtp_xact_commit(xact); rv = gtp_xact_commit(xact);