mirror of
https://github.com/open5gs/open5gs.git
synced 2025-11-03 05:23:38 +00:00
GTP Peer Node finding method is changed.
Before : received IP address from UDP socket After : Based on TEID. Initially, finding from Sender F-TEID
This commit is contained in:
@@ -660,18 +660,14 @@ out:
|
||||
return CORE_ERROR;
|
||||
}
|
||||
|
||||
status_t gtp_xact_receive(gtp_node_t *gnode, pkbuf_t *pkbuf,
|
||||
gtp_xact_t **xact, gtp_message_t *message)
|
||||
status_t gtp_xact_receive(
|
||||
gtp_node_t *gnode, gtp_header_t *h, gtp_xact_t **xact)
|
||||
{
|
||||
char buf[INET_ADDRSTRLEN];
|
||||
status_t rv;
|
||||
gtp_xact_t *new = NULL;
|
||||
gtp_header_t *h = NULL;
|
||||
|
||||
d_assert(gnode, return CORE_ERROR, "Null param");
|
||||
d_assert(pkbuf, return CORE_ERROR, "Null param");
|
||||
d_assert(pkbuf->payload, return CORE_ERROR, "Null param");
|
||||
h = pkbuf->payload;
|
||||
d_assert(h, return CORE_ERROR, "Null param");
|
||||
|
||||
new = gtp_xact_find_by_xid(gnode, h->type, GTP_SQN_TO_XID(h->sqn));
|
||||
@@ -687,14 +683,9 @@ status_t gtp_xact_receive(gtp_node_t *gnode, pkbuf_t *pkbuf,
|
||||
rv = gtp_xact_update_rx(new, h->type);
|
||||
if (rv != CORE_OK)
|
||||
{
|
||||
pkbuf_free(pkbuf);
|
||||
return rv;
|
||||
}
|
||||
|
||||
rv = gtp_parse_msg(message, pkbuf);
|
||||
d_assert(rv == CORE_OK,
|
||||
pkbuf_free(pkbuf); return CORE_ERROR, "parse error");
|
||||
|
||||
*xact = new;
|
||||
return CORE_OK;
|
||||
}
|
||||
|
||||
@@ -74,8 +74,7 @@ CORE_DECLARE(status_t) gtp_xact_commit(gtp_xact_t *xact);
|
||||
CORE_DECLARE(status_t) gtp_xact_timeout(index_t index, c_uintptr_t event);
|
||||
|
||||
CORE_DECLARE(status_t) gtp_xact_receive(
|
||||
gtp_node_t *gnode, pkbuf_t *pkbuf,
|
||||
gtp_xact_t **xact, gtp_message_t *gtp_message);
|
||||
gtp_node_t *gnode, gtp_header_t *h, gtp_xact_t **xact);
|
||||
|
||||
CORE_DECLARE(gtp_xact_t *) gtp_xact_find(index_t index);
|
||||
CORE_DECLARE(gtp_xact_t *)gtp_xact_find_by_xid(
|
||||
|
||||
@@ -35,9 +35,7 @@ static int _gtpv2_c_recv_cb(net_sock_t *sock, void *data)
|
||||
d_trace_hex(10, pkbuf->payload, pkbuf->len);
|
||||
|
||||
event_set(&e, MME_EVT_S11_MESSAGE);
|
||||
event_set_param1(&e, (c_uintptr_t)addr);
|
||||
event_set_param2(&e, (c_uintptr_t)port);
|
||||
event_set_param3(&e, (c_uintptr_t)pkbuf);
|
||||
event_set_param1(&e, (c_uintptr_t)pkbuf);
|
||||
rv = mme_event_send(&e);
|
||||
if (rv != CORE_OK)
|
||||
{
|
||||
|
||||
@@ -344,28 +344,26 @@ void mme_state_operational(fsm_t *s, event_t *e)
|
||||
case MME_EVT_S11_MESSAGE:
|
||||
{
|
||||
status_t rv;
|
||||
gtp_node_t *gnode = NULL;
|
||||
c_uint32_t addr = (c_uint32_t)event_get_param1(e);
|
||||
c_uint16_t port = (c_uint16_t)event_get_param2(e);
|
||||
pkbuf_t *pkbuf = (pkbuf_t *)event_get_param3(e);
|
||||
pkbuf_t *pkbuf = (pkbuf_t *)event_get_param1(e);
|
||||
gtp_xact_t *xact = NULL;
|
||||
gtp_message_t message;
|
||||
mme_ue_t *mme_ue = NULL;
|
||||
|
||||
d_assert(pkbuf, break, "Null param");
|
||||
gnode = mme_sgw_find(addr, port);
|
||||
d_assert(gnode, pkbuf_free(pkbuf); break, "Null param");
|
||||
|
||||
rv = gtp_xact_receive(gnode, pkbuf, &xact, &message);
|
||||
if (rv != CORE_OK)
|
||||
break;
|
||||
|
||||
d_assert(xact, return, "Null param");
|
||||
rv = gtp_parse_msg(&message, pkbuf);
|
||||
d_assert(rv == CORE_OK, pkbuf_free(pkbuf); break, "parse error");
|
||||
|
||||
mme_ue = mme_ue_find_by_teid(message.h.teid);
|
||||
d_assert(mme_ue, pkbuf_free(pkbuf); break,
|
||||
"No UE Context(TEID:%d)", message.h.teid);
|
||||
|
||||
|
||||
rv = gtp_xact_receive(mme_ue->sgw, &message.h, &xact);
|
||||
if (rv != CORE_OK)
|
||||
{
|
||||
pkbuf_free(pkbuf);
|
||||
break;
|
||||
}
|
||||
|
||||
switch(message.h.type)
|
||||
{
|
||||
case GTP_CREATE_SESSION_RESPONSE_TYPE:
|
||||
|
||||
@@ -469,11 +469,14 @@ static void *sess_hash_keygen(c_uint8_t *out, int *out_len,
|
||||
return out;
|
||||
}
|
||||
|
||||
pgw_sess_t *pgw_sess_add(
|
||||
pgw_sess_t *pgw_sess_add(gtp_f_teid_t *sgw_s5c_teid,
|
||||
c_uint8_t *imsi, int imsi_len, c_int8_t *apn, c_uint8_t ebi)
|
||||
{
|
||||
pgw_sess_t *sess = NULL;
|
||||
pgw_bearer_t *bearer = NULL;
|
||||
pgw_sgw_t *sgw = NULL;
|
||||
c_uint32_t addr = 0;
|
||||
c_uint16_t port = 0;
|
||||
|
||||
index_alloc(&pgw_sess_pool, &sess);
|
||||
d_assert(sess, return NULL, "Null param");
|
||||
@@ -486,6 +489,22 @@ pgw_sess_t *pgw_sess_add(
|
||||
memcpy(sess->imsi, imsi, sess->imsi_len);
|
||||
core_buffer_to_bcd(sess->imsi, sess->imsi_len, sess->imsi_bcd);
|
||||
|
||||
addr = sgw_s5c_teid->ipv4_addr;
|
||||
port = GTPV2_C_UDP_PORT;
|
||||
|
||||
sgw = pgw_sgw_find(addr, port);
|
||||
if (!sgw)
|
||||
{
|
||||
sgw = pgw_sgw_add();
|
||||
d_assert(sgw, return NULL, "Can't add SGW-GTP node");
|
||||
|
||||
sgw->addr = addr;
|
||||
sgw->port = port;
|
||||
sgw->sock = pgw_self()->gtpc_sock;
|
||||
}
|
||||
/* Setup GTP Node between PGW and SGW */
|
||||
CONNECT_SGW_GTP_NODE(sess, sgw);
|
||||
|
||||
/* Set APN */
|
||||
core_cpystrn(sess->pdn.apn, apn, MAX_APN_LEN+1);
|
||||
|
||||
@@ -570,23 +589,41 @@ pgw_sess_t *pgw_sess_find_or_add_by_message(gtp_message_t *gtp_message)
|
||||
gtp_create_session_request_t *req = >p_message->create_session_request;
|
||||
c_int8_t apn[MAX_APN_LEN];
|
||||
|
||||
if (req->sender_f_teid_for_control_plane.presence == 0)
|
||||
if (req->imsi.presence == 0)
|
||||
{
|
||||
d_error("No IMSI");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (req->sender_f_teid_for_control_plane.presence == 0)
|
||||
{
|
||||
d_error("No Sender F-TEID");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (req->access_point_name.presence == 0)
|
||||
{
|
||||
d_error("No APN");
|
||||
return NULL;
|
||||
}
|
||||
if (req->bearer_contexts_to_be_created.presence == 0)
|
||||
{
|
||||
d_error("No Bearer");
|
||||
return NULL;
|
||||
}
|
||||
if (req->bearer_contexts_to_be_created.eps_bearer_id.presence == 0)
|
||||
{
|
||||
d_error("No EPS Bearer ID");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
apn_parse(apn, req->access_point_name.data, req->access_point_name.len);
|
||||
sess = pgw_sess_find_by_imsi_apn(req->imsi.data, req->imsi.len, apn);
|
||||
if (!sess)
|
||||
{
|
||||
sess = pgw_sess_add(req->imsi.data, req->imsi.len, apn,
|
||||
sess = pgw_sess_add(
|
||||
req->sender_f_teid_for_control_plane.data,
|
||||
req->imsi.data, req->imsi.len, apn,
|
||||
req->bearer_contexts_to_be_created.eps_bearer_id.u8);
|
||||
d_assert(sess, return NULL, "No Session Context");
|
||||
}
|
||||
|
||||
@@ -92,11 +92,11 @@ typedef struct _pgw_sess_t {
|
||||
list_t bearer_list;
|
||||
|
||||
/* Related Context */
|
||||
#define CONNECT_SGW_GTP_NODE(__sESS, __xACT) \
|
||||
#define CONNECT_SGW_GTP_NODE(__sESS, __gNODE) \
|
||||
do { \
|
||||
d_assert((__sESS), return, "Null param"); \
|
||||
d_assert((__xACT), return, "Null param"); \
|
||||
(__sESS)->sgw = (__xACT)->gnode; \
|
||||
d_assert((__sESS), return NULL, "Null param"); \
|
||||
d_assert((__gNODE), return NULL, "Null param"); \
|
||||
(__sESS)->sgw = (__gNODE); \
|
||||
} while(0)
|
||||
pgw_sgw_t *sgw;
|
||||
} pgw_sess_t;
|
||||
@@ -175,8 +175,8 @@ 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);
|
||||
|
||||
CORE_DECLARE(pgw_sess_t*) pgw_sess_add(
|
||||
c_uint8_t *imsi, int imsi_len, c_int8_t *apn, c_uint8_t id);
|
||||
CORE_DECLARE(pgw_sess_t*) pgw_sess_add(gtp_f_teid_t *sgw_s5c_teid,
|
||||
c_uint8_t *imsi, int imsi_len, c_int8_t *apn, c_uint8_t ebi);
|
||||
CORE_DECLARE(status_t ) pgw_sess_remove(pgw_sess_t *sess);
|
||||
CORE_DECLARE(status_t ) pgw_sess_remove_all();
|
||||
CORE_DECLARE(pgw_sess_t*) pgw_sess_find(index_t index);
|
||||
|
||||
@@ -86,9 +86,6 @@ static int _gtpv2_c_recv_cb(net_sock_t *sock, void *data)
|
||||
event_t e;
|
||||
status_t rv;
|
||||
pkbuf_t *pkbuf = NULL;
|
||||
c_uint32_t addr;
|
||||
c_uint16_t port;
|
||||
pgw_sgw_t *sgw = NULL;
|
||||
|
||||
d_assert(sock, return -1, "Null param");
|
||||
|
||||
@@ -104,23 +101,8 @@ 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)sgw);
|
||||
event_set_param2(&e, (c_uintptr_t)pkbuf);
|
||||
event_set_param1(&e, (c_uintptr_t)pkbuf);
|
||||
rv = pgw_event_send(&e);
|
||||
if (rv != CORE_OK)
|
||||
{
|
||||
|
||||
@@ -23,9 +23,6 @@ void pgw_gx_handle_cca_initial_request(
|
||||
d_assert(cca_message, return, "Null param");
|
||||
d_assert(req, return, "Null param");
|
||||
|
||||
/* Setup GTP Node between PGW and SGW */
|
||||
CONNECT_SGW_GTP_NODE(sess, xact);
|
||||
|
||||
/* Send Create Session Request with Creating Default Bearer */
|
||||
memset(&h, 0, sizeof(gtp_header_t));
|
||||
h.type = GTP_CREATE_SESSION_RESPONSE_TYPE;
|
||||
|
||||
@@ -63,8 +63,7 @@ void pgw_state_operational(fsm_t *s, event_t *e)
|
||||
case PGW_EVT_S5C_MESSAGE:
|
||||
{
|
||||
status_t rv;
|
||||
gtp_node_t *gnode = (gtp_node_t *)event_get_param1(e);
|
||||
pkbuf_t *recvbuf = (pkbuf_t *)event_get_param2(e);
|
||||
pkbuf_t *recvbuf = (pkbuf_t *)event_get_param1(e);
|
||||
pkbuf_t *copybuf = NULL;
|
||||
c_uint16_t copybuf_len = 0;
|
||||
gtp_xact_t *xact = NULL;
|
||||
@@ -72,7 +71,6 @@ void pgw_state_operational(fsm_t *s, event_t *e)
|
||||
pgw_sess_t *sess = NULL;
|
||||
|
||||
d_assert(recvbuf, break, "Null param");
|
||||
d_assert(gnode, pkbuf_free(recvbuf); break, "Null param");
|
||||
|
||||
copybuf_len = sizeof(gtp_message_t);
|
||||
copybuf = pkbuf_alloc(0, copybuf_len);
|
||||
@@ -80,15 +78,26 @@ void pgw_state_operational(fsm_t *s, event_t *e)
|
||||
message = copybuf->payload;
|
||||
d_assert(message, break, "Null param");
|
||||
|
||||
rv = gtp_xact_receive(gnode, recvbuf, &xact, message);
|
||||
if (rv != CORE_OK)
|
||||
break;
|
||||
rv = gtp_parse_msg(message, recvbuf);
|
||||
d_assert(rv == CORE_OK,
|
||||
pkbuf_free(recvbuf); pkbuf_free(copybuf); break,
|
||||
"parse error");
|
||||
|
||||
if (message->h.type == GTP_CREATE_SESSION_REQUEST_TYPE)
|
||||
sess = pgw_sess_find_or_add_by_message(message);
|
||||
else
|
||||
sess = pgw_sess_find_by_teid(message->h.teid);
|
||||
d_assert(sess, pkbuf_free(recvbuf); break, "No Session Context");
|
||||
d_assert(sess,
|
||||
pkbuf_free(recvbuf); pkbuf_free(copybuf); break,
|
||||
"No Session Context");
|
||||
|
||||
rv = gtp_xact_receive(sess->sgw, &message->h, &xact);
|
||||
if (rv != CORE_OK)
|
||||
{
|
||||
pkbuf_free(recvbuf);
|
||||
pkbuf_free(copybuf);
|
||||
break;
|
||||
}
|
||||
|
||||
switch(message->h.type)
|
||||
{
|
||||
@@ -97,24 +106,22 @@ void pgw_state_operational(fsm_t *s, event_t *e)
|
||||
xact, sess, &message->create_session_request);
|
||||
pgw_gx_send_ccr(xact, sess, copybuf,
|
||||
GX_CC_REQUEST_TYPE_INITIAL_REQUEST);
|
||||
goto out;
|
||||
break;
|
||||
case GTP_DELETE_SESSION_REQUEST_TYPE:
|
||||
pgw_s5c_handle_delete_session_request(
|
||||
xact, sess, &message->delete_session_request);
|
||||
pgw_gx_send_ccr(xact, sess, copybuf,
|
||||
GX_CC_REQUEST_TYPE_TERMINATION_REQUEST);
|
||||
goto out;
|
||||
|
||||
break;
|
||||
case GTP_CREATE_BEARER_RESPONSE_TYPE:
|
||||
pgw_s5c_handle_create_bearer_response(
|
||||
xact, sess, &message->create_bearer_response);
|
||||
pkbuf_free(copybuf);
|
||||
break;
|
||||
default:
|
||||
d_warn("Not implmeneted(type:%d)", message->h.type);
|
||||
break;
|
||||
}
|
||||
pkbuf_free(copybuf);
|
||||
out:
|
||||
pkbuf_free(recvbuf);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -377,11 +377,20 @@ sgw_pgw_t* sgw_pgw_next(sgw_pgw_t *pgw)
|
||||
return list_next(pgw);
|
||||
}
|
||||
|
||||
sgw_ue_t* sgw_ue_add(
|
||||
sgw_ue_t* sgw_ue_add(gtp_f_teid_t *mme_s11_teid,
|
||||
c_uint8_t *imsi, int imsi_len, c_int8_t *apn, c_uint8_t ebi)
|
||||
{
|
||||
sgw_ue_t *sgw_ue = NULL;
|
||||
sgw_sess_t *sess = NULL;
|
||||
sgw_mme_t *mme = NULL;
|
||||
c_uint32_t addr = 0;
|
||||
c_uint16_t port = 0;
|
||||
|
||||
d_assert(mme_s11_teid, return NULL, "Null param");
|
||||
d_assert(imsi, return NULL, "Null param");
|
||||
d_assert(imsi_len, return NULL, "Null param");
|
||||
d_assert(apn, return NULL, "Null param");
|
||||
d_assert(ebi, return NULL, "Null param");
|
||||
|
||||
index_alloc(&sgw_ue_pool, &sgw_ue);
|
||||
d_assert(sgw_ue, return NULL, "Null param");
|
||||
@@ -389,6 +398,21 @@ sgw_ue_t* sgw_ue_add(
|
||||
sgw_ue->sgw_s11_teid = sgw_ue->index;
|
||||
sgw_ue->sgw_s11_addr = sgw_self()->gtpc_addr;
|
||||
|
||||
addr = mme_s11_teid->ipv4_addr;
|
||||
port = GTPV2_C_UDP_PORT;
|
||||
|
||||
mme = sgw_mme_find(addr, port);
|
||||
if (!mme)
|
||||
{
|
||||
mme = sgw_mme_add();
|
||||
d_assert(mme, return NULL, "Can't add MME-GTP node");
|
||||
|
||||
mme->addr = addr;
|
||||
mme->port = port;
|
||||
mme->sock = sgw_self()->gtpc_sock;
|
||||
}
|
||||
CONNECT_MME_GTP_NODE(sgw_ue, mme);
|
||||
|
||||
/* Set IMSI */
|
||||
sgw_ue->imsi_len = imsi_len;
|
||||
memcpy(sgw_ue->imsi, imsi, sgw_ue->imsi_len);
|
||||
@@ -433,7 +457,7 @@ status_t sgw_ue_remove_all()
|
||||
return CORE_OK;
|
||||
}
|
||||
|
||||
sgw_ue_t* sgw_ue_find(index_t index)
|
||||
static sgw_ue_t* sgw_ue_find(index_t index)
|
||||
{
|
||||
d_assert(index, return NULL, "Invalid index = 0x%x", index);
|
||||
return index_find(&sgw_ue_pool, index);
|
||||
@@ -469,24 +493,42 @@ sgw_ue_t *sgw_ue_find_or_add_by_message(gtp_message_t *gtp_message)
|
||||
|
||||
gtp_create_session_request_t *req = >p_message->create_session_request;
|
||||
|
||||
if (req->sender_f_teid_for_control_plane.presence == 0)
|
||||
if (req->imsi.presence == 0)
|
||||
{
|
||||
d_error("No IMSI");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (req->sender_f_teid_for_control_plane.presence == 0)
|
||||
{
|
||||
d_error("No Sender F-TEID");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (req->access_point_name.presence == 0)
|
||||
{
|
||||
d_error("No APN");
|
||||
return NULL;
|
||||
}
|
||||
if (req->bearer_contexts_to_be_created.presence == 0)
|
||||
{
|
||||
d_error("No Bearer");
|
||||
return NULL;
|
||||
}
|
||||
if (req->bearer_contexts_to_be_created.eps_bearer_id.presence == 0)
|
||||
{
|
||||
d_error("No EPS Bearer ID");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
sgw_ue = sgw_ue_find_by_imsi(req->imsi.data, req->imsi.len);
|
||||
if (!sgw_ue)
|
||||
{
|
||||
c_int8_t apn[MAX_APN_LEN];
|
||||
apn_parse(apn, req->access_point_name.data, req->access_point_name.len);
|
||||
sgw_ue = sgw_ue_add(req->imsi.data, req->imsi.len, apn,
|
||||
sgw_ue = sgw_ue_add(
|
||||
req->sender_f_teid_for_control_plane.data,
|
||||
req->imsi.data, req->imsi.len, apn,
|
||||
req->bearer_contexts_to_be_created.eps_bearer_id.u8);
|
||||
d_assert(sgw_ue, return NULL, "No UE Context");
|
||||
}
|
||||
@@ -523,7 +565,7 @@ sgw_sess_t *sgw_sess_add(
|
||||
index_alloc(&sgw_sess_pool, &sess);
|
||||
d_assert(sess, return NULL, "Null param");
|
||||
|
||||
sess->sgw_s5c_teid = sess->index;
|
||||
sess->sgw_s5c_teid = SGW_S5C_INDEX_TO_TEID(sess->index);
|
||||
sess->sgw_s5c_addr = sgw_self()->gtpc_addr;
|
||||
|
||||
/* Set APN */
|
||||
@@ -574,7 +616,7 @@ status_t sgw_sess_remove_all(sgw_ue_t *sgw_ue)
|
||||
return CORE_OK;
|
||||
}
|
||||
|
||||
sgw_sess_t* sgw_sess_find(index_t index)
|
||||
static sgw_sess_t* sgw_sess_find(index_t index)
|
||||
{
|
||||
d_assert(index, return NULL, "Invalid Index");
|
||||
return index_find(&sgw_sess_pool, index);
|
||||
@@ -582,7 +624,7 @@ sgw_sess_t* sgw_sess_find(index_t index)
|
||||
|
||||
sgw_sess_t* sgw_sess_find_by_teid(c_uint32_t teid)
|
||||
{
|
||||
return sgw_sess_find(teid);
|
||||
return sgw_sess_find(SGW_S5C_TEID_TO_INDEX(teid));
|
||||
}
|
||||
|
||||
sgw_sess_t* sgw_sess_find_by_apn(sgw_ue_t *sgw_ue, c_int8_t *apn)
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#include "core_hash.h"
|
||||
|
||||
#include "gtp_xact.h"
|
||||
#include "gtp_types.h"
|
||||
#include "types.h"
|
||||
|
||||
#include "sgw_sm.h"
|
||||
@@ -65,11 +66,11 @@ typedef struct _sgw_ue_t {
|
||||
|
||||
list_t sess_list;
|
||||
|
||||
#define CONNECT_MME_GTP_NODE(__sGW, __xACT) \
|
||||
#define CONNECT_MME_GTP_NODE(__sGW, __gNODE) \
|
||||
do { \
|
||||
d_assert((__sGW), return, "Null param"); \
|
||||
d_assert((__xACT), return, "Null param"); \
|
||||
(__sGW)->mme = (__xACT)->gnode; \
|
||||
d_assert((__sGW), return NULL, "Null param"); \
|
||||
d_assert((__gNODE), return NULL, "Null param"); \
|
||||
(__sGW)->mme = (__gNODE); \
|
||||
} while(0)
|
||||
sgw_mme_t *mme;
|
||||
} sgw_ue_t;
|
||||
@@ -79,7 +80,12 @@ typedef struct _sgw_sess_t {
|
||||
index_t index; /* An index of this node */
|
||||
|
||||
/* IMPORTANT!
|
||||
* SGW-S5C-F-TEID is same with an index */
|
||||
* SGW-S5C-TEID = INDEX | 0x80000000
|
||||
* INDEX = SGW-S5C-TEID & ~0x80000000
|
||||
*/
|
||||
#define SGW_S5C_TEID(__tEID) (__tEID & 0x80000000)
|
||||
#define SGW_S5C_TEID_TO_INDEX(__iNDEX) (__iNDEX & ~0x80000000)
|
||||
#define SGW_S5C_INDEX_TO_TEID(__iNDEX) (__iNDEX | 0x80000000)
|
||||
c_uint32_t sgw_s5c_teid;
|
||||
c_uint32_t sgw_s5c_addr;
|
||||
c_uint32_t pgw_s5c_teid; /* PGW-S5C-F-TEID */
|
||||
@@ -97,7 +103,7 @@ typedef struct _sgw_sess_t {
|
||||
d_assert((__gNODE), return, "Null param"); \
|
||||
(__sESS)->pgw = __gNODE; \
|
||||
} while(0)
|
||||
sgw_mme_t *pgw;
|
||||
sgw_pgw_t *pgw;
|
||||
sgw_ue_t *sgw_ue;
|
||||
} sgw_sess_t;
|
||||
|
||||
@@ -157,12 +163,11 @@ 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 *pgw);
|
||||
|
||||
CORE_DECLARE(sgw_ue_t*) sgw_ue_add(c_uint8_t *imsi, int imsi_len,
|
||||
c_int8_t *apn, c_uint8_t id);
|
||||
CORE_DECLARE(sgw_ue_t*) sgw_ue_add(gtp_f_teid_t *mme_s11_teid,
|
||||
c_uint8_t *imsi, int imsi_len, c_int8_t *apn, c_uint8_t ebi);
|
||||
CORE_DECLARE(status_t) sgw_ue_remove(sgw_ue_t *sgw_ue);
|
||||
CORE_DECLARE(status_t) sgw_ue_remove_all();
|
||||
|
||||
CORE_DECLARE(sgw_ue_t*) sgw_ue_find(index_t index);
|
||||
CORE_DECLARE(sgw_ue_t*) sgw_ue_find_by_imsi(c_uint8_t *imsi, int imsi_len);
|
||||
CORE_DECLARE(sgw_ue_t*) sgw_ue_find_by_imsi_bcd(c_int8_t *imsi_bcd);
|
||||
CORE_DECLARE(sgw_ue_t*) sgw_ue_find_by_teid(c_uint32_t teid);
|
||||
@@ -177,7 +182,6 @@ CORE_DECLARE(sgw_sess_t*) sgw_sess_add(sgw_ue_t *sgw_ue,
|
||||
c_int8_t *apn, c_uint8_t ebi);
|
||||
CORE_DECLARE(status_t ) sgw_sess_remove(sgw_sess_t *sess);
|
||||
CORE_DECLARE(status_t ) sgw_sess_remove_all(sgw_ue_t *sgw_ue);
|
||||
CORE_DECLARE(sgw_sess_t*) sgw_sess_find(index_t index);
|
||||
CORE_DECLARE(sgw_sess_t*) sgw_sess_find_by_apn(
|
||||
sgw_ue_t *sgw_ue, c_int8_t *apn);
|
||||
CORE_DECLARE(sgw_sess_t*) sgw_sess_find_by_ebi(
|
||||
|
||||
@@ -16,10 +16,8 @@ static int _gtpv2_c_recv_cb(net_sock_t *sock, void *data)
|
||||
event_t e;
|
||||
status_t rv;
|
||||
gtp_header_t *gtp_h = NULL;
|
||||
c_uint32_t teid = 0;
|
||||
pkbuf_t *pkbuf = NULL;
|
||||
c_uint32_t addr = 0;
|
||||
c_uint16_t port = 0;
|
||||
sgw_mme_t *mme = NULL;
|
||||
|
||||
d_assert(sock, return -1, "Null param");
|
||||
|
||||
@@ -34,39 +32,20 @@ static int _gtpv2_c_recv_cb(net_sock_t *sock, void *data)
|
||||
|
||||
gtp_h = (gtp_header_t *)pkbuf->payload;
|
||||
d_assert(gtp_h, return -1, "Null param");
|
||||
d_assert(gtp_h->teid_presence, return -1,);
|
||||
teid = ntohl(gtp_h->teid);
|
||||
|
||||
addr = sock->remote.sin_addr.s_addr;
|
||||
port = ntohs(sock->remote.sin_port);
|
||||
|
||||
mme = sgw_mme_find(addr, port);
|
||||
if (!mme && gtp_h->teid == 0)
|
||||
if (SGW_S5C_TEID(teid))
|
||||
{
|
||||
mme = sgw_mme_add();
|
||||
d_assert(mme, return -1, "Can't add MME-GTP node");
|
||||
|
||||
mme->addr = addr;
|
||||
mme->port = port;
|
||||
mme->sock = sock;
|
||||
}
|
||||
|
||||
if (mme)
|
||||
{
|
||||
d_trace(10, "S11 PDU received from MME\n");
|
||||
|
||||
event_set(&e, SGW_EVT_S11_MESSAGE);
|
||||
event_set_param1(&e, (c_uintptr_t)mme);
|
||||
event_set_param2(&e, (c_uintptr_t)pkbuf);
|
||||
|
||||
d_trace(10, "S5C PDU received from PGW\n");
|
||||
event_set(&e, SGW_EVT_S5C_MESSAGE);
|
||||
}
|
||||
else
|
||||
{
|
||||
d_trace(10, "S5C PDU received from PGW\n");
|
||||
|
||||
event_set(&e, SGW_EVT_S5C_MESSAGE);
|
||||
event_set_param1(&e, (c_uintptr_t)addr);
|
||||
event_set_param2(&e, (c_uintptr_t)port);
|
||||
event_set_param3(&e, (c_uintptr_t)pkbuf);
|
||||
d_trace(10, "S11 PDU received from MME\n");
|
||||
event_set(&e, SGW_EVT_S11_MESSAGE);
|
||||
}
|
||||
event_set_param1(&e, (c_uintptr_t)pkbuf);
|
||||
|
||||
d_trace_hex(10, pkbuf->payload, pkbuf->len);
|
||||
|
||||
@@ -241,222 +220,6 @@ static int _gtpv1_u_recv_cb(net_sock_t *sock, void *data)
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
#if 0
|
||||
static int _gtpv1_s5u_recv_cb(net_sock_t *sock, void *data)
|
||||
{
|
||||
pkbuf_t *pkbuf = NULL;
|
||||
gtp_node_t gnode;
|
||||
gtp_header_t *gtp_h = NULL;
|
||||
sgw_bearer_t *bearer = NULL;
|
||||
c_uint32_t teid;
|
||||
|
||||
d_assert(sock, return -1, "Null param");
|
||||
|
||||
pkbuf = gtp_read(sock);
|
||||
if (pkbuf == NULL)
|
||||
{
|
||||
if (sock->sndrcv_errno == EAGAIN)
|
||||
return 0;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
d_trace(50, "S5-U PDU received from PGW\n");
|
||||
d_trace_hex(50, pkbuf->payload, pkbuf->len);
|
||||
|
||||
gtp_h = (gtp_header_t *)pkbuf->payload;
|
||||
if (gtp_h->type == GTPU_MSGTYPE_ECHO_REQ)
|
||||
{
|
||||
pkbuf_t *echo_rsp;
|
||||
|
||||
d_trace(3, "Received echo-req");
|
||||
echo_rsp = gtp_handle_echo_req(pkbuf);
|
||||
if (echo_rsp)
|
||||
{
|
||||
/* Echo reply */
|
||||
d_trace(3, "Send echo-rsp to peer(PGW) ");
|
||||
|
||||
gnode.addr = sock->remote.sin_addr.s_addr;
|
||||
gnode.port = GTPV1_U_UDP_PORT;
|
||||
gnode.sock = sgw_self()->s5u_sock;
|
||||
|
||||
gtp_send(&gnode, echo_rsp);
|
||||
pkbuf_free(echo_rsp);
|
||||
}
|
||||
}
|
||||
else if (gtp_h->type == GTPU_MSGTYPE_GPDU)
|
||||
{
|
||||
teid = ntohl(gtp_h->teid);
|
||||
|
||||
d_trace(50, "Recv GPDU (teid = 0x%x)",teid);
|
||||
|
||||
bearer = sgw_bearer_find_by_sgw_s5u_teid(teid);
|
||||
if (bearer)
|
||||
{
|
||||
if (bearer->enb_s1u_teid)
|
||||
{
|
||||
/* Convert Teid and send to enodeB via s1u */
|
||||
gtp_h->teid = htonl(bearer->enb_s1u_teid);
|
||||
|
||||
gnode.addr = bearer->enb_s1u_addr;
|
||||
gnode.port = GTPV1_U_UDP_PORT;
|
||||
gnode.sock = sgw_self()->s1u_sock;
|
||||
|
||||
/* If there is buffered packet, send it first */
|
||||
if (bearer->num_buffered_pkt)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < bearer->num_buffered_pkt; i++)
|
||||
{
|
||||
gtp_h =
|
||||
(gtp_header_t *)bearer->buffered_pkts[i]->payload;
|
||||
gtp_h->teid = htonl(bearer->enb_s1u_teid);
|
||||
|
||||
gtp_send(&gnode, bearer->buffered_pkts[i]);
|
||||
pkbuf_free(bearer->buffered_pkts[i]);
|
||||
}
|
||||
bearer->num_buffered_pkt = 0;
|
||||
}
|
||||
|
||||
gtp_send(&gnode, pkbuf);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* S1U path is deactivated.
|
||||
* Send downlink_data_notification to MME.
|
||||
*
|
||||
*/
|
||||
sgw_ue_t *sgw_ue = NULL;
|
||||
|
||||
d_assert(bearer->sess, pkbuf_free(pkbuf); return 0,
|
||||
"Session is NULL");
|
||||
d_assert(bearer->sess->sgw_ue, pkbuf_free(pkbuf); return 0,
|
||||
"SGW_UE is NULL");
|
||||
|
||||
sgw_ue = bearer->sess->sgw_ue;
|
||||
|
||||
if ((SGW_GET_UE_STATE(sgw_ue) & SGW_S1U_INACTIVE))
|
||||
{
|
||||
if ( !(SGW_GET_UE_STATE(sgw_ue) & SGW_DL_NOTI_SENT))
|
||||
{
|
||||
event_t e;
|
||||
status_t rv;
|
||||
|
||||
event_set(&e, SGW_EVT_LO_DLDATA_NOTI);
|
||||
event_set_param1(&e, (c_uintptr_t)bearer->index);
|
||||
rv = sgw_event_send(&e);
|
||||
if (rv != CORE_OK)
|
||||
{
|
||||
d_error("sgw_event_send error");
|
||||
pkbuf_free(pkbuf);
|
||||
return -1;
|
||||
}
|
||||
|
||||
SGW_SET_UE_STATE(sgw_ue, SGW_DL_NOTI_SENT);
|
||||
}
|
||||
|
||||
/* Buffer the packet */
|
||||
if (bearer->num_buffered_pkt < MAX_NUM_BUFFER_PKT)
|
||||
{
|
||||
bearer->buffered_pkts[bearer->num_buffered_pkt++] =
|
||||
pkbuf;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* UE is S1U_ACTIVE state but there is no s1u teid */
|
||||
d_warn("UE is ACITVE but there is no matched "
|
||||
"s1u_teid(tedid = 0x%x)",teid);
|
||||
|
||||
/* Just drop it */
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pkbuf_free(pkbuf);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _gtpv1_s1u_recv_cb(net_sock_t *sock, void *data)
|
||||
{
|
||||
pkbuf_t *pkbuf = NULL;
|
||||
gtp_node_t gnode;
|
||||
gtp_header_t *gtp_h = NULL;
|
||||
sgw_tunnel_t *tunnel = NULL;
|
||||
c_uint32_t teid;
|
||||
|
||||
d_assert(sock, return -1, "Null param");
|
||||
|
||||
pkbuf = gtp_read(sock);
|
||||
if (pkbuf == NULL)
|
||||
{
|
||||
if (sock->sndrcv_errno == EAGAIN)
|
||||
return 0;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
d_trace(50, "S1-U PDU received from ENB\n");
|
||||
d_trace_hex(50, pkbuf->payload, pkbuf->len);
|
||||
|
||||
gtp_h = (gtp_header_t *)pkbuf->payload;
|
||||
if (gtp_h->type == GTPU_MSGTYPE_ECHO_REQ)
|
||||
{
|
||||
pkbuf_t *echo_rsp;
|
||||
|
||||
d_trace(3, "Received echo-req\n");
|
||||
echo_rsp = gtp_handle_echo_req(pkbuf);
|
||||
if (echo_rsp)
|
||||
{
|
||||
/* Echo reply */
|
||||
d_trace(3, "Send echo-rsp to peer(ENB)\n");
|
||||
|
||||
gnode.addr = sock->remote.sin_addr.s_addr;
|
||||
gnode.port = GTPV1_U_UDP_PORT;
|
||||
gnode.sock = sgw_self()->s1u_sock;
|
||||
|
||||
gtp_send(&gnode, echo_rsp);
|
||||
pkbuf_free(echo_rsp);
|
||||
}
|
||||
}
|
||||
else if (gtp_h->type == GTPU_MSGTYPE_GPDU ||
|
||||
gtp_h->type == GTPU_MSGTYPE_END_MARKER)
|
||||
{
|
||||
teid = ntohl(gtp_h->teid);
|
||||
d_trace(50, "Recv GPDU (teid = 0x%x) from ENB\n",teid);
|
||||
|
||||
tunnel = sgw_tunnel_find_by_teid(teid);
|
||||
if (tunnel)
|
||||
{
|
||||
gtp_h->teid = htonl(tunnel->remote_teid);
|
||||
|
||||
gnode.addr = tunnel->remote_addr;
|
||||
gnode.port = GTPV1_U_UDP_PORT;
|
||||
if (tunnel->interface_type == GTP_F_TEID_S1_U_SGW_GTP_U)
|
||||
gnode.sock = sgw_self()->s5u_sock;
|
||||
else if (tunnel->interface_type ==
|
||||
GTP_F_TEID_SGW_GTP_U_FOR_DL_DATA_FORWARDING)
|
||||
gnode.sock = sgw_self()->s1u_sock;
|
||||
else if (tunnel->interface_type ==
|
||||
GTP_F_TEID_SGW_GTP_U_FOR_UL_DATA_FORWARDING)
|
||||
gnode.sock = sgw_self()->s1u_sock;
|
||||
else
|
||||
d_assert(0, return -1, "Invalid type(%d)",
|
||||
tunnel->interface_type);
|
||||
|
||||
gtp_send(&gnode, pkbuf);
|
||||
}
|
||||
}
|
||||
|
||||
pkbuf_free(pkbuf);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
status_t sgw_gtp_open()
|
||||
{
|
||||
status_t rv;
|
||||
|
||||
@@ -37,11 +37,6 @@ void sgw_s11_handle_create_session_request(gtp_xact_t *s11_xact,
|
||||
|
||||
req = >p_message->create_session_request;
|
||||
|
||||
if (req->sender_f_teid_for_control_plane.presence == 0)
|
||||
{
|
||||
d_error("No TEID");
|
||||
return;
|
||||
}
|
||||
if (req->bearer_contexts_to_be_created.presence == 0)
|
||||
{
|
||||
d_error("No Bearer");
|
||||
@@ -77,6 +72,7 @@ void sgw_s11_handle_create_session_request(gtp_xact_t *s11_xact,
|
||||
sess = sgw_sess_add(sgw_ue, apn,
|
||||
req->bearer_contexts_to_be_created.eps_bearer_id.u8);
|
||||
}
|
||||
|
||||
d_assert(sess, return, "Null param");
|
||||
bearer = sgw_default_bearer_in_sess(sess);
|
||||
d_assert(bearer, return, "Null param");
|
||||
@@ -117,7 +113,6 @@ void sgw_s11_handle_create_session_request(gtp_xact_t *s11_xact,
|
||||
}
|
||||
|
||||
/* Setup GTP Node */
|
||||
CONNECT_MME_GTP_NODE(sgw_ue, s11_xact);
|
||||
CONNECT_PGW_GTP_NODE(sess, pgw);
|
||||
|
||||
req->pgw_s5_s8_address_for_control_plane_or_pmip.presence = 0;
|
||||
|
||||
@@ -56,18 +56,14 @@ void sgw_state_operational(fsm_t *s, event_t *e)
|
||||
case SGW_EVT_S11_MESSAGE:
|
||||
{
|
||||
status_t rv;
|
||||
gtp_node_t *gnode = (gtp_node_t *)event_get_param1(e);
|
||||
pkbuf_t *pkbuf = (pkbuf_t *)event_get_param2(e);
|
||||
pkbuf_t *pkbuf = (pkbuf_t *)event_get_param1(e);
|
||||
gtp_xact_t *xact = NULL;
|
||||
gtp_message_t message;
|
||||
sgw_ue_t *sgw_ue = NULL;
|
||||
|
||||
d_assert(pkbuf, break, "Null param");
|
||||
d_assert(gnode, pkbuf_free(pkbuf); break, "Null param");
|
||||
|
||||
rv = gtp_xact_receive(gnode, pkbuf, &xact, &message);
|
||||
if (rv != CORE_OK)
|
||||
break;
|
||||
rv = gtp_parse_msg(&message, pkbuf);
|
||||
d_assert(rv == CORE_OK, pkbuf_free(pkbuf); break, "parse error");
|
||||
|
||||
if (message.h.type == GTP_CREATE_SESSION_REQUEST_TYPE)
|
||||
sgw_ue = sgw_ue_find_or_add_by_message(&message);
|
||||
@@ -75,6 +71,13 @@ void sgw_state_operational(fsm_t *s, event_t *e)
|
||||
sgw_ue = sgw_ue_find_by_teid(message.h.teid);
|
||||
d_assert(sgw_ue, pkbuf_free(pkbuf); break, "No Session Context");
|
||||
|
||||
rv = gtp_xact_receive(sgw_ue->mme, &message.h, &xact);
|
||||
if (rv != CORE_OK)
|
||||
{
|
||||
pkbuf_free(pkbuf);
|
||||
break;
|
||||
}
|
||||
|
||||
switch(message.h.type)
|
||||
{
|
||||
case GTP_CREATE_SESSION_REQUEST_TYPE:
|
||||
@@ -121,25 +124,25 @@ void sgw_state_operational(fsm_t *s, event_t *e)
|
||||
case SGW_EVT_S5C_MESSAGE:
|
||||
{
|
||||
status_t rv;
|
||||
gtp_node_t *gnode = NULL;
|
||||
c_uint32_t addr = (c_uint32_t)event_get_param1(e);
|
||||
c_uint16_t port = (c_uint16_t)event_get_param2(e);
|
||||
pkbuf_t *pkbuf = (pkbuf_t *)event_get_param3(e);
|
||||
pkbuf_t *pkbuf = (pkbuf_t *)event_get_param1(e);
|
||||
gtp_xact_t *xact = NULL;
|
||||
gtp_message_t message;
|
||||
sgw_sess_t *sess = NULL;
|
||||
|
||||
d_assert(pkbuf, break, "Null param");
|
||||
gnode = sgw_pgw_find(addr, port);
|
||||
d_assert(gnode, pkbuf_free(pkbuf); break, "Null param");
|
||||
|
||||
rv = gtp_xact_receive(gnode, pkbuf, &xact, &message);
|
||||
if (rv != CORE_OK)
|
||||
break;
|
||||
rv = gtp_parse_msg(&message, pkbuf);
|
||||
d_assert(rv == CORE_OK, pkbuf_free(pkbuf); break, "parse error");
|
||||
|
||||
sess = sgw_sess_find_by_teid(message.h.teid);
|
||||
d_assert(sess, pkbuf_free(pkbuf); break, "No Session Context");
|
||||
|
||||
rv = gtp_xact_receive(sess->pgw, &message.h, &xact);
|
||||
if (rv != CORE_OK)
|
||||
{
|
||||
pkbuf_free(pkbuf);
|
||||
break;
|
||||
}
|
||||
|
||||
switch(message.h.type)
|
||||
{
|
||||
case GTP_CREATE_SESSION_RESPONSE_TYPE:
|
||||
|
||||
Reference in New Issue
Block a user