forked from acouzens/open5gs
All GTP re-archi done
This commit is contained in:
parent
6ddaa2a91e
commit
3bef0ac82f
|
@ -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));
|
||||
if (!new)
|
||||
{
|
||||
new = gtp_xact_remote_create(gnode, h->sqn);
|
||||
}
|
||||
d_assert(new, return CORE_ERROR, "Null param");
|
||||
|
||||
d_trace(3, "[%d] %s Receive peer %s:%d\n",
|
||||
|
|
|
@ -881,14 +881,14 @@ status_t mme_sgw_remove_all()
|
|||
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;
|
||||
|
||||
sgw = mme_sgw_first();
|
||||
while (sgw)
|
||||
{
|
||||
if (GTP_COMPARE_NODE(sgw, gnode))
|
||||
if (sgw->addr == addr && sgw->port == port)
|
||||
break;
|
||||
|
||||
sgw = mme_sgw_next(sgw);
|
||||
|
|
|
@ -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(status_t) mme_sgw_remove(mme_sgw_t *sgw);
|
||||
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_next(mme_sgw_t *sgw);
|
||||
|
||||
|
|
|
@ -13,7 +13,8 @@ static int _gtpv2_c_recv_cb(net_sock_t *sock, void *data)
|
|||
status_t rv;
|
||||
event_t e;
|
||||
pkbuf_t *pkbuf = NULL;
|
||||
gtp_node_t gnode;
|
||||
c_uint32_t addr;
|
||||
c_uint16_t port;
|
||||
mme_sgw_t *sgw = NULL;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
gnode.addr = sock->remote.sin_addr.s_addr;
|
||||
gnode.port = ntohs(sock->remote.sin_port);
|
||||
gnode.sock = sock; /* is it needed? */
|
||||
addr = sock->remote.sin_addr.s_addr;
|
||||
port = ntohs(sock->remote.sin_port);
|
||||
|
||||
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]",
|
||||
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",
|
||||
INET_NTOP(&gnode.addr, buf), gnode.port);
|
||||
INET_NTOP(&addr, buf), port);
|
||||
d_trace_hex(10, pkbuf->payload, pkbuf->len);
|
||||
|
||||
event_set(&e, MME_EVT_S11_MESSAGE);
|
||||
|
|
|
@ -37,9 +37,6 @@ status_t pgw_context_init()
|
|||
|
||||
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();
|
||||
|
||||
context_initiaized = 1;
|
||||
|
@ -52,9 +49,7 @@ status_t pgw_context_final()
|
|||
d_assert(context_initiaized == 1, return CORE_ERROR,
|
||||
"PGW context already has been finalized");
|
||||
|
||||
gtp_xact_delete_all(&self.s5c_node);
|
||||
pgw_sess_remove_all();
|
||||
|
||||
pgw_sgw_remove_all();
|
||||
|
||||
d_assert(self.sess_hash, , "Null param");
|
||||
|
@ -98,8 +93,6 @@ pgw_context_t* pgw_self()
|
|||
static status_t pgw_context_prepare()
|
||||
{
|
||||
self.s5c_port = GTPV2_C_UDP_PORT;
|
||||
self.s5c_node.port = GTPV2_C_UDP_PORT;
|
||||
|
||||
self.s5u_port = GTPV1_U_UDP_PORT;
|
||||
|
||||
return CORE_OK;
|
||||
|
@ -113,12 +106,6 @@ static status_t pgw_context_validation()
|
|||
context_self()->config.path);
|
||||
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)
|
||||
{
|
||||
d_error("No PGW.NEWORK.S5C_ADDR in '%s'",
|
||||
|
@ -162,7 +149,6 @@ status_t pgw_context_parse_config()
|
|||
|
||||
typedef enum {
|
||||
START, ROOT,
|
||||
SGW_START, SGW_ROOT,
|
||||
PGW_START, PGW_ROOT,
|
||||
SKIP, STOP
|
||||
} parse_state;
|
||||
|
@ -170,7 +156,6 @@ status_t pgw_context_parse_config()
|
|||
parse_state stack = STOP;
|
||||
|
||||
size_t root_tokens = 0;
|
||||
size_t sgw_tokens = 0;
|
||||
size_t pgw_tokens = 0;
|
||||
size_t skip_tokens = 0;
|
||||
int i, j, m, n;
|
||||
|
@ -196,11 +181,7 @@ status_t pgw_context_parse_config()
|
|||
}
|
||||
case ROOT:
|
||||
{
|
||||
if (jsmntok_equal(json, t, "SGW") == 0)
|
||||
{
|
||||
state = SGW_START;
|
||||
}
|
||||
else if (jsmntok_equal(json, t, "PGW") == 0)
|
||||
if (jsmntok_equal(json, t, "PGW") == 0)
|
||||
{
|
||||
state = PGW_START;
|
||||
}
|
||||
|
@ -215,53 +196,6 @@ status_t pgw_context_parse_config()
|
|||
}
|
||||
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:
|
||||
{
|
||||
state = PGW_ROOT;
|
||||
|
@ -529,14 +463,14 @@ status_t pgw_sgw_remove_all()
|
|||
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;
|
||||
|
||||
sgw = pgw_sgw_first();
|
||||
while (sgw)
|
||||
{
|
||||
if (GTP_COMPARE_NODE(sgw, gnode))
|
||||
if (sgw->addr == addr && sgw->port == port)
|
||||
break;
|
||||
|
||||
sgw = pgw_sgw_next(sgw);
|
||||
|
|
|
@ -25,7 +25,6 @@ typedef struct _pgw_context_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 */
|
||||
|
@ -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(status_t) pgw_sgw_remove(pgw_sgw_t *sgw);
|
||||
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_next(pgw_sgw_t *sgw);
|
||||
|
||||
|
|
|
@ -86,10 +86,11 @@ 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;
|
||||
c_uint32_t addr;
|
||||
c_uint16_t port;
|
||||
pgw_sgw_t *sgw = NULL;
|
||||
|
||||
d_assert(sock, return -1, "Null param");
|
||||
d_assert(gnode, return -1, "Null param");
|
||||
|
||||
pkbuf = gtp_read(sock);
|
||||
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_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_param1(&e, (c_uintptr_t)gnode);
|
||||
event_set_param1(&e, (c_uintptr_t)sgw);
|
||||
event_set_param2(&e, (c_uintptr_t)pkbuf);
|
||||
rv = pgw_event_send(&e);
|
||||
if (rv != CORE_OK)
|
||||
|
@ -160,15 +175,13 @@ status_t pgw_gtp_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);
|
||||
pgw_self()->s5c_addr, pgw_self()->s5c_port, NULL);
|
||||
if (rv != CORE_OK)
|
||||
{
|
||||
d_error("Can't establish S5-C Path for PGW");
|
||||
return rv;
|
||||
}
|
||||
|
||||
pgw_self()->s5c_node.sock = pgw_self()->s5c_sock;
|
||||
|
||||
rv = gtp_listen(&pgw_self()->s5u_sock, _gtpv1_u_recv_cb,
|
||||
pgw_self()->s5u_addr, pgw_self()->s5u_port, NULL);
|
||||
if (rv != CORE_OK)
|
||||
|
|
|
@ -39,12 +39,6 @@ status_t sgw_context_init()
|
|||
index_init(&sgw_sess_pool, MAX_POOL_OF_SESS);
|
||||
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();
|
||||
|
||||
context_initialized = 1;
|
||||
|
@ -57,11 +51,7 @@ status_t sgw_context_final()
|
|||
d_assert(context_initialized == 1, return CORE_ERROR,
|
||||
"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_mme_remove_all();
|
||||
sgw_pgw_remove_all();
|
||||
|
||||
|
@ -88,11 +78,7 @@ sgw_context_t* sgw_self()
|
|||
static status_t sgw_context_prepare()
|
||||
{
|
||||
self.s11_port = GTPV2_C_UDP_PORT;
|
||||
self.s11_node.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.s5u_port = GTPV1_U_UDP_PORT;
|
||||
|
||||
|
@ -101,18 +87,6 @@ static status_t sgw_context_prepare()
|
|||
|
||||
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)
|
||||
{
|
||||
d_error("No SGW.NEWORK.S11_ADDR in '%s'",
|
||||
|
@ -150,18 +124,14 @@ status_t sgw_context_parse_config()
|
|||
|
||||
typedef enum {
|
||||
START, ROOT,
|
||||
MME_START, MME_ROOT,
|
||||
SGW_START, SGW_ROOT,
|
||||
PGW_START, PGW_ROOT,
|
||||
SKIP, STOP
|
||||
} parse_state;
|
||||
parse_state state = START;
|
||||
parse_state stack = STOP;
|
||||
|
||||
size_t root_tokens = 0;
|
||||
size_t mme_tokens = 0;
|
||||
size_t sgw_tokens = 0;
|
||||
size_t pgw_tokens = 0;
|
||||
size_t skip_tokens = 0;
|
||||
int i, j, m, n;
|
||||
int arr, size;
|
||||
|
@ -186,18 +156,10 @@ status_t sgw_context_parse_config()
|
|||
}
|
||||
case ROOT:
|
||||
{
|
||||
if (jsmntok_equal(json, t, "MME") == 0)
|
||||
{
|
||||
state = MME_START;
|
||||
}
|
||||
else if (jsmntok_equal(json, t, "SGW") == 0)
|
||||
if (jsmntok_equal(json, t, "SGW") == 0)
|
||||
{
|
||||
state = SGW_START;
|
||||
}
|
||||
else if (jsmntok_equal(json, t, "PGW") == 0)
|
||||
{
|
||||
state = PGW_START;
|
||||
}
|
||||
else
|
||||
{
|
||||
state = SKIP;
|
||||
|
@ -209,53 +171,6 @@ status_t sgw_context_parse_config()
|
|||
}
|
||||
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:
|
||||
{
|
||||
state = SGW_ROOT;
|
||||
|
@ -333,53 +248,6 @@ status_t sgw_context_parse_config()
|
|||
if (sgw_tokens == 0) stack = ROOT;
|
||||
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:
|
||||
{
|
||||
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 = NULL;
|
||||
sgw_mme_t *mme = NULL;
|
||||
|
||||
pool_alloc_node(&sgw_mme_pool, &sgw);
|
||||
d_assert(sgw, return NULL, "Null param");
|
||||
pool_alloc_node(&sgw_mme_pool, &mme);
|
||||
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(&sgw->remote_list);
|
||||
list_init(&mme->local_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);
|
||||
pool_free_node(&sgw_mme_pool, sgw);
|
||||
list_remove(&self.mme_list, mme);
|
||||
pool_free_node(&sgw_mme_pool, mme);
|
||||
|
||||
return CORE_OK;
|
||||
}
|
||||
|
||||
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();
|
||||
while (sgw)
|
||||
mme = sgw_mme_first();
|
||||
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;
|
||||
}
|
||||
|
||||
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();
|
||||
while (sgw)
|
||||
mme = sgw_mme_first();
|
||||
while (mme)
|
||||
{
|
||||
if (GTP_COMPARE_NODE(sgw, gnode))
|
||||
if (mme->addr == addr && mme->port == port)
|
||||
break;
|
||||
|
||||
sgw = sgw_mme_next(sgw);
|
||||
mme = sgw_mme_next(mme);
|
||||
}
|
||||
|
||||
return sgw;
|
||||
return mme;
|
||||
}
|
||||
|
||||
sgw_mme_t* sgw_mme_first()
|
||||
|
@ -514,71 +382,71 @@ sgw_mme_t* sgw_mme_first()
|
|||
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 = NULL;
|
||||
sgw_pgw_t *pgw = NULL;
|
||||
|
||||
pool_alloc_node(&sgw_pgw_pool, &sgw);
|
||||
d_assert(sgw, return NULL, "Null param");
|
||||
pool_alloc_node(&sgw_pgw_pool, &pgw);
|
||||
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(&sgw->remote_list);
|
||||
list_init(&pgw->local_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);
|
||||
pool_free_node(&sgw_pgw_pool, sgw);
|
||||
list_remove(&self.pgw_list, pgw);
|
||||
pool_free_node(&sgw_pgw_pool, pgw);
|
||||
|
||||
return CORE_OK;
|
||||
}
|
||||
|
||||
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();
|
||||
while (sgw)
|
||||
pgw = sgw_pgw_first();
|
||||
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;
|
||||
}
|
||||
|
||||
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();
|
||||
while (sgw)
|
||||
pgw = sgw_pgw_first();
|
||||
while (pgw)
|
||||
{
|
||||
if (GTP_COMPARE_NODE(sgw, gnode))
|
||||
if (pgw->addr == addr && pgw->port == port)
|
||||
break;
|
||||
|
||||
sgw = sgw_pgw_next(sgw);
|
||||
pgw = sgw_pgw_next(pgw);
|
||||
}
|
||||
|
||||
return sgw;
|
||||
return pgw;
|
||||
}
|
||||
|
||||
sgw_pgw_t* sgw_pgw_first()
|
||||
|
@ -586,9 +454,9 @@ sgw_pgw_t* sgw_pgw_first()
|
|||
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(
|
||||
|
|
|
@ -25,12 +25,10 @@ typedef struct _sgw_context_t {
|
|||
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 s1u_addr; /* SGW S1-U local address */
|
||||
c_uint32_t s1u_port; /* SGW S1-U local port */
|
||||
|
@ -85,6 +83,8 @@ typedef struct _sgw_sess_t {
|
|||
list_t bearer_list;
|
||||
|
||||
/* Related Context */
|
||||
sgw_mme_t *mme;
|
||||
sgw_mme_t *pgw;
|
||||
sgw_ue_t *sgw_ue;
|
||||
} 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(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(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_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(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(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_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,
|
||||
c_int8_t *apn, c_uint8_t id);
|
||||
|
|
|
@ -15,10 +15,12 @@ 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;
|
||||
c_uint32_t addr;
|
||||
c_uint16_t port;
|
||||
event_e event = (event_e)data;
|
||||
|
||||
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);
|
||||
if (pkbuf == NULL)
|
||||
|
@ -29,23 +31,42 @@ static int _gtpv2_c_recv_cb(net_sock_t *sock, void *data)
|
|||
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");
|
||||
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");
|
||||
event_set(&e, SGW_EVT_S5C_MESSAGE);
|
||||
|
||||
event_set_param1(&e, (c_uintptr_t)pgw);
|
||||
}
|
||||
else
|
||||
d_assert(0, pkbuf_free(pkbuf); return -1, "Unknown GTP-Node");
|
||||
|
||||
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);
|
||||
if (rv != CORE_OK)
|
||||
{
|
||||
|
@ -243,25 +264,23 @@ status_t sgw_gtp_open()
|
|||
status_t rv;
|
||||
|
||||
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)
|
||||
{
|
||||
d_error("Can't establish S11 Path for SGW");
|
||||
return rv;
|
||||
}
|
||||
|
||||
sgw_self()->s11_node.sock = sgw_self()->s11_sock;
|
||||
|
||||
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)
|
||||
{
|
||||
d_error("Can't establish S5-C Path for SGW");
|
||||
return rv;
|
||||
}
|
||||
|
||||
sgw_self()->s5c_node.sock = sgw_self()->s5c_sock;
|
||||
|
||||
rv = gtp_listen(&sgw_self()->s5u_sock, _gtpv1_s5u_recv_cb,
|
||||
sgw_self()->s5u_addr, sgw_self()->s5u_port, NULL);
|
||||
if (rv != CORE_OK)
|
||||
|
|
|
@ -17,6 +17,10 @@ void sgw_handle_create_session_request(gtp_xact_t *s11_xact,
|
|||
gtp_create_session_request_t *req = NULL;
|
||||
pkbuf_t *pkbuf = 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_xact_t *s5c_xact = NULL;
|
||||
|
@ -49,6 +53,11 @@ void sgw_handle_create_session_request(gtp_xact_t *s11_xact,
|
|||
d_error("No APN");
|
||||
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,
|
||||
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;
|
||||
|
||||
/* 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;
|
||||
|
||||
/* 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);
|
||||
d_assert(rv == CORE_OK, return, "gtp build failed");
|
||||
|
||||
s5c_xact = gtp_xact_local_create(
|
||||
&sgw_self()->s5c_node, >p_message->h, pkbuf);
|
||||
s5c_xact = gtp_xact_local_create(sess->pgw, >p_message->h, pkbuf);
|
||||
d_assert(s5c_xact, return, "Null param");
|
||||
|
||||
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);
|
||||
d_assert(rv == CORE_OK, return, "gtp build failed");
|
||||
|
||||
s5c_xact = gtp_xact_local_create(
|
||||
&sgw_self()->s5c_node, >p_message->h, pkbuf);
|
||||
s5c_xact = gtp_xact_local_create(sess->pgw, >p_message->h, pkbuf);
|
||||
d_assert(s5c_xact, return, "Null param");
|
||||
|
||||
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, >p_message);
|
||||
d_assert(rv == CORE_OK, return, "gtp build failed");
|
||||
|
||||
xact = gtp_xact_local_create(
|
||||
&sgw_self()->s11_node, >p_message.h, pkbuf);
|
||||
xact = gtp_xact_local_create(sess->mme, >p_message.h, pkbuf);
|
||||
d_assert(xact, return, "Null param");
|
||||
|
||||
rv = gtp_xact_commit(xact);
|
||||
|
|
Loading…
Reference in New Issue